Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
74 lines
4.7 KiB
Plaintext
74 lines
4.7 KiB
Plaintext
--- a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c
|
|
+++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c
|
|
@@ -5,6 +5,7 @@
|
|
protected ref map<ERR_LocationComponent, int> m_ERRIntelSeen = new map<ERR_LocationComponent, int>();
|
|
protected ref map<ERR_LocationComponent, int> m_ERRIntelPending = new map<ERR_LocationComponent, int>();
|
|
protected float m_ERRIntelMessageAt;
|
|
+ protected float m_ERRIntelExhaustedAt;
|
|
protected bool m_ERRIntelFeedbackStopped;
|
|
protected int m_ERRIntelMessageSequence;
|
|
protected int m_ERRIntelReceivedSequence;
|
|
@@ -63,6 +64,11 @@
|
|
void ERR_IntelExhausted(bool duplicate = false)
|
|
{
|
|
if (!Replication.IsServer() || m_ERRIntelFeedbackStopped || !Active()) return;
|
|
+ // Recover scans a whole inventory; surplus folders share one team notice.
|
|
+ // Keep useful new discoveries on their independent coalescing schedule.
|
|
+ float now = GetWorld().GetWorldTime();
|
|
+ if (now < m_ERRIntelExhaustedAt) return;
|
|
+ m_ERRIntelExhaustedAt = now + 5000;
|
|
string message = "Every known location has already been identified. This intel doesn't help us.";
|
|
if (duplicate) message = "This document concerns a location we have already identified.";
|
|
m_ERRIntelMessageSequence++;
|
|
@@ -75,6 +81,7 @@
|
|
m_ERRIntelPending.Clear();
|
|
m_ERRIntelSeen.Clear();
|
|
m_ERRIntelMessageAt = 0;
|
|
+ m_ERRIntelExhaustedAt = 0;
|
|
OnLocationDiscovered().Remove(ERR_QueueDiscoveryFeedback);
|
|
OnTick().Remove(ERR_FlushDiscoveryFeedback);
|
|
}
|
|
--- a/tests/test_intel_discovery_feedback.py
|
|
+++ b/tests/test_intel_discovery_feedback.py
|
|
@@ -1,6 +1,8 @@
|
|
"""Execute production feedback queue/delivery bodies with fake engine boundaries."""
|
|
from policy_harness import ROOT, body, run
|
|
-P=ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c'
|
|
+from pathlib import Path
|
|
+import os
|
|
+P=Path(os.environ.get('ERR_INTEL_FEEDBACK_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c'))
|
|
source=P.read_text()
|
|
def cpp(s):
|
|
s=s.replace('protected ', '').replace('static ', '')
|
|
@@ -42,7 +44,7 @@
|
|
static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}
|
|
bool active=true;int phase=ERR_Phase::RADIO_SEARCH;bool Active(){return active;}int Phase(){return phase;}World* GetWorld(){return &world;}
|
|
Map<ERR_LocationComponent*,int> m_ERRIntelSeen,m_ERRIntelPending;
|
|
- float m_ERRIntelMessageAt=0;bool m_ERRIntelFeedbackStopped=false;int m_ERRIntelMessageSequence=0,m_ERRIntelReceivedSequence=0;
|
|
+ float m_ERRIntelMessageAt=0,m_ERRIntelExhaustedAt=0;bool m_ERRIntelFeedbackStopped=false;int m_ERRIntelMessageSequence=0,m_ERRIntelReceivedSequence=0;
|
|
Events discovered,tick;Events& OnLocationDiscovered(){return discovered;}Events& OnTick(){return tick;}
|
|
int rpcCount=0;void Rpc(int sequence,string message){rpcCount++;ERR_ReceiveDiscoveryFeedback(sequence,message);}
|
|
'''+methods+r'''
|
|
@@ -79,6 +81,21 @@
|
|
assert(ERR_IntelDiscoveryText::Type(ERR_LocationKind::MORTAR,"any")=="mortar site");
|
|
ERR_GameMode::current=&m;m.ERR_IntelExhausted();assert(SCR_ChatComponent::messages.back()=="Every known location has already been identified. This intel doesn't help us.");
|
|
assert(ERR_IntelDiscoveryText::Message(0,0,"secret").empty());assert(ERR_IntelDiscoveryText::Message(1,0,"")=="Hey! A location was identified in the intel!");
|
|
+ // Recovering a stack of spent-topic folders performs one exhaustion broadcast,
|
|
+ // not one chat line/RPC per physical document. Both variants share the budget.
|
|
+ ERR_GameMode surplus;ERR_GameMode::current=&surplus;world.time=10000;
|
|
+ for(int i=0;i<20;i++)surplus.ERR_IntelExhausted(i%2==0);
|
|
+ assert(surplus.rpcCount==1&&surplus.m_ERRIntelMessageSequence==1);
|
|
+ // Actual new discovery still follows its own coalescing window immediately.
|
|
+ world.time=10000;ERR_LocationComponent fresh;surplus.ERR_QueueDiscoveryFeedback(&fresh,0,1);
|
|
+ surplus.ERR_FlushDiscoveryFeedback(11500);assert(surplus.rpcCount==2);
|
|
+ assert(SCR_ChatComponent::messages.back()=="New location marked. Type unknown.");
|
|
+ world.time=14999;surplus.ERR_IntelExhausted();assert(surplus.rpcCount==2);
|
|
+ world.time=15000;surplus.ERR_IntelExhausted();assert(surplus.rpcCount==3&&surplus.m_ERRIntelMessageSequence==3);
|
|
+ world.time=20000;Replication::server=false;surplus.ERR_IntelExhausted();assert(surplus.rpcCount==3);Replication::server=true;
|
|
+ surplus.ERR_StopDiscoveryFeedback();surplus.ERR_IntelExhausted();assert(surplus.rpcCount==3);
|
|
+ ERR_GameMode freshRound;ERR_GameMode::current=&freshRound;world.time=0;freshRound.ERR_IntelExhausted();assert(freshRound.rpcCount==1);
|
|
+
|
|
}
|
|
''')
|
|
for required in ('OnLocationDiscovered().Insert(ERR_QueueDiscoveryFeedback)', 'OnTick().Insert(ERR_FlushDiscoveryFeedback)', 'OnStop().Insert(ERR_StopDiscoveryFeedback)', '[RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]'):
|