diff xrogue/effects.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/effects.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,721 @@
+/*
+    effects.c  -  functions for dealing with appllying effects to monsters
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * effect:
+ *      Check for effects of one thing hitting another thing.  Return
+ *      the reason code if the defender is killed.  Otherwise return 0.
+ */
+
+effect(att, def, weap, thrown, see_att, see_def)
+register struct thing *att, *def;
+struct object *weap;
+bool thrown;
+register bool see_att, see_def;
+{
+    register bool att_player, def_player;
+    char attname[LINELEN+1], defname[LINELEN+1];
+
+    /* See if the attacker or defender is the player */
+    att_player = (att == &player);
+    def_player = (def == &player);
+
+    /*
+     * If the player could see the attacker or defender, they can't
+     * surprise anymore (don't bother checking if they could).
+     */
+    if (see_att) turn_off(*att, CANSURPRISE);
+    if (see_def) turn_off(*def, CANSURPRISE);
+
+    /* What are the attacker and defender names? */
+    if (att_player) strcpy(attname, "you");
+    else {
+        if (see_att) strcpy(attname, monster_name(att));
+        else strcpy(attname, "something");
+    }
+
+    if (def_player) strcpy(defname, "you");
+    else {
+        if (see_def) strcpy(defname, monster_name(def));
+        else strcpy(defname, "something");
+    }
+
+    /*
+     * See what happens to the attacker first.  We can skip this
+     * whole section, however, if the defender is the player.
+     * Nothing happens (yet) to anyone just for hitting the player.
+     */
+    if (!def_player) {
+        if (!thrown) {  /* Some things require a direct hit. */
+            /*
+             * If the attacker hits a rusting monster, The weapon
+             * may be damaged
+             */
+            if (on(*def, CANRUST)       && weap                         &&
+                weap->o_type != RELIC   && (weap->o_flags & ISMETAL)    &&
+                !(weap->o_flags & ISPROT)) {
+                    if ((weap->o_hplus < 1 && weap->o_dplus < 1) ||
+                        roll(1,20) < weap->o_hplus+weap->o_dplus+10) {
+                            if (rnd(100) < 50) weap->o_hplus--;
+                            else               weap->o_dplus--;
+                            if (att_player)
+                                msg(terse ? "Your %s weakens!"
+                                          : "Your %s gets weaker!",
+                                    weaps[weap->o_which].w_name);
+                    }
+            }
+        }
+                
+        /* If the attacker hit something that shrieks, wake the dungeon */
+        if (on(*def, CANSHRIEK)) {
+            if (see_def)
+                msg("%s emits an ear piercing shriek! ", prname(defname, TRUE));
+            else
+                msg("You hear an ear piercing shriek!");
+
+            /* Friendly charactors should be immune */
+            if (player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER  || player.t_ctype == C_MONK)
+                    aggravate(TRUE, FALSE);
+            else
+                aggravate(TRUE, TRUE);
+        }
+
+        /*
+         * does the creature explode when hit?
+         */
+        if (on(*def, CANEXPLODE)) {
+            if (see_def) msg("%s explodes!", prname(defname, TRUE));
+            else msg("You hear a tremendous explosion!");
+            explode(def);
+            if (pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+                death(def->t_index);
+        }
+        }
+    }
+
+    /*
+     * Now let's see what happens to the defender.  Start out with
+     * the things that everyone can do.  Then exit if the attacker
+     * is the player.
+     */
+    if (!thrown) {
+        /* 
+         * Can the player confuse? 
+         */
+        if (on(*att, CANHUH) && att_player) {
+            msg("Your hands return to normal. ");
+            if (off(*def, ISCLEAR) && 
+               (off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) {
+                if (see_def) msg("%s appears confused!", prname(defname, TRUE));
+                turn_on(*def, ISHUH);
+            }
+            turn_off(*att, CANHUH);
+        }
+
+        /* Return now if the attacker is the player. */
+        if (att_player) return(0);
+
+        /*
+         * Some monsters may take half your hit points
+         */
+        if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) {
+            if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */
+            else {
+                def->t_stats.s_hpt /= 2;
+                if (def_player)
+                    msg("Your life force is being drained out of you.");
+            }
+        }
+
+        /*
+         * If a hugging monster hits, it may SQUEEEEEEEZE.
+         */
+        if (on(*att, CANHUG)) {
+            if (roll(1,20) >= 18 || roll(1,20) >= 18) {
+                if (def_player)
+                    msg("%s squeezes itself nastily against you!",
+                                prname(attname, TRUE));
+                else if (see_att)
+                    msg("%s squeezes real hard!", prname(attname, TRUE));
+
+                if ((def->t_stats.s_hpt -= roll(2,8)) <= 0)
+                    return(att->t_index);
+            }
+        }
+
+        /*
+         * Some monsters have poisonous bites.
+         */
+        if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) {
+            if (def_player) {
+                if (ISWEARING(R_SUSABILITY))
+                    msg(terse ? "Sting has no effect."
+                              : "A sting momentarily weakens your arm.");
+                else {
+                    chg_str(-1);
+                    msg(terse ? "A sting has weakened you." :
+                    "You get stung in the arm!  You feel weaker. ");
+                }
+            }
+            else {
+                /* Subtract a strength point and see if it kills it */
+                if (--def->t_stats.s_str <= 0) return(D_STRENGTH);
+            }
+        }
+
+        /*
+         * Turning to stone:
+         */
+        if (on(*att, TOUCHSTONE)) {
+            if (def_player) turn_off(*att, TOUCHSTONE);
+            if (on(*def, CANINWALL)) {
+                if (def_player)
+                    msg("%s's touch has no effect.", prname(attname, TRUE));
+            }
+            else {
+                if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) {
+                    if (def_player) {
+                        msg("Your body begins to solidify.. ");
+                        msg("You are transformed into stone!! --More--");
+                        wait_for(' ');
+                        return(D_PETRIFY);
+                    }
+                    else {
+                        /* The monster got stoned! */
+                        turn_on(*def, ISSTONE);
+                        turn_off(*def, ISRUN);
+                        turn_off(*def, ISINVIS);
+                        turn_off(*def, ISDISGUISE);
+                        if (def->t_stats.s_intel > 15)
+                            msg("%s staggers.. ", prname(defname, TRUE));
+                        else if (see_def)
+                            msg("%s turns to stone! ", prname(defname, TRUE));
+                        else if (cansee(unc(def->t_pos)))
+                            msg("A statue appears out of nowhere! ");
+                    }
+                }
+                else if (def->t_action != A_FREEZE) {
+                    if (def_player)
+                        msg("%s's touch stiffens your limbs.",
+                                        prname(attname, TRUE));
+                    else if (see_def)
+                        msg("%s appears to freeze over.", prname(defname, TRUE));
+
+                    def->t_no_move += movement(def) * STONETIME;
+                    def->t_action = A_FREEZE;
+                }
+            }
+        }
+
+        /*
+         * Wraiths might drain energy levels
+         */
+        if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) && 
+            !save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) {
+            if (def_player) {
+                lower_level(att->t_index);
+                if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index);
+                turn_on(*att, DIDDRAIN);  
+            }
+            else {
+                def->t_stats.s_hpt -= roll(1, 8);
+                def->t_stats.s_lvl--;
+                if (on(*att, DOUBLEDRAIN)) {
+                    def->t_stats.s_hpt -= roll(1, 8);
+                    def->t_stats.s_lvl--;
+                }
+                if (see_def)
+                    msg("%s appears less skillful.", prname(defname, TRUE));
+
+                /* Did it kill it? */
+                if (def->t_stats.s_hpt <= 0 ||
+                    def->t_stats.s_lvl <= 0)
+                    return(att->t_index);
+            }
+        }
+
+        /*
+         * Paralyzation:
+         */
+        if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) {
+            if (def_player) turn_off(*att, CANPARALYZE);
+            if (!save(VS_PARALYZATION, def, 0)) {
+                if (on(*def, CANINWALL)) {
+                    if (def_player)
+                        msg("%s's touch has no effect.", prname(attname, TRUE));
+                }
+                else {
+                    if (def_player)
+                        msg("%s's touch paralyzes you.", prname(attname, TRUE));
+                    else if (see_def)
+                        msg("%s appears to freeze over!", prname(defname, TRUE));
+
+                    def->t_no_move += movement(def) * FREEZETIME;
+                    def->t_action = A_FREEZE;
+                }
+            }