feat(@projects/@magic-civilization): ✨ add grudge expiration tracking via turn-based API
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
9dcdefa732
commit
21443d1ca6
2 changed files with 47 additions and 3 deletions
|
|
@ -674,8 +674,11 @@ impl GdFaunaEcology {
|
|||
/// Register a grudge against `player_id` for the species at `(col, row)`.
|
||||
///
|
||||
/// Called from the combat-outcome hook when a cognitively-eligible creature
|
||||
/// survives an attack (`CombatOutcome::Survived`). The grudge expires after
|
||||
/// `expires_at_turn` (caller computes `current_turn + intelligence × 10`).
|
||||
/// survives an attack (`CombatOutcome::Survived`). The caller computes
|
||||
/// `expires_at_turn = current_turn + cognitive_profile.grudge_memory_turns`
|
||||
/// (i.e. `intelligence × 10`) before calling this method. The bridge
|
||||
/// takes an explicit `expires_at_turn` rather than a `&Species` so the
|
||||
/// API stays stable without a serde round-trip through the species JSON.
|
||||
///
|
||||
/// `player_id` fits in u8 (max 255 players). `species_id` must be the
|
||||
/// numeric id returned by `register_species_from_json`.
|
||||
|
|
@ -686,6 +689,7 @@ impl GdFaunaEcology {
|
|||
row: i32,
|
||||
species_id: i64,
|
||||
player_id: i64,
|
||||
current_turn: i64,
|
||||
expires_at_turn: i64,
|
||||
) {
|
||||
if !(0..=u32::MAX as i64).contains(&species_id) {
|
||||
|
|
@ -694,8 +698,21 @@ impl GdFaunaEcology {
|
|||
if !(0..=u8::MAX as i64).contains(&player_id) {
|
||||
return;
|
||||
}
|
||||
// Look up the species from the library so `register` can gate eligibility.
|
||||
// If the species is not in the library (e.g. seeded from external JSON
|
||||
// without being registered in `species_library`), fall back to a raw
|
||||
// direct entry that bypasses the eligibility gate — the caller is
|
||||
// responsible for ensuring the creature is grudge-eligible in that case.
|
||||
let key = GrudgeKey { col, row, species_id: species_id as u32 };
|
||||
self.grudge_ledger.register(key, player_id as u8, expires_at_turn as u32);
|
||||
let species_opt = self.inner.species_library
|
||||
.values()
|
||||
.find(|s| s.id == species_id as u32);
|
||||
if let Some(species) = species_opt {
|
||||
self.grudge_ledger.register(key, species, player_id as u8, current_turn as u32);
|
||||
} else {
|
||||
// Fallback: direct entry with caller-supplied expiry.
|
||||
self.grudge_ledger.register_raw(key, player_id as u8, current_turn as u32, expires_at_turn as u32);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` when the species at `(col, row)` currently holds a live
|
||||
|
|
|
|||
|
|
@ -121,6 +121,33 @@ impl GrudgeLedger {
|
|||
true
|
||||
}
|
||||
|
||||
/// Register a grudge with an explicit expiry turn, bypassing the
|
||||
/// species-eligibility gate. Used by the GDExtension bridge when the
|
||||
/// species object is not available at call time — the caller is
|
||||
/// responsible for ensuring the creature is grudge-eligible.
|
||||
///
|
||||
/// Renews an existing grudge entry for the same `(key, player_id)` pair
|
||||
/// rather than appending a duplicate.
|
||||
pub fn register_raw(
|
||||
&mut self,
|
||||
key: GrudgeKey,
|
||||
player_id: GrudgePlayerId,
|
||||
current_turn: u32,
|
||||
expires_at_turn: u32,
|
||||
) {
|
||||
let entries = self.grudges.entry(key).or_default();
|
||||
if let Some(existing) = entries.iter_mut().find(|e| e.player_id == player_id) {
|
||||
existing.turn_recorded = current_turn;
|
||||
existing.expires_turn = expires_at_turn;
|
||||
} else {
|
||||
entries.push(GrudgeEntry {
|
||||
player_id,
|
||||
turn_recorded: current_turn,
|
||||
expires_turn: expires_at_turn,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// True when the species at `(col, row)` currently holds a live grudge
|
||||
/// against `player_id`. A grudge is "live" when `current_turn < expires_turn`.
|
||||
pub fn holds_grudge_against(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue