diff --git a/libs/combat/attack.zig b/libs/combat/attack.zig index 5de90d4..38109c2 100644 --- a/libs/combat/attack.zig +++ b/libs/combat/attack.zig @@ -7,8 +7,9 @@ fn rng(min: c_int, max: c_int) c_int { } fn applyResistance(damage: c_int, resistance: c_int) c_int { - if (resistance >= 100) return 0; - const factor = 100 - resistance; + var r = resistance; + if (r > 75) r = 75; + const factor = 100 - r; var result = @divTrunc(damage * factor, 100); if (result < 1) result = 1; return result; @@ -63,15 +64,17 @@ pub fn playerAttack(p: [*c]c.Player, e: [*c]c.Enemy) void { base_attack -= c.WEAKEN_ATTACK_REDUCTION; if (base_attack < 1) base_attack = 1; - const variance = rng(80, 120); - var damage = @divTrunc(base_attack * variance, 100); - if (damage < 1) damage = 1; + var damage = base_attack; if (rng(0, 99) < crit_chance) { damage = @divTrunc(damage * crit_mult, 100); event.last.is_critical = 1; } + const variance = rng(80, 120); + damage = @divTrunc(damage * variance, 100); + if (damage < 1) damage = 1; + const res_index: usize = @intCast(dmg_class); if (res_index < c.NUM_DMG_CLASSES) { damage = applyResistance(damage, e[0].resistance[res_index]); @@ -139,15 +142,19 @@ pub fn enemyAttack(e: [*c]c.Enemy, p: [*c]c.Player) void { base_damage -= p[0].defense; if (base_damage < 1) base_damage = 1; - const variance = rng(80, 120); - var damage = @divTrunc(base_damage * variance, 100); - if (damage < 1) damage = 1; + var damage = base_damage; - if (rng(0, 99) < c.ENEMY_CRIT_CHANCE) { - damage = @divTrunc(damage * c.ENEMY_CRIT_MULT, 100); + const e_crit_chance = if (e[0].crit_chance > 0) e[0].crit_chance else c.ENEMY_CRIT_CHANCE; + const e_crit_mult = if (e[0].crit_mult > 0) e[0].crit_mult else c.ENEMY_CRIT_MULT; + if (rng(0, 99) < e_crit_chance) { + damage = @divTrunc(damage * e_crit_mult, 100); event.last.is_critical = 1; } + const variance = rng(80, 120); + damage = @divTrunc(damage * variance, 100); + if (damage < 1) damage = 1; + if (p[0].block > 0 and rng(0, 99) < 30) { var blocked = p[0].block; if (blocked > damage) blocked = damage; diff --git a/src/common.h b/src/common.h index 70d1ba3..c015532 100644 --- a/src/common.h +++ b/src/common.h @@ -95,6 +95,8 @@ typedef struct { int resistance[NUM_DMG_CLASSES]; DamageClass dmg_class; int status_chance; + int crit_chance; // crit chance percentage (0-100) + int crit_mult; // crit damage multiplier percentage (e.g. 150 = 1.5x) // status effects StatusEffect effects[MAX_EFFECTS]; int effect_count; diff --git a/src/enemy.c b/src/enemy.c index f90415c..9f72670 100644 --- a/src/enemy.c +++ b/src/enemy.c @@ -48,16 +48,21 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) { e.effect_count = 0; // Stats based on type and floor + // Attack scales with floor: +1 per 2 floors so deeper enemies hit harder + int floor_atk = floor / 2; + switch (e.type) { case ENEMY_GOBLIN: e.max_hp = ENEMY_BASE_HP + floor; e.hp = e.max_hp; - e.attack = ENEMY_BASE_ATTACK; + e.attack = ENEMY_BASE_ATTACK + floor_atk; e.speed = 55 + rng_int(0, 10); e.dodge = 15; e.block = 0; e.dmg_class = DMG_POISON; e.status_chance = 15; + e.crit_chance = 8; + e.crit_mult = 150; e.resistance[DMG_SLASH] = 0; e.resistance[DMG_IMPACT] = 0; e.resistance[DMG_PIERCE] = 0; @@ -67,27 +72,31 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) { case ENEMY_SKELETON: e.max_hp = ENEMY_BASE_HP + floor + 2; e.hp = e.max_hp; - e.attack = ENEMY_BASE_ATTACK + 1; + e.attack = ENEMY_BASE_ATTACK + 1 + floor_atk; e.speed = 70 + rng_int(0, 10); e.dodge = 5; e.block = 0; e.dmg_class = DMG_SLASH; e.status_chance = 10; + e.crit_chance = 6; + e.crit_mult = 150; e.resistance[DMG_SLASH] = -25; e.resistance[DMG_IMPACT] = -50; e.resistance[DMG_PIERCE] = 50; e.resistance[DMG_FIRE] = 25; - e.resistance[DMG_POISON] = 100; + e.resistance[DMG_POISON] = 75; break; case ENEMY_ORC: e.max_hp = ENEMY_BASE_HP + floor + 4; e.hp = e.max_hp; - e.attack = ENEMY_BASE_ATTACK + 2; + e.attack = ENEMY_BASE_ATTACK + 2 + floor_atk; e.speed = 85 + rng_int(0, 10); e.dodge = 0; e.block = 3; e.dmg_class = DMG_IMPACT; e.status_chance = 20; + e.crit_chance = 5; + e.crit_mult = 175; e.resistance[DMG_SLASH] = 0; e.resistance[DMG_IMPACT] = 25; e.resistance[DMG_PIERCE] = -25; @@ -103,6 +112,8 @@ void enemy_spawn(Enemy enemies[], int *count, Map *map, Player *p, int floor) { e.block = 0; e.dmg_class = DMG_IMPACT; e.status_chance = 0; + e.crit_chance = ENEMY_CRIT_CHANCE; + e.crit_mult = ENEMY_CRIT_MULT; memset(e.resistance, 0, sizeof(e.resistance)); break; }