795 lines
23 KiB
Ucode
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
|
||
|
}
|