Compare commits

...

19 Commits

Author SHA1 Message Date
c754a53338 Merge remote-tracking branch 'origin/Monolith-Testing' into PilotMovement
# Conflicts:
#	Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset
2024-10-28 19:24:00 +00:00
6c0bb55009 Duplicated Default Input map
cba setting it all up again after merge
2024-10-28 18:54:12 +00:00
79d92fd2cb The whole of Pilot Movement :) 2024-10-28 18:52:03 +00:00
24739247d2 Added Ability 1
Added the first test ability
2024-10-26 16:05:08 +01:00
a76a00dce7 Added AbilityCircle widget
Added a UI widget for the ability circle so that it can grow when pressed and shrink when released
2024-10-26 15:32:20 +01:00
16f8a3cd00 Updated BPI Monolith
I updated the mech so it would be able to shoot and use a meele weapon
2024-10-24 14:46:43 +01:00
c10e904a27 Create Meele weapon and Bullet weapon Blueprints
Made these blueprints to create a test weapon for the mech
2024-10-24 14:46:10 +01:00
6d6c3e2d85 Made a left click and right click input
Made these two different inputs so we can make the weapon system later
2024-10-24 14:45:43 +01:00
5edb1d7b7e Updated Monolith Blueprint
Added a health widget bar to the monolith
2024-10-20 15:02:48 +01:00
32f3b00907 Added battery life blueprint
Added a health system to the monolith
2024-10-20 14:45:38 +01:00
7663ba8e09 Updated Monolith Interior blueprint
Made it so you can enter and exit the interior of the monolith
2024-10-17 21:24:27 +01:00
5de112aefb Updated First person blueprint
Added the function to enter the monolith Interior
2024-10-15 14:27:46 +01:00
b3cbe8e829 Updated Monolith Blueprint
I added character movement to the Monolith to give it basic maneuverability to the mech
2024-10-15 14:26:57 +01:00
7c8d12f476 Update Monolith blueprint
I added the ability to enter and exit the monolith mech
2024-10-14 17:41:37 +01:00
18df9e84f4 Updated BP_Monolith
I made the monolith possessable by the player character, however I cant test it because of a certain someone!
2024-10-14 16:23:44 +01:00
1f8edd00b4 Created MonolithMech blueprint class 2024-10-12 19:21:11 +01:00
7b066f9fab Imported Monolith skeletal mesh
Imported the monolith skeletal mesh, its probably not a good idea to use it with animations however, as its automatically weight painted
2024-10-12 18:58:02 +01:00
e5d7ed707b Implemented Monolith Mesh
I added in the monolith blockout mesh to use for testing
2024-10-12 18:18:58 +01:00
84a981a673 Removed TP Classes and Created Pilot Camera 2024-10-02 21:13:20 +01:00
53 changed files with 628 additions and 391 deletions

View File

@ -10,10 +10,12 @@ TransitionMap=None
bUseSplitscreen=True
TwoPlayerSplitscreenLayout=Horizontal
ThreePlayerSplitscreenLayout=FavorTop
FourPlayerSplitscreenLayout=Grid
bOffsetPlayerGamepadIds=False
GameInstanceClass=/Game/Blueprints/GI_Monolith.GI_Monolith_C
GameDefaultMap=/Game/MainMenu/MAP_MainMenu.MAP_MainMenu
ServerDefaultMap=/Engine/Maps/Entry
GlobalDefaultGameMode=/Game/MainMenu/GM_MainMenu.GM_MainMenu_C
ServerDefaultMap=/Engine/Maps/Entry.Entry
GlobalDefaultGameMode=/Game/FirstPerson/Blueprints/BP_FirstPersonGameMode.BP_FirstPersonGameMode_C
GlobalDefaultServerGameMode=None
[/Script/Engine.RendererSettings]

View File

