ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.139
Committed: Sat Dec 31 06:18:02 2011 UTC (12 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.138: +5 -5 lines
Log Message:
big min/max type change

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