diff --git a/.gitignore b/.gitignore index 6e0d95fb313c66ea3c2d0598f8715035397050e9..0ec8b6df4cb5c1d1c7df941d420e03319c8b038a 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ Plugins/**/Intermediate/* # Cache files for the editor to use DerivedDataCache/* +WeaponSystemBuild diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 020ee6ef45f2e16794fd7ad272303dbcd9681c0d..0e228d775ebd2f36d5328cf9d8e196d6f3055963 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -113,6 +113,8 @@ DoubleClickTime=0.200000 +ActionMappings=(ActionName="MoveUp",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=W) +ActionMappings=(ActionName="MoveDown",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=S) +ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) ++ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=F) ++ActionMappings=(ActionName="Revive",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R) DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent DefaultTouchInterface=/Game/Vehicles/Vehicle/LeftVirtualJoystickOnly.LeftVirtualJoystickOnly diff --git a/Content/Blueprints/BP_AIPawn.uasset b/Content/Blueprints/BP_AIPawn.uasset new file mode 100644 index 0000000000000000000000000000000000000000..85fae6b29b4b5ca409cceb99f913a5b4a220473b Binary files /dev/null and b/Content/Blueprints/BP_AIPawn.uasset differ diff --git a/Content/Blueprints/BP_StatePawn.uasset b/Content/Blueprints/BP_StatePawn.uasset index de18416da6b14084ba9f28f32ce831606dd0b753..a48c54d0fbe54ce534513403349702abd6afa3ee 100644 Binary files a/Content/Blueprints/BP_StatePawn.uasset and b/Content/Blueprints/BP_StatePawn.uasset differ diff --git a/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset b/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset new file mode 100644 index 0000000000000000000000000000000000000000..5506cae74a75b8619d266f96e3872fd78a7a890d Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_DefaultProjectile.uasset differ diff --git a/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset b/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset new file mode 100644 index 0000000000000000000000000000000000000000..4838f8662c564236035de5a57d64e4dd7ff73f42 Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_ExplosiveProjectile.uasset differ diff --git a/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset b/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset new file mode 100644 index 0000000000000000000000000000000000000000..2a12c40d9c94ff534a0d4591c99954e678406632 Binary files /dev/null and b/Content/Blueprints/ProjectileBPs/BP_ProjectileBPSettings.uasset differ diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset deleted file mode 100644 index f4dcfa28f1879dcbb08012ba84f59c57429aa65c..0000000000000000000000000000000000000000 Binary files a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/5/UX/X4O9TURN570CJLX950UHJ5.uasset and /dev/null differ diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset new file mode 100644 index 0000000000000000000000000000000000000000..02ee568bb33e38c48dc4207cbff83aab30e50891 Binary files /dev/null and b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/PD/ZYJ8DLKNYDI5HXR1Y7ZLWU.uasset differ diff --git a/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset new file mode 100644 index 0000000000000000000000000000000000000000..c11e2a78868bb9f9553441ebaa18997fb987b534 Binary files /dev/null and b/Content/__ExternalActors__/VehicleTemplate/Maps/VehicleAdvExampleMap/9/R5/XNB3B0O3TQYMSGYM5BCG74.uasset differ diff --git a/README.play b/README.play index a315f1ef962153900344d854dec163e5ed9d388a..eccfdf8b36f1175423fc2664ef4b79f995e9b756 100644 --- a/README.play +++ b/README.play @@ -1,30 +1,11 @@ README -Priority State Machine +Weapon System Player 1 Controls: -W - Speed Up -S - Speed Down -Space Bar - Jump +F - Fire Weapon +R - Reset Dummy HP Description: -This is a test of my priority state machine. The visuals are very rough and there are debug messages to make it clear whats happening in the background -since the cool parts of this are really buried in the code and not visually representable. - -States: -IDLE -MOVING -JUMP(IN AIR) -OVERHEAT -EXPLODE - -Conditions: -If your speed is less than 5 (magnitude) the player has an IDLE state that pulsates the scale of the cube -If speed is above 5 the player is MOVING and the cube rotates proportionally with speed - -When the player JUMPs, the JUMP state and animation overrides the idle or moving animations until the jump finishes. -When jumping the underlying movement state still exists and transitions between MOVING/IDLE but the corresponding animations are blocked - -If your speed is over 100 while not jumping the cube starts to OVERHEAT -OVERHEAT can coexist with MOVING and JUMP and changes the color of the cube to be more red the longer its overheating while allowing other animations to play -If you OVERHEAT for too long the cube EXPLODEs, the cube turns black and its game over. +This is my weapon system. Its built in the same project as my state machine and uses the state machine for weapon cds and health states. +The dummy will turn red when it gets injured and then black when it dies. There are also debug messages for its hp number. diff --git a/Source/State_Machine/Private/AIControlledPawn.cpp b/Source/State_Machine/Private/AIControlledPawn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db2caebd7ff4e9f5c1c1ff206b5bb7955f4b1b07 --- /dev/null +++ b/Source/State_Machine/Private/AIControlledPawn.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AIControlledPawn.h" + diff --git a/Source/State_Machine/Private/AoeWeapon.cpp b/Source/State_Machine/Private/AoeWeapon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fe3fe2de1f7a70a952e47a727af7dfc804ed532 --- /dev/null +++ b/Source/State_Machine/Private/AoeWeapon.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AoeWeapon.h" + +AoeWeapon* AoeWeapon::instance = nullptr; + +void AoeWeapon::Fire(PawnController* controller) +{ + FireAOE(controller, radius); +} diff --git a/Source/State_Machine/Private/ControlledPawn.cpp b/Source/State_Machine/Private/ControlledPawn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f219576eb12f0b290a623e5890e5796b2be411ef --- /dev/null +++ b/Source/State_Machine/Private/ControlledPawn.cpp @@ -0,0 +1,120 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ControlledPawn.h" + +#include "PawnController.h" + +// Sets default values +AControlledPawn::AControlledPawn() : + myController(new PawnController(this)) +{ + // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; +} + +AControlledPawn::~AControlledPawn() +{ + if (myController) + { + delete myController; + } +} + +// Called when the game starts or when spawned +void AControlledPawn::BeginPlay() +{ + Super::BeginPlay(); + + myBP = Cast<UObject>(this); + + if (myBP) + { + BPOverheat = myBP->FindFunction(TEXT("Overheat")); + } +} + +// Called every frame +void AControlledPawn::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + + // Hacked in jump logic + if (jumping) + { + height += DeltaTime * 150; + if (height > jumpHeight) + { + jumping = false; + } + } + else if (height > 0) + { + height -= DeltaTime * 150; + } + + //GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("Speed: %f"), speed)); + //GEngine->AddOnScreenDebugMessage(3, 10, FColor::Green, FString::Printf(TEXT("Height: %f"), height)); + + myController->TickController(DeltaTime); +} + +// Called to bind functionality to input +void AControlledPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); + +} + +void AControlledPawn::SetOverheatPercent(float percent) +{ + overheadPercent = percent; + + // update color + if (myBP && BPOverheat) + { + myBP->ProcessEvent(BPOverheat, nullptr); + } +} + +void AControlledPawn::Explode() +{ + hasExploded = true; + speed = 0; + height = 0; + jumping = false; + + // update color + if (myBP && BPOverheat) + { + myBP->ProcessEvent(BPOverheat, nullptr); + } +} + +void AControlledPawn::UnExplode() +{ + hasExploded = false; + overheadPercent = 0; + + // update color + if (myBP && BPOverheat) + { + myBP->ProcessEvent(BPOverheat, nullptr); + } +} + +void AControlledPawn::FireWeapon(int idx) +{ + myController->FireWeapon(idx); +} + +void AControlledPawn::ReleaseFireWeapon(int idx) +{ + myController->ReleaseFireWeapon(idx); +} + +void AControlledPawn::Revive() +{ + myController->Revive(); +} diff --git a/Source/State_Machine/Private/DeadState.cpp b/Source/State_Machine/Private/DeadState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba1004977ef0bd1eff6b8eb4f8de0511587f2d42 --- /dev/null +++ b/Source/State_Machine/Private/DeadState.cpp @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "DeadState.h" + +#include "BlackboardVariableNames.h" +#include "StateMachine.h" + +#include "HealthyState.h" + +void DeadState::EnterState() +{ + myController->Explode(); + GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Dead")); + + StateObject::EnterState(); +} + +StateObject* DeadState::Update(float dt) +{ + float val; + if (myMachine->RemoveValueFromBoard(REVIVE, val)) + { + ExitState(); + StateObject* healthyState = new HealthyState(myMachine, myController, maxHP, maxHP); + return healthyState; + } + + return this; +} + +StateObject* DeadState::UpdateBlocked(float dt) +{ + return this; +} + +void DeadState::ExitState() +{ + myController->UnExplode(); + GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Revived")); + + StateObject::ExitState(); +} diff --git a/Source/State_Machine/Private/DefaultProjectile.cpp b/Source/State_Machine/Private/DefaultProjectile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd55b141355e7c6849c1cea8c377d478058fd82a --- /dev/null +++ b/Source/State_Machine/Private/DefaultProjectile.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "DefaultProjectile.h" + +#include "ControlledPawn.h" + +void DefaultProjectile::ProjectileTick(float dt) +{} + +void DefaultProjectile::HandleOverlap(AActor* other, bool isOverlap) +{ + + AControlledPawn* hitPawn = Cast<AControlledPawn>(other); + if (hitPawn) + { + HitPlayer(hitPawn->GetPawnController()); + } + + GetActor()->Destroy(); + +} \ No newline at end of file diff --git a/Source/State_Machine/Private/ExplodeState.cpp b/Source/State_Machine/Private/ExplodeState.cpp deleted file mode 100644 index ac74d6a1893ffe511d3f401eddfeae9fc97f7ef4..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Private/ExplodeState.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "ExplodeState.h" - -#include "StatePawn.h" - -void ExplodeState::EnterState() -{ - hasStarted = true; - myPawn->Explode(); -} - -// Trap us in this state by always returning self -StateObject* ExplodeState::Update(float dt) -{ - return this; -} - -StateObject* ExplodeState::UpdateBlocked(float dt) -{ - return this; -} diff --git a/Source/State_Machine/Private/ExplosiveProjectile.cpp b/Source/State_Machine/Private/ExplosiveProjectile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a80baedcd1b39602cde52822c01207bf321e672 --- /dev/null +++ b/Source/State_Machine/Private/ExplosiveProjectile.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ExplosiveProjectile.h" + +void ExplosiveProjectile::ProjectileTick(float dt) +{ +} + +void ExplosiveProjectile::HandleOverlap(AActor* other, bool isOverlap) +{ + TriggerExplosion(100); + + GetActor()->Destroy(); +} diff --git a/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp b/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..233f26f0a888dcd97360934d92bd7ec7e1783986 --- /dev/null +++ b/Source/State_Machine/Private/ExplosiveProjectileWeapon.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ExplosiveProjectileWeapon.h" + +#include "ExplosiveProjectile.h" + +ExplosiveProjectileWeapon* ExplosiveProjectileWeapon::instance = nullptr; + +void ExplosiveProjectileWeapon::Fire(PawnController* controller) +{ + ExplosiveProjectile* projectileController = new ExplosiveProjectile(controller); + + FireProjectile(projectileController, FVector(3000, 0, 1000)); +} diff --git a/Source/State_Machine/Private/HealthState.cpp b/Source/State_Machine/Private/HealthState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eba8b583b129589aa786229350be59cc927a27e4 --- /dev/null +++ b/Source/State_Machine/Private/HealthState.cpp @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HealthState.h" + +#include "StateMachine.h" + +#include "BlackboardVariableNames.h" + +StateObject* HealthState::Update(float dt) +{ + float dmg; + if (myMachine->GetValueFromBoard(DAMAGE, dmg)) + { + currentHP -= dmg; + myMachine->PutValueOnBoard(DAMAGE, 0); + } + + GEngine->AddOnScreenDebugMessage(0, 10, FColor::Red, FString::Printf(TEXT("HP is ")) + std::to_string(currentHP).c_str() + " out of " + std::to_string(maxHP).c_str()); + myController->SetOverheatPercent(1 - (currentHP / maxHP)); + + return this; +} diff --git a/Source/State_Machine/Private/HealthyState.cpp b/Source/State_Machine/Private/HealthyState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ab25b9a7f2b4c2fb0b106a82705ea91bbdb6797 --- /dev/null +++ b/Source/State_Machine/Private/HealthyState.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HealthyState.h" + +#include "DeadState.h" +#include "LowHealthState.h" + +StateObject* HealthyState::Update(float dt) +{ + // Do this to update health automatically + HealthState::Update(dt); + + if (currentHP <= 0) + { + ExitState(); + StateObject* deadState = new DeadState(myMachine, myController, maxHP); + return deadState; + } + else if ((currentHP / maxHP) <= HealthState::LowPercentLimit) + { + ExitState(); + StateObject* lowState = new LowHealthState(myMachine, myController, currentHP, maxHP); + return lowState; + } + + return this; +} + +StateObject* HealthyState::UpdateBlocked(float dt) +{ + return this; +} diff --git a/Source/State_Machine/Private/IdleState.cpp b/Source/State_Machine/Private/IdleState.cpp deleted file mode 100644 index 11be6a1bdd4b2603b4f82288e0730c88b74edfc5..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Private/IdleState.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "IdleState.h" - -#include "StatePawn.h" -#include "MovingState.h" -#include "JumpState.h" - -StateObject* IdleState::Update(float dt) -{ - // TODO: something for jump - if (myPawn->GetHeight() > 0) - { - // Add a jumpstate to the stack, doesnt replace this - JumpState* newState = new JumpState(myMachine, myPawn); - return newState; - } - - // If we have started moving faster than the transtition speed return a moving state - if (abs(myPawn->GetSpeed()) > transitionSpeed) - { - ExitState(); - MovingState* newState = new MovingState(myMachine, myPawn); - newState->setMinTransitionSpeed(transitionSpeed); - return newState; - } - - timer += dt; - float scale = 1.f + (sin(timer * 2.5f) * 0.5f); - - myPawn->SetActorScale3D(FVector(scale)); - - return this; -} - -StateObject* IdleState::UpdateBlocked(float dt) -{ - // If we have started moving faster than the transtition speed return a moving state - if (abs(myPawn->GetSpeed()) > transitionSpeed) - { - ExitState(); - MovingState* newState = new MovingState(myMachine, myPawn); - newState->setMinTransitionSpeed(transitionSpeed); - return newState; - } - - return this; -} - -void IdleState::ExitState() -{ - myPawn->SetActorScale3D(FVector(1.f)); - shouldRemove = true; - -} - diff --git a/Source/State_Machine/Private/JumpState.cpp b/Source/State_Machine/Private/JumpState.cpp deleted file mode 100644 index b9e9b0e129a190dc0ffc55e4961e0d9762cd2099..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Private/JumpState.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "JumpState.h" - -#include "StatePawn.h" - -StateObject* JumpState::Update(float dt) -{ - myPawn->SetActorLocation(FVector(0, 0, myPawn->GetHeight())); - - if (myPawn->GetHeight() <= 0) - { - ExitState(); - return nullptr; - } - - return this; -} - -StateObject* JumpState::UpdateBlocked(float dt) -{ - return this; -} diff --git a/Source/State_Machine/Private/LaserWeapon.cpp b/Source/State_Machine/Private/LaserWeapon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f87e5f82c582d2166cd55b665aa2a38afcef8f5c --- /dev/null +++ b/Source/State_Machine/Private/LaserWeapon.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LaserWeapon.h" + +LaserWeapon* LaserWeapon::instance = nullptr; + +void LaserWeapon::Fire(PawnController* controller) +{ + FireLaser(controller, radius, maxDist, false); +} diff --git a/Source/State_Machine/Private/LowHealthState.cpp b/Source/State_Machine/Private/LowHealthState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b17fe2775cac33c6a9bf876b4d34fb9462a717ef --- /dev/null +++ b/Source/State_Machine/Private/LowHealthState.cpp @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LowHealthState.h" + +#include "DeadState.h" +#include "HealthyState.h" + +StateObject* LowHealthState::Update(float dt) +{ + // Do this to update health automatically + HealthState::Update(dt); + + GEngine->AddOnScreenDebugMessage(5, 10, FColor::Red, TEXT("Low")); + + if (currentHP <= 0) + { + ExitState(); + StateObject* deadState = new DeadState(myMachine, myController, maxHP); + return deadState; + + } + else if ((currentHP / maxHP) > HealthState::LowPercentLimit) + { + ExitState(); + StateObject* healthyState = new HealthyState(myMachine, myController, currentHP, maxHP); + return healthyState; + } + + return this; +} + +StateObject* LowHealthState::UpdateBlocked(float dt) +{ + return this; +} diff --git a/Source/State_Machine/Private/MovingState.cpp b/Source/State_Machine/Private/MovingState.cpp deleted file mode 100644 index ed3e7b573aece29203c5f67afed0e48dd261b6d7..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Private/MovingState.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "MovingState.h" - -#include "StatePawn.h" -#include "StateMachine.h" -#include "IdleState.h" -#include "OverheatState.h" -#include "JumpState.h" - -StateObject* MovingState::Update(float dt) -{ - myPawn->AddActorLocalRotation(FRotator(0, 3 * myPawn->GetSpeed() * dt, 0)); - - // Jumping doesn't stop movement - // We dont have to check for existing ones because jump blocks this update - if (myPawn->GetHeight() > 0) - { - // Add a jumpstate to the stack - JumpState* newState = new JumpState(myMachine, myPawn); - return newState; - } - - - // If we have started moving slower than the transtition speed return an idle state - if (abs(myPawn->GetSpeed()) < minTransitionSpeed) - { - ExitState(); - IdleState* newState = new IdleState(myMachine, myPawn, GetPriority()); - newState->setTransitionSpeed(minTransitionSpeed); - return newState; - } - - // Check if there is an existing overheat state already before creating. - if (myPawn->GetSpeed() > overheatSpeed && !(myMachine->HasState(StateTypes::OVERHEATING))) - { - // Add an overheat state to the machine - // Dont exit this state - OverheatState* newState = new OverheatState(myMachine, myPawn); - return newState; - } - - return this; -} - -StateObject* MovingState::UpdateBlocked(float dt) -{ - // We can still transition to idle when blocked - // If we have started moving slower than the transtition speed return an idle state - if (abs(myPawn->GetSpeed()) < minTransitionSpeed) - { - ExitState(); - IdleState* newState = new IdleState(myMachine, myPawn); - newState->setTransitionSpeed(minTransitionSpeed); - return newState; - } - - return this; -} \ No newline at end of file diff --git a/Source/State_Machine/Private/OverheatState.cpp b/Source/State_Machine/Private/OverheatState.cpp deleted file mode 100644 index acf7825464493262708feddeccc9b90634431fb8..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Private/OverheatState.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "OverheatState.h" - -#include "ExplodeState.h" -#include "StatePawn.h" - -StateObject* OverheatState::Update(float dt) -{ - - if (myPawn->GetSpeed() < overheatSpeed) - { - ExitState(); - // Tell the state machine to get rid of this - return nullptr; - } - - timeOverheated += dt; - - myPawn->SetOverheatPercent(timeOverheated / explodeTime); - - if (timeOverheated > explodeTime) - { - ExitState(); - ExplodeState* newState = new ExplodeState(myMachine, myPawn); - return newState; - } - - return this; -} - -StateObject* OverheatState::UpdateBlocked(float dt) -{ - // Dont tick the timer if this is blocked - return this; -} - -void OverheatState::ExitState() -{ - shouldRemove = true; - - myPawn->SetOverheatPercent(0); -} diff --git a/Source/State_Machine/Private/PawnController.cpp b/Source/State_Machine/Private/PawnController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f08f70aaec456715090a689e407be7d441387ce9 --- /dev/null +++ b/Source/State_Machine/Private/PawnController.cpp @@ -0,0 +1,80 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PawnController.h" + +#include "BlackboardVariableNames.h" + +#include "WeaponReadyState.h" + +#include "AoeWeapon.h" +#include "LaserWeapon.h" +#include "ProjectileWeapon.h" +#include "ExplosiveProjectileWeapon.h" + +#include "HealthyState.h" + +#include "AIControlledPawn.h" + +PawnController::PawnController(AControlledPawn* controlledPawn) : + myPawn(controlledPawn), + myStateMachine(), + myWeapons() +{ + // Initialize queue with an idle state + //myStateMachine.AddState(new IdleState(&myStateMachine, this)); + //AddWeapon(AoeWeapon::GetWeaponInstance()); + //AddWeapon(LaserWeapon::GetWeaponInstance()); + AddWeapon(ExplosiveProjectileWeapon::GetWeaponInstance()); + + + + AAIControlledPawn* aiPawn = Cast<AAIControlledPawn>(controlledPawn); + + if (aiPawn) + { + myStateMachine.AddState(new HealthyState(&myStateMachine, this, 50, 50)); + } +} + +void PawnController::TickController(float DeltaTime) +{ + + myStateMachine.Update(DeltaTime); +} + +void PawnController::AddWeapon(WeaponType* type) +{ + if (!myWeapons.Contains(type)) + { + myWeapons.Add(type); + myStateMachine.AddState(new WeaponReadyState(&myStateMachine, this, type)); + } +} + +void PawnController::FireWeapon(int idx) +{ + if (myWeapons.IsValidIndex(idx)) + { + myStateMachine.PutValueOnBoard(FIREINPUT, 1.f); + } +} + +void PawnController::ReleaseFireWeapon(int idx) +{ + if (myWeapons.IsValidIndex(idx)) + { + myStateMachine.PutValueOnBoard(FIREINPUT, 0); + } +} + +void PawnController::Revive() +{ + myStateMachine.PutValueOnBoard(REVIVE, 1); +} + +void PawnController::ApplyHit(HitInfo hitInfo) +{ + //GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, myPawn->GetName() + " took " + std::to_string(hitInfo.damage).c_str() + " damage"); + myStateMachine.PutValueOnBoard(DAMAGE, hitInfo.damage); +} diff --git a/Source/State_Machine/Private/ProjectileActor.cpp b/Source/State_Machine/Private/ProjectileActor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99ee54ccfb5b868bfc14f55e87dce9ae7a24e32c --- /dev/null +++ b/Source/State_Machine/Private/ProjectileActor.cpp @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ProjectileActor.h" + +#include "ProjectileController.h" + +#include "Kismet/GameplayStatics.h" + +// Sets default values +AProjectileActor::AProjectileActor() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; +} + +// Called when the game starts or when spawned +void AProjectileActor::BeginPlay() +{ + Super::BeginPlay(); + + physicsComponent = Cast<UPrimitiveComponent>(GetRootComponent()); + if (physicsComponent) + { + physicsComponent->SetSimulatePhysics(true); + + physicsComponent->OnComponentBeginOverlap.AddDynamic(this, &AProjectileActor::OnOverlapBegin); + } +} + +void AProjectileActor::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + // Cleanup our controller + if (pController) + { + delete pController; + } +} + +// Called every frame +void AProjectileActor::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + if (pController) + { + pController->ProjectileTick(DeltaTime); + } + +} + +void AProjectileActor::NotifyHit(UPrimitiveComponent* MyComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) +{ + Super::NotifyHit(MyComp, OtherActor, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit); + + if (pController) + { + pController->HandleOverlap(OtherActor, false); + } +} + +void AProjectileActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if (pController) + { + pController->HandleOverlap(OtherActor, true); + } +} + diff --git a/Source/State_Machine/Private/ProjectileBPHolder.cpp b/Source/State_Machine/Private/ProjectileBPHolder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91a2d3faf73526a7fa46395f1d881a619ef81089 --- /dev/null +++ b/Source/State_Machine/Private/ProjectileBPHolder.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ProjectileBPHolder.h" + +// Sets default values +AProjectileBPHolder::AProjectileBPHolder() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + diff --git a/Source/State_Machine/Private/ProjectileController.cpp b/Source/State_Machine/Private/ProjectileController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31ffee5267d8365b3b43ec839e0345a63a7426cd --- /dev/null +++ b/Source/State_Machine/Private/ProjectileController.cpp @@ -0,0 +1,111 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ProjectileController.h" + +#include "WeaponType.h" +#include "PawnController.h" + +#include "ProjectileBPHolder.h" + +#include "Kismet/GameplayStatics.h" + +// SubType includes for spawning + + +TSubclassOf<AProjectileActor> ProjectileController::GetBPToSpawn() +{ + AProjectileBPHolder* bpHolder = Cast<AProjectileBPHolder>(UGameplayStatics::GetActorOfClass(myController->GetControlledPawn()->GetWorld(), AProjectileBPHolder::StaticClass())); + + if (bpHolder) + { + for (FProjectilePairing pair : bpHolder->pairingList) + { + if (pair.type == type) + { + return pair.bpClass; + } + } + } + + return nullptr; +} + +ProjectileController::ProjectileController(PawnController* i_controller) : + myController(i_controller) +{} + +ProjectileController::~ProjectileController() +{ + if (!myActor) + { + myActor->Destroy(); + } +} + +AProjectileActor* ProjectileController::GetActor() +{ + if (!myActor) + { + FVector spawnLocation = myController->GetControlledPawn()->GetActorLocation() + (myController->GetControlledPawn()->GetActorForwardVector() * 100); + TSubclassOf<AProjectileActor> spawnClass = GetBPToSpawn(); + + if (spawnClass != nullptr) + { + myActor = myController->GetControlledPawn()->GetWorld()->SpawnActor<AProjectileActor>(spawnClass, spawnLocation, FRotator()); + + if (myActor) + { + myActor->SetProjectileController(this); + } + } + } + return myActor; +} + +void ProjectileController::TriggerExplosion(float radius) +{ + DrawDebugSphere(myActor->GetWorld(), myActor->GetActorLocation(), radius, 12, FColor::Red, false, 2); + + FCollisionQueryParams params; + params.AddIgnoredActor(myActor); + + TArray<FHitResult> hitResults; + + bool hasHit = myActor->GetWorld()->SweepMultiByChannel( + hitResults, + myActor->GetActorLocation(), + myActor->GetActorLocation(), // End at self since this is just an aoe + FQuat::Identity, + ECC_Visibility, + FCollisionShape::MakeSphere(radius), + params + ); + + if (hasHit) + { + for (FHitResult hit : hitResults) + { + AActor* hitActor = hit.GetActor(); + + AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor); + if (hitPawn) + { + + HitPlayer(hitPawn->GetPawnController()); + GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Explosion Hit " + hitPawn->GetName())); + DrawDebugSphere(myActor->GetWorld(), hit.ImpactPoint, 10.f, 12, FColor::Red, false, 5.0f); + } + } + } +} + +void ProjectileController::HitPlayer(PawnController* controller) +{ + HitInfo info; + info.appliedEffects; + info.damage = baseDamage; + info.originator = myController; + + controller->ApplyHit(info); +} diff --git a/Source/State_Machine/Private/ProjectileWeapon.cpp b/Source/State_Machine/Private/ProjectileWeapon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91f0cac908131ebaafb79a736ae0d6905a757e44 --- /dev/null +++ b/Source/State_Machine/Private/ProjectileWeapon.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ProjectileWeapon.h" + +#include "DefaultProjectile.h" + +ProjectileWeapon* ProjectileWeapon::instance = nullptr; + +void ProjectileWeapon::Fire(PawnController* controller) +{ + DefaultProjectile* projectileController = new DefaultProjectile(controller); + + FireProjectile(projectileController, FVector(3000, 0, 1000)); +} diff --git a/Source/State_Machine/Private/StateMachine.cpp b/Source/State_Machine/Private/StateMachine.cpp index 1a8f7462d14508e56a9812903886e3ed0e28720e..9897384aa18ce80a909466e891d6263609af60f1 100644 --- a/Source/State_Machine/Private/StateMachine.cpp +++ b/Source/State_Machine/Private/StateMachine.cpp @@ -3,16 +3,12 @@ #include "StateMachine.h" -#include "IdleState.h" +#include "BlackboardVariableNames.h" -StateMachine::StateMachine(AStatePawn* i_pawn) : - myPawn(i_pawn), +StateMachine::StateMachine() : stateQueue(new std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>()), backupQueue(new std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>()) -{ - // Initialize queue with an idle state - stateQueue->push(new IdleState(this, i_pawn)); -} +{} StateMachine::~StateMachine() { @@ -40,9 +36,12 @@ StateMachine::~StateMachine() } -void StateMachine::ProcessInput() +void StateMachine::ProcessInput(InputStruct i_struct) { - + PutValueOnBoard(ACCELERATIONINPUT, i_struct.accel); + PutValueOnBoard(BRAKEINPUT, i_struct.brake); + PutValueOnBoard(STEERINPUT, i_struct.steering); + PutValueOnBoard(FIRINGINPUT, (float)i_struct.firing); } void StateMachine::Update(float dt) @@ -116,9 +115,8 @@ void StateMachine::Update(float dt) state->EnterState(); } - // Add the states this blocks and removes to our bit maps - blocked = blocked | state->GetBlockMap(); - toRemove = toRemove | state->GetRemoveMap(); + uint16 stateBlockMap = state->GetBlockMap(); + uint16 stateRemoveMap = state->GetRemoveMap(); // Add to active state map if we process this state tempActiveStatesMap = tempActiveStatesMap | GetStateBitMap(state->GetType()); @@ -159,7 +157,10 @@ void StateMachine::Update(float dt) { delete state; } - + + // Add the states the processed state blocks and removes to our bit maps + blocked = blocked | stateBlockMap; + toRemove = toRemove | stateRemoveMap; } // Swap state queue and backup queue. State queue should always be empty here @@ -169,4 +170,59 @@ void StateMachine::Update(float dt) activeStatesMap = tempActiveStatesMap; existingStatesMap = tempExistingStatesMap; -} \ No newline at end of file +} + +void StateMachine::AddState(StateObject* state) +{ + stateQueue->emplace(state); +} + +void StateMachine::PutValueOnBoard(const std::string string, float value) +{ + if (myBlackboard.contains(string)) + { + myBlackboard.at(string) = value; + } + else + { + myBlackboard.emplace(string, value); + } +} + +bool StateMachine::GetValueFromBoard(const std::string string, float& o_value) +{ + if (myBlackboard.contains(string)) + { + o_value = myBlackboard.at(string); + return true; + } + + return false; +} + +bool StateMachine::RemoveValueFromBoard(const std::string string, float& o_value) +{ + if (myBlackboard.contains(string)) + { + o_value = myBlackboard.at(string); + myBlackboard.erase(string); + return true; + } + + return false; +} + +void StateMachine::AddToValueOnBoard(const std::string string, float value, float& o_value) +{ + if (myBlackboard.contains(string)) + { + myBlackboard.at(string) += value; + } + else + { + myBlackboard.emplace(string, value); + + } + + o_value = myBlackboard.at(string); +} diff --git a/Source/State_Machine/Private/StateMachine.h b/Source/State_Machine/Private/StateMachine.h index c94a546e97845c1dd38d224b60005d6e22acdffd..b9c29957924ebce3d71fdedaf63aaeef8a26f891 100644 --- a/Source/State_Machine/Private/StateMachine.h +++ b/Source/State_Machine/Private/StateMachine.h @@ -4,35 +4,48 @@ #include "CoreMinimal.h" +#include "PawnController.h" + #include "StateObject.h" +#include "InputDefinitions.h" + #include <queue> +#include <unordered_map> +#include <string> + class STATE_MACHINE_API StateMachine { public: - StateMachine() {} - - StateMachine(AStatePawn* i_pawn); + StateMachine(); ~StateMachine(); - void ProcessInput(); + void ProcessInput(InputStruct i_struct); void Update(float dt); - bool HasActiveState(StateTypes type) { return activeStatesMap & GetStateBitMap(type); } + void AddState(StateObject* state); + bool HasActiveState(StateTypes type) { return activeStatesMap & GetStateBitMap(type); } // Use this to check before creating duplicate states if needed bool HasState(StateTypes type) { return existingStatesMap & GetStateBitMap(type); } StateObject* GetHighestPriorityState() { return stateQueue->top(); } float getNumStates() { return stateQueue->size(); } -private: - AStatePawn* myPawn = nullptr; + // Put or replace existing value on board under this string name + void PutValueOnBoard(const std::string string, float value); + // Add this value to the current one under this string name, This will create a new value if one doesnt exist + void AddToValueOnBoard(const std::string string, float value, float& o_value); + bool GetValueFromBoard(const std::string string, float& o_value); + bool RemoveValueFromBoard(const std::string string, float& o_value); +private: std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>* stateQueue = nullptr; std::priority_queue<StateObject*, std::vector<StateObject*>, StateComparer>* backupQueue = nullptr; + std::unordered_map<std::string, float> myBlackboard; + // This is a bitmask for the processed Active states as of last frame uint16 activeStatesMap = 0x00; diff --git a/Source/State_Machine/Private/StatePawn.cpp b/Source/State_Machine/Private/StatePawn.cpp index 35a6bf36ea41fa690f3b7a5d826f19bd63fa3eb1..320a6b89fa029f2999724f9f5220646ff6055c8f 100644 --- a/Source/State_Machine/Private/StatePawn.cpp +++ b/Source/State_Machine/Private/StatePawn.cpp @@ -3,41 +3,33 @@ #include "StatePawn.h" +#include "PawnController.h" + #include "Kismet/GameplayStatics.h" #include "Camera\CameraActor.h" +#include "Camera/CameraComponent.h" #include "Components/StaticMeshComponent.h" -// Sets default values -AStatePawn::AStatePawn() : myStateMachine(this) -{ - // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. - PrimaryActorTick.bCanEverTick = true; - -} +#include "Kismet/GameplayStatics.h" // Called when the game starts or when spawned void AStatePawn::BeginPlay() { Super::BeginPlay(); - - myBP = Cast<UObject>(this); - - if (myBP) - { - BPOverheat = myBP->FindFunction(TEXT("Overheat")); - } // Spawn and setup camera { FVector CameraSpawnLocation = FVector(-600, 0, 400.f); FRotator CameraSpawnRotation = FRotator(-20.f, 0.f, 0.f); - SetActorLocation(FVector(0,0,0)); + SetActorLocation(FVector(0,0,50)); ACameraActor* camera = GetWorld()->SpawnActor<ACameraActor>(CameraSpawnLocation, CameraSpawnRotation); if (camera) { + camera->GetCameraComponent()->bConstrainAspectRatio = false; + APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0); // Player 0 if (PlayerController) { @@ -53,115 +45,19 @@ void AStatePawn::BeginPlay() } -// Called every frame -void AStatePawn::Tick(float DeltaTime) -{ - Super::Tick(DeltaTime); - - // Hacked in jump logic - if (jumping) - { - height += DeltaTime * 150; - if (height > jumpHeight) - { - jumping = false; - } - } - else if (height > 0) - { - height -= DeltaTime * 150; - } - - - myStateMachine.Update(DeltaTime); - - { - FString stateString(TEXT("Active States:")); - for (uint8 i = 0; i < StateTypes::NUM_STATES; i++) - { - if (myStateMachine.HasActiveState((StateTypes)i)) - { - switch ((StateTypes)i) - { - case StateTypes::IDLE: - stateString.Append(TEXT("\nIDLE")); - break; - - case StateTypes::MOVING: - stateString.Append(TEXT("\nMOVING")); - break; - - case StateTypes::INAIR: - stateString.Append(TEXT("\nIN AIR")); - break; - - case StateTypes::OVERHEATING: - stateString.Append(TEXT("\nOVERHEATING")); - break; - - case StateTypes::EXPLODING: - stateString.Append(TEXT("\nEXPLODED")); - break; - - default: - break; - } - } - } - GEngine->AddOnScreenDebugMessage(0, 10, FColor::Red, stateString); - } - - { - FString stateString(TEXT("Blocked States:")); - for (uint8 i = 0; i < StateTypes::NUM_STATES; i++) - { - if (!myStateMachine.HasActiveState((StateTypes)i) && myStateMachine.HasState((StateTypes)i)) - { - switch ((StateTypes)i) - { - case StateTypes::IDLE: - stateString.Append(TEXT("\nIDLE")); - break; - - case StateTypes::MOVING: - stateString.Append(TEXT("\nMOVING")); - break; - - case StateTypes::INAIR: - stateString.Append(TEXT("\nIN AIR")); - break; - - case StateTypes::OVERHEATING: - stateString.Append(TEXT("\nOVERHEATING")); - break; - - case StateTypes::EXPLODING: - stateString.Append(TEXT("\nEXPLODED")); - break; - - default: - break; - } - } - } - GEngine->AddOnScreenDebugMessage(1, 10, FColor::Red, stateString); - } - - - GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("Speed: %f"), speed)); - GEngine->AddOnScreenDebugMessage(3, 10, FColor::Green, FString::Printf(TEXT("Height: %f"), height)); - GEngine->AddOnScreenDebugMessage(4, 10, FColor::Orange, FString::Printf(TEXT("States in Queue: %f"), myStateMachine.getNumStates())); -} - // Called to bind functionality to input void AStatePawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); - PlayerInputComponent->BindAction("MoveUp", IE_Pressed, this, &AStatePawn::MoveUp); - PlayerInputComponent->BindAction("MoveDown", IE_Pressed, this, &AStatePawn::MoveDown); - PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AStatePawn::Jump); + //PlayerInputComponent->BindAction("MoveUp", IE_Pressed, this, &AStatePawn::MoveUp); + //PlayerInputComponent->BindAction("MoveDown", IE_Pressed, this, &AStatePawn::MoveDown); + //PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AStatePawn::Jump); + PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AStatePawn::PressFire); + PlayerInputComponent->BindAction("Fire", IE_Released, this, &AStatePawn::ReleaseFire); + + PlayerInputComponent->BindAction("Revive", IE_Pressed, this, &AStatePawn::TriggerRevive); } void AStatePawn::MoveUp() @@ -179,27 +75,26 @@ void AStatePawn::Jump() jumping = true; } -void AStatePawn::SetOverheatPercent(float percent) +void AStatePawn::PressFire() { - overheadPercent = percent; - - // update color - if (myBP && BPOverheat) - { - myBP->ProcessEvent(BPOverheat, nullptr); - } + FireWeapon(0); } -void AStatePawn::Explode() +void AStatePawn::ReleaseFire() { - hasExploded = true; - speed = 0; - height = 0; - jumping = false; + ReleaseFireWeapon(0); +} - // update color - if (myBP && BPOverheat) +void AStatePawn::TriggerRevive() +{ + TArray<AActor*> pawnArray; + UGameplayStatics::GetAllActorsOfClass(GetWorld(), AControlledPawn::StaticClass(), pawnArray); + for (AActor* actor : pawnArray) { - myBP->ProcessEvent(BPOverheat, nullptr); + AControlledPawn* pawn = Cast<AControlledPawn>(actor); + if (pawn && pawn != this) + { + pawn->Revive(); + } } } diff --git a/Source/State_Machine/Private/TargetedWeapon.cpp b/Source/State_Machine/Private/TargetedWeapon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..817f21b5e65988554e19bc09537b68f445559122 --- /dev/null +++ b/Source/State_Machine/Private/TargetedWeapon.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "TargetedWeapon.h" + +TargetedWeapon* TargetedWeapon::instance = nullptr; + +void TargetedWeapon::Fire(PawnController* controller) +{ + FireTargeted(controller, nullptr); +} diff --git a/Source/State_Machine/Private/WeaponCooldownState.cpp b/Source/State_Machine/Private/WeaponCooldownState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d51eb6f6dba4744c2e61d1620b535bf0ba0a4ffa --- /dev/null +++ b/Source/State_Machine/Private/WeaponCooldownState.cpp @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WeaponCooldownState.h" + +#include "WeaponReadyState.h" + +StateObject* WeaponCooldownState::Update(float dt) +{ + timer += dt; + + GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Cooling down")); + + if (timer > myType->GetCooldown()) + { + + ExitState(); + WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType); + return newState; + } + + return this; +} + +StateObject* WeaponCooldownState::UpdateBlocked(float dt) +{ + // Blocking does not stop timer ticking + timer += dt; + + return this; +} diff --git a/Source/State_Machine/Private/WeaponFireState.cpp b/Source/State_Machine/Private/WeaponFireState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d5aeb6a9d15a99c0312c686f389b6b26cd633b0 --- /dev/null +++ b/Source/State_Machine/Private/WeaponFireState.cpp @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WeaponFireState.h" + +#include "WeaponWinddownState.h" +#include "WeaponCooldownState.h" +#include "WeaponReadyState.h" + +StateObject* WeaponFireState::Update(float dt) +{ + timer += dt; + + myType->Fire(myController); + + GEngine->AddOnScreenDebugMessage(12, 10, FColor::Red, TEXT("Weapon Firing")); + + if (timer > myType->GetFireTime()) + { + // Check to see if we have a winddown to transition to + if (myType->GetWinddownTime() > 0) + { + ExitState(); + WeaponWinddownState* newState = new WeaponWinddownState(myMachine, myController, myType); + return newState; + } + else + { + // Check if we have a cooldown time + if (myType->GetCooldown() > 0) + { + ExitState(); + WeaponCooldownState* newState = new WeaponCooldownState(myMachine, myController, myType); + return newState; + } + else + { + ExitState(); + WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType); + return newState; + } + } + + } + + return this; +} + +StateObject* WeaponFireState::UpdateBlocked(float dt) +{ + // Blocking does not stop fire timer, just the actual firing + timer += dt; + + return this; +} diff --git a/Source/State_Machine/Private/WeaponReadyState.cpp b/Source/State_Machine/Private/WeaponReadyState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcae54dd95753e6dd2e7efc0c8ea4b47ad7dc20e --- /dev/null +++ b/Source/State_Machine/Private/WeaponReadyState.cpp @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WeaponReadyState.h" + +#include "BlackboardVariableNames.h" + +#include "StateMachine.h" + +#include "WeaponWindupState.h" +#include "WeaponFireState.h" + +StateObject* WeaponReadyState::Update(float dt) +{ + float input; + if (myMachine->GetValueFromBoard(FIREINPUT, input)) + { + GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Ready To Fire")); + if (input > 0) + { + // spawn next state + if (myType->GetWindupTime() > 0) + { + ExitState(); + WeaponWindupState* newState = new WeaponWindupState(myMachine, myController, myType); + return newState; + } + else + { + ExitState(); + WeaponFireState* newState = new WeaponFireState(myMachine, myController, myType); + return newState; + } + } + } + + return this; +} + +StateObject* WeaponReadyState::UpdateBlocked(float dt) +{ + return this; +} diff --git a/Source/State_Machine/Private/StateObject.cpp b/Source/State_Machine/Private/WeaponState.cpp similarity index 76% rename from Source/State_Machine/Private/StateObject.cpp rename to Source/State_Machine/Private/WeaponState.cpp index 73d380524c9088108ccbc2bbf4f3158d06414982..10a85915c1c371a71c9c1ab595be5a13e2351953 100644 --- a/Source/State_Machine/Private/StateObject.cpp +++ b/Source/State_Machine/Private/WeaponState.cpp @@ -1,5 +1,5 @@ // Fill out your copyright notice in the Description page of Project Settings. -#include "StateObject.h" +#include "WeaponState.h" diff --git a/Source/State_Machine/Private/WeaponType.cpp b/Source/State_Machine/Private/WeaponType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55e395fff478a6892af9d52afe94c0abe198f143 --- /dev/null +++ b/Source/State_Machine/Private/WeaponType.cpp @@ -0,0 +1,153 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WeaponType.h" +#include "PawnController.h" + +#include "GameFramework/Actor.h" + +void WeaponType::HitPlayer(PawnController* origin, PawnController* i_target) +{ + if (i_target) + { + HitInfo info; + info.originator = origin; + info.appliedEffects = hitEffects; + info.damage = baseDamage; + + i_target->ApplyHit(info); + } +} + +void WeaponType::FireProjectile(ProjectileController* type, FVector force) +{ + UPrimitiveComponent* projectileActor = type->GetPhysicsComponent(); + if (projectileActor) + { + projectileActor->AddImpulse(force); + GEngine->AddOnScreenDebugMessage(2, 10, FColor::Cyan, FString::Printf(TEXT("here"))); + } +} + +void WeaponType::FireLaser(PawnController* controller, float radius, float maxDist, bool stopOnHit) +{ + FVector start = controller->GetControlledPawn()->GetActorLocation(); + FVector end = start + (controller->GetAimDirection() * maxDist); + + FCollisionQueryParams params; + params.AddIgnoredActor(controller->GetControlledPawn()); + params.bDebugQuery = true; + + if (stopOnHit) + { + FHitResult hitResult; + + bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepSingleByChannel( + hitResult, + start, + end, + FQuat::Identity, + ECC_Visibility, + FCollisionShape::MakeSphere(radius), + params + ); + + DrawDebugLine(controller->GetControlledPawn()->GetWorld(), start, end, FColor::Green, false, -1, 0, radius); + + if (hasHit) + { + AActor* hitActor = hitResult.GetActor(); + + AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor); + if (hitPawn) + { + HitPlayer(controller, hitPawn->GetPawnController()); + GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Laser Hit " + hitPawn->GetName())); + + } + } + } + else // Multi cast and propogate all hits + { + TArray<FHitResult> hitResults; + + bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepMultiByChannel( + hitResults, + start, + end, + FQuat::Identity, + ECC_Visibility, + FCollisionShape::MakeSphere(radius), + params + ); + + DrawDebugLine(controller->GetControlledPawn()->GetWorld(), start, end, FColor::Green, false, -1, 0, radius); + + if (hasHit) + { + for (FHitResult hit : hitResults) + { + AActor* hitActor = hit.GetActor(); + + AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor); + if (hitPawn) + { + HitPlayer(controller, hitPawn->GetPawnController()); + GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Laser Hit " + hitPawn->GetName())); + + } + } + } + } + +} + +void WeaponType::FireAOE(PawnController* controller, float radius) +{ + FVector start = controller->GetControlledPawn()->GetActorLocation(); + + FCollisionQueryParams params; + params.AddIgnoredActor(controller->GetControlledPawn()); + + TArray<FHitResult> hitResults; + + bool hasHit = controller->GetControlledPawn()->GetWorld()->SweepMultiByChannel( + hitResults, + start, + start, // End at self since this is just an aoe + FQuat::Identity, + ECC_Visibility, + FCollisionShape::MakeSphere(radius), + params + ); + + DrawDebugSphere(controller->GetControlledPawn()->GetWorld(), start, radius, 12, FColor::Red, false); + + if (hasHit) + { + for (FHitResult hit : hitResults) + { + AActor* hitActor = hit.GetActor(); + + AControlledPawn* hitPawn = Cast<AControlledPawn>(hitActor); + if (hitPawn) + { + HitPlayer(controller, hitPawn->GetPawnController()); + GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("AOE Hit " + hitPawn->GetName())); + DrawDebugSphere(controller->GetControlledPawn()->GetWorld(), hit.ImpactPoint, 10.f, 12, FColor::Red, false, 5.0f); + } + } + } +} + +void WeaponType::FireTargeted(PawnController* controller, AActor* i_target) +{ + if (!i_target) return; + + AControlledPawn* pawnTarget = Cast<AControlledPawn>(i_target); + + if (pawnTarget) + { + HitPlayer(controller, pawnTarget->GetPawnController()); + GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Targeted Hit " + pawnTarget->GetName())); + } +} diff --git a/Source/State_Machine/Private/WeaponWinddownState.cpp b/Source/State_Machine/Private/WeaponWinddownState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c389c1f6b7d1dfcf98288975c5f473ffeb6889a --- /dev/null +++ b/Source/State_Machine/Private/WeaponWinddownState.cpp @@ -0,0 +1,42 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WeaponWinddownState.h" + +#include "WeaponCooldownState.h" +#include "WeaponReadyState.h" + +StateObject* WeaponWinddownState::Update(float dt) +{ + timer += dt; + + GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Winding down")); + + if (timer > myType->GetWinddownTime()) + { + + if (myType->GetCooldown() > 0) + { + GEngine->AddOnScreenDebugMessage(11, 10, FColor::Red, FString::Printf(TEXT("CD is %f"), myType->GetCooldown())); + ExitState(); + WeaponCooldownState* newState = new WeaponCooldownState(myMachine, myController, myType); + return newState; + } + else + { + ExitState(); + WeaponReadyState* newState = new WeaponReadyState(myMachine, myController, myType); + return newState; + } + } + + return this; +} + +StateObject* WeaponWinddownState::UpdateBlocked(float dt) +{ + // Blocking does not stop timer ticking + timer += dt; + + return this; +} diff --git a/Source/State_Machine/Private/WeaponWindupState.cpp b/Source/State_Machine/Private/WeaponWindupState.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a11c75c28d6040329b904b142ff8657f0d745c6a --- /dev/null +++ b/Source/State_Machine/Private/WeaponWindupState.cpp @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WeaponWindupState.h" + +#include "WeaponFireState.h" + +StateObject* WeaponWindupState::Update(float dt) +{ + timer += dt; + GEngine->AddOnScreenDebugMessage(10, 10, FColor::Red, TEXT("Winding up")); + + if (timer > myType->GetWindupTime()) + { + ExitState(); + WeaponFireState* newState = new WeaponFireState(myMachine, myController, myType); + return newState; + } + + return this; +} + +StateObject* WeaponWindupState::UpdateBlocked(float dt) +{ + // Blocking does not stop timer ticking + timer += dt; + + return this; +} diff --git a/Source/State_Machine/Public/AIControlledPawn.h b/Source/State_Machine/Public/AIControlledPawn.h new file mode 100644 index 0000000000000000000000000000000000000000..1822dd7ccaec27c13c140704ebccf12d2459235d --- /dev/null +++ b/Source/State_Machine/Public/AIControlledPawn.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ControlledPawn.h" +#include "AIControlledPawn.generated.h" + +/** + * + */ +UCLASS() +class STATE_MACHINE_API AAIControlledPawn : public AControlledPawn +{ + GENERATED_BODY() + +}; diff --git a/Source/State_Machine/Public/AoeWeapon.h b/Source/State_Machine/Public/AoeWeapon.h new file mode 100644 index 0000000000000000000000000000000000000000..9798a0c313c20114f5ff2624bf27be1267fcd94b --- /dev/null +++ b/Source/State_Machine/Public/AoeWeapon.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API AoeWeapon : public WeaponType +{ +private: + AoeWeapon() : WeaponType() + { + windupTime = 0.2f; + fireTime = 1.f; + winddownTime = 0; + baseCooldown = 2.f; + baseDamage = 10.f; + } + + static AoeWeapon* instance; + +public: + + static WeaponType* GetWeaponInstance() + { + if (instance == nullptr) + { + instance = new AoeWeapon(); + } + return instance; + } + + + void Fire(PawnController* controller) override; + +private: + float radius = 100.f; +}; + diff --git a/Source/State_Machine/Public/BlackboardVariableNames.h b/Source/State_Machine/Public/BlackboardVariableNames.h new file mode 100644 index 0000000000000000000000000000000000000000..69c6d496103f7d97673941765e890dd88059bba3 --- /dev/null +++ b/Source/State_Machine/Public/BlackboardVariableNames.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#define ACCELERATIONINPUT "AccelInput" +#define ACCELINPUT "AccelInput" + +#define BRAKEINPUT "BrakeInput" + +#define STEERINGINPUT "SteeringInput" +#define STEERINPUT "SteeringInput" + +#define FIRINGINPUT "FiringInput" +#define FIREINPUT "FiringInput" + +#define DAMAGE "Damage" +#define DMG "Damage" + +#define REVIVE "Revive" \ No newline at end of file diff --git a/Source/State_Machine/Public/ControlledPawn.h b/Source/State_Machine/Public/ControlledPawn.h new file mode 100644 index 0000000000000000000000000000000000000000..e9fd57a3f545ea46e07edb2169fa8fc8c4cc5982 --- /dev/null +++ b/Source/State_Machine/Public/ControlledPawn.h @@ -0,0 +1,73 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Pawn.h" +#include "ControlledPawn.generated.h" + +class PawnController; + +UCLASS() +class STATE_MACHINE_API AControlledPawn : public APawn +{ + GENERATED_BODY() + +public: + // Sets default values for this pawn's properties + AControlledPawn(); + virtual ~AControlledPawn(); + + PawnController* GetPawnController() { return myController; } + + // + // TEMP STUFF + UObject* myBP; + UFunction* BPOverheat = nullptr; + + UPROPERTY(BluePrintReadOnly) + float overheadPercent = 0.f; + + UPROPERTY(BluePrintReadOnly) + bool hasExploded = false; + + + float GetSpeed() { return speed; } + float GetHeight() { return height; } + + void SetOverheatPercent(float percent); + void Explode(); + void UnExplode(); + // ---------------- + // + + void FireWeapon(int idx); + void ReleaseFireWeapon(int idx); + void Revive(); + +private: + PawnController* myController = nullptr; + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + // + // TEMP STUFF + float speed = 0; + float height = 0; + bool jumping = false; + float jumpHeight = 250; + // ---------------------- + // + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + // Called to bind functionality to input + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + + + +}; diff --git a/Source/State_Machine/Public/DamageInterfaces.h b/Source/State_Machine/Public/DamageInterfaces.h new file mode 100644 index 0000000000000000000000000000000000000000..035672e8a8024377705117ec27588e39e751ef87 --- /dev/null +++ b/Source/State_Machine/Public/DamageInterfaces.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponDefinitions.h" + +class PawnController; + +struct HitInfo +{ + PawnController* originator = nullptr; + TArray<WEAPON_EFFECTS> appliedEffects; + float damage; + +}; + +struct IHittable +{ + float health = 100; + virtual void ApplyHit(HitInfo hitInfo) = 0; + virtual inline ~IHittable() = 0; +}; +IHittable::~IHittable() {} + diff --git a/Source/State_Machine/Public/DeadState.h b/Source/State_Machine/Public/DeadState.h new file mode 100644 index 0000000000000000000000000000000000000000..2562014179b1daddb33230619a338fcd9b8ddca4 --- /dev/null +++ b/Source/State_Machine/Public/DeadState.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "HealthState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API DeadState : public HealthState +{ +public: + DeadState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_maxHP) : + HealthState(i_machine, i_controlledPawn, 0, i_maxHP, HealthSubstateTypes::DEAD_STATE) + { + //BlockAll(); + //RemoveAll(); + //RemoveStateFromRemoveMap(WEAPON_STATE); + } + + void EnterState() override; + StateObject* Update(float dt) override; + StateObject* UpdateBlocked(float dt) override; + void ExitState() override; + +}; diff --git a/Source/State_Machine/Public/DefaultProjectile.h b/Source/State_Machine/Public/DefaultProjectile.h new file mode 100644 index 0000000000000000000000000000000000000000..c1d889503b0af3eae838188760740f76920b65a7 --- /dev/null +++ b/Source/State_Machine/Public/DefaultProjectile.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "ProjectileController.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API DefaultProjectile : public ProjectileController +{ +public: + DefaultProjectile(PawnController* i_spawner) : ProjectileController(i_spawner) + { + baseDamage = 10; + type = EProjectileVisual::Default; + } + + void ProjectileTick(float dt) override; // Called by actor tick + void HandleOverlap(AActor* other, bool isOverlap) override; // Called by actor overlap +}; diff --git a/Source/State_Machine/Public/ExplodeState.h b/Source/State_Machine/Public/ExplodeState.h deleted file mode 100644 index a9a5922779c138b574ad54878c1a8645998311e6..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Public/ExplodeState.h +++ /dev/null @@ -1,31 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" - -#include "StateObject.h" - -/** - * - */ -class STATE_MACHINE_API ExplodeState : public StateObject -{ -public: - ExplodeState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::EXPLODING, DefaultStatePriorities::ExplodingPriority) - { - // This state is the end of the game, overrides everything - RemoveAll(); - } - - ExplodeState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::EXPLODING, i_priority) - { - // This state is the end of the game, overrides everything - RemoveAll(); - } - - void EnterState(); - StateObject* Update(float dt); - StateObject* UpdateBlocked(float dt); - -}; diff --git a/Source/State_Machine/Public/ExplosiveProjectile.h b/Source/State_Machine/Public/ExplosiveProjectile.h new file mode 100644 index 0000000000000000000000000000000000000000..53c0152737c98ac9a030f537136af067d69d0697 --- /dev/null +++ b/Source/State_Machine/Public/ExplosiveProjectile.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "ProjectileController.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API ExplosiveProjectile : public ProjectileController +{ +public: + ExplosiveProjectile(PawnController* i_spawner) : ProjectileController(i_spawner) + { + baseDamage = 20; + type = EProjectileVisual::Explosive; + } + + void ProjectileTick(float dt) override; // Called by actor tick + void HandleOverlap(AActor* other, bool isOverlap) override; // Called by actor overlap +}; diff --git a/Source/State_Machine/Public/ExplosiveProjectileWeapon.h b/Source/State_Machine/Public/ExplosiveProjectileWeapon.h new file mode 100644 index 0000000000000000000000000000000000000000..3cdbeaf1b62221556ca5918f2543b0079027eeb8 --- /dev/null +++ b/Source/State_Machine/Public/ExplosiveProjectileWeapon.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API ExplosiveProjectileWeapon : public WeaponType +{ +private: + ExplosiveProjectileWeapon() : WeaponType() + { + windupTime = 0; + fireTime = 0; + winddownTime = 0; + baseCooldown = 1.f; + baseDamage = 10.f; + } + + static ExplosiveProjectileWeapon* instance; + +public: + static WeaponType* GetWeaponInstance() + { + if (instance == nullptr) + { + instance = new ExplosiveProjectileWeapon(); + } + + return instance; + } + + + void Fire(PawnController* controller) override; + + +}; diff --git a/Source/State_Machine/Public/HealthState.h b/Source/State_Machine/Public/HealthState.h new file mode 100644 index 0000000000000000000000000000000000000000..35ac70ec6ac0f6508cfda9dbbfb711e3e81b176c --- /dev/null +++ b/Source/State_Machine/Public/HealthState.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "StateObject.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API HealthState : public StateObject +{ +public: + constexpr static float LowPercentLimit = 0.2f; + + static enum HealthSubstateTypes : uint8 + { + HEALTHY_STATE = 0, + LOW_HEALTH_STATE = 1, + DEAD_STATE = 2, + + NUM_STATES // Keep this last as a helper + }; + + HealthState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_currentHP, float i_maxHP, HealthSubstateTypes subtype = HealthSubstateTypes::NUM_STATES, uint8 i_priority = DefaultStatePriorities::genericWeaponPriority) : + StateObject(i_machine, i_controlledPawn, StateTypes::HEALTH_STATE, subtype, i_priority), + maxHP(i_maxHP), currentHP(i_currentHP) + {} + + virtual StateObject* Update(float dt); + virtual StateObject* UpdateBlocked(float dt) = 0; + +protected: + float maxHP = 100; + float currentHP = 0; +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/HealthyState.h b/Source/State_Machine/Public/HealthyState.h new file mode 100644 index 0000000000000000000000000000000000000000..593a6e6592dc2e2c79852e493edcb6fd4fa7a267 --- /dev/null +++ b/Source/State_Machine/Public/HealthyState.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "HealthState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API HealthyState : public HealthState + { + public: + HealthyState(StateMachine * i_machine, PawnController * i_controlledPawn, float i_currentHP, float i_maxHP) : + HealthState(i_machine, i_controlledPawn, i_currentHP, i_maxHP, HealthSubstateTypes::HEALTHY_STATE) + {} + + StateObject * Update(float dt); + StateObject* UpdateBlocked(float dt); + +}; diff --git a/Source/State_Machine/Public/IdleState.h b/Source/State_Machine/Public/IdleState.h deleted file mode 100644 index 2fbed3196e8c7f4740dc46244cc4e1f43e05bc9a..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Public/IdleState.h +++ /dev/null @@ -1,31 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" - -#include "StateObject.h" - -/** - * - */ -class STATE_MACHINE_API IdleState : public StateObject -{ -public: - IdleState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::IDLE, DefaultStatePriorities::IdlePriority) - {} - - IdleState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::IDLE, i_priority) - {} - - StateObject* Update(float dt); - StateObject* UpdateBlocked(float dt); - void ExitState(); - - void setTransitionSpeed(float speed) { transitionSpeed = speed; } - -private: - float transitionSpeed = 5.f; - - float timer = 0.f; -}; diff --git a/Source/State_Machine/Public/InputDefinitions.h b/Source/State_Machine/Public/InputDefinitions.h new file mode 100644 index 0000000000000000000000000000000000000000..5606e528fd44c922370a2bc67607ec69c39098ec --- /dev/null +++ b/Source/State_Machine/Public/InputDefinitions.h @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +struct InputStruct +{ + float accel = 0; + float brake = 0; + float steering = 0; + bool firing = false; +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/JumpState.h b/Source/State_Machine/Public/JumpState.h deleted file mode 100644 index ac05b6b5e69ac87204dd0789500a6abbf5eeef26..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Public/JumpState.h +++ /dev/null @@ -1,30 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" - -#include "StateObject.h" -/** - * - */ -class STATE_MACHINE_API JumpState : public StateObject -{ -public: - JumpState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::INAIR, DefaultStatePriorities::InAirPriority) - { - AddStateToBlockMap(StateTypes::MOVING); - AddStateToBlockMap(StateTypes::IDLE); - } - - JumpState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::INAIR, i_priority) - { - AddStateToBlockMap(StateTypes::MOVING); - AddStateToBlockMap(StateTypes::IDLE); - } - - StateObject* Update(float dt); - StateObject* UpdateBlocked(float dt); - -private: -}; diff --git a/Source/State_Machine/Public/LaserWeapon.h b/Source/State_Machine/Public/LaserWeapon.h new file mode 100644 index 0000000000000000000000000000000000000000..5aa57f7f1291d0bd239afe9d8155b14e6b71d273 --- /dev/null +++ b/Source/State_Machine/Public/LaserWeapon.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API LaserWeapon : public WeaponType +{ +private: + LaserWeapon() : WeaponType() + { + windupTime = 2.f; + fireTime = 1.5f; + winddownTime = 3.f; + baseCooldown = 5.f; + baseDamage = 50.f; + } + + static LaserWeapon* instance; + +public: + static WeaponType* GetWeaponInstance() + { + if (instance == nullptr) + { + instance = new LaserWeapon(); + } + + return instance; + } + + + void Fire(PawnController* controller) override; + +private: + float radius = 20; + float maxDist = 5000; +}; diff --git a/Source/State_Machine/Public/LowHealthState.h b/Source/State_Machine/Public/LowHealthState.h new file mode 100644 index 0000000000000000000000000000000000000000..52790ac65a2876dcbec42117bea2a9924d876569 --- /dev/null +++ b/Source/State_Machine/Public/LowHealthState.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "HealthState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API LowHealthState : public HealthState +{ +public: + LowHealthState(StateMachine* i_machine, PawnController* i_controlledPawn, float i_currentHP, float i_maxHP) : + HealthState(i_machine, i_controlledPawn, i_currentHP, i_maxHP, HealthSubstateTypes::LOW_HEALTH_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/MovingState.h b/Source/State_Machine/Public/MovingState.h deleted file mode 100644 index e5f74a2e3334b5e6b232b39a2f673ff00451eb6a..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Public/MovingState.h +++ /dev/null @@ -1,36 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" - -#include "StateObject.h" - -/** - * - */ -class STATE_MACHINE_API MovingState : public StateObject -{ -public: - MovingState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::MOVING, DefaultStatePriorities::MovingPriority) - { - // Move state will handle replacing idle states when it finishes - AddStateToRemoveMap(StateTypes::IDLE); - } - - MovingState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::MOVING, i_priority) - { - AddStateToRemoveMap(StateTypes::IDLE); - } - - StateObject* Update(float dt); - StateObject* UpdateBlocked(float dt); - - void setMinTransitionSpeed(float speed) { minTransitionSpeed = speed; } - void setOverheatSpeed(float speed) { overheatSpeed = speed; } - -private: - float minTransitionSpeed = 5.f; - float overheatSpeed = 100.f; - -}; diff --git a/Source/State_Machine/Public/OverheatState.h b/Source/State_Machine/Public/OverheatState.h deleted file mode 100644 index 6a6946826636dabf7217ddae4d1c1227a4255aa2..0000000000000000000000000000000000000000 --- a/Source/State_Machine/Public/OverheatState.h +++ /dev/null @@ -1,34 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" - -#include "StateObject.h" - -/** - * - */ -class STATE_MACHINE_API OverheatState : public StateObject -{ -public: - OverheatState(StateMachine* i_machine, AStatePawn* i_controlledPawn) : StateObject(i_machine, i_controlledPawn, StateTypes::OVERHEATING, DefaultStatePriorities::OverheatingPriority) - {} - - OverheatState(StateMachine* i_machine, AStatePawn* i_controlledPawn, uint8 i_priority) : StateObject(i_machine, i_controlledPawn, StateTypes::OVERHEATING, i_priority) - {} - - StateObject* Update(float dt); - StateObject* UpdateBlocked(float dt); - void ExitState(); - - void setOverheatSpeed(float speed) { overheatSpeed = speed; } - void setExplodeTime(float i_time) { explodeTime = i_time; } - -private: - float timeOverheated = 0.f; - float explodeTime = 5.f; - - float overheatSpeed = 100.f; - -}; diff --git a/Source/State_Machine/Public/PawnController.h b/Source/State_Machine/Public/PawnController.h new file mode 100644 index 0000000000000000000000000000000000000000..1e95e1edce940c5234f786f67b5de04e63a36470 --- /dev/null +++ b/Source/State_Machine/Public/PawnController.h @@ -0,0 +1,51 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "ControlledPawn.h" + +#include "DamageInterfaces.h" +#include "StateMachine.h" +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API PawnController : public IHittable +{ +public: + PawnController(AControlledPawn* controlledPawn); + void TickController(float DeltaTime); + + // Aim Helpers + FVector GetAimDirection() { return myPawn->GetActorForwardVector(); } + AActor* GetTargetActor() { return nullptr; } + + AControlledPawn* GetControlledPawn() { return myPawn; } + + // TEMP for compatability + float GetSpeed() { return myPawn->GetSpeed(); } + float GetHeight() { return myPawn->GetHeight(); } + void Explode() { myPawn->Explode(); } + void UnExplode() { myPawn->UnExplode(); } + void SetOverheatPercent(float percent) { myPawn->SetOverheatPercent(percent); } + // --------------------------- + + void AddWeapon(WeaponType* type); + void FireWeapon(int idx); + void ReleaseFireWeapon(int idx); + + void Revive(); + +public: + // Hittable Implementation + void ApplyHit(HitInfo hitInfo) override; + +private: + StateMachine myStateMachine; + + AControlledPawn* myPawn = nullptr; + TArray<WeaponType*> myWeapons; +}; diff --git a/Source/State_Machine/Public/ProjectileActor.h b/Source/State_Machine/Public/ProjectileActor.h new file mode 100644 index 0000000000000000000000000000000000000000..814911f8eaa40164ab0f7947a77a0ab5b0be9328 --- /dev/null +++ b/Source/State_Machine/Public/ProjectileActor.h @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectileActor.generated.h" + +class ProjectileController; + +UCLASS() +class STATE_MACHINE_API AProjectileActor : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + AProjectileActor(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + virtual void NotifyHit( + UPrimitiveComponent* MyComp, + AActor* OtherActor, + UPrimitiveComponent* OtherComp, + bool bSelfMoved, + FVector HitLocation, + FVector HitNormal, + FVector NormalImpulse, + const FHitResult& Hit) override; + + UFUNCTION() + void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, + UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult); + + void SetProjectileController(ProjectileController* controller) { pController = controller; } + + UPrimitiveComponent* GetPhysicsComponent() { return physicsComponent; } + +private: + ProjectileController* pController = nullptr; + UPrimitiveComponent* physicsComponent = nullptr; +}; diff --git a/Source/State_Machine/Public/ProjectileBPHolder.h b/Source/State_Machine/Public/ProjectileBPHolder.h new file mode 100644 index 0000000000000000000000000000000000000000..eb7d2c2549d826ecf0d8b90d92013df562c7313b --- /dev/null +++ b/Source/State_Machine/Public/ProjectileBPHolder.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponDefinitions.h" +#include "ProjectileActor.h" + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectileBPHolder.generated.h" + +USTRUCT(BlueprintType) +struct FProjectilePairing +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TEnumAsByte<EProjectileVisual> type; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf<AProjectileActor> bpClass; +}; + +UCLASS() +class STATE_MACHINE_API AProjectileBPHolder : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + AProjectileBPHolder(); + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray<FProjectilePairing> pairingList; + +}; diff --git a/Source/State_Machine/Public/ProjectileController.h b/Source/State_Machine/Public/ProjectileController.h new file mode 100644 index 0000000000000000000000000000000000000000..bbdbe6d3ea63ece5aa207da77367357bc7d39f87 --- /dev/null +++ b/Source/State_Machine/Public/ProjectileController.h @@ -0,0 +1,66 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "ProjectileActor.h" +#include "WeaponDefinitions.h" + +#include "CoreMinimal.h" + +class WeaponType; +class PawnController; + +/** + * This is the Sandbox Super class for all projectiles + */ +class STATE_MACHINE_API ProjectileController +{ +public: + + ProjectileController(PawnController* i_spawner); + virtual ~ProjectileController(); + + AProjectileActor* GetActor(); + UPrimitiveComponent* GetPhysicsComponent() + { + if (GetActor()) + { + return myActor->GetPhysicsComponent(); + } + + return nullptr; + } + + //virtual functions for our paired actor to call + virtual void ProjectileTick(float dt) = 0; // Called by actor tick + virtual void HandleOverlap(AActor* other, bool isOverlap) = 0; // Called by actor overlap + + void SetTargetActor(AActor* i_target) { myTarget = i_target; } + void SetTravelVector(FVector i_vec) { myPropelVector = i_vec; } + +protected: + void HitPlayer(PawnController* controller); + + // Travel Functions + void SeekTarget(float dt); + void TravelPropelled(float dt); + + // Effect Functions + void TriggerExplosion(float radius); + +private: + TSubclassOf<AProjectileActor> GetBPToSpawn(); + + AProjectileActor* myActor = nullptr; + +protected: + PawnController* myController = nullptr; + EProjectileVisual type = EProjectileVisual::Default; + + AActor* myTarget = nullptr; + FVector myPropelVector; + + float myTravelSpeed; + float baseDamage; + +}; diff --git a/Source/State_Machine/Public/ProjectileWeapon.h b/Source/State_Machine/Public/ProjectileWeapon.h new file mode 100644 index 0000000000000000000000000000000000000000..9743b115e36fa49ef3426d26b60a1e17dc15fcde --- /dev/null +++ b/Source/State_Machine/Public/ProjectileWeapon.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API ProjectileWeapon : public WeaponType +{ +private: + ProjectileWeapon() : WeaponType() + { + windupTime = 0; + fireTime = 0; + winddownTime = 0; + baseCooldown = 1.f; + baseDamage = 10.f; + } + + static ProjectileWeapon* instance; + +public: + static WeaponType* GetWeaponInstance() + { + if (instance == nullptr) + { + instance = new ProjectileWeapon(); + } + + return instance; + } + + + void Fire(PawnController* controller) override; + + +}; diff --git a/Source/State_Machine/Public/StateObject.h b/Source/State_Machine/Public/StateObject.h index 57b03e901190110af211558d629c1609ebf77048..3a1006fea93f5da4cbabbfa0984e5b89c1e6b514 100644 --- a/Source/State_Machine/Public/StateObject.h +++ b/Source/State_Machine/Public/StateObject.h @@ -6,24 +6,20 @@ #include "StateTypes.h" -class AStatePawn; +class PawnController; class StateMachine; class STATE_MACHINE_API StateObject { public: - StateObject(StateMachine* i_machine, AStatePawn* i_controlledPawn) : - myMachine(i_machine), myPawn(i_controlledPawn), + StateObject(StateMachine* i_machine, PawnController* i_controlledPawn, StateTypes i_state = StateTypes::NUM_STATES, uint16 i_substate = 0, uint8 i_priority = 255) : + myMachine(i_machine), myController(i_controlledPawn), // Initialize our bitmaps to block any invalid states - blockMap(0xFF << StateTypes::NUM_STATES), removeMap(0xFF << StateTypes::NUM_STATES), - priority(255) - {} - - StateObject(StateMachine* i_machine, AStatePawn* i_controlledPawn, StateTypes i_state, uint8 i_priority = 255) : - myMachine(i_machine), myPawn(i_controlledPawn), - // Initialize our bitmaps to block any invalid states - blockMap(0xFF << StateTypes::NUM_STATES), removeMap(0xFF << StateTypes::NUM_STATES), - priority(i_priority), myType(i_state) + blockMap(0xFF << StateTypes::NUM_STATES), + removeMap(0xFF << StateTypes::NUM_STATES), + priority(i_priority), + stateType(i_state), + substateType(i_substate) {} virtual ~StateObject() {} @@ -34,28 +30,32 @@ public: uint8 GetPriority() const { return priority; } uint16 GetBlockMap() const { return blockMap; } uint16 GetRemoveMap() const { return removeMap; } - StateTypes GetType() const { return myType; } + StateTypes GetType() const { return stateType; } // Bitmap Setters // -------------- void AddStateToBlockMap(StateTypes type) { blockMap = blockMap | GetStateBitMap(type); } void RemoveStateFromBlockMap(StateTypes type) { blockMap = blockMap & ~(GetStateBitMap(type)); } void ClearBlockMap() { blockMap = 0xFF << StateTypes::NUM_STATES; } - void BlockAll() { blockMap = 0xFF & ~(GetStateBitMap(myType)); } + void BlockAll() { blockMap = 0xFF & ~(GetStateBitMap(stateType)); } void AddStateToRemoveMap(StateTypes type) { removeMap = removeMap | GetStateBitMap(type); } void RemoveStateFromRemoveMap(StateTypes type) { removeMap = removeMap & ~(GetStateBitMap(type)); } void ClearRemoveMap() { removeMap = 0xFF << StateTypes::NUM_STATES; } - void RemoveAll() { removeMap = 0xFF & ~(GetStateBitMap(myType)); } + void RemoveAll() { removeMap = 0xFF & ~(GetStateBitMap(stateType)); } // Virtual Functions to implement // ------------------------------ virtual void EnterState() { hasStarted = true; } + // Update functions return pointers to the resulting state. Self if nothing has changed, nullptr if this state has finished virtual StateObject* Update(float dt) = 0; + // Use this to do any background timekeeping without actually processing anything virtual StateObject* UpdateBlocked(float dt) = 0; + + // Please remember to set shouldRemove if you override this virtual void ExitState() { shouldRemove = true; } @@ -74,19 +74,18 @@ public: bool HasStarted() { return hasStarted; } protected: + StateMachine* myMachine = nullptr; - AStatePawn* myPawn = nullptr; + PawnController* myController = nullptr; bool shouldRemove = false; bool hasStarted = false; -private: - uint16 blockMap; - uint16 removeMap; - uint8 priority; - StateTypes myType = StateTypes::NUM_STATES; + StateTypes stateType = StateTypes::NUM_STATES; + uint8 substateType = 255; - + uint16 blockMap; + uint16 removeMap; }; diff --git a/Source/State_Machine/Public/StatePawn.h b/Source/State_Machine/Public/StatePawn.h index ea39cc008eeb8353e71ddb547fee179b31b31a5f..9c5a914b473e0caed31c4a6312ae242158f0d882 100644 --- a/Source/State_Machine/Public/StatePawn.h +++ b/Source/State_Machine/Public/StatePawn.h @@ -2,58 +2,33 @@ #pragma once -#include "StateMachine.h" - #include "CoreMinimal.h" -#include "GameFramework/Pawn.h" +#include "ControlledPawn.h" #include "StatePawn.generated.h" UCLASS() -class STATE_MACHINE_API AStatePawn : public APawn +class STATE_MACHINE_API AStatePawn : public AControlledPawn { GENERATED_BODY() public: - // Sets default values for this pawn's properties - AStatePawn(); - - float GetSpeed() { return speed; } - float GetHeight() { return height; } - - void SetOverheatPercent(float percent); - void Explode(); - - UObject* myBP; - UFunction* BPOverheat = nullptr; - - UPROPERTY(BluePrintReadOnly) - float overheadPercent = 0.f; - - UPROPERTY(BluePrintReadOnly) - bool hasExploded = false; protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: - // Called every frame - virtual void Tick(float DeltaTime) override; - // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; private: - - StateMachine myStateMachine; - - float speed = 0; - float height = 0; - bool jumping = false; - float jumpHeight = 250; - // Input Functions void MoveDown(); void MoveUp(); void Jump(); + + void PressFire(); + void ReleaseFire(); + void TriggerRevive(); + }; diff --git a/Source/State_Machine/Public/StateTypes.h b/Source/State_Machine/Public/StateTypes.h index d8053432afaf209f14c34b4a43a86ff4d8459f4b..4d3f7275ba5b9b830b848afd5cc7c657749ed7e7 100644 --- a/Source/State_Machine/Public/StateTypes.h +++ b/Source/State_Machine/Public/StateTypes.h @@ -5,25 +5,33 @@ static class DefaultStatePriorities { public: - const static uint8 IdlePriority = 255; - const static uint8 MovingPriority = 255; - const static uint8 InAirPriority = 1; // Overrides moving - const static uint8 OverheatingPriority = 2; // Calculate before movement - const static uint8 ExplodingPriority = 0; // overrides everything + const static uint8 genericHealthPriority = 16; // Highest Priority outside of special cases + const static uint8 genericEffectPriority = 32; + const static uint8 genericInputPriority = 64; + const static uint8 genericMovementPriority = 96; + const static uint8 genericWeaponPriority = 128; + + const static uint8 MAX_STATES = 16; // because we use a uint16 bit map }; enum StateTypes : uint8 { - IDLE = 0, - MOVING = 1, - INAIR = 2, - OVERHEATING = 3, - EXPLODING = 4, - NUM_STATES + HEALTH_STATE = 0, + EFFECT_STATE = 1, + INPUT_STATE = 2, + MOVEMENT_STATE = 3, + WEAPON_STATE = 4, + + NUM_STATES // Keep this last }; inline uint16 GetStateBitMap(StateTypes type) { return 0x01 << type; } + +inline uint16 GetStateBitMap(uint16 type) +{ + return 0x01 << type; +} diff --git a/Source/State_Machine/Public/TargetedWeapon.h b/Source/State_Machine/Public/TargetedWeapon.h new file mode 100644 index 0000000000000000000000000000000000000000..b91331e0d6160c6c4bcb47f566d481aad7ddc231 --- /dev/null +++ b/Source/State_Machine/Public/TargetedWeapon.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponType.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API TargetedWeapon : public WeaponType +{ +private: + TargetedWeapon() : WeaponType() + { + windupTime = 0.5f; + fireTime = 1.f; + winddownTime = 1.f; + baseCooldown = 2.f; + baseDamage = 50.f; + } + + static TargetedWeapon* instance; + +public: + static WeaponType* GetWeaponInstance() + { + if (instance == nullptr) + { + instance = new TargetedWeapon(); + } + + return instance; + } + + + void Fire(PawnController* controller) override; +}; diff --git a/Source/State_Machine/Public/WeaponCooldownState.h b/Source/State_Machine/Public/WeaponCooldownState.h new file mode 100644 index 0000000000000000000000000000000000000000..470ede93778d0c0856e98565a17b4bad4007dc03 --- /dev/null +++ b/Source/State_Machine/Public/WeaponCooldownState.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API WeaponCooldownState : public WeaponState +{ +public: + WeaponCooldownState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) : + WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::COOLDOWN_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +private: + float timer = 0; + +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/WeaponDefinitions.h b/Source/State_Machine/Public/WeaponDefinitions.h new file mode 100644 index 0000000000000000000000000000000000000000..bffa46bfd19166cfe962950b9de77c21c888e19c --- /dev/null +++ b/Source/State_Machine/Public/WeaponDefinitions.h @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +enum WEAPON_EFFECTS { + +}; + + +UENUM(BlueprintType) +enum EProjectileVisual : uint8 +{ + Default UMETA(DisplayName = "Default"), + Explosive UMETA(DisplayName = "Explosive") +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/WeaponFireState.h b/Source/State_Machine/Public/WeaponFireState.h new file mode 100644 index 0000000000000000000000000000000000000000..b14e9d3ce0bdab1262ac92a22154169259ba1882 --- /dev/null +++ b/Source/State_Machine/Public/WeaponFireState.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API WeaponFireState : public WeaponState +{ +public: + WeaponFireState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) : + WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::FIRE_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +private: + float timer = 0; + +}; diff --git a/Source/State_Machine/Public/WeaponReadyState.h b/Source/State_Machine/Public/WeaponReadyState.h new file mode 100644 index 0000000000000000000000000000000000000000..b74ba166eefb9a5bc1ebbc5ed5cd4a353a8c698f --- /dev/null +++ b/Source/State_Machine/Public/WeaponReadyState.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API WeaponReadyState : public WeaponState +{ +public: + WeaponReadyState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) : + WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::READY_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +}; diff --git a/Source/State_Machine/Public/WeaponState.h b/Source/State_Machine/Public/WeaponState.h new file mode 100644 index 0000000000000000000000000000000000000000..d26b42a6fe8a395f7e9c9e0a9a102d45f012fcf9 --- /dev/null +++ b/Source/State_Machine/Public/WeaponState.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "StateObject.h" +#include "WeaponType.h" + +#include "CoreMinimal.h" + + +/** + * + */ +class STATE_MACHINE_API WeaponState : public StateObject +{ +public: + static enum WeaponSubstateTypes : uint8 + { + READY_STATE = 0, + WINDUP_STATE = 1, + FIRE_STATE = 2, + WINDDOWN_STATE = 3, + COOLDOWN_STATE = 4, + + NUM_STATES // Keep this last as a helper + }; + + WeaponState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type, WeaponSubstateTypes subtype = WeaponSubstateTypes::NUM_STATES, uint8 i_priority = DefaultStatePriorities::genericWeaponPriority) : + StateObject(i_machine, i_controlledPawn, StateTypes::WEAPON_STATE, subtype, i_priority), + myType(i_type) + {} + + virtual StateObject* Update(float dt) = 0; + virtual StateObject* UpdateBlocked(float dt) = 0; + +protected: + WeaponType* myType = nullptr; +}; diff --git a/Source/State_Machine/Public/WeaponType.h b/Source/State_Machine/Public/WeaponType.h new file mode 100644 index 0000000000000000000000000000000000000000..9206fb8a923e5d79f7cea068712b461ffdfa7c48 --- /dev/null +++ b/Source/State_Machine/Public/WeaponType.h @@ -0,0 +1,54 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +#include "ProjectileController.h" + +#include "WeaponDefinitions.h" + +class PawnController; + +/** + * + */ +class STATE_MACHINE_API WeaponType +{ +public: + virtual ~WeaponType() {} + + virtual void Fire(PawnController* controller) = 0; + + float GetCooldown() { return baseCooldown; } + float GetDamage() { return baseDamage; } + + float GetWindupTime() { return windupTime; } + float GetFireTime() { return fireTime; } + float GetWinddownTime() { return winddownTime; } + + void HitPlayer(PawnController* origin, PawnController* i_target); + +protected: + WeaponType() : hitEffects() + {} + + // Functions for Firing + void FireProjectile(ProjectileController* type, FVector force); + void FireLaser(PawnController* controller, float radius, float maxDist = 10000, bool stopOnHit = true); + void FireAOE(PawnController* controller, float radius); // AOE around self, projectile aoes handled by fire projectile + void FireTargeted(PawnController* controller, AActor* i_target); + + // Helpers for firing projectiles + FVector GetTargetForce(FVector target, float timeToTarget); + + TArray<WEAPON_EFFECTS> hitEffects; + + float baseCooldown = 0; + float baseDamage = 0; + + // These divide the parts of firing for animation and timing purposes + float windupTime = 0; + float fireTime = 0; // 0 Fire time indicates 1 fire frame + float winddownTime = 0; +}; diff --git a/Source/State_Machine/Public/WeaponWinddownState.h b/Source/State_Machine/Public/WeaponWinddownState.h new file mode 100644 index 0000000000000000000000000000000000000000..b5f9943fef9121436764a94d07d4669764a4d287 --- /dev/null +++ b/Source/State_Machine/Public/WeaponWinddownState.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API WeaponWinddownState : public WeaponState +{ +public: + WeaponWinddownState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) : + WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::WINDDOWN_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +private: + float timer = 0; + +}; \ No newline at end of file diff --git a/Source/State_Machine/Public/WeaponWindupState.h b/Source/State_Machine/Public/WeaponWindupState.h new file mode 100644 index 0000000000000000000000000000000000000000..9cdb02be7e0ba5554ed483e53cc2429ca7bc5c61 --- /dev/null +++ b/Source/State_Machine/Public/WeaponWindupState.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "WeaponState.h" + +#include "CoreMinimal.h" + +/** + * + */ +class STATE_MACHINE_API WeaponWindupState : public WeaponState +{ +public: + WeaponWindupState(StateMachine* i_machine, PawnController* i_controlledPawn, WeaponType* i_type) : + WeaponState(i_machine, i_controlledPawn, i_type, WeaponSubstateTypes::WINDUP_STATE) + {} + + StateObject* Update(float dt); + StateObject* UpdateBlocked(float dt); + +private: + float timer = 0; + +};