ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.27
Committed: Tue Dec 26 20:04:09 2006 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.26: +47 -79 lines
Log Message:
- added maptile->insert and object->insert_at methods that might
  make code using it clearer.
- replaced some insert_ob_in_map calls.

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