ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.67
Committed: Mon Aug 13 12:50:30 2007 UTC (16 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.66: +1 -1 lines
Log Message:
hopefully fix alchemy scroll bug

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT 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 <crossfire@schmorp.de>
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 missile_plus = 0, bonus_plus = 0;
131 const char *missile_name;
132 object *tmp, *missile;
133
134 missile_name = "arrow";
135
136 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
137 if (tmp->type == BOW && QUERY_FLAG (tmp, FLAG_APPLIED))
138 missile_name = tmp->race;
139
140 missile_plus = spell->stats.dam + SP_level_dam_adjust (caster, spell);
141
142 if (archetype::find (missile_name) == NULL)
143 {
144 LOG (llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
145 return 0;
146 }
147
148 missile = get_archetype (missile_name);
149
150 if (stringarg)
151 {
152 /* If it starts with a letter, presume it is a description */
153 if (isalpha (*stringarg))
154 {
155 artifact *al = find_artifactlist (missile->type)->items;
156
157 for (; al; al = al->next)
158 if (!strcasecmp (al->item->name, stringarg))
159 break;
160
161 if (!al)
162 {
163 missile->destroy ();
164 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg);
165 return 0;
166 }
167
168 if (al->item->slaying)
169 {
170 missile->destroy ();
171 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg);
172 return 0;
173 }
174
175 give_artifact_abilities (missile, al->item);
176 /* These special arrows cost something extra. Don't have them also be magical -
177 * otherwise, in most cases, not enough will be created. I don't want to get into
178 * the parsing of having to do both plus and type.
179 */
180 bonus_plus = 1 + (al->item->value / 5);
181 missile_plus = 0;
182 }
183 else if (atoi (stringarg) < missile_plus)
184 missile_plus = atoi (stringarg);
185 }
186
187 if (missile_plus > 4)
188 missile_plus = 4;
189 else if (missile_plus < -4)
190 missile_plus = -4;
191
192 missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell);
193 missile->nrof -= 3 * (missile_plus + bonus_plus);
194
195 if (missile->nrof < 1)
196 missile->nrof = 1;
197
198 missile->magic = missile_plus;
199 /* Can't get any money for these objects */
200 missile->value = 0;
201
202 SET_FLAG (missile, FLAG_IDENTIFIED);
203
204 if (!cast_create_obj (op, caster, missile, dir) && op->type == PLAYER && !missile->destroyed ())
205 pick_up (op, missile);
206
207 return 1;
208 }
209
210
211 /* allows the choice of what sort of food object to make.
212 * If stringarg is NULL, it will create food dependent on level --PeterM*/
213 int
214 cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
215 {
216 int food_value;
217 archetype *at = NULL;
218 object *new_op;
219
220 food_value = spell_ob->stats.food + +50 * SP_level_duration_adjust (caster, spell_ob);
221
222 if (stringarg)
223 {
224 at = find_archetype_by_object_type_name (FOOD, stringarg);
225 if (at == NULL)
226 at = find_archetype_by_object_type_name (DRINK, stringarg);
227 if (at == NULL || at->stats.food > food_value)
228 stringarg = NULL;
229 }
230
231 if (!stringarg)
232 {
233 archetype *at_tmp;
234
235 /* We try to find the archetype with the maximum food value.
236 * This removes the dependancy of hard coded food values in this
237 * function, and addition of new food types is automatically added.
238 * We don't use flesh types because the weight values of those need
239 * to be altered from the donor.
240 */
241
242 /* We assume the food items don't have multiple parts */
243 for_all_archetypes (at_tmp)
244 {
245 if (at_tmp->type == FOOD || at_tmp->type == DRINK)
246 {
247 /* Basically, if the food value is something that is creatable
248 * under the limits of the spell and it is higher than
249 * the item we have now, take it instead.
250 */
251 if (at_tmp->stats.food <= food_value
252 && (!at
253 || at_tmp->stats.food > at->stats.food
254 || (at_tmp->stats.food == at->stats.food
255 && at_tmp->weight < at->weight)))
256 at = at_tmp;
257 }
258 }
259 }
260
261 /* Pretty unlikely (there are some very low food items), but you never
262 * know
263 */
264 if (!at)
265 {
266 new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food.");
267 return 0;
268 }
269
270 food_value /= at->stats.food;
271 new_op = arch_to_object (at);
272 new_op->nrof = food_value;
273
274 new_op->value = 0;
275 if (new_op->nrof < 1)
276 new_op->nrof = 1;
277
278 cast_create_obj (op, caster, new_op, dir);
279 return 1;
280 }
281
282 int
283 probe (object *op, object *caster, object *spell_ob, int dir)
284 {
285 int r, mflags, maxrange;
286 object *tmp;
287 maptile *m;
288
289
290 if (!dir)
291 {
292 examine_monster (op, op);
293 return 1;
294 }
295
296 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
297 for (r = 1; r < maxrange; r++)
298 {
299 sint16 x = op->x + r * freearr_x[dir], y = op->y + r * freearr_y[dir];
300
301 m = op->map;
302 mflags = get_map_flags (m, &m, x, y, &x, &y);
303
304 if (mflags & P_OUT_OF_MAP)
305 break;
306
307 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (mflags & P_NO_MAGIC))
308 {
309 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic.");
310 return 0;
311 }
312 if (mflags & P_IS_ALIVE)
313 {
314 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
315 if (QUERY_FLAG (tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG (tmp, FLAG_MONSTER)))
316 {
317 new_draw_info (NDI_UNIQUE, 0, op, "You detect something.");
318 if (tmp->head != NULL)
319 tmp = tmp->head;
320 examine_monster (op, tmp);
321 return 1;
322 }
323 }
324 }
325
326 new_draw_info (NDI_UNIQUE, 0, op, "You detect nothing.");
327 return 1;
328 }
329
330 /* This checks to see if 'pl' is invisible to 'mon'.
331 * does race check, undead check, etc
332 * Returns TRUE if mon can't see pl, false
333 * otherwise. This doesn't check range, walls, etc. It
334 * only checks the racial adjustments, and in fact that
335 * pl is invisible.
336 */
337 int
338 makes_invisible_to (object *pl, object *mon)
339 {
340
341 if (!pl->invisible)
342 return 0;
343 if (pl->type == PLAYER)
344 {
345 /* If race isn't set, then invisible unless it is undead */
346 if (!pl->contr->invis_race)
347 {
348 if (QUERY_FLAG (mon, FLAG_UNDEAD))
349 return 0;
350 return 1;
351 }
352 /* invis_race is set if we get here */
353 if (!strcmp (pl->contr->invis_race, "undead") && is_true_undead (mon))
354 return 1;
355 /* No race, can't be invisible to it */
356 if (!mon->race)
357 return 0;
358 if (strstr (mon->race, pl->contr->invis_race))
359 return 1;
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 && !strcmp (tmp->arch->archname, "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
901 /* cast_heal: Heals something.
902 * op is the caster.
903 * dir is the direction he is casting it in.
904 * spell is the spell object.
905 */
906 int
907 cast_heal (object *op, object *caster, object *spell, int dir)
908 {
909 object *tmp;
910 archetype *at;
911 object *poison;
912 int heal = 0, success = 0;
913
914 tmp = find_target_for_friendly_spell (op, dir);
915
916 if (!tmp)
917 return 0;
918
919 /* Figure out how many hp this spell might cure.
920 * could be zero if this spell heals effects, not damage.
921 */
922 heal = spell->stats.dam;
923 if (spell->stats.hp)
924 heal += random_roll (spell->stats.hp, 6, op, PREFER_HIGH) + spell->stats.hp;
925
926 if (heal)
927 {
928 if (tmp->stats.hp >= tmp->stats.maxhp)
929 new_draw_info (NDI_UNIQUE, 0, tmp, "You are already fully healed.");
930 else
931 {
932 /* See how many points we actually heal. Instead of messages
933 * based on type of spell, we instead do messages based
934 * on amount of damage healed.
935 */
936 if (heal > (tmp->stats.maxhp - tmp->stats.hp))
937 heal = tmp->stats.maxhp - tmp->stats.hp;
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))
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 if (tmp->stats.food > 999)
1016 tmp->stats.food = 999;
1017 success = 1;
1018 /* We could do something a bit better like the messages for healing above */
1019 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food");
1020 }
1021
1022 return success;
1023 }
1024
1025 /* This is used for the spells that gain stats. There are no spells
1026 * right now that icnrease wis/int/pow on a temp basis, so no
1027 * good comments for those.
1028 */
1029 static const char *const no_gain_msgs[NUM_STATS] = {
1030 "You grow no stronger.",
1031 "You grow no more agile.",
1032 "You don't feel any healthier.",
1033 "You didn't grow any more intelligent.",
1034 "You do not feel any wiser.",
1035 "You don't feel any more powerful."
1036 "You are no easier to look at.",
1037 };
1038
1039 int
1040 cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1041 {
1042 object *force = NULL;
1043 int i;
1044
1045 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1046 object *tmp = dir
1047 ? find_target_for_friendly_spell (op, dir)
1048 : op;
1049
1050 if (!tmp)
1051 return 0;
1052
1053 /* If we've already got a force of this type, don't add a new one. */
1054 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1055 {
1056 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1057 {
1058 if (tmp2->name == spell_ob->name)
1059 {
1060 force = tmp2; /* the old effect will be "refreshed" */
1061 break;
1062 }
1063 else if (spell_ob->race && spell_ob->race == tmp2->name)
1064 {
1065 if (!silent)
1066 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1067 return 0;
1068 }
1069 }
1070 }
1071 if (force == NULL)
1072 {
1073 force = get_archetype (FORCE_NAME);
1074 force->subtype = FORCE_CHANGE_ABILITY;
1075 if (spell_ob->race)
1076 force->name = spell_ob->race;
1077 else
1078 force->name = spell_ob->name;
1079 force->name_pl = spell_ob->name;
1080 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1081
1082 }
1083 else
1084 {
1085 int duration;
1086
1087 duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1088 if (duration > force->duration)
1089 {
1090 force->duration = duration;
1091 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1092 }
1093 else
1094 {
1095 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1096 }
1097
1098 return 1;
1099 }
1100
1101 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1102 force->speed = 1.0;
1103 force->speed_left = -1.0;
1104 SET_FLAG (force, FLAG_APPLIED);
1105
1106 /* Now start processing the effects. First, protections */
1107 for (i = 0; i < NROFATTACKS; i++)
1108 {
1109 if (spell_ob->resist[i])
1110 {
1111 force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob);
1112 if (force->resist[i] > 100)
1113 force->resist[i] = 100;
1114 }
1115 }
1116
1117 if (spell_ob->stats.hp)
1118 force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1119
1120 if (tmp->type == PLAYER)
1121 {
1122 /* Stat adjustment spells */
1123 for (i = 0; i < NUM_STATS; i++)
1124 {
1125 if (sint8 stat = spell_ob->stats.stat (i))
1126 {
1127 sint8 sm = 0;
1128 for (sint8 k = 0; k < stat; k++)
1129 sm += rndm (1, 3);
1130
1131 if (tmp->stats.stat (i) + sm > 15 + 5 * stat)
1132 sm = max (0, (15 + 5 * stat) - tmp->stats.stat (i));
1133
1134 force->stats.stat (i) = sm;
1135
1136 if (!sm)
1137 new_draw_info (NDI_UNIQUE, 0, op, no_gain_msgs[i]);
1138 }
1139 }
1140 }
1141
1142 force->move_type = spell_ob->move_type;
1143
1144 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK))
1145 SET_FLAG (force, FLAG_SEE_IN_DARK);
1146
1147 if (QUERY_FLAG (spell_ob, FLAG_XRAYS))
1148 SET_FLAG (force, FLAG_XRAYS);
1149
1150 /* Haste/bonus speed */
1151 if (spell_ob->stats.exp)
1152 {
1153 if (op->speed > 0.5f)
1154 force->stats.exp = (sint64) ((float) spell_ob->stats.exp / (op->speed + 0.5f));
1155 else
1156 force->stats.exp = spell_ob->stats.exp;
1157 }
1158
1159 force->stats.wc = spell_ob->stats.wc;
1160 force->stats.ac = spell_ob->stats.ac;
1161 force->attacktype = spell_ob->attacktype;
1162
1163 insert_ob_in_ob (force, tmp);
1164 change_abil (tmp, force); /* Mostly to display any messages */
1165 tmp->update_stats ();
1166
1167 return 1;
1168 }
1169
1170 /* This used to be part of cast_change_ability, but it really didn't make
1171 * a lot of sense, since most of the values it derives are from the god
1172 * of the caster.
1173 */
1174 int
1175 cast_bless (object *op, object *caster, object *spell_ob, int dir)
1176 {
1177 int i;
1178 object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp;
1179
1180 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1181 if (dir != 0)
1182 {
1183 tmp = find_target_for_friendly_spell (op, dir);
1184 }
1185 else
1186 {
1187 tmp = op;
1188 }
1189
1190 /* If we've already got a force of this type, don't add a new one. */
1191 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1192 {
1193 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1194 {
1195 if (tmp2->name == spell_ob->name)
1196 {
1197 force = tmp2; /* the old effect will be "refreshed" */
1198 break;
1199 }
1200 else if (spell_ob->race && spell_ob->race == tmp2->name)
1201 {
1202 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1203 return 0;
1204 }
1205 }
1206 }
1207 if (force == NULL)
1208 {
1209 force = get_archetype (FORCE_NAME);
1210 force->subtype = FORCE_CHANGE_ABILITY;
1211 if (spell_ob->race)
1212 force->name = spell_ob->race;
1213 else
1214 force->name = spell_ob->name;
1215 force->name_pl = spell_ob->name;
1216 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1217 }
1218 else
1219 {
1220 int duration;
1221
1222 duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1223 if (duration > force->duration)
1224 {
1225 force->duration = duration;
1226 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1227 }
1228 else
1229 {
1230 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1231 }
1232 return 0;
1233 }
1234 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1235 force->speed = 1.0;
1236 force->speed_left = -1.0;
1237 SET_FLAG (force, FLAG_APPLIED);
1238
1239 if (!god)
1240 {
1241 new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1242 }
1243 else
1244 {
1245 /* Only give out good benefits, and put a max on it */
1246 for (i = 0; i < NROFATTACKS; i++)
1247 {
1248 if (god->resist[i] > 0)
1249 {
1250 force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1251 }
1252 }
1253 force->path_attuned |= god->path_attuned;
1254
1255 if (spell_ob->attacktype)
1256 force->slaying = god->slaying;
1257
1258 if (tmp != op)
1259 {
1260 new_draw_info_format (NDI_UNIQUE, 0, op, "You bless %s.", &tmp->name);
1261 new_draw_info_format (NDI_UNIQUE, 0, tmp, "%s blessed you.", &op->name);
1262 }
1263 else
1264 {
1265 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are blessed by %s!", &god->name);
1266 }
1267
1268 }
1269 force->stats.wc = spell_ob->stats.wc;
1270 force->stats.ac = spell_ob->stats.ac;
1271
1272 change_abil (tmp, force); /* Mostly to display any messages */
1273 insert_ob_in_ob (force, tmp);
1274 tmp->update_stats ();
1275 return 1;
1276 }
1277
1278 /* Alchemy code by Mark Wedel
1279 *
1280 * This code adds a new spell, called alchemy. Alchemy will turn
1281 * objects to pyrite ("false gold"), henceforth called gold nuggets.
1282 *
1283 * The value of the gold nuggets being about 90% of that of the item
1284 * itself. It uses the value of the object before charisma adjustments,
1285 * because the nuggets themselves will be will be adjusted by charisma
1286 * when sold.
1287 *
1288 * There is also a chance (1:30) that you will get nothing at all
1289 * for the object. There is also a maximum weight that will be
1290 * alchemised.
1291 */
1292 static void
1293 alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1294 {
1295 uint64 value = query_cost (obj, NULL, F_TRUE);
1296
1297 /* Give third price when we alchemy money (This should hopefully
1298 * make it so that it isn't worth it to alchemy money, sell
1299 * the nuggets, alchemy the gold from that, etc.
1300 * Otherwise, give 9 silver on the gold for other objects,
1301 * so that it would still be more affordable to haul
1302 * the stuff back to town.
1303 */
1304 if (QUERY_FLAG (obj, FLAG_UNPAID))
1305 value = 0;
1306 else if (obj->type == MONEY || obj->type == GEM)
1307 value /= 3;
1308 else
1309 value = value * 9 / 10;
1310
1311 if (obj->value > 0 && rndm (0, 29))
1312 total_value += value;
1313
1314 total_weight += obj->total_weight ();
1315
1316 obj->destroy ();
1317 }
1318
1319 int
1320 alchemy (object *op, object *caster, object *spell_ob)
1321 {
1322 if (op->type != PLAYER)
1323 return 0;
1324
1325 archetype *nugget[3];
1326
1327 nugget[0] = archetype::find ("pyrite3");
1328 nugget[1] = archetype::find ("pyrite2");
1329 nugget[2] = archetype::find ("pyrite");
1330
1331 /* Put a maximum weight of items that can be alchemised. Limits the power
1332 * some, and also prevents people from alchemising every table/chair/clock
1333 * in sight
1334 */
1335 int duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1336 int weight_max = duration * 1000;
1337 uint64 value_max = duration * 1000;
1338
1339 int weight = 0;
1340
1341 for (int y = op->y - 1; y <= op->y + 1; y++)
1342 {
1343 for (int x = op->x - 1; x <= op->x + 1; x++)
1344 {
1345 uint64 value = 0;
1346
1347 sint16 nx = x;
1348 sint16 ny = y;
1349
1350 maptile *mp = op->map;
1351
1352 int mflags = get_map_flags (mp, &mp, nx, ny, &nx, &ny);
1353
1354 if (mflags & (P_OUT_OF_MAP | P_NO_MAGIC))
1355 continue;
1356
1357 /* Treat alchemy a little differently - most spell effects
1358 * use fly as the movement type - for alchemy, consider it
1359 * ground level effect.
1360 */
1361 if (GET_MAP_MOVE_BLOCK (mp, nx, ny) & MOVE_WALK)
1362 continue;
1363
1364 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1365 {
1366 next = tmp->above;
1367
1368 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) &&
1369 !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
1370 {
1371 if (tmp->inv)
1372 {
1373 object *next1, *tmp1;
1374
1375 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1376 {
1377 next1 = tmp1->below;
1378 if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) &&
1379 !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON))
1380 alchemy_object (tmp1, value, weight);
1381 }
1382 }
1383
1384 alchemy_object (tmp, value, weight);
1385
1386 if (weight > weight_max)
1387 break;
1388 }
1389 }
1390
1391 value -= rndm (value >> 4);
1392 value = min (value, value_max);
1393
1394 for (int i = 0; i < sizeof (nugget) / sizeof (nugget [0]); ++i)
1395 if (int nrof = value / nugget [i]->value)
1396 {
1397 value -= nrof * nugget[i]->value;
1398
1399 object *tmp = arch_to_object (nugget[i]);
1400 tmp->nrof = nrof;
1401 tmp->flag [FLAG_IDENTIFIED] = true;
1402 op->map->insert (tmp, x, y, op, 0);
1403 }
1404
1405 if (weight > weight_max)
1406 goto bailout;
1407 }
1408 }
1409
1410 bailout:
1411 return 1;
1412 }
1413
1414
1415 /* This function removes the cursed/damned status on equipped
1416 * items.
1417 */
1418 int
1419 remove_curse (object *op, object *caster, object *spell)
1420 {
1421 object *tmp;
1422 int success = 0, was_one = 0;
1423
1424 for (tmp = op->inv; tmp; tmp = tmp->below)
1425 if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1426 ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1427 (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1428 {
1429 was_one++;
1430 if (tmp->level <= caster_level (caster, spell))
1431 {
1432 success++;
1433 if (QUERY_FLAG (spell, FLAG_DAMNED))
1434 CLEAR_FLAG (tmp, FLAG_DAMNED);
1435
1436 CLEAR_FLAG (tmp, FLAG_CURSED);
1437 CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1438 tmp->value = 0; /* Still can't sell it */
1439 if (op->type == PLAYER)
1440 esrv_send_item (op, tmp);
1441 }
1442 }
1443
1444 if (op->type == PLAYER)
1445 {
1446 if (success)
1447 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now.");
1448 else
1449 {
1450 if (was_one)
1451 new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse.");
1452 else
1453 new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items.");
1454 }
1455 }
1456
1457 return success;
1458 }
1459
1460 /* Identifies objects in the players inventory/on the ground */
1461
1462 int
1463 cast_identify (object *op, object *caster, object *spell)
1464 {
1465 object *tmp;
1466 int success = 0, num_ident;
1467
1468 num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1469
1470 if (num_ident < 1)
1471 num_ident = 1;
1472
1473 for (tmp = op->inv; tmp; tmp = tmp->below)
1474 {
1475 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1476 {
1477 identify (tmp);
1478
1479 if (op->type == PLAYER)
1480 {
1481 new_draw_info_format (NDI_UNIQUE, 0, op, "You identified: %s.", long_desc (tmp, op));
1482
1483 if (tmp->msg)
1484 {
1485 new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1486 new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1487 }
1488 }
1489
1490 num_ident--;
1491 success = 1;
1492 if (!num_ident)
1493 break;
1494 }
1495 }
1496
1497 /* If all the power of the spell has been used up, don't go and identify
1498 * stuff on the floor. Only identify stuff on the floor if the spell
1499 * was not fully used.
1500 */
1501 if (num_ident)
1502 {
1503 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1504 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1505 {
1506 identify (tmp);
1507
1508 if (op->type == PLAYER)
1509 {
1510 new_draw_info_format (NDI_UNIQUE, 0, op, "On the ground you identified: %s.", long_desc (tmp, op));
1511
1512 if (tmp->msg)
1513 {
1514 new_draw_info (NDI_UNIQUE, 0, op, "The item has a story:");
1515 new_draw_info (NDI_UNIQUE, 0, op, tmp->msg);
1516 }
1517
1518 esrv_send_item (op, tmp);
1519 }
1520
1521 num_ident--;
1522 success = 1;
1523 if (!num_ident)
1524 break;
1525 }
1526 }
1527
1528 if (!success)
1529 new_draw_info (NDI_UNIQUE, 0, op, "You can't reach anything unidentified.");
1530 else
1531 spell_effect (spell, op->x, op->y, op->map, op);
1532
1533 return success;
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
2173
2174
2175
2176 /* create an aura spell object and put it in the player's inventory.
2177 * as usual, op is player, caster is the object casting the spell,
2178 * spell is the spell object itself.
2179 */
2180 int
2181 create_aura (object *op, object *caster, object *spell)
2182 {
2183 int refresh = 0;
2184 object *new_aura;
2185
2186 new_aura = present_arch_in_ob (spell->other_arch, op);
2187 if (new_aura)
2188 refresh = 1;
2189 else
2190 new_aura = arch_to_object (spell->other_arch);
2191
2192 new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell);
2193
2194 new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2195
2196 new_aura->set_owner (op);
2197 set_spell_skill (op, caster, spell, new_aura);
2198 new_aura->attacktype = spell->attacktype;
2199
2200 new_aura->level = caster_level (caster, spell);
2201 if (refresh)
2202 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2203 else
2204 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2205 insert_ob_in_ob (new_aura, op);
2206 return 1;
2207 }
2208
2209
2210 /* move aura function. An aura is a part of someone's inventory,
2211 * which he carries with him, but which acts on the map immediately
2212 * around him.
2213 * Aura parameters:
2214 * duration: duration counter.
2215 * attacktype: aura's attacktype
2216 * other_arch: archetype to drop where we attack
2217 */
2218
2219 void
2220 move_aura (object *aura)
2221 {
2222 int i, mflags;
2223 object *env;
2224 maptile *m;
2225
2226 /* auras belong in inventories */
2227 env = aura->env;
2228
2229 /* no matter what we've gotta remove the aura...
2230 * we'll put it back if its time isn't up.
2231 */
2232 aura->remove ();
2233
2234 /* exit if we're out of gas */
2235 if (aura->duration-- < 0)
2236 {
2237 aura->destroy ();
2238 return;
2239 }
2240
2241 /* auras only exist in inventories */
2242 if (env == NULL || env->map == NULL)
2243 {
2244 aura->destroy ();
2245 return;
2246 }
2247
2248 /* we need to jump out of the inventory for a bit
2249 * in order to hit the map conveniently.
2250 */
2251 aura->insert_at (env, aura);
2252
2253 for (i = 1; i < 9; i++)
2254 {
2255 sint16 nx, ny;
2256
2257 nx = aura->x + freearr_x[i];
2258 ny = aura->y + freearr_y[i];
2259 mflags = get_map_flags (env->map, &m, nx, ny, &nx, &ny);
2260
2261 /* Consider the movement tyep of the person with the aura as
2262 * movement type of the aura. Eg, if the player is flying, the aura
2263 * is flying also, if player is walking, it is on the ground, etc.
2264 */
2265 if (!(mflags & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (env, GET_MAP_MOVE_BLOCK (m, nx, ny))))
2266 {
2267 hit_map (aura, i, aura->attacktype, 0);
2268
2269 if (aura->other_arch)
2270 m->insert (arch_to_object (aura->other_arch), nx, ny, aura);
2271 }
2272 }
2273
2274 /* put the aura back in the player's inventory */
2275 aura->remove ();
2276 insert_ob_in_ob (aura, env);
2277 }
2278
2279 /* moves the peacemaker spell.
2280 * op is the piece object.
2281 */
2282
2283 void
2284 move_peacemaker (object *op)
2285 {
2286 object *tmp;
2287
2288 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2289 {
2290 int atk_lev, def_lev;
2291 object *victim = tmp;
2292
2293 if (tmp->head)
2294 victim = tmp->head;
2295 if (!QUERY_FLAG (victim, FLAG_MONSTER))
2296 continue;
2297 if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
2298 continue;
2299 if (victim->stats.exp == 0)
2300 continue;
2301
2302 def_lev = MAX (1, victim->level);
2303 atk_lev = MAX (1, op->level);
2304
2305 if (rndm (0, atk_lev - 1) > def_lev)
2306 {
2307 /* make this sucker peaceful. */
2308
2309 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2310 victim->stats.exp = 0;
2311 #if 0
2312 /* No idea why these were all set to zero - if something
2313 * makes this creature agressive, he should still do damage.
2314 */
2315 victim->stats.dam = 0;
2316 victim->stats.sp = 0;
2317 victim->stats.grace = 0;
2318 victim->stats.Pow = 0;
2319 #endif
2320 victim->attack_movement = RANDO2;
2321 SET_FLAG (victim, FLAG_UNAGGRESSIVE);
2322 SET_FLAG (victim, FLAG_RUN_AWAY);
2323 SET_FLAG (victim, FLAG_RANDOM_MOVE);
2324 CLEAR_FLAG (victim, FLAG_MONSTER);
2325 if (victim->name)
2326 {
2327 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2328 }
2329 }
2330 }
2331 }
2332
2333
2334 /* This writes a rune that contains the appropriate message.
2335 * There really isn't any adjustments we make.
2336 */
2337
2338 int
2339 write_mark (object *op, object *spell, const char *msg)
2340 {
2341 char rune[HUGE_BUF];
2342 object *tmp;
2343
2344 if (!msg || msg[0] == 0)
2345 {
2346 new_draw_info (NDI_UNIQUE, 0, op, "Write what?");
2347 return 0;
2348 }
2349
2350 if (strcasestr_local (msg, "endmsg"))
2351 {
2352 new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?");
2353 LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg);
2354 return 0;
2355 }
2356 if (!spell->other_arch)
2357 return 0;
2358 tmp = arch_to_object (spell->other_arch);
2359
2360 snprintf (rune, sizeof (rune), "%s\n", msg);
2361
2362 tmp->race = op->name; /*Save the owner of the rune */
2363 tmp->msg = rune;
2364
2365 tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2366 return 1;
2367 }