@ -92,7 +92,9 @@ bCaptureMouseOnLaunch=True
bEnableLegacyInputScales=True
bEnableMotionControls=True
bFilterInputByPlatformUser=False
bEnableInputDeviceSubsystem=True
bShouldFlushPressedKeysOnViewportFocusLost=True
bEnableDynamicComponentInputBinding=True
bAlwaysShowTouchInterface=False
bShowConsoleOnFourFingerTap=True
bEnableGestureRecognizer=False
@ -101,6 +103,18 @@ DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown
DefaultViewportMouseLockMode=LockOnCapture
FOVScale=0.011110
DoubleClickTime=0.200000
+ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar)
+ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftControl)
+ActionMappings=(ActionName="Sprint",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftShift)
+ActionMappings=(ActionName="Use Left Weapon",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton)
+ActionMappings=(ActionName="Use Right Weapon",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton)
+ActionMappings=(ActionName="Ability1",bShift=False,bCtrl=False,bAlt=True,bCmd=False,Key=One)
+AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W)
+AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S)
+AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=D)
+AxisMappings=(AxisName="MoveRight",Scale=-1.000000,Key=A)
+AxisMappings=(AxisName="Turn",Scale=1.000000,Key=MouseX)
+AxisMappings=(AxisName="LookUp",Scale=-1.000000,Key=MouseY)
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
DefaultTouchInterface=/Game/FirstPerson/Input/MobileControls.MobileControls

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Blueprints/BPI_MonolithInteriorExit.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/FirstPerson/HUD/WBP_DashesRemaining.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/FirstPerson/Input/Actions/IA_Sprint.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/FirstPerson/Input/IMC_DefaultDup.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/Levels/PrototypeLevel.umap (Stored with Git LFS)

Binary file not shown.

