//============================================================================= // KFMGA_DoshTossPit //============================================================================= // Actor that handles tracking of the dosh toss minigame. Paired with // a TargetGame actor to handle the core game win/lose condition. //============================================================================= // Killing Floor 2 // Copyright (C) 2015 Tripwire Interactive LLC // - Dan Weiss //============================================================================= class KFMGA_DoshTossPit extends KFMGA_Target; /** how much dosh to return to the player per-bucket */ var() const int DoshReward; /** how long to blend to closed after a bucket is hit */ var() float TimeToBlend; var AnimNodeBlendPerBone CachedBlendNode; /** PSC for internal bucket glow - Always on, gets color shifted between states */ var() ParticleSystemComponent InnerGlowPSC; /** PSC for external bucket glow - Only on when the box is inactive */ var() ParticleSystemComponent OuterGlowPSC; /** Glow Colors */ var() Color ActiveGlowColor; var() Color InactiveGlowColor; /** These don't take damage */ simulated event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser) {} simulated event Tick(float DeltaTime) { super.Tick(DeltaTime); if (TimeToBlend > 0.f) { TimeToBlend -= DeltaTime; SetBucketLidState(TimeToBlend > 0.f ? 1.f - (TimeToBlend / default.TimeToBlend) : 1.f); } } simulated event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal) { if (KFDroppedPickup_Cash(Other) != none && KFDroppedPickup_Cash(Other).CollisionComponent.RigidBodyIsAwake()) { KFDroppedPickup_Cash(Other).NotifyMinigameHit(self); } } /** We don't actually care about damage here. For client-authority purposes I'm routing a server call through here to handle * the actual hit tracking. I just care that DamageCauser is a cash object. Because of this, we also don't care about * non-authority damage calls, as that is handled by touch events against cash objects. */ function ValidHit(Controller EventInstigator, Actor HitActor) { DoshHit(KFDroppedPickup_Cash(HitActor)); } /** Handle cleanup after hit occurs */ function DoshHit(KFDroppedPickup_Cash Cash) { local KFPlayerController KFPC; local KFPlayerReplicationInfo KFPRI; if (Cash != none && IsAlive()) { NumHits--; if (NumHits <= 0 && SpawnerOwner != none) { SpawnerOwner.TargetHit(self, Cash.Instigator.Controller); PlayDeath(); //Reward tossing player KFPC = KFPlayerController(Cash.Owner); if (KFPC != none) { KFPRI = KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo); if (KFPRI != none) { KFPRI.AddDosh(DoshReward); } } } } //Cleanup cash now anyway. It's out of reach of the player permanently Cash.Destroy(); } simulated event Reset() { local Vector RelativeOffset; SetBucketLidState(0.f); if (WorldInfo.NetMode != NM_DedicatedServer) { OuterGlowPSC.SetHidden(true); OuterGlowPSC.DeactivateSystem(); InnerGlowPSC.SetHidden(true); InnerGlowPSC.DeactivateSystem(); InnerGlowPSC.SetColorParameter('Glow_Color', InactiveGlowColor); } super.Reset(); //Safe offset w/ attach bone directly in the base of the geo RelativeOffset.Z = CollisionCylinder.CollisionHeight + 10; SetRelativeLocation(RelativeOffset); TimeToBlend = 0.0f; } /** Note: This will only work w/ animtree support enabled. Without an animtree, this will silently fail. */ simulated function SetBucketLidState(float BlendAmount) { local name TopName; local KFMG_RiggedTargetGame TargetGame; local int BoneIndex; TargetGame = KFMG_RiggedTargetGame(SpawnerOwner); if (AttachBoneName != 'none' && TargetGame != none) { if (CachedBlendNode == none) { CachedBlendNode = AnimNodeBlendPerBone(TargetGame.MinigameRig.SkeletalMeshComponent.FindAnimNode('BucketBlend')); } if (CachedBlendNode != none) { //This name is going to be of the form Bucketxx. We also want to make sure to control BucketTopxx TopName = name("BucketTop" $ Right(string(AttachBoneName), 2)); BoneIndex = TargetGame.MinigameRig.SkeletalMeshComponent.MatchRefBone(TopName); if (BoneIndex != INDEX_NONE) { CachedBlendNode.Child2PerBoneWeight[BoneIndex] = BlendAmount; } } } } simulated function PlayDeath() { super.PlayDeath(); TimeToBlend = default.TimeToBlend; if (WorldInfo.NetMode != NM_DedicatedServer) { OuterGlowPSC.SetHidden(false); OuterGlowPSC.ActivateSystem(true); InnerGlowPSC.SetHidden(false); InnerGlowPSC.SetColorParameter('Glow_Color', InactiveGlowColor); } } simulated event SetActive() { bActiveTarget = true; if (WorldInfo.NetMode != NM_DedicatedServer) { OuterGlowPSC.SetHidden(true); InnerGlowPSC.SetHidden(false); InnerGlowPSC.ActivateSystem(true); InnerGlowPSC.SetColorParameter('Glow_Color', ActiveGlowColor); } } simulated event SetInactive() { bActiveTarget = false; } simulated event Finalize() { if (WorldInfo.NetMode != NM_DedicatedServer) { OuterGlowPSC.SetHidden(true); OuterGlowPSC.DeactivateSystem(); InnerGlowPSC.SetHidden(true); InnerGlowPSC.DeactivateSystem(); InnerGlowPSC.SetColorParameter('Glow_Color', InactiveGlowColor); } } defaultproperties { Begin Object Name=Cylinder0 CollisionHeight = 30.0 CollisionRadius = 30.0 End Object AcceptedDamageTypes.Empty NumHits = 1 DoshReward = 50 TimeToBlend = 0.5f Begin Object Class=ParticleSystemComponent Name=InnerGlow0 HiddenGame=true End Object Components.Add(InnerGlow0) InnerGlowPSC=InnerGlow0 Begin Object Class=ParticleSystemComponent Name=OuterGlow0 HiddenGame=true End Object Components.Add(OuterGlow0) OuterGlowPSC=OuterGlow0 ActiveGlowColor=(R=50,G=0,B=0,A=255) InactiveGlowColor=(R=0,G=50,B=0,A=255) }