Crossfire Server, Branches 1.12  R18729
c_range.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_c_range_c =
3  * "$Id: c_range.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  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
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #ifndef __CEXTRACT__
36 #include <sproto.h>
37 #endif
38 #include <spells.h>
39 #include <skills.h>
40 #include <newclient.h>
41 #include <commands.h>
42 
53 int command_invoke(object *op, char *params) {
54  return command_cast_spell(op, params, 'i');
55 }
56 
67 int command_cast(object *op, char *params) {
68  return command_cast_spell(op, params, 'c');
69 }
70 
82 int command_prepare(object *op, char *params) {
83  return command_cast_spell(op, params, 'p');
84 }
85 
97 static void show_matching_spells(object *op, char *params) {
98  object *spell;
99  char spell_sort[NROFREALSPELLS][MAX_BUF], tmp[MAX_BUF], *cp;
100  int num_found = 0, i;
101 
102  /* We go and see what spells the player has. We put them
103  * into the spell_sort array so that we can sort them -
104  * we prefix the skill in the name so that the sorting
105  * works better.
106  */
107  for (spell = op->inv; spell != NULL; spell = spell->below) {
108  /* If it is a spell, and no params are passed, or they
109  * match the name, process this spell.
110  */
111  if (spell->type == SPELL
112  && (!params || !strncmp(params, spell->name, strlen(params)))) {
113  if (spell->path_attuned&op->path_denied) {
114  snprintf(spell_sort[num_found++], sizeof(spell_sort[0]),
115  "%s:%-22s %3s %3s", spell->skill ? spell->skill : "generic",
116  spell->name, "den", "den");
117  } else {
118  snprintf(spell_sort[num_found++], sizeof(spell_sort[0]),
119  "%s:%-22s %3d %3d", spell->skill ? spell->skill : "generic",
120  spell->name, spell->level,
122  }
123  }
124  }
125  if (!num_found) {
126  /* If a matching string was passed along, now try it without that
127  * string. It is odd to do something like 'cast trans',
128  * and it say you have no spells, when really, you do, but just
129  * nothing that matches.
130  */
131  if (params)
132  show_matching_spells(op, NULL);
133  else
135  "You know no spells", NULL);
136  } else {
137  /* Note in the code below that we make some
138  * presumptions that there will be a colon in the
139  * string. given the code above, this is always
140  * the case.
141  */
142  qsort(spell_sort, num_found, MAX_BUF, (int (*)(const void *, const void *))strcmp);
143  strcpy(tmp, "asdfg"); /* Dummy string so initial compare fails */
144  for (i = 0; i < num_found; i++) {
145  /* Different skill name, so print banner */
146  if (strncmp(tmp, spell_sort[i], strlen(tmp))) {
147  strcpy(tmp, spell_sort[i]);
148  cp = strchr(tmp, ':');
149  *cp = '\0';
150 
152  "\n[fixed]%s spells %.*s <lvl> <sp>",
153  "\n%s spells %.*s <lvl> <sp>",
154  tmp, 12-strlen(tmp), " ");
155  }
157  "[fixed]%s",
158  "%s",
159  strchr(spell_sort[i], ':')+1);
160  }
161  }
162 }
163 
178 int command_cast_spell(object *op, char *params, char command) {
179  int castnow = 0;
180  char *cp;
181  object *spob;
182 
183  if (command == 'i')
184  castnow = 1;
185 
186  if (params != NULL) {
187  tag_t spellnumber = 0;
188  if ((spellnumber = atoi(params)) != 0)
189  for (spob = op->inv; spob && spob->count != spellnumber; spob = spob->below)
190  ;
191  else
192  spob = lookup_spell_by_name(op, params);
193 
194  if (spob && spob->type == SPELL) {
195  /* Now grab any extra data, if there is any. Forward pass
196  * any 'of' delimiter
197  */
198  if (spellnumber) {
199  /* if we passed a number, the options start at the second word */
200  cp = strchr(params, ' ');
201  if (cp) {
202  cp++;
203  if (!strncmp(cp, "of ", 3))
204  cp += 3;
205  }
206  } else if (strlen(params) > strlen(spob->name)) {
207  cp = params+strlen(spob->name);
208  *cp = 0;
209  cp++;
210  if (!strncmp(cp, "of ", 3))
211  cp += 3;
212  } else
213  cp = NULL;
214 
215  if (spob->skill && !find_skill_by_name(op, spob->skill)) {
217  "You need the skill %s to cast %s!",
218  "You need the skill %s to cast %s!",
219  spob->skill, spob->name);
220  return 1;
221  }
222 
223  /* Remove control of the golem */
224  if (op->contr->ranges[range_golem] != NULL) {
225  if (op->contr->golem_count == op->contr->ranges[range_golem]->count) {
229  }
230  op->contr->ranges[range_golem] = NULL;
231  op->contr->golem_count = 0;
232  }
233 
234  if (castnow) {
235  cast_spell(op, op, op->facing, spob, cp);
236  } else {
237  op->contr->ranges[range_magic] = spob;
238  op->contr->shoottype = range_magic;
239  if (cp != NULL) {
240  strncpy(op->contr->spellparam, cp, MAX_BUF);
241  op->contr->spellparam[MAX_BUF-1] = '\0';
242  } else {
243  op->contr->spellparam[0] = '\0';
244  }
246  "You ready the spell %s",
247  "You ready the spell %s",
248  spob->name);
249  }
250  return 0;
251  } /* else fall through to below and print spells */
252  } /* params supplied */
253 
254  /* We get here if cast was given without options or we could not find
255  * the requested spell. List all the spells the player knows.
256  */
258  "Cast what spell? Choose one of:", NULL);
259  show_matching_spells(op, params);
260  return 1;
261 }
262 
263 /**************************************************************************/
264 
282 int legal_range(object *op, int r) {
283 
284  switch (r) {
285  case range_none: /* "Nothing" is always legal */
286  return 1;
287 
288  case range_bow:
289  case range_misc:
290  case range_magic: /* cast spells */
291  if (op->contr->ranges[r])
292  return 1;
293  else
294  return 0;
295 
296  case range_golem: /* Use scrolls */
297  if (op->contr->ranges[range_golem]
298  && op->contr->ranges[range_golem]->count == op->contr->golem_count)
299  return 1;
300  else
301  return 0;
302 
303  case range_skill:
304  if (op->chosen_skill)
305  return 1;
306  else
307  return 0;
308  }
309  /* No match above, must not be valid */
310  return 0;
311 }
312 
321 void change_spell(object *op, char k) {
322 
323  char name[MAX_BUF];
324 
325  do {
326  op->contr->shoottype += ((k == '+') ? 1 : -1);
327  if (op->contr->shoottype >= range_size)
328  op->contr->shoottype = range_none;
329  else if (op->contr->shoottype <= range_bottom)
330  op->contr->shoottype = (rangetype)(range_size-1);
331  } while (!legal_range(op, op->contr->shoottype));
332 
333  /* Legal range has already checked that we have an appropriate item
334  * that uses the slot, so we don't need to be too careful about
335  * checking the status of the object.
336  */
337  switch (op->contr->shoottype) {
338  case range_none:
340  "No ranged attack chosen.", NULL);
341  break;
342 
343  case range_golem:
345  "You regain control of your golem.", NULL);
346  break;
347 
348  case range_bow:
349  query_name(op->contr->ranges[range_bow], name, MAX_BUF);
351  "Switched to %s and %s.",
352  "Switched to %s and %s.",
353  name,
354  op->contr->ranges[range_bow]->race ? op->contr->ranges[range_bow]->race : "nothing");
355  break;
356 
357  case range_magic:
359  "Switched to spells (%s).",
360  "Switched to spells (%s).",
361  op->contr->ranges[range_magic]->name);
362  break;
363 
364  case range_misc:
365  query_base_name(op->contr->ranges[range_misc], 0, name, MAX_BUF);
367  "Switched to %s.",
368  "Switched to %s.",
369  name);
370  break;
371 
372  case range_skill:
374  "Switched to skill: %s",
375  "Switched to skill: %s",
376  op->chosen_skill ? op->chosen_skill->name : "none");
377  break;
378 
379  default:
380  break;
381  }
382 }
383 
394 int command_rotateshoottype(object *op, char *params) {
395  if (!params)
396  change_spell(op, '+');
397  else
398  change_spell(op, params[0]);
399  return 0;
400 }
#define MSG_TYPE_SKILL_MISSING
Definition: newclient.h:501
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.c:430
const char * race
Definition: object.h:171
char spellparam[MAX_BUF]
Definition: player.h:154
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:448
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:732
rangetype shoottype
Definition: player.h:153
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
object * ranges[range_size]
Definition: player.h:157
int legal_range(object *op, int r)
Definition: c_range.c:282
void remove_friendly_object(object *op)
Definition: friend.c:69
uint32 path_attuned
Definition: object.h:194
static void show_matching_spells(object *op, char *params)
Definition: c_range.c:97
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
int command_prepare(object *op, char *params)
Definition: c_range.c:82
#define NROFREALSPELLS
Definition: spells.h:76
uint32 tag_t
Definition: object.h:40
struct obj * chosen_skill
Definition: object.h:237
void remove_ob(object *op)
Definition: object.c:1515
uint32 path_denied
Definition: object.h:196
uint32 golem_count
Definition: player.h:160
const char * name
Definition: object.h:167
#define SPELL
Definition: define.h:283
struct obj * below
Definition: object.h:145
int command_cast(object *op, char *params)
Definition: c_range.c:67
sint8 facing
Definition: object.h:186
struct pl * contr
Definition: object.h:134
int command_invoke(object *op, char *params)
Definition: c_range.c:53
int command_cast_spell(object *op, char *params, char command)
Definition: c_range.c:178
#define MSG_TYPE_SKILL
Definition: newclient.h:329
void change_spell(object *op, char k)
Definition: c_range.c:321
#define MAX_BUF
Definition: define.h:81
const char * skill
Definition: object.h:174
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
tag_t count
Definition: object.h:157
#define SPELL_HIGHEST
Definition: spells.h:88
rangetype
Definition: player.h:52
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
sint16 SP_level_spellpoint_cost(object *caster, object *spell, int flags)
Definition: spell_util.c:281
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
void free_object(object *ob)
Definition: object.c:1238
sint16 level
Definition: object.h:202
int command_rotateshoottype(object *op, char *params)
Definition: c_range.c:394
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:447
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:207
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1308
uint8 type
Definition: object.h:189