ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.147
Committed: Sat Sep 16 22:17:42 2017 UTC (6 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.146: +18 -18 lines
Log Message:
freearr => DIR

File Contents

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