BIN
Content/Monolith/BPI_AOverheat.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/BPI_Bullet.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/BPI_MeeleWeapon.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/BPI_Monolith.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/Monolith.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/UI/WB_AbilityCircle.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Monolith/UI/WB_BatteryLife.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -7,7 +7,10 @@
{
"Name": "Monolith",
"Type": "Runtime",
"LoadingPhase": "Default"
"LoadingPhase": "Default",
"AdditionalDependencies": [
"Engine"
]
}
],
"Plugins": [

View File

@ -1,47 +1,63 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "MonolithCharacter.h"
#include "MonolithProjectile.h"
#include "Animation/AnimInstance.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "Engine/LocalPlayer.h"
DEFINE_LOG_CATEGORY(LogTemplateCharacter);
//////////////////////////////////////////////////////////////////////////
// AMonolithCharacter
void AMonolithCharacter::StartRechargingDash()
{
if (DashRechargeHandle.IsValid()) return;
GetWorld()->GetTimerManager().SetTimer(DashRechargeHandle, this
, &AMonolithCharacter::DashRecharged, DashRechargeTime);
}
void AMonolithCharacter::DashRecharged()
{
DashesRemaining++;
UpdateDashUI(DashesRemaining);
DashRechargeHandle.Invalidate();
if (DashesRemaining < 4)
{
StartRechargingDash();
}
}
AMonolithCharacter::AMonolithCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());
FirstPersonCameraComponent->SetRelativeLocation(FVector(-10.f, 0.f, 60.f)); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->SetupAttachment(FirstPersonCameraComponent);
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
//Mesh1P->SetRelativeRotation(FRotator(0.9f, -19.19f, 5.2f));
Mesh1P->SetRelativeLocation(FVector(-30.f, 0.f, -150.f));
}
void AMonolithCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
Mesh1P = Cast<USkeletalMeshComponent>(GetComponentByClass(USkeletalMeshComponent::StaticClass()));
CharMove = Cast<UCharacterMovementComponent>(GetComponentByClass(UCharacterMovementComponent::StaticClass()));
if (CharMove) WalkSpeed = CharMove->MaxWalkSpeed;
}
void AMonolithCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (CharMove == nullptr) return;
CharMove->IsFalling() ? MoveState.Remove(GROUNDED) : MoveState.Add(GROUNDED);
MoveState.VelocityMag = CharMove->Velocity.Length();
MoveState.VelocityMag < VelocityTolerance ? MoveState.Add(STILL) : MoveState.Remove(STILL);
}
//////////////////////////////////////////////////////////////////////////// Input
@ -57,6 +73,15 @@ void AMonolithCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputC
// Moving
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMonolithCharacter::Move);
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Completed, this, &AMonolithCharacter::StopMove);
// Sprinting
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Triggered, this, &AMonolithCharacter::Sprint);
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AMonolithCharacter::StopSprint);
// Dashing
EnhancedInputComponent->BindAction(HorDashAction, ETriggerEvent::Triggered, this, &AMonolithCharacter::HorizontalDash);
EnhancedInputComponent->BindAction(VerDashAction, ETriggerEvent::Triggered, this, &AMonolithCharacter::VerticalDash);
// Looking
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMonolithCharacter::Look);
@ -67,20 +92,112 @@ void AMonolithCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputC
}
}
static void UpdateMoveState(FMoveState& MoveState, int Forwards, int Sideways)
{
if (Sideways && !Forwards)
{ // STRAFING
if (Sideways > 0)
{
MoveState.Add(STRAFE_R);
MoveState.Remove(STRAFE_L);
}
else
{
MoveState.Add(STRAFE_L);
MoveState.Remove(STRAFE_R);
}
MoveState.Remove(FORWARD);
}
else if (Forwards > 0)
{ // GOING ROUGHLY FORWARD
MoveState.Add(FORWARD);
MoveState.Remove(STRAFE_L);
MoveState.Remove(STRAFE_R);
}
else
{
MoveState.Remove(FORWARD);
MoveState.Remove(STRAFE_L);
MoveState.Remove(STRAFE_R);
}
}
void AMonolithCharacter::Move(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
MovementVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// add movement
AddMovementInput(GetActorForwardVector(), MovementVector.Y);
AddMovementInput(GetActorRightVector(), MovementVector.X);
UpdateMoveState(MoveState, MovementVector.Y, MovementVector.X);
}
}
void AMonolithCharacter::StopMove()
{
MoveState.Remove(STRAFE_L);
MoveState.Remove(STRAFE_R);
MoveState.Remove(FORWARD);
MoveState.Remove(SPRINT);
}
void AMonolithCharacter::Sprint(const FInputActionValue& Value)
{
if (CharMove == nullptr || MoveState.Is(SPRINT)) return;
if (!MoveState.Is(FORWARD)
|| !MoveState.Is(GROUNDED))
{
StopSprint();
}
else
{
MoveState.Add(SPRINT);
CharMove->MaxWalkSpeed = SprintSpeed;
}
}
void AMonolithCharacter::StopSprint()
{
MoveState.Remove(SPRINT);
CharMove->MaxWalkSpeed = WalkSpeed;
}
void AMonolithCharacter::HorizontalDash(const FInputActionValue& Value)
{
if (DashesRemaining <= 0) return;
DashesRemaining--;
UpdateDashUI(DashesRemaining);
FVector Impulse;
if (MovementVector.Y)
{
Impulse = MovementVector.Y > 0
? GetActorForwardVector() : -GetActorForwardVector();
}
else
{
Impulse = MovementVector.X > 0
? GetActorRightVector() : -GetActorRightVector();
}
Impulse *= DashImpulse;
Impulse.Z += DashImpulse * 0.25f;
CharMove->AddImpulse(Impulse, true);
StartRechargingDash();
}
void AMonolithCharacter::VerticalDash(const FInputActionValue& Value)
{
if (DashesRemaining <= 0) return;
DashesRemaining--;
UpdateDashUI(DashesRemaining);
FVector Impulse(0, 0, DashImpulse * 0.55f);
CharMove->AddImpulse(Impulse, true);
StartRechargingDash();
}
void AMonolithCharacter::Look(const FInputActionValue& Value)
{
// input is a Vector2D

View File

@ -5,12 +5,15 @@
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Logging/LogMacros.h"
#include "MoveState.h"
#include "PilotCamera.h"
#include "PilotCameraShake.h"
#include "MonolithCharacter.generated.h"
class UInputComponent;
class UCharacterMovementComponent;
class USkeletalMeshComponent;
class UCameraComponent;
class UInputAction;
class UInputComponent;
class UInputMappingContext;
struct FInputActionValue;
@ -21,13 +24,8 @@ class AMonolithCharacter : public ACharacter
{
GENERATED_BODY()
/** Pawn mesh: 1st person view (arms; seen only by self) */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Mesh, meta = (AllowPrivateAccess = "true"))
USkeletalMeshComponent* Mesh1P;
/** First person camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
UCameraComponent* FirstPersonCameraComponent;
friend UPilotCamera;
friend UPilotCameraShake;
/** Jump Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
@ -37,35 +35,82 @@ class AMonolithCharacter : public ACharacter
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
UInputAction* MoveAction;
public:
AMonolithCharacter();
/** Sprint Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
UInputAction* SprintAction;
/** Horizontal Dash Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
UInputAction* HorDashAction;
/** Vertical Dash Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
UInputAction* VerDashAction;
UPROPERTY(EditDefaultsOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
float SprintSpeed = 750.f;
float WalkSpeed = 600.f;
// Velocity Below this Value will be Ignored for Camera Effects
UPROPERTY(EditAnywhere, Category = "MoveState", meta=(AllowPrivateAccess = "true"))
float VelocityTolerance = 300.f;
// Amount of impulse to add when dashing
UPROPERTY(EditAnywhere, Category = "MoveState", meta=(AllowPrivateAccess = "true"))
float DashImpulse = 600.f;
USkeletalMeshComponent* Mesh1P;
UCharacterMovementComponent* CharMove;
FMoveState MoveState;
FVector2D MovementVector;
protected:
virtual void BeginPlay();
void BeginPlay();
void Tick(float DeltaSeconds) override;
/** Called for movement input */
void Move(const FInputActionValue& Value);
void StopMove();
/** Called for SPRINT input */
void Sprint(const FInputActionValue& Value);
void StopSprint();
/** Called for Dashing inputs */
void HorizontalDash(const FInputActionValue& Value);
void VerticalDash(const FInputActionValue& Value);
/** Called for looking input */
void Look(const FInputActionValue& Value);
// APawn interface
virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
// End of APawn interface
// Time to recharge 1 dash
UPROPERTY(EditDefaultsOnly, Category = "MoveState", meta = (AllowPrivateAccess = "true"))
float DashRechargeTime = 2.5f;
FTimerHandle DashRechargeHandle;
int DashesRemaining = 4;
void StartRechargingDash();
void DashRecharged();
UFUNCTION(BlueprintImplementableEvent)
void UpdateDashUI(int dashesRemaining);
public:
AMonolithCharacter();
/** Look Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* LookAction;
protected:
/** Called for movement input */
void Move(const FInputActionValue& Value);
/** Called for looking input */
void Look(const FInputActionValue& Value);
protected:
// APawn interface
virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
// End of APawn interface
public:
/** Returns Mesh1P subobject **/
USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; }
/** Returns FirstPersonCameraComponent subobject **/
UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
USkeletalMeshComponent* GetMesh1P()
{
if (Mesh1P) return Mesh1P;
Mesh1P = Cast<USkeletalMeshComponent>(GetComponentByClass(USkeletalMeshComponent::StaticClass()));
return Mesh1P;
}
};

