ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.32
Committed: Sat Jan 6 14:42:31 2007 UTC (17 years, 5 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.31: +1 -0 lines
Log Message:
added some copyrights

File Contents

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