ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.42
Committed: Wed Mar 14 04:12:29 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.41: +2 -1 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

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