Rebuild interaction layer on @YAProxy (1.29-working)
Replace the ZenProxyFramework dependency (broken on 1.29) with @YAProxy, our self-contained proxy framework. Actions now extend YAProxyActionBase: - Search / RepairSink / GatherWater resolve the targeted furniture proxy by keyword and use the synced world position from YAProxy - Confirmed proxy names from live test: case_sink_a, fridge, lekarnicka (vending defaulted to 'sodamachine' pending confirmation) - Registry lookup matches proxy names as substrings (handles '.001' suffix) - Sink repaired-state + search/water cooldowns tracked server-side, keyed by proxy world position / player UID (in-memory, reset on restart per v1 spec) - Repair on Wrench/PipeWrench, GatherWater on Bottle_Base (item-based, load- order safe); Search on PlayerBase requiredAddons: YAProxy. Loot tables / settings JSON unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e4cb0e4009
commit
5a07c85416
9 changed files with 126 additions and 196 deletions
|
|
@ -3,6 +3,11 @@
|
|||
A DayZ server mod that adds interactable furniture (search for loot) and a
|
||||
two-stage repairable sink (repair, then gather water).
|
||||
|
||||
> **Requires [@YAProxy](http://192.168.88.23/edvinas/YAProxy)** — the furniture
|
||||
> are proxies baked into house models, not entities. @YAProxy handles proxy
|
||||
> detection + position sync; YAInteraction's actions extend `YAProxyActionBase`.
|
||||
> Load `@YAProxy` before `@YAInteraction` (handled via `requiredAddons`).
|
||||
|
||||
## Features
|
||||
|
||||
- **Searchable furniture** — medical cabinet, fridge, and vending machine yield
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class CfgPatches
|
|||
{
|
||||
"DZ_Data",
|
||||
"DZ_Scripts",
|
||||
"ZenProxyFramework" // dependency: ensures ZPF loads before us (proxy API + ZenProxySinkTest)
|
||||
"YAProxy" // dependency: proxy detection framework (loads before us)
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,29 +2,22 @@
|
|||
// ActionYAGatherWater
|
||||
// ----------------------------------------------------------------------------
|
||||
// Stage 2 of the sink. Attached to the liquid container in the player's hands
|
||||
// (Bottle_Base). Only usable once the sink is repaired (a ZenProxySinkTest
|
||||
// entity exists at the proxy world position). Fills the held container with a
|
||||
// random amount of water from config, gated by a per-player cooldown.
|
||||
// (Bottle_Base). Only succeeds once the sink is repaired (server state keyed by
|
||||
// proxy world pos). Fills the held container with a random amount of water from
|
||||
// config, gated by a per-player cooldown.
|
||||
//
|
||||
// Registered on Bottle_Base (see YAInteractionInit) - item-based.
|
||||
// ============================================================================
|
||||
|
||||
class ActionYAGatherWaterCB : ActionContinuousBaseCB
|
||||
class ActionYAGatherWater : YAProxyActionBase
|
||||
{
|
||||
override void CreateActionComponent()
|
||||
override float GetDuration()
|
||||
{
|
||||
m_ActionData.m_ActionComponent = new CAContinuousTime(YAInteractionConfig.GATHER_WATER_TIME);
|
||||
return YAInteractionConfig.GATHER_WATER_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
class ActionYAGatherWater : ActionContinuousBase
|
||||
{
|
||||
void ActionYAGatherWater()
|
||||
override string GetProxyKeywords()
|
||||
{
|
||||
m_CallbackClass = ActionYAGatherWaterCB;
|
||||
m_CommandUID = DayZPlayerConstants.CMD_ACTIONFB_FILLBOTTLEWELL;
|
||||
m_FullBody = true;
|
||||
m_StanceMask = DayZPlayerConstants.STANCEMASK_ERECT | DayZPlayerConstants.STANCEMASK_CROUCH;
|
||||
return YAInteractionManager.GetRepairWaterProxyNames();
|
||||
}
|
||||
|
||||
override string GetText()
|
||||
|
|
@ -32,46 +25,15 @@ class ActionYAGatherWater : ActionContinuousBase
|
|||
return "Gather Water";
|
||||
}
|
||||
|
||||
override bool HasZenProxyTarget()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
override string GetZenProxyNameTarget()
|
||||
{
|
||||
return YAInteractionManager.GetRepairWaterProxyNames();
|
||||
}
|
||||
|
||||
override void CreateConditionComponents()
|
||||
{
|
||||
m_ConditionItem = new CCINonRuined(); // the container in hands
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.SMALL);
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.DEFAULT);
|
||||
}
|
||||
|
||||
override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
|
||||
override bool YA_ExtraCondition(PlayerBase player, ActionTarget target, ItemBase item, string proxyName, vector proxyWS)
|
||||
{
|
||||
if (!CanFill(item))
|
||||
return false;
|
||||
|
||||
if (!IsTargetingZenActionProxy(player, target, item))
|
||||
return false;
|
||||
|
||||
// Client-only: only available when the sink is repaired (entity exists).
|
||||
if (GetGame().IsClient())
|
||||
{
|
||||
vector ls, ws;
|
||||
string houseType;
|
||||
GetZenActionProxyTargetEx(player, target, item, ls, ws, houseType);
|
||||
if (!GetProxyObject(ws, YAInteractionConfig.SINK_PROXY_ENTITY))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
override bool IsLockTargetOnUse()
|
||||
{
|
||||
return false;
|
||||
return CanFill(item);
|
||||
}
|
||||
|
||||
override void OnFinishProgressServer(ActionData action_data)
|
||||
|
|
@ -80,10 +42,10 @@ class ActionYAGatherWater : ActionContinuousBase
|
|||
if (!player || !player.GetIdentity())
|
||||
return;
|
||||
|
||||
vector proxyWS = GetZenProxyTargetWS(action_data);
|
||||
vector proxyWS = GetProxyWS(action_data);
|
||||
string posKey = proxyWS.ToString(false);
|
||||
|
||||
// Defensive: sink must be repaired.
|
||||
if (!GetProxyObject(proxyWS, YAInteractionConfig.SINK_PROXY_ENTITY))
|
||||
if (!YAInteractionManager.IsSinkRepaired(posKey))
|
||||
{
|
||||
player.MessageStatus("The sink needs to be repaired first.");
|
||||
return;
|
||||
|
|
@ -92,8 +54,7 @@ class ActionYAGatherWater : ActionContinuousBase
|
|||
string uid = player.GetIdentity().GetId();
|
||||
if (YAInteractionManager.IsWaterOnCooldown(uid))
|
||||
{
|
||||
int remaining = YAInteractionManager.GetWaterCooldownRemaining(uid);
|
||||
player.MessageStatus(string.Format("You need to wait before gathering water again. (%1s)", remaining));
|
||||
player.MessageStatus(string.Format("You need to wait before gathering water again. (%1s)", YAInteractionManager.GetWaterCooldownRemaining(uid)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -107,9 +68,8 @@ class ActionYAGatherWater : ActionContinuousBase
|
|||
float amount = Math.RandomFloatInclusive(YAInteractionConfigLoader.Settings.WaterAmountMin, YAInteractionConfigLoader.Settings.WaterAmountMax);
|
||||
Liquid.FillContainer(container, YAInteractionConfig.WATER_LIQUID_TYPE, amount);
|
||||
|
||||
// Cooldown comes from the sink's registry entry.
|
||||
YAInteractableEntry entry = YAInteractionManager.GetEntryByProxyName(GetZenProxyTargetType(action_data));
|
||||
float cd = YAInteractionConfigLoader.Settings.SinkPlayerCooldownSec;
|
||||
YAInteractableEntry entry = YAInteractionManager.GetEntryByProxyName(GetProxyName(action_data));
|
||||
if (entry && entry.CooldownSec > 0)
|
||||
cd = entry.CooldownSec;
|
||||
YAInteractionManager.StampWaterCooldown(uid, cd);
|
||||
|
|
|
|||
|
|
@ -1,31 +1,23 @@
|
|||
// ============================================================================
|
||||
// ActionYARepairSink
|
||||
// ----------------------------------------------------------------------------
|
||||
// Stage 1 of the sink. Requires a wrench/pipe wrench (the item this action is
|
||||
// attached to). On completion it spawns a ZenProxySinkTest entity at the sink
|
||||
// proxy's world position - the entity's PRESENCE represents "repaired" and is
|
||||
// networked to all clients (ZenProxyFramework pattern).
|
||||
// Stage 1 of the sink. Requires a wrench / pipe wrench (the item this action
|
||||
// is attached to). On completion it flags the sink (keyed by proxy world pos)
|
||||
// as repaired in YAInteractionManager, which unlocks ActionYAGatherWater.
|
||||
//
|
||||
// Registered on Wrench + PipeWrench (see YAInteractionInit) - item-based, so
|
||||
// it is unaffected by PlayerBase action load-order issues.
|
||||
// Registered on Wrench + PipeWrench (see YAInteractionInit) - item-based.
|
||||
// Repaired state is in-memory and resets on server restart (v1).
|
||||
// ============================================================================
|
||||
|
||||
class ActionYARepairSinkCB : ActionContinuousBaseCB
|
||||
class ActionYARepairSink : YAProxyActionBase
|
||||
{
|
||||
override void CreateActionComponent()
|
||||
override float GetDuration()
|
||||
{
|
||||
m_ActionData.m_ActionComponent = new CAContinuousTime(YAInteractionConfig.REPAIR_TIME);
|
||||
return YAInteractionConfig.REPAIR_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
class ActionYARepairSink : ActionContinuousBase
|
||||
{
|
||||
void ActionYARepairSink()
|
||||
override string GetProxyKeywords()
|
||||
{
|
||||
m_CallbackClass = ActionYARepairSinkCB;
|
||||
m_CommandUID = DayZPlayerConstants.CMD_ACTIONFB_INTERACT;
|
||||
m_FullBody = true;
|
||||
m_StanceMask = DayZPlayerConstants.STANCEMASK_ERECT | DayZPlayerConstants.STANCEMASK_CROUCH;
|
||||
return YAInteractionManager.GetRepairWaterProxyNames();
|
||||
}
|
||||
|
||||
override string GetText()
|
||||
|
|
@ -33,66 +25,31 @@ class ActionYARepairSink : ActionContinuousBase
|
|||
return "Repair Sink";
|
||||
}
|
||||
|
||||
override bool HasZenProxyTarget()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
override string GetZenProxyNameTarget()
|
||||
{
|
||||
return YAInteractionManager.GetRepairWaterProxyNames();
|
||||
}
|
||||
|
||||
override void CreateConditionComponents()
|
||||
{
|
||||
m_ConditionItem = new CCINonRuined(); // the wrench in hands
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.SMALL);
|
||||
}
|
||||
|
||||
override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
|
||||
{
|
||||
if (!IsTargetingZenActionProxy(player, target, item))
|
||||
return false;
|
||||
|
||||
// Client-only: hide if the sink is already repaired (entity exists).
|
||||
if (GetGame().IsClient())
|
||||
{
|
||||
vector ls, ws;
|
||||
string houseType;
|
||||
GetZenActionProxyTargetEx(player, target, item, ls, ws, houseType);
|
||||
if (GetProxyObject(ws, YAInteractionConfig.SINK_PROXY_ENTITY))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
override bool IsLockTargetOnUse()
|
||||
{
|
||||
return false;
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.DEFAULT);
|
||||
}
|
||||
|
||||
override void OnFinishProgressServer(ActionData action_data)
|
||||
{
|
||||
PlayerBase player = action_data.m_Player;
|
||||
vector proxyWS = GetZenProxyTargetWS(action_data);
|
||||
vector proxyWS = GetProxyWS(action_data);
|
||||
string posKey = proxyWS.ToString(false);
|
||||
|
||||
// Already repaired? (entity present)
|
||||
if (GetProxyObject(proxyWS, YAInteractionConfig.SINK_PROXY_ENTITY))
|
||||
if (YAInteractionManager.IsSinkRepaired(posKey))
|
||||
{
|
||||
if (player)
|
||||
player.MessageStatus("This sink is already repaired.");
|
||||
return;
|
||||
}
|
||||
|
||||
Object marker = GetGame().CreateObjectEx(YAInteractionConfig.SINK_PROXY_ENTITY, proxyWS, ECE_FULL);
|
||||
if (!marker)
|
||||
{
|
||||
Print("[YAInteraction] FAILED to spawn sink marker @ " + proxyWS.ToString(false));
|
||||
return;
|
||||
}
|
||||
YAInteractionManager.SetSinkRepaired(posKey, true);
|
||||
|
||||
Print(string.Format("[YAInteraction] %1 repaired sink @ %2", player.GetIdentity().GetId(), proxyWS.ToString(false)));
|
||||
player.MessageStatus("You repaired the sink. You can now gather water.");
|
||||
if (player)
|
||||
{
|
||||
Print(string.Format("[YAInteraction] %1 repaired sink @ %2", player.GetIdentity().GetId(), posKey));
|
||||
player.MessageStatus("You repaired the sink. You can now gather water.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,23 @@
|
|||
// ============================================================================
|
||||
// ActionYASearch
|
||||
// ----------------------------------------------------------------------------
|
||||
// Empty-handed "Search" on a searchable furniture PROXY (fridge / med cabinet
|
||||
// / vending machine). Uses ZenProxyFramework: the action targets proxies by
|
||||
// name (GetZenProxyNameTarget) and the proxy world position is synced to the
|
||||
// server via ActionData, so OnFinishProgressServer can roll loot + gate the
|
||||
// per-object cooldown by that position.
|
||||
// Empty-handed "Search" on a searchable furniture proxy (fridge / med cabinet
|
||||
// / vending machine). Built on YAProxy: the framework resolves which proxy the
|
||||
// cursor is on and syncs its name + world position to the server. We roll our
|
||||
// loot table for that proxy and gate a per-object cooldown by the world pos.
|
||||
//
|
||||
// Registered on PlayerBase (see YAInteractionInit). Cooldown is in-memory.
|
||||
// TODO (v2): persist the per-proxy cooldown via CF.
|
||||
// Registered on PlayerBase (see YAInteractionInit).
|
||||
// ============================================================================
|
||||
|
||||
class ActionYASearchCB : ActionContinuousBaseCB
|
||||
class ActionYASearch : YAProxyActionBase
|
||||
{
|
||||
override void CreateActionComponent()
|
||||
override float GetDuration()
|
||||
{
|
||||
m_ActionData.m_ActionComponent = new CAContinuousTime(YAInteractionConfig.SEARCH_TIME);
|
||||
return YAInteractionConfig.SEARCH_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
class ActionYASearch : ActionContinuousBase
|
||||
{
|
||||
void ActionYASearch()
|
||||
override string GetProxyKeywords()
|
||||
{
|
||||
m_CallbackClass = ActionYASearchCB;
|
||||
m_CommandUID = DayZPlayerConstants.CMD_ACTIONFB_INTERACT;
|
||||
m_FullBody = true;
|
||||
m_StanceMask = DayZPlayerConstants.STANCEMASK_ERECT | DayZPlayerConstants.STANCEMASK_CROUCH;
|
||||
return YAInteractionManager.GetSearchProxyNames();
|
||||
}
|
||||
|
||||
override string GetText()
|
||||
|
|
@ -34,33 +25,15 @@ class ActionYASearch : ActionContinuousBase
|
|||
return "Search";
|
||||
}
|
||||
|
||||
override bool HasZenProxyTarget()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
override string GetZenProxyNameTarget()
|
||||
{
|
||||
return YAInteractionManager.GetSearchProxyNames();
|
||||
}
|
||||
|
||||
override void CreateConditionComponents()
|
||||
{
|
||||
m_ConditionItem = new CCINone();
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.SMALL);
|
||||
m_ConditionItem = new CCINotPresent(); // empty-handed
|
||||
m_ConditionTarget = new CCTCursorParent(UAMaxDistances.DEFAULT);
|
||||
}
|
||||
|
||||
override bool ActionCondition(PlayerBase player, ActionTarget target, ItemBase item)
|
||||
override bool YA_ExtraCondition(PlayerBase player, ActionTarget target, ItemBase item, string proxyName, vector proxyWS)
|
||||
{
|
||||
if (player.GetItemInHands())
|
||||
return false;
|
||||
|
||||
return IsTargetingZenActionProxy(player, target, item);
|
||||
}
|
||||
|
||||
override bool IsLockTargetOnUse()
|
||||
{
|
||||
return false;
|
||||
return !player.GetItemInHands();
|
||||
}
|
||||
|
||||
override void OnFinishProgressServer(ActionData action_data)
|
||||
|
|
@ -69,10 +42,10 @@ class ActionYASearch : ActionContinuousBase
|
|||
if (!player)
|
||||
return;
|
||||
|
||||
string proxyType = GetZenProxyTargetType(action_data);
|
||||
vector proxyWS = GetZenProxyTargetWS(action_data);
|
||||
string proxyName = GetProxyName(action_data);
|
||||
vector proxyWS = GetProxyWS(action_data);
|
||||
|
||||
YAInteractableEntry entry = YAInteractionManager.GetEntryByProxyName(proxyType);
|
||||
YAInteractableEntry entry = YAInteractionManager.GetEntryByProxyName(proxyName);
|
||||
if (!entry || entry.ActionType != YAInteractionConfig.ACTION_SEARCH)
|
||||
return;
|
||||
|
||||
|
|
@ -80,8 +53,7 @@ class ActionYASearch : ActionContinuousBase
|
|||
|
||||
if (YAInteractionManager.IsSearchOnCooldown(posKey))
|
||||
{
|
||||
int remaining = YAInteractionManager.GetSearchCooldownRemaining(posKey);
|
||||
player.MessageStatus(string.Format("You already searched this. (%1s)", remaining));
|
||||
player.MessageStatus(string.Format("You already searched this. (%1s)", YAInteractionManager.GetSearchCooldownRemaining(posKey)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +63,7 @@ class ActionYASearch : ActionContinuousBase
|
|||
|
||||
YAInteractionManager.StampSearchCooldown(posKey, entry.CooldownSec);
|
||||
|
||||
Print(string.Format("[YAInteraction] %1 searched proxy '%2' @ %3 -> %4 item(s)", player.GetIdentity().GetId(), proxyType, posKey, spawned.Count()));
|
||||
Print(string.Format("[YAInteraction] %1 searched '%2' @ %3 -> %4 item(s)", player.GetIdentity().GetId(), proxyName, posKey, spawned.Count()));
|
||||
|
||||
if (spawned.Count() > 0)
|
||||
player.MessageStatus(string.Format("You found %1 item(s).", spawned.Count()));
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ class YAInteractionConfig
|
|||
static const string TABLE_FOOD = "FoodTable";
|
||||
static const string TABLE_VENDING = "VendingTable";
|
||||
|
||||
// ZenProxyFramework entity reused as the sink "repaired" marker.
|
||||
static const string SINK_PROXY_ENTITY = "ZenProxySinkTest";
|
||||
|
||||
// Non-JSON engine constants.
|
||||
static const int WATER_LIQUID_TYPE = LIQUID_WATER;
|
||||
static const int SEARCH_ROLLS_MIN = 1;
|
||||
|
|
|
|||
|
|
@ -107,10 +107,13 @@ class YAInteractionConfigLoader
|
|||
// "case_sink_a" is confirmed (it's in ZenProxyConstants.SINKS). The search
|
||||
// names are best guesses - confirm via ZPF's proxy dump / debug F-key and
|
||||
// correct them in interactables.json (or here + rebuild).
|
||||
d.Interactables.Insert(MakeEntry("case_sink_a", YAInteractionConfig.ACTION_REPAIR_WATER, "", Settings.SinkPlayerCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("lekarnicka", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_MED, Settings.ObjectCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("fridge", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_FOOD, Settings.ObjectCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("vending_machine", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_VENDING, Settings.ObjectCooldownSec));
|
||||
// Proxy names confirmed via YAProxy debug: case_sink_a / fridge / lekarnicka.
|
||||
// Vending not yet confirmed - "sodamachine" is ZenProxyFramework's name;
|
||||
// adjust here (or in interactables.json) if your map differs.
|
||||
d.Interactables.Insert(MakeEntry("case_sink_a", YAInteractionConfig.ACTION_REPAIR_WATER, "", Settings.SinkPlayerCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("lekarnicka", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_MED, Settings.ObjectCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("fridge", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_FOOD, Settings.ObjectCooldownSec));
|
||||
d.Interactables.Insert(MakeEntry("sodamachine", YAInteractionConfig.ACTION_SEARCH, YAInteractionConfig.TABLE_VENDING, Settings.ObjectCooldownSec));
|
||||
|
||||
// --- Loot tables (classnames verified in P:\DZ) ---
|
||||
YALootTable med = MakeTable(YAInteractionConfig.TABLE_MED);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,26 @@
|
|||
// ============================================================================
|
||||
// YAInteractionManager
|
||||
// ----------------------------------------------------------------------------
|
||||
// Builds runtime lookups from the loaded config (keyed by ZenProxyFramework
|
||||
// proxy name) and owns the in-memory cooldowns.
|
||||
// Builds runtime lookups from the loaded config (keyed by YAProxy proxy name)
|
||||
// and owns the in-memory cooldowns + sink repaired-state.
|
||||
//
|
||||
// Repair state is NOT tracked here - it's represented by the presence of a
|
||||
// ZenProxySinkTest entity spawned at the sink (ZenProxyFramework pattern), so
|
||||
// it is networked to clients for free.
|
||||
//
|
||||
// Cooldowns (reset on restart):
|
||||
// * Search - per-object, keyed by proxy world-position string.
|
||||
// * Water - per-player, keyed by player UID.
|
||||
// TODO (v2): persist cooldowns via CF, keyed by proxy world position.
|
||||
// In-memory, reset on server restart (v1 spec):
|
||||
// * Search cooldown - per-object, keyed by proxy world-position string.
|
||||
// * Water cooldown - per-player, keyed by player UID.
|
||||
// * Sink repaired flag - per-object, keyed by proxy world-position string.
|
||||
// TODO (v2): persist via CF, and/or spawn a networked invisible marker so the
|
||||
// client can hide the Repair action once a sink is fixed.
|
||||
// ============================================================================
|
||||
class YAInteractionManager
|
||||
{
|
||||
private static ref map<string, ref YAInteractableEntry> m_EntryByProxy = new map<string, ref YAInteractableEntry>();
|
||||
private static ref map<string, ref YALootTable> m_TableByName = new map<string, ref YALootTable>();
|
||||
|
||||
private static ref map<string, int> m_SearchCooldowns = new map<string, int>(); // proxyWorldPos -> expiry ms
|
||||
private static ref map<string, int> m_WaterCooldowns = new map<string, int>(); // playerUID -> expiry ms
|
||||
private static ref map<string, int> m_SearchCooldowns = new map<string, int>(); // proxyWorldPos -> expiry ms
|
||||
private static ref map<string, int> m_WaterCooldowns = new map<string, int>(); // playerUID -> expiry ms
|
||||
private static ref map<string, bool> m_RepairedSinks = new map<string, bool>(); // proxyWorldPos -> repaired (resets on restart)
|
||||
|
||||
// Cached comma-joined proxy-name lists for the actions' GetZenProxyNameTarget().
|
||||
// Cached comma-joined proxy-name lists for the actions' GetProxyKeywords().
|
||||
private static string m_SearchProxyNames = "";
|
||||
private static string m_RepairWaterProxyNames = "";
|
||||
|
||||
|
|
@ -99,17 +98,33 @@ class YAInteractionManager
|
|||
return m_RepairWaterProxyNames;
|
||||
}
|
||||
|
||||
// Case-insensitive lookup by proxy name.
|
||||
// Lookup by proxy name. The resolved name often carries an instance suffix
|
||||
// (e.g. "fridge.001"), so we match the registry key as a substring.
|
||||
static YAInteractableEntry GetEntryByProxyName(string proxyName)
|
||||
{
|
||||
EnsureReady();
|
||||
if (proxyName == "")
|
||||
return null;
|
||||
string key = proxyName;
|
||||
key.ToLower();
|
||||
YAInteractableEntry e;
|
||||
if (m_EntryByProxy.Find(key, e))
|
||||
return e;
|
||||
|
||||
string lower = proxyName;
|
||||
lower.ToLower();
|
||||
|
||||
YAInteractableEntry exact;
|
||||
if (m_EntryByProxy.Find(lower, exact))
|
||||
return exact;
|
||||
|
||||
if (!YAInteractionConfigLoader.Data)
|
||||
return null;
|
||||
|
||||
foreach (YAInteractableEntry entry : YAInteractionConfigLoader.Data.Interactables)
|
||||
{
|
||||
if (!entry || entry.ProxyName == "")
|
||||
continue;
|
||||
string key = entry.ProxyName;
|
||||
key.ToLower();
|
||||
if (lower.Contains(key))
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -176,4 +191,25 @@ class YAInteractionManager
|
|||
{
|
||||
m_WaterCooldowns.Set(uid, GetGame().GetTime() + (int)(cooldownSec * 1000));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Sink repaired state (server-side, keyed by proxy world position).
|
||||
// In-memory only -> resets on server restart (v1 spec).
|
||||
// TODO (v2): spawn a networked invisible marker (so the client hides the
|
||||
// Repair action once done) + CF/types.xml lifetime for cross-restart expiry.
|
||||
// ------------------------------------------------------------------
|
||||
static bool IsSinkRepaired(string posKey)
|
||||
{
|
||||
bool repaired;
|
||||
if (m_RepairedSinks.Find(posKey, repaired))
|
||||
return repaired;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SetSinkRepaired(string posKey, bool value = true)
|
||||
{
|
||||
m_RepairedSinks.Set(posKey, value);
|
||||
Print(string.Format("[YAInteraction] Sink repaired state %1 = %2", posKey, value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ============================================================================
|
||||
// YAInteractionInit
|
||||
// ----------------------------------------------------------------------------
|
||||
// Wires the actions into the game, following the ZenProxyFramework pattern:
|
||||
// Wires the actions into the game (actions extend YAProxyActionBase):
|
||||
//
|
||||
// * ActionConstructor - register custom actions so GetAction() resolves them
|
||||
// (otherwise AddAction() dereferences null -> crash).
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
// * Wrench / PipeWrench - Repair Sink (item-in-hands; load-order safe).
|
||||
// * Bottle_Base - Gather Water (item-in-hands; load-order safe).
|
||||
//
|
||||
// Furniture identification + position sync is handled by ZenProxyFramework's
|
||||
// modded ActionBase (GetZenProxyNameTarget / GetZenProxyTargetWS).
|
||||
// Furniture identification + position sync is handled by @YAProxy
|
||||
// (YAProxyActionBase: GetProxyKeywords / GetProxyName / GetProxyWS).
|
||||
// ============================================================================
|
||||
|
||||
modded class ActionConstructor
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue