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