ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.65
Committed: Wed Aug 1 00:26:04 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.64: +3 -2 lines
Log Message:
allow exploding thingy effect

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.62 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.35 *
13 root 1.62 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.35 *
18 root 1.62 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.54 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.35 */
23 elmex 1.1
24     #include <global.h>
25     #include <object.h>
26     #include <living.h>
27 root 1.36 #include <sproto.h>
28 elmex 1.1 #include <spells.h>
29     #include <sounds.h>
30    
31     /* cast_magic_storm: This is really used mostly for spell
32     * fumbles at the like. tmp is the object to propogate.
33     * op is what is casting this.
34     */
35 root 1.8 void
36     cast_magic_storm (object *op, object *tmp, int lvl)
37 elmex 1.1 {
38 root 1.8 if (!tmp)
39     return; /* error */
40 root 1.27
41 root 1.8 tmp->level = op->level;
42     tmp->range += lvl / 5; /* increase the area of destruction */
43     tmp->duration += lvl / 5;
44    
45     /* Put a cap on duration for this - if the player fails in their
46     * apartment, don't want it to go on so long that it kills them
47     * multiple times. Also, damge already increases with level,
48     * so don't really need to increase the duration as much either.
49     */
50     if (tmp->duration >= 40)
51     tmp->duration = 40;
52 root 1.27
53 root 1.8 tmp->stats.dam = lvl; /* nasty recoils! */
54     tmp->stats.maxhp = tmp->count; /* tract single parent */
55 elmex 1.1
56 root 1.27 tmp->insert_at (op, op);
57 elmex 1.1 }
58    
59 root 1.8 int
60     recharge (object *op, object *caster, object *spell_ob)
61     {
62     object *wand, *tmp;
63     int ncharges;
64    
65     wand = find_marked_object (op);
66     if (wand == NULL || wand->type != WAND)
67     {
68     new_draw_info (NDI_UNIQUE, 0, op, "You need to mark the wand you want to recharge.");
69     return 0;
70 elmex 1.1 }
71 root 1.8 if (!(random_roll (0, 3, op, PREFER_HIGH)))
72     {
73     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s vibrates violently, then explodes!", query_name (wand));
74 root 1.64 op->play_sound (sound_find ("ob_explode"));
75 root 1.8 esrv_del_item (op->contr, wand->count);
76 root 1.17 wand->destroy ();
77 root 1.8 tmp = get_archetype ("fireball");
78     tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10;
79 root 1.27
80 root 1.8 if (!tmp->stats.dam)
81     tmp->stats.dam = 1;
82 root 1.27
83 root 1.8 tmp->stats.hp = tmp->stats.dam / 2;
84 root 1.27
85 root 1.8 if (tmp->stats.hp < 2)
86     tmp->stats.hp = 2;
87 root 1.27
88     tmp->insert_at (op);
89 root 1.8 return 1;
90     }
91    
92     ncharges = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob));
93 root 1.27
94 root 1.8 if (wand->inv && wand->inv->level)
95     ncharges /= wand->inv->level;
96     else
97     {
98     new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", query_name (wand));
99     return 0;
100 elmex 1.1 }
101 root 1.27
102 root 1.8 if (!ncharges)
103     ncharges = 1;
104 elmex 1.1
105 root 1.8 wand->stats.food += ncharges;
106     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s glows with power.", query_name (wand));
107 root 1.27
108 root 1.57 if (wand->arch && QUERY_FLAG (wand->arch, FLAG_ANIMATE))
109 root 1.8 {
110     SET_FLAG (wand, FLAG_ANIMATE);
111 root 1.57 wand->set_speed (wand->arch->speed);
112 elmex 1.1 }
113 root 1.26
114 root 1.8 return 1;
115 elmex 1.1 }
116    
117     /* Create a missile (nonmagic - magic +4). Will either create bolts or arrows
118     * based on whether a crossbow or bow is equiped. If neither, it defaults to
119     * arrows.
120     * Sets the plus based on the casters level. It is also settable with the
121     * invoke command. If the caster attempts to create missiles with too
122     * great a plus, the default is used.
123     * The # of arrows created also goes up with level, so if a 30th level mage
124     * wants LOTS of arrows, and doesn't care what the plus is he could
125     * create nonnmagic arrows, or even -1, etc...
126     */
127 root 1.8 int
128     cast_create_missile (object *op, object *caster, object *spell, int dir, const char *stringarg)
129 elmex 1.1 {
130 root 1.8 int missile_plus = 0, bonus_plus = 0;
131     const char *missile_name;
132     object *tmp, *missile;
133    
134     missile_name = "arrow";
135    
136     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
137     if (tmp->type == BOW && QUERY_FLAG (tmp, FLAG_APPLIED))
138 root 1.12 missile_name = tmp->race;
139 elmex 1.1
140 root 1.8 missile_plus = spell->stats.dam + SP_level_dam_adjust (caster, spell);
141 elmex 1.1
142 root 1.10 if (archetype::find (missile_name) == NULL)
143 root 1.8 {
144     LOG (llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
145     return 0;
146     }
147 root 1.12
148 root 1.8 missile = get_archetype (missile_name);
149 elmex 1.1
150 root 1.8 if (stringarg)
151     {
152     /* If it starts with a letter, presume it is a description */
153     if (isalpha (*stringarg))
154     {
155     artifact *al = find_artifactlist (missile->type)->items;
156 elmex 1.1
157 root 1.45 for (; al; al = al->next)
158 root 1.8 if (!strcasecmp (al->item->name, stringarg))
159     break;
160    
161     if (!al)
162     {
163 root 1.17 missile->destroy ();
164 root 1.8 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg);
165     return 0;
166     }
167 root 1.12
168 root 1.8 if (al->item->slaying)
169     {
170 root 1.17 missile->destroy ();
171 root 1.8 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg);
172     return 0;
173     }
174 root 1.12
175 root 1.8 give_artifact_abilities (missile, al->item);
176     /* These special arrows cost something extra. Don't have them also be magical -
177     * otherwise, in most cases, not enough will be created. I don't want to get into
178     * the parsing of having to do both plus and type.
179     */
180     bonus_plus = 1 + (al->item->value / 5);
181     missile_plus = 0;
182     }
183     else if (atoi (stringarg) < missile_plus)
184     missile_plus = atoi (stringarg);
185     }
186 root 1.12
187 root 1.8 if (missile_plus > 4)
188     missile_plus = 4;
189     else if (missile_plus < -4)
190     missile_plus = -4;
191    
192     missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell);
193     missile->nrof -= 3 * (missile_plus + bonus_plus);
194 root 1.12
195 root 1.8 if (missile->nrof < 1)
196     missile->nrof = 1;
197    
198     missile->magic = missile_plus;
199     /* Can't get any money for these objects */
200     missile->value = 0;
201 elmex 1.1
202 root 1.8 SET_FLAG (missile, FLAG_IDENTIFIED);
203 elmex 1.1
204 root 1.12 if (!cast_create_obj (op, caster, missile, dir) && op->type == PLAYER && !missile->destroyed ())
205     pick_up (op, missile);
206    
207 root 1.8 return 1;
208 elmex 1.1 }
209    
210    
211     /* allows the choice of what sort of food object to make.
212     * If stringarg is NULL, it will create food dependent on level --PeterM*/
213 root 1.8 int
214     cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
215 elmex 1.1 {
216 root 1.8 int food_value;
217     archetype *at = NULL;
218     object *new_op;
219    
220     food_value = spell_ob->stats.food + +50 * SP_level_duration_adjust (caster, spell_ob);
221    
222     if (stringarg)
223     {
224     at = find_archetype_by_object_type_name (FOOD, stringarg);
225     if (at == NULL)
226     at = find_archetype_by_object_type_name (DRINK, stringarg);
227 root 1.57 if (at == NULL || at->stats.food > food_value)
228 root 1.8 stringarg = NULL;
229     }
230    
231     if (!stringarg)
232     {
233     archetype *at_tmp;
234    
235     /* We try to find the archetype with the maximum food value.
236     * This removes the dependancy of hard coded food values in this
237     * function, and addition of new food types is automatically added.
238     * We don't use flesh types because the weight values of those need
239     * to be altered from the donor.
240     */
241 root 1.5
242 root 1.8 /* We assume the food items don't have multiple parts */
243 elmex 1.58 for_all_archetypes (at_tmp)
244 root 1.8 {
245 root 1.57 if (at_tmp->type == FOOD || at_tmp->type == DRINK)
246 root 1.8 {
247     /* Basically, if the food value is something that is creatable
248     * under the limits of the spell and it is higher than
249     * the item we have now, take it instead.
250     */
251 elmex 1.59 if (at_tmp->stats.food <= food_value
252     && (!at
253     || at_tmp->stats.food > at->stats.food
254     || (at_tmp->stats.food == at->stats.food
255     && at_tmp->weight < at->weight)))
256 root 1.8 at = at_tmp;
257 root 1.5 }
258     }
259 elmex 1.1 }
260 root 1.65
261 root 1.8 /* Pretty unlikely (there are some very low food items), but you never
262     * know
263     */
264     if (!at)
265     {
266     new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food.");
267     return 0;
268 elmex 1.1 }
269    
270 root 1.57 food_value /= at->stats.food;
271 root 1.8 new_op = arch_to_object (at);
272     new_op->nrof = food_value;
273 elmex 1.1
274 root 1.8 new_op->value = 0;
275     if (new_op->nrof < 1)
276     new_op->nrof = 1;
277 elmex 1.1
278 root 1.8 cast_create_obj (op, caster, new_op, dir);
279     return 1;
280 elmex 1.1 }
281 root 1.8
282     int
283     probe (object *op, object *caster, object *spell_ob, int dir)
284     {
285     int r, mflags, maxrange;
286     object *tmp;
287 root 1.13 maptile *m;
288 elmex 1.1
289    
290 root 1.8 if (!dir)
291     {
292     examine_monster (op, op);
293     return 1;
294 elmex 1.1 }
295 root 1.65
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.65
326 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You detect nothing.");
327     return 1;
328 elmex 1.1 }
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 const char *cp = describe_item (op, op);
575 root 1.10 archetype *at = archetype::find (ARCH_DEPLETION);
576 root 1.8
577 root 1.60 dynbuf_text buf;
578    
579     if (player *pl = op->contr)
580     if (object *race = archetype::find (op->race))
581     buf << "You are a " << (pl->gender ? "female" : "male") << " " << &race->name << ".\n";
582    
583     if (object *god = find_god (determine_god (op)))
584     buf << "You worship " << &god->name << ".\n";
585 root 1.8 else
586 root 1.60 buf << "You worship no god.\n";
587 root 1.8
588 root 1.60 object *tmp = present_arch_in_ob (at, op);
589 root 1.8
590     if (*cp == '\0' && tmp == NULL)
591 root 1.60 buf << "You feel very mundane. ";
592 root 1.8 else
593     {
594 root 1.60 buf << "You have: " << cp << ".\n";
595 root 1.51
596     if (tmp)
597 root 1.60 for (int i = 0; i < NUM_STATS; i++)
598 root 1.51 if (tmp->stats.stat (i) < 0)
599 root 1.60 buf.printf ("Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i));
600 elmex 1.1 }
601    
602 root 1.8 if (is_dragon_pl (op))
603 root 1.60 /* now grab the 'dragon_ability'-force from the player's inventory */
604     for (tmp = op->inv; tmp; tmp = tmp->below)
605     {
606     if (tmp->type == FORCE && !strcmp (tmp->arch->archname, "dragon_ability_force"))
607     {
608     if (tmp->stats.exp == 0)
609     buf << "Your metabolism isn't focused on anything.\n";
610     else
611     buf << "Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n";
612    
613     break;
614     }
615     }
616 root 1.36
617 root 1.61 buf << '\0'; // zero-terminate
618    
619 root 1.60 new_draw_info (NDI_UNIQUE, 0, op, buf.linearise ());
620 root 1.36
621 root 1.8 return 1;
622 elmex 1.1 }
623    
624     /* This creates magic walls. Really, it can create most any object,
625     * within some reason.
626     */
627 root 1.8 int
628     magic_wall (object *op, object *caster, int dir, object *spell_ob)
629     {
630 root 1.27 object *tmp;
631 root 1.8 int i, posblocked, negblocked, maxrange;
632     sint16 x, y;
633 root 1.13 maptile *m;
634 root 1.8 const char *name;
635     archetype *at;
636    
637     if (!dir)
638     {
639     dir = op->facing;
640     x = op->x;
641     y = op->y;
642     }
643     else
644     {
645     x = op->x + freearr_x[dir];
646     y = op->y + freearr_y[dir];
647     }
648 root 1.25
649 root 1.8 m = op->map;
650    
651     if ((spell_ob->move_block || x != op->x || y != op->y) &&
652     (get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE) ||
653     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) == spell_ob->move_block)))
654     {
655     new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
656     return 0;
657     }
658 root 1.25
659 root 1.8 if (spell_ob->other_arch)
660 root 1.25 tmp = arch_to_object (spell_ob->other_arch);
661 root 1.8 else if (spell_ob->race)
662     {
663     char buf1[MAX_BUF];
664    
665     sprintf (buf1, spell_ob->race, dir);
666 root 1.10 at = archetype::find (buf1);
667 root 1.8 if (!at)
668     {
669     LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1);
670     new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken.");
671     return 0;
672 root 1.5 }
673 root 1.27
674 root 1.8 tmp = arch_to_object (at);
675     }
676     else
677     {
678     LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name);
679     return 0;
680     }
681    
682     if (tmp->type == SPELL_EFFECT)
683     {
684     tmp->attacktype = spell_ob->attacktype;
685     tmp->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
686     tmp->stats.dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
687     tmp->range = 0;
688     }
689     else if (QUERY_FLAG (tmp, FLAG_ALIVE))
690     {
691     tmp->stats.hp = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
692     tmp->stats.maxhp = tmp->stats.hp;
693     }
694 root 1.25
695 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG (tmp, FLAG_IS_USED_UP))
696     {
697     tmp->stats.food = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
698     SET_FLAG (tmp, FLAG_IS_USED_UP);
699 elmex 1.1 }
700 root 1.25
701 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_TEAR_DOWN))
702     {
703     tmp->stats.hp = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
704     tmp->stats.maxhp = tmp->stats.hp;
705     SET_FLAG (tmp, FLAG_TEAR_DOWN);
706     SET_FLAG (tmp, FLAG_ALIVE);
707     }
708    
709     /* This can't really hurt - if the object doesn't kill anything,
710 root 1.25 * these fields just won't be used. Do not set the owner for
711     * earthwalls, though, so they survive restarts.
712 root 1.8 */
713 root 1.25 if (tmp->type != EARTHWALL) //TODO
714     tmp->set_owner (op);
715    
716 root 1.8 set_spell_skill (op, caster, spell_ob, tmp);
717     tmp->level = caster_level (caster, spell_ob) / 2;
718 elmex 1.1
719 root 1.8 name = tmp->name;
720 root 1.27 if (!(tmp = m->insert (tmp, x, y, op)))
721 root 1.8 {
722     new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name);
723     return 0;
724 elmex 1.1 }
725 root 1.25
726 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
727 root 1.57 if (tmp->other_arch && tmp->other_arch->type == SPELL)
728 root 1.8 insert_ob_in_ob (arch_to_object (tmp->other_arch), tmp);
729    
730     /* This code causes the wall to extend some distance in
731     * each direction, or until an obstruction is encountered.
732     * posblocked and negblocked help determine how far the
733     * created wall can extend, it won't go extend through
734     * blocked spaces.
735     */
736     maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
737     posblocked = 0;
738     negblocked = 0;
739    
740     for (i = 1; i <= maxrange; i++)
741     {
742     int dir2;
743    
744     dir2 = (dir < 4) ? (dir + 2) : dir - 2;
745    
746     x = tmp->x + i * freearr_x[dir2];
747     y = tmp->y + i * freearr_y[dir2];
748     m = tmp->map;
749    
750     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
751     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !posblocked)
752     {
753 root 1.27 object *tmp2 = tmp->clone ();
754     m->insert (tmp2, x, y, op);
755    
756 root 1.8 /* If this is a spellcasting wall, need to insert the spell object */
757 root 1.57 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
758 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
759 root 1.8
760     }
761     else
762     posblocked = 1;
763    
764     x = tmp->x - i * freearr_x[dir2];
765     y = tmp->y - i * freearr_y[dir2];
766     m = tmp->map;
767    
768     if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
769     ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !negblocked)
770     {
771 root 1.27 object *tmp2 = tmp->clone ();
772     m->insert (tmp2, x, y, op);
773    
774 root 1.57 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
775 root 1.27 tmp2->insert (arch_to_object (tmp2->other_arch));
776 root 1.8 }
777     else
778     negblocked = 1;
779 elmex 1.1 }
780    
781 root 1.8 if (QUERY_FLAG (tmp, FLAG_BLOCKSVIEW))
782     update_all_los (op->map, op->x, op->y);
783 elmex 1.1
784 root 1.8 return 1;
785 elmex 1.1 }
786    
787 root 1.8 int
788     dimension_door (object *op, object *caster, object *spob, int dir)
789     {
790     uint32 dist, maxdist;
791     int mflags;
792 root 1.13 maptile *m;
793 root 1.8 sint16 sx, sy;
794 elmex 1.1
795 root 1.8 if (op->type != PLAYER)
796     return 0;
797 elmex 1.1
798 root 1.8 if (!dir)
799     {
800     new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
801     return 0;
802 elmex 1.1 }
803    
804 root 1.8 /* Given the new outdoor maps, can't let players dimension door for
805     * ever, so put limits in.
806     */
807     maxdist = spob->range + SP_level_range_adjust (caster, spob);
808    
809     if (op->contr->count)
810     {
811     if (op->contr->count > maxdist)
812     {
813     new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!");
814     return 0;
815 root 1.5 }
816    
817 root 1.8 for (dist = 0; dist < op->contr->count; dist++)
818     {
819     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
820 root 1.5
821 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
822     break;
823 root 1.5
824 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
825     break;
826 root 1.5 }
827    
828 root 1.8 if (dist < op->contr->count)
829     {
830     new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n");
831     op->contr->count = 0;
832     return 0;
833     }
834 root 1.27
835 root 1.8 op->contr->count = 0;
836    
837     /* Remove code that puts player on random space on maps. IMO,
838     * a lot of maps probably have areas the player should not get to,
839     * but may not be marked as NO_MAGIC (as they may be bounded
840     * by such squares). Also, there are probably treasure rooms and
841     * lots of other maps that protect areas with no magic, but the
842     * areas themselves don't contain no magic spaces.
843     */
844     /* This call here is really just to normalize the coordinates */
845     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, &sx, &sy);
846     if (mflags & P_IS_ALIVE || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
847     {
848     new_draw_info (NDI_UNIQUE, 0, op, "You cast your spell, but nothing happens.\n");
849     return 1; /* Maybe the penalty should be more severe... */
850 root 1.5 }
851 root 1.8 }
852     else
853     {
854     /* Player didn't specify a distance, so lets see how far
855     * we can move the player. Don't know why this stopped on
856     * spaces that blocked the players view.
857     */
858 root 1.5
859 root 1.8 for (dist = 0; dist < maxdist; dist++)
860     {
861     mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
862 root 1.5
863 root 1.8 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
864     break;
865 root 1.5
866 root 1.8 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
867     break;
868 root 1.5
869     }
870    
871 root 1.8 /* If the destination is blocked, keep backing up until we
872     * find a place for the player.
873     */
874     for (; dist > 0; dist--)
875     {
876     if (get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist,
877     &sx, &sy) & (P_OUT_OF_MAP | P_IS_ALIVE))
878     continue;
879 root 1.5
880    
881 root 1.8 if (!OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
882     break;
883 root 1.5
884     }
885 root 1.8 if (!dist)
886     {
887     new_draw_info (NDI_UNIQUE, 0, op, "Your spell failed!\n");
888     return 0;
889 root 1.5 }
890 elmex 1.1 }
891    
892 root 1.8 /* Actually move the player now */
893 root 1.27 if (!(op = op->map->insert (op, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, op)))
894 root 1.8 return 1;
895 elmex 1.1
896 root 1.8 op->speed_left = -FABS (op->speed) * 5; /* Freeze them for a short while */
897     return 1;
898 elmex 1.1 }
899    
900    
901     /* cast_heal: Heals something.
902     * op is the caster.
903     * dir is the direction he is casting it in.
904     * spell is the spell object.
905     */
906 root 1.8 int
907     cast_heal (object *op, object *caster, object *spell, int dir)
908     {
909     object *tmp;
910     archetype *at;
911     object *poison;
912     int heal = 0, success = 0;
913    
914     tmp = find_target_for_friendly_spell (op, dir);
915    
916 root 1.40 if (!tmp)
917 root 1.8 return 0;
918    
919     /* Figure out how many hp this spell might cure.
920     * could be zero if this spell heals effects, not damage.
921     */
922     heal = spell->stats.dam;
923     if (spell->stats.hp)
924     heal += random_roll (spell->stats.hp, 6, op, PREFER_HIGH) + spell->stats.hp;
925    
926     if (heal)
927     {
928     if (tmp->stats.hp >= tmp->stats.maxhp)
929 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You are already fully healed.");
930 root 1.8 else
931     {
932     /* See how many points we actually heal. Instead of messages
933     * based on type of spell, we instead do messages based
934     * on amount of damage healed.
935     */
936     if (heal > (tmp->stats.maxhp - tmp->stats.hp))
937     heal = tmp->stats.maxhp - tmp->stats.hp;
938     tmp->stats.hp += heal;
939    
940     if (tmp->stats.hp >= tmp->stats.maxhp)
941 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel just fine!");
942 root 1.8 else if (heal > 50)
943 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds close!");
944 root 1.8 else if (heal > 25)
945 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds mostly close.");
946 root 1.8 else if (heal > 10)
947 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to fade.");
948 root 1.8 else
949 root 1.40 new_draw_info (NDI_UNIQUE, 0, tmp, "Your wounds start to close.");
950    
951 root 1.8 success = 1;
952     }
953     }
954 root 1.40
955 root 1.8 if (spell->attacktype & AT_DISEASE)
956     if (cure_disease (tmp, op))
957     success = 1;
958    
959     if (spell->attacktype & AT_POISON)
960     {
961 root 1.10 at = archetype::find ("poisoning");
962 root 1.8 poison = present_arch_in_ob (at, tmp);
963     if (poison)
964     {
965     success = 1;
966     new_draw_info (NDI_UNIQUE, 0, tmp, "Your body feels cleansed");
967     poison->stats.food = 1;
968 root 1.5 }
969 elmex 1.1 }
970 root 1.40
971 root 1.8 if (spell->attacktype & AT_CONFUSION)
972     {
973     poison = present_in_ob_by_name (FORCE, "confusion", tmp);
974     if (poison)
975     {
976     success = 1;
977     new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
978     poison->duration = 1;
979 root 1.5 }
980 elmex 1.1 }
981 root 1.40
982 root 1.8 if (spell->attacktype & AT_BLIND)
983     {
984 root 1.10 at = archetype::find ("blindness");
985 root 1.8 poison = present_arch_in_ob (at, tmp);
986     if (poison)
987     {
988     success = 1;
989     new_draw_info (NDI_UNIQUE, 0, tmp, "Your vision begins to return.");
990     poison->stats.food = 1;
991 root 1.5 }
992 elmex 1.1 }
993 root 1.40
994 root 1.8 if (spell->last_sp && tmp->stats.sp < tmp->stats.maxsp)
995     {
996     tmp->stats.sp += spell->last_sp;
997     if (tmp->stats.sp > tmp->stats.maxsp)
998     tmp->stats.sp = tmp->stats.maxsp;
999     success = 1;
1000     new_draw_info (NDI_UNIQUE, 0, tmp, "Magical energy surges through your body!");
1001     }
1002 root 1.40
1003 root 1.8 if (spell->last_grace && tmp->stats.grace < tmp->stats.maxgrace)
1004     {
1005     tmp->stats.grace += spell->last_grace;
1006     if (tmp->stats.grace > tmp->stats.maxgrace)
1007     tmp->stats.grace = tmp->stats.maxgrace;
1008     success = 1;
1009     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!");
1010 elmex 1.1 }
1011 root 1.40
1012 root 1.8 if (spell->stats.food && tmp->stats.food < 999)
1013     {
1014     tmp->stats.food += spell->stats.food;
1015     if (tmp->stats.food > 999)
1016     tmp->stats.food = 999;
1017     success = 1;
1018     /* We could do something a bit better like the messages for healing above */
1019     new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food");
1020     }
1021 root 1.40
1022 root 1.8 return success;
1023 elmex 1.1 }
1024    
1025     /* This is used for the spells that gain stats. There are no spells
1026     * right now that icnrease wis/int/pow on a temp basis, so no
1027     * good comments for those.
1028     */
1029 root 1.8 static const char *const no_gain_msgs[NUM_STATS] = {
1030     "You grow no stronger.",
1031     "You grow no more agile.",
1032     "You don't feel any healthier.",
1033 root 1.55 "You didn't grow any more intelligent.",
1034     "You do not feel any wiser.",
1035     "You don't feel any more powerful."
1036 root 1.8 "You are no easier to look at.",
1037 elmex 1.1 };
1038    
1039 root 1.8 int
1040     cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1041     {
1042     object *force = NULL;
1043     int i;
1044    
1045     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1046 root 1.27 object *tmp = dir
1047     ? find_target_for_friendly_spell (op, dir)
1048     : op;
1049 root 1.8
1050 root 1.27 if (!tmp)
1051 root 1.8 return 0;
1052    
1053     /* If we've already got a force of this type, don't add a new one. */
1054 root 1.27 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1055 root 1.8 {
1056     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1057     {
1058     if (tmp2->name == spell_ob->name)
1059     {
1060     force = tmp2; /* the old effect will be "refreshed" */
1061     break;
1062 root 1.5 }
1063 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1064     {
1065     if (!silent)
1066     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1067     return 0;
1068 root 1.5 }
1069     }
1070 elmex 1.1 }
1071 root 1.8 if (force == NULL)
1072     {
1073     force = get_archetype (FORCE_NAME);
1074     force->subtype = FORCE_CHANGE_ABILITY;
1075     if (spell_ob->race)
1076     force->name = spell_ob->race;
1077     else
1078     force->name = spell_ob->name;
1079     force->name_pl = spell_ob->name;
1080     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1081    
1082     }
1083     else
1084     {
1085     int duration;
1086    
1087     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1088     if (duration > force->duration)
1089     {
1090     force->duration = duration;
1091     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1092     }
1093     else
1094     {
1095     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1096     }
1097 root 1.55
1098 root 1.8 return 1;
1099     }
1100 root 1.55
1101 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1102     force->speed = 1.0;
1103     force->speed_left = -1.0;
1104     SET_FLAG (force, FLAG_APPLIED);
1105    
1106     /* Now start processing the effects. First, protections */
1107     for (i = 0; i < NROFATTACKS; i++)
1108     {
1109     if (spell_ob->resist[i])
1110     {
1111     force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob);
1112     if (force->resist[i] > 100)
1113     force->resist[i] = 100;
1114 root 1.5 }
1115 elmex 1.1 }
1116 root 1.55
1117 root 1.8 if (spell_ob->stats.hp)
1118     force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1119    
1120     if (tmp->type == PLAYER)
1121     {
1122     /* Stat adjustment spells */
1123     for (i = 0; i < NUM_STATS; i++)
1124     {
1125 root 1.51 if (sint8 stat = spell_ob->stats.stat (i))
1126 root 1.8 {
1127 root 1.51 sint8 sm = 0;
1128     for (sint8 k = 0; k < stat; k++)
1129 root 1.8 sm += rndm (1, 3);
1130    
1131 root 1.51 if (tmp->stats.stat (i) + sm > 15 + 5 * stat)
1132     sm = max (0, (15 + 5 * stat) - tmp->stats.stat (i));
1133    
1134     force->stats.stat (i) = sm;
1135    
1136 root 1.8 if (!sm)
1137     new_draw_info (NDI_UNIQUE, 0, op, no_gain_msgs[i]);
1138 root 1.5 }
1139     }
1140 elmex 1.1 }
1141    
1142 root 1.8 force->move_type = spell_ob->move_type;
1143 elmex 1.1
1144 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK))
1145     SET_FLAG (force, FLAG_SEE_IN_DARK);
1146 elmex 1.1
1147 root 1.8 if (QUERY_FLAG (spell_ob, FLAG_XRAYS))
1148     SET_FLAG (force, FLAG_XRAYS);
1149 elmex 1.1
1150 root 1.8 /* Haste/bonus speed */
1151     if (spell_ob->stats.exp)
1152     {
1153     if (op->speed > 0.5f)
1154     force->stats.exp = (sint64) ((float) spell_ob->stats.exp / (op->speed + 0.5f));
1155     else
1156     force->stats.exp = spell_ob->stats.exp;
1157 elmex 1.1 }
1158    
1159 root 1.8 force->stats.wc = spell_ob->stats.wc;
1160     force->stats.ac = spell_ob->stats.ac;
1161     force->attacktype = spell_ob->attacktype;
1162    
1163     insert_ob_in_ob (force, tmp);
1164     change_abil (tmp, force); /* Mostly to display any messages */
1165 root 1.24 tmp->update_stats ();
1166 root 1.55
1167 root 1.8 return 1;
1168 elmex 1.1 }
1169    
1170     /* This used to be part of cast_change_ability, but it really didn't make
1171     * a lot of sense, since most of the values it derives are from the god
1172     * of the caster.
1173     */
1174 root 1.8 int
1175     cast_bless (object *op, object *caster, object *spell_ob, int dir)
1176     {
1177     int i;
1178     object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp;
1179    
1180     /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1181     if (dir != 0)
1182     {
1183     tmp = find_target_for_friendly_spell (op, dir);
1184     }
1185     else
1186     {
1187     tmp = op;
1188     }
1189    
1190     /* If we've already got a force of this type, don't add a new one. */
1191     for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1192     {
1193     if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1194     {
1195     if (tmp2->name == spell_ob->name)
1196     {
1197     force = tmp2; /* the old effect will be "refreshed" */
1198     break;
1199 root 1.5 }
1200 root 1.8 else if (spell_ob->race && spell_ob->race == tmp2->name)
1201     {
1202     new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1203     return 0;
1204 root 1.5 }
1205     }
1206 elmex 1.1 }
1207 root 1.8 if (force == NULL)
1208     {
1209     force = get_archetype (FORCE_NAME);
1210     force->subtype = FORCE_CHANGE_ABILITY;
1211     if (spell_ob->race)
1212     force->name = spell_ob->race;
1213     else
1214     force->name = spell_ob->name;
1215     force->name_pl = spell_ob->name;
1216     new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1217     }
1218     else
1219     {
1220     int duration;
1221    
1222     duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1223     if (duration > force->duration)
1224     {
1225     force->duration = duration;
1226     new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1227 root 1.5 }
1228 root 1.8 else
1229     {
1230     new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1231     }
1232     return 0;
1233 elmex 1.1 }
1234 root 1.8 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1235     force->speed = 1.0;
1236     force->speed_left = -1.0;
1237     SET_FLAG (force, FLAG_APPLIED);
1238 elmex 1.1
1239 root 1.8 if (!god)
1240     {
1241     new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1242     }
1243     else
1244     {
1245     /* Only give out good benefits, and put a max on it */
1246     for (i = 0; i < NROFATTACKS; i++)
1247     {
1248     if (god->resist[i] > 0)
1249     {
1250     force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1251 root 1.5 }
1252     }
1253 root 1.8 force->path_attuned |= god->path_attuned;
1254 root 1.7
1255 root 1.8 if (spell_ob->attacktype)
1256     force->slaying = god->slaying;
1257 root 1.7
1258 root 1.8 if (tmp != op)
1259     {
1260     new_draw_info_format (NDI_UNIQUE, 0, op, "You bless %s.", &tmp->name);
1261     new_draw_info_format (NDI_UNIQUE, 0, tmp, "%s blessed you.", &op->name);
1262     }
1263     else
1264     {
1265     new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are blessed by %s!", &god->name);
1266 root 1.5 }
1267 elmex 1.1
1268     }
1269 root 1.8 force->stats.wc = spell_ob->stats.wc;
1270     force->stats.ac = spell_ob->stats.ac;
1271 elmex 1.1
1272 root 1.8 change_abil (tmp, force); /* Mostly to display any messages */
1273     insert_ob_in_ob (force, tmp);
1274 root 1.24 tmp->update_stats ();
1275 root 1.8 return 1;
1276 elmex 1.1 }
1277    
1278     /* Alchemy code by Mark Wedel
1279     *
1280     * This code adds a new spell, called alchemy. Alchemy will turn
1281     * objects to gold nuggets, the value of the gold nuggets being
1282     * about 90% of that of the item itself. It uses the value of the
1283     * object before charisma adjustments, because the nuggets themselves
1284     * will be will be adjusted by charisma when sold.
1285     *
1286     * Large nuggets are worth 25 gp each (base). You will always get
1287     * the maximum number of large nuggets you could get.
1288     * Small nuggets are worth 1 gp each (base). You will get from 0
1289     * to the max amount of small nuggets as you could get.
1290     *
1291     * For example, if an item is worth 110 gold, you will get
1292     * 4 large nuggets, and from 0-10 small nuggets.
1293     *
1294     * There is also a chance (1:30) that you will get nothing at all
1295     * for the object. There is also a maximum weight that will be
1296 root 1.37 * alchemised.
1297 elmex 1.1 */
1298 root 1.8 static void
1299 root 1.38 alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1300 root 1.8 {
1301     uint64 value = query_cost (obj, NULL, F_TRUE);
1302    
1303     /* Give third price when we alchemy money (This should hopefully
1304     * make it so that it isn't worth it to alchemy money, sell
1305     * the nuggets, alchemy the gold from that, etc.
1306     * Otherwise, give 9 silver on the gold for other objects,
1307     * so that it would still be more affordable to haul
1308     * the stuff back to town.
1309     */
1310     if (QUERY_FLAG (obj, FLAG_UNPAID))
1311     value = 0;
1312     else if (obj->type == MONEY || obj->type == GEM)
1313     value /= 3;
1314     else
1315 root 1.39 value = value * 9 / 10;
1316 root 1.8
1317 root 1.37 if (obj->value > 0 && rndm (0, 29))
1318 root 1.38 total_value += value;
1319 root 1.8
1320 root 1.38 total_weight += obj->total_weight ();
1321 root 1.8
1322 root 1.17 obj->destroy ();
1323 root 1.8 }
1324    
1325     static void
1326 root 1.38 update_map (object *op, maptile *m, int small_nuggets, object *small, int large_nuggets, object *large, int x, int y)
1327 root 1.8 {
1328     int flag = 0;
1329    
1330     /* Put any nuggets below the player, but we can only pass this
1331     * flag if we are on the same space as the player
1332     */
1333     if (x == op->x && y == op->y && op->map == m)
1334     flag = INS_BELOW_ORIGINATOR;
1335    
1336     if (small_nuggets)
1337     {
1338 root 1.38 object *tmp = small->clone ();
1339 root 1.8 tmp->nrof = small_nuggets;
1340 root 1.27 m->insert (tmp, x, y, op, flag);
1341 root 1.8 }
1342 root 1.18
1343 root 1.8 if (large_nuggets)
1344     {
1345 root 1.38 object *tmp = large->clone ();
1346 root 1.8 tmp->nrof = large_nuggets;
1347 root 1.27 m->insert (tmp, x, y, op, flag);
1348 root 1.8 }
1349 root 1.38
1350     if (object *pl = m->at (x, y).player ())
1351     if (pl->contr->ns)
1352     pl->contr->ns->look_position = 0;
1353 root 1.8 }
1354    
1355     int
1356     alchemy (object *op, object *caster, object *spell_ob)
1357 elmex 1.1 {
1358 root 1.8 if (op->type != PLAYER)
1359     return 0;
1360    
1361 root 1.39 object *large = get_archetype ("largenugget");
1362     object *small = get_archetype ("smallnugget");
1363    
1364 root 1.38 /* Put a maximum weight of items that can be alchemised. Limits the power
1365     * some, and also prevents people from alchemising every table/chair/clock
1366 root 1.8 * in sight
1367     */
1368 root 1.38 int duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1369     int weight_max = duration * 1000;
1370     uint64 value_max = duration * 1000;
1371 elmex 1.1
1372 root 1.39 int weight = 0;
1373 root 1.38
1374     for (int y = op->y - 1; y <= op->y + 1; y++)
1375 root 1.8 {
1376 root 1.38 for (int x = op->x - 1; x <= op->x + 1; x++)
1377 root 1.8 {
1378 root 1.38 uint64 value = 0;
1379    
1380     sint16 nx = x;
1381     sint16 ny = y;
1382 elmex 1.1
1383 root 1.39 maptile *mp = op->map;
1384 root 1.5
1385 root 1.39 int mflags = get_map_flags (mp, &mp, nx, ny, &nx, &ny);
1386 root 1.5
1387 root 1.8 if (mflags & (P_OUT_OF_MAP | P_NO_MAGIC))
1388     continue;
1389    
1390     /* Treat alchemy a little differently - most spell effects
1391     * use fly as the movement type - for alchemy, consider it
1392     * ground level effect.
1393     */
1394     if (GET_MAP_MOVE_BLOCK (mp, nx, ny) & MOVE_WALK)
1395     continue;
1396    
1397 root 1.38 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1398 root 1.8 {
1399     next = tmp->above;
1400 root 1.37
1401 root 1.8 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) &&
1402     !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
1403     {
1404     if (tmp->inv)
1405     {
1406     object *next1, *tmp1;
1407    
1408 root 1.37 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1409 root 1.8 {
1410     next1 = tmp1->below;
1411     if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) &&
1412     !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON))
1413 root 1.38 alchemy_object (tmp1, value, weight);
1414 root 1.5 }
1415     }
1416 root 1.37
1417 root 1.38 alchemy_object (tmp, value, weight);
1418 root 1.8
1419     if (weight > weight_max)
1420 root 1.38 break;
1421     }
1422     }
1423    
1424     value = min (value, value_max);
1425    
1426     uint64 count = value / large->value;
1427     int large_nuggets = count;
1428     value -= count * large->value;
1429    
1430     count = value / small->value;
1431     int small_nuggets = count;
1432 root 1.5
1433 root 1.8 /* Insert all the nuggets at one time. This probably saves time, but
1434     * it also prevents us from alcheming nuggets that were just created
1435     * with this spell.
1436     */
1437 root 1.38 update_map (op, mp, small_nuggets, small, large_nuggets, large, nx, ny);
1438    
1439     if (weight > weight_max)
1440     goto bailout;
1441 root 1.8 }
1442     }
1443 root 1.17
1444 root 1.38 bailout:
1445 root 1.17 large->destroy ();
1446     small->destroy ();
1447 root 1.8 return 1;
1448 elmex 1.1 }
1449    
1450    
1451     /* This function removes the cursed/damned status on equipped
1452     * items.
1453     */
1454 root 1.8 int
1455     remove_curse (object *op, object *caster, object *spell)
1456     {
1457     object *tmp;
1458     int success = 0, was_one = 0;
1459    
1460     for (tmp = op->inv; tmp; tmp = tmp->below)
1461     if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1462     ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1463     (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1464     {
1465     was_one++;
1466     if (tmp->level <= caster_level (caster, spell))
1467     {
1468     success++;
1469     if (QUERY_FLAG (spell, FLAG_DAMNED))
1470     CLEAR_FLAG (tmp, FLAG_DAMNED);
1471    
1472     CLEAR_FLAG (tmp, FLAG_CURSED);
1473     CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1474     tmp->value = 0; /* Still can't sell it */
1475     if (op->type == PLAYER)
1476     esrv_send_item (op, tmp);
1477     }
1478     }
1479    
1480     if (op->type == PLAYER)
1481     {
1482     if (success)
1483 root 1.38 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now.");
1484 root 1.8 else
1485     {
1486     if (was_one)
1487     new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse.");
1488     else
1489     new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items.");
1490 root 1.5 }
1491 elmex 1.1 }
1492 root 1.21
1493 root 1.8 return success;
1494 elmex 1.1 }
1495    
1496     /* Identifies objects in the players inventory/on the ground */
1497    
1498 root 1.8 int
1499     cast_identify (object *op, object *caster, object *spell)
1500     {
1501     object *tmp;
1502     int success = 0, num_ident;
1503    
1504     num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1505    
1506     if (num_ident < 1)
1507     num_ident = 1;
1508    
1509     for (tmp = op->inv; tmp; tmp = tmp->below)
1510     {
1511     if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1512     {
1513     identify (tmp);
1514 root 1.21
1515 root 1.8 if (op->type == PLAYER)
1516     {
1517 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "You identified: %s.", long_desc (tmp, op));
1518 root 1.21
1519 root 1.8 if (tmp->msg)
1520     {
1521     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1522     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1523 root 1.5 }
1524     }
1525 root 1.21
1526 root 1.8 num_ident--;
1527     success = 1;
1528     if (!num_ident)
1529     break;
1530 root 1.5 }
1531 elmex 1.1 }
1532 root 1.21
1533 root 1.8 /* If all the power of the spell has been used up, don't go and identify
1534     * stuff on the floor. Only identify stuff on the floor if the spell
1535     * was not fully used.
1536     */
1537     if (num_ident)
1538     {
1539 root 1.48 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1540 root 1.8 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1541     {
1542 root 1.21 identify (tmp);
1543 root 1.8
1544     if (op->type == PLAYER)
1545     {
1546 root 1.48 new_draw_info_format (NDI_UNIQUE, 0, op, "On the ground you identified: %s.", long_desc (tmp, op));
1547 root 1.21
1548 root 1.8 if (tmp->msg)
1549     {
1550     new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1551     new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1552     }
1553 root 1.21
1554 root 1.8 esrv_send_item (op, tmp);
1555     }
1556 root 1.21
1557 root 1.5 num_ident--;
1558 root 1.8 success = 1;
1559     if (!num_ident)
1560     break;
1561     }
1562     }
1563 root 1.21
1564 root 1.8 if (!success)
1565     new_draw_info (NDI_UNIQUE, 0, op, "You can't reach anything unidentified.");
1566     else
1567 root 1.21 spell_effect (spell, op->x, op->y, op->map, op);
1568    
1569 root 1.8 return success;
1570 elmex 1.1 }
1571    
1572 root 1.8 int
1573     cast_detection (object *op, object *caster, object *spell, object *skill)
1574     {
1575     object *tmp, *last, *god, *detect;
1576     int done_one, range, mflags, floor, level;
1577     sint16 x, y, nx, ny;
1578 root 1.13 maptile *m;
1579 root 1.8
1580     /* We precompute some values here so that we don't have to keep
1581     * doing it over and over again.
1582     */
1583     god = find_god (determine_god (op));
1584     level = caster_level (caster, spell);
1585     range = spell->range + SP_level_range_adjust (caster, spell);
1586    
1587     if (!skill)
1588     skill = caster;
1589    
1590     for (x = op->x - range; x <= op->x + range; x++)
1591     for (y = op->y - range; y <= op->y + range; y++)
1592     {
1593     m = op->map;
1594     mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1595     if (mflags & P_OUT_OF_MAP)
1596     continue;
1597    
1598     /* For most of the detections, we only detect objects above the
1599     * floor. But this is not true for show invisible.
1600     * Basically, we just go and find the top object and work
1601     * down - that is easier than working up.
1602     */
1603 elmex 1.1
1604 root 1.22 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above)
1605 root 1.8 last = tmp;
1606 root 1.21
1607 root 1.8 /* Shouldn't happen, but if there are no objects on a space, this
1608     * would happen.
1609     */
1610     if (!last)
1611     continue;
1612 elmex 1.1
1613 root 1.8 done_one = 0;
1614     floor = 0;
1615     detect = NULL;
1616     for (tmp = last; tmp; tmp = tmp->below)
1617     {
1618     /* show invisible */
1619     if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) &&
1620 root 1.21 /* Might there be other objects that we can make visible? */
1621 root 1.8 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) ||
1622     (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) ||
1623     tmp->type == CF_HANDLE ||
1624     tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE ||
1625     tmp->type == BUTTON || tmp->type == TELEPORTER ||
1626     tmp->type == GATE || tmp->type == LOCKED_DOOR ||
1627     tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN ||
1628     tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY ||
1629     tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR)))
1630     {
1631     if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1632     {
1633     tmp->invisible = 0;
1634     done_one = 1;
1635     }
1636     }
1637 root 1.21
1638 root 1.8 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1639     floor = 1;
1640 elmex 1.1
1641 root 1.8 /* All detections below this point don't descend beneath the floor,
1642     * so just continue on. We could be clever and look at the type of
1643     * detection to completely break out if we don't care about objects beneath
1644     * the floor, but once we get to the floor, not likely a very big issue anyways.
1645     */
1646     if (floor)
1647     continue;
1648 root 1.5
1649 root 1.8 /* I had thought about making detect magic and detect curse
1650     * show the flash the magic item like it does for detect monster.
1651     * however, if the object is within sight, this would then make it
1652     * difficult to see what object is magical/cursed, so the
1653     * effect wouldn't be as apparant.
1654 root 1.5 */
1655    
1656 root 1.8 /* detect magic */
1657     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1658     !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1659     {
1660     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1661     /* make runes more visibile */
1662     if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1663     tmp->stats.Cha /= 4;
1664     done_one = 1;
1665     }
1666     /* detect monster */
1667     if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1668     {
1669     done_one = 2;
1670     if (!detect)
1671     detect = tmp;
1672     }
1673     /* Basically, if race is set in the spell, then the creatures race must
1674     * match that. if the spell race is set to GOD, then the gods opposing
1675     * race must match.
1676 root 1.5 */
1677 root 1.8 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1678     ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) ||
1679     (strstr (spell->race, tmp->race))))
1680     {
1681     done_one = 2;
1682     if (!detect)
1683     detect = tmp;
1684     }
1685     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1686     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1687     {
1688     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1689     done_one = 1;
1690     }
1691     } /* for stack of objects on this space */
1692 root 1.5
1693 root 1.8 /* Code here puts an effect of the spell on the space, so you can see
1694     * where the magic is.
1695     */
1696     if (done_one)
1697     {
1698     object *detect_ob = arch_to_object (spell->other_arch);
1699    
1700     /* if this is set, we want to copy the face */
1701     if (done_one == 2 && detect)
1702     {
1703     detect_ob->face = detect->face;
1704     detect_ob->animation_id = detect->animation_id;
1705     detect_ob->anim_speed = detect->anim_speed;
1706     detect_ob->last_anim = 0;
1707     /* by default, the detect_ob is already animated */
1708     if (!QUERY_FLAG (detect, FLAG_ANIMATE))
1709     CLEAR_FLAG (detect_ob, FLAG_ANIMATE);
1710     }
1711 root 1.27
1712     m->insert (detect_ob, nx, ny, op);
1713 root 1.8 }
1714     } /* for processing the surrounding spaces */
1715 root 1.5
1716    
1717 root 1.8 /* Now process objects in the players inventory if detect curse or magic */
1718     if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL))
1719     {
1720     done_one = 0;
1721     for (tmp = op->inv; tmp; tmp = tmp->below)
1722     {
1723     if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1724     {
1725     if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL))
1726     {
1727     SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1728     if (op->type == PLAYER)
1729     esrv_send_item (op, tmp);
1730 root 1.5 }
1731 root 1.8 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1732     (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1733     {
1734     SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1735     if (op->type == PLAYER)
1736     esrv_send_item (op, tmp);
1737 root 1.5 }
1738 root 1.8 } /* if item is not identified */
1739     } /* for the players inventory */
1740     } /* if detect magic/curse and object is a player */
1741     return 1;
1742 elmex 1.1 }
1743    
1744    
1745     /**
1746     * Checks if victim has overcharged mana. caster_level is the caster's (skill)
1747     * level whos spell did cause the overcharge.
1748     */
1749 root 1.8 static void
1750     charge_mana_effect (object *victim, int caster_level)
1751 elmex 1.1 {
1752    
1753 root 1.8 /* Prevent explosions for objects without mana. Without this check, doors
1754     * will explode, too.
1755     */
1756     if (victim->stats.maxsp <= 0)
1757     return;
1758 elmex 1.1
1759 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
1760 elmex 1.1
1761 root 1.8 if (victim->stats.sp >= victim->stats.maxsp * 2)
1762     {
1763     object *tmp;
1764 elmex 1.1
1765 root 1.8 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
1766 elmex 1.1
1767 root 1.8 /* Explodes a fireball centered at player */
1768     tmp = get_archetype (EXPLODING_FIREBALL);
1769     tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
1770     tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
1771 root 1.27
1772     tmp->insert_at (victim);
1773 root 1.8 victim->stats.sp = 2 * victim->stats.maxsp;
1774 elmex 1.1 }
1775 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
1776 root 1.27 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode.");
1777 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
1778 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
1779 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
1780     {
1781     new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
1782     confuse_player (victim, victim, 99);
1783 elmex 1.1 }
1784 root 1.8 else if (victim->stats.sp >= victim->stats.maxsp * 1.25)
1785 root 1.27 new_draw_info (NDI_UNIQUE, 0, victim, "You start hearing voices.");
1786 elmex 1.1 }
1787    
1788     /* cast_transfer
1789     * This spell transfers sp from the player to another person.
1790     * We let the target go above their normal maximum SP.
1791     */
1792    
1793 root 1.8 int
1794     cast_transfer (object *op, object *caster, object *spell, int dir)
1795     {
1796     object *plyr = NULL;
1797     sint16 x, y;
1798 root 1.13 maptile *m;
1799 root 1.8 int mflags;
1800    
1801     m = op->map;
1802     x = op->x + freearr_x[dir];
1803     y = op->y + freearr_y[dir];
1804    
1805     mflags = get_map_flags (m, &m, x, y, &x, &y);
1806    
1807     if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
1808     {
1809 root 1.22 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above)
1810 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1811     break;
1812 elmex 1.1 }
1813    
1814    
1815 root 1.8 /* If we did not find a player in the specified direction, transfer
1816     * to anyone on top of us. This is used for the rune of transference mostly.
1817     */
1818     if (plyr == NULL)
1819 root 1.22 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
1820 root 1.8 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE))
1821     break;
1822 elmex 1.1
1823 root 1.8 if (!plyr)
1824     {
1825     new_draw_info (NDI_BLACK, 0, op, "There is no one there.");
1826     return 0;
1827 elmex 1.1 }
1828 root 1.8 /* give sp */
1829     if (spell->stats.dam > 0)
1830     {
1831     plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
1832     charge_mana_effect (plyr, caster_level (caster, spell));
1833     return 1;
1834 elmex 1.1 }
1835 root 1.8 /* suck sp away. Can't suck sp from yourself */
1836     else if (op != plyr)
1837     {
1838     /* old dragin magic used floats. easier to just use ints and divide by 100 */
1839    
1840     int rate = -spell->stats.dam + SP_level_dam_adjust (caster, spell), sucked;
1841    
1842     if (rate > 95)
1843     rate = 95;
1844    
1845     sucked = (plyr->stats.sp * rate) / 100;
1846     plyr->stats.sp -= sucked;
1847     if (QUERY_FLAG (op, FLAG_ALIVE))
1848     {
1849     /* Player doesn't get full credit */
1850     sucked = (sucked * rate) / 100;
1851     op->stats.sp += sucked;
1852     if (sucked > 0)
1853     {
1854     charge_mana_effect (op, caster_level (caster, spell));
1855 root 1.5 }
1856     }
1857 root 1.8 return 1;
1858 elmex 1.1 }
1859 root 1.8 return 0;
1860 elmex 1.1 }
1861    
1862    
1863     /* counterspell: nullifies spell effects.
1864     * op is the counterspell object, dir is the direction
1865     * it was cast in.
1866     * Basically, if the object has a magic attacktype,
1867     * this may nullify it.
1868     */
1869 root 1.8 void
1870     counterspell (object *op, int dir)
1871 elmex 1.1 {
1872 root 1.8 object *tmp, *head, *next;
1873     int mflags;
1874 root 1.13 maptile *m;
1875 root 1.8 sint16 sx, sy;
1876    
1877     sx = op->x + freearr_x[dir];
1878     sy = op->y + freearr_y[dir];
1879     m = op->map;
1880     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1881     if (mflags & P_OUT_OF_MAP)
1882     return;
1883 elmex 1.1
1884 root 1.22 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next)
1885 root 1.8 {
1886     next = tmp->above;
1887 elmex 1.1
1888 root 1.8 /* Need to look at the head object - otherwise, if tmp
1889     * points to a monster, we don't have all the necessary
1890     * info for it.
1891     */
1892     if (tmp->head)
1893     head = tmp->head;
1894     else
1895     head = tmp;
1896    
1897     /* don't attack our own spells */
1898     if (tmp->owner && tmp->owner == op->owner)
1899     continue;
1900    
1901     /* Basically, if the object is magical and not counterspell,
1902     * we will more or less remove the object. Don't counterspell
1903     * monsters either.
1904     */
1905 elmex 1.1
1906 elmex 1.44 if (head->attacktype & AT_MAGIC
1907     && !(head->attacktype & AT_COUNTERSPELL)
1908     && !QUERY_FLAG (head, FLAG_MONSTER)
1909     && (op->level > head->level))
1910 root 1.17 head->destroy ();
1911 root 1.8 else
1912     switch (head->type)
1913     {
1914     case SPELL_EFFECT:
1915 elmex 1.44 // XXX: Don't affect floor spelleffects. See also XXX comment
1916     // about sanctuary in spell_util.C
1917     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1918     continue;
1919    
1920 root 1.8 if (op->level > head->level)
1921 root 1.17 head->destroy ();
1922    
1923 root 1.5 break;
1924    
1925 root 1.8 /* I really don't get this rune code that much - that
1926     * random chance seems really low.
1927     */
1928     case RUNE:
1929     if (rndm (0, 149) == 0)
1930     {
1931     head->stats.hp--; /* weaken the rune */
1932     if (!head->stats.hp)
1933 root 1.17 head->destroy ();
1934 root 1.8 }
1935 root 1.5 break;
1936 root 1.8 }
1937 elmex 1.1 }
1938     }
1939    
1940    
1941    
1942     /* cast_consecrate() - a spell to make an altar your god's */
1943 root 1.8 int
1944     cast_consecrate (object *op, object *caster, object *spell)
1945     {
1946     char buf[MAX_BUF];
1947 elmex 1.1
1948 root 1.8 object *tmp, *god = find_god (determine_god (op));
1949 elmex 1.1
1950 root 1.8 if (!god)
1951     {
1952     new_draw_info (NDI_UNIQUE, 0, op, "You can't consecrate anything if you don't worship a god!");
1953     return 0;
1954 elmex 1.1 }
1955 root 1.8
1956     for (tmp = op->below; tmp; tmp = tmp->below)
1957     {
1958     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1959     break;
1960     if (tmp->type == HOLY_ALTAR)
1961     {
1962    
1963     if (tmp->level > caster_level (caster, spell))
1964     {
1965     new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name);
1966     return 0;
1967     }
1968     else
1969     {
1970     /* If we got here, we are consecrating an altar */
1971     sprintf (buf, "Altar of %s", &god->name);
1972     tmp->name = buf;
1973     tmp->level = caster_level (caster, spell);
1974     tmp->other_arch = god->arch;
1975     if (op->type == PLAYER)
1976     esrv_update_item (UPD_NAME, op, tmp);
1977     new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
1978     return 1;
1979 root 1.5 }
1980     }
1981 elmex 1.1 }
1982 root 1.8 new_draw_info (NDI_UNIQUE, 0, op, "You are not standing over an altar!");
1983     return 0;
1984 elmex 1.1 }
1985    
1986     /* animate_weapon -
1987     * Generalization of staff_to_snake. Makes a golem out of the caster's weapon.
1988     * The golem is based on the archetype specified, modified by the caster's level
1989     * and the attributes of the weapon. The weapon is inserted in the golem's
1990     * inventory so that it falls to the ground when the golem dies.
1991     * This code was very odd - code early on would only let players use the spell,
1992     * yet the code wass full of player checks. I've presumed that the code
1993     * that only let players use it was correct, and removed all the other
1994     * player checks. MSW 2003-01-06
1995     */
1996 root 1.8 int
1997     animate_weapon (object *op, object *caster, object *spell, int dir)
1998     {
1999     object *weapon, *tmp;
2000     char buf[MAX_BUF];
2001     int a, i;
2002     sint16 x, y;
2003 root 1.13 maptile *m;
2004 root 1.8
2005     if (!spell->other_arch)
2006     {
2007     new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
2008     LOG (llevError, "animate_weapon failed: spell %s missing other_arch!\n", &spell->name);
2009     return 0;
2010 elmex 1.1 }
2011 root 1.8 /* exit if it's not a player using this spell. */
2012     if (op->type != PLAYER)
2013     return 0;
2014 elmex 1.1
2015 root 1.8 /* if player already has a golem, abort */
2016 root 1.49 if (object *golem = op->contr->golem)
2017 root 1.8 {
2018 root 1.46 control_golem (golem, dir);
2019 root 1.8 return 0;
2020 elmex 1.1 }
2021    
2022 root 1.8 /* if no direction specified, pick one */
2023     if (!dir)
2024     dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9);
2025    
2026     m = op->map;
2027     x = op->x + freearr_x[dir];
2028     y = op->y + freearr_y[dir];
2029    
2030     /* if there's no place to put the golem, abort */
2031     if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) ||
2032 root 1.57 ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type))
2033 root 1.8 {
2034     new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
2035     return 0;
2036 elmex 1.1 }
2037    
2038 root 1.8 /* Use the weapon marked by the player. */
2039     weapon = find_marked_object (op);
2040 elmex 1.1
2041 root 1.8 if (!weapon)
2042     {
2043     new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!");
2044     return 0;
2045     }
2046 root 1.56 if (spell->race && strcmp (weapon->arch->archname, spell->race))
2047 root 1.8 {
2048     new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon.");
2049     return 0;
2050     }
2051     if (weapon->type != WEAPON)
2052     {
2053     new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it.");
2054     return 0;
2055 elmex 1.1 }
2056 root 1.8 if (QUERY_FLAG (weapon, FLAG_APPLIED))
2057     {
2058     new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon));
2059     return 0;
2060 elmex 1.1 }
2061 root 1.8
2062     if (weapon->nrof > 1)
2063     {
2064     tmp = get_split_ob (weapon, 1);
2065     esrv_send_item (op, weapon);
2066     weapon = tmp;
2067     }
2068    
2069     /* create the golem object */
2070     tmp = arch_to_object (spell->other_arch);
2071    
2072     /* if animated by a player, give the player control of the golem */
2073     CLEAR_FLAG (tmp, FLAG_MONSTER);
2074     tmp->stats.exp = 0;
2075     add_friendly_object (tmp);
2076     tmp->type = GOLEM;
2077 root 1.19 tmp->set_owner (op);
2078 root 1.49 op->contr->golem = tmp;
2079 root 1.46 set_spell_skill (op, caster, spell, tmp);
2080 root 1.8
2081     /* Give the weapon to the golem now. A bit of a hack to check the
2082     * removed flag - it should only be set if get_split_object was
2083     * used above.
2084     */
2085     if (!QUERY_FLAG (weapon, FLAG_REMOVED))
2086 root 1.16 weapon->remove ();
2087 root 1.46
2088 root 1.8 insert_ob_in_ob (weapon, tmp);
2089     esrv_send_item (op, weapon);
2090     /* To do everything necessary to let a golem use the weapon is a pain,
2091     * so instead, just set it as equipped (otherwise, we need to update
2092     * body_info, skills, etc)
2093     */
2094     SET_FLAG (tmp, FLAG_USE_WEAPON);
2095     SET_FLAG (weapon, FLAG_APPLIED);
2096 root 1.24 tmp->update_stats ();
2097 root 1.8
2098     /* There used to be 'odd' code that basically seemed to take the absolute
2099     * value of the weapon->magic an use that. IMO, that doesn't make sense -
2100     * if you're using a crappy weapon, it shouldn't be as good.
2101     */
2102    
2103     /* modify weapon's animated wc */
2104     tmp->stats.wc = tmp->stats.wc - SP_level_range_adjust (caster, spell) - 5 * weapon->stats.Dex - 2 * weapon->stats.Str - weapon->magic;
2105     if (tmp->stats.wc < -127)
2106     tmp->stats.wc = -127;
2107    
2108     /* Modify hit points for weapon */
2109     tmp->stats.maxhp = tmp->stats.maxhp + spell->duration +
2110     SP_level_duration_adjust (caster, spell) + +8 * weapon->magic + 12 * weapon->stats.Con;
2111     if (tmp->stats.maxhp < 0)
2112     tmp->stats.maxhp = 10;
2113     tmp->stats.hp = tmp->stats.maxhp;
2114    
2115     /* Modify weapon's damage */
2116     tmp->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell) + weapon->stats.dam + weapon->magic + 5 * weapon->stats.Str;
2117     if (tmp->stats.dam < 0)
2118     tmp->stats.dam = 127;
2119    
2120    
2121     /* attacktype */
2122     if (!tmp->attacktype)
2123     tmp->attacktype = AT_PHYSICAL;
2124    
2125 root 1.63 if (materialtype_t *mt = name_to_material (op->materialname))
2126 root 1.8 {
2127     for (i = 0; i < NROFATTACKS; i++)
2128     tmp->resist[i] = 50 - (mt->save[i] * 5);
2129     a = mt->save[0];
2130 elmex 1.1 }
2131 root 1.8 else
2132     {
2133     for (i = 0; i < NROFATTACKS; i++)
2134     tmp->resist[i] = 5;
2135     a = 10;
2136     }
2137 root 1.63
2138 root 1.8 /* Set weapon's immunity */
2139     tmp->resist[ATNR_CONFUSION] = 100;
2140     tmp->resist[ATNR_POISON] = 100;
2141     tmp->resist[ATNR_SLOW] = 100;
2142     tmp->resist[ATNR_PARALYZE] = 100;
2143     tmp->resist[ATNR_TURN_UNDEAD] = 100;
2144     tmp->resist[ATNR_FEAR] = 100;
2145     tmp->resist[ATNR_DEPLETE] = 100;
2146     tmp->resist[ATNR_DEATH] = 100;
2147     tmp->resist[ATNR_BLIND] = 100;
2148    
2149     /* Improve weapon's armour value according to best save vs. physical of its material */
2150    
2151     if (a > 14)
2152     a = 14;
2153 root 1.63
2154 root 1.8 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 }