ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.11
Committed: Thu Sep 14 22:34:05 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.10: +1 -8 lines
Log Message:
indent

File Contents

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