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