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