ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.80
Committed: Tue Apr 22 07:01:47 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_52
Changes since 1.79: +19 -21 lines
Log Message:
see Changes

File Contents

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