ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.59
Committed: Sun Jun 10 10:16:04 2007 UTC (16 years, 11 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.58: +5 -1 lines
Log Message:
fixed create food spell a bit to have less dependency on
archetype order

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