ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.82
Committed: Sun May 4 15:22:14 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_53
Changes since 1.81: +1 -5 lines
Log Message:
fix the dummy-teleport-objects c callers

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