ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.8
Committed: Sun Sep 10 15:59:57 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +2209 -1895 lines
Log Message:
indent

File Contents

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