ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_range.C
(Generate patch)

Comparing deliantra/server/server/c_range.C (file contents):
Revision 1.1 by elmex, Sun Aug 13 17:16:04 2006 UTC vs.
Revision 1.18 by root, Tue Apr 24 12:32:16 2007 UTC

1/* 1/*
2 * static char *rcsid_c_range_c = 2 * CrossFire, A Multiplayer game
3 * "$Id: c_range.C,v 1.1 2006/08/13 17:16:04 elmex Exp $";
4 */ 3 *
5 4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
6/*
7 CrossFire, A Multiplayer game for X-windows
8
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
11 7 *
12 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version. 11 * (at your option) any later version.
16 12 *
17 This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details. 16 * GNU General Public License for more details.
21 17 *
22 You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21 *
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23 */
28 24
29/* This file deals with range related commands (casting, shooting, 25/* This file deals with range related commands (casting, shooting,
30 * throwing, etc. 26 * throwing, etc.
31 */ 27 */
32 28
33#include <global.h> 29#include <global.h>
34#ifndef __CEXTRACT__
35#include <sproto.h> 30#include <sproto.h>
36#endif
37#include <spells.h> 31#include <spells.h>
38#include <skills.h> 32#include <skills.h>
39#include <newclient.h>
40#include <commands.h> 33#include <commands.h>
41 34
42 35int
43int command_invoke(object *op, char *params) 36command_invoke (object *op, char *params)
44{ 37{
45 return command_cast_spell(op, params, 'i'); 38 return command_cast_spell (op, params, 'i');
46} 39}
47 40
41int
48int command_cast(object *op, char *params) 42command_cast (object *op, char *params)
49{ 43{
50 return command_cast_spell(op, params, 'c'); 44 return command_cast_spell (op, params, 'c');
51} 45}
52 46
47int
53int command_prepare(object *op, char *params) 48command_prepare (object *op, char *params)
54{ 49{
55 return command_cast_spell(op, params, 'p'); 50 return command_cast_spell (op, params, 'p');
56} 51}
57 52
58/* Shows all spells that op knows. If params is supplied, the must match 53/* Shows all spells that op knows. If params is supplied, the must match
59 * that. Given there is more than one skill, we can't supply break 54 * that. Given there is more than one skill, we can't supply break
60 * them down to cleric/wizardry. 55 * them down to cleric/wizardry.
61 */ 56 */
57static void
62static void show_matching_spells(object *op, char *params) 58show_matching_spells (object *op, char *params)
63{ 59{
64 object *spell; 60 object *spell;
65 char spell_sort[NROFREALSPELLS][MAX_BUF], tmp[MAX_BUF], *cp; 61 char spell_sort[NROFREALSPELLS][MAX_BUF], tmp[MAX_BUF], *cp;
66 int num_found=0, i; 62 int num_found = 0, i;
67 63
68 /* We go and see what spells the player has. We put them 64 /* We go and see what spells the player has. We put them
69 * into the spell_sort array so that we can sort them - 65 * into the spell_sort array so that we can sort them -
70 * we prefix the skill in the name so that the sorting 66 * we prefix the skill in the name so that the sorting
71 * works better. 67 * works better.
72 */ 68 */
73 for (spell=op->inv; spell!=NULL; spell=spell->below) { 69 for (spell = op->inv; spell != NULL; spell = spell->below)
70 {
74 /* If it is a spell, and no params are passed, or they 71 /* If it is a spell, and no params are passed, or they
75 * match the name, process this spell. 72 * match the name, process this spell.
76 */ 73 */
77 if (spell->type == SPELL && 74 if (spell->type == SPELL && (!params || !strncmp (params, spell->name, strlen (params))))
78 (!params || !strncmp(params, spell->name, strlen(params)))) { 75 {
79 if (spell->path_attuned & op->path_denied) { 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 {
80 sprintf(spell_sort[num_found++], 82 sprintf (spell_sort[num_found++],
81 "%s:%-22s %3s %3s", spell->skill?spell->skill:"generic",
82 spell->name, "den", "den");
83 } else {
84 sprintf(spell_sort[num_found++],
85 "%s:%-22s %3d %3d", spell->skill?spell->skill:"generic", 83 "%s:%-22s %3d %3d", spell->skill ? &spell->skill : "generic",
86 spell->name, spell->level, 84 &spell->name, spell->level, SP_level_spellpoint_cost (op, spell, SPELL_HIGHEST));
87 SP_level_spellpoint_cost(op,spell, SPELL_HIGHEST)); 85 }
86 }
88 } 87 }
89 }
90 }
91 if (!num_found) { 88 if (!num_found)
89 {
92 /* If a matching string was passed along, now try it without that 90 /* If a matching string was passed along, now try it without that
93 * string. It is odd to do something like 'cast trans', 91 * string. It is odd to do something like 'cast trans',
94 * and it say you have no spells, when really, you do, but just 92 * and it say you have no spells, when really, you do, but just
95 * nothing that matches. 93 * nothing that matches.
96 */ 94 */
97 if (params) 95 if (params)
98 show_matching_spells(op, NULL); 96 show_matching_spells (op, NULL);
99 else 97 else
100 new_draw_info(NDI_UNIQUE, 0, op, "You know no spells"); 98 new_draw_info (NDI_UNIQUE, 0, op, "You know no spells");
101 } else { 99 }
100 else
101 {
102 /* Note in the code below that we make some 102 /* Note in the code below that we make some
103 * presumptions that there will be a colon in the 103 * presumptions that there will be a colon in the
104 * string. given the code above, this is always 104 * string. given the code above, this is always
105 * the case. 105 * the case.
106 */ 106 */
107 qsort(spell_sort, num_found, MAX_BUF, (int (*)(const void*, const void*))strcmp); 107 qsort (spell_sort, num_found, MAX_BUF, (int (*)(const void *, const void *)) std::strcmp);
108 strcpy(tmp,"asdfg"); /* Dummy string so initial compare fails */ 108 strcpy (tmp, "asdfg"); /* Dummy string so initial compare fails */
109 for (i=0; i<num_found; i++) { 109 for (i = 0; i < num_found; i++)
110 {
110 /* Different skill name, so print banner */ 111 /* Different skill name, so print banner */
111 if (strncmp(tmp, spell_sort[i], strlen(tmp))) { 112 if (strncmp (tmp, spell_sort[i], strlen (tmp)))
113 {
112 strcpy(tmp, spell_sort[i]); 114 strcpy (tmp, spell_sort[i]);
113 cp = strchr(tmp, ':'); 115 cp = strchr (tmp, ':');
114 *cp = '\0'; 116 *cp = '\0';
115 new_draw_info(NDI_UNIQUE, 0, op, ""); 117 new_draw_info (NDI_UNIQUE, 0, op, "");
116 new_draw_info_format(NDI_UNIQUE, 0,op,"%s spells %.*s [lvl] [sp]", 118 new_draw_info_format (NDI_UNIQUE, 0, op, "%s spells %.*s [lvl] [sp]", tmp, 12 - strlen (tmp), " ");
117 tmp, 12-strlen(tmp), " "); 119 }
118 }
119 new_draw_info(NDI_UNIQUE, 0, op, strchr(spell_sort[i], ':') + 1); 120 new_draw_info (NDI_UNIQUE, 0, op, strchr (spell_sort[i], ':') + 1);
120 } 121 }
121 } 122 }
122} 123}
123
124
125 124
126/* sets up to cast a spell. op is the caster, params is the spell name, 125/* 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, 126 * 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 127 * p=prepare). Invoke casts a spell immediately, where as cast (and I believe
129 * prepare) just set up the range type. 128 * prepare) just set up the range type.
130 */ 129 */
131 130int
132int command_cast_spell (object *op, char *params, char command) 131command_cast_spell (object *op, char *params, char command)
133{ 132{
134 int castnow=0; 133 int castnow = 0;
135 char *cp; 134 char *cp;
136 object *spob; 135 object *spob;
137 136
138 if (command=='i') castnow = 1; 137 if (command == 'i')
138 castnow = 1;
139 139
140 /* Remove control of the golem */ 140 /* Remove control of the golem */
141 if(op->contr->ranges[range_golem]!=NULL) { 141 if (object *golem = op->contr->ranges[range_golem])
142 if (op->contr->golem_count == op->contr->ranges[range_golem]->count) { 142 golem->destroy ();
143 remove_friendly_object(op->contr->ranges[range_golem]); 143
144 remove_ob(op->contr->ranges[range_golem]); 144 if (params)
145 free_object(op->contr->ranges[range_golem]);
146 }
147 op->contr->ranges[range_golem]=NULL;
148 op->contr->golem_count = 0;
149 } 145 {
150
151 if(params!=NULL) {
152 int spellnumber = 0; 146 int spellnumber = 0;
147
153 if (spellnumber = atoi(params)) 148 if ((spellnumber = atoi (params)))
154 for (spob = op->inv; spob && spob->count != spellnumber; spob=spob->below); 149 for (spob = op->inv; spob && spob->count != spellnumber; spob = spob->below)
150 /* nop */;
151 else
155 else spob = lookup_spell_by_name(op, params); 152 spob = lookup_spell_by_name (op, params);
156 153
157 if (spob && spob->type == SPELL) { 154 if (spob && spob->type == SPELL)
155 {
158 /* Now grab any extra data, if there is any. Forward pass 156 /* Now grab any extra data, if there is any. Forward pass
159 * any 'of' delimiter 157 * any 'of' delimiter
160 */ 158 */
161 if (spellnumber) { 159 if (spellnumber)
160 {
162 /* if we passed a number, the options start at the second word */ 161 /* if we passed a number, the options start at the second word */
163 cp = strchr(params, ' '); 162 cp = strchr (params, ' ');
164 if (cp) { 163 if (cp)
165 cp++; 164 {
166 if (!strncmp(cp, "of ", 3)) cp+=3; 165 cp++;
167 } 166 if (!strncmp (cp, "of ", 3))
168 } 167 cp += 3;
168 }
169 }
169 else if (strlen(params) > strlen(spob->name)) { 170 else if (strlen (params) > (size_t) strlen (spob->name))
171 {
170 cp = params + strlen(spob->name); 172 cp = params + strlen (spob->name);
171 *cp = 0; 173 *cp = 0;
172 cp++; 174 cp++;
173 if (!strncmp(cp, "of ", 3)) cp+=3; 175 if (!strncmp (cp, "of ", 3))
174 } else 176 cp += 3;
175 cp = NULL; 177 }
178 else
179 cp = NULL;
176 180
177 if (spob->skill && !find_skill_by_name(op, spob->skill)) { 181 if (spob->skill && !find_skill_by_name (op, spob->skill))
178 new_draw_info_format(NDI_UNIQUE, 0, op, 182 {
179 "You need the skill %s to cast %s!", 183 new_draw_info_format (NDI_UNIQUE, 0, op, "You need the skill %s to cast %s!", &spob->skill, &spob->name);
180 spob->skill, spob->name); 184 return 1;
181 return 1; 185 }
182 } 186
183
184 if (castnow) { 187 if (castnow)
185 cast_spell(op,op,op->facing,spob,cp); 188 cast_spell (op, op, op->facing, spob, cp);
186 } else { 189 else
190 {
187 op->contr->ranges[range_magic] = spob; 191 op->contr->ranges[range_magic] = spob;
188 op->contr->shoottype = range_magic; 192 op->contr->shoottype = range_magic;
189 if(cp != NULL) { 193 assign (op->contr->spellparam, cp ? cp : "");
190 strncpy(op->contr->spellparam, cp, MAX_BUF); 194 new_draw_info_format (NDI_UNIQUE, 0, op, "You ready the spell %s", &spob->name);
191 op->contr->spellparam[MAX_BUF-1] = '\0'; 195 }
192 } else { 196
193 op->contr->spellparam[0] = '\0';
194 }
195 new_draw_info_format(NDI_UNIQUE, 0, op,
196 "You ready the spell %s", spob->name);
197 }
198 return 0; 197 return 0;
199 } /* else fall through to below and print spells */ 198 } /* else fall through to below and print spells */
200 } /* params supplied */ 199 } /* params supplied */
201 200
202 /* We get here if cast was given without options or we could not find 201 /* We get here if cast was given without options or we could not find
203 * the requested spell. List all the spells the player knows. 202 * the requested spell. List all the spells the player knows.
204 */ 203 */
205 new_draw_info(NDI_UNIQUE, 0,op,"Cast what spell? Choose one of:"); 204 new_draw_info (NDI_UNIQUE, 0, op, "Cast what spell? Choose one of:");
206 show_matching_spells(op, params); 205 show_matching_spells (op, params);
207 return 1; 206 return 1;
208} 207}
209 208
210/**************************************************************************/ 209/**************************************************************************/
211 210
212/* Returns TRUE if the range specified (int r) is legal - that is, 211/* Returns TRUE if the range specified (int r) is legal - that is,
214 * return 0 if there is no item of that range type that is usable. 213 * return 0 if there is no item of that range type that is usable.
215 * This function could probably be simplified, eg, everything 214 * This function could probably be simplified, eg, everything
216 * should index into the ranges[] array. 215 * should index into the ranges[] array.
217 */ 216 */
218 217
218int
219int legal_range(object *op,int r) { 219legal_range (object *op, int r)
220 220{
221 switch(r) { 221 switch (r)
222 {
222 case range_none: /* "Nothing" is always legal */ 223 case range_none: /* "Nothing" is always legal */
223 return 1; 224 return 1;
225
224 case range_bow: 226 case range_bow:
225 case range_misc: 227 case range_misc:
226 case range_magic: /* cast spells */ 228 case range_magic: /* cast spells */
227 if (op->contr->ranges[r]) return 1; 229 return !!op->contr->ranges[r];
228 else return 0;
229 230
230 case range_golem: /* Use scrolls */ 231 case range_golem: /* Use scrolls */
231 if (op->contr->ranges[range_golem] && 232 return !!op->contr->ranges[range_golem];
232 op->contr->ranges[range_golem]->count == op->contr->golem_count)
233 return 1;
234 else
235 return 0;
236 233
237 case range_skill: 234 case range_skill:
238 if (op->chosen_skill) 235 return !!op->chosen_skill;
239 return 1;
240 else
241 return 0;
242 } 236 }
237
243 /* No match above, must not be valid */ 238 /* No match above, must not be valid */
244 return 0; 239 return 0;
245} 240}
246 241
242void
247void change_spell(object *op,char k) { 243change_spell (object *op, char k)
248 244{
245 do
249 do { 246 {
250 op->contr->shoottype = (rangetype) (op->contr->shoottype + ((k == '+') ? 1 : -1)); 247 op->contr->shoottype = (rangetype) (op->contr->shoottype + ((k == '+') ? 1 : -1));
251 if(op->contr->shoottype >= range_size) 248 if (op->contr->shoottype >= range_size)
252 op->contr->shoottype = range_none; 249 op->contr->shoottype = range_none;
253 else if (op->contr->shoottype <= range_bottom) 250 else if (op->contr->shoottype <= range_bottom)
254 op->contr->shoottype = (rangetype)(range_size-1); 251 op->contr->shoottype = (rangetype) (range_size - 1);
252 }
255 } while (!legal_range(op,op->contr->shoottype)); 253 while (!legal_range (op, op->contr->shoottype));
256 254
257 /* Legal range has already checked that we have an appropriate item 255 /* Legal range has already checked that we have an appropriate item
258 * that uses the slot, so we don't need to be too careful about 256 * that uses the slot, so we don't need to be too careful about
259 * checking the status of the object. 257 * checking the status of the object.
260 */ 258 */
261 switch(op->contr->shoottype) { 259 switch (op->contr->shoottype)
260 {
262 case range_none: 261 case range_none:
263 new_draw_info(NDI_UNIQUE, 0,op, "No ranged attack chosen."); 262 new_draw_info (NDI_UNIQUE, 0, op, "No ranged attack chosen.");
264 break; 263 break;
265 264
266 case range_golem: 265 case range_golem:
267 new_draw_info(NDI_UNIQUE, 0,op, "You regain control of your golem."); 266 new_draw_info (NDI_UNIQUE, 0, op, "You regain control of your golem.");
268 break; 267 break;
269 268
270 case range_bow: 269 case range_bow:
271 new_draw_info_format(NDI_UNIQUE, 0,op, "Switched to %s and %s.", query_name(op->contr->ranges[range_bow]), 270 new_draw_info_format (NDI_UNIQUE, 0, op, "Switched to %s and %s.", query_name (op->contr->ranges[range_bow]),
272 op->contr->ranges[range_bow]->race ? op->contr->ranges[range_bow]->race : "nothing"); 271 op->contr->ranges[range_bow]->race ? &op->contr->ranges[range_bow]->race : "nothing");
273 break; 272 break;
274 273
275 case range_magic: 274 case range_magic:
276 new_draw_info_format(NDI_UNIQUE, 0,op,"Switched to spells (%s).", 275 new_draw_info_format (NDI_UNIQUE, 0, op, "Switched to spells (%s).", &op->contr->ranges[range_magic]->name);
277 op->contr->ranges[range_magic]->name); 276 break;
278 break;
279 277
280 case range_misc: 278 case range_misc:
281 new_draw_info_format(NDI_UNIQUE, 0,op, "Switched to %s.", query_base_name(op->contr->ranges[range_misc], 0)); 279 new_draw_info_format (NDI_UNIQUE, 0, op, "Switched to %s.", query_base_name (op->contr->ranges[range_misc], 0));
282 break; 280 break;
283 281
284 case range_skill: 282 case range_skill:
285 new_draw_info_format(NDI_UNIQUE, 0,op, "Switched to skill: %s", op->chosen_skill ? 283 new_draw_info_format (NDI_UNIQUE, 0, op, "Switched to skill: %s", op->chosen_skill ? &op->chosen_skill->name : "none");
286 op->chosen_skill->name : "none"); 284 break;
287 break;
288 285
289 default: 286 default:
290 break; 287 break;
291 } 288 }
292} 289}
293 290
294 291
292int
295int command_rotateshoottype (object *op, char *params) 293command_rotateshoottype (object *op, char *params)
296{ 294{
297 if (!params) 295 if (!params)
298 change_spell(op,'+'); 296 change_spell (op, '+');
299 else 297 else
300 change_spell(op, params[0]); 298 change_spell (op, params[0]);
301 return 0; 299 return 0;
302} 300}
303

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines