Mercurial > hg > early-roguelike
comparison xrogue/sticks.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 sticks.c - Functions to implement the various sticks one might find | |
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 <ctype.h> | |
21 #include "rogue.h" | |
22 | |
23 /* | |
24 * zap a stick and see what happens | |
25 */ | |
26 | |
27 do_zap(zapper, obj, direction, which, flags) | |
28 struct thing *zapper; | |
29 struct object *obj; | |
30 coord *direction; | |
31 int which; | |
32 int flags; | |
33 { | |
34 register struct linked_list *item = NULL; | |
35 register struct thing *tp; | |
36 register int y = 0, x = 0, bonus; | |
37 struct linked_list *nitem; | |
38 struct object *nobj; | |
39 bool cursed, blessed, is_player = FALSE; | |
40 char *mname = NULL; | |
41 | |
42 cursed = flags & ISCURSED; | |
43 blessed = flags & ISBLESSED; | |
44 | |
45 if (obj && obj->o_type != RELIC) { /* all relics are chargeless */ | |
46 if (obj->o_charges < 1) { | |
47 msg(nothing); | |
48 return; | |
49 } | |
50 obj->o_charges--; | |
51 } | |
52 if (which == WS_WONDER) { | |
53 switch (rnd(19)) { | |
54 case 0: which = WS_ELECT; | |
55 when 1: which = WS_FIRE; | |
56 when 2: which = WS_COLD; | |
57 when 3: which = WS_POLYMORPH; | |
58 when 4: which = WS_MISSILE; | |
59 when 5: which = WS_SLOW_M; | |
60 when 6: which = WS_TELMON; | |
61 when 7: which = WS_CANCEL; | |
62 when 8: which = WS_CONFMON; | |
63 when 9: which = WS_DISINTEGRATE; | |
64 when 10: which = WS_PETRIFY; | |
65 when 11: which = WS_PARALYZE; | |
66 when 12: which = WS_MDEG; | |
67 when 13: which = WS_FEAR; | |
68 when 14: which = WS_CURING; | |
69 when 15: which = WS_LIGHT; | |
70 when 16: which = WS_HIT; | |
71 when 17: which = WS_DRAIN; | |
72 when 18: which = WS_CHARGE; | |
73 } | |
74 if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){ | |
75 cursed = TRUE; | |
76 blessed = FALSE; | |
77 } | |
78 } | |
79 | |
80 tp = NULL; | |
81 switch (which) { | |
82 case WS_POLYMORPH: | |
83 case WS_SLOW_M: | |
84 case WS_TELMON: | |
85 case WS_CANCEL: | |
86 case WS_CONFMON: | |
87 case WS_DISINTEGRATE: | |
88 case WS_PETRIFY: | |
89 case WS_PARALYZE: | |
90 case WS_MDEG: | |
91 case WS_FEAR: | |
92 y = zapper->t_pos.y; | |
93 x = zapper->t_pos.x; | |
94 | |
95 do { | |
96 y += direction->y; | |
97 x += direction->x; | |
98 } | |
99 while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x)); | |
100 | |
101 if (y == hero.y && x == hero.x) | |
102 is_player = TRUE; | |
103 else if (isalpha(mvwinch(mw, y, x))) { | |
104 item = find_mons(y, x); | |
105 tp = THINGPTR(item); | |
106 runto(tp, &hero); | |
107 turn_off(*tp, CANSURPRISE); | |
108 mname = monster_name(tp); | |
109 is_player = FALSE; | |
110 | |
111 /* The monster may not like being shot at */ | |
112 if ((zapper == &player) && | |
113 on(*tp, ISCHARMED) && | |
114 save(VS_MAGIC, tp, 0)) { | |
115 msg("The eyes of %s turn clear.", prname(mname, FALSE)); | |
116 turn_off(*tp, ISCHARMED); | |
117 mname = monster_name(tp); | |
118 } | |
119 } | |
120 else { | |
121 /* | |
122 * if monster misses player because the player dodged then lessen | |
123 * the chances he will use the wand again since the player appears | |
124 * to be rather dextrous | |
125 */ | |
126 if (zapper != &player) | |
127 zapper->t_wand = zapper->t_wand * 3 / 5; | |
128 } | |
129 } | |
130 switch (which) { | |
131 case WS_LIGHT: | |
132 /* | |
133 * Reddy Kilowat wand. Light up the room | |
134 */ | |
135 blue_light(blessed, cursed); | |
136 when WS_DRAIN: | |
137 /* | |
138 * Take away 1/2 of hero's hit points, then take it away | |
139 * evenly from the monsters in the room or next to hero | |
140 * if he is in a passage (but leave the monsters alone | |
141 * if the stick is cursed) | |
142 */ | |
143 if (pstats.s_hpt < 2) { | |
144 msg("You are too weak to use it."); | |
145 } | |
146 else if (cursed) | |
147 pstats.s_hpt /= 2; | |
148 if (pstats.s_hpt <= 0) { | |
149 pstats.s_hpt = -1; | |
150 msg("You drain your own life away. --More--"); | |
151 death(D_STRENGTH); | |
152 } | |
153 else | |
154 drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1); | |
155 | |
156 when WS_POLYMORPH: | |
157 { | |
158 register char oldch; | |
159 register struct room *rp; | |
160 register struct linked_list *pitem; | |
161 coord delta; | |
162 | |
163 if (tp == NULL) | |
164 break; | |
165 if (save(VS_MAGIC, tp, 0)) { | |
166 msg(nothing); | |
167 break; | |
168 } | |
169 rp = roomin(&tp->t_pos); | |
170 check_residue(tp); | |
171 delta.x = x; | |
172 delta.y = y; | |
173 detach(mlist, item); | |
174 oldch = tp->t_oldch; | |
175 pitem = tp->t_pack; /* save his pack */ | |
176 tp->t_pack = NULL; | |
177 | |
178 if (levtype == OUTSIDE) | |
179 new_monster(item,rnd(NUMDINOS)+NUMMONST-NUMDINOS,&delta,FALSE); | |
180 else | |
181 new_monster(item,rnd(NUMMONST-NUMUNIQUE-NUMDINOS-1)+1,&delta,FALSE); | |
182 | |
183 if (tp->t_pack != NULL) | |
184 o_free_list (tp->t_pack); | |
185 tp->t_pack = pitem; | |
186 if (isalpha(mvwinch(cw, y, x))) | |
187 mvwaddch(cw, y, x, tp->t_type); | |
188 tp->t_oldch = oldch; | |
189 /* | |
190 * should the room light up? | |
191 */ | |
192 if (on(*tp, HASFIRE)) { | |
193 if (rp) { | |
194 register struct linked_list *fire_item; | |
195 | |
196 fire_item = creat_item(); | |
197 ldata(fire_item) = (char *) tp; | |
198 attach(rp->r_fires, fire_item); | |
199 rp->r_flags |= HASFIRE; | |
200 if (cansee(tp->t_pos.y,tp->t_pos.x) && | |
201 next(rp->r_fires) == NULL) light(&hero); | |
202 } | |
203 } | |
204 runto(tp, &hero); | |
205 msg(terse ? "A new %s!" | |
206 : "You have created a new %s!", | |
207 monster_name(tp)); | |
208 } | |
209 | |
210 when WS_PETRIFY: | |
211 if (tp == NULL) | |
212 break; | |
213 if (save(VS_MAGIC, tp, 0)) { | |
214 msg(nothing); | |
215 break; | |
216 } | |
217 check_residue(tp); | |
218 turn_on(*tp, ISSTONE); | |
219 turn_on(*tp, NOSTONE); | |
220 turn_off(*tp, ISRUN); | |
221 turn_off(*tp, ISINVIS); | |
222 turn_off(*tp, CANSURPRISE); | |
223 turn_off(*tp, ISDISGUISE); | |
224 tp->t_action = A_NIL; | |
225 tp->t_no_move = 0; | |
226 msg("%s is turned to stone!",prname(mname, TRUE)); | |
227 | |
228 when WS_TELMON: | |
229 { | |
230 register int rm; | |
231 register struct room *rp; | |
232 | |
233 if (tp == NULL) | |
234 break; | |
235 if (save(VS_MAGIC, tp, 0)) { | |
236 msg(nothing); | |
237 break; | |
238 } | |
239 rp = NULL; | |
240 check_residue(tp); | |
241 tp->t_action = A_FREEZE; /* creature is disoriented */ | |
242 tp->t_no_move = 2; | |
243 if (cursed) { /* Teleport monster to player */ | |
244 if ((y == (hero.y + direction->y)) && | |
245 (x == (hero.x + direction->x))) | |
246 msg(nothing); | |
247 else { | |
248 tp->t_pos.y = hero.y + direction->y; | |
249 tp->t_pos.x = hero.x + direction->x; | |
250 } | |
251 } | |
252 else if (blessed) { /* Get rid of monster */ | |
253 killed(item, FALSE, TRUE, TRUE); | |
254 return; | |
255 } | |
256 else { | |
257 register int i=0; | |
258 | |
259 do { /* Move monster to another room */ | |
260 rm = rnd_room(); | |
261 rnd_pos(&rooms[rm], &tp->t_pos); | |
262 }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500); | |
263 rp = &rooms[rm]; | |
264 } | |
265 | |
266 /* Now move the monster */ | |
267 if (isalpha(mvwinch(cw, y, x))) | |
268 mvwaddch(cw, y, x, tp->t_oldch); | |
269 mvwaddch(mw, y, x, ' '); | |
270 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type); | |
271 if (tp->t_pos.y != y || tp->t_pos.x != x) | |
272 tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x); | |
273 /* | |
274 * check to see if room that creature appears in should | |
275 * light up | |
276 */ | |
277 if (on(*tp, HASFIRE)) { | |
278 if (rp) { | |
279 register struct linked_list *fire_item; | |
280 | |
281 fire_item = creat_item(); | |
282 ldata(fire_item) = (char *) tp; | |
283 attach(rp->r_fires, fire_item); | |
284 rp->r_flags |= HASFIRE; | |
285 if(cansee(tp->t_pos.y, tp->t_pos.x) && | |
286 next(rp->r_fires) == NULL) | |
287 light(&hero); | |
288 } | |
289 } | |
290 } | |
291 when WS_CANCEL: | |
292 if (tp == NULL) | |
293 break; | |
294 if (save(VS_MAGIC, tp, 0)) { | |
295 msg(nothing); | |
296 break; | |
297 } | |
298 check_residue(tp); | |
299 tp->t_flags[0] &= CANC0MASK; | |
300 tp->t_flags[1] &= CANC1MASK; | |
301 tp->t_flags[2] &= CANC2MASK; | |
302 tp->t_flags[3] &= CANC3MASK; | |
303 tp->t_flags[4] &= CANC4MASK; | |
304 tp->t_flags[5] &= CANC5MASK; | |
305 tp->t_flags[6] &= CANC6MASK; | |
306 tp->t_flags[7] &= CANC7MASK; | |
307 tp->t_flags[8] &= CANC8MASK; | |
308 tp->t_flags[9] &= CANC9MASK; | |
309 tp->t_flags[10] &= CANCAMASK; | |
310 tp->t_flags[11] &= CANCBMASK; | |
311 tp->t_flags[12] &= CANCCMASK; | |
312 tp->t_flags[13] &= CANCDMASK; | |
313 tp->t_flags[14] &= CANCEMASK; | |
314 tp->t_flags[15] &= CANCFMASK; | |
315 | |
316 when WS_MISSILE: | |
317 { | |
318 int dice; | |
319 static struct object bolt = | |
320 { | |
321 MISSILE , {0, 0}, 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1 | |
322 }; | |
323 | |
324 if (!obj) | |
325 dice = zapper->t_stats.s_lvl; | |
326 if (obj->o_type == RELIC) | |
327 dice = 15; | |
328 else if (EQUAL(ws_type[which], "staff")) | |
329 dice = 10; | |
330 else | |
331 dice = 6; | |
332 sprintf(bolt.o_hurldmg, "%dd4", dice); | |
333 do_motion(&bolt, direction->y, direction->x, zapper); | |
334 if (!hit_monster(unc(bolt.o_pos), &bolt, zapper)) | |
335 msg("The missile vanishes with a puff of smoke"); | |
336 } | |
337 when WS_HIT: | |
338 { | |
339 register unsigned char ch; | |
340 struct object strike; /* don't want to change sticks attributes */ | |
341 | |
342 direction->y += hero.y; | |
343 direction->x += hero.x; | |
344 ch = winat(direction->y, direction->x); | |
345 if (isalpha(ch)) | |
346 { | |
347 strike = *obj; | |
348 strike.o_hplus = 7; | |
349 if (EQUAL(ws_type[which], "staff")) | |
350 strcpy(strike.o_damage,"3d8"); | |
351 else | |
352 strcpy(strike.o_damage,"2d8"); | |
353 fight(direction, &strike, FALSE); | |
354 } | |
355 } | |
356 when WS_SLOW_M: | |
357 if (is_player) { | |
358 add_slow(); | |
359 break; | |
360 } | |
361 if (tp == NULL) | |
362 break; | |
363 if (cursed) { | |
364 if (on(*tp, ISSLOW)) | |
365 turn_off(*tp, ISSLOW); | |
366 else | |
367 turn_on(*tp, ISHASTE); | |
368 break; | |
369 } | |
370 if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) { | |
371 msg(nothing); | |
372 break; | |
373 } | |
374 else if (blessed) { | |
375 turn_off(*tp, ISRUN); | |
376 turn_on(*tp, ISHELD); | |
377 } | |
378 /* | |
379 * always slow in case he breaks free of HOLD | |
380 */ | |
381 if (on(*tp, ISHASTE)) | |
382 turn_off(*tp, ISHASTE); | |
383 else | |
384 turn_on(*tp, ISSLOW); | |
385 | |
386 when WS_CHARGE: | |
387 if (ws_know[WS_CHARGE] != TRUE && obj) | |
388 msg("This is a wand of charging."); | |
389 nitem = get_item(pack, "charge", STICK, FALSE, FALSE); | |
390 if (nitem != NULL) { | |
391 nobj = OBJPTR(nitem); | |
392 if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT)) | |
393 fix_stick(nobj); | |
394 if (blessed) ++(nobj->o_charges); | |
395 if (EQUAL(ws_type[nobj->o_which], "staff")) { | |
396 if (nobj->o_charges > 200) | |
397 nobj->o_charges = 200; | |
398 } | |
399 else { | |
400 if (nobj->o_charges > 200) | |
401 nobj->o_charges = 200; | |
402 } | |
403 } | |
404 when WS_ELECT: | |
405 shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, | |
406 "lightning bolt", roll(zapper->t_stats.s_lvl,6)); | |
407 | |
408 when WS_FIRE: | |
409 shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, | |
410 "flame", roll(zapper->t_stats.s_lvl,6)); | |
411 | |
412 when WS_COLD: | |
413 shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, | |
414 "ice", roll(zapper->t_stats.s_lvl,6)); | |
415 | |
416 when WS_CONFMON: | |
417 if (cursed || is_player) { | |
418 if (!save(VS_WAND, &player, 0)) { | |
419 dsrpt_player(); | |
420 confus_player(); | |
421 } | |
422 else { | |
423 if (zapper != &player) zapper->t_wand /= 2; | |
424 msg(nothing); | |
425 } | |
426 } | |
427 else { | |
428 if (tp == NULL) | |
429 break; | |
430 if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR)) | |
431 msg(nothing); | |
432 else | |
433 turn_on (*tp, ISHUH); | |
434 } | |
435 when WS_PARALYZE: | |
436 if (is_player || cursed) { | |
437 if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){ | |
438 player.t_no_move += 2 * movement(&player) * FREEZETIME; | |
439 player.t_action = A_FREEZE; | |
440 msg("You can't move."); | |
441 } | |
442 else { | |
443 if (zapper != &player) zapper->t_wand /= 2; | |
444 msg(nothing); | |
445 } | |
446 } | |
447 else { | |
448 if (tp == NULL) | |
449 break; | |
450 bonus = 0; | |
451 if (blessed) bonus = -3; | |
452 if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) && | |
453 off(*tp, NOPARALYZE)) { | |
454 tp->t_no_move += 2 * movement(tp) * FREEZETIME; | |
455 tp->t_action = A_FREEZE; | |
456 } | |
457 else { | |
458 msg(nothing); | |
459 } | |
460 } | |
461 when WS_FEAR: | |
462 if (is_player) { | |
463 if (!on(player, ISFLEE) || | |
464 ISWEARING(R_HEROISM) || | |
465 save(VS_WAND, &player, 0)) { | |
466 msg(nothing); | |
467 zapper->t_wand /= 2; | |
468 } | |
469 else { | |
470 turn_on(player, ISFLEE); | |
471 player.t_dest = &zapper->t_pos; | |
472 msg("The sight of %s terrifies you.", prname(mname, FALSE)); | |
473 } | |
474 break; | |
475 } | |
476 if (tp == NULL) | |
477 break; | |
478 bonus = 0; | |
479 if (blessed) bonus = -3; | |
480 if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){ | |
481 msg(nothing); | |
482 break; | |
483 } | |
484 turn_on(*tp, ISFLEE); | |
485 turn_on(*tp, WASTURNED); | |
486 | |
487 /* Stop it from attacking us */ | |
488 dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x)); | |
489 | |
490 /* If monster was suffocating, stop it */ | |
491 if (on(*tp, DIDSUFFOCATE)) { | |
492 turn_off(*tp, DIDSUFFOCATE); | |
493 extinguish(suffocate); | |
494 } | |
495 | |
496 /* If monster held us, stop it */ | |
497 if (on(*tp, DIDHOLD) && (--hold_count == 0)) | |
498 turn_off(player, ISHELD); | |
499 turn_off(*tp, DIDHOLD); | |
500 | |
501 /* It is okay to turn tail */ | |
502 tp->t_oldpos = tp->t_pos; | |
503 | |
504 when WS_MDEG: | |
505 if (is_player) { | |
506 if (save(VS_WAND, &player, 0)) { | |
507 msg (nothing); | |
508 zapper->t_wand /= 2; | |
509 break; | |
510 } | |
511 pstats.s_hpt /= 2; | |
512 if (pstats.s_hpt <= 0) { | |
513 pstats.s_hpt = -1; | |
514 msg("Your life has been sucked out from you! --More--"); | |
515 wait_for(' '); | |
516 death(zapper); | |
517 } | |
518 else | |
519 msg("You feel a great drain on your system."); | |
520 } | |
521 if (tp == NULL) | |
522 break; | |
523 if (cursed) { | |
524 tp->t_stats.s_hpt *= 2; | |
525 msg("%s appears to be stronger now!", prname(mname, TRUE)); | |
526 } | |
527 else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0)) | |
528 msg (nothing); | |
529 else { | |
530 tp->t_stats.s_hpt /= 2; | |
531 msg("%s appears to be weaker now", prname(mname, TRUE)); | |
532 } | |
533 if (tp->t_stats.s_hpt < 1) | |
534 killed(item, TRUE, TRUE, TRUE); | |
535 when WS_DISINTEGRATE: | |
536 if (tp == NULL) | |
537 break; | |
538 if (cursed) { | |
539 register int m1, m2; | |
540 coord mp; | |
541 struct linked_list *titem; | |
542 char ch; | |
543 struct thing *th; | |
544 | |
545 if (on(*tp, ISUNIQUE) || on(*tp, CANSELL)) { | |
546 msg (nothing); | |
547 break; | |
548 } | |
549 for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) { | |
550 for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) { | |
551 if (m1 == hero.x && m2 == hero.y) | |
552 continue; | |
553 ch = winat(m2,m1); | |
554 if (shoot_ok(ch)) { | |
555 mp.x = m1; /* create it */ | |
556 mp.y = m2; | |
557 titem = new_item(sizeof(struct thing)); | |
558 new_monster(titem,(short)tp->t_index,&mp,FALSE); | |
559 th = THINGPTR(titem); | |
560 turn_on (*th, ISMEAN); | |
561 runto(th,&hero); | |
562 if (on(*th, HASFIRE)) { | |
563 register struct room *rp; | |
564 | |
565 rp = roomin(&th->t_pos); | |
566 if (rp) { | |
567 register struct linked_list *fire_item; | |
568 | |
569 fire_item = creat_item(); | |
570 ldata(fire_item) = (char *) th; | |
571 attach(rp->r_fires, fire_item); | |
572 rp->r_flags |= HASFIRE; | |
573 if (cansee(th->t_pos.y, th->t_pos.x) && | |
574 next(rp->r_fires) == NULL) | |
575 light(&hero); | |
576 } | |
577 } | |
578 } | |
579 } | |
580 } | |
581 } | |
582 else { /* if its a UNIQUE it might still live */ | |
583 if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) { | |
584 tp->t_stats.s_hpt /= 2; | |
585 if (tp->t_stats.s_hpt < 1) { | |
586 killed(item, FALSE, TRUE, TRUE); | |
587 msg("You have disintegrated %s", prname(mname, FALSE)); | |
588 } | |
589 else { | |
590 msg("%s appears wounded", prname(mname, TRUE)); | |
591 } | |
592 } | |
593 else { | |
594 msg("You have disintegrated %s", prname(mname, FALSE)); | |
595 killed (item, FALSE, TRUE, TRUE); | |
596 } | |
597 } | |
598 when WS_CURING: | |
599 if (cursed) { | |
600 bool sick = FALSE; | |
601 if (!save(VS_POISON, &player, 0)) { | |
602 msg("You feel extremely sick. "); | |
603 sick = TRUE; | |
604 pstats.s_hpt -= (pstats.s_hpt/3)+1; | |
605 if (pstats.s_hpt == 0) { | |
606 pstats.s_hpt = -1; | |
607 msg("You die! --More--"); | |
608 wait_for(' '); | |
609 death (D_POISON); | |
610 } | |
611 } | |
612 if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) { | |
613 turn_on(player, HASDISEASE); | |
614 turn_on(player, HASINFEST); | |
615 turn_on(player, DOROT); | |
616 fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME), AFTER); | |
617 infest_dam++; | |
618 } | |
619 else if (sick == FALSE) msg("You feel momentarily sick"); | |
620 } | |
621 else { | |
622 if (on(player, HASDISEASE) || on(player, HASINFEST)) { | |
623 extinguish(cure_disease); | |
624 turn_off(player, HASINFEST); | |
625 infest_dam = 0; | |
626 cure_disease(); /* this prints message */ | |
627 } | |
628 if (on(player, DOROT)) { | |
629 msg("You feel your skin returning to normal."); | |
630 turn_off(player, DOROT); | |
631 } | |
632 pstats.s_hpt += roll(pstats.s_lvl, blessed ? 9 : 6); | |
633 if (pstats.s_hpt > max_stats.s_hpt) | |
634 pstats.s_hpt = max_stats.s_hpt; | |
635 msg("You begin to feel %sbetter.", blessed ? "much " : ""); | |
636 | |
637 } | |
638 otherwise: | |
639 msg("What a bizarre schtick!"); | |
640 } | |
641 } | |
642 | |
643 | |
644 /* | |
645 * drain: | |
646 * Do drain hit points from player shtick | |
647 */ | |
648 | |
649 drain(ymin, ymax, xmin, xmax) | |
650 int ymin, ymax, xmin, xmax; | |
651 { | |
652 register int i, j, count; | |
653 register struct thing *ick; | |
654 register struct linked_list *item; | |
655 | |
656 /* | |
657 * First count how many things we need to spread the hit points among | |
658 */ | |
659 count = 0; | |
660 for (i = ymin; i <= ymax; i++) { | |
661 if (i < 1 || i > lines - 3) | |
662 continue; | |
663 for (j = xmin; j <= xmax; j++) { | |
664 if (j < 0 || j > cols - 1) | |
665 continue; | |
666 if (isalpha(mvwinch(mw, i, j))) | |
667 count++; | |
668 } | |
669 } | |
670 if (count == 0) | |
671 { | |
672 msg("You have a tingling feeling."); | |
673 return; | |
674 } | |
675 count = pstats.s_hpt / count; | |
676 pstats.s_hpt /= 2; | |
677 if (pstats.s_hpt <= 0) { | |
678 pstats.s_hpt = -1; | |
679 msg("Aarrgghhh!! --More--"); | |
680 wait_for(' '); | |
681 death(D_STRENGTH); | |
682 } | |
683 /* | |
684 * Now zot all of the monsters | |
685 */ | |
686 for (i = ymin; i <= ymax; i++) { | |
687 if (i < 1 || i > lines - 3) | |
688 continue; | |
689 for (j = xmin; j <= xmax; j++) { | |
690 if (j < 0 || j > cols - 1) | |
691 continue; | |
692 if (isalpha(mvwinch(mw, i, j)) && | |
693 ((item = find_mons(i, j)) != NULL)) { | |
694 ick = THINGPTR(item); | |
695 if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0)) | |
696 ick->t_stats.s_hpt -= count / 2; | |
697 else | |
698 ick->t_stats.s_hpt -= count; | |
699 if (ick->t_stats.s_hpt < 1) | |
700 killed(item, | |
701 cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)), | |
702 TRUE, TRUE); | |
703 else { | |
704 runto(ick, &hero); | |
705 | |
706 /* | |
707 * The monster may not like being shot at. Since the | |
708 * shot is not aimed directly at the monster, we will | |
709 * give him a poorer save. | |
710 */ | |
711 if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) { | |
712 msg("The eyes of %s turn clear.", | |
713 prname(monster_name(ick), FALSE)); | |
714 turn_off(*ick, ISCHARMED); | |
715 } | |
716 if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE))) | |
717 msg("%s appears wounded", | |
718 prname(monster_name(ick), TRUE)); | |
719 } | |
720 } | |
721 } | |
722 } | |
723 } | |
724 | |
725 /* | |
726 * initialize a stick | |
727 */ | |
728 | |
729 fix_stick(cur) | |
730 register struct object *cur; | |
731 { | |
732 if (EQUAL(ws_type[cur->o_which], "staff")) { | |
733 cur->o_weight = 100; | |
734 cur->o_charges = 5 + rnd(11); | |
735 strcpy(cur->o_damage,"3d4"); | |
736 cur->o_hplus = 1; | |
737 cur->o_dplus = 0; | |
738 switch (cur->o_which) { | |
739 case WS_HIT: | |
740 cur->o_hplus = 3; | |
741 cur->o_dplus = 3; | |
742 strcpy(cur->o_damage,"2d8"); | |
743 when WS_LIGHT: | |
744 cur->o_charges = 15 + rnd(11); | |
745 } | |
746 } | |
747 else { | |
748 strcpy(cur->o_damage,"2d3"); | |
749 cur->o_weight = 75; | |
750 cur->o_hplus = 1; | |
751 cur->o_dplus = 0; | |
752 cur->o_charges = 5 + rnd(11); | |
753 switch (cur->o_which) { | |
754 case WS_HIT: | |
755 cur->o_hplus = 3; | |
756 cur->o_dplus = 3; | |
757 strcpy(cur->o_damage,"2d8"); | |
758 when WS_LIGHT: | |
759 cur->o_charges = 15 + rnd(11); | |
760 } | |
761 } | |
762 strcpy(cur->o_hurldmg,"3d3"); | |
763 | |
764 } | |
765 | |
766 /* | |
767 * Use the wand that our monster is wielding. | |
768 */ | |
769 | |
770 m_use_wand(monster) | |
771 register struct thing *monster; | |
772 { | |
773 register struct object *obj; | |
774 | |
775 /* Make sure we really have it */ | |
776 if (monster->t_using) | |
777 obj = OBJPTR(monster->t_using); | |
778 else { | |
779 debug("Stick not set!"); | |
780 monster->t_action = A_NIL; | |
781 return; | |
782 } | |
783 | |
784 if (obj->o_type != STICK) { | |
785 debug("Stick not selected!"); | |
786 monster->t_action = A_NIL; | |
787 return; | |
788 } | |
789 /* | |
790 * shoot the stick! | |
791 * assume all blessed sticks are normal for now. | |
792 * Note that we don't get here if the wand is cursed. | |
793 */ | |
794 msg("%s points a %s at you!", prname(monster_name(monster), TRUE), | |
795 ws_type[obj->o_which]); | |
796 do_zap(monster, obj, &monster->t_newpos, obj->o_which, NULL); | |
797 monster->t_wand /= 2; /* chance lowers with each use */ | |
798 } | |
799 | |
800 bool | |
801 need_dir(type, which) | |
802 int type, /* type of item, NULL means stick */ | |
803 which; /* which item */ | |
804 { | |
805 if (type == STICK || type == 0) { | |
806 switch (which) { | |
807 case WS_LIGHT: | |
808 case WS_DRAIN: | |
809 case WS_CHARGE: | |
810 case WS_CURING: | |
811 return(FALSE); | |
812 default: | |
813 return(TRUE); | |
814 } | |
815 } | |
816 else if (type == RELIC) { | |
817 switch (which) { | |
818 case MING_STAFF: | |
819 case ASMO_ROD: | |
820 case EMORI_CLOAK: | |
821 return(TRUE); | |
822 default: | |
823 return(FALSE); | |
824 } | |
825 } | |
826 return (FALSE); /* hope we don't get here */ | |
827 } | |
828 | |
829 /* | |
830 * let the player zap a stick and see what happens | |
831 */ | |
832 | |
833 player_zap(which, flag) | |
834 int which; | |
835 int flag; | |
836 { | |
837 register struct linked_list *item; | |
838 register struct object *obj; | |
839 | |
840 obj = NULL; | |
841 if (which == 0) { | |
842 /* This is a stick. It takes 2 movement periods to zap it */ | |
843 if (player.t_action != C_ZAP) { | |
844 if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL) | |
845 return(FALSE); | |
846 | |
847 obj = OBJPTR(item); | |
848 | |
849 if (need_dir(obj->o_type, obj->o_which)) { | |
850 if (!get_dir(&player.t_newpos)) | |
851 return(FALSE); | |
852 } | |
853 player.t_using = item; /* Remember what it is */ | |
854 player.t_action = C_ZAP; /* We are quaffing */ | |
855 player.t_no_move = 2 * movement(&player); | |
856 return(TRUE); | |
857 } | |
858 | |
859 item = player.t_using; | |
860 /* We've waited our time, let's shoot 'em up! */ | |
861 player.t_using = NULL; | |
862 player.t_action = A_NIL; | |
863 | |
864 obj = OBJPTR(item); | |
865 | |
866 /* Handle relics specially here */ | |
867 if (obj->o_type == RELIC) { | |
868 switch (obj->o_which) { | |
869 case ORCUS_WAND: | |
870 /* msg(nothing); */ | |
871 read_scroll(S_PETRIFY, NULL, FALSE); | |
872 return(TRUE); | |
873 when MING_STAFF: | |
874 which = WS_MISSILE; | |
875 when EMORI_CLOAK: | |
876 which = WS_PARALYZE; | |
877 obj->o_charges = 0; /* one zap/day (whatever that is) */ | |
878 fuse(cloak_charge, obj, CLOAK_TIME, AFTER); | |
879 when ASMO_ROD: | |
880 switch (rnd(3)) { | |
881 case 0: which = WS_ELECT; | |
882 when 1: which = WS_COLD; | |
883 otherwise: which = WS_FIRE; | |
884 } | |
885 } | |
886 } | |
887 else { | |
888 which = obj->o_which; | |
889 ws_know[which] = TRUE; | |
890 flag = obj->o_flags; | |
891 } | |
892 } | |
893 do_zap(&player, obj, &player.t_newpos, which, flag); | |
894 return(TRUE); | |
895 } | |
896 |