View File

@ -1,43 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "MonolithProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"
AMonolithProjectile::AMonolithProjectile()
{
// Use a sphere as a simple collision representation
CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
CollisionComp->InitSphereRadius(5.0f);
CollisionComp->BodyInstance.SetCollisionProfileName("Projectile");
CollisionComp->OnComponentHit.AddDynamic(this, &AMonolithProjectile::OnHit); // set up a notification for when this component hits something blocking
// Players can't walk on it
CollisionComp->SetWalkableSlopeOverride(FWalkableSlopeOverride(WalkableSlope_Unwalkable, 0.f));
CollisionComp->CanCharacterStepUpOn = ECB_No;
// Set as root component
RootComponent = CollisionComp;
// Use a ProjectileMovementComponent to govern this projectile's movement
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
ProjectileMovement->UpdatedComponent = CollisionComp;
ProjectileMovement->InitialSpeed = 3000.f;
ProjectileMovement->MaxSpeed = 3000.f;
ProjectileMovement->bRotationFollowsVelocity = true;
ProjectileMovement->bShouldBounce = true;
// Die after 3 seconds by default
InitialLifeSpan = 3.0f;
}
void AMonolithProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
// Only add impulse and destroy projectile if we hit a physics
if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics())
{
OtherComp->AddImpulseAtLocation(GetVelocity() * 100.0f, GetActorLocation());
Destroy();
}
}

