ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.51
Committed: Sat May 12 18:14:48 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.50: +13 -22 lines
Log Message:
- unrelated change, replace get_attr_value/set_attr_value by a nicer to use
  stat member function. should really replace the struct values by an array.

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 root 1.51
591     if (tmp)
592     for (i = 0; i < NUM_STATS; i++)
593     if (tmp->stats.stat (i) < 0)
594     new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is depleted by %d", statname[i], -tmp->stats.stat (i));
595 elmex 1.1 }
596    
597 root 1.8 if (is_dragon_pl (op))
598     {
599     /* now grab the 'dragon_ability'-force from the player's inventory */
600     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
601     {
602     if (tmp->type == FORCE && !strcmp (tmp->arch->name, "dragon_ability_force"))
603     {
604     if (tmp->stats.exp == 0)
605 root 1.36 sprintf (buf, "Your metabolism isn't focused on anything.");
606 root 1.8 else
607 root 1.36 sprintf (buf, "Your metabolism is focused on %s.", change_resist_msg[tmp->stats.exp]);
608    
609 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, buf);
610     break;
611 root 1.5 }
612     }
613 elmex 1.1 }
614 root 1.36
615 root 1.8 return 1;
616 elmex 1.1 }
617    
618     /* int cast_create_town_portal (object *op, object *caster, int dir)
619     *
620     * This function cast the spell of town portal for op
621     *
622     * The spell operates in two passes. During the first one a place
623     * is marked as a destination for the portal. During the second one,
624     * 2 portals are created, one in the position the player cast it and
625     * one in the destination place. The portal are synchronized and 2 forces
626     * are inserted in the player to destruct the portal next time player
627     * creates a new portal pair.
628     * This spell has a side effect that it allows people to meet each other
629     * in a permanent, private, appartements by making a town portal from it
630     * to the town or another public place. So, check if the map is unique and if
631     * so return an error
632     *
633     * Code by Tchize (david.delbecq@usa.net)
634     */
635 root 1.8 int
636     cast_create_town_portal (object *op, object *caster, object *spell, int dir)
637 elmex 1.1 {
638 root 1.31 object *dummy, *force, *old_force;
639 root 1.8 archetype *perm_portal;
640     char portal_name[1024], portal_message[1024];
641 root 1.13 maptile *exitmap;
642 root 1.8 int op_level;
643    
644     /* Check to see if the map the player is currently on is a per player unique
645     * map. This can be determined in that per player unique maps have the
646     * full pathname listed.
647     */
648     if (!strncmp (op->map->path, settings.localdir, strlen (settings.localdir)) && settings.create_home_portals != TRUE)
649 elmex 1.1 {
650 root 1.8 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "You can't cast that here.\n");
651     return 0;
652 elmex 1.1 }
653    
654 root 1.8 /* The first thing to do is to check if we have a marked destination
655     * dummy is used to make a check inventory for the force
656     */
657     dummy = arch_to_object (spell->other_arch);
658     if (dummy == NULL)
659     {
660     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
661 root 1.17 LOG (llevError, "object::create failed (force in cast_create_town_portal for %s!\n", &op->name);
662 root 1.8 return 0;
663 elmex 1.1 }
664 root 1.18
665 root 1.8 force = check_inv_recursive (op, dummy);
666 elmex 1.1
667 root 1.8 if (force == NULL)
668     {
669     /* Here we know there is no destination marked up.
670     * We have 2 things to do:
671     * 1. Mark the destination in the player inventory.
672     * 2. Let the player know it worked.
673     */
674     dummy->name = op->map->path;
675     EXIT_X (dummy) = op->x;
676     EXIT_Y (dummy) = op->y;
677     insert_ob_in_ob (dummy, op);
678 root 1.50 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "You fix this place in your mind. You feel you are able to come here from anywhere.");
679 root 1.8 return 1;
680     }
681 root 1.17
682     dummy->destroy ();
683 root 1.8
684     /* Here we know where the town portal should go to
685     * We should kill any existing portal associated with the player.
686     * Than we should create the 2 portals.
687     * For each of them, we need:
688     * - To create the portal with the name of the player+destination map
689     * - set the owner of the town portal
690     * - To mark the position of the portal in the player's inventory
691     * for easier destruction.
692     *
693     * The mark works has follow:
694     * slaying: Existing town portal
695     * hp, sp : x & y of the associated portal
696     * name : name of the portal
697     * race : map the portal is in
698     */
699    
700     /* First step: killing existing town portals */
701     dummy = get_archetype (spell->race);
702     if (dummy == NULL)
703     {
704     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
705 root 1.17 LOG (llevError, "object::create failed (force) in cast_create_town_portal for %s!\n", &op->name);
706 root 1.8 return 0;
707     }
708 root 1.18
709 root 1.10 perm_portal = archetype::find (spell->slaying);
710 root 1.8
711     /* To kill a town portal, we go trough the player's inventory,
712     * for each marked portal in player's inventory,
713     * -We try load the associated map (if impossible, consider the portal destructed)
714     * -We find any portal in the specified location.
715     * If it has the good name, we destruct it.
716     * -We destruct the force indicating that portal.
717     */
718     while ((old_force = check_inv_recursive (op, dummy)))
719     {
720 root 1.31 exitmap = maptile::find_sync (old_force->race, op->map);
721 elmex 1.1
722 root 1.8 if (exitmap)
723     {
724 root 1.31 exitmap->load_sync ();
725    
726 root 1.28 int exitx = EXIT_X (old_force);
727     int exity = EXIT_Y (old_force);
728    
729 root 1.31 for (object *tmp = present_arch (perm_portal, exitmap, exitx, exity); tmp; tmp = tmp->above)
730 root 1.8 {
731     if (tmp->name == old_force->name)
732     {
733 root 1.17 tmp->destroy ();
734 root 1.8 break;
735     }
736 root 1.5 }
737     }
738 root 1.17
739     old_force->destroy ();
740 root 1.8 }
741 root 1.17
742     dummy->destroy ();
743 root 1.8
744     /* Creating the portals.
745     * The very first thing to do is to ensure
746     * access to the destination map.
747     * If we can't, don't fizzle. Simply warn player.
748     * This ensure player pays his mana for the spell
749     * because HE is responsible of forgotting.
750     * 'force' is the destination of the town portal, which we got
751     * from the players inventory above.
752     */
753    
754     /* Ensure exit map is loaded */
755 root 1.31 exitmap = maptile::find_sync (force->name);
756 elmex 1.1
757 root 1.8 /* If we were unable to load (ex. random map deleted), warn player */
758 root 1.28 if (!exitmap)
759 root 1.8 {
760 root 1.50 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "Something strange happens. You can't remember where to go!?");
761 root 1.17 force->destroy ();
762 root 1.8 return 1;
763     }
764    
765 root 1.31 exitmap->load_sync ();
766    
767 root 1.8 op_level = caster_level (caster, spell);
768     if (op_level < 15)
769     snprintf (portal_message, 1024,
770 root 1.50 "The air moves around you and a huge smell of ammonia surounds you as you pass through %s's tiny portal. Pouah!\n",
771 root 1.8 &op->name);
772     else if (op_level < 30)
773     snprintf (portal_message, 1024,
774 root 1.50 "%s's portal smells of ozone. You do a lot of movements and finally pass through the small hole in the air\n", &op->name);
775 root 1.8 else if (op_level < 60)
776 root 1.50 snprintf (portal_message, 1024, "A shining door opens in the air in front of you, showing you the path to another place.\n");
777 root 1.8 else
778 root 1.50 snprintf (portal_message, 1024, "As you walk through %s's portal, flowers come out from the ground around you. You feel awed.\n",
779 root 1.8 &op->name);
780    
781     /* Create a portal in front of player
782     * dummy contain the portal and
783     * force contain the track to kill it later
784     */
785     snprintf (portal_name, 1024, "%s's portal to %s", &op->name, &force->name);
786     dummy = get_archetype (spell->slaying); /*The portal */
787     if (dummy == NULL)
788     {
789     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
790 root 1.17 LOG (llevError, "object::create failed (perm_magic_portal) in cast_create_town_portal for %s!\n", &op->name);
791 root 1.8 return 0;
792     }
793 root 1.18
794 root 1.8 EXIT_PATH (dummy) = force->name;
795     EXIT_X (dummy) = EXIT_X (force);
796     EXIT_Y (dummy) = EXIT_Y (force);
797     dummy->name = dummy->name_pl = portal_name;
798     dummy->msg = portal_message;
799     dummy->race = op->name; /*Save the owner of the portal */
800     cast_create_obj (op, caster, dummy, 0);
801    
802     /* Now we need to to create a town portal marker inside the player
803     * object, so on future castings, we can know that he has an active
804     * town portal.
805     */
806 root 1.31 object *tmp = get_archetype (spell->race);
807    
808     if (!tmp)
809 root 1.8 {
810     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
811 root 1.17 LOG (llevError, "object::create failed (force) in cast_create_town_portal for %s!\n", &op->name);
812 root 1.8 return 0;
813     }
814 root 1.18
815 root 1.8 tmp->race = op->map->path;
816     tmp->name = portal_name;
817     EXIT_X (tmp) = dummy->x;
818     EXIT_Y (tmp) = dummy->y;
819 root 1.27 op->insert (tmp);
820 root 1.8
821     /* Create a portal in the destination map
822     * dummy contain the portal and
823     * force the track to kill it later
824     * the 'force' variable still contains the 'reminder' of
825     * where this portal goes to.
826     */
827 root 1.28 snprintf (portal_name, 1024, "%s's portal to %s", &op->name, &op->map->path);
828 root 1.8 dummy = get_archetype (spell->slaying); /*The portal */
829     if (dummy == NULL)
830     {
831     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
832 root 1.17 LOG (llevError, "object::create failed (perm_magic_portal) in cast_create_town_portal for %s!\n", &op->name);
833 root 1.8 return 0;
834     }
835 root 1.18
836 root 1.8 EXIT_PATH (dummy) = op->map->path;
837     EXIT_X (dummy) = op->x;
838     EXIT_Y (dummy) = op->y;
839     dummy->name = dummy->name_pl = portal_name;
840     dummy->msg = portal_message;
841     dummy->race = op->name; /*Save the owner of the portal */
842 root 1.27 exitmap->insert (dummy, EXIT_X (force), EXIT_Y (force), op);
843 root 1.8
844     /* Now we create another town portal marker that
845     * points back to the one we just made
846     */
847     tmp = get_archetype (spell->race);
848     if (tmp == NULL)
849     {
850     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
851 root 1.17 LOG (llevError, "object::create failed (force) in cast_create_town_portal for %s!\n", &op->name);
852 root 1.8 return 0;
853     }
854 root 1.18
855 root 1.8 tmp->race = force->name;
856     tmp->name = portal_name;
857     EXIT_X (tmp) = dummy->x;
858     EXIT_Y (tmp) = dummy->y;
859     insert_ob_in_ob (tmp, op);
860    
861     /* Describe the player what happened
862     */
863     new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "You see air moving and showing you the way home.");
864 root 1.17 force->destroy ();
865    
866 root 1.8 return 1;
867 elmex 1.1 }
868    
869     /* This creates magic walls. Really, it can create most any object,
870     * within some reason.
871     */
872 root 1.8 int
873     magic_wall (object *op, object *caster, int dir, object *spell_ob)
874     {
875 root 1.27 object *tmp;
876 root 1.8 int i, posblocked, negblocked, maxrange;
877     sint16 x, y;
878 root 1.13 maptile *m;
879 root 1.8 const char *name;
880     archetype *at;
881    
882     if (!dir)
883     {
884     dir = op->facing;
885     x = op->x;
886     y = op->y;
887     }
888     else
889     {
890     x = op->x + freearr_x[dir];
891     y = op->y + freearr_y[dir];
892     }
893 root 1.25
894 root 1.8 m = op->map;
895    
896     if ((spell_ob->move_block || x != op->x || y != op->y) &&
897     (get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE) ||
898     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) == spell_ob->move_block)))
899     {
900     new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
901     return 0;
902     }
903 root 1.25
904 root 1.8 if (spell_ob->other_arch)
905 root 1.25 tmp = arch_to_object (spell_ob->other_arch);
906 root 1.8 else if (spell_ob->race)
907     {
908     char buf1[MAX_BUF];
909    
910     sprintf (buf1, spell_ob->race, dir);
911 root 1.10 at = archetype::find (buf1);
912 root 1.8 if (!at)
913     {
914     LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1);
915     new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken.");
916     return 0;
917 root 1.5 }
918 root 1.27
919 root 1.8 tmp = arch_to_object (at);
920     }
921     else
922     {
923     LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name);
924     return 0;
925     }
926    
927     if (tmp->type == SPELL_EFFECT)
928     {
929     tmp->attacktype = spell_ob->attacktype;
930     tmp->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
931     tmp->stats.dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
932     tmp->range = 0;
933     }
934     else if (QUERY_FLAG (tmp, FLAG_ALIVE))
935     {
936     tmp->stats.hp = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
937     tmp->stats.maxhp = tmp->stats.hp;
938     }
939 root 1.25
940 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG (tmp, FLAG_IS_USED_UP))
941     {
942     tmp->stats.food = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
943     SET_FLAG (tmp, FLAG_IS_USED_UP);
944 elmex 1.1 }
945 root 1.25
946 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_TEAR_DOWN))
947     {
948     tmp->stats.hp = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
949     tmp->stats.maxhp = tmp->stats.hp;
950     SET_FLAG (tmp, FLAG_TEAR_DOWN);
951     SET_FLAG (tmp, FLAG_ALIVE);
952     }
953    
954     /* This can't really hurt - if the object doesn't kill anything,
955 root 1.25 * these fields just won't be used. Do not set the owner for
956     * earthwalls, though, so they survive restarts.
957 root 1.8 */
958 root 1.25 if (tmp->type != EARTHWALL) //TODO
959     tmp->set_owner (op);
960    
961 root 1.8 set_spell_skill (op, caster, spell_ob, tmp);
962     tmp->level = caster_level (caster, spell_ob) / 2;
963 elmex 1.1
964 root 1.8 name = tmp->name;
965 root 1.27 if (!(tmp = m->insert (tmp, x, y, op)))
966 root 1.8 {
967     new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name);
968     return 0;
969 elmex 1.1 }
970 root 1.25
971 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
972     if (tmp->other_arch && tmp->other_arch->clone.type == SPELL)
973     insert_ob_in_ob (arch_to_object (tmp->other_arch), tmp);
974    
975     /* This code causes the wall to extend some distance in
976     * each direction, or until an obstruction is encountered.
977     * posblocked and negblocked help determine how far the
978     * created wall can extend, it won't go extend through
979     * blocked spaces.
980     */
981     maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
982     posblocked = 0;
983     negblocked = 0;
984    
985     for (i = 1; i <= maxrange; i++)
986     {
987     int dir2;
988    
989     dir2 = (dir < 4) ? (dir + 2) : dir - 2;
990    
991     x = tmp->x + i * freearr_x[dir2];
992     y = tmp->y + i * freearr_y[dir2];
993     m = tmp->map;
994    
995     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
996     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !posblocked)
997     {
998 root 1.27 object *tmp2 = tmp->clone ();
999     m->insert (tmp2, x, y, op);
1000    
1001 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
1002     if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1003 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
1004 root 1.8
1005     }
1006     else
1007     posblocked = 1;
1008    
1009     x = tmp->x - i * freearr_x[dir2];
1010     y = tmp->y - i * freearr_y[dir2];
1011     m = tmp->map;
1012    
1013     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
1014     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !negblocked)
1015     {
1016 root 1.27 object *tmp2 = tmp->clone ();
1017     m->insert (tmp2, x, y, op);
1018    
1019 root 1.8 if (tmp2->other_arch && tmp2->other_arch->clone.type == SPELL)
1020 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
1021 root 1.8 }
1022     else
1023     negblocked = 1;
1024 elmex 1.1 }
1025    
1026 root 1.8 if (QUERY_FLAG (tmp, FLAG_BLOCKSVIEW))
1027     update_all_los (op->map, op->x, op->y);
1028 elmex 1.1
1029 root 1.8 return 1;
1030 elmex 1.1 }
1031    
1032 root 1.8 int
1033     dimension_door (object *op, object *caster, object *spob, int dir)
1034     {
1035     uint32 dist, maxdist;
1036     int mflags;
1037 root 1.13 maptile *m;
1038 root 1.8 sint16 sx, sy;
1039 elmex 1.1
1040 root 1.8 if (op->type != PLAYER)
1041     return 0;
1042 elmex 1.1
1043 root 1.8 if (!dir)
1044     {
1045     new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
1046     return 0;
1047 elmex 1.1 }
1048    
1049 root 1.8 /* Given the new outdoor maps, can't let players dimension door for
1050     * ever, so put limits in.
1051     */
1052     maxdist = spob->range + SP_level_range_adjust (caster, spob);
1053    
1054     if (op->contr->count)
1055     {
1056     if (op->contr->count > maxdist)
1057     {
1058     new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!");
1059     return 0;
1060 root 1.5 }
1061    
1062 root 1.8 for (dist = 0; dist < op->contr->count; dist++)
1063     {
1064     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
1065 root 1.5
1066 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
1067     break;
1068 root 1.5
1069 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
1070     break;
1071 root 1.5 }
1072    
1073 root 1.8 if (dist < op->contr->count)
1074     {
1075     new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n");
1076     op->contr->count = 0;
1077     return 0;
1078     }
1079 root 1.27
1080 root 1.8 op->contr->count = 0;
1081    
1082     /* Remove code that puts player on random space on maps. IMO,
1083     * a lot of maps probably have areas the player should not get to,
1084     * but may not be marked as NO_MAGIC (as they may be bounded
1085     * by such squares). Also, there are probably treasure rooms and
1086     * lots of other maps that protect areas with no magic, but the
1087     * areas themselves don't contain no magic spaces.
1088     */
1089     /* This call here is really just to normalize the coordinates */
1090     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, &sx, &sy);
1091     if (mflags & P_IS_ALIVE || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
1092     {
1093     new_draw_info (NDI_UNIQUE, 0, op, "You cast your spell, but nothing happens.\n");
1094     return 1; /* Maybe the penalty should be more severe... */
1095 root 1.5 }
1096 root 1.8 }
1097     else
1098     {
1099     /* Player didn't specify a distance, so lets see how far
1100     * we can move the player. Don't know why this stopped on
1101     * spaces that blocked the players view.
1102     */
1103 root 1.5
1104 root 1.8 for (dist = 0; dist < maxdist; dist++)
1105     {
1106     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
1107 root 1.5
1108 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
1109     break;
1110 root 1.5
1111 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
1112     break;
1113 root 1.5
1114     }
1115    
1116 root 1.8 /* If the destination is blocked, keep backing up until we
1117     * find a place for the player.
1118     */
1119     for (; dist > 0; dist--)
1120     {
1121     if (get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist,
1122     &sx, &sy) & (P_OUT_OF_MAP | P_IS_ALIVE))
1123     continue;
1124 root 1.5
1125    
1126 root 1.8 if (!OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
1127     break;
1128 root 1.5
1129     }
1130 root 1.8 if (!dist)
1131     {
1132     new_draw_info (NDI_UNIQUE, 0, op, "Your spell failed!\n");
1133     return 0;
1134 root 1.5 }
1135 elmex 1.1 }
1136    
1137 root 1.8 /* Actually move the player now */
1138 root 1.27 if (!(op = op->map->insert (op, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, op)))
1139 root 1.8 return 1;
1140 elmex 1.1
1141 root 1.8 op->speed_left = -FABS (op->speed) * 5; /* Freeze them for a short while */
1142     return 1;
1143 elmex 1.1 }
1144    
1145    
1146     /* cast_heal: Heals something.
1147     * op is the caster.
1148     * dir is the direction he is casting it in.
1149     * spell is the spell object.
1150     */
1151 root 1.8 int
1152     cast_heal (object *op, object *caster, object *spell, int dir)
1153     {
1154     object *tmp;
1155     archetype *at;
1156     object *poison;
1157     int heal = 0, success = 0;
1158    
1159     tmp = find_target_for_friendly_spell (op, dir);
1160    
1161 root 1.40 if (!tmp)
1162 root 1.8 return 0;
1163    
1164     /* Figure out how many hp this spell might cure.
1165     * could be zero if this spell heals effects, not damage.
1166     */
1167     heal = spell->stats.dam;
1168     if (spell->stats.hp)
1169     heal += random_roll (spell->stats.hp, 6, op, PREFER_HIGH) + spell->stats.hp;
1170    
1171     if (heal)
1172     {
1173     if (tmp->stats.hp >= tmp->stats.maxhp)
1174 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You are already fully healed.");
1175 root 1.8 else
1176     {
1177     /* See how many points we actually heal. Instead of messages
1178     * based on type of spell, we instead do messages based
1179     * on amount of damage healed.
1180     */
1181     if (heal > (tmp->stats.maxhp - tmp->stats.hp))
1182     heal = tmp->stats.maxhp - tmp->stats.hp;
1183     tmp->stats.hp += heal;
1184    
1185     if (tmp->stats.hp >= tmp->stats.maxhp)
1186 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel just fine!");
1187 root 1.8 else if (heal > 50)
1188 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds close!");
1189 root 1.8 else if (heal > 25)
1190 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds mostly close.");
1191 root 1.8 else if (heal > 10)
1192 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to fade.");
1193 root 1.8 else
1194 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to close.");
1195    
1196 root 1.8 success = 1;
1197     }
1198     }
1199 root 1.40
1200 root 1.8 if (spell->attacktype & AT_DISEASE)
1201     if (cure_disease (tmp, op))
1202     success = 1;
1203    
1204     if (spell->attacktype & AT_POISON)
1205     {
1206 root 1.10 at = archetype::find ("poisoning");
1207 root 1.8 poison = present_arch_in_ob (at, tmp);
1208     if (poison)
1209     {
1210     success = 1;
1211     new_draw_info (NDI_UNIQUE, 0, tmp, "Your body feels cleansed");
1212     poison->stats.food = 1;
1213 root 1.5 }
1214 elmex 1.1 }
1215 root 1.40
1216 root 1.8 if (spell->attacktype & AT_CONFUSION)
1217     {
1218     poison = present_in_ob_by_name (FORCE, "confusion", tmp);
1219     if (poison)
1220     {
1221     success = 1;
1222     new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
1223     poison->duration = 1;
1224 root 1.5 }
1225 elmex 1.1 }
1226 root 1.40
1227 root 1.8 if (spell->attacktype & AT_BLIND)
1228     {
1229 root 1.10 at = archetype::find ("blindness");
1230 root 1.8 poison = present_arch_in_ob (at, tmp);
1231     if (poison)
1232     {
1233     success = 1;
1234     new_draw_info (NDI_UNIQUE, 0, tmp, "Your vision begins to return.");
1235     poison->stats.food = 1;
1236 root 1.5 }
1237 elmex 1.1 }
1238 root 1.40
1239 root 1.8 if (spell->last_sp && tmp->stats.sp < tmp->stats.maxsp)
1240     {
1241     tmp->stats.sp += spell->last_sp;
1242     if (tmp->stats.sp > tmp->stats.maxsp)
1243     tmp->stats.sp = tmp->stats.maxsp;
1244     success = 1;
1245     new_draw_info (NDI_UNIQUE, 0, tmp, "Magical energy surges through your body!");
1246     }
1247 root 1.40
1248 root 1.8 if (spell->last_grace && tmp->stats.grace < tmp->stats.maxgrace)
1249     {
1250     tmp->stats.grace += spell->last_grace;
1251     if (tmp->stats.grace > tmp->stats.maxgrace)
1252     tmp->stats.grace = tmp->stats.maxgrace;
1253     success = 1;
1254     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!");
1255 elmex 1.1 }
1256 root 1.40
1257 root 1.8 if (spell->stats.food && tmp->stats.food < 999)
1258     {
1259     tmp->stats.food += spell->stats.food;
1260     if (tmp->stats.food > 999)
1261     tmp->stats.food = 999;
1262     success = 1;
1263     /* We could do something a bit better like the messages for healing above */
1264     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food");
1265     }
1266 root 1.40
1267 root 1.8 return success;
1268 elmex 1.1 }
1269    
1270    
1271     /* This is used for the spells that gain stats. There are no spells
1272     * right now that icnrease wis/int/pow on a temp basis, so no
1273     * good comments for those.
1274     */
1275 root 1.8 static const char *const no_gain_msgs[NUM_STATS] = {
1276     "You grow no stronger.",
1277     "You grow no more agile.",
1278     "You don't feel any healthier.",
1279     "no wis",
1280     "You are no easier to look at.",
1281     "no int",
1282     "no pow"
1283 elmex 1.1 };
1284    
1285 root 1.8 int
1286     cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1287     {
1288     object *force = NULL;
1289     int i;
1290    
1291     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1292 root 1.27 object *tmp = dir
1293     ? find_target_for_friendly_spell (op, dir)
1294     : op;
1295 root 1.8
1296 root 1.27 if (!tmp)
1297 root 1.8 return 0;
1298    
1299     /* If we've already got a force of this type, don't add a new one. */
1300 root 1.27 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1301 root 1.8 {
1302     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1303     {
1304     if (tmp2->name == spell_ob->name)
1305     {
1306     force = tmp2; /* the old effect will be "refreshed" */
1307     break;
1308 root 1.5 }
1309 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1310     {
1311     if (!silent)
1312     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1313     return 0;
1314 root 1.5 }
1315     }
1316 elmex 1.1 }
1317 root 1.8 if (force == NULL)
1318     {
1319     force = get_archetype (FORCE_NAME);
1320     force->subtype = FORCE_CHANGE_ABILITY;
1321     if (spell_ob->race)
1322     force->name = spell_ob->race;
1323     else
1324     force->name = spell_ob->name;
1325     force->name_pl = spell_ob->name;
1326     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1327    
1328     }
1329     else
1330     {
1331     int duration;
1332    
1333     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1334     if (duration > force->duration)
1335     {
1336     force->duration = duration;
1337     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1338     }
1339     else
1340     {
1341     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1342     }
1343     return 1;
1344     }
1345     force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1346     force->speed = 1.0;
1347     force->speed_left = -1.0;
1348     SET_FLAG (force, FLAG_APPLIED);
1349    
1350     /* Now start processing the effects. First, protections */
1351     for (i = 0; i < NROFATTACKS; i++)
1352     {
1353     if (spell_ob->resist[i])
1354     {
1355     force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob);
1356     if (force->resist[i] > 100)
1357     force->resist[i] = 100;
1358 root 1.5 }
1359 elmex 1.1 }
1360 root 1.8 if (spell_ob->stats.hp)
1361     force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1362    
1363     if (tmp->type == PLAYER)
1364     {
1365     /* Stat adjustment spells */
1366     for (i = 0; i < NUM_STATS; i++)
1367     {
1368 root 1.51 if (sint8 stat = spell_ob->stats.stat (i))
1369 root 1.8 {
1370 root 1.51 sint8 sm = 0;
1371     for (sint8 k = 0; k < stat; k++)
1372 root 1.8 sm += rndm (1, 3);
1373    
1374 root 1.51 if (tmp->stats.stat (i) + sm > 15 + 5 * stat)
1375     sm = max (0, (15 + 5 * stat) - tmp->stats.stat (i));
1376    
1377     force->stats.stat (i) = sm;
1378    
1379 root 1.8 if (!sm)
1380     new_draw_info (NDI_UNIQUE, 0, op, no_gain_msgs[i]);
1381 root 1.5 }
1382     }
1383 elmex 1.1 }
1384    
1385 root 1.8 force->move_type = spell_ob->move_type;
1386 elmex 1.1
1387 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK))
1388     SET_FLAG (force, FLAG_SEE_IN_DARK);
1389 elmex 1.1
1390 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_XRAYS))
1391     SET_FLAG (force, FLAG_XRAYS);
1392 elmex 1.1
1393 root 1.8 /* Haste/bonus speed */
1394     if (spell_ob->stats.exp)
1395     {
1396     if (op->speed > 0.5f)
1397     force->stats.exp = (sint64) ((float) spell_ob->stats.exp / (op->speed + 0.5f));
1398     else
1399     force->stats.exp = spell_ob->stats.exp;
1400 elmex 1.1 }
1401    
1402 root 1.8 force->stats.wc = spell_ob->stats.wc;
1403     force->stats.ac = spell_ob->stats.ac;
1404     force->attacktype = spell_ob->attacktype;
1405    
1406     insert_ob_in_ob (force, tmp);
1407     change_abil (tmp, force); /* Mostly to display any messages */
1408 root 1.24 tmp->update_stats ();
1409 root 1.8 return 1;
1410 elmex 1.1 }
1411    
1412     /* This used to be part of cast_change_ability, but it really didn't make
1413     * a lot of sense, since most of the values it derives are from the god
1414     * of the caster.
1415     */
1416    
1417 root 1.8 int
1418     cast_bless (object *op, object *caster, object *spell_ob, int dir)
1419     {
1420     int i;
1421     object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp;
1422    
1423     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1424     if (dir != 0)
1425     {
1426     tmp = find_target_for_friendly_spell (op, dir);
1427     }
1428     else
1429     {
1430     tmp = op;
1431     }
1432    
1433     /* If we've already got a force of this type, don't add a new one. */
1434     for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1435     {
1436     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1437     {
1438     if (tmp2->name == spell_ob->name)
1439     {
1440     force = tmp2; /* the old effect will be "refreshed" */
1441     break;
1442 root 1.5 }
1443 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1444     {
1445     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1446     return 0;
1447 root 1.5 }
1448     }
1449 elmex 1.1 }
1450 root 1.8 if (force == NULL)
1451     {
1452     force = get_archetype (FORCE_NAME);
1453     force->subtype = FORCE_CHANGE_ABILITY;
1454     if (spell_ob->race)
1455     force->name = spell_ob->race;
1456     else
1457     force->name = spell_ob->name;
1458     force->name_pl = spell_ob->name;
1459     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1460     }
1461     else
1462     {
1463     int duration;
1464    
1465     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1466     if (duration > force->duration)
1467     {
1468     force->duration = duration;
1469     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1470 root 1.5 }
1471 root 1.8 else
1472     {
1473     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1474     }
1475     return 0;
1476 elmex 1.1 }
1477 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1478     force->speed = 1.0;
1479     force->speed_left = -1.0;
1480     SET_FLAG (force, FLAG_APPLIED);
1481 elmex 1.1
1482 root 1.8 if (!god)
1483     {
1484     new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1485     }
1486     else
1487     {
1488     /* Only give out good benefits, and put a max on it */
1489     for (i = 0; i < NROFATTACKS; i++)
1490     {
1491     if (god->resist[i] > 0)
1492     {
1493     force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1494 root 1.5 }
1495     }
1496 root 1.8 force->path_attuned |= god->path_attuned;
1497 root 1.7
1498 root 1.8 if (spell_ob->attacktype)
1499     force->slaying = god->slaying;
1500 root 1.7
1501 root 1.8 if (tmp != op)
1502     {
1503     new_draw_info_format (NDI_UNIQUE, 0, op, "You bless %s.", &tmp->name);
1504     new_draw_info_format (NDI_UNIQUE, 0, tmp, "%s blessed you.", &op->name);
1505     }
1506     else
1507     {
1508     new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are blessed by %s!", &god->name);
1509 root 1.5 }
1510 elmex 1.1
1511     }
1512 root 1.8 force->stats.wc = spell_ob->stats.wc;
1513     force->stats.ac = spell_ob->stats.ac;
1514 elmex 1.1
1515 root 1.8 change_abil (tmp, force); /* Mostly to display any messages */
1516     insert_ob_in_ob (force, tmp);
1517 root 1.24 tmp->update_stats ();
1518 root 1.8 return 1;
1519 elmex 1.1 }
1520    
1521     /* Alchemy code by Mark Wedel
1522     *
1523     * This code adds a new spell, called alchemy. Alchemy will turn
1524     * objects to gold nuggets, the value of the gold nuggets being
1525     * about 90% of that of the item itself. It uses the value of the
1526     * object before charisma adjustments, because the nuggets themselves
1527     * will be will be adjusted by charisma when sold.
1528     *
1529     * Large nuggets are worth 25 gp each (base). You will always get
1530     * the maximum number of large nuggets you could get.
1531     * Small nuggets are worth 1 gp each (base). You will get from 0
1532     * to the max amount of small nuggets as you could get.
1533     *
1534     * For example, if an item is worth 110 gold, you will get
1535     * 4 large nuggets, and from 0-10 small nuggets.
1536     *
1537     * There is also a chance (1:30) that you will get nothing at all
1538     * for the object. There is also a maximum weight that will be
1539 root 1.37 * alchemised.
1540 elmex 1.1 */
1541 root 1.8 static void
1542 root 1.38 alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1543 root 1.8 {
1544     uint64 value = query_cost (obj, NULL, F_TRUE);
1545    
1546     /* Give third price when we alchemy money (This should hopefully
1547     * make it so that it isn't worth it to alchemy money, sell
1548     * the nuggets, alchemy the gold from that, etc.
1549     * Otherwise, give 9 silver on the gold for other objects,
1550     * so that it would still be more affordable to haul
1551     * the stuff back to town.
1552     */
1553     if (QUERY_FLAG (obj, FLAG_UNPAID))
1554     value = 0;
1555     else if (obj->type == MONEY || obj->type == GEM)
1556     value /= 3;
1557     else
1558 root 1.39 value = value * 9 / 10;
1559 root 1.8
1560 root 1.37 if (obj->value > 0 && rndm (0, 29))
1561 root 1.38 total_value += value;
1562 root 1.8
1563 root 1.38 total_weight += obj->total_weight ();
1564 root 1.8
1565 root 1.17 obj->destroy ();
1566 root 1.8 }
1567    
1568     static void
1569 root 1.38 update_map (object *op, maptile *m, int small_nuggets, object *small, int large_nuggets, object *large, int x, int y)
1570 root 1.8 {
1571     int flag = 0;
1572    
1573     /* Put any nuggets below the player, but we can only pass this
1574     * flag if we are on the same space as the player
1575     */
1576     if (x == op->x && y == op->y && op->map == m)
1577     flag = INS_BELOW_ORIGINATOR;
1578    
1579     if (small_nuggets)
1580     {
1581 root 1.38 object *tmp = small->clone ();
1582 root 1.8 tmp->nrof = small_nuggets;
1583 root 1.27 m->insert (tmp, x, y, op, flag);
1584 root 1.8 }
1585 root 1.18
1586 root 1.8 if (large_nuggets)
1587     {
1588 root 1.38 object *tmp = large->clone ();
1589 root 1.8 tmp->nrof = large_nuggets;
1590 root 1.27 m->insert (tmp, x, y, op, flag);
1591 root 1.8 }
1592 root 1.38
1593     if (object *pl = m->at (x, y).player ())
1594     if (pl->contr->ns)
1595     pl->contr->ns->look_position = 0;
1596 root 1.8 }
1597    
1598     int
1599     alchemy (object *op, object *caster, object *spell_ob)
1600 elmex 1.1 {
1601 root 1.8 if (op->type != PLAYER)
1602     return 0;
1603    
1604 root 1.39 object *large = get_archetype ("largenugget");
1605     object *small = get_archetype ("smallnugget");
1606    
1607 root 1.38 /* Put a maximum weight of items that can be alchemised. Limits the power
1608     * some, and also prevents people from alchemising every table/chair/clock
1609 root 1.8 * in sight
1610     */
1611 root 1.38 int duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1612     int weight_max = duration * 1000;
1613     uint64 value_max = duration * 1000;
1614 elmex 1.1
1615 root 1.39 int weight = 0;
1616 root 1.38
1617     for (int y = op->y - 1; y <= op->y + 1; y++)
1618 root 1.8 {
1619 root 1.38 for (int x = op->x - 1; x <= op->x + 1; x++)
1620 root 1.8 {
1621 root 1.38 uint64 value = 0;
1622    
1623     sint16 nx = x;
1624     sint16 ny = y;
1625 elmex 1.1
1626 root 1.39 maptile *mp = op->map;
1627 root 1.5
1628 root 1.39 int mflags = get_map_flags (mp, &mp, nx, ny, &nx, &ny);
1629 root 1.5
1630 root 1.8 if (mflags & (P_OUT_OF_MAP | P_NO_MAGIC))
1631     continue;
1632    
1633     /* Treat alchemy a little differently - most spell effects
1634     * use fly as the movement type - for alchemy, consider it
1635     * ground level effect.
1636     */
1637     if (GET_MAP_MOVE_BLOCK (mp, nx, ny) & MOVE_WALK)
1638     continue;
1639    
1640 root 1.38 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1641 root 1.8 {
1642     next = tmp->above;
1643 root 1.37
1644 root 1.8 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) &&
1645     !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
1646     {
1647     if (tmp->inv)
1648     {
1649     object *next1, *tmp1;
1650    
1651 root 1.37 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1652 root 1.8 {
1653     next1 = tmp1->below;
1654     if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) &&
1655     !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON))
1656 root 1.38 alchemy_object (tmp1, value, weight);
1657 root 1.5 }
1658     }
1659 root 1.37
1660 root 1.38 alchemy_object (tmp, value, weight);
1661 root 1.8
1662     if (weight > weight_max)
1663 root 1.38 break;
1664     }
1665     }
1666    
1667     value = min (value, value_max);
1668    
1669     uint64 count = value / large->value;
1670     int large_nuggets = count;
1671     value -= count * large->value;
1672    
1673     count = value / small->value;
1674     int small_nuggets = count;
1675 root 1.5
1676 root 1.8 /* Insert all the nuggets at one time. This probably saves time, but
1677     * it also prevents us from alcheming nuggets that were just created
1678     * with this spell.
1679     */
1680 root 1.38 update_map (op, mp, small_nuggets, small, large_nuggets, large, nx, ny);
1681    
1682     if (weight > weight_max)
1683     goto bailout;
1684 root 1.8 }
1685     }
1686 root 1.17
1687 root 1.38 bailout:
1688 root 1.17 large->destroy ();
1689     small->destroy ();
1690 root 1.8 return 1;
1691 elmex 1.1 }
1692    
1693    
1694     /* This function removes the cursed/damned status on equipped
1695     * items.
1696     */
1697 root 1.8 int
1698     remove_curse (object *op, object *caster, object *spell)
1699     {
1700     object *tmp;
1701     int success = 0, was_one = 0;
1702    
1703     for (tmp = op->inv; tmp; tmp = tmp->below)
1704     if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1705     ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1706     (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1707     {
1708     was_one++;
1709     if (tmp->level <= caster_level (caster, spell))
1710     {
1711     success++;
1712     if (QUERY_FLAG (spell, FLAG_DAMNED))
1713     CLEAR_FLAG (tmp, FLAG_DAMNED);
1714    
1715     CLEAR_FLAG (tmp, FLAG_CURSED);
1716     CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1717     tmp->value = 0; /* Still can't sell it */
1718     if (op->type == PLAYER)
1719     esrv_send_item (op, tmp);
1720     }
1721     }
1722    
1723     if (op->type == PLAYER)
1724     {
1725     if (success)
1726 root 1.38 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now.");
1727 root 1.8 else
1728     {
1729     if (was_one)
1730     new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse.");
1731     else
1732     new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items.");
1733 root 1.5 }
1734 elmex 1.1 }
1735 root 1.21
1736 root 1.8 return success;
1737 elmex 1.1 }
1738    
1739     /* Identifies objects in the players inventory/on the ground */
1740    
1741 root 1.8 int
1742     cast_identify (object *op, object *caster, object *spell)
1743     {
1744     object *tmp;
1745     int success = 0, num_ident;
1746    
1747     num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1748    
1749     if (num_ident < 1)
1750     num_ident = 1;
1751    
1752     for (tmp = op->inv; tmp; tmp = tmp->below)
1753     {
1754     if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1755     {
1756     identify (tmp);
1757 root 1.21
1758 root 1.8 if (op->type == PLAYER)
1759     {
1760 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "You identified: %s.", long_desc (tmp, op));
1761 root 1.21
1762 root 1.8 if (tmp->msg)
1763     {
1764     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1765     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1766 root 1.5 }
1767     }
1768 root 1.21
1769 root 1.8 num_ident--;
1770     success = 1;
1771     if (!num_ident)
1772     break;
1773 root 1.5 }
1774 elmex 1.1 }
1775 root 1.21
1776 root 1.8 /* If all the power of the spell has been used up, don't go and identify
1777     * stuff on the floor. Only identify stuff on the floor if the spell
1778     * was not fully used.
1779     */
1780     if (num_ident)
1781     {
1782 root 1.48 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1783 root 1.8 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1784     {
1785 root 1.21 identify (tmp);
1786 root 1.8
1787     if (op->type == PLAYER)
1788     {
1789 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "On the ground you identified: %s.", long_desc (tmp, op));
1790 root 1.21
1791 root 1.8 if (tmp->msg)
1792     {
1793     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1794     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1795     }
1796 root 1.21
1797 root 1.8 esrv_send_item (op, tmp);
1798     }
1799 root 1.21
1800 root 1.5 num_ident--;
1801 root 1.8 success = 1;
1802     if (!num_ident)
1803     break;
1804     }
1805     }
1806 root 1.21
1807 root 1.8 if (!success)
1808     new_draw_info (NDI_UNIQUE, 0, op, "You can't reach anything unidentified.");
1809     else
1810 root 1.21 spell_effect (spell, op->x, op->y, op->map, op);
1811    
1812 root 1.8 return success;
1813 elmex 1.1 }
1814    
1815 root 1.8 int
1816     cast_detection (object *op, object *caster, object *spell, object *skill)
1817     {
1818     object *tmp, *last, *god, *detect;
1819     int done_one, range, mflags, floor, level;
1820     sint16 x, y, nx, ny;
1821 root 1.13 maptile *m;
1822 root 1.8
1823     /* We precompute some values here so that we don't have to keep
1824     * doing it over and over again.
1825     */
1826     god = find_god (determine_god (op));
1827     level = caster_level (caster, spell);
1828     range = spell->range + SP_level_range_adjust (caster, spell);
1829    
1830     if (!skill)
1831     skill = caster;
1832    
1833     for (x = op->x - range; x <= op->x + range; x++)
1834     for (y = op->y - range; y <= op->y + range; y++)
1835     {
1836     m = op->map;
1837     mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1838     if (mflags & P_OUT_OF_MAP)
1839     continue;
1840    
1841     /* For most of the detections, we only detect objects above the
1842     * floor. But this is not true for show invisible.
1843     * Basically, we just go and find the top object and work
1844     * down - that is easier than working up.
1845     */
1846 elmex 1.1
1847 root 1.22 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above)
1848 root 1.8 last = tmp;
1849 root 1.21
1850 root 1.8 /* Shouldn't happen, but if there are no objects on a space, this
1851     * would happen.
1852     */
1853     if (!last)
1854     continue;
1855 elmex 1.1
1856 root 1.8 done_one = 0;
1857     floor = 0;
1858     detect = NULL;
1859     for (tmp = last; tmp; tmp = tmp->below)
1860     {
1861     /* show invisible */
1862     if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) &&
1863 root 1.21 /* Might there be other objects that we can make visible? */
1864 root 1.8 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) ||
1865     (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) ||
1866     tmp->type == CF_HANDLE ||
1867     tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
1868     tmp->type == BUTTON || tmp->type == TELEPORTER ||
1869     tmp->type == GATE || tmp->type == LOCKED_DOOR ||
1870     tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
1871     tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
1872     tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR)))
1873     {
1874     if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1875     {
1876     tmp->invisible = 0;
1877     done_one = 1;
1878     }
1879     }
1880 root 1.21
1881 root 1.8 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1882     floor = 1;
1883 elmex 1.1
1884 root 1.8 /* All detections below this point don't descend beneath the floor,
1885     * so just continue on. We could be clever and look at the type of
1886     * detection to completely break out if we don't care about objects beneath
1887     * the floor, but once we get to the floor, not likely a very big issue anyways.
1888     */
1889     if (floor)
1890     continue;
1891 root 1.5
1892 root 1.8 /* I had thought about making detect magic and detect curse
1893     * show the flash the magic item like it does for detect monster.
1894     * however, if the object is within sight, this would then make it
1895     * difficult to see what object is magical/cursed, so the
1896     * effect wouldn't be as apparant.
1897 root 1.5 */
1898    
1899 root 1.8 /* detect magic */
1900     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1901     !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1902     {
1903     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1904     /* make runes more visibile */
1905     if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1906     tmp->stats.Cha /= 4;
1907     done_one = 1;
1908     }
1909     /* detect monster */
1910     if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1911     {
1912     done_one = 2;
1913     if (!detect)
1914     detect = tmp;
1915     }
1916     /* Basically, if race is set in the spell, then the creatures race must
1917     * match that. if the spell race is set to GOD, then the gods opposing
1918     * race must match.
1919 root 1.5 */
1920 root 1.8 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1921     ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) ||
1922     (strstr (spell->race, tmp->race))))
1923     {
1924     done_one = 2;
1925     if (!detect)
1926     detect = tmp;
1927     }
1928     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1929     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1930     {
1931     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1932     done_one = 1;
1933     }
1934     } /* for stack of objects on this space */
1935 root 1.5
1936 root 1.8 /* Code here puts an effect of the spell on the space, so you can see
1937     * where the magic is.
1938     */
1939     if (done_one)
1940     {
1941     object *detect_ob = arch_to_object (spell->other_arch);
1942    
1943     /* if this is set, we want to copy the face */
1944     if (done_one == 2 && detect)
1945     {
1946     detect_ob->face = detect->face;
1947     detect_ob->animation_id = detect->animation_id;
1948     detect_ob->anim_speed = detect->anim_speed;
1949     detect_ob->last_anim = 0;
1950     /* by default, the detect_ob is already animated */
1951     if (!QUERY_FLAG (detect, FLAG_ANIMATE))
1952     CLEAR_FLAG (detect_ob, FLAG_ANIMATE);
1953     }
1954 root 1.27
1955     m->insert (detect_ob, nx, ny, op);
1956 root 1.8 }
1957     } /* for processing the surrounding spaces */
1958 root 1.5
1959    
1960 root 1.8 /* Now process objects in the players inventory if detect curse or magic */
1961     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL))
1962     {
1963     done_one = 0;
1964     for (tmp = op->inv; tmp; tmp = tmp->below)
1965     {
1966     if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1967     {
1968     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL))
1969     {
1970     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1971     if (op->type == PLAYER)
1972     esrv_send_item (op, tmp);
1973 root 1.5 }
1974 root 1.8 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1975     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1976     {
1977     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1978     if (op->type == PLAYER)
1979     esrv_send_item (op, tmp);
1980 root 1.5 }
1981 root 1.8 } /* if item is not identified */
1982     } /* for the players inventory */
1983     } /* if detect magic/curse and object is a player */
1984     return 1;
1985 elmex 1.1 }
1986    
1987    
1988     /**
1989     * Checks if victim has overcharged mana. caster_level is the caster's (skill)
1990     * level whos spell did cause the overcharge.
1991     */
1992 root 1.8 static void
1993     charge_mana_effect (object *victim, int caster_level)
1994 elmex 1.1 {
1995    
1996 root 1.8 /* Prevent explosions for objects without mana. Without this check, doors
1997     * will explode, too.
1998     */
1999     if (victim->stats.maxsp <= 0)
2000     return;
2001 elmex 1.1
2002 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
2003 elmex 1.1
2004 root 1.8 if (victim->stats.sp >= victim->stats.maxsp * 2)
2005     {
2006     object *tmp;
2007 elmex 1.1
2008 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
2009 elmex 1.1
2010 root 1.8 /* Explodes a fireball centered at player */
2011     tmp = get_archetype (EXPLODING_FIREBALL);
2012     tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
2013     tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
2014 root 1.27
2015     tmp->insert_at (victim);
2016 root 1.8 victim->stats.sp = 2 * victim->stats.maxsp;
2017 elmex 1.1 }
2018 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
2019 root 1.27 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode.");
2020 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
2021 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
2022 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
2023     {
2024     new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
2025     confuse_player (victim, victim, 99);
2026 elmex 1.1 }
2027 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.25)
2028 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You start hearing voices.");
2029 elmex 1.1 }
2030    
2031     /* cast_transfer
2032     * This spell transfers sp from the player to another person.
2033     * We let the target go above their normal maximum SP.
2034     */
2035    
2036 root 1.8 int
2037     cast_transfer (object *op, object *caster, object *spell, int dir)
2038     {
2039     object *plyr = NULL;
2040     sint16 x, y;
2041 root 1.13 maptile *m;
2042 root 1.8 int mflags;
2043    
2044     m = op->map;
2045     x = op->x + freearr_x[dir];
2046     y = op->y + freearr_y[dir];
2047    
2048     mflags = get_map_flags (m, &m, x, y, &x, &y);
2049    
2050     if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
2051     {
2052 root 1.22 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above)
2053 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
2054     break;
2055 elmex 1.1 }
2056    
2057    
2058 root 1.8 /* If we did not find a player in the specified direction, transfer
2059     * to anyone on top of us. This is used for the rune of transference mostly.
2060     */
2061     if (plyr == NULL)
2062 root 1.22 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
2063 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
2064     break;
2065 elmex 1.1
2066 root 1.8 if (!plyr)
2067     {
2068     new_draw_info (NDI_BLACK, 0, op, "There is no one there.");
2069     return 0;
2070 elmex 1.1 }
2071 root 1.8 /* give sp */
2072     if (spell->stats.dam > 0)
2073     {
2074     plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
2075     charge_mana_effect (plyr, caster_level (caster, spell));
2076     return 1;
2077 elmex 1.1 }
2078 root 1.8 /* suck sp away. Can't suck sp from yourself */
2079     else if (op != plyr)
2080     {
2081     /* old dragin magic used floats. easier to just use ints and divide by 100 */
2082    
2083     int rate = -spell->stats.dam + SP_level_dam_adjust (caster, spell), sucked;
2084    
2085     if (rate > 95)
2086     rate = 95;
2087    
2088     sucked = (plyr->stats.sp * rate) / 100;
2089     plyr->stats.sp -= sucked;
2090     if (QUERY_FLAG (op, FLAG_ALIVE))
2091     {
2092     /* Player doesn't get full credit */
2093     sucked = (sucked * rate) / 100;
2094     op->stats.sp += sucked;
2095     if (sucked > 0)
2096     {
2097     charge_mana_effect (op, caster_level (caster, spell));
2098 root 1.5 }
2099     }
2100 root 1.8 return 1;
2101 elmex 1.1 }
2102 root 1.8 return 0;
2103 elmex 1.1 }
2104    
2105    
2106     /* counterspell: nullifies spell effects.
2107     * op is the counterspell object, dir is the direction
2108     * it was cast in.
2109     * Basically, if the object has a magic attacktype,
2110     * this may nullify it.
2111     */
2112 root 1.8 void
2113     counterspell (object *op, int dir)
2114 elmex 1.1 {
2115 root 1.8 object *tmp, *head, *next;
2116     int mflags;
2117 root 1.13 maptile *m;
2118 root 1.8 sint16 sx, sy;
2119    
2120     sx = op->x + freearr_x[dir];
2121     sy = op->y + freearr_y[dir];
2122     m = op->map;
2123     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
2124     if (mflags & P_OUT_OF_MAP)
2125     return;
2126 elmex 1.1
2127 root 1.22 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next)
2128 root 1.8 {
2129     next = tmp->above;
2130 elmex 1.1
2131 root 1.8 /* Need to look at the head object - otherwise, if tmp
2132     * points to a monster, we don't have all the necessary
2133     * info for it.
2134     */
2135     if (tmp->head)
2136     head = tmp->head;
2137     else
2138     head = tmp;
2139    
2140     /* don't attack our own spells */
2141     if (tmp->owner && tmp->owner == op->owner)
2142     continue;
2143    
2144     /* Basically, if the object is magical and not counterspell,
2145     * we will more or less remove the object. Don't counterspell
2146     * monsters either.
2147     */
2148 elmex 1.1
2149 elmex 1.44 if (head->attacktype & AT_MAGIC
2150     && !(head->attacktype & AT_COUNTERSPELL)
2151     && !QUERY_FLAG (head, FLAG_MONSTER)
2152     && (op->level > head->level))
2153 root 1.17 head->destroy ();
2154 root 1.8 else
2155     switch (head->type)
2156     {
2157     case SPELL_EFFECT:
2158 elmex 1.44 // XXX: Don't affect floor spelleffects. See also XXX comment
2159     // about sanctuary in spell_util.C
2160     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
2161     continue;
2162    
2163 root 1.8 if (op->level > head->level)
2164 root 1.17 head->destroy ();
2165    
2166 root 1.5 break;
2167    
2168 root 1.8 /* I really don't get this rune code that much - that
2169     * random chance seems really low.
2170     */
2171     case RUNE:
2172     if (rndm (0, 149) == 0)
2173     {
2174     head->stats.hp--; /* weaken the rune */
2175     if (!head->stats.hp)
2176 root 1.17 head->destroy ();
2177 root 1.8 }
2178 root 1.5 break;
2179 root 1.8 }
2180 elmex 1.1 }
2181     }
2182    
2183    
2184    
2185     /* cast_consecrate() - a spell to make an altar your god's */
2186 root 1.8 int
2187     cast_consecrate (object *op, object *caster, object *spell)
2188     {
2189     char buf[MAX_BUF];
2190 elmex 1.1
2191 root 1.8 object *tmp, *god = find_god (determine_god (op));
2192 elmex 1.1
2193 root 1.8 if (!god)
2194     {
2195     new_draw_info (NDI_UNIQUE, 0, op, "You can't consecrate anything if you don't worship a god!");
2196     return 0;
2197 elmex 1.1 }
2198 root 1.8
2199     for (tmp = op->below; tmp; tmp = tmp->below)
2200     {
2201     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
2202     break;
2203     if (tmp->type == HOLY_ALTAR)
2204     {
2205    
2206     if (tmp->level > caster_level (caster, spell))
2207     {
2208     new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name);
2209     return 0;
2210     }
2211     else
2212     {
2213     /* If we got here, we are consecrating an altar */
2214     sprintf (buf, "Altar of %s", &god->name);
2215     tmp->name = buf;
2216     tmp->level = caster_level (caster, spell);
2217     tmp->other_arch = god->arch;
2218     if (op->type == PLAYER)
2219     esrv_update_item (UPD_NAME, op, tmp);
2220     new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
2221     return 1;
2222 root 1.5 }
2223     }
2224 elmex 1.1 }
2225 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You are not standing over an altar!");
2226     return 0;
2227 elmex 1.1 }
2228    
2229     /* animate_weapon -
2230     * Generalization of staff_to_snake. Makes a golem out of the caster's weapon.
2231     * The golem is based on the archetype specified, modified by the caster's level
2232     * and the attributes of the weapon. The weapon is inserted in the golem's
2233     * inventory so that it falls to the ground when the golem dies.
2234     * This code was very odd - code early on would only let players use the spell,
2235     * yet the code wass full of player checks. I've presumed that the code
2236     * that only let players use it was correct, and removed all the other
2237     * player checks. MSW 2003-01-06
2238     */
2239 root 1.8 int
2240     animate_weapon (object *op, object *caster, object *spell, int dir)
2241     {
2242     object *weapon, *tmp;
2243     char buf[MAX_BUF];
2244     int a, i;
2245     sint16 x, y;
2246 root 1.13 maptile *m;
2247 root 1.8 materialtype_t *mt;
2248    
2249     if (!spell->other_arch)
2250     {
2251     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
2252     LOG (llevError, "animate_weapon failed: spell %s missing other_arch!\n", &spell->name);
2253     return 0;
2254 elmex 1.1 }
2255 root 1.8 /* exit if it's not a player using this spell. */
2256     if (op->type != PLAYER)
2257     return 0;
2258 elmex 1.1
2259 root 1.8 /* if player already has a golem, abort */
2260 root 1.49 if (object *golem = op->contr->golem)
2261 root 1.8 {
2262 root 1.46 control_golem (golem, dir);
2263 root 1.8 return 0;
2264 elmex 1.1 }
2265    
2266 root 1.8 /* if no direction specified, pick one */
2267     if (!dir)
2268     dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9);
2269    
2270     m = op->map;
2271     x = op->x + freearr_x[dir];
2272     y = op->y + freearr_y[dir];
2273    
2274     /* if there's no place to put the golem, abort */
2275     if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) ||
2276     ((spell->other_arch->clone.move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->clone.move_type))
2277     {
2278     new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
2279     return 0;
2280 elmex 1.1 }
2281    
2282 root 1.8 /* Use the weapon marked by the player. */
2283     weapon = find_marked_object (op);
2284 elmex 1.1
2285 root 1.8 if (!weapon)
2286     {
2287     new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!");
2288     return 0;
2289     }
2290     if (spell->race && strcmp (weapon->arch->name, spell->race))
2291     {
2292     new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon.");
2293     return 0;
2294     }
2295     if (weapon->type != WEAPON)
2296     {
2297     new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it.");
2298     return 0;
2299 elmex 1.1 }
2300 root 1.8 if (QUERY_FLAG (weapon, FLAG_APPLIED))
2301     {
2302     new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon));
2303     return 0;
2304 elmex 1.1 }
2305 root 1.8
2306     if (weapon->nrof > 1)
2307     {
2308     tmp = get_split_ob (weapon, 1);
2309     esrv_send_item (op, weapon);
2310     weapon = tmp;
2311     }
2312    
2313     /* create the golem object */
2314     tmp = arch_to_object (spell->other_arch);
2315    
2316     /* if animated by a player, give the player control of the golem */
2317     CLEAR_FLAG (tmp, FLAG_MONSTER);
2318     tmp->stats.exp = 0;
2319     add_friendly_object (tmp);
2320     tmp->type = GOLEM;
2321 root 1.19 tmp->set_owner (op);
2322 root 1.49 op->contr->golem = tmp;
2323 root 1.46 set_spell_skill (op, caster, spell, tmp);
2324 root 1.8
2325     /* Give the weapon to the golem now. A bit of a hack to check the
2326     * removed flag - it should only be set if get_split_object was
2327     * used above.
2328     */
2329     if (!QUERY_FLAG (weapon, FLAG_REMOVED))
2330 root 1.16 weapon->remove ();
2331 root 1.46
2332 root 1.8 insert_ob_in_ob (weapon, tmp);
2333     esrv_send_item (op, weapon);
2334     /* To do everything necessary to let a golem use the weapon is a pain,
2335     * so instead, just set it as equipped (otherwise, we need to update
2336     * body_info, skills, etc)
2337     */
2338     SET_FLAG (tmp, FLAG_USE_WEAPON);
2339     SET_FLAG (weapon, FLAG_APPLIED);
2340 root 1.24 tmp->update_stats ();
2341 root 1.8
2342     /* There used to be 'odd' code that basically seemed to take the absolute
2343     * value of the weapon->magic an use that. IMO, that doesn't make sense -
2344     * if you're using a crappy weapon, it shouldn't be as good.
2345     */
2346    
2347     /* modify weapon's animated wc */
2348     tmp->stats.wc = tmp->stats.wc - SP_level_range_adjust (caster, spell) - 5 * weapon->stats.Dex - 2 * weapon->stats.Str - weapon->magic;
2349     if (tmp->stats.wc < -127)
2350     tmp->stats.wc = -127;
2351    
2352     /* Modify hit points for weapon */
2353     tmp->stats.maxhp = tmp->stats.maxhp + spell->duration +
2354     SP_level_duration_adjust (caster, spell) + +8 * weapon->magic + 12 * weapon->stats.Con;
2355     if (tmp->stats.maxhp < 0)
2356     tmp->stats.maxhp = 10;
2357     tmp->stats.hp = tmp->stats.maxhp;
2358    
2359     /* Modify weapon's damage */
2360     tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell) + weapon->stats.dam + weapon->magic + 5 * weapon->stats.Str;
2361     if (tmp->stats.dam < 0)
2362     tmp->stats.dam = 127;
2363    
2364    
2365     /* attacktype */
2366     if (!tmp->attacktype)
2367     tmp->attacktype = AT_PHYSICAL;
2368    
2369     mt = NULL;
2370     if (op->materialname != NULL)
2371     mt = name_to_material (op->materialname);
2372     if (mt != NULL)
2373     {
2374     for (i = 0; i < NROFATTACKS; i++)
2375     tmp->resist[i] = 50 - (mt->save[i] * 5);
2376     a = mt->save[0];
2377 elmex 1.1 }
2378 root 1.8 else
2379     {
2380     for (i = 0; i < NROFATTACKS; i++)
2381     tmp->resist[i] = 5;
2382     a = 10;
2383     }
2384     /* Set weapon's immunity */
2385     tmp->resist[ATNR_CONFUSION] = 100;
2386     tmp->resist[ATNR_POISON] = 100;
2387     tmp->resist[ATNR_SLOW] = 100;
2388     tmp->resist[ATNR_PARALYZE] = 100;
2389     tmp->resist[ATNR_TURN_UNDEAD] = 100;
2390     tmp->resist[ATNR_FEAR] = 100;
2391     tmp->resist[ATNR_DEPLETE] = 100;
2392     tmp->resist[ATNR_DEATH] = 100;
2393     tmp->resist[ATNR_BLIND] = 100;
2394    
2395     /* Improve weapon's armour value according to best save vs. physical of its material */
2396    
2397     if (a > 14)
2398     a = 14;
2399     tmp->resist[ATNR_PHYSICAL] = 100 - (int) ((100.0 - (float) tmp->resist[ATNR_PHYSICAL]) / (30.0 - 2.0 * a));
2400    
2401     /* Determine golem's speed */
2402 root 1.26 tmp->set_speed (min (3.33, 0.4 + 0.1 * SP_level_range_adjust (caster, spell)));
2403 root 1.8
2404     if (!spell->race)
2405     {
2406     sprintf (buf, "animated %s", &weapon->name);
2407     tmp->name = buf;
2408    
2409     tmp->face = weapon->face;
2410     tmp->animation_id = weapon->animation_id;
2411     tmp->anim_speed = weapon->anim_speed;
2412     tmp->last_anim = weapon->last_anim;
2413     tmp->state = weapon->state;
2414 root 1.26 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE];
2415 elmex 1.1 }
2416    
2417 root 1.8 /* make experience increase in proportion to the strength of the summoned creature. */
2418     tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / caster_level (caster, spell));
2419    
2420     tmp->speed_left = -1;
2421     tmp->direction = dir;
2422 root 1.27
2423     m->insert (tmp, x, y, op);
2424 root 1.8 return 1;
2425 elmex 1.1 }
2426    
2427     /* cast_daylight() - changes the map darkness level *lower* */
2428    
2429     /* cast_change_map_lightlevel: Was cast_daylight/nightfall.
2430     * This changes the light level for the entire map.
2431     */
2432    
2433 root 1.8 int
2434     cast_change_map_lightlevel (object *op, object *caster, object *spell)
2435     {
2436     int success;
2437 elmex 1.1
2438 root 1.8 if (!op->map)
2439     return 0; /* shouldnt happen */
2440 elmex 1.1
2441 root 1.28 success = op->map->change_map_light (spell->stats.dam);
2442    
2443 root 1.8 if (!success)
2444     {
2445     if (spell->stats.dam < 0)
2446     new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here.");
2447     else
2448     new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here.");
2449 elmex 1.1 }
2450 root 1.8 return success;
2451 elmex 1.1 }
2452    
2453    
2454    
2455    
2456    
2457     /* create an aura spell object and put it in the player's inventory.
2458     * as usual, op is player, caster is the object casting the spell,
2459     * spell is the spell object itself.
2460     */
2461 root 1.8 int
2462     create_aura (object *op, object *caster, object *spell)
2463 elmex 1.1 {
2464 root 1.8 int refresh = 0;
2465     object *new_aura;
2466 elmex 1.1
2467 root 1.8 new_aura = present_arch_in_ob (spell->other_arch, op);
2468     if (new_aura)
2469     refresh = 1;
2470     else
2471     new_aura = arch_to_object (spell->other_arch);
2472    
2473     new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell);
2474    
2475     new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2476    
2477 root 1.19 new_aura->set_owner (op);
2478 root 1.8 set_spell_skill (op, caster, spell, new_aura);
2479     new_aura->attacktype = spell->attacktype;
2480    
2481     new_aura->level = caster_level (caster, spell);
2482     if (refresh)
2483     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2484     else
2485     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2486     insert_ob_in_ob (new_aura, op);
2487     return 1;
2488 elmex 1.1 }
2489    
2490    
2491     /* move aura function. An aura is a part of someone's inventory,
2492     * which he carries with him, but which acts on the map immediately
2493     * around him.
2494     * Aura parameters:
2495     * duration: duration counter.
2496     * attacktype: aura's attacktype
2497     * other_arch: archetype to drop where we attack
2498     */
2499    
2500 root 1.8 void
2501     move_aura (object *aura)
2502     {
2503     int i, mflags;
2504     object *env;
2505 root 1.13 maptile *m;
2506 root 1.8
2507     /* auras belong in inventories */
2508     env = aura->env;
2509    
2510     /* no matter what we've gotta remove the aura...
2511     * we'll put it back if its time isn't up.
2512     */
2513 root 1.16 aura->remove ();
2514 root 1.8
2515     /* exit if we're out of gas */
2516     if (aura->duration-- < 0)
2517     {
2518 root 1.17 aura->destroy ();
2519 root 1.8 return;
2520     }
2521    
2522     /* auras only exist in inventories */
2523     if (env == NULL || env->map == NULL)
2524     {
2525 root 1.17 aura->destroy ();
2526 root 1.8 return;
2527     }
2528 root 1.17
2529 root 1.8 /* we need to jump out of the inventory for a bit
2530     * in order to hit the map conveniently.
2531     */
2532 root 1.27 aura->insert_at (env, aura);
2533 root 1.8
2534     for (i = 1; i < 9; i++)
2535     {
2536     sint16 nx, ny;
2537    
2538     nx = aura->x + freearr_x[i];
2539     ny = aura->y + freearr_y[i];
2540     mflags = get_map_flags (env->map, &m, nx, ny, &nx, &ny);
2541    
2542     /* Consider the movement tyep of the person with the aura as
2543     * movement type of the aura. Eg, if the player is flying, the aura
2544     * is flying also, if player is walking, it is on the ground, etc.
2545     */
2546     if (!(mflags & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (env, GET_MAP_MOVE_BLOCK (m, nx, ny))))
2547 elmex 1.6 {
2548 root 1.8 hit_map (aura, i, aura->attacktype, 0);
2549 root 1.5
2550 root 1.8 if (aura->other_arch)
2551 root 1.27 m->insert (arch_to_object (aura->other_arch), nx, ny, aura);
2552 root 1.5 }
2553 elmex 1.1 }
2554 root 1.27
2555 root 1.8 /* put the aura back in the player's inventory */
2556 root 1.16 aura->remove ();
2557 root 1.8 insert_ob_in_ob (aura, env);
2558 elmex 1.1 }
2559    
2560     /* moves the peacemaker spell.
2561     * op is the piece object.
2562 root 1.8 */
2563 elmex 1.1
2564 root 1.8 void
2565     move_peacemaker (object *op)
2566     {
2567     object *tmp;
2568 elmex 1.1
2569 root 1.22 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2570 root 1.8 {
2571     int atk_lev, def_lev;
2572     object *victim = tmp;
2573 elmex 1.1
2574 root 1.8 if (tmp->head)
2575     victim = tmp->head;
2576     if (!QUERY_FLAG (victim, FLAG_MONSTER))
2577     continue;
2578     if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
2579     continue;
2580     if (victim->stats.exp == 0)
2581     continue;
2582 elmex 1.1
2583 root 1.8 def_lev = MAX (1, victim->level);
2584     atk_lev = MAX (1, op->level);
2585 elmex 1.1
2586 root 1.8 if (rndm (0, atk_lev - 1) > def_lev)
2587     {
2588     /* make this sucker peaceful. */
2589 elmex 1.1
2590 root 1.19 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2591 root 1.8 victim->stats.exp = 0;
2592 elmex 1.1 #if 0
2593 root 1.8 /* No idea why these were all set to zero - if something
2594     * makes this creature agressive, he should still do damage.
2595     */
2596     victim->stats.dam = 0;
2597     victim->stats.sp = 0;
2598     victim->stats.grace = 0;
2599     victim->stats.Pow = 0;
2600 elmex 1.1 #endif
2601 root 1.8 victim->attack_movement = RANDO2;
2602     SET_FLAG (victim, FLAG_UNAGGRESSIVE);
2603     SET_FLAG (victim, FLAG_RUN_AWAY);
2604     SET_FLAG (victim, FLAG_RANDOM_MOVE);
2605     CLEAR_FLAG (victim, FLAG_MONSTER);
2606     if (victim->name)
2607     {
2608     new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2609 root 1.5 }
2610     }
2611 elmex 1.1 }
2612 root 1.8 }
2613    
2614 elmex 1.1
2615     /* This writes a rune that contains the appropriate message.
2616     * There really isn't any adjustments we make.
2617     */
2618    
2619 root 1.8 int
2620     write_mark (object *op, object *spell, const char *msg)
2621     {
2622     char rune[HUGE_BUF];
2623     object *tmp;
2624 elmex 1.1
2625 root 1.8 if (!msg || msg[0] == 0)
2626     {
2627     new_draw_info (NDI_UNIQUE, 0, op, "Write what?");
2628     return 0;
2629 elmex 1.1 }
2630    
2631 root 1.8 if (strcasestr_local (msg, "endmsg"))
2632     {
2633     new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?");
2634     LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg);
2635     return 0;
2636 elmex 1.1 }
2637 root 1.8 if (!spell->other_arch)
2638     return 0;
2639     tmp = arch_to_object (spell->other_arch);
2640 root 1.9
2641     snprintf (rune, sizeof (rune), "%s\n", msg);
2642    
2643 root 1.8 tmp->race = op->name; /*Save the owner of the rune */
2644     tmp->msg = rune;
2645 root 1.27
2646     tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2647 root 1.8 return 1;
2648 elmex 1.1 }