ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.37
Committed: Tue Feb 6 03:21:20 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.36: +8 -6 lines
Log Message:
*** empty log message ***

File Contents

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