View File

@ -1,37 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MonolithProjectile.generated.h"
class USphereComponent;
class UProjectileMovementComponent;
UCLASS(config=Game)
class AMonolithProjectile : public AActor
{
GENERATED_BODY()
/** Sphere collision component */
UPROPERTY(VisibleDefaultsOnly, Category=Projectile)
USphereComponent* CollisionComp;
/** Projectile movement component */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = "true"))
UProjectileMovementComponent* ProjectileMovement;
public:
AMonolithProjectile();
/** called when projectile hits something */
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
/** Returns CollisionComp subobject **/
USphereComponent* GetCollisionComp() const { return CollisionComp; }
/** Returns ProjectileMovement subobject **/
UProjectileMovementComponent* GetProjectileMovement() const { return ProjectileMovement; }
};

View File

@ -0,0 +1,33 @@
#pragma once
using State = unsigned short;
#define STRAFE_L 0x1
#define STRAFE_R 0x2
#define SPRINT 0x4
#define GROUNDED 0x8
#define FORWARD 0x10
#define STILL 0x20
class FMoveState
{
State MoveState = 0;
public:
bool Is(State state) const
{
return MoveState & state;
}
void Add(State state)
{
MoveState += Is(state) ? 0 : state;
}
void Remove(State state)
{
MoveState -= Is(state) ? state : 0;
}
double VelocityMag = 0;
};

View File

@ -0,0 +1,82 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PilotCamera.h"
#include "MonolithPlayerController.h"
#include "MonolithCharacter.h"
#include "MoveState.h"
void UPilotCamera::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (TickType == LEVELTICK_ViewportsOnly
|| (!isMoveStateSet() && !TrySetMoveState())) return;
// TODO - Set FOV based on Velocity mag
UpdateFOV(DeltaTime);
// TODO - Add Camera Roll if Strafing
UpdateRoll(DeltaTime);
// if (MoveState->Is(STRAFE_L)) UE_LOG(LogTemp, Warning, TEXT("Strafing Left"));
// if (MoveState->Is(STRAFE_R)) UE_LOG(LogTemp, Warning, TEXT("Strafing Right"));
// if (MoveState->Is(SPRINT)) UE_LOG(LogTemp, Warning, TEXT("Sprinting"));
// if (MoveState->Is(GROUNDED)) UE_LOG(LogTemp, Warning, TEXT("On the floor"));
// if (MoveState->Is(FORWARD)) UE_LOG(LogTemp, Warning, TEXT("Going FORWARD"));
}
bool UPilotCamera::TrySetMoveState()
{
AMonolithCharacter* PlayerChar = Cast<AMonolithCharacter>
(
Cast<AMonolithPlayerController>(GetWorld()->GetFirstPlayerController())->GetPawn()
);
if ( PlayerChar == nullptr) return false;
MoveState = &PlayerChar->MoveState;
return MoveState != nullptr;
}
void UPilotCamera::UpdateFOV(float DeltaTime)
{
const float targetFOV = GetTargetFOV();
if (FieldOfView == targetFOV) return;
float linearModifier = 1 - (FMath::Abs(targetFOV - FieldOfView)) / targetFOV;
float rateOfChange = RateOfChange * DeltaTime * linearModifier;
bool increasing = targetFOV > FieldOfView;
rateOfChange *= increasing ? 1 : -1;
float newFOV = FieldOfView + rateOfChange;
if ((increasing && newFOV > targetFOV) || (!increasing && newFOV < targetFOV))
{
newFOV = targetFOV;
}
SetFieldOfView(newFOV);
}
void UPilotCamera::UpdateRoll(float DeltaTime)
{
FRotator rot = GetRelativeRotation();
if (MoveState->Is(STRAFE_R))
{
TargetRoll = MaxStrafeRoll;
}
else if (MoveState->Is(STRAFE_L))
{
TargetRoll = -MaxStrafeRoll;
}
else
{
TargetRoll = 0;
}
float rateOfChange = RollRateOfChange * DeltaTime;
bool increasing = TargetRoll > rot.Roll;
rateOfChange *= increasing ? 1 : -1;
rot.Roll += rateOfChange;
if ((increasing && rot.Roll > TargetRoll) || (!increasing && rot.Roll < TargetRoll))
{
rot.Roll = TargetRoll;
}
SetRelativeRotation(rot);
}

