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!");