From: Martin Read Date: Wed, 19 Feb 2014 01:46:42 +0000 (+0000) Subject: Power attack, and some notification-related cleanup. X-Git-Tag: stretchy-levels~5 X-Git-Url: http://git.blackswordsonics.com/?a=commitdiff_plain;h=7ee7743f27fdd9faffe198897812803d9fa80977;p=victrix-abyssi Power attack, and some notification-related cleanup. * combat.cc,combat.hh: Implement power attack and refactor uhitm(). * map.cc: Replace touch_back_buffer() with notify_fov() * notify-local-tty.cc, notify.hh: Various new notifications. * objects.cc: Reflow eat_food(), eliminate reference to display vars therein. * u.cc: Debug chain-of-detection for power attack --- diff --git a/combat.cc b/combat.cc index 37cd9aa..7d51ed9 100644 --- a/combat.cc +++ b/combat.cc @@ -31,10 +31,115 @@ #include "monsters.hh" #include "objects.hh" + +/*! \brief Do the baseline melee damage calculation + * + * \return The computed basic damage output of the player's weapon/hands + */ +int player_melee_base(void) +{ + int dmgbase; + int damage; + if (u.weapon != NO_OBJ) + { + dmgbase = permobjs[objects[u.weapon].obj_id].power + (u.body / 10); + damage = dmgbase / 3 + one_die(dmgbase - dmgbase / 3); + } + else + { + damage = u.body / 10; + } + return damage; +} + +/*! \brief Calculate the effect of the player's damage amplifier ring + */ +bool ring_effectiveness(int mon, int ring_pobj, int damage, int *bonus_damage, int *vamp_healing) +{ + bool rv = false; + int pm = monsters[mon].mon_id; + *vamp_healing = 0; + switch (ring_pobj) + { + case PO_FIRE_RING: + if (!pmon_resists_fire(pm)) + { + *bonus_damage = dice(2, 4) + ((damage + 1) / 2); + rv = true; + } + break; + case PO_VAMPIRE_RING: + if (!pmon_resists_necro(pm)) + { + *bonus_damage = dice(2, 4) + ((damage + 3) / 4); + *vamp_healing = std::min(monsters[mon].hpcur, (damage + 5) / 6); + rv = true; + } + break; + case PO_FROST_RING: + if (!pmon_resists_cold(pm)) + { + *bonus_damage = dice(2, 4) + ((damage + 3) / 4); + rv = true; + } + break; + default: + break; + } + return rv; +} + +/*! \brief Common damage path for uhitm(), player_power_attack()... + * + * \param mon Monster hit + * \param damage Rolled damage before rings are applied + */ +void resolve_player_melee(int mon, int damage) +{ + bool ring_eff; + int ring_bonus; + int healing; // = 0; + if (u.ring != NO_OBJ) + { + ring_eff = ring_effectiveness(mon, objects[u.ring].obj_id, damage, &ring_bonus, &healing); + if (ring_eff) + { + notify_ring_boost(mon, objects[u.ring].obj_id); + damage += ring_bonus; + } + } + notify_player_hurt_mon(mon, damage); + damage_mon(mon, damage, true); + if (healing > 0) + { + heal_u(healing, 0, 1); + } + if (u.weapon != NO_OBJ) + { + damage_obj(u.weapon); + } +} + +/*! \brief Resolve the "Power Attack" combo move + * + * \param delta Direction in which player is attacking. + */ +Action_cost player_power_attack(Offset delta) +{ + Coord c = u.pos + delta; + int damage; + int mon = lvl.mon_at(c); + /* Power Attack: Always hit, do +75% damage. */ + notify_player_combo_powatk(mon); + damage = (player_melee_base() * 7) / 4; + resolve_player_melee(mon, damage); + return Cost_std; +} + Action_cost player_attack(Offset delta) { Coord c = u.pos + delta; - if ((objects[u.weapon].obj_id == PO_BOW) || (objects[u.weapon].obj_id == PO_CROSSBOW)) + if (wielding_ranged_weapon()) { ushootm(delta); } @@ -53,14 +158,9 @@ Action_cost player_attack(Offset delta) int uhitm(int mon) { Mon *mp; - Obj *wep; - Permobj *pwep; - Obj *ring; int tohit; int damage; - int healing; int hitbase = u.agility + u.level; - int dmgbase; mp = monsters + mon; tohit = hitbase / 3 + zero_die(hitbase - hitbase / 3); if (tohit < mp->defence) @@ -69,52 +169,8 @@ int uhitm(int mon) return 0; /* Missed. */ } notify_player_hit_mon(mon); - if (u.weapon != NO_OBJ) - { - wep = objects + u.weapon; - pwep = permobjs + wep->obj_id; - dmgbase = pwep->power + u.body / 10; - damage = dmgbase / 3 + one_die(dmgbase - dmgbase / 3); - } - else - { - damage = u.body / 10; - } - if (u.ring != NO_OBJ) - { - ring = objects + u.ring; - switch (ring->obj_id) - { - case PO_FIRE_RING: - if (!pmon_resists_fire(mp->mon_id)) - { - notify_ring_boost(mon, ring->obj_id); - damage += (damage + 1) / 2 + dice(2, 4); - } - break; - case PO_VAMPIRE_RING: - if (!pmon_is_undead(mp->mon_id)) - { - notify_ring_boost(mon, ring->obj_id); - damage += (damage + 3) / 4 + dice(2, 4); - healing = std::min(mp->hpcur, (damage + 5) / 6); - heal_u(healing, 0, 1); - } - break; - case PO_FROST_RING: - if (!pmon_resists_cold(mp->mon_id)) - { - notify_ring_boost(mon, ring->obj_id); - damage += (damage + 2) / 3 + dice(1, 6); - } - } - } - notify_player_hurt_mon(mon, damage); - damage_mon(mon, damage, true); - if (u.weapon != NO_OBJ) - { - damage_obj(u.weapon); - } + damage = player_melee_base(); + resolve_player_melee(mon, damage); return 1; /* Hit. */ } diff --git a/combat.hh b/combat.hh index 27df577..fe0699d 100644 --- a/combat.hh +++ b/combat.hh @@ -41,6 +41,8 @@ /* XXX combat.c data and funcs */ extern Action_cost throw_flask(int obj, Offset step); extern Action_cost player_attack(Offset step); +extern Action_cost player_power_attack(Offset step); +extern void resolve_player_melee(int mon, int damage); extern int mhitu(int mon, Damtyp dtyp); extern int uhitm(int mon); extern int mshootu(int mon); diff --git a/map.cc b/map.cc index 406b0e1..6e36831 100644 --- a/map.cc +++ b/map.cc @@ -600,7 +600,7 @@ void inject_player(void) void look_around_you(void) { compute_fov(); - touch_back_buffer(); + notify_fov(); } Terrain_props terrain_props[NUM_TERRAINS] = diff --git a/notify-local-tty.cc b/notify-local-tty.cc index b9738c1..45504b9 100644 --- a/notify-local-tty.cc +++ b/notify-local-tty.cc @@ -351,6 +351,13 @@ void notify_player_hit_mon(int mon) print_msg(".\n"); } +void notify_player_combo_powatk(int mon) +{ + print_msg("You deal a powerful blow to "); + print_mon_name(mon, 1); + print_msg(".\n"); +} + void notify_player_shot_terrain(int obj, Coord c) { print_msg("Your %s hits the %s.\n", (objects[obj].obj_id == PO_CROSSBOW) ? "bolt" : "arrow", terrain_props[lvl.terrain_at(c)].name); @@ -829,11 +836,13 @@ void notify_dress_shredded(void) void notify_eat_food(bool ravenous) { + status_updated = true; print_msg(ravenous ? "You ravenously devour your food!\n" : "You eat some food.\n"); } void notify_ingest_spleen(void) { + status_updated = true; print_msg("%s power suffuses your body as you devour the devil spleen.\n", u.corrupt() ? "Delicious" : "Vile"); } @@ -926,6 +935,11 @@ void notify_new_mon_at(Coord c, int mon) newsym(c); } +void notify_fov(void) +{ + touch_back_buffer(); +} + /* Debugging notifications */ void debug_bad_monspell(int spell) diff --git a/notify.hh b/notify.hh index 67766f5..c1aa42b 100644 --- a/notify.hh +++ b/notify.hh @@ -114,6 +114,7 @@ void notify_ring_boost(int mon, int pobj); void notify_player_hit_mon(int mon); void notify_player_hurt_mon(int mon, int damage); void notify_player_killed_mon(int mon); +void notify_player_combo_powatk(int mon); void notify_knockback_mon_resisted(int mon); void notify_knockback_mon_blocked(int mon); void notify_knockback_mon_hover_lava(int mon); @@ -152,6 +153,9 @@ void notify_necrosmite_fail(void); void notify_necrosmite_hit(void); void notify_hellfire_hit(bool resisted); +// Miscellaneous notifications +void notify_fov(void); + // Debugging notifications void debug_move_oob(Coord c); void debug_body_gain(int amount); diff --git a/objects.cc b/objects.cc index a812346..5d4b619 100644 --- a/objects.cc +++ b/objects.cc @@ -165,6 +165,8 @@ bool consume_obj(int obj) Action_cost eat_food(int obj) { Obj *optr = objects + obj; + bool ravenous = (u.food < 0); + u.food += 1500; if (permobjs[optr->obj_id].poclass != POCLASS_FOOD) { debug_eat_non_food(obj); @@ -186,11 +188,8 @@ Action_cost eat_food(int obj) } else { - notify_eat_food(u.food < 0); + notify_eat_food(ravenous); } - u.food += 1500; - status_updated = 1; - display_update(); consume_obj(obj); return Cost_std; } diff --git a/u.cc b/u.cc index 63c029a..0c07a18 100644 --- a/u.cc +++ b/u.cc @@ -564,7 +564,8 @@ enum Combo_phase bool action_rewrite(Action const *act, Action *revised_act) { - Coord c; + Coord c = u.pos; + int mon = NO_MON; Offset o; Action tmp_act = *act; Combo_phase p; @@ -586,6 +587,7 @@ bool action_rewrite(Action const *act, Action *revised_act) p = Combo_invalid; break; } + mon = lvl.mon_at(c); p = Combo_finisher; break; case WALK: @@ -601,6 +603,7 @@ bool action_rewrite(Action const *act, Action *revised_act) } else if (lvl.mon_at(c) != NO_MON) { + mon = lvl.mon_at(c); tmp_act.cmd = ATTACK; rewrite_flag = true; p = Combo_finisher; @@ -655,7 +658,8 @@ bool action_rewrite(Action const *act, Action *revised_act) switch (past_actions.front().cmd) { case STAND_STILL: - if (empty_handed() || wielding_melee_weapon()) + if ((empty_handed() || wielding_melee_weapon()) && + (mon != NO_MON)) { rewrite_flag = true; tmp_act.cmd = CMD_POWER_ATTACK; @@ -700,7 +704,7 @@ Action_cost do_player_action(Action *act) case CMD_POWER_ATTACK: step.y = act->details[0]; step.x = act->details[1]; - return player_attack(step); + return player_power_attack(step); case WALK: step.y = act->details[0];