combat: rewrite in Zig; add basic damage types and weapon archetypes
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ic8055a1cf6bdad1aca13673ea171b4b46a6a6964
This commit is contained in:
parent
7af642612b
commit
22ab6fc6eb
15 changed files with 802 additions and 158 deletions
151
libs/combat/effects.zig
Normal file
151
libs/combat/effects.zig
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
const c = @import("c.zig");
|
||||
|
||||
pub const EffectParams = struct {
|
||||
duration: c_int,
|
||||
intensity: c_int,
|
||||
};
|
||||
|
||||
pub fn procForClass(dmg_class: c.DamageClass) c.StatusEffectType {
|
||||
return switch (dmg_class) {
|
||||
c.DMG_SLASH => c.EFFECT_BLEED,
|
||||
c.DMG_IMPACT => c.EFFECT_STUN,
|
||||
c.DMG_PIERCE => c.EFFECT_WEAKEN,
|
||||
c.DMG_FIRE => c.EFFECT_BURN,
|
||||
c.DMG_POISON => c.EFFECT_POISON,
|
||||
else => c.EFFECT_NONE,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn name(effect: c.StatusEffectType) ?[*:0]const u8 {
|
||||
return switch (effect) {
|
||||
c.EFFECT_POISON => "Poisoned",
|
||||
c.EFFECT_BLEED => "Bleeding",
|
||||
c.EFFECT_STUN => "Stunned",
|
||||
c.EFFECT_BURN => "Burning",
|
||||
c.EFFECT_WEAKEN => "Weakened",
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn paramsFor(effect: c.StatusEffectType) EffectParams {
|
||||
return switch (effect) {
|
||||
c.EFFECT_BLEED => .{ .duration = 4, .intensity = c.BLEED_STACK_DAMAGE },
|
||||
c.EFFECT_STUN => .{ .duration = 1, .intensity = 0 },
|
||||
c.EFFECT_WEAKEN => .{ .duration = 3, .intensity = c.WEAKEN_ATTACK_REDUCTION },
|
||||
c.EFFECT_BURN => .{ .duration = 2, .intensity = c.BURN_BASE_DAMAGE },
|
||||
c.EFFECT_POISON => .{ .duration = 5, .intensity = c.POISON_BASE_DAMAGE },
|
||||
else => .{ .duration = 0, .intensity = 0 },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn clampCount(count: c_int) usize {
|
||||
if (count < 0) return 0;
|
||||
if (count > c.MAX_EFFECTS) return @intCast(c.MAX_EFFECTS);
|
||||
return @intCast(count);
|
||||
}
|
||||
|
||||
pub fn has(effects: [*c]const c.StatusEffect, count: c_int, effect_type: c.StatusEffectType) bool {
|
||||
const safe_count = clampCount(count);
|
||||
for (0..safe_count) |i| {
|
||||
if (effects[i].type == effect_type and effects[i].duration > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn apply(
|
||||
effects: [*c]c.StatusEffect,
|
||||
count: [*c]c_int,
|
||||
effect_type: c.StatusEffectType,
|
||||
duration: c_int,
|
||||
intensity: c_int,
|
||||
) void {
|
||||
const safe_count = clampCount(count[0]);
|
||||
|
||||
for (0..safe_count) |i| {
|
||||
if (effects[i].type == effect_type and effects[i].duration > 0) {
|
||||
if (effect_type == c.EFFECT_BLEED) {
|
||||
effects[i].intensity += intensity;
|
||||
if (effects[i].duration < duration)
|
||||
effects[i].duration = duration;
|
||||
} else {
|
||||
effects[i].duration = duration;
|
||||
if (intensity > effects[i].intensity)
|
||||
effects[i].intensity = intensity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (safe_count < @as(usize, @intCast(c.MAX_EFFECTS))) {
|
||||
effects[safe_count] = .{
|
||||
.type = effect_type,
|
||||
.duration = duration,
|
||||
.intensity = intensity,
|
||||
};
|
||||
count[0] = @intCast(safe_count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn compact(effects: [*c]c.StatusEffect, count: [*c]c_int) void {
|
||||
var write: usize = 0;
|
||||
const safe_count = clampCount(count[0]);
|
||||
|
||||
for (0..safe_count) |read| {
|
||||
if (effects[read].duration > 0) {
|
||||
if (write != read)
|
||||
effects[write] = effects[read];
|
||||
write += 1;
|
||||
}
|
||||
}
|
||||
count[0] = @intCast(write);
|
||||
}
|
||||
|
||||
fn tickOne(eff: *c.StatusEffect, hp: *c_int) c_int {
|
||||
if (eff.duration <= 0) return 0;
|
||||
|
||||
var dmg: c_int = 0;
|
||||
switch (eff.type) {
|
||||
c.EFFECT_POISON, c.EFFECT_BLEED, c.EFFECT_BURN => {
|
||||
dmg = eff.intensity;
|
||||
hp.* -= dmg;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
eff.duration -= 1;
|
||||
return dmg;
|
||||
}
|
||||
|
||||
pub fn tickPlayer(p: [*c]c.Player) c_int {
|
||||
if (p == null) return 0;
|
||||
|
||||
var total: c_int = 0;
|
||||
const safe_count = clampCount(p[0].effect_count);
|
||||
|
||||
for (0..safe_count) |i| {
|
||||
total += tickOne(&p[0].effects[i], &p[0].hp);
|
||||
}
|
||||
|
||||
compact(&p[0].effects, &p[0].effect_count);
|
||||
return total;
|
||||
}
|
||||
|
||||
pub fn tickEnemy(e: [*c]c.Enemy) c_int {
|
||||
if (e == null) return 0;
|
||||
if (e[0].alive == 0) return 0;
|
||||
|
||||
var total: c_int = 0;
|
||||
const safe_count = clampCount(e[0].effect_count);
|
||||
|
||||
for (0..safe_count) |i| {
|
||||
total += tickOne(&e[0].effects[i], &e[0].hp);
|
||||
}
|
||||
|
||||
if (e[0].hp <= 0) {
|
||||
e[0].hp = 0;
|
||||
e[0].alive = 0;
|
||||
}
|
||||
|
||||
compact(&e[0].effects, &e[0].effect_count);
|
||||
return total;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue