ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.52
Committed: Thu May 17 14:14:55 2007 UTC (17 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.51: +0 -10 lines
Log Message:
remove superfluous/broken settings and related code

- COZY_SERVER:
  enabled most msall adjustments, changed digestion formula to the original one,
  party member treament w.r.t. pets enforced.
- PROHIBIT_PLAYERKILL: default
- real_wiz: removed and enforced
- create_home_portals: removed and enforced
- casting_time: removed and forced to be off (was crashing anyways)
- was_wiz flag removed and treated as off usually unless it was used
  in place of flag_wiz.
- do not save or restore wiz, wizcast and wizpass flags.

File Contents

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