diff --git a/src/dungeon.c b/src/dungeon.c index 515f8e2..89f1fdb 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -20,6 +20,7 @@ #include "button.h" #include "cave.h" #include "cmds.h" +#include "effects.h" #include "files.h" #include "game-event.h" #include "generate.h" @@ -477,6 +478,98 @@ static void decrease_timeouts(void) /* + * Process poison. Poison causes damage, and can cause various additional + * effects for short durations. + * Larger poison timers unlock additional status ailments to roll. + * Min poison timer value status ailment % chance each turn + * 10 hallucinate 10 + * 20 confuse 8 + * 40 blind 6 + * 50 additional poison 5 + * 80 stun 6 + * 100 vomit 2 + * 150 paralyze 1 + * 200 drain physical stat 1 + */ +static void process_poison(void) +{ + /* Dice roll, determines status effects */ + int chance = randint0(100); + /* Current poison timer */ + int timer = p_ptr->timed[TMD_POISONED]; + /* Stat to drain if necessary */ + int stat_idx; + + /* Take damage */ + take_hit(1, "poison"); + + if (timer > 10 && chance < 10) + { + if (!p_ptr->state.resist_chaos) + { + message(MSG_DRUGGED, 0, "Poison blurs your vision!"); + inc_timed(TMD_IMAGE, 2, TRUE); + } + } + else if (timer > 20 && chance < 18) + { + if (!p_ptr->state.resist_confu) + { + message(MSG_CONFUSED, 0, "You become delirious!"); + inc_timed(TMD_CONFUSED, 2, TRUE); + } + } + else if (timer > 40 && chance < 24) + { + if (!p_ptr->state.resist_blind) + { + message(MSG_BLIND, 0, "Poison removes your vision!"); + inc_timed(TMD_BLIND, 2, TRUE); + } + } + else if (timer > 50 && chance < 29) + { + message(MSG_POISONED, 0, "The poison becomes worse!"); + inc_timed(TMD_POISONED, 20, TRUE); + } + else if (timer > 80 && chance < 35) + { + /* Note stunning lasts longer. */ + message(MSG_STUN, 0, "The poison stuns you!"); + inc_timed(TMD_STUN, 10, TRUE); + } + else if (timer > 100 && chance < 37) + { + /* Only if the player has anything in their stomach. */ + if (p_ptr->food > PY_FOOD_FAINT) + { + msg_print("You are assaulted by nausea!"); + vomit(); + } + } + else if (timer > 150 && chance < 38) + { + message(MSG_PARALYZED, 0, "The poison locks up your muscles!"); + inc_timed(TMD_PARALYZED, 2, TRUE); + } + else if (timer > 200 && chance < 39) + { + msg_print("The poison leaves you weakened!"); + /* Pick a random stat from (STR, DEX, CON) to drain */ + stat_idx = randint0(3); + if (stat_idx == 1) + { + stat_idx = 3; + } + else if (stat_idx == 2) + { + stat_idx = 4; + } + do_dec_stat(stat_idx, FALSE); + } +} + +/* * Handle certain things once every 10 game turns */ static void process_world(void) @@ -550,13 +643,10 @@ static void process_world(void) /*** Damage over Time ***/ - - /* Take damage from poison */ - if (p_ptr->timed[TMD_POISONED]) - { - /* Take damage */ - take_hit(1, "poison"); - } + if (p_ptr->timed[TMD_POISONED]) + { + (void)process_poison(); + } /* Take damage from cuts */ if (p_ptr->timed[TMD_CUT]) @@ -820,9 +910,6 @@ static void process_world(void) } - - - /* * Hack -- helper function for "process_player()" * diff --git a/src/effects.c b/src/effects.c index 12f58ae..f6e9631 100644 --- a/src/effects.c +++ b/src/effects.c @@ -1725,9 +1725,8 @@ bool effect_do(effect_type effect, bool *ident, bool aware, int dir, int beam, case EF_DRINK_SALT: { msg_print("The potion makes you vomit!"); - (void)set_food(PY_FOOD_STARVE - 1); - (void)clear_timed(TMD_POISONED, TRUE); - (void)inc_timed(TMD_PARALYZED, 4, TRUE); + vomit(); + (void)clear_timed(TMD_POISONED, TRUE); *ident = TRUE; return TRUE; } @@ -1992,3 +1991,13 @@ bool effect_do(effect_type effect, bool *ident, bool aware, int dir, int beam, msg_print("Effect not handled."); return FALSE; } + +/* + * Cause the player to lose their lunch. Sets them to starving and paralyzes + * them. + */ +void vomit() +{ + (void)set_food(PY_FOOD_STARVE - 1); + (void)inc_timed(TMD_PARALYZED, 4, TRUE); +} diff --git a/src/effects.h b/src/effects.h index d738d71..e3cb249 100644 --- a/src/effects.h +++ b/src/effects.h @@ -37,5 +37,5 @@ const char *effect_desc(effect_type effect); int effect_power(effect_type effect); bool effect_obvious(effect_type effect); bool effect_wonder(int dir, int die, int beam); - +void vomit(void); #endif /* INCLUDED_EFFECTS_H */ diff --git a/src/xtra3.c b/src/xtra3.c index ac9dde5..772e5df 100644 --- a/src/xtra3.c +++ b/src/xtra3.c @@ -679,6 +679,13 @@ static const struct state_info stun_data[] = { 0, S("Stun"), TERM_ORANGE }, }; +/* TMD_POISONED descriptions */ +static const struct state_info poison_data[] = +{ + { 100, S("Heavily poisoned"), TERM_RED }, + { 0, S("Poisoned"), TERM_ORANGE }, +}; + /* p_ptr->hunger descriptions */ static const struct state_info hunger_data[] = { @@ -699,7 +706,6 @@ static const struct state_info effects[] = { TMD_AFRAID, S("Afraid"), TERM_ORANGE }, { TMD_TERROR, S("Terror"), TERM_RED }, { TMD_IMAGE, S("Halluc"), TERM_ORANGE }, - { TMD_POISONED, S("Poisoned"), TERM_ORANGE }, { TMD_PROTEVIL, S("ProtEvil"), TERM_L_GREEN }, { TMD_SPRINT, S("Sprint"), TERM_L_GREEN }, { TMD_TELEPATHY, S("ESP"), TERM_L_BLUE }, @@ -776,6 +782,14 @@ static size_t prt_stun(int row, int col) return 0; } +/* + * Print poison indicator. + */ +static size_t prt_poison(int row, int col) +{ + PRINT_STATE(>, poison_data, p_ptr->timed[TMD_POISONED], row, col); + return 0; +} /* * Prints status of hunger @@ -974,8 +988,8 @@ static size_t prt_buttons(int row, int col) typedef size_t status_f(int row, int col); status_f *status_handlers[] = -{ prt_recall, prt_state, prt_cut, prt_stun, prt_hunger, prt_study, prt_tmd, - prt_dtrap, prt_buttons }; +{ prt_recall, prt_state, prt_cut, prt_stun, prt_poison, prt_hunger, + prt_study, prt_tmd, prt_dtrap, prt_buttons }; /*