ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.28
Committed: Sat Dec 30 10:16:11 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.27: +10 -19 lines
Log Message:
preliminary snapshot check-in, DO NOT USE IN PRODUCTION SYSTEMS
See the Changes file for details

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