ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.61
Committed: Sun Jun 24 16:11:51 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.60: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

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