1
0
KF2-Dev-Scripts/Engine/Classes/CoverReplicator.uc
2020-12-13 18:01:13 +03:00

795 lines
23 KiB
Ucode

/**
*
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
/** this handles replicating cover changes to a client
* can't use variable replication on the CoverLinks because the slots list is a dynamic array
* also, that could potentially be a whole lot of channels if LDs mess with a lot of cover via Kismet, so this is more efficient
*/
class CoverReplicator extends ReplicationInfo;
struct ManualCoverTypeInfo
{
var byte SlotIndex;
var ECoverType ManualCoverType;
};
struct CoverReplicationInfo
{
/** CoverLink that was changed */
var CoverLink Link;
/** indices of slots that were enabled */
var array<byte> SlotsEnabled;
/** indices of slots that were disabled */
var array<byte> SlotsDisabled;
/** indices of slots that were adjusted */
var array<byte> SlotsAdjusted;
/** slots that have had cover type manually set */
var array<ManualCoverTypeInfo> SlotsCoverTypeChanged;
};
var array<CoverReplicationInfo> CoverReplicationData;
/** removes entries that are no longer valid (i.e. the CoverLink has been streamed out) */
function PurgeOldEntries()
{
local int i;
for (i = 0; i < CoverReplicationData.length; i++)
{
if (CoverReplicationData[i].Link == None)
{
CoverReplicationData.Remove(i--, 1);
}
}
}
/** copies and starts replicating already changed cover info */
function ReplicateInitialCoverInfo()
{
local CoverReplicator CoverReplicatorBase;
CoverReplicatorBase = WorldInfo.Game.GetCoverReplicator();
// clean out old entries first
CoverReplicatorBase.PurgeOldEntries();
// copy over data
CoverReplicationData = CoverReplicatorBase.CoverReplicationData;
if (PlayerController(Owner) != None)
{
//@HACK: bSkipActorPropertyReplication prevents Owner from being replicated. Should fix that eventually, but for now, force it by RPC
ClientSetOwner(PlayerController(Owner));
// start replicating it out
ServerSendInitialCoverReplicationInfo(0);
}
}
//@HACK: bSkipActorPropertyReplication prevents Owner from being replicated. Should fix that eventually, but for now, force it by RPC
reliable client function ClientSetOwner(PlayerController PC)
{
SetOwner(PC);
}
/** sends info for one CoverReplicationData to the client */
reliable server function ServerSendInitialCoverReplicationInfo(int Index)
{
local byte SlotsArrayIndex,
NumSlotsEnabled, NumSlotsDisabled, NumSlotsAdjusted, NumCoverTypesChanged,
SlotsEnabled[8], SlotsDisabled[8], SlotsAdjusted[8];
local ManualCoverTypeInfo SlotsCoverTypeChanged[8];
local int i;
local bool bDone;
// verify there's no None entries as the client assumes that means the data must be resent
while (Index < CoverReplicationData.length && CoverReplicationData[Index].Link == None)
{
CoverReplicationData.Remove(Index, 1);
}
if (Index < CoverReplicationData.length)
{
SlotsArrayIndex = 0;
do
{
// figure out how many elements of each array to send
NumSlotsEnabled = Clamp(CoverReplicationData[Index].SlotsEnabled.length - SlotsArrayIndex, 0, 8);
NumSlotsDisabled = Clamp(CoverReplicationData[Index].SlotsDisabled.length - SlotsArrayIndex, 0, 8);
NumSlotsAdjusted = Clamp(CoverReplicationData[Index].SlotsAdjusted.length - SlotsArrayIndex, 0, 8);
NumCoverTypesChanged = Clamp(CoverReplicationData[Index].SlotsCoverTypeChanged.length - SlotsArrayIndex, 0, 8);
// if we're sending nothing, make sure we zero the array so the netcode doesn't send that parameter at all
if (NumSlotsEnabled == 0)
{
for (i = 0; i < 8; i++)
{
SlotsEnabled[i] = 0;
}
}
else
{
// compose the data to send
// we don't bother with elements after NumSlotsEnabled as the netcode will send them regardless
for (i = 0; i < NumSlotsEnabled; i++)
{
SlotsEnabled[i] = CoverReplicationData[Index].SlotsEnabled[SlotsArrayIndex + i];
}
}
// do the same for the other three arrays
if (NumSlotsDisabled == 0)
{
for (i = 0; i < 8; i++)
{
SlotsDisabled[i] = 0;
}
}
else
{
for (i = 0; i < NumSlotsDisabled; i++)
{
SlotsDisabled[i] = CoverReplicationData[Index].SlotsDisabled[SlotsArrayIndex + i];
}
}
if (NumSlotsAdjusted == 0)
{
for (i = 0; i < 8; i++)
{
SlotsAdjusted[i] = 0;
}
}
else
{
for (i = 0; i < NumSlotsAdjusted; i++)
{
SlotsAdjusted[i] = CoverReplicationData[Index].SlotsAdjusted[SlotsArrayIndex + i];
}
}
if (NumCoverTypesChanged == 0)
{
for (i = 0; i < 8; i++)
{
SlotsCoverTypeChanged[i].SlotIndex = 0;
SlotsCoverTypeChanged[i].ManualCoverType = CT_None;
}
}
else
{
for (i = 0; i < NumCoverTypesChanged; i++)
{
SlotsCoverTypeChanged[i] = CoverReplicationData[Index].SlotsCoverTypeChanged[SlotsArrayIndex + i];
}
}
// we're done if all of the arrays have 8 elements to send or less
bDone = ( CoverReplicationData[Index].SlotsEnabled.length - SlotsArrayIndex <= 8 &&
CoverReplicationData[Index].SlotsDisabled.length - SlotsArrayIndex <= 8 &&
CoverReplicationData[Index].SlotsAdjusted.length - SlotsArrayIndex <= 8 &&
CoverReplicationData[Index].SlotsCoverTypeChanged.length - SlotsArrayIndex <= 8 );
// send out the data
ClientReceiveInitialCoverReplicationInfo( Index, CoverReplicationData[Index].Link, CoverReplicationData[Index].Link.bDisabled,
NumSlotsEnabled, SlotsEnabled,
NumSlotsDisabled, SlotsDisabled,
NumSlotsAdjusted, SlotsAdjusted,
NumCoverTypesChanged, SlotsCoverTypeChanged,
bDone );
// increment base array index
SlotsArrayIndex += 8;
} until (bDone);
}
}
/** replicates the information for one CoverReplicationData entry
* bDone indicates whether or not there is more data coming for this entry (because some arrays have more than 8 elements)
*/
reliable client function ClientReceiveInitialCoverReplicationInfo( int Index, CoverLink Link, bool bLinkDisabled,
byte NumSlotsEnabled, byte SlotsEnabled[8],
byte NumSlotsDisabled, byte SlotsDisabled[8],
byte NumSlotsAdjusted, byte SlotsAdjusted[8],
byte NumCoverTypesChanged, ManualCoverTypeInfo SlotsCoverTypeChanged[8],
bool bDone )
{
local int i;
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
if (bDone)
{
ServerSendInitialCoverReplicationInfo(Index);
}
}
else
{
// process the data
Link.bDisabled = bLinkDisabled;
for (i = 0; i < NumSlotsEnabled; i++)
{
Link.SetSlotEnabled(SlotsEnabled[i], true);
}
for (i = 0; i < NumSlotsDisabled; i++)
{
Link.SetSlotEnabled(SlotsDisabled[i], false);
}
for (i = 0; i < NumSlotsAdjusted; i++)
{
if (Link.AutoAdjustSlot(SlotsAdjusted[i], false) && Link.Slots[SlotsAdjusted[i]].SlotOwner != None && Link.Slots[SlotsAdjusted[i]].SlotOwner.Controller != None)
{
Link.Slots[SlotsAdjusted[i]].SlotOwner.Controller.NotifyCoverAdjusted();
}
}
for (i = 0; i < NumCoverTypesChanged; i++)
{
Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].CoverType = SlotsCoverTypeChanged[i].ManualCoverType;
if (Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner != None && Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner.Controller != None)
{
Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner.Controller.NotifyCoverAdjusted();
}
}
// ask for next
if (bDone)
{
ServerSendInitialCoverReplicationInfo(Index + 1);
}
}
}
/** notification that slots on the given CoverLink have been enabled */
function NotifyEnabledSlots(CoverLink Link, const out array<int> SlotIndices)
{
local int Index, SlotIndex;
local int i;
local PlayerController PC;
Index = CoverReplicationData.Find('Link', Link);
if (Index == INDEX_NONE)
{
Index = CoverReplicationData.length;
CoverReplicationData.length = CoverReplicationData.length + 1;
CoverReplicationData[Index].Link = Link;
for (i = 0; i < SlotIndices.length; i++)
{
CoverReplicationData[Index].SlotsEnabled[i] = SlotIndices[i];
}
}
else
{
for (i = 0; i < SlotIndices.length; i++)
{
// add to enabled list if not already there
SlotIndex = CoverReplicationData[Index].SlotsEnabled.Find(SlotIndices[i]);
if (SlotIndex == INDEX_NONE)
{
CoverReplicationData[Index].SlotsEnabled[CoverReplicationData[Index].SlotsEnabled.length] = SlotIndices[i];
}
// remove from disabled list, if necessary
SlotIndex = CoverReplicationData[Index].SlotsDisabled.Find(SlotIndices[i]);
if (SlotIndex != INDEX_NONE)
{
CoverReplicationData[Index].SlotsDisabled.Remove(SlotIndex, 1);
}
}
}
if (WorldInfo.Game.GetCoverReplicator() == self)
{
// we are the base info; inform players of the change now
foreach WorldInfo.AllControllers(class'PlayerController', PC)
{
if (PC.MyCoverReplicator == None)
{
PC.SpawnCoverReplicator();
}
else
{
PC.MyCoverReplicator.NotifyEnabledSlots(Link, SlotIndices);
}
}
}
if (PlayerController(Owner) != None)
{
// replicate the data for this action
ServerSendEnabledSlots(Index);
}
}
/** send just the enabled slots for the CoverLink at the given index */
reliable server function ServerSendEnabledSlots(int Index)
{
local int SlotsArrayIndex;
local byte NumSlotsEnabled, SlotsEnabled[8];
local int i;
local bool bDone;
if (CoverReplicationData[Index].Link != None)
{
SlotsArrayIndex = 0;
do
{
NumSlotsEnabled = Clamp(CoverReplicationData[Index].SlotsEnabled.length - SlotsArrayIndex, 0, 8);
// compose the data to send
// we don't bother with elements after NumSlotsEnabled as the netcode will send them regardless
for (i = 0; i < NumSlotsEnabled; i++)
{
SlotsEnabled[i] = CoverReplicationData[Index].SlotsEnabled[SlotsArrayIndex + i];
}
// we're done if the array has 8 elements to send or less
bDone = (CoverReplicationData[Index].SlotsEnabled.length - SlotsArrayIndex <= 8);
// send out the data
ClientReceiveEnabledSlots(Index, CoverReplicationData[Index].Link, NumSlotsEnabled, SlotsEnabled, bDone);
// increment base array index
SlotsArrayIndex += 8;
} until (bDone);
}
}
/** client receives just the enabled slots for the given CoverLink */
reliable client function ClientReceiveEnabledSlots(int Index, CoverLink Link, byte NumSlotsEnabled, byte SlotsEnabled[8], bool bDone)
{
local int i;
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
if (bDone)
{
ServerSendEnabledSlots(Index);
}
}
else
{
// process the data
for (i = 0; i < NumSlotsEnabled; i++)
{
Link.SetSlotEnabled(SlotsEnabled[i], true);
}
}
}
/** notification that the slots on the given CoverLink have been disabled */
function NotifyDisabledSlots(CoverLink Link, const out array<int> SlotIndices)
{
local int Index, SlotIndex;
local int i;
local PlayerController PC;
Index = CoverReplicationData.Find('Link', Link);
if (Index == INDEX_NONE)
{
Index = CoverReplicationData.length;
CoverReplicationData.length = CoverReplicationData.length + 1;
CoverReplicationData[Index].Link = Link;
for (i = 0; i < SlotIndices.length; i++)
{
CoverReplicationData[Index].SlotsDisabled[i] = SlotIndices[i];
}
}
else
{
for (i = 0; i < SlotIndices.length; i++)
{
// add to disabled list if not already there
SlotIndex = CoverReplicationData[Index].SlotsDisabled.Find(SlotIndices[i]);
if (SlotIndex == INDEX_NONE)
{
CoverReplicationData[Index].SlotsDisabled[CoverReplicationData[Index].SlotsDisabled.length] = SlotIndices[i];
}
// remove from enabled list, if necessary
SlotIndex = CoverReplicationData[Index].SlotsEnabled.Find(SlotIndices[i]);
if (SlotIndex != INDEX_NONE)
{
CoverReplicationData[Index].SlotsEnabled.Remove(SlotIndex, 1);
}
}
}
if (WorldInfo.Game.GetCoverReplicator() == self)
{
// we are the base info; inform players of the change now
foreach WorldInfo.AllControllers(class'PlayerController', PC)
{
if (PC.MyCoverReplicator == None)
{
PC.SpawnCoverReplicator();
}
else
{
PC.MyCoverReplicator.NotifyDisabledSlots(Link, SlotIndices);
}
}
}
if (PlayerController(Owner) != None)
{
// replicate the data for this action
ServerSendDisabledSlots(Index);
}
}
/** send just the disabled slots for the CoverLink at the given index */
reliable server function ServerSendDisabledSlots(int Index)
{
local int SlotsArrayIndex;
local byte NumSlotsDisabled, SlotsDisabled[8];
local int i;
local bool bDone;
if (CoverReplicationData[Index].Link != None)
{
SlotsArrayIndex = 0;
do
{
NumSlotsDisabled = Clamp(CoverReplicationData[Index].SlotsDisabled.length - SlotsArrayIndex, 0, 8);
// compose the data to send
// we don't bother with elements after NumSlotsDisabled as the netcode will send them regardless
for (i = 0; i < NumSlotsDisabled; i++)
{
SlotsDisabled[i] = CoverReplicationData[Index].SlotsDisabled[SlotsArrayIndex + i];
}
// we're done if the array has 8 elements to send or less
bDone = (CoverReplicationData[Index].SlotsDisabled.length - SlotsArrayIndex <= 8);
// send out the data
ClientReceiveDisabledSlots(Index, CoverReplicationData[Index].Link, NumSlotsDisabled, SlotsDisabled, bDone);
// increment base array index
SlotsArrayIndex += 8;
} until (bDone);
}
}
/** client receives just the disabled slots for the given CoverLink */
reliable client function ClientReceiveDisabledSlots(int Index, CoverLink Link, byte NumSlotsDisabled, byte SlotsDisabled[8], bool bDone)
{
local int i;
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
if (bDone)
{
ServerSendDisabledSlots(Index);
}
}
else
{
// process the data
for (i = 0; i < NumSlotsDisabled; i++)
{
Link.SetSlotEnabled(SlotsDisabled[i], false);
}
}
}
/** notification that the slots on the given CoverLink have been auto-adjusted */
function NotifyAutoAdjustSlots(CoverLink Link, const out array<int> SlotIndices)
{
local int Index, SlotIndex;
local int i;
local PlayerController PC;
Index = CoverReplicationData.Find('Link', Link);
if (Index == INDEX_NONE)
{
Index = CoverReplicationData.length;
CoverReplicationData.length = CoverReplicationData.length + 1;
CoverReplicationData[Index].Link = Link;
for (i = 0; i < SlotIndices.length; i++)
{
CoverReplicationData[Index].SlotsAdjusted[i] = SlotIndices[i];
}
}
else
{
for (i = 0; i < SlotIndices.length; i++)
{
// add to adjusted list if not already there
SlotIndex = CoverReplicationData[Index].SlotsAdjusted.Find(SlotIndices[i]);
if (SlotIndex == INDEX_NONE)
{
CoverReplicationData[Index].SlotsAdjusted[CoverReplicationData[Index].SlotsAdjusted.length] = SlotIndices[i];
}
// remove from manual list, if necessary
SlotIndex = CoverReplicationData[Index].SlotsCoverTypeChanged.Find('SlotIndex', SlotIndices[i]);
if (SlotIndex != INDEX_NONE)
{
CoverReplicationData[Index].SlotsCoverTypeChanged.Remove(SlotIndex, 1);
}
}
}
if (WorldInfo.Game.GetCoverReplicator() == self)
{
// we are the base info; inform players of the change now
foreach WorldInfo.AllControllers(class'PlayerController', PC)
{
if (PC.MyCoverReplicator == None)
{
PC.SpawnCoverReplicator();
}
else
{
PC.MyCoverReplicator.NotifyAutoAdjustSlots(Link, SlotIndices);
}
}
}
if (PlayerController(Owner) != None)
{
// replicate the data for this action
ServerSendAdjustedSlots(Index);
}
}
/** send just the auto-adjusted slots for the CoverLink at the given index */
reliable server function ServerSendAdjustedSlots(int Index)
{
local int SlotsArrayIndex;
local byte NumSlotsAdjusted, SlotsAdjusted[8];
local int i;
local bool bDone;
if (CoverReplicationData[Index].Link != None)
{
SlotsArrayIndex = 0;
do
{
NumSlotsAdjusted = Clamp(CoverReplicationData[Index].SlotsAdjusted.length - SlotsArrayIndex, 0, 8);
// compose the data to send
// we don't bother with elements after NumSlotsDisabled as the netcode will send them regardless
for (i = 0; i < NumSlotsAdjusted; i++)
{
SlotsAdjusted[i] = CoverReplicationData[Index].SlotsAdjusted[SlotsArrayIndex + i];
}
// we're done if the array has 8 elements to send or less
bDone = (CoverReplicationData[Index].SlotsAdjusted.length - SlotsArrayIndex <= 8);
// send out the data
ClientReceiveAdjustedSlots(Index, CoverReplicationData[Index].Link, NumSlotsAdjusted, SlotsAdjusted, bDone);
// increment base array index
SlotsArrayIndex += 8;
} until (bDone);
}
}
/** client receives just the auto-adjusted slots for the given CoverLink */
reliable client function ClientReceiveAdjustedSlots(int Index, CoverLink Link, byte NumSlotsAdjusted, byte SlotsAdjusted[8], bool bDone)
{
local int i;
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
if (bDone)
{
ServerSendAdjustedSlots(Index);
}
}
else
{
// process the data
for (i = 0; i < NumSlotsAdjusted; i++)
{
if (Link.AutoAdjustSlot(SlotsAdjusted[i], true) && Link.Slots[SlotsAdjusted[i]].SlotOwner != None && Link.Slots[SlotsAdjusted[i]].SlotOwner.Controller != None)
{
Link.Slots[SlotsAdjusted[i]].SlotOwner.Controller.NotifyCoverAdjusted();
}
}
}
}
/** notification that the slots on the given CoverLink have been manually adjusted */
function NotifySetManualCoverTypeForSlots(CoverLink Link, const out array<int> SlotIndices, ECoverType NewCoverType)
{
local int Index, SlotIndex;
local int i;
local PlayerController PC;
Index = CoverReplicationData.Find('Link', Link);
if (Index == INDEX_NONE)
{
Index = CoverReplicationData.length;
CoverReplicationData.length = CoverReplicationData.length + 1;
CoverReplicationData[Index].Link = Link;
CoverReplicationData[Index].SlotsCoverTypeChanged.length = SlotIndices.length;
for (i = 0; i < SlotIndices.length; i++)
{
CoverReplicationData[Index].SlotsCoverTypeChanged[i].SlotIndex = SlotIndices[i];
CoverReplicationData[Index].SlotsCoverTypeChanged[i].ManualCoverType = NewCoverType;
}
}
else
{
for (i = 0; i < SlotIndices.length; i++)
{
// add to adjusted list if not already there
SlotIndex = CoverReplicationData[Index].SlotsCoverTypeChanged.Find('SlotIndex', SlotIndices[i]);
if (SlotIndex == INDEX_NONE)
{
SlotIndex = CoverReplicationData[Index].SlotsCoverTypeChanged.length;
CoverReplicationData[Index].SlotsCoverTypeChanged.length = CoverReplicationData[Index].SlotsCoverTypeChanged.length + 1;
CoverReplicationData[Index].SlotsCoverTypeChanged[SlotIndex].SlotIndex = SlotIndices[i];
}
CoverReplicationData[Index].SlotsCoverTypeChanged[SlotIndex].ManualCoverType = NewCoverType;
// remove from auto list, if necessary
SlotIndex = CoverReplicationData[Index].SlotsAdjusted.Find(SlotIndices[i]);
if (SlotIndex != INDEX_NONE)
{
CoverReplicationData[Index].SlotsAdjusted.Remove(SlotIndex, 1);
}
}
}
if (WorldInfo.Game.GetCoverReplicator() == self)
{
// we are the base info; inform players of the change now
foreach WorldInfo.AllControllers(class'PlayerController', PC)
{
if (PC.MyCoverReplicator == None)
{
PC.SpawnCoverReplicator();
}
else
{
PC.MyCoverReplicator.NotifySetManualCoverTypeForSlots(Link, SlotIndices, NewCoverType);
}
}
}
if (PlayerController(Owner) != None)
{
// replicate the data for this action
ServerSendManualCoverTypeSlots(Index);
}
}
/** send just the manual adjusted slots for the CoverLink at the given index */
reliable server function ServerSendManualCoverTypeSlots(int Index)
{
local int SlotsArrayIndex;
local byte NumCoverTypesChanged;
local ManualCoverTypeInfo SlotsCoverTypeChanged[8];
local int i;
local bool bDone;
if (CoverReplicationData[Index].Link != None)
{
SlotsArrayIndex = 0;
do
{
NumCoverTypesChanged = Clamp(CoverReplicationData[Index].SlotsCoverTypeChanged.length - SlotsArrayIndex, 0, 8);
// compose the data to send
// we don't bother with elements after NumSlotsDisabled as the netcode will send them regardless
for (i = 0; i < NumCoverTypesChanged; i++)
{
SlotsCoverTypeChanged[i] = CoverReplicationData[Index].SlotsCoverTypeChanged[SlotsArrayIndex + i];
}
// we're done if the array has 8 elements to send or less
bDone = (CoverReplicationData[Index].SlotsCoverTypeChanged.length - SlotsArrayIndex <= 8);
// send out the data
ClientReceiveManualCoverTypeSlots(Index, CoverReplicationData[Index].Link, NumCoverTypesChanged, SlotsCoverTypeChanged, bDone);
// increment base array index
SlotsArrayIndex += 8;
} until (bDone);
}
}
/** client receives just the manual adjusted slots for the given CoverLink */
reliable client function ClientReceiveManualCoverTypeSlots( int Index, CoverLink Link, byte NumCoverTypesChanged,
ManualCoverTypeInfo SlotsCoverTypeChanged[8], bool bDone )
{
local int i;
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
if (bDone)
{
ServerSendManualCoverTypeSlots(Index);
}
}
else
{
// process the data
for (i = 0; i < NumCoverTypesChanged; i++)
{
Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].CoverType = SlotsCoverTypeChanged[i].ManualCoverType;
if (Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner != None && Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner.Controller != None)
{
Link.Slots[SlotsCoverTypeChanged[i].SlotIndex].SlotOwner.Controller.NotifyCoverAdjusted();
}
}
}
}
function NotifyLinkDisabledStateChange(CoverLink Link)
{
local int Index;
local PlayerController PC;
Index = CoverReplicationData.Find('Link', Link);
if (Index == INDEX_NONE)
{
Index = CoverReplicationData.length;
CoverReplicationData.length = CoverReplicationData.length + 1;
CoverReplicationData[Index].Link = Link;
}
if (WorldInfo.Game.GetCoverReplicator() == self)
{
// we are the base info; inform players of the change now
foreach WorldInfo.AllControllers(class'PlayerController', PC)
{
if (PC.MyCoverReplicator == None)
{
PC.SpawnCoverReplicator();
}
else
{
PC.MyCoverReplicator.NotifyLinkDisabledStateChange(Link);
}
}
}
if (PlayerController(Owner) != None)
{
// replicate the data for this action
ServerSendLinkDisabledState(Index);
}
}
reliable server function ServerSendLinkDisabledState(int Index)
{
if (CoverReplicationData[Index].Link != None)
{
ClientReceiveLinkDisabledState(Index, CoverReplicationData[Index].Link, CoverReplicationData[Index].Link.bDisabled);
}
}
reliable client function ClientReceiveLinkDisabledState(int Index, CoverLink Link, bool bLinkDisabled)
{
// if we received an invalid CoverLink, we might not have loaded that level yet, so ask for a resend
if (Link == None)
{
ServerSendLinkDisabledState(Index);
}
else
{
Link.bDisabled = bLinkDisabled;
}
}
defaultproperties
{
bOnlyRelevantToOwner=true
bAlwaysRelevant=false
bOnlyDirtyReplication=true
NetUpdateFrequency=0.1
}