ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.58
Committed: Fri Jun 8 08:36:48 2007 UTC (16 years, 11 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.57: +1 -1 lines
Log Message:
fix for horn of plenty and others

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.57 if (wand->arch && QUERY_FLAG (wand->arch, FLAG_ANIMATE))
110 root 1.8 {
111     SET_FLAG (wand, FLAG_ANIMATE);
112 root 1.57 wand->set_speed (wand->arch->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 root 1.57 if (at == NULL || at->stats.food > food_value)
230 root 1.8 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 elmex 1.58 for_all_archetypes (at_tmp)
246 root 1.8 {
247 root 1.57 if (at_tmp->type == FOOD || at_tmp->type == DRINK)
248 root 1.8 {
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 root 1.57 if (at_tmp->stats.food <= food_value && (!at || at_tmp->stats.food > at->stats.food))
254 root 1.8 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.57 food_value /= at->stats.food;
268 root 1.8 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 root 1.56 if (tmp->type == FORCE && !strcmp (tmp->arch->archname, "dragon_ability_force"))
603 root 1.8 {
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 root 1.57 if (tmp->other_arch && tmp->other_arch->type == SPELL)
722 root 1.8 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 root 1.57 if (tmp2->other_arch && tmp2->other_arch->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.57 if (tmp2->other_arch && tmp2->other_arch->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     /* This is used for the spells that gain stats. There are no spells
1020     * right now that icnrease wis/int/pow on a temp basis, so no
1021     * good comments for those.
1022     */
1023 root 1.8 static const char *const no_gain_msgs[NUM_STATS] = {
1024     "You grow no stronger.",
1025     "You grow no more agile.",
1026     "You don't feel any healthier.",
1027 root 1.55 "You didn't grow any more intelligent.",
1028     "You do not feel any wiser.",
1029     "You don't feel any more powerful."
1030 root 1.8 "You are no easier to look at.",
1031 elmex 1.1 };
1032    
1033 root 1.8 int
1034     cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1035     {
1036     object *force = NULL;
1037     int i;
1038    
1039     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1040 root 1.27 object *tmp = dir
1041     ? find_target_for_friendly_spell (op, dir)
1042     : op;
1043 root 1.8
1044 root 1.27 if (!tmp)
1045 root 1.8 return 0;
1046    
1047     /* If we've already got a force of this type, don't add a new one. */
1048 root 1.27 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1049 root 1.8 {
1050     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1051     {
1052     if (tmp2->name == spell_ob->name)
1053     {
1054     force = tmp2; /* the old effect will be "refreshed" */
1055     break;
1056 root 1.5 }
1057 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1058     {
1059     if (!silent)
1060     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1061     return 0;
1062 root 1.5 }
1063     }
1064 elmex 1.1 }
1065 root 1.8 if (force == NULL)
1066     {
1067     force = get_archetype (FORCE_NAME);
1068     force->subtype = FORCE_CHANGE_ABILITY;
1069     if (spell_ob->race)
1070     force->name = spell_ob->race;
1071     else
1072     force->name = spell_ob->name;
1073     force->name_pl = spell_ob->name;
1074     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1075    
1076     }
1077     else
1078     {
1079     int duration;
1080    
1081     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1082     if (duration > force->duration)
1083     {
1084     force->duration = duration;
1085     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1086     }
1087     else
1088     {
1089     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1090     }
1091 root 1.55
1092 root 1.8 return 1;
1093     }
1094 root 1.55
1095 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1096     force->speed = 1.0;
1097     force->speed_left = -1.0;
1098     SET_FLAG (force, FLAG_APPLIED);
1099    
1100     /* Now start processing the effects. First, protections */
1101     for (i = 0; i < NROFATTACKS; i++)
1102     {
1103     if (spell_ob->resist[i])
1104     {
1105     force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob);
1106     if (force->resist[i] > 100)
1107     force->resist[i] = 100;
1108 root 1.5 }
1109 elmex 1.1 }
1110 root 1.55
1111 root 1.8 if (spell_ob->stats.hp)
1112     force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1113    
1114     if (tmp->type == PLAYER)
1115     {
1116     /* Stat adjustment spells */
1117     for (i = 0; i < NUM_STATS; i++)
1118     {
1119 root 1.51 if (sint8 stat = spell_ob->stats.stat (i))
1120 root 1.8 {
1121 root 1.51 sint8 sm = 0;
1122     for (sint8 k = 0; k < stat; k++)
1123 root 1.8 sm += rndm (1, 3);
1124    
1125 root 1.51 if (tmp->stats.stat (i) + sm > 15 + 5 * stat)
1126     sm = max (0, (15 + 5 * stat) - tmp->stats.stat (i));
1127    
1128     force->stats.stat (i) = sm;
1129    
1130 root 1.8 if (!sm)
1131     new_draw_info (NDI_UNIQUE, 0, op, no_gain_msgs[i]);
1132 root 1.5 }
1133     }
1134 elmex 1.1 }
1135    
1136 root 1.8 force->move_type = spell_ob->move_type;
1137 elmex 1.1
1138 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK))
1139     SET_FLAG (force, FLAG_SEE_IN_DARK);
1140 elmex 1.1
1141 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_XRAYS))
1142     SET_FLAG (force, FLAG_XRAYS);
1143 elmex 1.1
1144 root 1.8 /* Haste/bonus speed */
1145     if (spell_ob->stats.exp)
1146     {
1147     if (op->speed > 0.5f)
1148     force->stats.exp = (sint64) ((float) spell_ob->stats.exp / (op->speed + 0.5f));
1149     else
1150     force->stats.exp = spell_ob->stats.exp;
1151 elmex 1.1 }
1152    
1153 root 1.8 force->stats.wc = spell_ob->stats.wc;
1154     force->stats.ac = spell_ob->stats.ac;
1155     force->attacktype = spell_ob->attacktype;
1156    
1157     insert_ob_in_ob (force, tmp);
1158     change_abil (tmp, force); /* Mostly to display any messages */
1159 root 1.24 tmp->update_stats ();
1160 root 1.55
1161 root 1.8 return 1;
1162 elmex 1.1 }
1163    
1164     /* This used to be part of cast_change_ability, but it really didn't make
1165     * a lot of sense, since most of the values it derives are from the god
1166     * of the caster.
1167     */
1168 root 1.8 int
1169     cast_bless (object *op, object *caster, object *spell_ob, int dir)
1170     {
1171     int i;
1172     object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp;
1173    
1174     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1175     if (dir != 0)
1176     {
1177     tmp = find_target_for_friendly_spell (op, dir);
1178     }
1179     else
1180     {
1181     tmp = op;
1182     }
1183    
1184     /* If we've already got a force of this type, don't add a new one. */
1185     for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1186     {
1187     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1188     {
1189     if (tmp2->name == spell_ob->name)
1190     {
1191     force = tmp2; /* the old effect will be "refreshed" */
1192     break;
1193 root 1.5 }
1194 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1195     {
1196     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1197     return 0;
1198 root 1.5 }
1199     }
1200 elmex 1.1 }
1201 root 1.8 if (force == NULL)
1202     {
1203     force = get_archetype (FORCE_NAME);
1204     force->subtype = FORCE_CHANGE_ABILITY;
1205     if (spell_ob->race)
1206     force->name = spell_ob->race;
1207     else
1208     force->name = spell_ob->name;
1209     force->name_pl = spell_ob->name;
1210     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1211     }
1212     else
1213     {
1214     int duration;
1215    
1216     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1217     if (duration > force->duration)
1218     {
1219     force->duration = duration;
1220     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1221 root 1.5 }
1222 root 1.8 else
1223     {
1224     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1225     }
1226     return 0;
1227 elmex 1.1 }
1228 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1229     force->speed = 1.0;
1230     force->speed_left = -1.0;
1231     SET_FLAG (force, FLAG_APPLIED);
1232 elmex 1.1
1233 root 1.8 if (!god)
1234     {
1235     new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1236     }
1237     else
1238     {
1239     /* Only give out good benefits, and put a max on it */
1240     for (i = 0; i < NROFATTACKS; i++)
1241     {
1242     if (god->resist[i] > 0)
1243     {
1244     force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1245 root 1.5 }
1246     }
1247 root 1.8 force->path_attuned |= god->path_attuned;
1248 root 1.7
1249 root 1.8 if (spell_ob->attacktype)
1250     force->slaying = god->slaying;
1251 root 1.7
1252 root 1.8 if (tmp != op)
1253     {
1254     new_draw_info_format (NDI_UNIQUE, 0, op, "You bless %s.", &tmp->name);
1255     new_draw_info_format (NDI_UNIQUE, 0, tmp, "%s blessed you.", &op->name);
1256     }
1257     else
1258     {
1259     new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are blessed by %s!", &god->name);
1260 root 1.5 }
1261 elmex 1.1
1262     }
1263 root 1.8 force->stats.wc = spell_ob->stats.wc;
1264     force->stats.ac = spell_ob->stats.ac;
1265 elmex 1.1
1266 root 1.8 change_abil (tmp, force); /* Mostly to display any messages */
1267     insert_ob_in_ob (force, tmp);
1268 root 1.24 tmp->update_stats ();
1269 root 1.8 return 1;
1270 elmex 1.1 }
1271    
1272     /* Alchemy code by Mark Wedel
1273     *
1274     * This code adds a new spell, called alchemy. Alchemy will turn
1275     * objects to gold nuggets, the value of the gold nuggets being
1276     * about 90% of that of the item itself. It uses the value of the
1277     * object before charisma adjustments, because the nuggets themselves
1278     * will be will be adjusted by charisma when sold.
1279     *
1280     * Large nuggets are worth 25 gp each (base). You will always get
1281     * the maximum number of large nuggets you could get.
1282     * Small nuggets are worth 1 gp each (base). You will get from 0
1283     * to the max amount of small nuggets as you could get.
1284     *
1285     * For example, if an item is worth 110 gold, you will get
1286     * 4 large nuggets, and from 0-10 small nuggets.
1287     *
1288     * There is also a chance (1:30) that you will get nothing at all
1289     * for the object. There is also a maximum weight that will be
1290 root 1.37 * alchemised.
1291 elmex 1.1 */
1292 root 1.8 static void
1293 root 1.38 alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1294 root 1.8 {
1295     uint64 value = query_cost (obj, NULL, F_TRUE);
1296    
1297     /* Give third price when we alchemy money (This should hopefully
1298     * make it so that it isn't worth it to alchemy money, sell
1299     * the nuggets, alchemy the gold from that, etc.
1300     * Otherwise, give 9 silver on the gold for other objects,
1301     * so that it would still be more affordable to haul
1302     * the stuff back to town.
1303     */
1304     if (QUERY_FLAG (obj, FLAG_UNPAID))
1305     value = 0;
1306     else if (obj->type == MONEY || obj->type == GEM)
1307     value /= 3;
1308     else
1309 root 1.39 value = value * 9 / 10;
1310 root 1.8
1311 root 1.37 if (obj->value > 0 && rndm (0, 29))
1312 root 1.38 total_value += value;
1313 root 1.8
1314 root 1.38 total_weight += obj->total_weight ();
1315 root 1.8
1316 root 1.17 obj->destroy ();
1317 root 1.8 }
1318    
1319     static void
1320 root 1.38 update_map (object *op, maptile *m, int small_nuggets, object *small, int large_nuggets, object *large, int x, int y)
1321 root 1.8 {
1322     int flag = 0;
1323    
1324     /* Put any nuggets below the player, but we can only pass this
1325     * flag if we are on the same space as the player
1326     */
1327     if (x == op->x && y == op->y && op->map == m)
1328     flag = INS_BELOW_ORIGINATOR;
1329    
1330     if (small_nuggets)
1331     {
1332 root 1.38 object *tmp = small->clone ();
1333 root 1.8 tmp->nrof = small_nuggets;
1334 root 1.27 m->insert (tmp, x, y, op, flag);
1335 root 1.8 }
1336 root 1.18
1337 root 1.8 if (large_nuggets)
1338     {
1339 root 1.38 object *tmp = large->clone ();
1340 root 1.8 tmp->nrof = large_nuggets;
1341 root 1.27 m->insert (tmp, x, y, op, flag);
1342 root 1.8 }
1343 root 1.38
1344     if (object *pl = m->at (x, y).player ())
1345     if (pl->contr->ns)
1346     pl->contr->ns->look_position = 0;
1347 root 1.8 }
1348    
1349     int
1350     alchemy (object *op, object *caster, object *spell_ob)
1351 elmex 1.1 {
1352 root 1.8 if (op->type != PLAYER)
1353     return 0;
1354    
1355 root 1.39 object *large = get_archetype ("largenugget");
1356     object *small = get_archetype ("smallnugget");
1357    
1358 root 1.38 /* Put a maximum weight of items that can be alchemised. Limits the power
1359     * some, and also prevents people from alchemising every table/chair/clock
1360 root 1.8 * in sight
1361     */
1362 root 1.38 int duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1363     int weight_max = duration * 1000;
1364     uint64 value_max = duration * 1000;
1365 elmex 1.1
1366 root 1.39 int weight = 0;
1367 root 1.38
1368     for (int y = op->y - 1; y <= op->y + 1; y++)
1369 root 1.8 {
1370 root 1.38 for (int x = op->x - 1; x <= op->x + 1; x++)
1371 root 1.8 {
1372 root 1.38 uint64 value = 0;
1373    
1374     sint16 nx = x;
1375     sint16 ny = y;
1376 elmex 1.1
1377 root 1.39 maptile *mp = op->map;
1378 root 1.5
1379 root 1.39 int mflags = get_map_flags (mp, &mp, nx, ny, &nx, &ny);
1380 root 1.5
1381 root 1.8 if (mflags & (P_OUT_OF_MAP | P_NO_MAGIC))
1382     continue;
1383    
1384     /* Treat alchemy a little differently - most spell effects
1385     * use fly as the movement type - for alchemy, consider it
1386     * ground level effect.
1387     */
1388     if (GET_MAP_MOVE_BLOCK (mp, nx, ny) & MOVE_WALK)
1389     continue;
1390    
1391 root 1.38 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1392 root 1.8 {
1393     next = tmp->above;
1394 root 1.37
1395 root 1.8 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) &&
1396     !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
1397     {
1398     if (tmp->inv)
1399     {
1400     object *next1, *tmp1;
1401    
1402 root 1.37 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1403 root 1.8 {
1404     next1 = tmp1->below;
1405     if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) &&
1406     !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON))
1407 root 1.38 alchemy_object (tmp1, value, weight);
1408 root 1.5 }
1409     }
1410 root 1.37
1411 root 1.38 alchemy_object (tmp, value, weight);
1412 root 1.8
1413     if (weight > weight_max)
1414 root 1.38 break;
1415     }
1416     }
1417    
1418     value = min (value, value_max);
1419    
1420     uint64 count = value / large->value;
1421     int large_nuggets = count;
1422     value -= count * large->value;
1423    
1424     count = value / small->value;
1425     int small_nuggets = count;
1426 root 1.5
1427 root 1.8 /* Insert all the nuggets at one time. This probably saves time, but
1428     * it also prevents us from alcheming nuggets that were just created
1429     * with this spell.
1430     */
1431 root 1.38 update_map (op, mp, small_nuggets, small, large_nuggets, large, nx, ny);
1432    
1433     if (weight > weight_max)
1434     goto bailout;
1435 root 1.8 }
1436     }
1437 root 1.17
1438 root 1.38 bailout:
1439 root 1.17 large->destroy ();
1440     small->destroy ();
1441 root 1.8 return 1;
1442 elmex 1.1 }
1443    
1444    
1445     /* This function removes the cursed/damned status on equipped
1446     * items.
1447     */
1448 root 1.8 int
1449     remove_curse (object *op, object *caster, object *spell)
1450     {
1451     object *tmp;
1452     int success = 0, was_one = 0;
1453    
1454     for (tmp = op->inv; tmp; tmp = tmp->below)
1455     if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1456     ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1457     (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1458     {
1459     was_one++;
1460     if (tmp->level <= caster_level (caster, spell))
1461     {
1462     success++;
1463     if (QUERY_FLAG (spell, FLAG_DAMNED))
1464     CLEAR_FLAG (tmp, FLAG_DAMNED);
1465    
1466     CLEAR_FLAG (tmp, FLAG_CURSED);
1467     CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1468     tmp->value = 0; /* Still can't sell it */
1469     if (op->type == PLAYER)
1470     esrv_send_item (op, tmp);
1471     }
1472     }
1473    
1474     if (op->type == PLAYER)
1475     {
1476     if (success)
1477 root 1.38 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now.");
1478 root 1.8 else
1479     {
1480     if (was_one)
1481     new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse.");
1482     else
1483     new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items.");
1484 root 1.5 }
1485 elmex 1.1 }
1486 root 1.21
1487 root 1.8 return success;
1488 elmex 1.1 }
1489    
1490     /* Identifies objects in the players inventory/on the ground */
1491    
1492 root 1.8 int
1493     cast_identify (object *op, object *caster, object *spell)
1494     {
1495     object *tmp;
1496     int success = 0, num_ident;
1497    
1498     num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1499    
1500     if (num_ident < 1)
1501     num_ident = 1;
1502    
1503     for (tmp = op->inv; tmp; tmp = tmp->below)
1504     {
1505     if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1506     {
1507     identify (tmp);
1508 root 1.21
1509 root 1.8 if (op->type == PLAYER)
1510     {
1511 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "You identified: %s.", long_desc (tmp, op));
1512 root 1.21
1513 root 1.8 if (tmp->msg)
1514     {
1515     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1516     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1517 root 1.5 }
1518     }
1519 root 1.21
1520 root 1.8 num_ident--;
1521     success = 1;
1522     if (!num_ident)
1523     break;
1524 root 1.5 }
1525 elmex 1.1 }
1526 root 1.21
1527 root 1.8 /* If all the power of the spell has been used up, don't go and identify
1528     * stuff on the floor. Only identify stuff on the floor if the spell
1529     * was not fully used.
1530     */
1531     if (num_ident)
1532     {
1533 root 1.48 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1534 root 1.8 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1535     {
1536 root 1.21 identify (tmp);
1537 root 1.8
1538     if (op->type == PLAYER)
1539     {
1540 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "On the ground you identified: %s.", long_desc (tmp, op));
1541 root 1.21
1542 root 1.8 if (tmp->msg)
1543     {
1544     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1545     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1546     }
1547 root 1.21
1548 root 1.8 esrv_send_item (op, tmp);
1549     }
1550 root 1.21
1551 root 1.5 num_ident--;
1552 root 1.8 success = 1;
1553     if (!num_ident)
1554     break;
1555     }
1556     }
1557 root 1.21
1558 root 1.8 if (!success)
1559     new_draw_info (NDI_UNIQUE, 0, op, "You can't reach anything unidentified.");
1560     else
1561 root 1.21 spell_effect (spell, op->x, op->y, op->map, op);
1562    
1563 root 1.8 return success;
1564 elmex 1.1 }
1565    
1566 root 1.8 int
1567     cast_detection (object *op, object *caster, object *spell, object *skill)
1568     {
1569     object *tmp, *last, *god, *detect;
1570     int done_one, range, mflags, floor, level;
1571     sint16 x, y, nx, ny;
1572 root 1.13 maptile *m;
1573 root 1.8
1574     /* We precompute some values here so that we don't have to keep
1575     * doing it over and over again.
1576     */
1577     god = find_god (determine_god (op));
1578     level = caster_level (caster, spell);
1579     range = spell->range + SP_level_range_adjust (caster, spell);
1580    
1581     if (!skill)
1582     skill = caster;
1583    
1584     for (x = op->x - range; x <= op->x + range; x++)
1585     for (y = op->y - range; y <= op->y + range; y++)
1586     {
1587     m = op->map;
1588     mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1589     if (mflags & P_OUT_OF_MAP)
1590     continue;
1591    
1592     /* For most of the detections, we only detect objects above the
1593     * floor. But this is not true for show invisible.
1594     * Basically, we just go and find the top object and work
1595     * down - that is easier than working up.
1596     */
1597 elmex 1.1
1598 root 1.22 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above)
1599 root 1.8 last = tmp;
1600 root 1.21
1601 root 1.8 /* Shouldn't happen, but if there are no objects on a space, this
1602     * would happen.
1603     */
1604     if (!last)
1605     continue;
1606 elmex 1.1
1607 root 1.8 done_one = 0;
1608     floor = 0;
1609     detect = NULL;
1610     for (tmp = last; tmp; tmp = tmp->below)
1611     {
1612     /* show invisible */
1613     if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) &&
1614 root 1.21 /* Might there be other objects that we can make visible? */
1615 root 1.8 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) ||
1616     (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) ||
1617     tmp->type == CF_HANDLE ||
1618     tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
1619     tmp->type == BUTTON || tmp->type == TELEPORTER ||
1620     tmp->type == GATE || tmp->type == LOCKED_DOOR ||
1621     tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
1622     tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
1623     tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR)))
1624     {
1625     if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1626     {
1627     tmp->invisible = 0;
1628     done_one = 1;
1629     }
1630     }
1631 root 1.21
1632 root 1.8 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1633     floor = 1;
1634 elmex 1.1
1635 root 1.8 /* All detections below this point don't descend beneath the floor,
1636     * so just continue on. We could be clever and look at the type of
1637     * detection to completely break out if we don't care about objects beneath
1638     * the floor, but once we get to the floor, not likely a very big issue anyways.
1639     */
1640     if (floor)
1641     continue;
1642 root 1.5
1643 root 1.8 /* I had thought about making detect magic and detect curse
1644     * show the flash the magic item like it does for detect monster.
1645     * however, if the object is within sight, this would then make it
1646     * difficult to see what object is magical/cursed, so the
1647     * effect wouldn't be as apparant.
1648 root 1.5 */
1649    
1650 root 1.8 /* detect magic */
1651     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1652     !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1653     {
1654     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1655     /* make runes more visibile */
1656     if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1657     tmp->stats.Cha /= 4;
1658     done_one = 1;
1659     }
1660     /* detect monster */
1661     if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1662     {
1663     done_one = 2;
1664     if (!detect)
1665     detect = tmp;
1666     }
1667     /* Basically, if race is set in the spell, then the creatures race must
1668     * match that. if the spell race is set to GOD, then the gods opposing
1669     * race must match.
1670 root 1.5 */
1671 root 1.8 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1672     ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) ||
1673     (strstr (spell->race, tmp->race))))
1674     {
1675     done_one = 2;
1676     if (!detect)
1677     detect = tmp;
1678     }
1679     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1680     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1681     {
1682     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1683     done_one = 1;
1684     }
1685     } /* for stack of objects on this space */
1686 root 1.5
1687 root 1.8 /* Code here puts an effect of the spell on the space, so you can see
1688     * where the magic is.
1689     */
1690     if (done_one)
1691     {
1692     object *detect_ob = arch_to_object (spell->other_arch);
1693    
1694     /* if this is set, we want to copy the face */
1695     if (done_one == 2 && detect)
1696     {
1697     detect_ob->face = detect->face;
1698     detect_ob->animation_id = detect->animation_id;
1699     detect_ob->anim_speed = detect->anim_speed;
1700     detect_ob->last_anim = 0;
1701     /* by default, the detect_ob is already animated */
1702     if (!QUERY_FLAG (detect, FLAG_ANIMATE))
1703     CLEAR_FLAG (detect_ob, FLAG_ANIMATE);
1704     }
1705 root 1.27
1706     m->insert (detect_ob, nx, ny, op);
1707 root 1.8 }
1708     } /* for processing the surrounding spaces */
1709 root 1.5
1710    
1711 root 1.8 /* Now process objects in the players inventory if detect curse or magic */
1712     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL))
1713     {
1714     done_one = 0;
1715     for (tmp = op->inv; tmp; tmp = tmp->below)
1716     {
1717     if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1718     {
1719     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL))
1720     {
1721     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1722     if (op->type == PLAYER)
1723     esrv_send_item (op, tmp);
1724 root 1.5 }
1725 root 1.8 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1726     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1727     {
1728     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1729     if (op->type == PLAYER)
1730     esrv_send_item (op, tmp);
1731 root 1.5 }
1732 root 1.8 } /* if item is not identified */
1733     } /* for the players inventory */
1734     } /* if detect magic/curse and object is a player */
1735     return 1;
1736 elmex 1.1 }
1737    
1738    
1739     /**
1740     * Checks if victim has overcharged mana. caster_level is the caster's (skill)
1741     * level whos spell did cause the overcharge.
1742     */
1743 root 1.8 static void
1744     charge_mana_effect (object *victim, int caster_level)
1745 elmex 1.1 {
1746    
1747 root 1.8 /* Prevent explosions for objects without mana. Without this check, doors
1748     * will explode, too.
1749     */
1750     if (victim->stats.maxsp <= 0)
1751     return;
1752 elmex 1.1
1753 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
1754 elmex 1.1
1755 root 1.8 if (victim->stats.sp >= victim->stats.maxsp * 2)
1756     {
1757     object *tmp;
1758 elmex 1.1
1759 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
1760 elmex 1.1
1761 root 1.8 /* Explodes a fireball centered at player */
1762     tmp = get_archetype (EXPLODING_FIREBALL);
1763     tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
1764     tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
1765 root 1.27
1766     tmp->insert_at (victim);
1767 root 1.8 victim->stats.sp = 2 * victim->stats.maxsp;
1768 elmex 1.1 }
1769 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
1770 root 1.27 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode.");
1771 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
1772 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
1773 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
1774     {
1775     new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
1776     confuse_player (victim, victim, 99);
1777 elmex 1.1 }
1778 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.25)
1779 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You start hearing voices.");
1780 elmex 1.1 }
1781    
1782     /* cast_transfer
1783     * This spell transfers sp from the player to another person.
1784     * We let the target go above their normal maximum SP.
1785     */
1786    
1787 root 1.8 int
1788     cast_transfer (object *op, object *caster, object *spell, int dir)
1789     {
1790     object *plyr = NULL;
1791     sint16 x, y;
1792 root 1.13 maptile *m;
1793 root 1.8 int mflags;
1794    
1795     m = op->map;
1796     x = op->x + freearr_x[dir];
1797     y = op->y + freearr_y[dir];
1798    
1799     mflags = get_map_flags (m, &m, x, y, &x, &y);
1800    
1801     if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
1802     {
1803 root 1.22 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above)
1804 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1805     break;
1806 elmex 1.1 }
1807    
1808    
1809 root 1.8 /* If we did not find a player in the specified direction, transfer
1810     * to anyone on top of us. This is used for the rune of transference mostly.
1811     */
1812     if (plyr == NULL)
1813 root 1.22 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
1814 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1815     break;
1816 elmex 1.1
1817 root 1.8 if (!plyr)
1818     {
1819     new_draw_info (NDI_BLACK, 0, op, "There is no one there.");
1820     return 0;
1821 elmex 1.1 }
1822 root 1.8 /* give sp */
1823     if (spell->stats.dam > 0)
1824     {
1825     plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
1826     charge_mana_effect (plyr, caster_level (caster, spell));
1827     return 1;
1828 elmex 1.1 }
1829 root 1.8 /* suck sp away. Can't suck sp from yourself */
1830     else if (op != plyr)
1831     {
1832     /* old dragin magic used floats. easier to just use ints and divide by 100 */
1833    
1834     int rate = -spell->stats.dam + SP_level_dam_adjust (caster, spell), sucked;
1835    
1836     if (rate > 95)
1837     rate = 95;
1838    
1839     sucked = (plyr->stats.sp * rate) / 100;
1840     plyr->stats.sp -= sucked;
1841     if (QUERY_FLAG (op, FLAG_ALIVE))
1842     {
1843     /* Player doesn't get full credit */
1844     sucked = (sucked * rate) / 100;
1845     op->stats.sp += sucked;
1846     if (sucked > 0)
1847     {
1848     charge_mana_effect (op, caster_level (caster, spell));
1849 root 1.5 }
1850     }
1851 root 1.8 return 1;
1852 elmex 1.1 }
1853 root 1.8 return 0;
1854 elmex 1.1 }
1855    
1856    
1857     /* counterspell: nullifies spell effects.
1858     * op is the counterspell object, dir is the direction
1859     * it was cast in.
1860     * Basically, if the object has a magic attacktype,
1861     * this may nullify it.
1862     */
1863 root 1.8 void
1864     counterspell (object *op, int dir)
1865 elmex 1.1 {
1866 root 1.8 object *tmp, *head, *next;
1867     int mflags;
1868 root 1.13 maptile *m;
1869 root 1.8 sint16 sx, sy;
1870    
1871     sx = op->x + freearr_x[dir];
1872     sy = op->y + freearr_y[dir];
1873     m = op->map;
1874     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1875     if (mflags & P_OUT_OF_MAP)
1876     return;
1877 elmex 1.1
1878 root 1.22 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next)
1879 root 1.8 {
1880     next = tmp->above;
1881 elmex 1.1
1882 root 1.8 /* Need to look at the head object - otherwise, if tmp
1883     * points to a monster, we don't have all the necessary
1884     * info for it.
1885     */
1886     if (tmp->head)
1887     head = tmp->head;
1888     else
1889     head = tmp;
1890    
1891     /* don't attack our own spells */
1892     if (tmp->owner && tmp->owner == op->owner)
1893     continue;
1894    
1895     /* Basically, if the object is magical and not counterspell,
1896     * we will more or less remove the object. Don't counterspell
1897     * monsters either.
1898     */
1899 elmex 1.1
1900 elmex 1.44 if (head->attacktype & AT_MAGIC
1901     && !(head->attacktype & AT_COUNTERSPELL)
1902     && !QUERY_FLAG (head, FLAG_MONSTER)
1903     && (op->level > head->level))
1904 root 1.17 head->destroy ();
1905 root 1.8 else
1906     switch (head->type)
1907     {
1908     case SPELL_EFFECT:
1909 elmex 1.44 // XXX: Don't affect floor spelleffects. See also XXX comment
1910     // about sanctuary in spell_util.C
1911     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1912     continue;
1913    
1914 root 1.8 if (op->level > head->level)
1915 root 1.17 head->destroy ();
1916    
1917 root 1.5 break;
1918    
1919 root 1.8 /* I really don't get this rune code that much - that
1920     * random chance seems really low.
1921     */
1922     case RUNE:
1923     if (rndm (0, 149) == 0)
1924     {
1925     head->stats.hp--; /* weaken the rune */
1926     if (!head->stats.hp)
1927 root 1.17 head->destroy ();
1928 root 1.8 }
1929 root 1.5 break;
1930 root 1.8 }
1931 elmex 1.1 }
1932     }
1933    
1934    
1935    
1936     /* cast_consecrate() - a spell to make an altar your god's */
1937 root 1.8 int
1938     cast_consecrate (object *op, object *caster, object *spell)
1939     {
1940     char buf[MAX_BUF];
1941 elmex 1.1
1942 root 1.8 object *tmp, *god = find_god (determine_god (op));
1943 elmex 1.1
1944 root 1.8 if (!god)
1945     {
1946     new_draw_info (NDI_UNIQUE, 0, op, "You can't consecrate anything if you don't worship a god!");
1947     return 0;
1948 elmex 1.1 }
1949 root 1.8
1950     for (tmp = op->below; tmp; tmp = tmp->below)
1951     {
1952     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1953     break;
1954     if (tmp->type == HOLY_ALTAR)
1955     {
1956    
1957     if (tmp->level > caster_level (caster, spell))
1958     {
1959     new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name);
1960     return 0;
1961     }
1962     else
1963     {
1964     /* If we got here, we are consecrating an altar */
1965     sprintf (buf, "Altar of %s", &god->name);
1966     tmp->name = buf;
1967     tmp->level = caster_level (caster, spell);
1968     tmp->other_arch = god->arch;
1969     if (op->type == PLAYER)
1970     esrv_update_item (UPD_NAME, op, tmp);
1971     new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
1972     return 1;
1973 root 1.5 }
1974     }
1975 elmex 1.1 }
1976 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You are not standing over an altar!");
1977     return 0;
1978 elmex 1.1 }
1979    
1980     /* animate_weapon -
1981     * Generalization of staff_to_snake. Makes a golem out of the caster's weapon.
1982     * The golem is based on the archetype specified, modified by the caster's level
1983     * and the attributes of the weapon. The weapon is inserted in the golem's
1984     * inventory so that it falls to the ground when the golem dies.
1985     * This code was very odd - code early on would only let players use the spell,
1986     * yet the code wass full of player checks. I've presumed that the code
1987     * that only let players use it was correct, and removed all the other
1988     * player checks. MSW 2003-01-06
1989     */
1990 root 1.8 int
1991     animate_weapon (object *op, object *caster, object *spell, int dir)
1992     {
1993     object *weapon, *tmp;
1994     char buf[MAX_BUF];
1995     int a, i;
1996     sint16 x, y;
1997 root 1.13 maptile *m;
1998 root 1.8 materialtype_t *mt;
1999    
2000     if (!spell->other_arch)
2001     {
2002     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
2003     LOG (llevError, "animate_weapon failed: spell %s missing other_arch!\n", &spell->name);
2004     return 0;
2005 elmex 1.1 }
2006 root 1.8 /* exit if it's not a player using this spell. */
2007     if (op->type != PLAYER)
2008     return 0;
2009 elmex 1.1
2010 root 1.8 /* if player already has a golem, abort */
2011 root 1.49 if (object *golem = op->contr->golem)
2012 root 1.8 {
2013 root 1.46 control_golem (golem, dir);
2014 root 1.8 return 0;
2015 elmex 1.1 }
2016    
2017 root 1.8 /* if no direction specified, pick one */
2018     if (!dir)
2019     dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9);
2020    
2021     m = op->map;
2022     x = op->x + freearr_x[dir];
2023     y = op->y + freearr_y[dir];
2024    
2025     /* if there's no place to put the golem, abort */
2026     if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) ||
2027 root 1.57 ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type))
2028 root 1.8 {
2029     new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
2030     return 0;
2031 elmex 1.1 }
2032    
2033 root 1.8 /* Use the weapon marked by the player. */
2034     weapon = find_marked_object (op);
2035 elmex 1.1
2036 root 1.8 if (!weapon)
2037     {
2038     new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!");
2039     return 0;
2040     }
2041 root 1.56 if (spell->race && strcmp (weapon->arch->archname, spell->race))
2042 root 1.8 {
2043     new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon.");
2044     return 0;
2045     }
2046     if (weapon->type != WEAPON)
2047     {
2048     new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it.");
2049     return 0;
2050 elmex 1.1 }
2051 root 1.8 if (QUERY_FLAG (weapon, FLAG_APPLIED))
2052     {
2053     new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon));
2054     return 0;
2055 elmex 1.1 }
2056 root 1.8
2057     if (weapon->nrof > 1)
2058     {
2059     tmp = get_split_ob (weapon, 1);
2060     esrv_send_item (op, weapon);
2061     weapon = tmp;
2062     }
2063    
2064     /* create the golem object */
2065     tmp = arch_to_object (spell->other_arch);
2066    
2067     /* if animated by a player, give the player control of the golem */
2068     CLEAR_FLAG (tmp, FLAG_MONSTER);
2069     tmp->stats.exp = 0;
2070     add_friendly_object (tmp);
2071     tmp->type = GOLEM;
2072 root 1.19 tmp->set_owner (op);
2073 root 1.49 op->contr->golem = tmp;
2074 root 1.46 set_spell_skill (op, caster, spell, tmp);
2075 root 1.8
2076     /* Give the weapon to the golem now. A bit of a hack to check the
2077     * removed flag - it should only be set if get_split_object was
2078     * used above.
2079     */
2080     if (!QUERY_FLAG (weapon, FLAG_REMOVED))
2081 root 1.16 weapon->remove ();
2082 root 1.46
2083 root 1.8 insert_ob_in_ob (weapon, tmp);
2084     esrv_send_item (op, weapon);
2085     /* To do everything necessary to let a golem use the weapon is a pain,
2086     * so instead, just set it as equipped (otherwise, we need to update
2087     * body_info, skills, etc)
2088     */
2089     SET_FLAG (tmp, FLAG_USE_WEAPON);
2090     SET_FLAG (weapon, FLAG_APPLIED);
2091 root 1.24 tmp->update_stats ();
2092 root 1.8
2093     /* There used to be 'odd' code that basically seemed to take the absolute
2094     * value of the weapon->magic an use that. IMO, that doesn't make sense -
2095     * if you're using a crappy weapon, it shouldn't be as good.
2096     */
2097    
2098     /* modify weapon's animated wc */
2099     tmp->stats.wc = tmp->stats.wc - SP_level_range_adjust (caster, spell) - 5 * weapon->stats.Dex - 2 * weapon->stats.Str - weapon->magic;
2100     if (tmp->stats.wc < -127)
2101     tmp->stats.wc = -127;
2102    
2103     /* Modify hit points for weapon */
2104     tmp->stats.maxhp = tmp->stats.maxhp + spell->duration +
2105     SP_level_duration_adjust (caster, spell) + +8 * weapon->magic + 12 * weapon->stats.Con;
2106     if (tmp->stats.maxhp < 0)
2107     tmp->stats.maxhp = 10;
2108     tmp->stats.hp = tmp->stats.maxhp;
2109    
2110     /* Modify weapon's damage */
2111     tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell) + weapon->stats.dam + weapon->magic + 5 * weapon->stats.Str;
2112     if (tmp->stats.dam < 0)
2113     tmp->stats.dam = 127;
2114    
2115    
2116     /* attacktype */
2117     if (!tmp->attacktype)
2118     tmp->attacktype = AT_PHYSICAL;
2119    
2120     mt = NULL;
2121     if (op->materialname != NULL)
2122     mt = name_to_material (op->materialname);
2123     if (mt != NULL)
2124     {
2125     for (i = 0; i < NROFATTACKS; i++)
2126     tmp->resist[i] = 50 - (mt->save[i] * 5);
2127     a = mt->save[0];
2128 elmex 1.1 }
2129 root 1.8 else
2130     {
2131     for (i = 0; i < NROFATTACKS; i++)
2132     tmp->resist[i] = 5;
2133     a = 10;
2134     }
2135     /* Set weapon's immunity */
2136     tmp->resist[ATNR_CONFUSION] = 100;
2137     tmp->resist[ATNR_POISON] = 100;
2138     tmp->resist[ATNR_SLOW] = 100;
2139     tmp->resist[ATNR_PARALYZE] = 100;
2140     tmp->resist[ATNR_TURN_UNDEAD] = 100;
2141     tmp->resist[ATNR_FEAR] = 100;
2142     tmp->resist[ATNR_DEPLETE] = 100;
2143     tmp->resist[ATNR_DEATH] = 100;
2144     tmp->resist[ATNR_BLIND] = 100;
2145    
2146     /* Improve weapon's armour value according to best save vs. physical of its material */
2147    
2148     if (a > 14)
2149     a = 14;
2150     tmp->resist[ATNR_PHYSICAL] = 100 - (int) ((100.0 - (float) tmp->resist[ATNR_PHYSICAL]) / (30.0 - 2.0 * a));
2151    
2152     /* Determine golem's speed */
2153 root 1.26 tmp->set_speed (min (3.33, 0.4 + 0.1 * SP_level_range_adjust (caster, spell)));
2154 root 1.8
2155     if (!spell->race)
2156     {
2157     sprintf (buf, "animated %s", &weapon->name);
2158     tmp->name = buf;
2159    
2160     tmp->face = weapon->face;
2161     tmp->animation_id = weapon->animation_id;
2162     tmp->anim_speed = weapon->anim_speed;
2163     tmp->last_anim = weapon->last_anim;
2164     tmp->state = weapon->state;
2165 root 1.26 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE];
2166 elmex 1.1 }
2167    
2168 root 1.8 /* make experience increase in proportion to the strength of the summoned creature. */
2169     tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / caster_level (caster, spell));
2170    
2171     tmp->speed_left = -1;
2172     tmp->direction = dir;
2173 root 1.27
2174     m->insert (tmp, x, y, op);
2175 root 1.8 return 1;
2176 elmex 1.1 }
2177    
2178     /* cast_daylight() - changes the map darkness level *lower* */
2179    
2180     /* cast_change_map_lightlevel: Was cast_daylight/nightfall.
2181     * This changes the light level for the entire map.
2182     */
2183    
2184 root 1.8 int
2185     cast_change_map_lightlevel (object *op, object *caster, object *spell)
2186     {
2187     int success;
2188 elmex 1.1
2189 root 1.8 if (!op->map)
2190     return 0; /* shouldnt happen */
2191 elmex 1.1
2192 root 1.28 success = op->map->change_map_light (spell->stats.dam);
2193    
2194 root 1.8 if (!success)
2195     {
2196     if (spell->stats.dam < 0)
2197     new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here.");
2198     else
2199     new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here.");
2200 elmex 1.1 }
2201 root 1.8 return success;
2202 elmex 1.1 }
2203    
2204    
2205    
2206    
2207    
2208     /* create an aura spell object and put it in the player's inventory.
2209     * as usual, op is player, caster is the object casting the spell,
2210     * spell is the spell object itself.
2211     */
2212 root 1.8 int
2213     create_aura (object *op, object *caster, object *spell)
2214 elmex 1.1 {
2215 root 1.8 int refresh = 0;
2216     object *new_aura;
2217 elmex 1.1
2218 root 1.8 new_aura = present_arch_in_ob (spell->other_arch, op);
2219     if (new_aura)
2220     refresh = 1;
2221     else
2222     new_aura = arch_to_object (spell->other_arch);
2223    
2224     new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell);
2225    
2226     new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2227    
2228 root 1.19 new_aura->set_owner (op);
2229 root 1.8 set_spell_skill (op, caster, spell, new_aura);
2230     new_aura->attacktype = spell->attacktype;
2231    
2232     new_aura->level = caster_level (caster, spell);
2233     if (refresh)
2234     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2235     else
2236     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2237     insert_ob_in_ob (new_aura, op);
2238     return 1;
2239 elmex 1.1 }
2240    
2241    
2242     /* move aura function. An aura is a part of someone's inventory,
2243     * which he carries with him, but which acts on the map immediately
2244     * around him.
2245     * Aura parameters:
2246     * duration: duration counter.
2247     * attacktype: aura's attacktype
2248     * other_arch: archetype to drop where we attack
2249     */
2250    
2251 root 1.8 void
2252     move_aura (object *aura)
2253     {
2254     int i, mflags;
2255     object *env;
2256 root 1.13 maptile *m;
2257 root 1.8
2258     /* auras belong in inventories */
2259     env = aura->env;
2260    
2261     /* no matter what we've gotta remove the aura...
2262     * we'll put it back if its time isn't up.
2263     */
2264 root 1.16 aura->remove ();
2265 root 1.8
2266     /* exit if we're out of gas */
2267     if (aura->duration-- < 0)
2268     {
2269 root 1.17 aura->destroy ();
2270 root 1.8 return;
2271     }
2272    
2273     /* auras only exist in inventories */
2274     if (env == NULL || env->map == NULL)
2275     {
2276 root 1.17 aura->destroy ();
2277 root 1.8 return;
2278     }
2279 root 1.17
2280 root 1.8 /* we need to jump out of the inventory for a bit
2281     * in order to hit the map conveniently.
2282     */
2283 root 1.27 aura->insert_at (env, aura);
2284 root 1.8
2285     for (i = 1; i < 9; i++)
2286     {
2287     sint16 nx, ny;
2288    
2289     nx = aura->x + freearr_x[i];
2290     ny = aura->y + freearr_y[i];
2291     mflags = get_map_flags (env->map, &m, nx, ny, &nx, &ny);
2292    
2293     /* Consider the movement tyep of the person with the aura as
2294     * movement type of the aura. Eg, if the player is flying, the aura
2295     * is flying also, if player is walking, it is on the ground, etc.
2296     */
2297     if (!(mflags & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (env, GET_MAP_MOVE_BLOCK (m, nx, ny))))
2298 elmex 1.6 {
2299 root 1.8 hit_map (aura, i, aura->attacktype, 0);
2300 root 1.5
2301 root 1.8 if (aura->other_arch)
2302 root 1.27 m->insert (arch_to_object (aura->other_arch), nx, ny, aura);
2303 root 1.5 }
2304 elmex 1.1 }
2305 root 1.27
2306 root 1.8 /* put the aura back in the player's inventory */
2307 root 1.16 aura->remove ();
2308 root 1.8 insert_ob_in_ob (aura, env);
2309 elmex 1.1 }
2310    
2311     /* moves the peacemaker spell.
2312     * op is the piece object.
2313 root 1.8 */
2314 elmex 1.1
2315 root 1.8 void
2316     move_peacemaker (object *op)
2317     {
2318     object *tmp;
2319 elmex 1.1
2320 root 1.22 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2321 root 1.8 {
2322     int atk_lev, def_lev;
2323     object *victim = tmp;
2324 elmex 1.1
2325 root 1.8 if (tmp->head)
2326     victim = tmp->head;
2327     if (!QUERY_FLAG (victim, FLAG_MONSTER))
2328     continue;
2329     if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
2330     continue;
2331     if (victim->stats.exp == 0)
2332     continue;
2333 elmex 1.1
2334 root 1.8 def_lev = MAX (1, victim->level);
2335     atk_lev = MAX (1, op->level);
2336 elmex 1.1
2337 root 1.8 if (rndm (0, atk_lev - 1) > def_lev)
2338     {
2339     /* make this sucker peaceful. */
2340 elmex 1.1
2341 root 1.19 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2342 root 1.8 victim->stats.exp = 0;
2343 elmex 1.1 #if 0
2344 root 1.8 /* No idea why these were all set to zero - if something
2345     * makes this creature agressive, he should still do damage.
2346     */
2347     victim->stats.dam = 0;
2348     victim->stats.sp = 0;
2349     victim->stats.grace = 0;
2350     victim->stats.Pow = 0;
2351 elmex 1.1 #endif
2352 root 1.8 victim->attack_movement = RANDO2;
2353     SET_FLAG (victim, FLAG_UNAGGRESSIVE);
2354     SET_FLAG (victim, FLAG_RUN_AWAY);
2355     SET_FLAG (victim, FLAG_RANDOM_MOVE);
2356     CLEAR_FLAG (victim, FLAG_MONSTER);
2357     if (victim->name)
2358     {
2359     new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2360 root 1.5 }
2361     }
2362 elmex 1.1 }
2363 root 1.8 }
2364    
2365 elmex 1.1
2366     /* This writes a rune that contains the appropriate message.
2367     * There really isn't any adjustments we make.
2368     */
2369    
2370 root 1.8 int
2371     write_mark (object *op, object *spell, const char *msg)
2372     {
2373     char rune[HUGE_BUF];
2374     object *tmp;
2375 elmex 1.1
2376 root 1.8 if (!msg || msg[0] == 0)
2377     {
2378     new_draw_info (NDI_UNIQUE, 0, op, "Write what?");
2379     return 0;
2380 elmex 1.1 }
2381    
2382 root 1.8 if (strcasestr_local (msg, "endmsg"))
2383     {
2384     new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?");
2385     LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg);
2386     return 0;
2387 elmex 1.1 }
2388 root 1.8 if (!spell->other_arch)
2389     return 0;
2390     tmp = arch_to_object (spell->other_arch);
2391 root 1.9
2392     snprintf (rune, sizeof (rune), "%s\n", msg);
2393    
2394 root 1.8 tmp->race = op->name; /*Save the owner of the rune */
2395     tmp->msg = rune;
2396 root 1.27
2397     tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2398 root 1.8 return 1;
2399 elmex 1.1 }