94 lines
4.1 KiB
C
94 lines
4.1 KiB
C
// Adapts the owned Intel addon's team discovery messages to successor events.
|
|
// Core already owns the local phase briefing; this never hides or replaces it.
|
|
modded class ERR_GameMode
|
|
{
|
|
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 bool m_ERRIntelFeedbackStopped;
|
|
protected int m_ERRIntelMessageSequence;
|
|
protected int m_ERRIntelReceivedSequence;
|
|
|
|
protected override void EOnInit(IEntity owner)
|
|
{
|
|
super.EOnInit(owner);
|
|
if (SCR_Global.IsEditMode() || !Replication.IsServer()) return;
|
|
OnLocationDiscovered().Insert(ERR_QueueDiscoveryFeedback);
|
|
OnTick().Insert(ERR_FlushDiscoveryFeedback);
|
|
OnStop().Insert(ERR_StopDiscoveryFeedback);
|
|
}
|
|
protected void ERR_QueueDiscoveryFeedback(ERR_LocationComponent location, int previous, int current)
|
|
{
|
|
if (!Replication.IsServer() || m_ERRIntelFeedbackStopped || !Active() || Phase() == ERR_Phase.PREPARING || !location) return;
|
|
// Initial prison/cache setup and automatic extraction disclosure are already
|
|
// explained by Core. A rough clue must never disclose a site's name or kind.
|
|
if (location.Kind() == ERR_LocationKind.PRISON || location.Kind() == ERR_LocationKind.EXTRACTION) return;
|
|
if (previous < 0 || current <= previous || current > 2 || current != location.Knowledge()) return;
|
|
int seen;
|
|
if (m_ERRIntelSeen.Find(location, seen) && current <= seen) return;
|
|
if (!m_ERRIntelSeen.Contains(location) && m_ERRIntelSeen.Count() >= 64) return;
|
|
m_ERRIntelSeen.Set(location, current);
|
|
if (m_ERRIntelPending.IsEmpty())
|
|
m_ERRIntelMessageAt = Math.Max(m_ERRIntelMessageAt, GetWorld().GetWorldTime() + 1500);
|
|
// Several folders recovered in one inventory scan become one final update.
|
|
m_ERRIntelPending.Set(location, current);
|
|
}
|
|
protected void ERR_FlushDiscoveryFeedback(float now)
|
|
{
|
|
if (!Replication.IsServer() || m_ERRIntelFeedbackStopped || !Active() || m_ERRIntelPending.IsEmpty() || now < m_ERRIntelMessageAt) return;
|
|
int identified;
|
|
int rough;
|
|
string label;
|
|
foreach (ERR_LocationComponent location, int knowledge : m_ERRIntelPending)
|
|
{
|
|
if (!location) continue;
|
|
if (knowledge == 2)
|
|
{
|
|
identified++;
|
|
label = location.Label();
|
|
}
|
|
else rough++;
|
|
}
|
|
m_ERRIntelPending.Clear();
|
|
m_ERRIntelMessageAt = now + 5000;
|
|
string message = ERR_IntelDiscoveryText.Message(identified, rough, label);
|
|
if (message.IsEmpty()) return;
|
|
// The listen host and remote recipients share the same per-round sequence.
|
|
// Local delivery is explicit and cannot duplicate a transport callback.
|
|
m_ERRIntelMessageSequence++;
|
|
ERR_ReceiveDiscoveryFeedback(m_ERRIntelMessageSequence, message);
|
|
Rpc(ERR_ReceiveDiscoveryFeedback, m_ERRIntelMessageSequence, message);
|
|
}
|
|
[RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]
|
|
protected void ERR_ReceiveDiscoveryFeedback(int sequence, string message)
|
|
{
|
|
if (!GetGame() || this != ERR_GameMode.Get() || m_ERRIntelFeedbackStopped || !Active() || !GetGame().GetPlayerController() || SCR_Global.IsEditMode() || message.IsEmpty() || sequence <= m_ERRIntelReceivedSequence) return;
|
|
m_ERRIntelReceivedSequence = sequence;
|
|
SCR_ChatComponent.RadioProtocolMessage(message);
|
|
}
|
|
protected void ERR_StopDiscoveryFeedback()
|
|
{
|
|
m_ERRIntelFeedbackStopped = true;
|
|
m_ERRIntelPending.Clear();
|
|
m_ERRIntelSeen.Clear();
|
|
m_ERRIntelMessageAt = 0;
|
|
OnLocationDiscovered().Remove(ERR_QueueDiscoveryFeedback);
|
|
OnTick().Remove(ERR_FlushDiscoveryFeedback);
|
|
}
|
|
}
|
|
|
|
class ERR_IntelDiscoveryText
|
|
{
|
|
static string Message(int identified, int rough, string label)
|
|
{
|
|
if (identified + rough == 0) return "";
|
|
if (identified == 0 && rough == 1) return "A new 500 m search area is marked on your field map. Recover another folder to identify the location.";
|
|
if (identified == 1 && rough == 0)
|
|
{
|
|
if (label.IsEmpty()) label = "A location";
|
|
return label + " identified. Check your field map.";
|
|
}
|
|
return string.Format("Field map updated: %1 identified locations and %2 search areas. Open a carried map to review them.", identified, rough);
|
|
}
|
|
}
|