ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.73
Committed: Sat Sep 1 08:03:46 2007 UTC (16 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2
Changes since 1.72: +17 -19 lines
Log Message:
first round of infobox and c++-level channels

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