ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.48
Committed: Tue Apr 24 16:33:38 2007 UTC (17 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.47: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

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