View File

@ -0,0 +1,61 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MoveState.h"
#include "Camera/CameraComponent.h"
#include "PilotCamera.generated.h"
class FMoveState;
UCLASS(Blueprintable, ClassGroup=Camera, meta=(BlueprintSpawnableComponent))
class MONOLITH_API UPilotCamera : public UCameraComponent
{
GENERATED_BODY()
using FOVs = std::tuple<float, float, float>;
#define ARE(Stand, Walk, Sprint) std::make_tuple(Stand, Walk, Sprint)
void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);
inline bool isMoveStateSet() const;
bool TrySetMoveState();
// FOV
FOVs TargetFOVs = ARE(87.f, 92.f, 100.f);
const float RateOfChange = 30;
float GetTargetFOV() const;
void UpdateFOV(float DeltaTime);
// Roll
float TargetRoll = 0;
// Max amount of roll applied when strafing
UPROPERTY(EditDefaultsOnly, Category = "Move State", meta = (AllowPrivateAccess = "true"))
float MaxStrafeRoll = 3;
// Amount of roll applied per second
UPROPERTY(EditDefaultsOnly, Category = "Move State", meta = (AllowPrivateAccess = "true"))
float RollRateOfChange = 15;
void UpdateRoll(float DeltaTime);
// TODO - Implement these
void ApplyImpulseFOV();
void ImpactCameraShake();
FMoveState* MoveState;
};
inline float UPilotCamera::GetTargetFOV() const
{
auto[stand, walk, sprint] = TargetFOVs;
if (MoveState->Is(SPRINT)) return sprint;
if (!MoveState->Is(STILL)
&& !MoveState->Is(STRAFE_R)
&& !MoveState->Is(STRAFE_L)) return walk;
return stand;
}
inline bool UPilotCamera::isMoveStateSet() const
{
return MoveState != nullptr;
}

View File

@ -0,0 +1,62 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PilotCameraShake.h"
#include "MonolithCharacter.h"
#include "MonolithPlayerController.h"
#include "MoveState.h"
void UPilotCameraShake::BeginPlay()
{
Super::BeginPlay();
// For some reason camera shakes dont override tick :((
GetWorld()->GetTimerManager().SetTimer(TickHandle, this
, &UPilotCameraShake::UpdateCameraShake, 0.25f, true);
}
bool UPilotCameraShake::TrySetMoveState()
{
AMonolithCharacter* PlayerChar = Cast<AMonolithCharacter>
(
Cast<AMonolithPlayerController>(GetWorld()->GetFirstPlayerController())->GetPawn()
);
if ( PlayerChar == nullptr) return false;
MoveState = &PlayerChar->MoveState;
return MoveState != nullptr;
}
void UPilotCameraShake::UpdateCameraShake()
{
if (CantUpdate()) return;
if (!MoveState->Is(GROUNDED))
{
if (CurrentState == Floating) return;
CurrentState = Floating;
SetCameraShakeBase(FloatingShake);
}
else if (MoveState->Is(SPRINT))
{
if (CurrentState == Running) return;
CurrentState = Running;
SetCameraShakeBase(RunningShake);
}
else if (MoveState->Is(STILL))
{
if (CurrentState == Idling) return;
CurrentState = Idling;
SetCameraShakeBase(IdleShake);
}
else
{
if (CurrentState == Walking) return;
CurrentState = Walking;
SetCameraShakeBase(WalkingShake);
}
}
void UPilotCameraShake::SetCameraShakeBase(TSubclassOf<UCameraShakeBase> ShakeBase)
{
StopAllCameraShakes();
StartCameraShake(ShakeBase);
}

