ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_range.c
Revision: 1.1
Committed: Fri Feb 3 07:14:29 2006 UTC (18 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Branch point for: UPSTREAM
Log Message:
Initial revision

File Contents

# User Rev Content
1 root 1.1 /*
2     * static char *rcsid_c_range_c =
3     * "$Id: c_range.c,v 1.15 2006/01/10 16:32:44 cavesomething Exp $";
4     */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2002 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    
29     /* This file deals with range related commands (casting, shooting,
30     * throwing, etc.
31     */
32    
33     #include <global.h>
34     #ifndef __CEXTRACT__
35     #include <sproto.h>
36     #endif
37     #include <spells.h>
38     #include <skills.h>
39     #include <newclient.h>
40     #include <commands.h>
41    
42    
43     int command_invoke(object *op, char *params)
44     {
45     return command_cast_spell(op, params, 'i');
46     }
47    
48     int command_cast(object *op, char *params)
49     {
50     return command_cast_spell(op, params, 'c');
51     }
52    
53     int command_prepare(object *op, char *params)
54     {
55     return command_cast_spell(op, params, 'p');
56     }
57    
58     /* 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
60     * them down to cleric/wizardry.
61     */
62     static void show_matching_spells(object *op, char *params)
63     {
64     object *spell;
65     char spell_sort[NROFREALSPELLS][MAX_BUF], tmp[MAX_BUF], *cp;
66     int num_found=0, i;
67    
68     /* We go and see what spells the player has. We put them
69     * into the spell_sort array so that we can sort them -
70     * we prefix the skill in the name so that the sorting
71     * works better.
72     */
73     for (spell=op->inv; spell!=NULL; spell=spell->below) {
74     /* If it is a spell, and no params are passed, or they
75     * match the name, process this spell.
76     */
77     if (spell->type == SPELL &&
78     (!params || !strncmp(params, spell->name, strlen(params)))) {
79     if (spell->path_attuned & op->path_denied) {
80     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",
86     spell->name, spell->level,
87     SP_level_spellpoint_cost(op,spell, SPELL_HIGHEST));
88     }
89     }
90     }
91     if (!num_found) {
92     /* If a matching string was passed along, now try it without that
93     * string. It is odd to do something like 'cast trans',
94     * and it say you have no spells, when really, you do, but just
95     * nothing that matches.
96     */
97     if (params)
98     show_matching_spells(op, NULL);
99     else
100     new_draw_info(NDI_UNIQUE, 0, op, "You know no spells");
101     } else {
102     /* Note in the code below that we make some
103     * presumptions that there will be a colon in the
104     * string. given the code above, this is always
105     * the case.
106     */
107     qsort(spell_sort, num_found, MAX_BUF, (int (*)(const void*, const void*))strcmp);
108     strcpy(tmp,"asdfg"); /* Dummy string so initial compare fails */
109     for (i=0; i<num_found; i++) {
110     /* Different skill name, so print banner */
111     if (strncmp(tmp, spell_sort[i], strlen(tmp))) {
112     strcpy(tmp, spell_sort[i]);
113     cp = strchr(tmp, ':');
114     *cp = '\0';
115     new_draw_info(NDI_UNIQUE, 0, op, "");
116     new_draw_info_format(NDI_UNIQUE, 0,op,"%s spells %.*s [lvl] [sp]",
117     tmp, 12-strlen(tmp), " ");
118     }
119     new_draw_info(NDI_UNIQUE, 0, op, strchr(spell_sort[i], ':') + 1);
120     }
121     }
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    
132     int 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') castnow = 1;
139    
140     /* Remove control of the golem */
141     if(op->contr->ranges[range_golem]!=NULL) {
142     if (op->contr->golem_count == op->contr->ranges[range_golem]->count) {
143     remove_friendly_object(op->contr->ranges[range_golem]);
144     remove_ob(op->contr->ranges[range_golem]);
145     free_object(op->contr->ranges[range_golem]);
146     }
147     op->contr->ranges[range_golem]=NULL;
148     op->contr->golem_count = 0;
149     }
150    
151     if(params!=NULL) {
152     int spellnumber = 0;
153     if (spellnumber = atoi(params))
154     for (spob = op->inv; spob && spob->count != spellnumber; spob=spob->below);
155     else spob = lookup_spell_by_name(op, params);
156    
157     if (spob && spob->type == SPELL) {
158     /* Now grab any extra data, if there is any. Forward pass
159     * any 'of' delimiter
160     */
161     if (spellnumber) {
162     /* if we passed a number, the options start at the second word */
163     cp = strchr(params, ' ');
164     if (cp) {
165     cp++;
166     if (!strncmp(cp, "of ", 3)) cp+=3;
167     }
168     }
169     else if (strlen(params) > strlen(spob->name)) {
170     cp = params + strlen(spob->name);
171     *cp = 0;
172     cp++;
173     if (!strncmp(cp, "of ", 3)) cp+=3;
174     } else
175     cp = NULL;
176    
177     if (spob->skill && !find_skill_by_name(op, spob->skill)) {
178     new_draw_info_format(NDI_UNIQUE, 0, op,
179     "You need the skill %s to cast %s!",
180     spob->skill, spob->name);
181     return 1;
182     }
183    
184     if (castnow) {
185     cast_spell(op,op,op->facing,spob,cp);
186     } else {
187     op->contr->ranges[range_magic] = spob;
188     op->contr->shoottype = range_magic;
189     if(cp != NULL) {
190     strncpy(op->contr->spellparam, cp, MAX_BUF);
191     op->contr->spellparam[MAX_BUF-1] = '\0';
192     } else {
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;
199     } /* else fall through to below and print spells */
200     } /* params supplied */
201    
202     /* 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.
204     */
205     new_draw_info(NDI_UNIQUE, 0,op,"Cast what spell? Choose one of:");
206     show_matching_spells(op, params);
207     return 1;
208     }
209    
210     /**************************************************************************/
211    
212     /* Returns TRUE if the range specified (int r) is legal - that is,
213     * the character has an item that is equipped for that range type.
214     * return 0 if there is no item of that range type that is usable.
215     * This function could probably be simplified, eg, everything
216     * should index into the ranges[] array.
217     */
218    
219     int legal_range(object *op,int r) {
220    
221     switch(r) {
222     case range_none: /* "Nothing" is always legal */
223     return 1;
224     case range_bow:
225     case range_misc:
226     case range_magic: /* cast spells */
227     if (op->contr->ranges[r]) return 1;
228     else return 0;
229    
230     case range_golem: /* Use scrolls */
231     if (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    
237     case range_skill:
238     if (op->chosen_skill)
239     return 1;
240     else
241     return 0;
242     }
243     /* No match above, must not be valid */
244     return 0;
245     }
246    
247     void change_spell(object *op,char k) {
248    
249     do {
250     op->contr->shoottype += ((k == '+') ? 1 : -1);
251     if(op->contr->shoottype >= range_size)
252     op->contr->shoottype = range_none;
253     else if (op->contr->shoottype <= range_bottom)
254     op->contr->shoottype = (rangetype)(range_size-1);
255     } while (!legal_range(op,op->contr->shoottype));
256    
257     /* 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
259     * checking the status of the object.
260     */
261     switch(op->contr->shoottype) {
262     case range_none:
263     new_draw_info(NDI_UNIQUE, 0,op, "No ranged attack chosen.");
264     break;
265    
266     case range_golem:
267     new_draw_info(NDI_UNIQUE, 0,op, "You regain control of your golem.");
268     break;
269    
270     case range_bow:
271     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");
273     break;
274    
275     case range_magic:
276     new_draw_info_format(NDI_UNIQUE, 0,op,"Switched to spells (%s).",
277     op->contr->ranges[range_magic]->name);
278     break;
279    
280     case range_misc:
281     new_draw_info_format(NDI_UNIQUE, 0,op, "Switched to %s.", query_base_name(op->contr->ranges[range_misc], 0));
282     break;
283    
284     case range_skill:
285     new_draw_info_format(NDI_UNIQUE, 0,op, "Switched to skill: %s", op->chosen_skill ?
286     op->chosen_skill->name : "none");
287     break;
288    
289     default:
290     break;
291     }
292     }
293    
294    
295     int command_rotateshoottype (object *op, char *params)
296     {
297     if (!params)
298     change_spell(op,'+');
299     else
300     change_spell(op, params[0]);
301     return 0;
302     }
303