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