ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.68
Committed: Thu Aug 23 17:13:04 2007 UTC (16 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.67: +6 -1 lines
Log Message:
cleanup

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.54 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.35 *
4 root 1.54 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.35 *
8 root 1.62 * Crossfire TRT 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 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.35 *
13 root 1.62 * 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 pippijn 1.35 *
18 root 1.62 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.54 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.35 */
23 elmex 1.1
24     #include <global.h>
25     #include <object.h>
26     #include <living.h>
27 root 1.36 #include <sproto.h>
28 elmex 1.1 #include <spells.h>
29     #include <sounds.h>
30    
31     /* cast_magic_storm: This is really used mostly for spell
32     * fumbles at the like. tmp is the object to propogate.
33     * op is what is casting this.
34     */
35 root 1.8 void
36     cast_magic_storm (object *op, object *tmp, int lvl)
37 elmex 1.1 {
38 root 1.8 if (!tmp)
39     return; /* error */
40 root 1.27
41 root 1.8 tmp->level = op->level;
42     tmp->range += lvl / 5; /* increase the area of destruction */
43     tmp->duration += lvl / 5;
44    
45     /* Put a cap on duration for this - if the player fails in their
46     * apartment, don't want it to go on so long that it kills them
47     * multiple times. Also, damge already increases with level,
48     * so don't really need to increase the duration as much either.
49     */
50     if (tmp->duration >= 40)
51     tmp->duration = 40;
52 root 1.27
53 root 1.8 tmp->stats.dam = lvl; /* nasty recoils! */
54     tmp->stats.maxhp = tmp->count; /* tract single parent */
55 elmex 1.1
56 root 1.27 tmp->insert_at (op, op);
57 elmex 1.1 }
58    
59 root 1.8 int
60     recharge (object *op, object *caster, object *spell_ob)
61     {
62     object *wand, *tmp;
63     int ncharges;
64    
65     wand = find_marked_object (op);
66     if (wand == NULL || wand->type != WAND)
67     {
68     new_draw_info (NDI_UNIQUE, 0, op, "You need to mark the wand you want to recharge.");
69     return 0;
70 elmex 1.1 }
71 root 1.8 if (!(random_roll (0, 3, op, PREFER_HIGH)))
72     {
73     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s vibrates violently, then explodes!", query_name (wand));
74 root 1.64 op->play_sound (sound_find ("ob_explode"));
75 root 1.8 esrv_del_item (op->contr, wand->count);
76 root 1.17 wand->destroy ();
77 root 1.8 tmp = get_archetype ("fireball");
78     tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10;
79 root 1.27
80 root 1.8 if (!tmp->stats.dam)
81     tmp->stats.dam = 1;
82 root 1.27
83 root 1.8 tmp->stats.hp = tmp->stats.dam / 2;
84 root 1.27
85 root 1.8 if (tmp->stats.hp < 2)
86     tmp->stats.hp = 2;
87 root 1.27
88     tmp->insert_at (op);
89 root 1.8 return 1;
90     }
91    
92     ncharges = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob));
93 root 1.27
94 root 1.8 if (wand->inv && wand->inv->level)
95     ncharges /= wand->inv->level;
96     else
97     {
98     new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", query_name (wand));
99     return 0;
100 elmex 1.1 }
101 root 1.27
102 root 1.8 if (!ncharges)
103     ncharges = 1;
104 elmex 1.1
105 root 1.8 wand->stats.food += ncharges;
106     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s glows with power.", query_name (wand));
107 root 1.27
108 root 1.57 if (wand->arch && QUERY_FLAG (wand->arch, FLAG_ANIMATE))
109 root 1.8 {
110     SET_FLAG (wand, FLAG_ANIMATE);
111 root 1.57 wand->set_speed (wand->arch->speed);
112 elmex 1.1 }
113 root 1.26
114 root 1.8 return 1;
115 elmex 1.1 }
116    
117     /* Create a missile (nonmagic - magic +4). Will either create bolts or arrows
118     * based on whether a crossbow or bow is equiped. If neither, it defaults to
119     * arrows.
120     * Sets the plus based on the casters level. It is also settable with the
121     * invoke command. If the caster attempts to create missiles with too
122     * great a plus, the default is used.
123     * The # of arrows created also goes up with level, so if a 30th level mage
124     * wants LOTS of arrows, and doesn't care what the plus is he could
125     * create nonnmagic arrows, or even -1, etc...
126     */
127 root 1.8 int
128     cast_create_missile (object *op, object *caster, object *spell, int dir, const char *stringarg)
129 elmex 1.1 {
130 root 1.8 int missile_plus = 0, bonus_plus = 0;
131     const char *missile_name;
132     object *tmp, *missile;
133    
134     missile_name = "arrow";
135    
136     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
137     if (tmp->type == BOW && QUERY_FLAG (tmp, FLAG_APPLIED))
138 root 1.12 missile_name = tmp->race;
139 elmex 1.1
140 root 1.8 missile_plus = spell->stats.dam + SP_level_dam_adjust (caster, spell);
141 elmex 1.1
142 root 1.10 if (archetype::find (missile_name) == NULL)
143 root 1.8 {
144     LOG (llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
145     return 0;
146     }
147 root 1.12
148 root 1.8 missile = get_archetype (missile_name);
149 elmex 1.1
150 root 1.8 if (stringarg)
151     {
152     /* If it starts with a letter, presume it is a description */
153     if (isalpha (*stringarg))
154     {
155     artifact *al = find_artifactlist (missile->type)->items;
156 elmex 1.1
157 root 1.45 for (; al; al = al->next)
158 root 1.8 if (!strcasecmp (al->item->name, stringarg))
159     break;
160    
161     if (!al)
162     {
163 root 1.17 missile->destroy ();
164 root 1.8 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg);
165     return 0;
166     }
167 root 1.12
168 root 1.8 if (al->item->slaying)
169     {
170 root 1.17 missile->destroy ();
171 root 1.8 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg);
172     return 0;
173     }
174 root 1.12
175 root 1.8 give_artifact_abilities (missile, al->item);
176     /* These special arrows cost something extra. Don't have them also be magical -
177     * otherwise, in most cases, not enough will be created. I don't want to get into
178     * the parsing of having to do both plus and type.
179     */
180     bonus_plus = 1 + (al->item->value / 5);
181     missile_plus = 0;
182     }
183     else if (atoi (stringarg) < missile_plus)
184     missile_plus = atoi (stringarg);
185     }
186 root 1.12
187 root 1.8 if (missile_plus > 4)
188     missile_plus = 4;
189     else if (missile_plus < -4)
190     missile_plus = -4;
191    
192     missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell);
193     missile->nrof -= 3 * (missile_plus + bonus_plus);
194 root 1.12
195 root 1.8 if (missile->nrof < 1)
196     missile->nrof = 1;
197    
198     missile->magic = missile_plus;
199     /* Can't get any money for these objects */
200     missile->value = 0;
201 elmex 1.1
202 root 1.8 SET_FLAG (missile, FLAG_IDENTIFIED);
203 elmex 1.1
204 root 1.12 if (!cast_create_obj (op, caster, missile, dir) && op->type == PLAYER && !missile->destroyed ())
205     pick_up (op, missile);
206    
207 root 1.8 return 1;
208 elmex 1.1 }
209    
210    
211     /* allows the choice of what sort of food object to make.
212     * If stringarg is NULL, it will create food dependent on level --PeterM*/
213 root 1.8 int
214     cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
215 elmex 1.1 {
216 root 1.8 int food_value;
217     archetype *at = NULL;
218     object *new_op;
219    
220     food_value = spell_ob->stats.food + +50 * SP_level_duration_adjust (caster, spell_ob);
221    
222     if (stringarg)
223     {
224     at = find_archetype_by_object_type_name (FOOD, stringarg);
225     if (at == NULL)
226     at = find_archetype_by_object_type_name (DRINK, stringarg);
227 root 1.57 if (at == NULL || at->stats.food > food_value)
228 root 1.8 stringarg = NULL;
229     }
230    
231     if (!stringarg)
232     {
233     archetype *at_tmp;
234    
235     /* We try to find the archetype with the maximum food value.
236     * This removes the dependancy of hard coded food values in this
237     * function, and addition of new food types is automatically added.
238     * We don't use flesh types because the weight values of those need
239     * to be altered from the donor.
240     */
241 root 1.5
242 root 1.8 /* We assume the food items don't have multiple parts */
243 elmex 1.58 for_all_archetypes (at_tmp)
244 root 1.8 {
245 root 1.57 if (at_tmp->type == FOOD || at_tmp->type == DRINK)
246 root 1.8 {
247     /* Basically, if the food value is something that is creatable
248     * under the limits of the spell and it is higher than
249     * the item we have now, take it instead.
250     */
251 elmex 1.59 if (at_tmp->stats.food <= food_value
252     && (!at
253     || at_tmp->stats.food > at->stats.food
254     || (at_tmp->stats.food == at->stats.food
255     && at_tmp->weight < at->weight)))
256 root 1.8 at = at_tmp;
257 root 1.5 }
258     }
259 elmex 1.1 }
260 root 1.65
261 root 1.8 /* Pretty unlikely (there are some very low food items), but you never
262     * know
263     */
264     if (!at)
265     {
266     new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food.");
267     return 0;
268 elmex 1.1 }
269    
270 root 1.57 food_value /= at->stats.food;
271 root 1.8 new_op = arch_to_object (at);
272     new_op->nrof = food_value;
273 elmex 1.1
274 root 1.8 new_op->value = 0;
275     if (new_op->nrof < 1)
276     new_op->nrof = 1;
277 elmex 1.1
278 root 1.8 cast_create_obj (op, caster, new_op, dir);
279     return 1;
280 elmex 1.1 }
281 root 1.8
282     int
283     probe (object *op, object *caster, object *spell_ob, int dir)
284     {
285     int r, mflags, maxrange;
286     object *tmp;
287 root 1.13 maptile *m;
288 elmex 1.1
289    
290 root 1.8 if (!dir)
291     {
292     examine_monster (op, op);
293     return 1;
294 elmex 1.1 }
295 root 1.65
296 root 1.8 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
297     for (r = 1; r < maxrange; r++)
298     {
299     sint16 x = op->x + r * freearr_x[dir], y = op->y + r * freearr_y[dir];
300 elmex 1.1
301 root 1.8 m = op->map;
302     mflags = get_map_flags (m, &m, x, y, &x, &y);
303 elmex 1.1
304 root 1.8 if (mflags & P_OUT_OF_MAP)
305     break;
306 elmex 1.1
307 root 1.8 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (mflags & P_NO_MAGIC))
308     {
309     new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic.");
310     return 0;
311 root 1.5 }
312 root 1.8 if (mflags & P_IS_ALIVE)
313     {
314 root 1.22 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
315 root 1.8 if (QUERY_FLAG (tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG (tmp, FLAG_MONSTER)))
316     {
317     new_draw_info (NDI_UNIQUE, 0, op, "You detect something.");
318     if (tmp->head != NULL)
319     tmp = tmp->head;
320     examine_monster (op, tmp);
321     return 1;
322     }
323 root 1.5 }
324 elmex 1.1 }
325 root 1.65
326 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You detect nothing.");
327     return 1;
328 elmex 1.1 }
329    
330     /* This checks to see if 'pl' is invisible to 'mon'.
331     * does race check, undead check, etc
332     * Returns TRUE if mon can't see pl, false
333     * otherwise. This doesn't check range, walls, etc. It
334     * only checks the racial adjustments, and in fact that
335     * pl is invisible.
336     */
337 root 1.8 int
338     makes_invisible_to (object *pl, object *mon)
339 elmex 1.1 {
340 root 1.8 if (!pl->invisible)
341     return 0;
342 root 1.68
343 root 1.8 if (pl->type == PLAYER)
344     {
345     /* If race isn't set, then invisible unless it is undead */
346     if (!pl->contr->invis_race)
347     {
348     if (QUERY_FLAG (mon, FLAG_UNDEAD))
349     return 0;
350 root 1.68
351 root 1.8 return 1;
352     }
353 root 1.68
354 root 1.8 /* invis_race is set if we get here */
355     if (!strcmp (pl->contr->invis_race, "undead") && is_true_undead (mon))
356     return 1;
357 root 1.68
358 root 1.8 /* No race, can't be invisible to it */
359     if (!mon->race)
360 root 1.5 return 0;
361 root 1.68
362 root 1.8 if (strstr (mon->race, pl->contr->invis_race))
363 root 1.5 return 1;
364 root 1.68
365 root 1.8 /* Nothing matched above, return 0 */
366     return 0;
367     }
368     else
369     {
370     /* monsters are invisible to everything */
371     return 1;
372 elmex 1.1 }
373     }
374    
375     /* Makes the player or character invisible.
376     * Note the spells to 'stack', but perhaps in odd ways.
377     * the duration for all is cumulative.
378     * In terms of invis undead/normal invis, it is the last one cast that
379     * will determine if you are invisible to undead or normal monsters.
380     * For improved invis, if you cast it with a one of the others, you
381     * lose the improved part of it, and the above statement about undead/
382     * normal applies.
383     */
384 root 1.8 int
385     cast_invisible (object *op, object *caster, object *spell_ob)
386     {
387     if (op->invisible > 1000)
388     {
389     new_draw_info (NDI_UNIQUE, 0, op, "You can not extend the duration of your invisibility any further");
390     return 0;
391 elmex 1.1 }
392    
393 root 1.8 /* Remove the switch with 90% duplicate code - just handle the differences with
394     * and if statement or two.
395     */
396     op->invisible += spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
397     /* max duration */
398     if (op->invisible > 1000)
399     op->invisible = 1000;
400    
401     if (op->type == PLAYER)
402     {
403     op->contr->invis_race = spell_ob->race;
404    
405     if (QUERY_FLAG (spell_ob, FLAG_MAKE_INVIS))
406     op->contr->tmp_invis = 0;
407     else
408     op->contr->tmp_invis = 1;
409    
410     op->contr->hidden = 0;
411     }
412 root 1.42
413 root 1.8 if (makes_invisible_to (op, op))
414     new_draw_info (NDI_UNIQUE, 0, op, "You can't see your hands!");
415     else
416     new_draw_info (NDI_UNIQUE, 0, op, "You feel more transparent!");
417    
418 root 1.42 update_object (op, UP_OBJ_CHANGE);
419 root 1.8
420     /* Only search the active objects - only these should actually do
421     * harm to the player.
422     */
423 root 1.33 for_all_actives (tmp)
424 root 1.8 if (tmp->enemy == op)
425 root 1.33 tmp->enemy = 0;
426    
427 root 1.8 return 1;
428 elmex 1.1 }
429    
430     /* earth to dust spell. Basically destroys earthwalls in the area.
431     */
432 root 1.8 int
433     cast_earth_to_dust (object *op, object *caster, object *spell_ob)
434     {
435     object *tmp, *next;
436     int range, i, j, mflags;
437     sint16 sx, sy;
438 root 1.13 maptile *m;
439 elmex 1.1
440 root 1.8 if (op->type != PLAYER)
441     return 0;
442 elmex 1.1
443 root 1.8 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
444 elmex 1.1
445 root 1.8 for (i = -range; i <= range; i++)
446     for (j = -range; j <= range; j++)
447     {
448     sx = op->x + i;
449     sy = op->y + j;
450     m = op->map;
451     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
452 elmex 1.1
453 root 1.8 if (mflags & P_OUT_OF_MAP)
454     continue;
455 elmex 1.1
456 root 1.8 // earth to dust tears down everything that can be teared down
457 root 1.22 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next)
458 root 1.8 {
459     next = tmp->above;
460     if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN))
461     hit_player (tmp, 9998, op, AT_PHYSICAL, 0);
462     }
463     }
464 root 1.31
465 root 1.8 return 1;
466 elmex 1.1 }
467    
468 root 1.8 void
469     execute_word_of_recall (object *op)
470     {
471 root 1.31 if (object *pl = op->in_player ())
472     {
473     if (pl->ms ().flags () & P_NO_CLERIC && !QUERY_FLAG (pl, FLAG_WIZCAST))
474     new_draw_info (NDI_UNIQUE, 0, pl, "You feel something fizzle inside you.");
475     else
476     {
477     // remove first so we do not call update_stats
478     op->remove ();
479     pl->enter_exit (op);
480     }
481     }
482 root 1.14
483 root 1.31 op->destroy ();
484 elmex 1.1 }
485    
486     /* Word of recall causes the player to return 'home'.
487     * we put a force into the player object, so that there is a
488     * time delay effect.
489     */
490 root 1.8 int
491     cast_word_of_recall (object *op, object *caster, object *spell_ob)
492     {
493     object *dummy;
494     int time;
495 elmex 1.1
496 root 1.8 if (op->type != PLAYER)
497     return 0;
498 elmex 1.1
499 root 1.8 if (find_obj_by_type_subtype (op, SPELL_EFFECT, SP_WORD_OF_RECALL))
500 elmex 1.1 {
501 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you.");
502     return 1;
503 elmex 1.1 }
504    
505 root 1.8 dummy = get_archetype (FORCE_NAME);
506     if (dummy == NULL)
507     {
508     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
509     LOG (llevError, "cast_word_of_recall: get_archetype(force) failed!\n");
510     return 0;
511     }
512 root 1.29
513 root 1.8 time = spell_ob->duration - SP_level_duration_adjust (caster, spell_ob);
514     if (time < 1)
515     time = 1;
516    
517     /* value of speed really doesn't make much difference, as long as it is
518     * positive. Lower value may be useful so that the problem doesn't
519     * do anything really odd if it say a -1000 or something.
520     */
521 root 1.26 dummy->set_speed (0.002);
522 root 1.8 dummy->speed_left = -dummy->speed * time;
523     dummy->type = SPELL_EFFECT;
524     dummy->subtype = SP_WORD_OF_RECALL;
525    
526     /* If we could take advantage of enter_player_savebed() here, it would be
527     * nice, but until the map load fails, we can't.
528     */
529     EXIT_PATH (dummy) = op->contr->savebed_map;
530 root 1.29 EXIT_X (dummy) = op->contr->bed_x;
531     EXIT_Y (dummy) = op->contr->bed_y;
532 root 1.8
533 root 1.31 op->insert (dummy);
534    
535 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you.");
536 root 1.31
537 root 1.8 return 1;
538 elmex 1.1 }
539    
540     /* cast_wonder
541     * wonder is really just a spell that will likely cast another
542     * spell.
543     */
544 root 1.8 int
545     cast_wonder (object *op, object *caster, int dir, object *spell_ob)
546     {
547     object *newspell;
548 elmex 1.1
549 root 1.8 if (!rndm (0, 3))
550     return cast_cone (op, caster, dir, spell_ob);
551 elmex 1.1
552 root 1.8 if (spell_ob->randomitems)
553     {
554     newspell = generate_treasure (spell_ob->randomitems, caster->level);
555     if (!newspell)
556     {
557     LOG (llevError, "cast_wonder: Unable to get a spell!\n");
558     return 0;
559 root 1.5 }
560 root 1.8 if (newspell->type != SPELL)
561     {
562     LOG (llevError, "cast_wonder: spell returned is not a spell (%d, %s)!\n", &newspell->type, &newspell->name);
563     return 0;
564 root 1.5 }
565 root 1.8 /* Prevent inifinit recursion */
566     if (newspell->subtype == SP_WONDER)
567     {
568     LOG (llevError, "cast_wonder: spell returned is another wonder spell!\n");
569     return 0;
570 root 1.5 }
571 root 1.8 return cast_spell (op, caster, dir, newspell, NULL);
572 elmex 1.1 }
573 root 1.8 return 1;
574 elmex 1.1 }
575    
576 root 1.8 int
577     perceive_self (object *op)
578     {
579 root 1.43 const char *cp = describe_item (op, op);
580 root 1.10 archetype *at = archetype::find (ARCH_DEPLETION);
581 root 1.8
582 root 1.60 dynbuf_text buf;
583    
584     if (player *pl = op->contr)
585     if (object *race = archetype::find (op->race))
586     buf << "You are a " << (pl->gender ? "female" : "male") << " " << &race->name << ".\n";
587    
588     if (object *god = find_god (determine_god (op)))
589     buf << "You worship " << &god->name << ".\n";
590 root 1.8 else
591 root 1.60 buf << "You worship no god.\n";
592 root 1.8
593 root 1.60 object *tmp = present_arch_in_ob (at, op);
594 root 1.8
595     if (*cp == '\0' && tmp == NULL)
596 root 1.60 buf << "You feel very mundane. ";
597 root 1.8 else
598     {
599 root 1.60 buf << "You have: " << cp << ".\n";
600 root 1.51
601     if (tmp)
602 root 1.60 for (int i = 0; i < NUM_STATS; i++)
603 root 1.51 if (tmp->stats.stat (i) < 0)
604 root 1.60 buf.printf ("Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i));
605 elmex 1.1 }
606    
607 root 1.8 if (is_dragon_pl (op))
608 root 1.60 /* now grab the 'dragon_ability'-force from the player's inventory */
609     for (tmp = op->inv; tmp; tmp = tmp->below)
610     {
611     if (tmp->type == FORCE && !strcmp (tmp->arch->archname, "dragon_ability_force"))
612     {
613     if (tmp->stats.exp == 0)
614     buf << "Your metabolism isn't focused on anything.\n";
615     else
616     buf << "Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n";
617    
618     break;
619     }
620     }
621 root 1.36
622 root 1.61 buf << '\0'; // zero-terminate
623    
624 root 1.60 new_draw_info (NDI_UNIQUE, 0, op, buf.linearise ());
625 root 1.36
626 root 1.8 return 1;
627 elmex 1.1 }
628    
629     /* This creates magic walls. Really, it can create most any object,
630     * within some reason.
631     */
632 root 1.8 int
633     magic_wall (object *op, object *caster, int dir, object *spell_ob)
634     {
635 root 1.27 object *tmp;
636 root 1.8 int i, posblocked, negblocked, maxrange;
637     sint16 x, y;
638 root 1.13 maptile *m;
639 root 1.8 const char *name;
640     archetype *at;
641    
642     if (!dir)
643     {
644     dir = op->facing;
645     x = op->x;
646     y = op->y;
647     }
648     else
649     {
650     x = op->x + freearr_x[dir];
651     y = op->y + freearr_y[dir];
652     }
653 root 1.25
654 root 1.8 m = op->map;
655    
656     if ((spell_ob->move_block || x != op->x || y != op->y) &&
657     (get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE) ||
658     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) == spell_ob->move_block)))
659     {
660     new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
661     return 0;
662     }
663 root 1.25
664 root 1.8 if (spell_ob->other_arch)
665 root 1.25 tmp = arch_to_object (spell_ob->other_arch);
666 root 1.8 else if (spell_ob->race)
667     {
668     char buf1[MAX_BUF];
669    
670     sprintf (buf1, spell_ob->race, dir);
671 root 1.10 at = archetype::find (buf1);
672 root 1.8 if (!at)
673     {
674     LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1);
675     new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken.");
676     return 0;
677 root 1.5 }
678 root 1.27
679 root 1.8 tmp = arch_to_object (at);
680     }
681     else
682     {
683     LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name);
684     return 0;
685     }
686    
687     if (tmp->type == SPELL_EFFECT)
688     {
689     tmp->attacktype = spell_ob->attacktype;
690     tmp->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
691     tmp->stats.dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
692     tmp->range = 0;
693     }
694     else if (QUERY_FLAG (tmp, FLAG_ALIVE))
695     {
696     tmp->stats.hp = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
697     tmp->stats.maxhp = tmp->stats.hp;
698     }
699 root 1.25
700 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG (tmp, FLAG_IS_USED_UP))
701     {
702     tmp->stats.food = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
703     SET_FLAG (tmp, FLAG_IS_USED_UP);
704 elmex 1.1 }
705 root 1.25
706 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_TEAR_DOWN))
707     {
708     tmp->stats.hp = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
709     tmp->stats.maxhp = tmp->stats.hp;
710     SET_FLAG (tmp, FLAG_TEAR_DOWN);
711     SET_FLAG (tmp, FLAG_ALIVE);
712     }
713    
714     /* This can't really hurt - if the object doesn't kill anything,
715 root 1.25 * these fields just won't be used. Do not set the owner for
716     * earthwalls, though, so they survive restarts.
717 root 1.8 */
718 root 1.25 if (tmp->type != EARTHWALL) //TODO
719     tmp->set_owner (op);
720    
721 root 1.8 set_spell_skill (op, caster, spell_ob, tmp);
722     tmp->level = caster_level (caster, spell_ob) / 2;
723 elmex 1.1
724 root 1.8 name = tmp->name;
725 root 1.27 if (!(tmp = m->insert (tmp, x, y, op)))
726 root 1.8 {
727     new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name);
728     return 0;
729 elmex 1.1 }
730 root 1.25
731 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
732 root 1.57 if (tmp->other_arch && tmp->other_arch->type == SPELL)
733 root 1.8 insert_ob_in_ob (arch_to_object (tmp->other_arch), tmp);
734    
735     /* This code causes the wall to extend some distance in
736     * each direction, or until an obstruction is encountered.
737     * posblocked and negblocked help determine how far the
738     * created wall can extend, it won't go extend through
739     * blocked spaces.
740     */
741     maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
742     posblocked = 0;
743     negblocked = 0;
744    
745     for (i = 1; i <= maxrange; i++)
746     {
747     int dir2;
748    
749     dir2 = (dir < 4) ? (dir + 2) : dir - 2;
750    
751     x = tmp->x + i * freearr_x[dir2];
752     y = tmp->y + i * freearr_y[dir2];
753     m = tmp->map;
754    
755     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
756     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !posblocked)
757     {
758 root 1.27 object *tmp2 = tmp->clone ();
759     m->insert (tmp2, x, y, op);
760    
761 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
762 root 1.57 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
763 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
764 root 1.8
765     }
766     else
767     posblocked = 1;
768    
769     x = tmp->x - i * freearr_x[dir2];
770     y = tmp->y - i * freearr_y[dir2];
771     m = tmp->map;
772    
773     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
774     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !negblocked)
775     {
776 root 1.27 object *tmp2 = tmp->clone ();
777     m->insert (tmp2, x, y, op);
778    
779 root 1.57 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
780 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
781 root 1.8 }
782     else
783     negblocked = 1;
784 elmex 1.1 }
785    
786 root 1.8 if (QUERY_FLAG (tmp, FLAG_BLOCKSVIEW))
787     update_all_los (op->map, op->x, op->y);
788 elmex 1.1
789 root 1.8 return 1;
790 elmex 1.1 }
791    
792 root 1.8 int
793     dimension_door (object *op, object *caster, object *spob, int dir)
794     {
795     uint32 dist, maxdist;
796     int mflags;
797 root 1.13 maptile *m;
798 root 1.8 sint16 sx, sy;
799 elmex 1.1
800 root 1.8 if (op->type != PLAYER)
801     return 0;
802 elmex 1.1
803 root 1.8 if (!dir)
804     {
805     new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
806     return 0;
807 elmex 1.1 }
808    
809 root 1.8 /* Given the new outdoor maps, can't let players dimension door for
810     * ever, so put limits in.
811     */
812     maxdist = spob->range + SP_level_range_adjust (caster, spob);
813    
814     if (op->contr->count)
815     {
816     if (op->contr->count > maxdist)
817     {
818     new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!");
819     return 0;
820 root 1.5 }
821    
822 root 1.8 for (dist = 0; dist < op->contr->count; dist++)
823     {
824     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
825 root 1.5
826 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
827     break;
828 root 1.5
829 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
830     break;
831 root 1.5 }
832    
833 root 1.8 if (dist < op->contr->count)
834     {
835     new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n");
836     op->contr->count = 0;
837     return 0;
838     }
839 root 1.27
840 root 1.8 op->contr->count = 0;
841    
842     /* Remove code that puts player on random space on maps. IMO,
843     * a lot of maps probably have areas the player should not get to,
844     * but may not be marked as NO_MAGIC (as they may be bounded
845     * by such squares). Also, there are probably treasure rooms and
846     * lots of other maps that protect areas with no magic, but the
847     * areas themselves don't contain no magic spaces.
848     */
849     /* This call here is really just to normalize the coordinates */
850     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, &sx, &sy);
851     if (mflags & P_IS_ALIVE || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
852     {
853     new_draw_info (NDI_UNIQUE, 0, op, "You cast your spell, but nothing happens.\n");
854     return 1; /* Maybe the penalty should be more severe... */
855 root 1.5 }
856 root 1.8 }
857     else
858     {
859     /* Player didn't specify a distance, so lets see how far
860     * we can move the player. Don't know why this stopped on
861     * spaces that blocked the players view.
862     */
863 root 1.5
864 root 1.8 for (dist = 0; dist < maxdist; dist++)
865     {
866     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
867 root 1.5
868 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
869     break;
870 root 1.5
871 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
872     break;
873 root 1.5
874     }
875    
876 root 1.8 /* If the destination is blocked, keep backing up until we
877     * find a place for the player.
878     */
879     for (; dist > 0; dist--)
880     {
881     if (get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist,
882     &sx, &sy) & (P_OUT_OF_MAP | P_IS_ALIVE))
883     continue;
884 root 1.5
885    
886 root 1.8 if (!OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
887     break;
888 root 1.5
889     }
890 root 1.8 if (!dist)
891     {
892     new_draw_info (NDI_UNIQUE, 0, op, "Your spell failed!\n");
893     return 0;
894 root 1.5 }
895 elmex 1.1 }
896    
897 root 1.8 /* Actually move the player now */
898 root 1.27 if (!(op = op->map->insert (op, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, op)))
899 root 1.8 return 1;
900 elmex 1.1
901 root 1.8 op->speed_left = -FABS (op->speed) * 5; /* Freeze them for a short while */
902     return 1;
903 elmex 1.1 }
904    
905    
906     /* cast_heal: Heals something.
907     * op is the caster.
908     * dir is the direction he is casting it in.
909     * spell is the spell object.
910     */
911 root 1.8 int
912     cast_heal (object *op, object *caster, object *spell, int dir)
913     {
914     object *tmp;
915     archetype *at;
916     object *poison;
917     int heal = 0, success = 0;
918    
919     tmp = find_target_for_friendly_spell (op, dir);
920    
921 root 1.40 if (!tmp)
922 root 1.8 return 0;
923    
924     /* Figure out how many hp this spell might cure.
925     * could be zero if this spell heals effects, not damage.
926     */
927     heal = spell->stats.dam;
928     if (spell->stats.hp)
929     heal += random_roll (spell->stats.hp, 6, op, PREFER_HIGH) + spell->stats.hp;
930    
931     if (heal)
932     {
933     if (tmp->stats.hp >= tmp->stats.maxhp)
934 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You are already fully healed.");
935 root 1.8 else
936     {
937     /* See how many points we actually heal. Instead of messages
938     * based on type of spell, we instead do messages based
939     * on amount of damage healed.
940     */
941     if (heal > (tmp->stats.maxhp - tmp->stats.hp))
942     heal = tmp->stats.maxhp - tmp->stats.hp;
943     tmp->stats.hp += heal;
944    
945     if (tmp->stats.hp >= tmp->stats.maxhp)
946 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel just fine!");
947 root 1.8 else if (heal > 50)
948 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds close!");
949 root 1.8 else if (heal > 25)
950 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds mostly close.");
951 root 1.8 else if (heal > 10)
952 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to fade.");
953 root 1.8 else
954 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to close.");
955    
956 root 1.8 success = 1;
957     }
958     }
959 root 1.40
960 root 1.8 if (spell->attacktype & AT_DISEASE)
961     if (cure_disease (tmp, op))
962     success = 1;
963    
964     if (spell->attacktype & AT_POISON)
965     {
966 root 1.10 at = archetype::find ("poisoning");
967 root 1.8 poison = present_arch_in_ob (at, tmp);
968     if (poison)
969     {
970     success = 1;
971     new_draw_info (NDI_UNIQUE, 0, tmp, "Your body feels cleansed");
972     poison->stats.food = 1;
973 root 1.5 }
974 elmex 1.1 }
975 root 1.40
976 root 1.8 if (spell->attacktype & AT_CONFUSION)
977     {
978     poison = present_in_ob_by_name (FORCE, "confusion", tmp);
979     if (poison)
980     {
981     success = 1;
982     new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
983     poison->duration = 1;
984 root 1.5 }
985 elmex 1.1 }
986 root 1.40
987 root 1.8 if (spell->attacktype & AT_BLIND)
988     {
989 root 1.10 at = archetype::find ("blindness");
990 root 1.8 poison = present_arch_in_ob (at, tmp);
991     if (poison)
992     {
993     success = 1;
994     new_draw_info (NDI_UNIQUE, 0, tmp, "Your vision begins to return.");
995     poison->stats.food = 1;
996 root 1.5 }
997 elmex 1.1 }
998 root 1.40
999 root 1.8 if (spell->last_sp && tmp->stats.sp < tmp->stats.maxsp)
1000     {
1001     tmp->stats.sp += spell->last_sp;
1002     if (tmp->stats.sp > tmp->stats.maxsp)
1003     tmp->stats.sp = tmp->stats.maxsp;
1004     success = 1;
1005     new_draw_info (NDI_UNIQUE, 0, tmp, "Magical energy surges through your body!");
1006     }
1007 root 1.40
1008 root 1.8 if (spell->last_grace && tmp->stats.grace < tmp->stats.maxgrace)
1009     {
1010     tmp->stats.grace += spell->last_grace;
1011     if (tmp->stats.grace > tmp->stats.maxgrace)
1012     tmp->stats.grace = tmp->stats.maxgrace;
1013     success = 1;
1014     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!");
1015 elmex 1.1 }
1016 root 1.40
1017 root 1.8 if (spell->stats.food && tmp->stats.food < 999)
1018     {
1019     tmp->stats.food += spell->stats.food;
1020     if (tmp->stats.food > 999)
1021     tmp->stats.food = 999;
1022     success = 1;
1023     /* We could do something a bit better like the messages for healing above */
1024     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food");
1025     }
1026 root 1.40
1027 root 1.8 return success;
1028 elmex 1.1 }
1029    
1030     /* This is used for the spells that gain stats. There are no spells
1031     * right now that icnrease wis/int/pow on a temp basis, so no
1032     * good comments for those.
1033     */
1034 root 1.8 static const char *const no_gain_msgs[NUM_STATS] = {
1035     "You grow no stronger.",
1036     "You grow no more agile.",
1037     "You don't feel any healthier.",
1038 root 1.55 "You didn't grow any more intelligent.",
1039     "You do not feel any wiser.",
1040     "You don't feel any more powerful."
1041 root 1.8 "You are no easier to look at.",
1042 elmex 1.1 };
1043    
1044 root 1.8 int
1045     cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1046     {
1047     object *force = NULL;
1048     int i;
1049    
1050     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1051 root 1.27 object *tmp = dir
1052     ? find_target_for_friendly_spell (op, dir)
1053     : op;
1054 root 1.8
1055 root 1.27 if (!tmp)
1056 root 1.8 return 0;
1057    
1058     /* If we've already got a force of this type, don't add a new one. */
1059 root 1.27 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1060 root 1.8 {
1061     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1062     {
1063     if (tmp2->name == spell_ob->name)
1064     {
1065     force = tmp2; /* the old effect will be "refreshed" */
1066     break;
1067 root 1.5 }
1068 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1069     {
1070     if (!silent)
1071     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1072     return 0;
1073 root 1.5 }
1074     }
1075 elmex 1.1 }
1076 root 1.8 if (force == NULL)
1077     {
1078     force = get_archetype (FORCE_NAME);
1079     force->subtype = FORCE_CHANGE_ABILITY;
1080     if (spell_ob->race)
1081     force->name = spell_ob->race;
1082     else
1083     force->name = spell_ob->name;
1084     force->name_pl = spell_ob->name;
1085     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1086    
1087     }
1088     else
1089     {
1090     int duration;
1091    
1092     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1093     if (duration > force->duration)
1094     {
1095     force->duration = duration;
1096     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1097     }
1098     else
1099     {
1100     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1101     }
1102 root 1.55
1103 root 1.8 return 1;
1104     }
1105 root 1.55
1106 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1107     force->speed = 1.0;
1108     force->speed_left = -1.0;
1109     SET_FLAG (force, FLAG_APPLIED);
1110    
1111     /* Now start processing the effects. First, protections */
1112     for (i = 0; i < NROFATTACKS; i++)
1113     {
1114     if (spell_ob->resist[i])
1115     {
1116     force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob);
1117     if (force->resist[i] > 100)
1118     force->resist[i] = 100;
1119 root 1.5 }
1120 elmex 1.1 }
1121 root 1.55
1122 root 1.8 if (spell_ob->stats.hp)
1123     force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1124    
1125     if (tmp->type == PLAYER)
1126     {
1127     /* Stat adjustment spells */
1128     for (i = 0; i < NUM_STATS; i++)
1129     {
1130 root 1.51 if (sint8 stat = spell_ob->stats.stat (i))
1131 root 1.8 {
1132 root 1.51 sint8 sm = 0;
1133     for (sint8 k = 0; k < stat; k++)
1134 root 1.8 sm += rndm (1, 3);
1135    
1136 root 1.51 if (tmp->stats.stat (i) + sm > 15 + 5 * stat)
1137     sm = max (0, (15 + 5 * stat) - tmp->stats.stat (i));
1138    
1139     force->stats.stat (i) = sm;
1140    
1141 root 1.8 if (!sm)
1142     new_draw_info (NDI_UNIQUE, 0, op, no_gain_msgs[i]);
1143 root 1.5 }
1144     }
1145 elmex 1.1 }
1146    
1147 root 1.8 force->move_type = spell_ob->move_type;
1148 elmex 1.1
1149 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK))
1150     SET_FLAG (force, FLAG_SEE_IN_DARK);
1151 elmex 1.1
1152 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_XRAYS))
1153     SET_FLAG (force, FLAG_XRAYS);
1154 elmex 1.1
1155 root 1.8 /* Haste/bonus speed */
1156     if (spell_ob->stats.exp)
1157     {
1158     if (op->speed > 0.5f)
1159     force->stats.exp = (sint64) ((float) spell_ob->stats.exp / (op->speed + 0.5f));
1160     else
1161     force->stats.exp = spell_ob->stats.exp;
1162 elmex 1.1 }
1163    
1164 root 1.8 force->stats.wc = spell_ob->stats.wc;
1165     force->stats.ac = spell_ob->stats.ac;
1166     force->attacktype = spell_ob->attacktype;
1167    
1168     insert_ob_in_ob (force, tmp);
1169     change_abil (tmp, force); /* Mostly to display any messages */
1170 root 1.24 tmp->update_stats ();
1171 root 1.55
1172 root 1.8 return 1;
1173 elmex 1.1 }
1174    
1175     /* This used to be part of cast_change_ability, but it really didn't make
1176     * a lot of sense, since most of the values it derives are from the god
1177     * of the caster.
1178     */
1179 root 1.8 int
1180     cast_bless (object *op, object *caster, object *spell_ob, int dir)
1181     {
1182     int i;
1183     object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp;
1184    
1185     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1186     if (dir != 0)
1187     {
1188     tmp = find_target_for_friendly_spell (op, dir);
1189     }
1190     else
1191     {
1192     tmp = op;
1193     }
1194    
1195     /* If we've already got a force of this type, don't add a new one. */
1196     for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1197     {
1198     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1199     {
1200     if (tmp2->name == spell_ob->name)
1201     {
1202     force = tmp2; /* the old effect will be "refreshed" */
1203     break;
1204 root 1.5 }
1205 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1206     {
1207     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1208     return 0;
1209 root 1.5 }
1210     }
1211 elmex 1.1 }
1212 root 1.8 if (force == NULL)
1213     {
1214     force = get_archetype (FORCE_NAME);
1215     force->subtype = FORCE_CHANGE_ABILITY;
1216     if (spell_ob->race)
1217     force->name = spell_ob->race;
1218     else
1219     force->name = spell_ob->name;
1220     force->name_pl = spell_ob->name;
1221     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1222     }
1223     else
1224     {
1225     int duration;
1226    
1227     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1228     if (duration > force->duration)
1229     {
1230     force->duration = duration;
1231     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1232 root 1.5 }
1233 root 1.8 else
1234     {
1235     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1236     }
1237     return 0;
1238 elmex 1.1 }
1239 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1240     force->speed = 1.0;
1241     force->speed_left = -1.0;
1242     SET_FLAG (force, FLAG_APPLIED);
1243 elmex 1.1
1244 root 1.8 if (!god)
1245     {
1246     new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1247     }
1248     else
1249     {
1250     /* Only give out good benefits, and put a max on it */
1251     for (i = 0; i < NROFATTACKS; i++)
1252     {
1253     if (god->resist[i] > 0)
1254     {
1255     force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1256 root 1.5 }
1257     }
1258 root 1.8 force->path_attuned |= god->path_attuned;
1259 root 1.7
1260 root 1.8 if (spell_ob->attacktype)
1261     force->slaying = god->slaying;
1262 root 1.7
1263 root 1.8 if (tmp != op)
1264     {
1265     new_draw_info_format (NDI_UNIQUE, 0, op, "You bless %s.", &tmp->name);
1266     new_draw_info_format (NDI_UNIQUE, 0, tmp, "%s blessed you.", &op->name);
1267     }
1268     else
1269     {
1270     new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are blessed by %s!", &god->name);
1271 root 1.5 }
1272 elmex 1.1
1273     }
1274 root 1.8 force->stats.wc = spell_ob->stats.wc;
1275     force->stats.ac = spell_ob->stats.ac;
1276 elmex 1.1
1277 root 1.8 change_abil (tmp, force); /* Mostly to display any messages */
1278     insert_ob_in_ob (force, tmp);
1279 root 1.24 tmp->update_stats ();
1280 root 1.8 return 1;
1281 elmex 1.1 }
1282    
1283     /* Alchemy code by Mark Wedel
1284     *
1285     * This code adds a new spell, called alchemy. Alchemy will turn
1286 root 1.66 * objects to pyrite ("false gold"), henceforth called gold nuggets.
1287     *
1288     * The value of the gold nuggets being about 90% of that of the item
1289     * itself. It uses the value of the object before charisma adjustments,
1290     * because the nuggets themselves will be will be adjusted by charisma
1291     * when sold.
1292 elmex 1.1 *
1293     * There is also a chance (1:30) that you will get nothing at all
1294     * for the object. There is also a maximum weight that will be
1295 root 1.37 * alchemised.
1296 elmex 1.1 */
1297 root 1.8 static void
1298 root 1.38 alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1299 root 1.8 {
1300     uint64 value = query_cost (obj, NULL, F_TRUE);
1301    
1302     /* Give third price when we alchemy money (This should hopefully
1303     * make it so that it isn't worth it to alchemy money, sell
1304     * the nuggets, alchemy the gold from that, etc.
1305     * Otherwise, give 9 silver on the gold for other objects,
1306     * so that it would still be more affordable to haul
1307     * the stuff back to town.
1308     */
1309     if (QUERY_FLAG (obj, FLAG_UNPAID))
1310     value = 0;
1311     else if (obj->type == MONEY || obj->type == GEM)
1312     value /= 3;
1313     else
1314 root 1.39 value = value * 9 / 10;
1315 root 1.8
1316 root 1.37 if (obj->value > 0 && rndm (0, 29))
1317 root 1.38 total_value += value;
1318 root 1.8
1319 root 1.38 total_weight += obj->total_weight ();
1320 root 1.8
1321 root 1.17 obj->destroy ();
1322 root 1.8 }
1323    
1324     int
1325     alchemy (object *op, object *caster, object *spell_ob)
1326 elmex 1.1 {
1327 root 1.8 if (op->type != PLAYER)
1328     return 0;
1329    
1330 root 1.66 archetype *nugget[3];
1331    
1332     nugget[0] = archetype::find ("pyrite3");
1333     nugget[1] = archetype::find ("pyrite2");
1334     nugget[2] = archetype::find ("pyrite");
1335 root 1.39
1336 root 1.38 /* Put a maximum weight of items that can be alchemised. Limits the power
1337     * some, and also prevents people from alchemising every table/chair/clock
1338 root 1.8 * in sight
1339     */
1340 root 1.38 int duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1341     int weight_max = duration * 1000;
1342     uint64 value_max = duration * 1000;
1343 elmex 1.1
1344 root 1.39 int weight = 0;
1345 root 1.38
1346     for (int y = op->y - 1; y <= op->y + 1; y++)
1347 root 1.8 {
1348 root 1.38 for (int x = op->x - 1; x <= op->x + 1; x++)
1349 root 1.8 {
1350 root 1.38 uint64 value = 0;
1351    
1352     sint16 nx = x;
1353     sint16 ny = y;
1354 elmex 1.1
1355 root 1.39 maptile *mp = op->map;
1356 root 1.5
1357 root 1.39 int mflags = get_map_flags (mp, &mp, nx, ny, &nx, &ny);
1358 root 1.5
1359 root 1.8 if (mflags & (P_OUT_OF_MAP | P_NO_MAGIC))
1360     continue;
1361    
1362     /* Treat alchemy a little differently - most spell effects
1363     * use fly as the movement type - for alchemy, consider it
1364     * ground level effect.
1365     */
1366     if (GET_MAP_MOVE_BLOCK (mp, nx, ny) & MOVE_WALK)
1367     continue;
1368    
1369 root 1.38 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1370 root 1.8 {
1371     next = tmp->above;
1372 root 1.37
1373 root 1.8 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) &&
1374     !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
1375     {
1376     if (tmp->inv)
1377     {
1378     object *next1, *tmp1;
1379    
1380 root 1.37 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1381 root 1.8 {
1382     next1 = tmp1->below;
1383     if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) &&
1384     !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON))
1385 root 1.38 alchemy_object (tmp1, value, weight);
1386 root 1.5 }
1387     }
1388 root 1.37
1389 root 1.38 alchemy_object (tmp, value, weight);
1390 root 1.8
1391     if (weight > weight_max)
1392 root 1.38 break;
1393     }
1394     }
1395    
1396 root 1.66 value -= rndm (value >> 4);
1397 root 1.38 value = min (value, value_max);
1398    
1399 root 1.66 for (int i = 0; i < sizeof (nugget) / sizeof (nugget [0]); ++i)
1400     if (int nrof = value / nugget [i]->value)
1401     {
1402     value -= nrof * nugget[i]->value;
1403    
1404     object *tmp = arch_to_object (nugget[i]);
1405     tmp->nrof = nrof;
1406     tmp->flag [FLAG_IDENTIFIED] = true;
1407 root 1.67 op->map->insert (tmp, x, y, op, 0);
1408 root 1.66 }
1409 root 1.38
1410     if (weight > weight_max)
1411     goto bailout;
1412 root 1.8 }
1413     }
1414 root 1.17
1415 root 1.38 bailout:
1416 root 1.8 return 1;
1417 elmex 1.1 }
1418    
1419    
1420     /* This function removes the cursed/damned status on equipped
1421     * items.
1422     */
1423 root 1.8 int
1424     remove_curse (object *op, object *caster, object *spell)
1425     {
1426     object *tmp;
1427     int success = 0, was_one = 0;
1428    
1429     for (tmp = op->inv; tmp; tmp = tmp->below)
1430     if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1431     ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1432     (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1433     {
1434     was_one++;
1435     if (tmp->level <= caster_level (caster, spell))
1436     {
1437     success++;
1438     if (QUERY_FLAG (spell, FLAG_DAMNED))
1439     CLEAR_FLAG (tmp, FLAG_DAMNED);
1440    
1441     CLEAR_FLAG (tmp, FLAG_CURSED);
1442     CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1443     tmp->value = 0; /* Still can't sell it */
1444     if (op->type == PLAYER)
1445     esrv_send_item (op, tmp);
1446     }
1447     }
1448    
1449     if (op->type == PLAYER)
1450     {
1451     if (success)
1452 root 1.38 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now.");
1453 root 1.8 else
1454     {
1455     if (was_one)
1456     new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse.");
1457     else
1458     new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items.");
1459 root 1.5 }
1460 elmex 1.1 }
1461 root 1.21
1462 root 1.8 return success;
1463 elmex 1.1 }
1464    
1465     /* Identifies objects in the players inventory/on the ground */
1466    
1467 root 1.8 int
1468     cast_identify (object *op, object *caster, object *spell)
1469     {
1470     object *tmp;
1471     int success = 0, num_ident;
1472    
1473     num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1474    
1475     if (num_ident < 1)
1476     num_ident = 1;
1477    
1478     for (tmp = op->inv; tmp; tmp = tmp->below)
1479     {
1480     if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1481     {
1482     identify (tmp);
1483 root 1.21
1484 root 1.8 if (op->type == PLAYER)
1485     {
1486 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "You identified: %s.", long_desc (tmp, op));
1487 root 1.21
1488 root 1.8 if (tmp->msg)
1489     {
1490     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1491     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1492 root 1.5 }
1493     }
1494 root 1.21
1495 root 1.8 num_ident--;
1496     success = 1;
1497     if (!num_ident)
1498     break;
1499 root 1.5 }
1500 elmex 1.1 }
1501 root 1.21
1502 root 1.8 /* If all the power of the spell has been used up, don't go and identify
1503     * stuff on the floor. Only identify stuff on the floor if the spell
1504     * was not fully used.
1505     */
1506     if (num_ident)
1507     {
1508 root 1.48 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1509 root 1.8 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1510     {
1511 root 1.21 identify (tmp);
1512 root 1.8
1513     if (op->type == PLAYER)
1514     {
1515 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "On the ground you identified: %s.", long_desc (tmp, op));
1516 root 1.21
1517 root 1.8 if (tmp->msg)
1518     {
1519     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1520     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1521     }
1522 root 1.21
1523 root 1.8 esrv_send_item (op, tmp);
1524     }
1525 root 1.21
1526 root 1.5 num_ident--;
1527 root 1.8 success = 1;
1528     if (!num_ident)
1529     break;
1530     }
1531     }
1532 root 1.21
1533 root 1.8 if (!success)
1534     new_draw_info (NDI_UNIQUE, 0, op, "You can't reach anything unidentified.");
1535     else
1536 root 1.21 spell_effect (spell, op->x, op->y, op->map, op);
1537    
1538 root 1.8 return success;
1539 elmex 1.1 }
1540    
1541 root 1.8 int
1542     cast_detection (object *op, object *caster, object *spell, object *skill)
1543     {
1544     object *tmp, *last, *god, *detect;
1545     int done_one, range, mflags, floor, level;
1546     sint16 x, y, nx, ny;
1547 root 1.13 maptile *m;
1548 root 1.8
1549     /* We precompute some values here so that we don't have to keep
1550     * doing it over and over again.
1551     */
1552     god = find_god (determine_god (op));
1553     level = caster_level (caster, spell);
1554     range = spell->range + SP_level_range_adjust (caster, spell);
1555    
1556     if (!skill)
1557     skill = caster;
1558    
1559     for (x = op->x - range; x <= op->x + range; x++)
1560     for (y = op->y - range; y <= op->y + range; y++)
1561     {
1562     m = op->map;
1563     mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1564     if (mflags & P_OUT_OF_MAP)
1565     continue;
1566    
1567     /* For most of the detections, we only detect objects above the
1568     * floor. But this is not true for show invisible.
1569     * Basically, we just go and find the top object and work
1570     * down - that is easier than working up.
1571     */
1572 elmex 1.1
1573 root 1.22 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above)
1574 root 1.8 last = tmp;
1575 root 1.21
1576 root 1.8 /* Shouldn't happen, but if there are no objects on a space, this
1577     * would happen.
1578     */
1579     if (!last)
1580     continue;
1581 elmex 1.1
1582 root 1.8 done_one = 0;
1583     floor = 0;
1584     detect = NULL;
1585     for (tmp = last; tmp; tmp = tmp->below)
1586     {
1587     /* show invisible */
1588     if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) &&
1589 root 1.21 /* Might there be other objects that we can make visible? */
1590 root 1.8 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) ||
1591     (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) ||
1592     tmp->type == CF_HANDLE ||
1593     tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
1594     tmp->type == BUTTON || tmp->type == TELEPORTER ||
1595     tmp->type == GATE || tmp->type == LOCKED_DOOR ||
1596     tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
1597     tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
1598     tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR)))
1599     {
1600     if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1601     {
1602     tmp->invisible = 0;
1603     done_one = 1;
1604     }
1605     }
1606 root 1.21
1607 root 1.8 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1608     floor = 1;
1609 elmex 1.1
1610 root 1.8 /* All detections below this point don't descend beneath the floor,
1611     * so just continue on. We could be clever and look at the type of
1612     * detection to completely break out if we don't care about objects beneath
1613     * the floor, but once we get to the floor, not likely a very big issue anyways.
1614     */
1615     if (floor)
1616     continue;
1617 root 1.5
1618 root 1.8 /* I had thought about making detect magic and detect curse
1619     * show the flash the magic item like it does for detect monster.
1620     * however, if the object is within sight, this would then make it
1621     * difficult to see what object is magical/cursed, so the
1622     * effect wouldn't be as apparant.
1623 root 1.5 */
1624    
1625 root 1.8 /* detect magic */
1626     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1627     !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1628     {
1629     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1630     /* make runes more visibile */
1631     if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1632     tmp->stats.Cha /= 4;
1633     done_one = 1;
1634     }
1635     /* detect monster */
1636     if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1637     {
1638     done_one = 2;
1639     if (!detect)
1640     detect = tmp;
1641     }
1642     /* Basically, if race is set in the spell, then the creatures race must
1643     * match that. if the spell race is set to GOD, then the gods opposing
1644     * race must match.
1645 root 1.5 */
1646 root 1.8 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1647     ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) ||
1648     (strstr (spell->race, tmp->race))))
1649     {
1650     done_one = 2;
1651     if (!detect)
1652     detect = tmp;
1653     }
1654     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1655     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1656     {
1657     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1658     done_one = 1;
1659     }
1660     } /* for stack of objects on this space */
1661 root 1.5
1662 root 1.8 /* Code here puts an effect of the spell on the space, so you can see
1663     * where the magic is.
1664     */
1665     if (done_one)
1666     {
1667     object *detect_ob = arch_to_object (spell->other_arch);
1668    
1669     /* if this is set, we want to copy the face */
1670     if (done_one == 2 && detect)
1671     {
1672     detect_ob->face = detect->face;
1673     detect_ob->animation_id = detect->animation_id;
1674     detect_ob->anim_speed = detect->anim_speed;
1675     detect_ob->last_anim = 0;
1676     /* by default, the detect_ob is already animated */
1677     if (!QUERY_FLAG (detect, FLAG_ANIMATE))
1678     CLEAR_FLAG (detect_ob, FLAG_ANIMATE);
1679     }
1680 root 1.27
1681     m->insert (detect_ob, nx, ny, op);
1682 root 1.8 }
1683     } /* for processing the surrounding spaces */
1684 root 1.5
1685    
1686 root 1.8 /* Now process objects in the players inventory if detect curse or magic */
1687     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL))
1688     {
1689     done_one = 0;
1690     for (tmp = op->inv; tmp; tmp = tmp->below)
1691     {
1692     if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1693     {
1694     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL))
1695     {
1696     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1697     if (op->type == PLAYER)
1698     esrv_send_item (op, tmp);
1699 root 1.5 }
1700 root 1.8 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1701     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1702     {
1703     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1704     if (op->type == PLAYER)
1705     esrv_send_item (op, tmp);
1706 root 1.5 }
1707 root 1.8 } /* if item is not identified */
1708     } /* for the players inventory */
1709     } /* if detect magic/curse and object is a player */
1710     return 1;
1711 elmex 1.1 }
1712    
1713    
1714     /**
1715     * Checks if victim has overcharged mana. caster_level is the caster's (skill)
1716     * level whos spell did cause the overcharge.
1717     */
1718 root 1.8 static void
1719     charge_mana_effect (object *victim, int caster_level)
1720 elmex 1.1 {
1721    
1722 root 1.8 /* Prevent explosions for objects without mana. Without this check, doors
1723     * will explode, too.
1724     */
1725     if (victim->stats.maxsp <= 0)
1726     return;
1727 elmex 1.1
1728 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
1729 elmex 1.1
1730 root 1.8 if (victim->stats.sp >= victim->stats.maxsp * 2)
1731     {
1732     object *tmp;
1733 elmex 1.1
1734 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
1735 elmex 1.1
1736 root 1.8 /* Explodes a fireball centered at player */
1737     tmp = get_archetype (EXPLODING_FIREBALL);
1738     tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
1739     tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
1740 root 1.27
1741     tmp->insert_at (victim);
1742 root 1.8 victim->stats.sp = 2 * victim->stats.maxsp;
1743 elmex 1.1 }
1744 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
1745 root 1.27 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode.");
1746 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
1747 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
1748 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
1749     {
1750     new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
1751     confuse_player (victim, victim, 99);
1752 elmex 1.1 }
1753 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.25)
1754 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You start hearing voices.");
1755 elmex 1.1 }
1756    
1757     /* cast_transfer
1758     * This spell transfers sp from the player to another person.
1759     * We let the target go above their normal maximum SP.
1760     */
1761    
1762 root 1.8 int
1763     cast_transfer (object *op, object *caster, object *spell, int dir)
1764     {
1765     object *plyr = NULL;
1766     sint16 x, y;
1767 root 1.13 maptile *m;
1768 root 1.8 int mflags;
1769    
1770     m = op->map;
1771     x = op->x + freearr_x[dir];
1772     y = op->y + freearr_y[dir];
1773    
1774     mflags = get_map_flags (m, &m, x, y, &x, &y);
1775    
1776     if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
1777     {
1778 root 1.22 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above)
1779 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1780     break;
1781 elmex 1.1 }
1782    
1783    
1784 root 1.8 /* If we did not find a player in the specified direction, transfer
1785     * to anyone on top of us. This is used for the rune of transference mostly.
1786     */
1787     if (plyr == NULL)
1788 root 1.22 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
1789 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1790     break;
1791 elmex 1.1
1792 root 1.8 if (!plyr)
1793     {
1794     new_draw_info (NDI_BLACK, 0, op, "There is no one there.");
1795     return 0;
1796 elmex 1.1 }
1797 root 1.8 /* give sp */
1798     if (spell->stats.dam > 0)
1799     {
1800     plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
1801     charge_mana_effect (plyr, caster_level (caster, spell));
1802     return 1;
1803 elmex 1.1 }
1804 root 1.8 /* suck sp away. Can't suck sp from yourself */
1805     else if (op != plyr)
1806     {
1807     /* old dragin magic used floats. easier to just use ints and divide by 100 */
1808    
1809     int rate = -spell->stats.dam + SP_level_dam_adjust (caster, spell), sucked;
1810    
1811     if (rate > 95)
1812     rate = 95;
1813    
1814     sucked = (plyr->stats.sp * rate) / 100;
1815     plyr->stats.sp -= sucked;
1816     if (QUERY_FLAG (op, FLAG_ALIVE))
1817     {
1818     /* Player doesn't get full credit */
1819     sucked = (sucked * rate) / 100;
1820     op->stats.sp += sucked;
1821     if (sucked > 0)
1822     {
1823     charge_mana_effect (op, caster_level (caster, spell));
1824 root 1.5 }
1825     }
1826 root 1.8 return 1;
1827 elmex 1.1 }
1828 root 1.8 return 0;
1829 elmex 1.1 }
1830    
1831    
1832     /* counterspell: nullifies spell effects.
1833     * op is the counterspell object, dir is the direction
1834     * it was cast in.
1835     * Basically, if the object has a magic attacktype,
1836     * this may nullify it.
1837     */
1838 root 1.8 void
1839     counterspell (object *op, int dir)
1840 elmex 1.1 {
1841 root 1.8 object *tmp, *head, *next;
1842     int mflags;
1843 root 1.13 maptile *m;
1844 root 1.8 sint16 sx, sy;
1845    
1846     sx = op->x + freearr_x[dir];
1847     sy = op->y + freearr_y[dir];
1848     m = op->map;
1849     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1850     if (mflags & P_OUT_OF_MAP)
1851     return;
1852 elmex 1.1
1853 root 1.22 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next)
1854 root 1.8 {
1855     next = tmp->above;
1856 elmex 1.1
1857 root 1.8 /* Need to look at the head object - otherwise, if tmp
1858     * points to a monster, we don't have all the necessary
1859     * info for it.
1860     */
1861     if (tmp->head)
1862     head = tmp->head;
1863     else
1864     head = tmp;
1865    
1866     /* don't attack our own spells */
1867     if (tmp->owner && tmp->owner == op->owner)
1868     continue;
1869    
1870     /* Basically, if the object is magical and not counterspell,
1871     * we will more or less remove the object. Don't counterspell
1872     * monsters either.
1873     */
1874 elmex 1.1
1875 elmex 1.44 if (head->attacktype & AT_MAGIC
1876     && !(head->attacktype & AT_COUNTERSPELL)
1877     && !QUERY_FLAG (head, FLAG_MONSTER)
1878     && (op->level > head->level))
1879 root 1.17 head->destroy ();
1880 root 1.8 else
1881     switch (head->type)
1882     {
1883     case SPELL_EFFECT:
1884 elmex 1.44 // XXX: Don't affect floor spelleffects. See also XXX comment
1885     // about sanctuary in spell_util.C
1886     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1887     continue;
1888    
1889 root 1.8 if (op->level > head->level)
1890 root 1.17 head->destroy ();
1891    
1892 root 1.5 break;
1893    
1894 root 1.8 /* I really don't get this rune code that much - that
1895     * random chance seems really low.
1896     */
1897     case RUNE:
1898     if (rndm (0, 149) == 0)
1899     {
1900     head->stats.hp--; /* weaken the rune */
1901     if (!head->stats.hp)
1902 root 1.17 head->destroy ();
1903 root 1.8 }
1904 root 1.5 break;
1905 root 1.8 }
1906 elmex 1.1 }
1907     }
1908    
1909    
1910    
1911     /* cast_consecrate() - a spell to make an altar your god's */
1912 root 1.8 int
1913     cast_consecrate (object *op, object *caster, object *spell)
1914     {
1915     char buf[MAX_BUF];
1916 elmex 1.1
1917 root 1.8 object *tmp, *god = find_god (determine_god (op));
1918 elmex 1.1
1919 root 1.8 if (!god)
1920     {
1921     new_draw_info (NDI_UNIQUE, 0, op, "You can't consecrate anything if you don't worship a god!");
1922     return 0;
1923 elmex 1.1 }
1924 root 1.8
1925     for (tmp = op->below; tmp; tmp = tmp->below)
1926     {
1927     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1928     break;
1929     if (tmp->type == HOLY_ALTAR)
1930     {
1931    
1932     if (tmp->level > caster_level (caster, spell))
1933     {
1934     new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name);
1935     return 0;
1936     }
1937     else
1938     {
1939     /* If we got here, we are consecrating an altar */
1940     sprintf (buf, "Altar of %s", &god->name);
1941     tmp->name = buf;
1942     tmp->level = caster_level (caster, spell);
1943     tmp->other_arch = god->arch;
1944     if (op->type == PLAYER)
1945     esrv_update_item (UPD_NAME, op, tmp);
1946     new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
1947     return 1;
1948 root 1.5 }
1949     }
1950 elmex 1.1 }
1951 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You are not standing over an altar!");
1952     return 0;
1953 elmex 1.1 }
1954    
1955     /* animate_weapon -
1956     * Generalization of staff_to_snake. Makes a golem out of the caster's weapon.
1957     * The golem is based on the archetype specified, modified by the caster's level
1958     * and the attributes of the weapon. The weapon is inserted in the golem's
1959     * inventory so that it falls to the ground when the golem dies.
1960     * This code was very odd - code early on would only let players use the spell,
1961     * yet the code wass full of player checks. I've presumed that the code
1962     * that only let players use it was correct, and removed all the other
1963     * player checks. MSW 2003-01-06
1964     */
1965 root 1.8 int
1966     animate_weapon (object *op, object *caster, object *spell, int dir)
1967     {
1968     object *weapon, *tmp;
1969     char buf[MAX_BUF];
1970     int a, i;
1971     sint16 x, y;
1972 root 1.13 maptile *m;
1973 root 1.8
1974     if (!spell->other_arch)
1975     {
1976     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
1977     LOG (llevError, "animate_weapon failed: spell %s missing other_arch!\n", &spell->name);
1978     return 0;
1979 elmex 1.1 }
1980 root 1.8 /* exit if it's not a player using this spell. */
1981     if (op->type != PLAYER)
1982     return 0;
1983 elmex 1.1
1984 root 1.8 /* if player already has a golem, abort */
1985 root 1.49 if (object *golem = op->contr->golem)
1986 root 1.8 {
1987 root 1.46 control_golem (golem, dir);
1988 root 1.8 return 0;
1989 elmex 1.1 }
1990    
1991 root 1.8 /* if no direction specified, pick one */
1992     if (!dir)
1993     dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9);
1994    
1995     m = op->map;
1996     x = op->x + freearr_x[dir];
1997     y = op->y + freearr_y[dir];
1998    
1999     /* if there's no place to put the golem, abort */
2000     if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) ||
2001 root 1.57 ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type))
2002 root 1.8 {
2003     new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
2004     return 0;
2005 elmex 1.1 }
2006    
2007 root 1.8 /* Use the weapon marked by the player. */
2008     weapon = find_marked_object (op);
2009 elmex 1.1
2010 root 1.8 if (!weapon)
2011     {
2012     new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!");
2013     return 0;
2014     }
2015 root 1.56 if (spell->race && strcmp (weapon->arch->archname, spell->race))
2016 root 1.8 {
2017     new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon.");
2018     return 0;
2019     }
2020     if (weapon->type != WEAPON)
2021     {
2022     new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it.");
2023     return 0;
2024 elmex 1.1 }
2025 root 1.8 if (QUERY_FLAG (weapon, FLAG_APPLIED))
2026     {
2027     new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon));
2028     return 0;
2029 elmex 1.1 }
2030 root 1.8
2031     if (weapon->nrof > 1)
2032     {
2033     tmp = get_split_ob (weapon, 1);
2034     esrv_send_item (op, weapon);
2035     weapon = tmp;
2036     }
2037    
2038     /* create the golem object */
2039     tmp = arch_to_object (spell->other_arch);
2040    
2041     /* if animated by a player, give the player control of the golem */
2042     CLEAR_FLAG (tmp, FLAG_MONSTER);
2043     tmp->stats.exp = 0;
2044     add_friendly_object (tmp);
2045     tmp->type = GOLEM;
2046 root 1.19 tmp->set_owner (op);
2047 root 1.49 op->contr->golem = tmp;
2048 root 1.46 set_spell_skill (op, caster, spell, tmp);
2049 root 1.8
2050     /* Give the weapon to the golem now. A bit of a hack to check the
2051     * removed flag - it should only be set if get_split_object was
2052     * used above.
2053     */
2054     if (!QUERY_FLAG (weapon, FLAG_REMOVED))
2055 root 1.16 weapon->remove ();
2056 root 1.46
2057 root 1.8 insert_ob_in_ob (weapon, tmp);
2058     esrv_send_item (op, weapon);
2059     /* To do everything necessary to let a golem use the weapon is a pain,
2060     * so instead, just set it as equipped (otherwise, we need to update
2061     * body_info, skills, etc)
2062     */
2063     SET_FLAG (tmp, FLAG_USE_WEAPON);
2064     SET_FLAG (weapon, FLAG_APPLIED);
2065 root 1.24 tmp->update_stats ();
2066 root 1.8
2067     /* There used to be 'odd' code that basically seemed to take the absolute
2068     * value of the weapon->magic an use that. IMO, that doesn't make sense -
2069     * if you're using a crappy weapon, it shouldn't be as good.
2070     */
2071    
2072     /* modify weapon's animated wc */
2073     tmp->stats.wc = tmp->stats.wc - SP_level_range_adjust (caster, spell) - 5 * weapon->stats.Dex - 2 * weapon->stats.Str - weapon->magic;
2074     if (tmp->stats.wc < -127)
2075     tmp->stats.wc = -127;
2076    
2077     /* Modify hit points for weapon */
2078     tmp->stats.maxhp = tmp->stats.maxhp + spell->duration +
2079     SP_level_duration_adjust (caster, spell) + +8 * weapon->magic + 12 * weapon->stats.Con;
2080     if (tmp->stats.maxhp < 0)
2081     tmp->stats.maxhp = 10;
2082     tmp->stats.hp = tmp->stats.maxhp;
2083    
2084     /* Modify weapon's damage */
2085     tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell) + weapon->stats.dam + weapon->magic + 5 * weapon->stats.Str;
2086     if (tmp->stats.dam < 0)
2087     tmp->stats.dam = 127;
2088    
2089    
2090     /* attacktype */
2091     if (!tmp->attacktype)
2092     tmp->attacktype = AT_PHYSICAL;
2093    
2094 root 1.63 if (materialtype_t *mt = name_to_material (op->materialname))
2095 root 1.8 {
2096     for (i = 0; i < NROFATTACKS; i++)
2097     tmp->resist[i] = 50 - (mt->save[i] * 5);
2098     a = mt->save[0];
2099 elmex 1.1 }
2100 root 1.8 else
2101     {
2102     for (i = 0; i < NROFATTACKS; i++)
2103     tmp->resist[i] = 5;
2104     a = 10;
2105     }
2106 root 1.63
2107 root 1.8 /* Set weapon's immunity */
2108     tmp->resist[ATNR_CONFUSION] = 100;
2109     tmp->resist[ATNR_POISON] = 100;
2110     tmp->resist[ATNR_SLOW] = 100;
2111     tmp->resist[ATNR_PARALYZE] = 100;
2112     tmp->resist[ATNR_TURN_UNDEAD] = 100;
2113     tmp->resist[ATNR_FEAR] = 100;
2114     tmp->resist[ATNR_DEPLETE] = 100;
2115     tmp->resist[ATNR_DEATH] = 100;
2116     tmp->resist[ATNR_BLIND] = 100;
2117    
2118     /* Improve weapon's armour value according to best save vs. physical of its material */
2119    
2120     if (a > 14)
2121     a = 14;
2122 root 1.63
2123 root 1.8 tmp->resist[ATNR_PHYSICAL] = 100 - (int) ((100.0 - (float) tmp->resist[ATNR_PHYSICAL]) / (30.0 - 2.0 * a));
2124    
2125     /* Determine golem's speed */
2126 root 1.26 tmp->set_speed (min (3.33, 0.4 + 0.1 * SP_level_range_adjust (caster, spell)));
2127 root 1.8
2128     if (!spell->race)
2129     {
2130     sprintf (buf, "animated %s", &weapon->name);
2131     tmp->name = buf;
2132    
2133     tmp->face = weapon->face;
2134     tmp->animation_id = weapon->animation_id;
2135     tmp->anim_speed = weapon->anim_speed;
2136     tmp->last_anim = weapon->last_anim;
2137     tmp->state = weapon->state;
2138 root 1.26 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE];
2139 elmex 1.1 }
2140    
2141 root 1.8 /* make experience increase in proportion to the strength of the summoned creature. */
2142     tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / caster_level (caster, spell));
2143    
2144     tmp->speed_left = -1;
2145     tmp->direction = dir;
2146 root 1.27
2147     m->insert (tmp, x, y, op);
2148 root 1.8 return 1;
2149 elmex 1.1 }
2150    
2151     /* cast_daylight() - changes the map darkness level *lower* */
2152    
2153     /* cast_change_map_lightlevel: Was cast_daylight/nightfall.
2154     * This changes the light level for the entire map.
2155     */
2156    
2157 root 1.8 int
2158     cast_change_map_lightlevel (object *op, object *caster, object *spell)
2159     {
2160     int success;
2161 elmex 1.1
2162 root 1.8 if (!op->map)
2163     return 0; /* shouldnt happen */
2164 elmex 1.1
2165 root 1.28 success = op->map->change_map_light (spell->stats.dam);
2166    
2167 root 1.8 if (!success)
2168     {
2169     if (spell->stats.dam < 0)
2170     new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here.");
2171     else
2172     new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here.");
2173 elmex 1.1 }
2174 root 1.8 return success;
2175 elmex 1.1 }
2176    
2177    
2178    
2179    
2180    
2181     /* create an aura spell object and put it in the player's inventory.
2182     * as usual, op is player, caster is the object casting the spell,
2183     * spell is the spell object itself.
2184     */
2185 root 1.8 int
2186     create_aura (object *op, object *caster, object *spell)
2187 elmex 1.1 {
2188 root 1.8 int refresh = 0;
2189     object *new_aura;
2190 elmex 1.1
2191 root 1.8 new_aura = present_arch_in_ob (spell->other_arch, op);
2192     if (new_aura)
2193     refresh = 1;
2194     else
2195     new_aura = arch_to_object (spell->other_arch);
2196    
2197     new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell);
2198    
2199     new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2200    
2201 root 1.19 new_aura->set_owner (op);
2202 root 1.8 set_spell_skill (op, caster, spell, new_aura);
2203     new_aura->attacktype = spell->attacktype;
2204    
2205     new_aura->level = caster_level (caster, spell);
2206     if (refresh)
2207     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2208     else
2209     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2210     insert_ob_in_ob (new_aura, op);
2211     return 1;
2212 elmex 1.1 }
2213    
2214    
2215     /* move aura function. An aura is a part of someone's inventory,
2216     * which he carries with him, but which acts on the map immediately
2217     * around him.
2218     * Aura parameters:
2219     * duration: duration counter.
2220     * attacktype: aura's attacktype
2221     * other_arch: archetype to drop where we attack
2222     */
2223    
2224 root 1.8 void
2225     move_aura (object *aura)
2226     {
2227     int i, mflags;
2228     object *env;
2229 root 1.13 maptile *m;
2230 root 1.8
2231     /* auras belong in inventories */
2232     env = aura->env;
2233    
2234     /* no matter what we've gotta remove the aura...
2235     * we'll put it back if its time isn't up.
2236     */
2237 root 1.16 aura->remove ();
2238 root 1.8
2239     /* exit if we're out of gas */
2240     if (aura->duration-- < 0)
2241     {
2242 root 1.17 aura->destroy ();
2243 root 1.8 return;
2244     }
2245    
2246     /* auras only exist in inventories */
2247     if (env == NULL || env->map == NULL)
2248     {
2249 root 1.17 aura->destroy ();
2250 root 1.8 return;
2251     }
2252 root 1.17
2253 root 1.8 /* we need to jump out of the inventory for a bit
2254     * in order to hit the map conveniently.
2255     */
2256 root 1.27 aura->insert_at (env, aura);
2257 root 1.8
2258     for (i = 1; i < 9; i++)
2259     {
2260     sint16 nx, ny;
2261    
2262     nx = aura->x + freearr_x[i];
2263     ny = aura->y + freearr_y[i];
2264     mflags = get_map_flags (env->map, &m, nx, ny, &nx, &ny);
2265    
2266     /* Consider the movement tyep of the person with the aura as
2267     * movement type of the aura. Eg, if the player is flying, the aura
2268     * is flying also, if player is walking, it is on the ground, etc.
2269     */
2270     if (!(mflags & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (env, GET_MAP_MOVE_BLOCK (m, nx, ny))))
2271 elmex 1.6 {
2272 root 1.8 hit_map (aura, i, aura->attacktype, 0);
2273 root 1.5
2274 root 1.8 if (aura->other_arch)
2275 root 1.27 m->insert (arch_to_object (aura->other_arch), nx, ny, aura);
2276 root 1.5 }
2277 elmex 1.1 }
2278 root 1.27
2279 root 1.8 /* put the aura back in the player's inventory */
2280 root 1.16 aura->remove ();
2281 root 1.8 insert_ob_in_ob (aura, env);
2282 elmex 1.1 }
2283    
2284     /* moves the peacemaker spell.
2285     * op is the piece object.
2286 root 1.8 */
2287 elmex 1.1
2288 root 1.8 void
2289     move_peacemaker (object *op)
2290     {
2291     object *tmp;
2292 elmex 1.1
2293 root 1.22 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2294 root 1.8 {
2295     int atk_lev, def_lev;
2296     object *victim = tmp;
2297 elmex 1.1
2298 root 1.8 if (tmp->head)
2299     victim = tmp->head;
2300     if (!QUERY_FLAG (victim, FLAG_MONSTER))
2301     continue;
2302     if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
2303     continue;
2304     if (victim->stats.exp == 0)
2305     continue;
2306 elmex 1.1
2307 root 1.8 def_lev = MAX (1, victim->level);
2308     atk_lev = MAX (1, op->level);
2309 elmex 1.1
2310 root 1.8 if (rndm (0, atk_lev - 1) > def_lev)
2311     {
2312     /* make this sucker peaceful. */
2313 elmex 1.1
2314 root 1.19 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2315 root 1.8 victim->stats.exp = 0;
2316 elmex 1.1 #if 0
2317 root 1.8 /* No idea why these were all set to zero - if something
2318     * makes this creature agressive, he should still do damage.
2319     */
2320     victim->stats.dam = 0;
2321     victim->stats.sp = 0;
2322     victim->stats.grace = 0;
2323     victim->stats.Pow = 0;
2324 elmex 1.1 #endif
2325 root 1.8 victim->attack_movement = RANDO2;
2326     SET_FLAG (victim, FLAG_UNAGGRESSIVE);
2327     SET_FLAG (victim, FLAG_RUN_AWAY);
2328     SET_FLAG (victim, FLAG_RANDOM_MOVE);
2329     CLEAR_FLAG (victim, FLAG_MONSTER);
2330     if (victim->name)
2331     {
2332     new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2333 root 1.5 }
2334     }
2335 elmex 1.1 }
2336 root 1.8 }
2337    
2338 elmex 1.1
2339     /* This writes a rune that contains the appropriate message.
2340     * There really isn't any adjustments we make.
2341     */
2342    
2343 root 1.8 int
2344     write_mark (object *op, object *spell, const char *msg)
2345     {
2346     char rune[HUGE_BUF];
2347     object *tmp;
2348 elmex 1.1
2349 root 1.8 if (!msg || msg[0] == 0)
2350     {
2351     new_draw_info (NDI_UNIQUE, 0, op, "Write what?");
2352     return 0;
2353 elmex 1.1 }
2354    
2355 root 1.8 if (strcasestr_local (msg, "endmsg"))
2356     {
2357     new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?");
2358     LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg);
2359     return 0;
2360 elmex 1.1 }
2361 root 1.8 if (!spell->other_arch)
2362     return 0;
2363     tmp = arch_to_object (spell->other_arch);
2364 root 1.9
2365     snprintf (rune, sizeof (rune), "%s\n", msg);
2366    
2367 root 1.8 tmp->race = op->name; /*Save the owner of the rune */
2368     tmp->msg = rune;
2369 root 1.27
2370     tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2371 root 1.8 return 1;
2372 elmex 1.1 }