View File

@ -0,0 +1,55 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Camera/CameraShakeSourceComponent.h"
#include "PilotCameraShake.generated.h"
class FMoveState;
UCLASS(Blueprintable, ClassGroup=Camera, meta=(BlueprintSpawnableComponent))
class MONOLITH_API UPilotCameraShake : public UCameraShakeSourceComponent
{
GENERATED_BODY()
enum EState{Idling, Walking, Running, Floating};
void BeginPlay() override;
bool CantUpdate();
bool isMoveStateSet() const;
bool TrySetMoveState();
UFUNCTION(BlueprintCallable)
void UpdateCameraShake();
void SetCameraShakeBase(TSubclassOf<UCameraShakeBase> ShakeBase);
FTimerHandle TickHandle;
FMoveState* MoveState;
EState CurrentState = Idling;
UPROPERTY(EditDefaultsOnly, Category = "Cam Shake", meta=(AllowPrivateAccess = "true"))
TSubclassOf<UCameraShakeBase> RunningShake;
UPROPERTY(EditDefaultsOnly, Category = "Cam Shake", meta=(AllowPrivateAccess = "true"))
TSubclassOf<UCameraShakeBase> WalkingShake;
UPROPERTY(EditDefaultsOnly, Category = "Cam Shake", meta=(AllowPrivateAccess = "true"))
TSubclassOf<UCameraShakeBase> FloatingShake;
UPROPERTY(EditDefaultsOnly, Category = "Cam Shake", meta=(AllowPrivateAccess = "true"))
TSubclassOf<UCameraShakeBase> IdleShake;
};
inline bool UPilotCameraShake::CantUpdate()
{
return !isMoveStateSet() && !TrySetMoveState();
}
inline bool UPilotCameraShake::isMoveStateSet() const
{
return MoveState != nullptr;
}

View File

@ -1,31 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "TP_PickUpComponent.h"
UTP_PickUpComponent::UTP_PickUpComponent()
{
// Setup the Sphere Collision
SphereRadius = 32.f;
}
void UTP_PickUpComponent::BeginPlay()
{
Super::BeginPlay();
// Register our Overlap Event
OnComponentBeginOverlap.AddDynamic(this, &UTP_PickUpComponent::OnSphereBeginOverlap);
}
void UTP_PickUpComponent::OnSphereBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// Checking if it is a First Person Character overlapping
AMonolithCharacter* Character = Cast<AMonolithCharacter>(OtherActor);
if(Character != nullptr)
{
// Notify that the actor is being picked up
OnPickUp.Broadcast(Character);
// Unregister from the Overlap Event so it is no longer triggered
OnComponentBeginOverlap.RemoveAll(this);
}
}

View File

