/** * Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. */ class KAsset extends Actor native(Physics) nativereplication ClassGroup(Physics) placeable; var() const editconst SkeletalMeshComponent SkeletalMeshComponent; var() bool bDamageAppliesImpulse; var() bool bWakeOnLevelStart; /** Whether this KAsset should block Pawns. */ var() bool bBlockPawns; /** Used to replicate mesh to clients */ var repnotify transient SkeletalMesh ReplicatedMesh; /** Used to replicate physics asset to clients */ var repnotify transient PhysicsAsset ReplicatedPhysAsset; replication { if ( Role == ROLE_Authority) ReplicatedMesh, ReplicatedPhysAsset; } cpptext { public: // AActor interface. virtual INT* GetOptimizedRepList(BYTE* InDefault, FPropertyRetirement* Retire, INT* Ptr, UPackageMap* Map, UActorChannel* Channel); /** * Function that gets called from within Map_Check to allow this actor to check itself * for any potential errors and register them with map check dialog. */ #if WITH_EDITOR virtual void CheckForErrors(); #endif UBOOL ShouldTrace(UPrimitiveComponent* Primitive, AActor *SourceActor, DWORD TraceFlags); UBOOL IgnoreBlockingBy(const AActor* Other) const; } simulated event PostBeginPlay() { Super.PostBeginPlay(); if (bWakeOnLevelStart) { SkeletalMeshComponent.WakeRigidBody(); } ReplicatedMesh = SkeletalMeshComponent.SkeletalMesh; ReplicatedPhysAsset = SkeletalMeshComponent.PhysicsAsset; `if(`__TW_PERFORMANCE_) // Added forceskel update to allow us to use bUpdateSkelWhenNotRendered if ( !SkeletalMeshComponent.bUpdateSkelWhenNotRendered ) { SkeletalMeshComponent.ForceSkelUpdate(); } `endif } /** Sets the new mesh and physics asset, along with the replicated properties for clients. */ final function SetMeshAndPhysAsset(SkeletalMesh NewMesh, PhysicsAsset NewPhysAsset) { SkeletalMeshComponent.SetSkeletalMesh(NewMesh); ReplicatedMesh = NewMesh; SkeletalMeshComponent.SetPhysicsAsset(NewPhysAsset); ReplicatedPhysAsset = NewPhysAsset; } simulated event ReplicatedEvent( name VarName ) { if (VarName == 'ReplicatedMesh') { SkeletalMeshComponent.SetSkeletalMesh(ReplicatedMesh); } else if(VarName == 'ReplicatedPhysAsset') { SkeletalMeshComponent.SetPhysicsAsset(ReplicatedPhysAsset); } } /** * Default behaviour when shot is to apply an impulse and kick the KActor. */ simulated event TakeDamage(int Damage, Controller EventInstigator, vector HitLocation, vector Momentum, class DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser) { local vector ApplyImpulse; // call Actor's version to handle any SeqEvent_TakeDamage for scripting Super.TakeDamage(Damage, EventInstigator, HitLocation, Momentum, DamageType, HitInfo, DamageCauser); if ( bDamageAppliesImpulse && damageType.default.KDamageImpulse > 0 ) { if ( VSize(momentum) < 0.001 ) { `Log("Zero momentum to KActor.TakeDamage"); return; } // Make sure we have a valid TraceHitInfo with our SkeletalMesh // we need a bone to apply proper impulse CheckHitInfo( HitInfo, SkeletalMeshComponent, Normal(Momentum), hitlocation ); ApplyImpulse = Normal(momentum) * damageType.default.KDamageImpulse; if ( HitInfo.HitComponent != None ) { HitInfo.HitComponent.AddImpulse(ApplyImpulse, HitLocation, HitInfo.BoneName); } } } /** * Take Radius Damage * * @param InstigatedBy, instigator of the damage * @param Base Damage * @param Damage Radius (from Origin) * @param DamageType class * @param Momentum (float) * @param HurtOrigin, origin of the damage radius. * @param DamageCauser the Actor that directly caused the damage (i.e. the Projectile that exploded, the Weapon that fired, etc) */ simulated function TakeRadiusDamage ( Controller InstigatedBy, float BaseDamage, float DamageRadius, class DamageType, float Momentum, vector HurtOrigin, bool bFullDamage, Actor DamageCauser, optional float DamageFalloffExponent=1.f, optional bool bAdjustRadiusDamage=true ) { if ( bDamageAppliesImpulse && damageType.default.RadialDamageImpulse > 0 && (Role == ROLE_Authority) ) { CollisionComponent.AddRadialImpulse(HurtOrigin, DamageRadius, damageType.default.RadialDamageImpulse, RIF_Linear, damageType.default.bRadialDamageVelChange); } } /** If this KAsset receives a Toggle ON event from Kismet, wake the physics up. */ simulated function OnToggle(SeqAct_Toggle action) { if(action.InputLinks[0].bHasImpulse) { SkeletalMeshComponent.WakeRigidBody(); } } simulated function OnTeleport(SeqAct_Teleport InAction) { local Actor DestActor; DestActor = Actor(SeqVar_Object(InAction.VariableLinks[1].LinkedVariables[0]).GetObjectValue()); if (DestActor != None) { SkeletalMeshComponent.SetRBPosition(DestActor.Location); } else { InAction.ScriptLog("No Destination for" @ InAction @ "on" @ self); } } /** Performs actual attachment. Can be subclassed for class specific behaviors. */ function DoKismetAttachment( Actor Attachment, SeqAct_AttachToActor Action ) { Attachment.SetBase( Self,, SkeletalMeshComponent, Action.BoneName ); } defaultproperties { TickGroup=TG_PostAsyncWork Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment End Object `if(`__TW_LIGHTING_MODIFICATIONS_) // Don't add to components list `else Components.Add(MyLightEnvironment) `endif Begin Object Class=SkeletalMeshComponent Name=KAssetSkelMeshComponent CollideActors=true BlockActors=true BlockZeroExtent=true BlockNonZeroExtent=false BlockRigidBody=true bHasPhysicsAssetInstance=true bUpdateKinematicBonesFromAnimation=false bUseTickOptimization=false PhysicsWeight=1.0 RBChannel=RBCC_GameplayPhysics RBCollideWithChannels=(Default=TRUE,BlockingVolume=TRUE,GameplayPhysics=TRUE,EffectPhysics=TRUE) LightEnvironment=MyLightEnvironment bSkipAllUpdateWhenPhysicsAsleep=TRUE bBlockFootPlacement=false End Object CollisionComponent=KAssetSkelMeshComponent SkeletalMeshComponent=KAssetSkelMeshComponent Components.Add(KAssetSkelMeshComponent) SupportedEvents.Add(class'SeqEvent_ConstraintBroken') SupportedEvents.Add(class'SeqEvent_RigidBodyCollision') bDamageAppliesImpulse=true bNetInitialRotation=true Physics=PHYS_RigidBody bEdShouldSnap=true bStatic=false bCollideActors=true bBlockActors=true bWorldGeometry=false bCollideWorld=false bProjTarget=true bNoDelete=true bAlwaysRelevant=true bSkipActorPropertyReplication=false bUpdateSimulatedPosition=true bReplicateMovement=true `if(`__TW_NETWORKING_) // SimProxy makes sense in KAssetSpawnable, but not in KAsset. TakeDamage is // marked simulated and only applies local client damage impulses. RemoteRole=ROLE_None `else RemoteRole=ROLE_SimulatedProxy `endif bReplicateRigidBodyLocation=FALSE }