ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.59
Committed: Sun Jun 10 10:16:04 2007 UTC (16 years, 11 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.58: +5 -1 lines
Log Message:
fixed create food spell a bit to have less dependency on
archetype order

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