Page MenuHomeFeedback Tracker

DeadPlayerCrate.c

File Metadata

Author
Smola
Created
Mon, Jan 13, 1:29 AM

DeadPlayerCrate.c

class DeadPlayerCrate_Base extends Container_Base
{
protected bool m_FliesDisabled;
static ref array<EntityAI> clonedObjects = new array<EntityAI>;
protected int m_FliesIndex = -1;
protected ref EffectParticle m_FliesEffect;
protected ref EffectSound m_SoundFliesEffect;
protected PlayerBase m_Player;
void DeadPlayerCrate_Base()
{
RegisterNetSyncVariableBool( "m_FliesDisabled" );
if ( GetGame().IsServer() || !GetGame().IsMultiplayer() )
{
SetAllowDamage( false );
if ( GetGame().ServerConfigGetInt( "TransferItemsToCrateWhenDying_FliesDisabled" ) )
{
m_FliesDisabled = true;
}
}
else
{
ConditionalDeferredDecayEffect();
}
clonedObjects.Clear();
}
override void AfterStoreLoad()
{
super.AfterStoreLoad();
// Set crate to ruined after current remaining lifetime has passed so interacting with it no longer resets lifetime
SetRuinedLater( GetLifetime(), GetType() + "::AfterStoreLoad position=" + GetPosition() );
}
override void OnVariablesSynchronized()
{
super.OnVariablesSynchronized();
ConditionalDeferredDecayEffect();
}
override void EEHealthLevelChanged( int oldLevel, int newLevel, string zone )
{
super.EEHealthLevelChanged( oldLevel, newLevel, zone );
if ( newLevel == GameConstants.STATE_RUINED && !GetGame().IsServer() )
StopFlies();
}
override void EEDelete( EntityAI parent )
{
StopFlies();
}
void StopFlies()
{
if ( m_FliesEffect )
m_FliesEffect.Stop();
if ( m_SoundFliesEffect )
StopSoundSet( m_SoundFliesEffect );
}
void ConditionalDeferredDecayEffect()
{
if ( !m_FliesDisabled )
{
// Add client-side flies effect after delay
GetGame().GetCallQueue( CALL_CATEGORY_SYSTEM ).CallLater( SetDecayEffect, 30000, false );
}
}
void SetDecayEffect()
{
if ( IsDamageDestroyed() )
return;
if ( !m_FliesEffect )
{
m_FliesEffect = new EffSwarmingFlies();
}
if ( m_FliesEffect && !SEffectManager.IsEffectExist( m_FliesIndex ) )
{
m_FliesEffect.SetDecalOwner( this );
m_FliesIndex = SEffectManager.PlayOnObject( m_FliesEffect, this, "0 0.25 0" );
Particle p = m_FliesEffect.GetParticle();
AddChild( p, -1 );
if ( !m_SoundFliesEffect )
{
PlaySoundSetLoop( m_SoundFliesEffect, "Flies_SoundSet", 1.0, 1.0 );
}
}
}
override bool CanPutInCargo( EntityAI parent )
{
return false;
}
override bool CanPutIntoHands( EntityAI parent )
{
return false;
}
override bool CanReceiveAttachment( EntityAI attachment, int slotId )
{
if (GetGame().IsClient() || !GetGame().IsMultiplayer())
{
string slot_name = InventorySlots.GetSlotName(slotId);
switch (slot_name)
{
case "Case":
return false;
}
}
return !IsRuined();
}
override bool CanLoadAttachment( EntityAI attachment )
{
return true;
}
override bool CanDisplayAttachmentSlot( int slot_id )
{
if ( InventorySlots.GetSlotDisplayName( slot_id ) == string.Empty )
return false;
string slot_name = InventorySlots.GetSlotName(slot_id);
switch (slot_name)
{
case "Case":
return false;
}
return super.CanDisplayAttachmentSlot( slot_id );
}
override void EEItemDetached( EntityAI item, string slot_name )
{
super.EEItemDetached( item, slot_name );
if ( ( GetGame().IsServer() || !GetGame().IsMultiplayer() ) && GetHealth() )
{
GetGame().GetCallQueue( CALL_CATEGORY_SYSTEM ).CallLater( SetRuinedIfEmpty, 100, false );
}
if ( m_Player )
{
EntityAI attachment = m_Player.FindAttachmentBySlotName( slot_name );
if ( attachment )
attachment.Delete();
}
}
override void EEItemAttached(EntityAI item, string slot_name)
{
super.EEItemAttached(item, slot_name);
if (GetGame().IsServer() || !GetGame().IsMultiplayer())
{
switch (slot_name)
{
case "Case":
if (item)
item.DeleteSafe();
break;
}
}
}
void SetRuined()
{
SetAllowDamage( true );
SetHealth( 0 );
}
void SetRuinedIfEmpty()
{
if (GetInventory().AttachmentCount() == 0)
{
GetGame().GetCallQueue( CALL_CATEGORY_SYSTEM ).Remove( SetRuined );
SetRuined();
}
}
void SetRuinedLater( float lifetime, string caller )
{
GetGame().GetCallQueue( CALL_CATEGORY_SYSTEM ).CallLater( SetRuined, lifetime * 1000, false );
}
static float GetItemScore( ItemBase item, string indent = "" )
{
float score;
float size = 1;
PlayerBase player = PlayerBase.Cast( item.GetHierarchyParent() );
if ( player && item == player.GetItemInHands() && item.GetHealth() )
{
// Item in hands will be dropped if not ruined, so it doesn't count
}
else if ( item.IsWeapon() )
{
if ( item.ConfigIsExisting( "itemSize" ) )
{
// from ItemBase.c
vector v_size = item.ConfigGetVector( "itemSize" );
float v_size_x = v_size[0];
float v_size_y = v_size[1];
size = v_size_x * v_size_y;
}
if ( size < 6 )
{
// Probably using DinkyItems or such
size *= 4;
}
score = size + item.GetInventory().GetAttachmentSlotsCount();
score *= 3; // Multiplier applied to weapons score
}
else if ( item.GetInventory().GetCargo() )
{
score = item.GetInventory().GetCargo().GetWidth() * item.GetInventory().GetCargo().GetHeight();
}
else
{
score = 5;
}
return score;
}
static float GetInventoryScore( EntityAI parent, inout int items_count, string indent = "" )
{
float score;
array< EntityAI > inventory = new array< EntityAI >;
parent.GetInventory().EnumerateInventory( InventoryTraversalType.LEVELORDER, inventory );
for ( int i = 0; i < inventory.Count(); i++ )
{
ItemBase item = ItemBase.Cast( inventory[i] );
if ( item )
{
items_count++;
float item_score = GetItemScore( item, indent );
if ( item_score )
{
score += item_score;
score += GetInventoryScore( item, items_count, indent + " " );
}
}
}
return score;
}
void TransferAttachmentsFromOther( EntityAI other, vector ground, vector orientation )
{
// Dynamically transfer all attachments from other, drop any attachment that cannot be added to crate
array< EntityAI > inventory = new array< EntityAI >;
other.GetInventory().EnumerateInventory( InventoryTraversalType.LEVELORDER, inventory );
for (int i = 0; i < inventory.Count(); i++)
{
EntityAI item = inventory[i];
if (item)
{
InventoryLocation src = new InventoryLocation;
if (item.GetInventory().GetCurrentInventoryLocation(src))
{
float health;
if (GetGame().IsServer())
{
health = item.GetHealth();
if (!health)
{
item.SetHealth(item.GetMaxHealth());
}
}
bool ret = false;
if (GetInventory().CanAddAttachment(item) && (src.GetType() != InventoryLocationType.HANDS || !health))
{
InventoryLocation dst = new InventoryLocation;
if (src.GetType() == InventoryLocationType.HANDS)
{
GetInventory().FindFreeLocationFor(item, FindInventoryLocationType.ATTACHMENT, dst);
}
else
{
int slot_id = src.GetSlot();
dst.SetAttachment(this, item, slot_id);
}
if (GetGame().IsMultiplayer())
{
ret = other.GetInventory().TakeToDst(InventoryMode.SERVER, src, dst);
}
else
{
ret = other.GetInventory().TakeToDst(InventoryMode.LOCAL, src, dst);
}
if (!ret)
{
// Handle transfer failure
}
}
if (!ret)
{
if (GetGame().IsMultiplayer())
{
ret = other.GetInventory().DropEntity(InventoryMode.SERVER, other, item);
}
else
{
ret = other.GetInventory().DropEntity(InventoryMode.LOCAL, other, item);
}
if (!ret)
{
// Handle drop failure
}
else
{
item.SetPosition(ground);
item.SetOrientation(orientation);
}
}
if (GetGame().IsServer() && !health)
{
item.SetHealth(0);
}
}
else
{
// Handle error when source location is NULL
}
}
}
SetSynchDirty();
}
static void CloneAttachments( EntityAI src, EntityAI dst, bool recursively = true )
{
EntityAI cSrc;
InventoryLocation cLocation();
InventoryLocation dLocation();
for (int i = 0; i < src.GetInventory().AttachmentCount(); i++)
{
cSrc = src.GetInventory().GetAttachmentFromIndex(i);
cSrc.GetInventory().GetCurrentInventoryLocation(cLocation);
dLocation.SetAttachment(dst, null, cLocation.GetSlot());
Clone(cSrc, recursively, dLocation);
}
}
static EntityAI Clone(EntityAI src, bool recursively = true, InventoryLocation location = null)
{
int i;
//! 1) create entity
EntityAI dst;
switch (location.GetType())
{
case InventoryLocationType.GROUND:
dst = GameInventory.LocationCreateEntity(location, src.GetType(), ECE_PLACE_ON_SURFACE, RF_DEFAULT);
break;
case InventoryLocationType.ATTACHMENT:
case InventoryLocationType.HANDS:
dst = GameInventory.LocationCreateEntity(location, src.GetType(), ECE_IN_INVENTORY, RF_DEFAULT);
break;
case InventoryLocationType.CARGO:
case InventoryLocationType.PROXYCARGO:
dst = location.GetParent().GetInventory().CreateEntityInCargoEx(src.GetType(), location.GetIdx(), location.GetRow(), location.GetCol(), location.GetFlip()); //! Only way to get flip correct
break;
default:
return null;
}
if (!dst)
{
if (!Class.CastTo(dst, GetGame().CreateObjectEx(src.GetType(), src.GetPosition(), ECE_PLACE_ON_SURFACE, RF_DEFAULT)))
{
return null;
}
}
//! @note order of operations matters! DO NOT CHANGE!
//! 2) attachments
if (recursively)
{
CloneAttachments(src, dst);
CargoBase cargo = src.GetInventory().GetCargo();
if (cargo)
{
EntityAI cSrc;
InventoryLocation cLocation();
InventoryLocation dLocation();
for (i = 0; i < cargo.GetItemCount(); i++)
{
cSrc = cargo.GetItem(i);
if (clonedObjects.Find(cSrc) != -1)
{
continue;
}
cSrc.GetInventory().GetCurrentInventoryLocation(cLocation);
dLocation.SetCargo(dst, null, cLocation.GetIdx(), cLocation.GetRow(), cLocation.GetCol(), cLocation.GetFlip());
clonedObjects.Insert(cSrc);
Clone(cSrc, recursively, dLocation);
}
}
}
//! 3) special treatment for weapons
Weapon_Base srcWeapon;
Weapon_Base dstWeapon;
if (Class.CastTo(srcWeapon, src) && Class.CastTo(dstWeapon, dst))
{
float ammoDamage;
string ammoTypeName;
for (int mi = 0; mi < srcWeapon.GetMuzzleCount(); ++mi)
{
if (!srcWeapon.IsChamberEmpty(mi))
{
if (srcWeapon.GetCartridgeInfo(mi, ammoDamage, ammoTypeName))
{
dstWeapon.PushCartridgeToChamber(mi, ammoDamage, ammoTypeName);
}
}
for (int ci = 0; ci < srcWeapon.GetInternalMagazineCartridgeCount(mi); ++ci)
{
if (srcWeapon.GetInternalMagazineCartridgeInfo(mi, ci, ammoDamage, ammoTypeName))
{
dstWeapon.PushCartridgeToInternalMagazine(mi, ammoDamage, ammoTypeName);
}
}
}
}
//! 4) storesave/storeload
ScriptReadWriteContext ctx = new ScriptReadWriteContext;
src.OnStoreSave(ctx.GetWriteContext());
dst.OnStoreLoad(ctx.GetReadContext(), GetGame().SaveVersion());
//! 5) special treatment for mags
Magazine srcMag;
Magazine dstMag;
if (Class.CastTo(srcMag, src) && Class.CastTo(dstMag, dst))
{
float damage; //! @note damage is the damage of the cartridge itself (0..1), NOT the damage it inflicts!
string cartTypeName;
dstMag.ServerSetAmmoCount(0);
for (i = 0; i < srcMag.GetAmmoCount(); i++)
{
srcMag.GetCartridgeAtIndex(i, damage, cartTypeName);
dstMag.ServerStoreCartridge(damage, cartTypeName);
}
}
//! 6) ...
//! 7) global health and damage zones
TStringArray dmgZones();
src.GetDamageZones(dmgZones);
dst.SetHealth(src.GetHealth());
foreach (string dmgZone: dmgZones)
{
dst.SetHealth(dmgZone, "Health", src.GetHealth(dmgZone, "Health"));
}
dst.AfterStoreLoad();
GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(dst.EEOnAfterLoad); //! Make sure EEOnAfterLoad gets called AFTER whole hierarchy has loaded
return dst;
}
void SetPlayer( PlayerBase player )
{
m_Player = player;
}
}

Event Timeline