/** * trash by m_cu8 * DON'T ASK ME HOW THAT WORKS BECAUSE I HAVE NO CLUE LMAO * (I even decompiled this garbage because I thought that we have outdated source code... but also I'm too lazy to swap it back with the original class code... peck it, it works, so I won't touch this again) */ class mcu8_Hazard_Train extends Hat_Hazard_Train_Base dependson(CameraModifier_CameraShake) dontsortcategories(OnNPCManagedDistance) autoexpandcategories(Navigation); /** How long the train should be inactive before starting its route (first activation only). */ var(TrainFront) float StartWait; /** Train teleports all at once instead of car-by-car. */ var(TrainFront) bool InstantTeleport; /** Rotates player camera with train rotation when riding on the train. */ var(TrainFront) bool OrientPlayerCamera; var(TrainFront) bool TurnCameraToFaceTrainDirectionOnBase; var(TrainFront) bool TurnCameraEvenIfPreviousBaseWasTrain; /** If enabled, colliding with the front of the train will trigger fall recovery instead of knocking you off the track. Recommended when the train is in a tunnel. */ var(TrainFront) bool DoJumpFailRecovery; /** Camera shakes when train is nearby */ var(TrainFront) bool UseShakeCamera; /** Whether to use the train horn or not */ var(TrainFront) bool UseTrainHorn; var(TrainFront) bool IgnoreFrontDamageWhileAirborne; var(TrainFront) bool UseFastTrainVFX; var bool DamageOnAnyTouch; var bool CamShakeDirty; var bool IsFront; var bool IsDamageFront; var bool OptimizeStraightTrack; var transient bool Initialized; var transient bool IsPlayerNearby; var bool FollowFrontDirectly; /** Point that the player returns to if fall recovery is triggered by this train. If not set, it will use the last visited checkpoint. */ var(TrainFront) Actor JumpFailReturnPoint; /** The camera shake applied near the wheels of the train. */ var(TrainFront) editinline CameraShake CamShake; /** The camera shake applied near the tracks in front of an incoming train. */ var(TrainFront) editinline CameraShake WarningCamShake; /** How far ahead of the front train the camera shake is centralized at. */ var(TrainFront) float WarningCameraShakeLead; /** Distance at which the camera shake fades away. */ var(TrainFront) float CameraShakeFalloff; /** Distance at which the warning camera shake fades away. */ var(TrainFront) float WarningShakeFalloff; /** How far ahead of the front train is the detection area for the train horn. */ var(TrainFront) float TrainHornLead; /** The radius of the sphere used for the train horn detection area. */ var(TrainFront) float TrainHornSize; /** The train/car this car is immediately connected to. Setting this ignores all property settings in the Train Front" section. */ var(TrainCar) mcu8_Hazard_Train Following; /** Total length of this car in the train. Assumes car pivots around its center. */ var(TrainCar) float CarLength; /** How far the 0,0,0 origin point of the model is from the ground. */ var(TrainCar) float CarHeight; /** Sound that plays when you are about to get hit by the train. */ var(Sounds) SoundCue TrainHornSound; /** Sound played by the front of the train while moving. */ var(Sounds) export editinline AudioComponent TrainFrontSound; /** Sound played by the cars of the train while moving. */ var(Sounds) export editinline AudioComponent TrainWheelSound; /** Sound that plays when the train runs into you. */ var(Sounds) SoundCue DamageCollideSound; var export editinline Hat_DrawCatapultComponent StartLineComponent; var export editinline Hat_DrawCatapultComponent FollowLineComponent; var Rotator AngleChangeCamera; var mcu8_Hazard_Train FrontTrain; var float FrontDist; var array Train; var ECollisionType InitialCollision; var float VelocityTransitionTime; var float VelocityTransitionPercentage; var transient array PlayersBasedOnTrain; var transient float LastHornPlayTime; var transient array CamShakeCache; var transient array WarningCamShakeCache; var(TrainFront) float Speed; var(TrainFront) float SpeedMultiplier; var(TrainFront) mcu8_TrainPoint StartPoint; var float AdjustedSpeed; var transient float CurrentSpeed; var bool IsDweller; var bool InvertCollisionWhenDeactivated_Internal; var transient bool InitialBlockActors; simulated event PostBeginPlay() { super(InterpActor).PostBeginPlay(); InitialCollision = CollisionType; if((Owner == none) && CreationTime <= float(0)) { InitTrain(); } //return; } // for dweller trains function bool CanActivate(Actor Other) { if (Other.IsA('Hat_SubconPainting')) return true; if (!Other.IsA('Pawn')) return false; if (Pawn(Other).Controller == None) return false; if (!Pawn(Other).Controller.IsA('Hat_PlayerController')) return false; return true; } // Subclass this to perform your own blocking check. Return false if the Actor should block, return true if the Actor should not block event bool ShouldIgnoreBlockingBy(const Actor Other) { if (!isDweller) return Super.ShouldIgnoreBlockingBy(Other); if (Other.IsA('Hat_DwellerBell')) return true; if (InvertCollisionWhenDeactivated_Internal && CanActivate(Other)) { CollisionComponent.CanBeEdgeGrabbed = class'Hat_DwellerMaskComponent'.static.IsLocationBlocked(Other.Location, 1, !InitialBlockActors); // prevent player climb when disabled return !class'Hat_DwellerMaskComponent'.static.IsLocationBlocked(Other.Location, 1, !InitialBlockActors); } return InitialBlockActors; } function InitTrain(optional bool DoInitShake) { DoInitShake = true; if((StartPoint == none) && Following == none) { Destroy(); return; } if(StartPoint != none) { if(((StartPoint.TrackMaster == none) || StartPoint.TrackMaster.EditorTimeTrackCalculationState != 2) || StartPoint.TrackMaster.SubPoints.Length == 0) { ScriptTrace(); Destroy(); return; } } IsFront = Following == none; if(IsFront) { CurrentSubPoint = StartPoint.GetMySubPoint(); if(StartWait > float(0)) { UpdateAdjustedSpeed(); MoveTrain(AdjustedSpeed * -StartWait); } if(StartPoint.TrackMaster != none) { MoveTrain(StartPoint.TrackMaster.SyncStartOffset); } } else { FrontTrain = GetFrontTrain(); FrontTrain.Train.AddItem(self); if(DoInitShake) { UseShakeCamera = FrontTrain.UseShakeCamera; CameraShakeFalloff = FrontTrain.CameraShakeFalloff; CamShake = FrontTrain.CamShake; } InstantTeleport = FrontTrain.InstantTeleport; DoJumpFailRecovery = FrontTrain.DoJumpFailRecovery; JumpFailReturnPoint = FrontTrain.JumpFailReturnPoint; StartPoint = FrontTrain.StartPoint; IgnoreFrontDamageWhileAirborne = FrontTrain.IgnoreFrontDamageWhileAirborne; UseFastTrainVFX = FrontTrain.UseFastTrainVFX; bPlayerShouldStayBasedAfterJumping = FrontTrain.bPlayerShouldStayBasedAfterJumping; if(StaticMeshComponent.HiddenGame || StaticMeshComponent.LightEnvironment == none) { SetTickIsDisabled(true); } LightEnvironment.SetEnabled(false); } UpdateAdjustedSpeed(); if(!UseShakeCamera) { CamShake = none; WarningCamShake = none; } if(!IsFront) { WarningCamShake = none; } OptimizeStraightTrack = StartPoint.TrackMaster.TrackIsStraight; if(OptimizeStraightTrack) { SetRotation(StartPoint.TrackMaster.SubPoints[CurrentSubPoint].Rotation); } Initialized = true; //return; } function bool SetIsPlayerNearby(bool B, bool bEnableDebugCollisionView) { if(IsPlayerNearby == B) { return false; } IsPlayerNearby = B; SetCollision(B && default.bCollideActors, B && default.bBlockActors); SetCollisionType(((B) ? InitialCollision : 1)); StaticMeshComponent.SetHidden(!bBlockActors || !bEnableDebugCollisionView); return true; //return ReturnValue; } event OnTickOptimized() { CleanCamShake(); } simulated event Attach(Actor Other) { local Hat_Player ply; local SetRotationGradually srg; if(FrontTrain == none) { return; } ply = Hat_Player(Other); if(ply == none) { return; } Other.bIgnoreAirBaseDownwardMovement = true; Other.AirBaseWeight = 1.0; if(PlayersBasedOnTrain.Find(Other) == -1) { PlayersBasedOnTrain.AddItem(Other); } if(FrontTrain.PlayersBasedOnTrain.Find(Other) == -1) { FrontTrain.PlayersBasedOnTrain.AddItem(Other); } FrontTrain.UpdateMusicParameter(); if(UseFastTrainVFX) { if(!FrontTrain.IsTimerActive('FadeOutTrainFrontSound') && FrontTrain.TrainFrontSound != none) { FrontTrain.TrainFrontSound.FadeIn(0.50, 1.0); } else { FrontTrain.ClearTimer('FadeOutTrainFrontSound'); } ply.CatTrainMovingFastParticle.SetActive(true); Hat_PlayerCamera(PlayerController(ply.Controller).PlayerCamera).AddCameraModeClass(class'mcu8_CamMode_CatTrainRoof'); if(!ply.IsTimerActive('FadeOutWindSound')) { ply.CatTrainWindSound.FadeIn(0.80, 1.0); } else { ply.ClearTimer('FadeOutWindSound'); } } if(TurnCameraToFaceTrainDirectionOnBase) { if((((ply.Controller != none) && ply.LastFloorActor != self) && ply.LastFloorActor != FrontTrain) && ((ply.LastFloorActor == none) || !ply.LastFloorActor.IsA('mcu8_Hazard_Train')) || TurnCameraEvenIfPreviousBaseWasTrain) { srg.Rotation = Rotation; srg.Rotation.Pitch = -2000; srg.AffectPitch = true; srg.AffectRoll = false; srg.TurnTime = 0.50; Hat_PlayerController(ply.Controller).OnSetCameraRotationS(srg); } } //return; } function ApplyVelocityToActor(Actor Other, float Weight) { local Vector VelocityAdd; VelocityAdd = (GetVelocity()) * Weight; if(VelocityAdd.Z < float(0)) { VelocityAdd *= vect(1.0, 1.0, 0.0); } VelocityAdd /= Other.CustomTimeDilation; if(Other.Physics == 1) { VelocityAdd *= 0.50; } Other.Velocity += VelocityAdd; //return; } simulated event Detach(Actor Other) { if((Pawn(Other) != none) && !bPlayerShouldStayBasedAfterJumping) { ApplyVelocityToActor(Other, 1.0); } if(FrontTrain == none) { return; } if(!Other.IsA('Hat_Player')) { return; } PlayersBasedOnTrain.RemoveItem(Other); FrontTrain.PlayersBasedOnTrain.RemoveItem(Other); FrontTrain.UpdateMusicParameter(); if(UseFastTrainVFX) { if(PlayersBasedOnTrain.Length == 0) { FrontTrain.SetTimer(0.30, false, 'FadeOutTrainFrontSound'); } Other.AirBaseWeight = 1.0; Hat_Player(Other).CatTrainMovingFastParticle.SetActive(false); Hat_PlayerCamera(PlayerController(Hat_Player(Other).Controller).PlayerCamera).RemoveCameraModeClass(class'mcu8_CamMode_CatTrainRoof'); Hat_Player(Other).SetTimer(0.30, false, 'FadeOutWindSound'); } //return; } function UpdateMusicParameter() { if((class'Hat_GameManager'.static.GetStaticMusicManager() != none) && class'Hat_GameManager'.static.GetStaticMusicManager().MusicTreeInstance != none) { class'Hat_GameManager'.static.GetStaticMusicManager().MusicTreeInstance.SetParameterInt('OnMetroTrain', ((PlayersBasedOnTrain.Length > 0) ? 1 : 0)); } //return; } function FollowerTick(float D) { if(!Initialized) { return; } Speed = Following.Speed; SpeedMultiplier = Following.SpeedMultiplier; OrientPlayerCamera = Following.OrientPlayerCamera; TurnCameraToFaceTrainDirectionOnBase = Following.TurnCameraToFaceTrainDirectionOnBase; TurnCameraEvenIfPreviousBaseWasTrain = Following.TurnCameraEvenIfPreviousBaseWasTrain; MovementTick(D); if(UseShakeCamera) { UpdateCamShake(CurrentSpeed / AdjustedSpeed); } //return; } simulated event Tick(float D) { if(!IsFront) { return; } if(!Initialized) { return; } if(MovementTick(D)) { TickFollowers(D); TickAttachedPlayers(D); if(IsA('mcu8_Hazard_CatTrain')) { UpdateVisuals(StartPoint.TrackMaster.SubPoints); } } if(UseShakeCamera) { UpdateCamShake(CurrentSpeed / AdjustedSpeed); } if(UseTrainHorn) { UpdateTrainHorn(); } //return; } function TickFollowers(float D) { local mcu8_Hazard_Train T; foreach Train(T) { if(T != self) { T.FollowerTick(D); } } //return; } function TickAttachedPlayers(float D) { local Actor A, TracedActor; local Vector HitLoc, HitNrm; local Hat_Player ply; local float VelocityDot, PlayerSpeedSq, OldWeight; local bool bShouldDampenAirAttachment, bPlayerIsOverTrain; foreach PlayersBasedOnTrain(A) { ply = Hat_Player(A); ply.CatTrainMovingFastParticle.SetRotation(ply.Base.Rotation); if(((ply != none) && ply.Physics == 2) && bPlayerShouldStayBasedAfterJumping) { bShouldDampenAirAttachment = false; if(ply.AirBaseWeight < 1.0) { bShouldDampenAirAttachment = true; } if(!bShouldDampenAirAttachment) { if(ply.m_iPlatformMove != 0) { bShouldDampenAirAttachment = true; } } if(!bShouldDampenAirAttachment) { PlayerSpeedSq = VSizeSq(ply.Velocity * vect(1.0, 1.0, 0.0)); VelocityDot = Normal(ply.Velocity * vect(1.0, 1.0, 0.0)) Dot Normal(mcu8_Hazard_Train(ply.Base).GetVelocity()); if((PlayerSpeedSq >= (float(200) ** float(2))) && VelocityDot < 0.60) { bShouldDampenAirAttachment = true; } } if(!bShouldDampenAirAttachment) { bPlayerIsOverTrain = false; foreach ply.TraceActors(class'Actor', TracedActor, HitLoc, HitNrm, ply.Location + vect(0.0, 0.0, -750.0),, vect(0.0, 0.0, 0.0)) { if(!TracedActor.bCollideActors || !TracedActor.bBlockActors) { continue; } if(TracedActor.IsA('mcu8_Hazard_Train')) { if(mcu8_Hazard_Train(TracedActor).FrontTrain == self) { if(ply.Base != TracedActor) { ply.SetBase(TracedActor); } ply.AirBaseWeight = 1.0; ply.bIgnoreAirBaseDownwardMovement = true; bPlayerIsOverTrain = true; break; } continue; } if(TracedActor.bStatic && !TracedActor.IsA('Hat_Hazard_RoadBlock')) { bShouldDampenAirAttachment = true; break; } } if(!bPlayerIsOverTrain) { bShouldDampenAirAttachment = true; } } if(bShouldDampenAirAttachment) { OldWeight = ply.AirBaseWeight; ply.AirBaseWeight -= (D / VelocityTransitionTime); mcu8_Hazard_Train(ply.Base).ApplyVelocityToActor(ply, (OldWeight - ply.AirBaseWeight) * VelocityTransitionPercentage); if(ply.AirBaseWeight <= 0.0) { ply.SetBase(none); ply.AirBaseWeight = 1.0; } } } } //return; } function TurnBasedPlayerCamera(Rotator Offset) { local Player ply; local array GamePlayers; Offset.Pitch = 0; Offset.Roll = 0; GamePlayers = class'Engine'.static.GetEngine().GamePlayers; foreach GamePlayers(ply) { if((((ply.Actor != none) && ply.Actor.Pawn != none) && ply.Actor.Pawn.Base == self) && ply.Actor.Pawn.Physics == 1) { ply.Actor.SetRotation(ply.Actor.Rotation + Offset); } } //return; } function mcu8_Hazard_Train GetFrontTrain() { local mcu8_Hazard_Train R; R = self; FrontDist = 0.0; J0x1A: if(R.Following != none) { FrontDist += ((R.CarLength * 0.50) + (R.Following.CarLength * 0.50)); R = R.Following; if(R.FrontTrain != none) { FrontDist += R.FrontDist; R = R.FrontTrain; // [Explicit Break] goto J0x15F; } if(R == self) { // [Explicit Break] goto J0x15F; } J0x15F: // [Loop Continue] goto J0x1A; } return R; //return ReturnValue; } function UpdateTrainHorn() { local Player ply; local array GamePlayers; if((TrainHornSound == none) || TrainHornSize == float(0)) { return; } if((LastHornPlayTime > float(0)) && (LastHornPlayTime + float(3)) >= WorldInfo.TimeSeconds) { return; } GamePlayers = class'Engine'.static.GetEngine().GamePlayers; foreach GamePlayers(ply) { if((((ply.Actor == none) || ply.Actor.Pawn == none) || !ply.Actor.Pawn.IsA('Hat_Player')) || ply.Actor.Pawn.Health == 0) { continue; } if((ply.Actor.Pawn.Base != none) && ply.Actor.Pawn.Base.IsA('mcu8_Hazard_CatTrain')) { continue; } if(VSizeSq(ply.Actor.Pawn.Location - Location) > ((((TrainHornSize * 0.50) + TrainHornLead) + (CarLength * 0.50)) ** float(2))) { continue; } if(VSizeSq((((GetSubPointOffsetBase(StartPoint.TrackMaster.SubPoints, TrainHornLead + (CarLength * 0.50), true)) + ((vect(0.0, 0.0, 1.0) * TrainHornSize) * 0.660)) - (ply.Actor.Pawn.Location + vect(0.0, 0.0, 50.0))) * vect(1.0, 1.0, 1.50)) > (TrainHornSize ** float(2))) { continue; } PlaySound(TrainHornSound); LastHornPlayTime = WorldInfo.TimeSeconds; Hat_PawnCombat(ply.Actor.Pawn).ShakeNearbyCameras(100.0, 256.0, 4.50, 2.0, true); Hat_Player(ply.Actor.Pawn).SetExpression(8, 3.0); if(Rand(4) == 1) { Hat_Player(ply.Actor.Pawn).PlayVoice(Hat_Player(ply.Actor.Pawn).VoiceTrainStartled); } return; } //return; } function UpdateCamShake(optional float Intensity) { local PlayerController PC; local array GamePlayers; local Vector vertweight; local float CamShakeAmount, WarningShakeAmount; local int I; local bool ForceZeroShake; Intensity = 1.0; vertweight = vect(1.0, 1.0, 2.0); GamePlayers = class'Engine'.static.GetEngine().GamePlayers; I = 0; J0x69: if(I < GamePlayers.Length) { if((GamePlayers[I].Actor == none) || Hat_Player(GamePlayers[I].Actor.Pawn) == none) { } else { ForceZeroShake = Hat_PlayerController(GamePlayers[I].Actor).bCinematicMode; PC = GamePlayers[I].Actor; CamShakeAmount = 0.0; WarningShakeAmount = 0.0; if((Intensity > float(0)) && (CamShake != none) || WarningCamShake != none) { if((CameraShakeFalloff > float(0)) && CamShake != none) { if(!ForceZeroShake && VSizeSq(PC.Pawn.Location - Location) <= (CameraShakeFalloff ** float(2))) { CamShakeAmount = (1.0 - FClamp((VSize(((Location - (vect(0.0, 0.0, 1.0) * CarHeight)) - PC.Pawn.Location) * vertweight) / CameraShakeFalloff) * Intensity, 0.0, 1.0)) * FMin(1.0, Intensity); } if((CamShakeAmount > float(0)) || CamShakeDirty) { SetCamShakeScale(PC, CamShake, CamShakeAmount); } } if(((IsFront && WarningShakeFalloff > float(0)) && WarningCamShake != none) && WarningCameraShakeLead != float(0)) { if(!ForceZeroShake && VSizeSq(PC.Pawn.Location - Location) <= ((((WarningShakeFalloff * 0.50) + WarningCameraShakeLead) + (CarLength * 0.50)) ** float(2))) { WarningShakeAmount = (1.0 - FClamp(VSize((((GetSubPointOffsetBase(StartPoint.TrackMaster.SubPoints, WarningCameraShakeLead + (CarLength * 0.50), true)) - (vect(0.0, 0.0, 1.0) * CarHeight)) - PC.Pawn.Location) * vertweight) / WarningShakeFalloff, 0.0, 1.0)) * FMin(1.0, Intensity); } if((WarningShakeAmount > float(0)) || CamShakeDirty) { SetCamShakeScale(PC, WarningCamShake, WarningShakeAmount); } if(WarningShakeAmount > 0.450) { Hat_Player(PC.Pawn).ExpressionComponent.ForcedViewTarget = self; Hat_Player(PC.Pawn).ExpressionComponent.SetDefaultExpression(8); } else { if(Hat_Player(PC.Pawn).ExpressionComponent.ForcedViewTarget == self) { Hat_Player(PC.Pawn).ExpressionComponent.ForcedViewTarget = none; Hat_Player(PC.Pawn).ExpressionComponent.SetDefaultExpression(0); } } } CamShakeDirty = (CamShakeAmount + WarningShakeAmount) > float(0); } } ++ I; // [Loop Continue] goto J0x69; } //return; } function CleanCamShake() { local array GamePlayers; local Player ply; if(!CamShakeDirty) { return; } GamePlayers = class'Engine'.static.GetEngine().GamePlayers; foreach GamePlayers(ply) { if(CamShake != none) { SetCamShakeScale(ply.Actor, CamShake, 0.0); } if(((WarningCamShake != none) && WarningCameraShakeLead != float(0)) && IsFront) { SetCamShakeScale(ply.Actor, WarningCamShake, 0.0); } } CamShakeDirty = false; //return; } function SetCamShakeScale(PlayerController PC, CameraShake Cam, float Amount) { local int I; if(Amount == float(0)) { PC.ClientStopCameraShake(Cam); return; } I = PC.PlayerCamera.CameraShakeCamMod.ActiveShakes.Find('SourceShakeName', Cam.Name); if(I == -1) { PC.ClientPlayCameraShake(Cam); I = PC.PlayerCamera.CameraShakeCamMod.ActiveShakes.Find('SourceShakeName', Cam.Name); } if(I != -1) { PC.PlayerCamera.CameraShakeCamMod.ActiveShakes[I].Scale = Amount; } //return; } event Bump(Actor Other, PrimitiveComponent OtherComp, Vector HitNormal) { TrainHit(Hat_PawnCombat(Other), HitNormal); super(Actor).Bump(Other, OtherComp, HitNormal); //return; } event Touch(Actor Other, PrimitiveComponent OtherComp, Vector HitLocation, Vector HitNormal) { TrainHit(Hat_PawnCombat(Other), HitNormal); super(Actor).Touch(Other, OtherComp, HitLocation, HitNormal); //return; } function TrainHit(Hat_PawnCombat P, Vector HitNormal) { local float KnockForce, KnockUp, KnockSideways; local Vector V; local bool DealDamage; if(P == none) { return; } // for dweller trains if (ShouldIgnoreBlockingBy(p)) return; if((IgnoreFrontDamageWhileAirborne && CollisionComponent.CanBeStoodOn) && (P.Physics == 2) || P.Physics == 0) { return; } if((IsDamageFront && (vector(Rotation) Dot HitNormal) < 0.50) && !DamageOnAnyTouch) { return; } if((AdjustedSpeed < float(400)) && !DamageOnAnyTouch) { return; } if((P.Base != none) && P.Base.IsA(Class.Name)) { return; } if((P.Base == none) && !IsDamageFront) { return; } DealDamage = P.CanTakeDamage(false, self, 1); if((DamageCollideSound != none) && DealDamage) { PlaySound(DamageCollideSound); } if(IsDamageFront) { KnockForce = 700.0; KnockUp = 1500.0; KnockSideways = 0.550; V = VLerp(Normal(P.Location - Location), HitNormal, 0.50); if(KnockSideways > float(0)) { V = VLerp(V, ((HitNormal Cross vect(0.0, 0.0, 1.0)) * -KnockSideways) * float(((((Normal(P.Location - Location) Cross vect(0.0, 0.0, 1.0)) Dot HitNormal) > float(0)) ? 1 : -1)), KnockSideways); } if(DealDamage) { P.TakeDamage(1, none, P.Location, ((Normal(V) * vect(1.0, 1.0, 0.0)) * KnockForce) + (vect(0.0, 0.0, 1.0) * KnockUp), class'Hat_DamageType_WorldShove',, self); if(DoJumpFailRecovery && P.IsA('Hat_Player')) { Hat_Player(P).DoJumpFailRecovery(0.0, JumpFailReturnPoint,, 0.50); } } else { P.Velocity = (Normal(V) * vect(1.0, 1.0, 0.0)) * KnockForce; } } else { if(DealDamage) { P.TakeDamage(1, none, P.Location, (Normal((P.Location - Location) * vect(1.0, 1.0, 0.0)) * float(700)) + vect(0.0, 0.0, 300.0), class'Hat_DamageType_WorldShove',, self); } } //return; } event editoronly OnEditorPropertyChanged(name PropertyName) { if(PropertyName == 'Speed') { if(StartPoint != none) { StartPoint.PerformEditorTimeTrackCalculation(); } } //return; } event editoronly CheckForErrors(out array ErrorMessages) { super(Actor).CheckForErrors(ErrorMessages); if(StartPoint != none) { if(StartPoint.TrackMaster == none) { ErrorMessages.AddItem("Track has no master point. Move a track point!"); } else { if(StartPoint.TrackMaster.EditorTimeTrackCalculationState != 2) { ErrorMessages.AddItem("Track calculations incomplete. Move a track point!"); } else { if(StartPoint.TrackMaster.SubPoints.Length == 0) { ErrorMessages.AddItem("Track has no subpoints. Move a track point!"); } } } } //return; } function Actor GetAdjustedLastFloorActorForPlayer() { return FrontTrain; //return ReturnValue; } function UpdateAdjustedSpeed() { AdjustedSpeed = (Speed * StartPoint.TrackMaster.SyncSpeedMultiplier) * SpeedMultiplier; //return; } function float GetAdjustedSpeed() { UpdateAdjustedSpeed(); return AdjustedSpeed; //return ReturnValue; } function Vector GetVelocity() { return AdjustedSpeed * vector(Rotation); //return ReturnValue; } static function Vector GetProgressPositionCurved(float Progress, mcu8_TrainPoint CurPoint) { local Vector PP, P, N, nn; if((CurPoint == none) || CurPoint.Next == none) { return vect(0.0, 0.0, 0.0); } if((CurPoint.Prev == none) || !CurPoint.Next.Teleport && CurPoint.Next.Next == none) { return VLerp(CurPoint.Location, CurPoint.Next.Location, Progress); } PP = ((CurPoint.Prev.Teleport) ? CurPoint.Location + (Normal(CurPoint.Location - CurPoint.Next.Location) * float(100)) : CurPoint.Prev.Location); P = CurPoint.Location; N = CurPoint.Next.Location; nn = ((CurPoint.Next.Teleport) ? CurPoint.Next.Location + (Normal(CurPoint.Next.Location - CurPoint.Location) * float(100)) : CurPoint.Next.Next.Location); return class'Hat_TrainPoint_Base'.static.ArgleCubicSpline(PP, P, N, nn, Progress); //return ReturnValue; } function bool MovementTick(float D) { CurrentSpeed = AdjustedSpeed; Teleporting = false; return MoveTrain(CurrentSpeed * D); //return ReturnValue; } function bool MoveTrain(float Dist) { local Vector Offset, Target; local Rotator oldRot, NewRot; if(Dist == float(0)) { return false; } if(IsFront) { AddSubPointDistanceBase(StartPoint.TrackMaster.SubPoints, Dist, InstantTeleport, false); } else { if(FollowFrontDirectly) { CurrentSubPoint = FrontTrain.CurrentSubPoint; NextSubPoint = FrontTrain.NextSubPoint; CurrentProgress = FrontTrain.CurrentProgress; AddSubPointDistanceBase(StartPoint.TrackMaster.SubPoints, -FrontDist, InstantTeleport, true); } else { CurrentSubPoint = Following.CurrentSubPoint; NextSubPoint = FrontTrain.NextSubPoint; CurrentProgress = Following.CurrentProgress; AddSubPointDistanceBase(StartPoint.TrackMaster.SubPoints, ((CarLength * 0.50) + (Following.CarLength * 0.50)) * float(-1), InstantTeleport, true); } } Target = VLerp(StartPoint.TrackMaster.SubPoints[CurrentSubPoint].Location, StartPoint.TrackMaster.SubPoints[NextSubPoint].Location, CurrentProgress); if(!FollowFrontDirectly && !IsFront) { Target = (Following.Location - (vect(0.0, 0.0, 1.0) * Following.CarHeight)) + (Normal(Target - (Following.Location - (vect(0.0, 0.0, 1.0) * Following.CarHeight))) * ((CarLength * 0.50) + (Following.CarLength * 0.50))); } Offset = (Target + (vect(0.0, 0.0, 1.0) * CarHeight)) - Location; if(VSizeSq(Offset) == float(0)) { return false; } Move(Offset); if(!OptimizeStraightTrack) { oldRot = Rotation; NewRot = class'Hat_Math'.static.RLerpShortest(StartPoint.TrackMaster.SubPoints[CurrentSubPoint].Rotation, StartPoint.TrackMaster.SubPoints[NextSubPoint].Rotation, CurrentProgress); if(oldRot != NewRot) { SetRotation(NewRot); if((OrientPlayerCamera && FrontTrain != none) && FrontTrain.PlayersBasedOnTrain.Length > 0) { TurnBasedPlayerCamera(Rotation - oldRot); } } } return true; //return ReturnValue; } defaultproperties { Begin Object Class=Hat_DrawCatapultComponent Name=DrawCatapultComponent0 PropertyName_CatapultTargetActor = "StartPoint" LineWidth = 15 SphereColor=(R=255,G=255,B=0,A=255) bSelectable=false MaxDrawDistance = 4000; End Object Components.Add(DrawCatapultComponent0) StartLineComponent=DrawCatapultComponent0 Begin Object Class=Hat_DrawCatapultComponent Name=DrawCatapultComponent1 PropertyName_CatapultTargetActor = "Following" LineWidth = 30 SphereColor=(R=255,G=0,B=128,A=255) bSelectable=false MaxDrawDistance = 4000; End Object Components.Add(DrawCatapultComponent1) FollowLineComponent=DrawCatapultComponent1 Begin Object Name=MyLightEnvironment bEnabled = true bDynamic = true bIsCharacterLightEnvironment = false bSynthesizeSHLight = false bSynthesizeDirectionalLight = false AmbientGlow = (R=0.2f,G=0.2f,B=0.2f,A=1.0f); End Object Begin Object Name=StaticMeshComponent0 StaticMesh=StaticMesh'HatInTime_Levels_Murder_V.models.LoungeTrolley' CanBlockCamera=true bUsePrecomputedShadows=false LightEnvironment=MyLightEnvironment MotionBlurInstanceScale=0 MaxDrawDistance = 14000 End Object Begin Object Class=CameraShake Name=Shake0 OscillationDuration=-1 RotOscillation={(Pitch=(Amplitude=26.f,Frequency=80.f), Yaw=(Amplitude=12.f,Frequency=60.f), Roll=(Amplitude=26.f,Frequency=120.f))} End Object CamShake=Shake0 Begin Object Class=CameraShake Name=Shake1 OscillationDuration=-1 RotOscillation={(Pitch=(Amplitude=120.f,Frequency=40.f), Yaw=(Amplitude=50.f,Frequency=30.f), Roll=(Amplitude=120.f,Frequency=60.f))} End Object WarningCamShake=Shake1 bNoDelete = false bCollideWorld = false TickOptimize = TickOptimize_View TickOptimize_TimingSensitive = true bNoEncroachCheck = false bEncroachPlayersOnly = true bStopOnEncroach = false Physics = PHYS_Interpolating bBlockActors = true bCollideActors = true bPlayerShouldStayBasedAfterJumping = true; IsPlayerNearby = true // Defaults to true so full logic in SetIsPlayerNearby() will run at least once. Should get turned off on first frame Speed = 450 CarLength = 150 UseShakeCamera = false WarningCameraShakeLead = 350 CameraShakeFalloff = 200 WarningShakeFalloff = 900 TrainHornLead = 400 TrainHornSize = 300 VelocityTransitionTime = 0.75f; VelocityTransitionPercentage = 0.5f; IsActorEnemy=true // This is to freeze trains during cinematics HiddenCameraGroups.Add("Hat_Hazard_Train"); TurnCameraEvenIfPreviousBaseWasTrain = true; ScriptShouldIgnoreBlockingBy = true; NextSubPoint = -1; SpeedMultiplier = 1; }