ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.78
Committed: Tue Jan 15 12:02:24 2008 UTC (16 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_5, rel-2_43, rel-2_42, rel-2_41
Changes since 1.77: +0 -1 lines
Log Message:
*** empty log message ***

File Contents

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