ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.111
Committed: Mon Oct 12 21:27:55 2009 UTC (14 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_82
Changes since 1.110: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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