Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class GVBreakable extends InterpActor
- DependsOn(GVEffectActor);
- // Static mesh for this state
- struct SBreakableState
- {
- var() StaticMesh StaticMesh; // Effects to create when entering this state
- var() array<sGVEffect> Effects; // When the breakable's health is below this, it will activate this state. This is a percentage representation of the health, thus keep values between 0.f and 1.f
- var() float HealthPercentage<UIMin=0|UIMax=1>; // When the breakable's health is below this, it will activate this state. This is the actual health, thus keep values between 0 and Health
- };
- // Health of the breakable
- var(GVBreakable) int Health;
- // Minimum damage that must be exceeded to cause damage to the breakable
- var(GVBreakable) float MinimumDamage;
- // Breakable states
- var(GVBreakable) array<SBreakableState> BreakableStates;
- // Hide if breakable is below zero health
- var(GVBreakable) bool HideWhenDead;
- // Disable collision if breakable is below zero health
- var(GVBreakable) bool DisableCollisionWhenDead;
- // Time delay, in seconds, between each state change
- var(GVBreakable) float StateChangeInterval;
- // Damage caused to other actors in the vicinity when the breakable dies
- var(GVBreakable) float DamageOnDeath;
- // Radius of the damage, use a value less than or equal to zero to disable
- var(GVBreakable) float DamageOnDeathRadius;
- // Damage type to use when radial damage is done on death
- var(GVBreakable) class<DamageType> DamageTypeOnDeath;
- // Damage momentum to use when radial damage is done on death
- var(GVBreakable) float DamageMomentumOnDeath;
- // Apply linear fall off from the damage applied to victims when radial damage is done on death
- var(GVBreakable) bool LinearFallOffDamageOnDeath;
- // Apply vertical offset to damage location. This is useful if the breakable is positioned on the floor, as their static meshes have the pivot point aligned to the base of the mesh
- var(GVBreakable) bool ApplyVerticalOffsetOnRadialDamageLocation;
- var array<GVEffectActor> EffectActors;
- var int HealthMax;
- var int CurrentStateIndex;
- var int DesiredStateIndex;
- simulated function PostBeginPlay()
- {
- local SBreakableState BreakableState;
- Super.PostBeginPlay();
- HealthMax = Health;
- if (BreakableStates.Length > 0)
- {
- // Add HealthPercentage == 0.f if it doesn't exist
- if (BreakableStates.Find('HealthPercentage', 0.f) == INDEX_NONE)
- {
- BreakableState.StaticMesh = StaticMeshComponent.StaticMesh;
- BreakableState.HealthPercentage = 0.f;
- BreakableStates.AddItem(BreakableState);
- }
- // Add HealthPercentage == 1.f if it doesn't exist
- if (BreakableStates.Find('HealthPercentage', 1.f) == INDEX_NONE)
- {
- BreakableState.StaticMesh = BreakableStates[BreakableStates.Length - 1].StaticMesh;
- BreakableState.HealthPercentage = 1.f;
- BreakableStates.Insert(0, 1);
- BreakableStates[0] = BreakableState;
- }
- }
- }
- event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
- {
- local int i;
- local float HealthPercentage;
- local float BoundingCylinderRadius, BoundingCylinderHeight;
- local Vector DamageLocation;
- // Abort this function if the damage amount is less than the minimum damage
- if (DamageAmount < MinimumDamage)
- {
- return;
- }
- Super.TakeDamage(DamageAmount, EventInstigator, HitLocation, Momentum, DamageType, HitInfo, DamageCauser);
- Health -= DamageAmount;
- if (Health < 0)
- {
- // Kismet event triggering
- TriggerEventClass(class'SeqEvent_Destroyed', DamageCauser);
- if (DamageOnDeathRadius > 0.f)
- {
- DamageLocation = Location;
- if (ApplyVerticalOffsetOnRadialDamageLocation)
- {
- GetBoundingCylinder(BoundingCylinderRadius, BoundingCylinderHeight);
- DamageLocation.Z += BoundingCylinderHeight;
- }
- HurtRadius(DamageOnDeath, DamageOnDeathRadius, DamageTypeOnDeath, DamageMomentumOnDeath, DamageLocation, Self, None, !LinearFallOffDamageOnDeath);
- }
- if (HideWhenDead)
- {
- SetHidden(true);
- }
- if (DisableCollisionWhenDead)
- {
- SetCollision(false, false, false);
- }
- }
- else
- {
- if (BreakableStates.Length > 0)
- {
- HealthPercentage = float(Health) / float(HealthMax);
- // Get the next state index
- for (i = 0; i < BreakableStates.Length - 1; ++i)
- {
- if (BreakableStates[i].HealthPercentage >= HealthPercentage && BreakableStates[i + 1].HealthPercentage <= HealthPercentage && DesiredStateIndex != i)
- {
- // The new state that we wish to switch to is only 1 difference away
- if (Abs(i - CurrentStateIndex) == 1)
- {
- CurrentStateIndex = i;
- SetState();
- }
- else // The new state is a few states away, so we want to interpolate to it
- {
- DesiredStateIndex = i;
- if (DesiredStateIndex > CurrentStateIndex)
- {
- ++CurrentStateIndex;
- }
- else if (DesiredStateIndex < CurrentStateIndex)
- {
- --CurrentStateIndex;
- }
- SetState();
- SetTimer(StateChangeInterval, true, NameOf(SetStateTimer));
- }
- break;
- }
- }
- }
- }
- }
- function SetStateTimer()
- {
- if (DesiredStateIndex > CurrentStateIndex)
- {
- ++CurrentStateIndex;
- }
- else if (DesiredStateIndex < CurrentStateIndex)
- {
- --CurrentStateIndex;
- }
- if (CurrentStateIndex == DesiredStateIndex)
- {
- SetState();
- ClearTimer(NameOf(SetStateTimer));
- }
- else
- {
- SetState(false);
- }
- }
- function SetState(optional bool CreateEffects = true)
- {
- // Handle previous effect destruction
- if (EffectActors.Length >= 0)
- {
- class'GVEffectActor'.static.StopAndDestroyEffectArray(EffectActors);
- EffectActors.Length = 0;
- }
- // Handle creation of effects for this state
- if (CreateEffects && BreakableStates[CurrentStateIndex].Effects.Length > 0)
- {
- EffectActors = class'GVEffectActor'.static.CreateEffects(BreakableStates[CurrentStateIndex].Effects, Self);
- }
- if (StaticMeshComponent != None)
- {
- StaticMeshComponent.SetStaticMesh(BreakableStates[CurrentStateIndex].StaticMesh);
- }
- }
- defaultproperties
- {
- Health=100
- HideWhenDead=true
- DisableCollisionWhenDead=true
- StateChangeInterval=0.0166667f
- LinearFallOffDamageOnDeath=true
- Begin Object Class=DynamicLightEnvironmentComponent Name=BreakableLightEnvironment
- bEnabled=false
- bDynamic=false
- End Object
- LightEnvironment=BreakableLightEnvironment
- Components.Add(BreakableLightEnvironment)
- Begin Object Name=StaticMeshComponent0
- bUsePrecomputedShadows=true
- BlockRigidBody=true
- LightEnvironment=BreakableLightEnvironment
- End Object
- CollisionType=COLLIDE_BlockAll
- BlockRigidBody=true
- bCollideActors=true
- bBlockActors=true
- SupportedEvents.Empty
- SupportedEvents(0)=class'SeqEvent_Touch'
- SupportedEvents(1)=class'SeqEvent_Destroyed'
- SupportedEvents(2)=class'SeqEvent_TakeDamage'
- SupportedEvents(3)=class'SeqEvent_Mover'
- }
Add Comment
Please, Sign In to add comment