ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.83
Committed: Tue May 6 16:55:26 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_54, rel-2_55, rel-2_56
Changes since 1.82: +1 -1 lines
Log Message:
update copyright

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