ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.41
Committed: Thu Mar 1 12:28:16 2007 UTC (17 years, 3 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_0
Changes since 1.40: +0 -2 lines
Log Message:
nano-cleanups

File Contents

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