Makes critical hits cause bleeding

This commit is contained in:
Linus Probert 2019-05-14 10:26:28 +02:00
parent 8f21e8bfb2
commit dd3e84d70d
8 changed files with 66 additions and 59 deletions

View File

@ -135,13 +135,13 @@ damage_surroundings(Monster *m, RoomMatrix *rm)
RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y]; RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y];
if (r->monster) { if (r->monster) {
int dmg = stats_fight(&m->stats, &r->monster->stats); CombatResult result = stats_fight(&m->stats, &r->monster->stats);
monster_hit(r->monster, dmg); monster_hit(r->monster, result.dmg, result.critical);
gui_log("%s takes %d damage from the explosion", r->monster->label, dmg); gui_log("%s takes %d damage from the explosion", r->monster->label, result.dmg);
} else if (r->player) { } else if (r->player) {
int dmg = stats_fight(&m->stats, &r->player->stats); CombatResult result = stats_fight(&m->stats, &r->player->stats);
player_hit(r->player, dmg); player_hit(r->player, result.dmg);
gui_log("You take %d damage from the explosion", dmg); gui_log("You take %d damage from the explosion", result.dmg);
} }
} }
} }
@ -314,14 +314,14 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction)
RoomSpace *space = roommatrix_get_space_for(matrix, &monster->sprite->pos); RoomSpace *space = roommatrix_get_space_for(matrix, &monster->sprite->pos);
if (space->player && monster->state.current == AGRESSIVE) { if (space->player && monster->state.current == AGRESSIVE) {
unsigned int dmg = stats_fight(&monster->stats, CombatResult result = stats_fight(&monster->stats,
&space->player->stats); &space->player->stats);
player_hit(space->player, dmg); player_hit(space->player, result.dmg);
if (dmg > 0) { if (result.dmg > 0) {
gui_log("%s hit you for %u damage", gui_log("%s hit you for %u damage",
monster->label, dmg); monster->label, result.dmg);
camera_shake(direction, 300); camera_shake(direction, 300);
} else { } else {
gui_log("%s missed you", monster->label); gui_log("%s missed you", monster->label);
@ -563,7 +563,7 @@ apply_bleed_damage(Player *p, Monster *m)
return; return;
uint32_t dmg = m->stats.lvl * 2; uint32_t dmg = m->stats.lvl * 2;
monster_hit(m, dmg); monster_hit(m, dmg, false);
m->stats.hp -= dmg; m->stats.hp -= dmg;
player_monster_kill_check(p, m); player_monster_kill_check(p, m);
} }
@ -685,7 +685,7 @@ monster_update(Monster *m, UpdateData *data)
} }
void void
monster_hit(Monster *monster, unsigned int dmg) monster_hit(Monster *monster, unsigned int dmg, bool critical)
{ {
if (dmg > 0) { if (dmg > 0) {
Position p = monster->sprite->pos; Position p = monster->sprite->pos;
@ -703,6 +703,9 @@ monster_hit(Monster *monster, unsigned int dmg)
C_YELLOW, C_YELLOW,
&monster->sprite->pos); &monster->sprite->pos);
} }
if (critical)
monster_set_bleeding(monster);
monster_behaviour_check_post_hit(monster); monster_behaviour_check_post_hit(monster);
} }
@ -878,7 +881,7 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
if (space->trap) { if (space->trap) {
int dmg = space->trap->damage * 3; int dmg = space->trap->damage * 3;
m->stats.hp -= dmg; m->stats.hp -= dmg;
monster_hit(m, dmg); monster_hit(m, dmg, false);
gui_log("%s takes %d damage from a trap", m->label, dmg); gui_log("%s takes %d damage from a trap", m->label, dmg);
} else if (space->damaging) { } else if (space->damaging) {
LinkedList *objects = space->objects; LinkedList *objects = space->objects;
@ -888,7 +891,7 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
if (!o->damage) if (!o->damage)
return; return;
m->stats.hp -= o->damage * 3; m->stats.hp -= o->damage * 3;
monster_hit(m, o->damage * 3); monster_hit(m, o->damage * 3, false);
} }
} else if (has_collided(m, rm, direction)) { } else if (has_collided(m, rm, direction)) {
m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x; m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x;

View File

@ -103,7 +103,7 @@ void
monster_render_top_layer(Monster*, RoomMatrix*, Camera*); monster_render_top_layer(Monster*, RoomMatrix*, Camera*);
void void
monster_hit(Monster*, unsigned int dmg); monster_hit(Monster*, unsigned int dmg, bool critical);
void void
monster_update_stats_for_level(Monster*, unsigned int level); monster_update_stats_for_level(Monster*, unsigned int level);

View File

@ -103,7 +103,7 @@ particle_engine_init(void)
void void
particle_engine_bleed(Position pos, Dimension dim) particle_engine_bleed(Position pos, Dimension dim)
{ {
particle_engine_bloodspray(pos, dim, 5); particle_engine_bloodspray(pos, dim, 10);
} }
void void

View File

@ -133,16 +133,16 @@ on_monster_collision(Player *player,
RoomMatrix *matrix, RoomMatrix *matrix,
Vector2d direction) Vector2d direction)
{ {
unsigned int hit = stats_fight(&player->stats, CombatResult result = stats_fight(&player->stats,
&monster->stats); &monster->stats);
mixer_play_effect(SWING0 + get_random(2)); mixer_play_effect(SWING0 + get_random(2));
monster_hit(monster, hit); monster_hit(monster, result.dmg, result.critical);
animation_run(player->swordAnimation); animation_run(player->swordAnimation);
if (hit > 0) { if (result.dmg > 0) {
gui_log("You hit %s for %u damage", gui_log("You hit %s for %u damage",
monster->lclabel, hit); monster->lclabel, result.dmg);
player->stat_data.hits += 1; player->stat_data.hits += 1;
mixer_play_effect(SWORD_HIT); mixer_play_effect(SWORD_HIT);
} else { } else {

View File

@ -119,14 +119,14 @@ projectile_update(Projectile *p, UpdateData *data)
if (space->monster) { if (space->monster) {
Stats tmpStats = data->player->stats; Stats tmpStats = data->player->stats;
tmpStats.dmg *= 2; tmpStats.dmg *= 2;
Uint32 dmg = stats_fight(&tmpStats, &space->monster->stats); CombatResult result = stats_fight(&tmpStats, &space->monster->stats);
if (dmg > 0) { if (result.dmg > 0) {
gui_log("Your dagger pierced %s for %u damage", space->monster->lclabel, dmg); gui_log("Your dagger pierced %s for %u damage", space->monster->lclabel, result.dmg);
data->player->stat_data.hits += 1; data->player->stat_data.hits += 1;
} else { } else {
gui_log("%s dodged your dagger", space->monster->label); gui_log("%s dodged your dagger", space->monster->label);
} }
monster_hit(space->monster, dmg); monster_hit(space->monster, result.dmg, result.critical);
player_monster_kill_check(data->player, space->monster); player_monster_kill_check(data->player, space->monster);
alive = player_has_artifact(data->player, PIERCING_DAGGERS) > p->collisionCount; alive = player_has_artifact(data->player, PIERCING_DAGGERS) > p->collisionCount;
projectilePos = space->monster->sprite->pos; projectilePos = space->monster->sprite->pos;

View File

@ -319,12 +319,12 @@ skill_use_flurry(Skill *skill, SkillData *data)
unsigned int hitCount = 0; unsigned int hitCount = 0;
for (size_t i = 0; i < 3; ++i) { for (size_t i = 0; i < 3; ++i) {
unsigned int originalHp = monster->stats.hp; unsigned int originalHp = monster->stats.hp;
unsigned int dmg = stats_fight(&data->player->stats, &monster->stats); CombatResult result = stats_fight(&data->player->stats, &monster->stats);
if (dmg > 0 && originalHp > 0) { if (result.dmg > 0 && originalHp > 0) {
gui_log("You hit for %u damage", dmg); gui_log("You hit for %u damage", result.dmg);
hitCount++; hitCount++;
} }
monster_hit(monster, dmg); monster_hit(monster, result.dmg, result.critical);
} }
if (hitCount == 1) { if (hitCount == 1) {
mixer_play_effect(SWORD_HIT); mixer_play_effect(SWORD_HIT);
@ -436,9 +436,9 @@ skill_bash(Skill *skill, SkillData *data)
mixer_play_effect(SWING0); mixer_play_effect(SWING0);
if (monster) { if (monster) {
gui_log("You bash %s with your shield", monster->lclabel); gui_log("You bash %s with your shield", monster->lclabel);
unsigned int dmg = stats_fight(&data->player->stats, &monster->stats); CombatResult result = stats_fight(&data->player->stats, &monster->stats);
if (dmg > 0) { if (result.dmg > 0) {
gui_log("You hit for %u damage", dmg); gui_log("You hit for %u damage", result.dmg);
if (monster->stats.hp > 0) { if (monster->stats.hp > 0) {
gui_log("%s seems dazed and confused", monster->label); gui_log("%s seems dazed and confused", monster->label);
monster_set_state(monster, STUNNED, monster_set_state(monster, STUNNED,
@ -449,7 +449,7 @@ skill_bash(Skill *skill, SkillData *data)
} else { } else {
gui_log("You missed %s", monster->lclabel); gui_log("You missed %s", monster->lclabel);
} }
monster_hit(monster, dmg); monster_hit(monster, result.dmg, result.critical);
} else { } else {
gui_log("You bash your shield at nothing"); gui_log("You bash your shield at nothing");
} }
@ -491,13 +491,13 @@ skill_trip(Skill *skill, SkillData *data)
mixer_play_effect(SWING0 + get_random(2)); mixer_play_effect(SWING0 + get_random(2));
animation_run(data->player->swordAnimation); animation_run(data->player->swordAnimation);
if (space->monster) { if (space->monster) {
int dmg = stats_fight(&data->player->stats, &space->monster->stats); CombatResult result = stats_fight(&data->player->stats, &space->monster->stats);
if (dmg) if (result.dmg)
mixer_play_effect(SWORD_HIT); mixer_play_effect(SWORD_HIT);
gui_log("You trip %s causing it to fall away from you", space->monster->lclabel); gui_log("You trip %s causing it to fall away from you", space->monster->lclabel);
monster_hit(space->monster, dmg); monster_hit(space->monster, result.dmg, result.critical);
player_monster_kill_check(data->player, space->monster); player_monster_kill_check(data->player, space->monster);
if (dmg && space->monster->stats.hp > 0) { if (result.dmg && space->monster->stats.hp > 0) {
Uint32 pushCount = 1 + player_has_artifact(data->player, PUSH_BACK); Uint32 pushCount = 1 + player_has_artifact(data->player, PUSH_BACK);
for (Uint32 i = 0; i < pushCount; ++i) { for (Uint32 i = 0; i < pushCount; ++i) {
monster_push(space->monster, data->player, data->matrix, data->direction); monster_push(space->monster, data->player, data->matrix, data->direction);
@ -564,11 +564,11 @@ skill_backstab(Skill *skill, SkillData *data)
monster_push(m, data->player, data->matrix, reverseDirection); monster_push(m, data->player, data->matrix, reverseDirection);
m->stats.disadvantage = true; m->stats.disadvantage = true;
int dmg = stats_fight(&data->player->stats, &m->stats); CombatResult result = stats_fight(&data->player->stats, &m->stats);
m->stats.disadvantage = false; m->stats.disadvantage = false;
monster_hit(m, dmg); monster_hit(m, result.dmg, result.critical);
player_monster_kill_check(data->player, m); player_monster_kill_check(data->player, m);
if (dmg) { if (result.dmg) {
mixer_play_effect(SWORD_HIT); mixer_play_effect(SWORD_HIT);
monster_set_state(m, STUNNED, (Uint8)(2 + player_has_artifact(data->player, INCREASED_STUN))); monster_set_state(m, STUNNED, (Uint8)(2 + player_has_artifact(data->player, INCREASED_STUN)));
monster_set_bleeding(m); monster_set_bleeding(m);
@ -680,13 +680,13 @@ skill_charge_check_path(SkillData *data,
Stats tmpStats = player->stats; Stats tmpStats = player->stats;
tmpStats.dmg *= steps > 0 ? steps : 1; tmpStats.dmg *= steps > 0 ? steps : 1;
mixer_play_effect(SWING0 + get_random(2)); mixer_play_effect(SWING0 + get_random(2));
unsigned int dmg = stats_fight(&tmpStats, &monster->stats); CombatResult result = stats_fight(&tmpStats, &monster->stats);
if (dmg > 0) { if (result.dmg > 0) {
gui_log("You charged %s for %u damage", monster->lclabel, dmg); gui_log("You charged %s for %u damage", monster->lclabel, result.dmg);
mixer_play_effect(SWORD_HIT); mixer_play_effect(SWORD_HIT);
data->player->stat_data.hits += 1; data->player->stat_data.hits += 1;
} }
monster_hit(monster, dmg); monster_hit(monster, result.dmg, result.critical);
player_monster_kill_check(data->player, monster); player_monster_kill_check(data->player, monster);
} }
@ -886,10 +886,10 @@ skill_erupt(Skill *skill, SkillData *data)
RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y]; RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y];
if (r->monster) { if (r->monster) {
player->stats.advantage = true; player->stats.advantage = true;
int dmg = stats_fight(&player->stats, &r->monster->stats); CombatResult result = stats_fight(&player->stats, &r->monster->stats);
player->stats.advantage = false; player->stats.advantage = false;
monster_hit(r->monster, dmg); monster_hit(r->monster, result.dmg, result.critical);
gui_log("%s takes %d damage from the explosion", r->monster->label, dmg); gui_log("%s takes %d damage from the explosion", r->monster->label, result.dmg);
monster_set_bleeding(r->monster); monster_set_bleeding(r->monster);
int lvl = 1 + player_has_artifact(player, PUSH_BACK); int lvl = 1 + player_has_artifact(player, PUSH_BACK);

View File

@ -61,31 +61,30 @@ get_defence_roll(Stats *defender)
return roll + defender->def; return roll + defender->def;
} }
unsigned int CombatResult
stats_fight(Stats *attacker, Stats *defender) stats_fight(Stats *attacker, Stats *defender)
{ {
bool critical = false; CombatResult result = { 0, false };
int atkRoll = get_attack_roll(attacker); int atkRoll = get_attack_roll(attacker);
int defRoll = get_defence_roll(defender); int defRoll = get_defence_roll(defender);
if (atkRoll - attacker->atk == 20) if (atkRoll - attacker->atk == 20)
critical = get_attack_roll(attacker) > defRoll; result.critical = get_attack_roll(attacker) > defRoll;
int dmgRoll = 0;
if (atkRoll >= defRoll) { if (atkRoll >= defRoll) {
if (attacker->dmg > 0) if (attacker->dmg > 0)
dmgRoll = get_random(attacker->dmg - 1) + 1; result.dmg = get_random(attacker->dmg - 1) + 1;
else else
dmgRoll = 1; result.dmg = 1;
if (critical) { if (result.critical) {
dmgRoll = dmgRoll * 2; result.dmg = result.dmg * 2;
gui_log("CRITICAL HIT!"); gui_log("CRITICAL HIT!");
} }
defender->hp -= dmgRoll; defender->hp -= result.dmg;
} }
return dmgRoll; return result;
} }

View File

@ -31,7 +31,12 @@ typedef struct Stats_t {
bool disadvantage; bool disadvantage;
} Stats; } Stats;
unsigned int typedef struct CombatResult {
unsigned int dmg;
bool critical;
} CombatResult;
CombatResult
stats_fight(Stats *attacker, Stats *defender); stats_fight(Stats *attacker, Stats *defender);
#endif // STATS_H_ #endif // STATS_H_