ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.74
Committed: Tue Oct 16 00:30:25 2007 UTC (16 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.73: +11 -15 lines
Log Message:
- implement archetype->instance as replacement for arch_to_object
  (better name?)
- fix arrows merging with stuff on floor
- fix level_for_item to read more clearfly, do not use drand48
  and fix the random level generation when !level set.
- splay arrow container in find_arrow (but searching containers is still borked?)
- improve create_missile spell.

File Contents

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