ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.54
Committed: Mon May 28 21:28:36 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.53: +17 -17 lines
Log Message:
update copyrights in server/*.C

File Contents

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