ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_range.C
Revision: 1.20
Committed: Mon Apr 30 04:25:30 2007 UTC (17 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.19: +17 -44 lines
Log Message:
This is the first rough cut of the skill use system (use the STABLE tag).

Details will likely change, and combat skills do not work very well, but
it works quite well.

Players no longer have a shoottype or range slots, instead, each player
has these members:

   combat_skill/combat_ob  the currently selected skill (and weapon)
                           for direct attacks.
   ranged_skill/ranged_ob  the currently selected ranged skill (and
                           bow/spell/item)
   golem                   the currently-controlled golem, if any.

File Contents

# Content
1 /*
2 * CrossFire, A Multiplayer game
3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
23 */
24
25 /* This file deals with range related commands (casting, shooting,
26 * throwing, etc.
27 */
28
29 #include <global.h>
30 #include <sproto.h>
31 #include <spells.h>
32 #include <skills.h>
33 #include <commands.h>
34
35 int
36 command_invoke (object *op, char *params)
37 {
38 return command_cast_spell (op, params, 'i');
39 }
40
41 int
42 command_cast (object *op, char *params)
43 {
44 return command_cast_spell (op, params, 'c');
45 }
46
47 int
48 command_prepare (object *op, char *params)
49 {
50 return command_cast_spell (op, params, 'p');
51 }
52
53 /* Shows all spells that op knows. If params is supplied, the must match
54 * that. Given there is more than one skill, we can't supply break
55 * them down to cleric/wizardry.
56 */
57 static void
58 show_matching_spells (object *op, char *params)
59 {
60 object *spell;
61 char spell_sort[NROFREALSPELLS][MAX_BUF], tmp[MAX_BUF], *cp;
62 int num_found = 0, i;
63
64 /* We go and see what spells the player has. We put them
65 * into the spell_sort array so that we can sort them -
66 * we prefix the skill in the name so that the sorting
67 * works better.
68 */
69 for (spell = op->inv; spell; spell = spell->below)
70 {
71 /* If it is a spell, and no params are passed, or they
72 * match the name, process this spell.
73 */
74 if (spell->type == SPELL && (!params || !strncmp (params, spell->name, strlen (params))))
75 {
76 if (spell->path_attuned & op->path_denied)
77 {
78 sprintf (spell_sort[num_found++], "%s:%-22s %3s %3s", spell->skill ? &spell->skill : "generic", &spell->name, "den", "den");
79 }
80 else
81 {
82 sprintf (spell_sort[num_found++],
83 "%s:%-22s %3d %3d", spell->skill ? &spell->skill : "generic",
84 &spell->name, spell->level, SP_level_spellpoint_cost (op, spell, SPELL_HIGHEST));
85 }
86 }
87 }
88
89 if (!num_found)
90 {
91 /* If a matching string was passed along, now try it without that
92 * string. It is odd to do something like 'cast trans',
93 * and it say you have no spells, when really, you do, but just
94 * nothing that matches.
95 */
96 if (params)
97 show_matching_spells (op, NULL);
98 else
99 new_draw_info (NDI_UNIQUE, 0, op, "You know no spells");
100 }
101 else
102 {
103 /* Note in the code below that we make some
104 * presumptions that there will be a colon in the
105 * string. given the code above, this is always
106 * the case.
107 */
108 qsort (spell_sort, num_found, MAX_BUF, (int (*)(const void *, const void *)) std::strcmp);
109 strcpy (tmp, "asdfg"); /* Dummy string so initial compare fails */
110 for (i = 0; i < num_found; i++)
111 {
112 /* Different skill name, so print banner */
113 if (strncmp (tmp, spell_sort[i], strlen (tmp)))
114 {
115 strcpy (tmp, spell_sort[i]);
116 cp = strchr (tmp, ':');
117 *cp = '\0';
118 new_draw_info (NDI_UNIQUE, 0, op, "");
119 new_draw_info_format (NDI_UNIQUE, 0, op, "%s spells %.*s [lvl] [sp]", tmp, 12 - strlen (tmp), " ");
120 }
121 new_draw_info (NDI_UNIQUE, 0, op, strchr (spell_sort[i], ':') + 1);
122 }
123 }
124 }
125
126 /* sets up to cast a spell. op is the caster, params is the spell name,
127 * and command is the first letter of the spell type (c=cast, i=invoke,
128 * p=prepare). Invoke casts a spell immediately, where as cast (and I believe
129 * prepare) just set up the range type.
130 */
131 int
132 command_cast_spell (object *op, char *params, char command)
133 {
134 int castnow = 0;
135 char *cp;
136 object *spob;
137
138 if (command == 'i')
139 castnow = 1;
140
141 /* Remove control of the golem */
142 if (object *golem = op->contr->golem)
143 golem->destroy ();
144
145 if (params)
146 {
147 int spellnumber = 0;
148
149 if ((spellnumber = atoi (params)))
150 for (spob = op->inv; spob && spob->count != spellnumber; spob = spob->below)
151 /* nop */;
152 else
153 spob = lookup_spell_by_name (op, params);
154
155 if (spob && spob->type == SPELL)
156 {
157 /* Now grab any extra data, if there is any. Forward pass
158 * any 'of' delimiter
159 */
160 if (spellnumber)
161 {
162 /* if we passed a number, the options start at the second word */
163 cp = strchr (params, ' ');
164 if (cp)
165 {
166 cp++;
167 if (!strncmp (cp, "of ", 3))
168 cp += 3;
169 }
170 }
171 else if (strlen (params) > strlen (spob->name))
172 {
173 cp = params + strlen (spob->name);
174 *cp = 0;
175 cp++;
176 if (!strncmp (cp, "of ", 3))
177 cp += 3;
178 }
179 else
180 cp = NULL;
181
182 if (!spob->skill)
183 {
184 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is a weird spell, please report it to the dungeon master!", &spob->name);
185 LOG (llevError, "spell without skill found: %s", spob->debug_desc ());
186 return 1;
187 }
188
189 object *skill = find_skill_by_name (op, spob->skill);
190
191 if (!skill)
192 {
193 new_draw_info_format (NDI_UNIQUE, 0, op, "You need the skill %s to cast %s!", &spob->skill, &spob->name);
194 return 1;
195 }
196
197 if (castnow)
198 cast_spell (op, op, op->facing, spob, cp);
199 else
200 {
201 op->contr->ranged_skill = skill;
202 op->contr->ranged_ob = spob;
203
204 assign (op->contr->spellparam, cp ? cp : "");
205 new_draw_info_format (NDI_UNIQUE, 0, op, "You ready the spell %s", &spob->name);
206 }
207
208 return 0;
209 } /* else fall through to below and print spells */
210 } /* params supplied */
211
212 /* We get here if cast was given without options or we could not find
213 * the requested spell. List all the spells the player knows.
214 */
215 new_draw_info (NDI_UNIQUE, 0, op, "Cast what spell? Choose one of:");
216 show_matching_spells (op, params);
217 return 1;
218 }
219
220 /**************************************************************************/
221
222 void
223 change_spell (object *op, char k)
224 {
225 //TODO: maybe switch to golem, if any?
226 // does nothing
227 }
228
229 int
230 command_rotateshoottype (object *op, char *params)
231 {
232 if (!params)
233 change_spell (op, '+');
234 else
235 change_spell (op, params[0]);
236
237 return 0;
238 }