ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.54
Committed: Mon May 28 21:28:36 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.53: +17 -17 lines
Log Message:
update copyrights in server/*.C

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