@ -1,34 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/SphereComponent.h"
#include "MonolithCharacter.h"
#include "TP_PickUpComponent.generated.h"
// Declaration of the delegate that will be called when someone picks this up
// The character picking this up is the parameter sent with the notification
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPickUp, AMonolithCharacter*, PickUpCharacter);
UCLASS(Blueprintable, BlueprintType, ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MONOLITH_API UTP_PickUpComponent : public USphereComponent
{
GENERATED_BODY()
public:
/** Delegate to whom anyone can subscribe to receive this event */
UPROPERTY(BlueprintAssignable, Category = "Interaction")
FOnPickUp OnPickUp;
UTP_PickUpComponent();
protected:
/** Called when the game starts */
virtual void BeginPlay() override;
/** Code for when something overlaps this component */
UFUNCTION()
void OnSphereBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
};

View File

@ -1,119 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "TP_WeaponComponent.h"
#include "MonolithCharacter.h"
#include "MonolithProjectile.h"
#include "GameFramework/PlayerController.h"
#include "Camera/PlayerCameraManager.h"
#include "Kismet/GameplayStatics.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Animation/AnimInstance.h"
#include "Engine/LocalPlayer.h"
#include "Engine/World.h"
// Sets default values for this component's properties
UTP_WeaponComponent::UTP_WeaponComponent()
{
// Default offset from the character location for projectiles to spawn
MuzzleOffset = FVector(100.0f, 0.0f, 10.0f);
}
void UTP_WeaponComponent::Fire()
{
if (Character == nullptr || Character->GetController() == nullptr)
{
return;
}
// Try and fire a projectile
if (ProjectileClass != nullptr)
{
UWorld* const World = GetWorld();
if (World != nullptr)
{
APlayerController* PlayerController = Cast<APlayerController>(Character->GetController());
const FRotator SpawnRotation = PlayerController->PlayerCameraManager->GetCameraRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
const FVector SpawnLocation = GetOwner()->GetActorLocation() + SpawnRotation.RotateVector(MuzzleOffset);
//Set Spawn Collision Handling Override
FActorSpawnParameters ActorSpawnParams;
ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;
// Spawn the projectile at the muzzle
World->SpawnActor<AMonolithProjectile>(ProjectileClass, SpawnLocation, SpawnRotation, ActorSpawnParams);
}
}
// Try and play the sound if specified
if (FireSound != nullptr)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, Character->GetActorLocation());
}
// Try and play a firing animation if specified
if (FireAnimation != nullptr)
{
// Get the animation object for the arms mesh
UAnimInstance* AnimInstance = Character->GetMesh1P()->GetAnimInstance();
if (AnimInstance != nullptr)
{
AnimInstance->Montage_Play(FireAnimation, 1.f);
}
}
}
bool UTP_WeaponComponent::AttachWeapon(AMonolithCharacter* TargetCharacter)
{
Character = TargetCharacter;
// Check that the character is valid, and has no weapon component yet
if (Character == nullptr || Character->GetInstanceComponents().FindItemByClass<UTP_WeaponComponent>())
{
return false;
}
// Attach the weapon to the First Person Character
FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
AttachToComponent(Character->GetMesh1P(), AttachmentRules, FName(TEXT("GripPoint")));
// add the weapon as an instance component to the character
Character->AddInstanceComponent(this);
// Set up action bindings
if (APlayerController* PlayerController = Cast<APlayerController>(Character->GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
// Set the priority of the mapping to 1, so that it overrides the Jump action with the Fire action when using touch input
Subsystem->AddMappingContext(FireMappingContext, 1);
}
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerController->InputComponent))
{
// Fire
EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Triggered, this, &UTP_WeaponComponent::Fire);
}
}
return true;
}
void UTP_WeaponComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (Character == nullptr)
{
return;
}
if (APlayerController* PlayerController = Cast<APlayerController>(Character->GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->RemoveMappingContext(FireMappingContext);
}
}
}

View File

@ -1,60 +0,0 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/SkeletalMeshComponent.h"
#include "TP_WeaponComponent.generated.h"
class AMonolithCharacter;
UCLASS(Blueprintable, BlueprintType, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MONOLITH_API UTP_WeaponComponent : public USkeletalMeshComponent
{
GENERATED_BODY()
public:
/** Projectile class to spawn */
UPROPERTY(EditDefaultsOnly, Category=Projectile)
TSubclassOf<class AMonolithProjectile> ProjectileClass;
/** Sound to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
USoundBase* FireSound;
/** AnimMontage to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
UAnimMontage* FireAnimation;
/** Gun muzzle's offset from the characters location */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
FVector MuzzleOffset;
/** MappingContext */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
class UInputMappingContext* FireMappingContext;
/** Fire Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
class UInputAction* FireAction;
/** Sets default values for this component's properties */
UTP_WeaponComponent();
/** Attaches the actor to a FirstPersonCharacter */
UFUNCTION(BlueprintCallable, Category="Weapon")
bool AttachWeapon(AMonolithCharacter* TargetCharacter);
/** Make the weapon Fire a Projectile */
UFUNCTION(BlueprintCallable, Category="Weapon")
void Fire();
protected:
/** Ends gameplay for this component. */
UFUNCTION()
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
private:
/** The Character holding this weapon*/
AMonolithCharacter* Character;
};