Mercurial > hg > early-roguelike
comparison arogue7/effects.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 08 May 2015 15:24:40 -0400 |
| parents | |
| children | b786053d2f37 |
comparison
equal
deleted
inserted
replaced
| 124:d10fc4a065ac | 125:adfa37e67084 |
|---|---|
| 1 /* | |
| 2 * effects.c - functions for dealing with appllying effects to monsters | |
| 3 * | |
| 4 * Advanced Rogue | |
| 5 * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T | |
| 6 * All rights reserved. | |
| 7 * | |
| 8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
| 9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 13 */ | |
| 14 | |
| 15 #include "curses.h" | |
| 16 #include "rogue.h" | |
| 17 | |
| 18 /* | |
| 19 * effect: | |
| 20 * Check for effects of one thing hitting another thing. Return | |
| 21 * the reason code if the defender is killed. Otherwise return 0. | |
| 22 */ | |
| 23 effect(att, def, weap, thrown, see_att, see_def) | |
| 24 register struct thing *att, *def; | |
| 25 struct object *weap; | |
| 26 bool thrown; | |
| 27 register bool see_att, see_def; | |
| 28 { | |
| 29 register bool att_player, def_player; | |
| 30 char attname[LINELEN+1], defname[LINELEN+1]; | |
| 31 | |
| 32 /* See if the attacker or defender is the player */ | |
| 33 att_player = (att == &player); | |
| 34 def_player = (def == &player); | |
| 35 | |
| 36 /* | |
| 37 * If the player could see the attacker or defender, they can't | |
| 38 * surprise anymore (don't bother checking if they could). | |
| 39 */ | |
| 40 if (see_att) turn_off(*att, CANSURPRISE); | |
| 41 if (see_def) turn_off(*def, CANSURPRISE); | |
| 42 | |
| 43 /* What are the attacker and defender names? */ | |
| 44 if (att_player) strcpy(attname, "you"); | |
| 45 else { | |
| 46 if (see_att) strcpy(attname, monster_name(att)); | |
| 47 else strcpy(attname, "something"); | |
| 48 } | |
| 49 | |
| 50 if (def_player) strcpy(defname, "you"); | |
| 51 else { | |
| 52 if (see_def) strcpy(defname, monster_name(def)); | |
| 53 else strcpy(defname, "something"); | |
| 54 } | |
| 55 | |
| 56 /* | |
| 57 * See what happens to the attacker first. We can skip this | |
| 58 * whole section, however, if the defender is the player. | |
| 59 * Nothing happens (yet) to anyone just for hitting the player. | |
| 60 */ | |
| 61 if (!def_player) { | |
| 62 if (!thrown) { /* Some things require a direct hit. */ | |
| 63 /* | |
| 64 * If the attacker hits a rusting monster, The weapon | |
| 65 * may be damaged | |
| 66 */ | |
| 67 if (on(*def, CANRUST) && weap && | |
| 68 weap->o_type != RELIC && (weap->o_flags & ISMETAL) && | |
| 69 !(weap->o_flags & ISPROT)) { | |
| 70 if ((weap->o_hplus < 1 && weap->o_dplus < 1) || | |
| 71 roll(1,20) < weap->o_hplus+weap->o_dplus+10) { | |
| 72 if (rnd(100) < 50) weap->o_hplus--; | |
| 73 else weap->o_dplus--; | |
| 74 if (att_player) | |
| 75 msg(terse ? "Your %s weakens!" | |
| 76 : "Your %s appears to be weaker now!", | |
| 77 weaps[weap->o_which].w_name); | |
| 78 } | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 /* If the attacker hit something that shrieks, wake the dungeon */ | |
| 83 if (on(*def, CANSHRIEK)) { | |
| 84 turn_off(*def, CANSHRIEK); | |
| 85 if (see_def) | |
| 86 msg("%s emits a piercing shriek.", prname(defname, TRUE)); | |
| 87 else msg("You hear a piercing shriek."); | |
| 88 aggravate(TRUE, TRUE); | |
| 89 } | |
| 90 | |
| 91 /* | |
| 92 * does the creature explode when hit? | |
| 93 */ | |
| 94 if (on(*def, CANEXPLODE)) { | |
| 95 if (see_def) msg("%s explodes!", prname(defname, TRUE)); | |
| 96 else msg("You hear a tremendous explosion!"); | |
| 97 explode(def); | |
| 98 if (pstats.s_hpt <= 0) | |
| 99 death(def->t_index); | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 /* | |
| 104 * Now let's see what happens to the defender. Start out with | |
| 105 * the things that everyone can do. Then exit if the attacker | |
| 106 * is the player. | |
| 107 */ | |
| 108 if (!thrown) { | |
| 109 /* | |
| 110 * Can the player confuse? | |
| 111 */ | |
| 112 if (on(*att, CANHUH) && att_player) { | |
| 113 msg("Your hands stop glowing red."); | |
| 114 if (off(*def, ISCLEAR) && | |
| 115 (off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) { | |
| 116 if (see_def) msg("%s appears confused.", prname(defname, TRUE)); | |
| 117 turn_on(*def, ISHUH); | |
| 118 } | |
| 119 turn_off(*att, CANHUH); | |
| 120 } | |
| 121 | |
| 122 /* Return now if the attacker is the player. */ | |
| 123 if (att_player) return(0); | |
| 124 | |
| 125 /* | |
| 126 * Some monsters may take half your hit points | |
| 127 */ | |
| 128 if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) { | |
| 129 if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */ | |
| 130 else { | |
| 131 def->t_stats.s_hpt /= 2; | |
| 132 if (def_player) | |
| 133 msg("You feel your life force being drawn from you."); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 /* | |
| 138 * If a hugging monster hits, it may SQUEEEEEEEZE. | |
| 139 */ | |
| 140 if (on(*att, CANHUG)) { | |
| 141 if (roll(1,20) >= 18 || roll(1,20) >= 18) { | |
| 142 if (def_player) | |
| 143 msg("%s squeezes you against itself.", | |
| 144 prname(attname, TRUE)); | |
| 145 else if (see_att) | |
| 146 msg("%s squeezes hard.", prname(attname, TRUE)); | |
| 147 | |
| 148 if ((def->t_stats.s_hpt -= roll(2,8)) <= 0) | |
| 149 return(att->t_index); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 /* | |
| 154 * Some monsters have poisonous bites. | |
| 155 */ | |
| 156 if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) { | |
| 157 if (def_player) { | |
| 158 if (ISWEARING(R_SUSABILITY)) | |
| 159 msg(terse ? "Sting has no effect" | |
| 160 : "A sting momentarily weakens you"); | |
| 161 else { | |
| 162 chg_str(-1); | |
| 163 msg(terse ? "A sting has weakened you" : | |
| 164 "You feel a sting in your arm and now feel weaker"); | |
| 165 } | |
| 166 } | |
| 167 else { | |
| 168 /* Subtract a strength point and see if it kills it */ | |
| 169 if (--def->t_stats.s_str <= 0) return(D_STRENGTH); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 /* | |
| 174 * Turning to stone: | |
| 175 */ | |
| 176 if (on(*att, TOUCHSTONE)) { | |
| 177 if (def_player) turn_off(*att, TOUCHSTONE); | |
| 178 if (on(*def, CANINWALL)) { | |
| 179 if (def_player) | |
| 180 msg("%s's touch has no effect.", prname(attname, TRUE)); | |
| 181 } | |
| 182 else { | |
| 183 if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) { | |
| 184 if (def_player) { | |
| 185 msg("Your body begins to solidify."); | |
| 186 msg("You are turned to stone !!! --More--"); | |
| 187 wait_for(' '); | |
| 188 return(D_PETRIFY); | |
| 189 } | |
| 190 else { | |
| 191 /* The monster got stoned! */ | |
| 192 turn_on(*def, ISSTONE); | |
| 193 turn_off(*def, ISRUN); | |
| 194 turn_off(*def, ISINVIS); | |
| 195 turn_off(*def, ISDISGUISE); | |
| 196 if (see_def) | |
| 197 msg("%s turns to stone.", prname(defname, TRUE)); | |
| 198 else if (cansee(unc(def->t_pos))) | |
| 199 msg("A new statue appears!"); | |
| 200 } | |
| 201 } | |
| 202 else if (def->t_action != A_FREEZE) { | |
| 203 if (def_player) | |
| 204 msg("%s's touch stiffens your limbs.", | |
| 205 prname(attname, TRUE)); | |
| 206 else if (see_def) | |
| 207 msg("%s appears to freeze.", prname(defname, TRUE)); | |
| 208 | |
| 209 def->t_no_move += movement(def) * STONETIME; | |
| 210 def->t_action = A_FREEZE; | |
| 211 } | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 /* | |
| 216 * Wraiths might drain energy levels | |
| 217 */ | |
| 218 if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) && | |
| 219 !save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) { | |
| 220 if (def_player) { | |
| 221 lower_level(att->t_index); | |
| 222 if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index); | |
| 223 turn_on(*att, DIDDRAIN); | |
| 224 } | |
| 225 else { | |
| 226 def->t_stats.s_hpt -= roll(1, 8); | |
| 227 def->t_stats.s_lvl--; | |
| 228 if (on(*att, DOUBLEDRAIN)) { | |
| 229 def->t_stats.s_hpt -= roll(1, 8); | |
| 230 def->t_stats.s_lvl--; | |
| 231 } | |
| 232 if (see_def) | |
| 233 msg("%s appears less skillfull.", prname(defname, TRUE)); | |
| 234 | |
| 235 /* Did it kill it? */ | |
| 236 if (def->t_stats.s_hpt <= 0 || | |
| 237 def->t_stats.s_lvl <= 0) | |
| 238 return(att->t_index); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 /* | |
| 243 * Paralyzation: | |
| 244 */ | |
| 245 if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) { | |
| 246 if (def_player) turn_off(*att, CANPARALYZE); | |
| 247 if (!save(VS_PARALYZATION, def, 0)) { | |
| 248 if (on(*def, CANINWALL)) { | |
| 249 if (def_player) | |
| 250 msg("%s's touch has no effect.", prname(attname, TRUE)); | |
| 251 } | |
| 252 else { | |
| 253 if (def_player) | |
| 254 msg("%s's touch paralyzes you.", prname(attname, TRUE)); | |
| 255 else if (see_def) | |
| 256 msg("%s appears to freeze.", prname(defname, TRUE)); | |
| 257 | |
| 258 def->t_no_move += movement(def) * FREEZETIME; | |
| 259 def->t_action = A_FREEZE; | |
| 260 } | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 /* | |
| 265 * Painful wounds make the defendant faint | |
| 266 */ | |
| 267 if (on(*att, CANPAIN) && def->t_action != A_FREEZE) { | |
| 268 if (def_player) turn_off(*att, CANPAIN); | |
| 269 if (!ISWEARING(R_ALERT) && !save(VS_POISON, def, 0)) { | |
| 270 if (def_player) | |
| 271 msg("You faint from the painful wound"); | |
| 272 else if (see_def) | |
| 273 msg("%s appears to faint.", prname(defname, TRUE)); | |
| 274 | |
| 275 def->t_no_move += movement(def) * PAINTIME; | |
| 276 def->t_action = A_FREEZE; | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 /* | |
| 281 * Some things currently affect only the player. Let's make | |
| 282 * a check here so we don't have to check for each thing. | |
| 283 */ | |
| 284 if (def_player) { | |
| 285 /* | |
| 286 * Stinking monsters make the defender weaker (to hit). For now | |
| 287 * this will only affect the player. We may later add the HASSTINK | |
| 288 * effect to monsters, too. | |
| 289 */ | |
| 290 if (on(*att, CANSTINK)) { | |
| 291 turn_off(*att, CANSTINK); | |
| 292 if (!save(VS_POISON, def, 0)) { | |
| 293 msg("The stench of %s sickens you.", | |
| 294 prname(attname, FALSE)); | |
| 295 if (on(player, HASSTINK)) lengthen(unstink, STINKTIME); | |
| 296 else { | |
| 297 turn_on(player, HASSTINK); | |
| 298 fuse(unstink, 0, STINKTIME, AFTER); | |
| 299 } | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 /* | |
| 304 * Chilling monster reduces strength each time. This only | |
| 305 * affects the player for now because of its temporary nature. | |
| 306 */ | |
| 307 if (on(*att, CANCHILL)) { | |
| 308 if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, def, 0)) { | |
| 309 msg("You cringe at %s's chilling touch.", | |
| 310 prname(attname, FALSE)); | |
| 311 chg_str(-1); | |
| 312 if (lost_str++ == 0) | |
| 313 fuse(res_strength, 0, CHILLTIME, AFTER); | |
| 314 else lengthen(res_strength, CHILLTIME); | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 /* | |
| 319 * Itching monsters reduce dexterity (temporarily). This only | |
| 320 * affects the player for now because of its temporary nature. | |
| 321 */ | |
| 322 if (on(*att, CANITCH) && !save(VS_POISON, def, 0)) { | |
| 323 msg("The claws of %s scratch you.", prname(attname, FALSE)); | |
| 324 if (ISWEARING(R_SUSABILITY)) { | |
| 325 msg("The scratch has no effect"); | |
| 326 } | |
| 327 else { | |
| 328 add_abil[A_DEXTERITY](-1); | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 | |
| 333 /* | |
| 334 * If a disease-carrying monster hits, there is a chance the | |
| 335 * defender will catch the disease. This only applies to the | |
| 336 * player for now because of the temporary nature. | |
| 337 */ | |
| 338 if (on(*att, CANDISEASE) && | |
| 339 (rnd(def->t_stats.s_const) < att->t_stats.s_lvl) && | |
| 340 off(*def, HASDISEASE)) { | |
| 341 if (ISWEARING(R_HEALTH) || | |
| 342 player.t_ctype == C_PALADIN || | |
| 343 player.t_ctype == C_MONK) { | |
| 344 msg("The wound heals quickly."); | |
| 345 } | |
| 346 else { | |
| 347 turn_on(*def, HASDISEASE); | |
| 348 fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER); | |
| 349 msg(terse ? "You have been diseased." | |
| 350 : "You have contracted a disease!"); | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 /* | |
| 355 * If a rusting monster hits, you lose armor. This only applies to | |
| 356 * the player because monsters don't wear armor (for now). | |
| 357 */ | |
| 358 if (on(*att, CANRUST)) { | |
| 359 if (cur_armor != NULL && | |
| 360 cur_armor->o_which != LEATHER && | |
| 361 cur_armor->o_which != STUDDED_LEATHER && | |
| 362 cur_armor->o_which != PADDED_ARMOR && | |
| 363 !(cur_armor->o_flags & ISPROT) && | |
| 364 cur_armor->o_ac < def->t_stats.s_arm+1) { | |
| 365 msg(terse ? "Your armor weakens" | |
| 366 : "Your armor appears to be weaker now. Oh my!"); |
