Mercurial > hg > early-roguelike
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 | |