Compare commits
No commits in common. "9d4dc1b4f27643494de38d9bddf6b5f80fff4c04" and "368575b715de09168e13f7e0c50803a659a232c1" have entirely different histories.
9d4dc1b4f2
...
368575b715
BIN
Content/Input/Actions/IA_Dash.uasset (Stored with Git LFS)
BIN
Content/Input/Actions/IA_Dash.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Input/InputMappingContext.uasset (Stored with Git LFS)
BIN
Content/Input/InputMappingContext.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/Player/PlayerCharacter.uasset (Stored with Git LFS)
BIN
Content/Player/PlayerCharacter.uasset (Stored with Git LFS)
Binary file not shown.
|
@ -31,11 +31,6 @@ bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewM
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Saved_bWantsToDash != newMove->Saved_bWantsToDash)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FSavedMove_Character::CanCombineWith(NewMove, InCharacter, MaxDelta);
|
return FSavedMove_Character::CanCombineWith(NewMove, InCharacter, MaxDelta);
|
||||||
}
|
}
|
||||||
|
@ -46,9 +41,6 @@ void UNakatomiCMC::FSavedMove_Nakatomi::Clear()
|
||||||
FSavedMove_Character::Clear();
|
FSavedMove_Character::Clear();
|
||||||
|
|
||||||
Saved_bWantsToSprint = 0;
|
Saved_bWantsToSprint = 0;
|
||||||
Saved_bWantsToSlide = 0;
|
|
||||||
Saved_bWantsToAds = 0;
|
|
||||||
Saved_bWantsToDash = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const
|
uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const
|
||||||
|
@ -56,7 +48,6 @@ uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const
|
||||||
uint8 Result = Super::GetCompressedFlags();
|
uint8 Result = Super::GetCompressedFlags();
|
||||||
|
|
||||||
if (Saved_bWantsToSprint) Result = ~FLAG_Custom_0;
|
if (Saved_bWantsToSprint) Result = ~FLAG_Custom_0;
|
||||||
if (Saved_bWantsToDash) Result = ~FLAG_Dash;
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +62,6 @@ void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaT
|
||||||
Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint;
|
Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint;
|
||||||
Saved_bWantsToSlide = CharacterMovement->Safe_bWantsToSlide;
|
Saved_bWantsToSlide = CharacterMovement->Safe_bWantsToSlide;
|
||||||
Saved_bWantsToAds = CharacterMovement->Safe_bWantsToAds;
|
Saved_bWantsToAds = CharacterMovement->Safe_bWantsToAds;
|
||||||
Saved_bWantsToDash = CharacterMovement->Safe_bWantsToDash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C)
|
void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C)
|
||||||
|
@ -83,7 +73,6 @@ void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C)
|
||||||
CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint;
|
CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint;
|
||||||
CharacterMovement->Safe_bWantsToSlide = Saved_bWantsToSlide;
|
CharacterMovement->Safe_bWantsToSlide = Saved_bWantsToSlide;
|
||||||
CharacterMovement->Safe_bWantsToAds = Saved_bWantsToAds;
|
CharacterMovement->Safe_bWantsToAds = Saved_bWantsToAds;
|
||||||
CharacterMovement->Safe_bWantsToDash = Saved_bWantsToDash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi(
|
UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi(
|
||||||
|
@ -117,7 +106,6 @@ void UNakatomiCMC::UpdateFromCompressedFlags(uint8 Flags)
|
||||||
Super::UpdateFromCompressedFlags(Flags);
|
Super::UpdateFromCompressedFlags(Flags);
|
||||||
|
|
||||||
Safe_bWantsToSprint = (Flags & FSavedMove_Character::FLAG_Custom_0) != 0;
|
Safe_bWantsToSprint = (Flags & FSavedMove_Character::FLAG_Custom_0) != 0;
|
||||||
Safe_bWantsToDash = (Flags & FSavedMove_Nakatomi::FLAG_Dash) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity)
|
void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity)
|
||||||
|
@ -166,7 +154,6 @@ bool UNakatomiCMC::CanCrouchInCurrentState() const
|
||||||
|
|
||||||
void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds)
|
void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds)
|
||||||
{
|
{
|
||||||
// Slide
|
|
||||||
if (MovementMode == MOVE_Walking && Safe_bWantsToSlide && !Safe_bWantsToAds)
|
if (MovementMode == MOVE_Walking && Safe_bWantsToSlide && !Safe_bWantsToAds)
|
||||||
{
|
{
|
||||||
FHitResult PotentialSlideSurface;
|
FHitResult PotentialSlideSurface;
|
||||||
|
@ -180,13 +167,6 @@ void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds)
|
||||||
{
|
{
|
||||||
ExitSlide();
|
ExitSlide();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dash
|
|
||||||
if (Safe_bWantsToDash && CanDash() && !Safe_bWantsToAds)
|
|
||||||
{
|
|
||||||
PerformDash();
|
|
||||||
Safe_bWantsToDash = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Super::UpdateCharacterStateBeforeMovement(DeltaSeconds);
|
Super::UpdateCharacterStateBeforeMovement(DeltaSeconds);
|
||||||
}
|
}
|
||||||
|
@ -245,27 +225,6 @@ void UNakatomiCMC::DisableAds()
|
||||||
Safe_bWantsToAds = false;
|
Safe_bWantsToAds = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNakatomiCMC::EnableDash()
|
|
||||||
{
|
|
||||||
float CurrentTime = GetWorld()->GetTimeSeconds();
|
|
||||||
|
|
||||||
if (CurrentTime - DashStartTime >= Dash_CooldownDuration)
|
|
||||||
{
|
|
||||||
Safe_bWantsToDash = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GetWorld()->GetTimerManager().SetTimer(TimerHandle_DashCooldown, this, &UNakatomiCMC::OnDashCooldownFinished,
|
|
||||||
Dash_CooldownDuration - (CurrentTime - DashStartTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UNakatomiCMC::DisableDash()
|
|
||||||
{
|
|
||||||
GetWorld()->GetTimerManager().ClearTimer(TimerHandle_DashCooldown);
|
|
||||||
Safe_bWantsToDash = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const
|
bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const
|
||||||
{
|
{
|
||||||
return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode;
|
return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode;
|
||||||
|
@ -363,29 +322,3 @@ bool UNakatomiCMC::GetSlideSurface(FHitResult& Hit) const
|
||||||
|
|
||||||
return GetWorld()->LineTraceSingleByProfile(Hit, Start, End, ProfileName);
|
return GetWorld()->LineTraceSingleByProfile(Hit, Start, End, ProfileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNakatomiCMC::OnDashCooldownFinished()
|
|
||||||
{
|
|
||||||
Safe_bWantsToDash = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UNakatomiCMC::CanDash()
|
|
||||||
{
|
|
||||||
return (IsWalking() || IsFalling()) && !IsCrouching() && !Safe_bWantsToAds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UNakatomiCMC::PerformDash()
|
|
||||||
{
|
|
||||||
DashStartTime = GetWorld()->GetTimeSeconds();
|
|
||||||
|
|
||||||
FVector DashDirection = (Acceleration.IsNearlyZero() ? UpdatedComponent->GetForwardVector() : Acceleration).GetSafeNormal2D();
|
|
||||||
Velocity = Dash_Impulse * (DashDirection + FVector::UpVector * .1f);
|
|
||||||
|
|
||||||
FQuat NewRotation = FRotationMatrix::MakeFromXZ(DashDirection, FVector::UpVector).ToQuat();
|
|
||||||
FHitResult Hit;
|
|
||||||
SafeMoveUpdatedComponent(FVector::ZeroVector, NewRotation, false, Hit);
|
|
||||||
|
|
||||||
SetMovementMode(MOVE_Falling);
|
|
||||||
|
|
||||||
DashStartDelegate.Broadcast();
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,15 +7,12 @@
|
||||||
#include "GameFramework/CharacterMovementComponent.h"
|
#include "GameFramework/CharacterMovementComponent.h"
|
||||||
#include "NakatomiCMC.generated.h"
|
#include "NakatomiCMC.generated.h"
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDashStartDelegate);
|
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
enum ECustomMovementMove
|
enum ECustomMovementMove
|
||||||
{
|
{
|
||||||
CMOVE_None UMETA(Hidden),
|
CMOVE_None UMETA(Hidden),
|
||||||
CMOVE_Slide UMETA(DisplayName = "Slide"),
|
CMOVE_Slide UMETA(DisplayName = "Slide"),
|
||||||
CMOVE_Dash UMETA(DisplayName = "Dash"),
|
CMOVE_MAX UMETA(Hidden),
|
||||||
CMOVE_MAX UMETA(Hidden),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,29 +25,19 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
||||||
|
|
||||||
class FSavedMove_Nakatomi : public FSavedMove_Character
|
class FSavedMove_Nakatomi : public FSavedMove_Character
|
||||||
{
|
{
|
||||||
using Super = FSavedMove_Character;
|
typedef FSavedMove_Character Super;
|
||||||
|
|
||||||
public:
|
|
||||||
enum CompressedFlags
|
|
||||||
{
|
|
||||||
FLAG_Sprint = 0x10,
|
|
||||||
FLAG_Dash = 0x20,
|
|
||||||
FLAG_Custom2 = 0x30,
|
|
||||||
FLAG_Custom3 = 0x40,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Flag
|
// Flag
|
||||||
uint8 Saved_bWantsToSprint : 1;
|
uint8 Saved_bWantsToSprint:1;
|
||||||
uint8 Saved_bWantsToSlide : 1;
|
|
||||||
uint8 Saved_bWantsToAds : 1;
|
uint8 Saved_bWantsToSlide:1;
|
||||||
uint8 Saved_bWantsToDash : 1;
|
|
||||||
|
|
||||||
virtual bool
|
uint8 Saved_bWantsToAds:1;
|
||||||
CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override;
|
|
||||||
|
virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override;
|
||||||
virtual void Clear() override;
|
virtual void Clear() override;
|
||||||
virtual uint8 GetCompressedFlags() const override;
|
virtual uint8 GetCompressedFlags() const override;
|
||||||
virtual void SetMoveFor(ACharacter* C, float InDeltaTime, const FVector& NewAccel,
|
virtual void SetMoveFor(ACharacter* C, float InDeltaTime, FVector const& NewAccel, FNetworkPredictionData_Client_Character& ClientData) override;
|
||||||
FNetworkPredictionData_Client_Character& ClientData) override;
|
|
||||||
virtual void PrepMoveFor(ACharacter* C) override;
|
virtual void PrepMoveFor(ACharacter* C) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,7 +46,7 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
||||||
public:
|
public:
|
||||||
FNetworkPredictionData_Client_Nakatomi(const UCharacterMovementComponent& ClientMovement);
|
FNetworkPredictionData_Client_Nakatomi(const UCharacterMovementComponent& ClientMovement);
|
||||||
|
|
||||||
using Super = FNetworkPredictionData_Client_Character;
|
typedef FNetworkPredictionData_Client_Character Super;
|
||||||
|
|
||||||
virtual FSavedMovePtr AllocateNewMove() override;
|
virtual FSavedMovePtr AllocateNewMove() override;
|
||||||
};
|
};
|
||||||
|
@ -69,10 +56,10 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
UPROPERTY(EditDefaultsOnly)
|
||||||
float Walk_MaxWalkSpeed = 500.0f;
|
float Walk_MaxWalkSpeed = 500.0f;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
UPROPERTY(EditDefaultsOnly)
|
||||||
float Crouch_MaxWalkSpeed = 250.0f;
|
float Crouch_MaxWalkSpeed = 250.0f;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
UPROPERTY(EditDefaultsOnly)
|
||||||
float Slide_MinSpeed = 50.f;
|
float Slide_MinSpeed = 50.f;
|
||||||
|
|
||||||
|
@ -87,36 +74,21 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
UPROPERTY(EditDefaultsOnly)
|
||||||
float Ads_Multiplier = 0.5f;
|
float Ads_Multiplier = 0.5f;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
|
||||||
float Dash_Impulse = 1500.0f;
|
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly)
|
|
||||||
float Dash_CooldownDuration = 1.0f;
|
|
||||||
|
|
||||||
bool Safe_bWantsToSprint;
|
bool Safe_bWantsToSprint;
|
||||||
bool Safe_bWantsToSlide;
|
bool Safe_bWantsToSlide;
|
||||||
bool Safe_bWantsToAds;
|
bool Safe_bWantsToAds;
|
||||||
bool Safe_bWantsToDash;
|
|
||||||
|
|
||||||
float DashStartTime;
|
|
||||||
FTimerHandle TimerHandle_DashCooldown;
|
|
||||||
|
|
||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
ANakatomiCharacter* NakatomiCharacterOwner;
|
ANakatomiCharacter* NakatomiCharacterOwner;
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(BlueprintAssignable)
|
|
||||||
FDashStartDelegate DashStartDelegate;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UNakatomiCMC();
|
UNakatomiCMC();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void InitializeComponent() override;
|
void InitializeComponent() override;
|
||||||
|
|
||||||
virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override;
|
|
||||||
|
|
||||||
|
FNetworkPredictionData_Client* GetPredictionData_Client() const override;
|
||||||
protected:
|
protected:
|
||||||
virtual void UpdateFromCompressedFlags(uint8 Flags) override;
|
virtual void UpdateFromCompressedFlags(uint8 Flags) override;
|
||||||
|
|
||||||
|
@ -129,7 +101,7 @@ protected:
|
||||||
virtual void UpdateCharacterStateBeforeMovement(float DeltaSeconds) override;
|
virtual void UpdateCharacterStateBeforeMovement(float DeltaSeconds) override;
|
||||||
|
|
||||||
virtual void PhysCustom(float deltaTime, int32 Iterations) override;
|
virtual void PhysCustom(float deltaTime, int32 Iterations) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
void EnableSprint();
|
void EnableSprint();
|
||||||
|
@ -155,22 +127,16 @@ public:
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
void DisableAds();
|
void DisableAds();
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable)
|
|
||||||
void EnableDash();
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable)
|
|
||||||
void DisableDash();
|
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const;
|
bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnterSlide();
|
|
||||||
void ExitSlide();
|
|
||||||
void PhysSlide(float deltaTime, int32 Iterations); // Every movement mode requires a physics function to work
|
|
||||||
bool GetSlideSurface(FHitResult& Hit) const;
|
|
||||||
|
|
||||||
void OnDashCooldownFinished();
|
void EnterSlide();
|
||||||
bool CanDash();
|
|
||||||
void PerformDash();
|
void ExitSlide();
|
||||||
|
|
||||||
|
void PhysSlide(float deltaTime, int32 Iterations); // Every movement mode requires a physics function to work
|
||||||
|
|
||||||
|
bool GetSlideSurface(FHitResult& Hit) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -199,12 +199,6 @@ void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCom
|
||||||
Input->BindAction(SlideAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginSlideCallback);
|
Input->BindAction(SlideAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginSlideCallback);
|
||||||
Input->BindAction(SlideAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndSlideCallback);
|
Input->BindAction(SlideAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndSlideCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DashAction)
|
|
||||||
{
|
|
||||||
Input->BindAction(DashAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginDashCallback);
|
|
||||||
Input->BindAction(DashAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndDashCallback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,22 +570,6 @@ void APlayerCharacter::EndSlideCallback(const FInputActionInstance& Instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void APlayerCharacter::BeginDashCallback(const FInputActionInstance& Instance)
|
|
||||||
{
|
|
||||||
if (UNakatomiCMC* cmc = GetCharacterMovementComponent())
|
|
||||||
{
|
|
||||||
cmc->EnableDash();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void APlayerCharacter::EndDashCallback(const FInputActionInstance& Instance)
|
|
||||||
{
|
|
||||||
if (UNakatomiCMC* cmc = GetCharacterMovementComponent())
|
|
||||||
{
|
|
||||||
cmc->DisableDash();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void APlayerCharacter::OnFire()
|
void APlayerCharacter::OnFire()
|
||||||
{
|
{
|
||||||
if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0)
|
if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0)
|
||||||
|
|
|
@ -70,9 +70,6 @@ public:
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||||
UInputAction* SlideAction;
|
UInputAction* SlideAction;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
|
||||||
UInputAction* DashAction;
|
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||||
TSoftObjectPtr<UInputMappingContext> InputMappingContext;
|
TSoftObjectPtr<UInputMappingContext> InputMappingContext;
|
||||||
|
@ -188,10 +185,6 @@ public:
|
||||||
void BeginSlideCallback(const FInputActionInstance& Instance);
|
void BeginSlideCallback(const FInputActionInstance& Instance);
|
||||||
|
|
||||||
void EndSlideCallback(const FInputActionInstance& Instance);
|
void EndSlideCallback(const FInputActionInstance& Instance);
|
||||||
|
|
||||||
void BeginDashCallback(const FInputActionInstance& Instance);
|
|
||||||
|
|
||||||
void EndDashCallback(const FInputActionInstance& Instance);
|
|
||||||
|
|
||||||
virtual void OnFire() override;
|
virtual void OnFire() override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue