ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.71
Committed: Wed Aug 29 20:40:25 2007 UTC (16 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.70: +4 -5 lines
Log Message:
corretcly set owner afetr insert to fix new owner semantics

File Contents

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