feat: add combat, wild wolves, factions, and tribe war motivation
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
class_name FactionStateRecord
|
||||
extends RefCounted
|
||||
|
||||
signal changed(state: FactionStateRecord)
|
||||
|
||||
const SCHEMA_VERSION := 1
|
||||
|
||||
var data: Dictionary
|
||||
|
||||
|
||||
func _init(record_data: Dictionary = {}) -> void:
|
||||
data = record_data.duplicate(true)
|
||||
|
||||
|
||||
static func _snap_food(value: float) -> float:
|
||||
return snappedf(value, 1.0 / 64.0)
|
||||
|
||||
|
||||
static func create(
|
||||
faction_id: StringName,
|
||||
display_name: String,
|
||||
food: float,
|
||||
warriors: int,
|
||||
aggression: float,
|
||||
morale: float
|
||||
) -> FactionStateRecord:
|
||||
return (
|
||||
FactionStateRecord
|
||||
. new(
|
||||
{
|
||||
"schema_version": SCHEMA_VERSION,
|
||||
"faction_id": String(faction_id),
|
||||
"display_name": display_name,
|
||||
"food": _snap_food(food),
|
||||
"warriors": warriors,
|
||||
"aggression": clampf(aggression, 0.0, 1.0),
|
||||
"morale": clampf(morale, 0.0, 1.0),
|
||||
"stance": String(SimulationIds.STANCE_NEUTRAL),
|
||||
"war_plan": String(SimulationIds.WAR_PLAN_NONE),
|
||||
"plan_tick": -1,
|
||||
"confidence": 0.0,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
static func from_dictionary(record_data: Dictionary) -> FactionStateRecord:
|
||||
if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION:
|
||||
return null
|
||||
if not (
|
||||
record_data
|
||||
. has_all(
|
||||
[
|
||||
"faction_id",
|
||||
"display_name",
|
||||
"food",
|
||||
"warriors",
|
||||
"aggression",
|
||||
"morale",
|
||||
"stance",
|
||||
"war_plan",
|
||||
"plan_tick",
|
||||
"confidence",
|
||||
]
|
||||
)
|
||||
):
|
||||
return null
|
||||
var faction_id := String(record_data["faction_id"])
|
||||
var display_name := String(record_data["display_name"])
|
||||
if faction_id.is_empty() or display_name.is_empty():
|
||||
return null
|
||||
var food := float(record_data["food"])
|
||||
var warriors := int(record_data["warriors"])
|
||||
var aggression := float(record_data["aggression"])
|
||||
var morale := float(record_data["morale"])
|
||||
var confidence := float(record_data["confidence"])
|
||||
if (
|
||||
not is_finite(food)
|
||||
or not is_finite(aggression)
|
||||
or not is_finite(morale)
|
||||
or not is_finite(confidence)
|
||||
or food < 0.0
|
||||
or warriors < 0
|
||||
or aggression < 0.0
|
||||
or aggression > 1.0
|
||||
or morale < 0.0
|
||||
or morale > 1.0
|
||||
or confidence < 0.0
|
||||
or confidence > 1.0
|
||||
):
|
||||
return null
|
||||
var normalized := record_data.duplicate(true)
|
||||
normalized["schema_version"] = SCHEMA_VERSION
|
||||
normalized["faction_id"] = faction_id
|
||||
normalized["display_name"] = display_name
|
||||
normalized["food"] = _snap_food(food)
|
||||
normalized["warriors"] = warriors
|
||||
normalized["aggression"] = aggression
|
||||
normalized["morale"] = morale
|
||||
normalized["stance"] = String(record_data["stance"])
|
||||
normalized["war_plan"] = String(record_data["war_plan"])
|
||||
normalized["plan_tick"] = int(record_data["plan_tick"])
|
||||
normalized["confidence"] = confidence
|
||||
return FactionStateRecord.new(normalized)
|
||||
|
||||
|
||||
func get_faction_id() -> StringName:
|
||||
return StringName(data["faction_id"])
|
||||
|
||||
|
||||
func get_display_name() -> String:
|
||||
return String(data["display_name"])
|
||||
|
||||
|
||||
func get_food() -> float:
|
||||
return maxf(float(data["food"]), 0.0)
|
||||
|
||||
|
||||
func get_warriors() -> int:
|
||||
return int(data["warriors"])
|
||||
|
||||
|
||||
func get_aggression() -> float:
|
||||
return clampf(float(data["aggression"]), 0.0, 1.0)
|
||||
|
||||
|
||||
func get_morale() -> float:
|
||||
return clampf(float(data["morale"]), 0.0, 1.0)
|
||||
|
||||
|
||||
func get_stance() -> StringName:
|
||||
return StringName(data["stance"])
|
||||
|
||||
|
||||
func get_war_plan() -> StringName:
|
||||
return StringName(data["war_plan"])
|
||||
|
||||
|
||||
func get_plan_tick() -> int:
|
||||
return int(data["plan_tick"])
|
||||
|
||||
|
||||
func get_confidence() -> float:
|
||||
return clampf(float(data["confidence"]), 0.0, 1.0)
|
||||
|
||||
|
||||
func set_food(value: float) -> void:
|
||||
var next := _snap_food(maxf(value, 0.0))
|
||||
if is_equal_approx(next, get_food()):
|
||||
return
|
||||
data["food"] = next
|
||||
changed.emit(self)
|
||||
|
||||
|
||||
func set_morale(value: float) -> void:
|
||||
var next := clampf(value, 0.0, 1.0)
|
||||
if is_equal_approx(next, get_morale()):
|
||||
return
|
||||
data["morale"] = next
|
||||
changed.emit(self)
|
||||
|
||||
|
||||
func set_stance(value: StringName) -> void:
|
||||
if String(value) == String(get_stance()):
|
||||
return
|
||||
data["stance"] = String(value)
|
||||
changed.emit(self)
|
||||
|
||||
|
||||
func set_war_plan(value: StringName, current_tick: int, confidence: float = -1.0) -> void:
|
||||
data["war_plan"] = String(value)
|
||||
data["plan_tick"] = current_tick
|
||||
if confidence >= 0.0:
|
||||
data["confidence"] = clampf(confidence, 0.0, 1.0)
|
||||
changed.emit(self)
|
||||
|
||||
|
||||
func to_dictionary() -> Dictionary:
|
||||
return data.duplicate(true)
|
||||
Reference in New Issue
Block a user