From 2bfd6d4f155bf89f445bd0314e6eb2c4488b042f Mon Sep 17 00:00:00 2001 From: Maxime Date: Tue, 21 Nov 2023 19:05:26 +0100 Subject: [PATCH] First iteration of spline movement mechanic in C++ --- Pawn_Unreal/Config/DefaultInput.ini | 3 + Pawn_Unreal/Content/Characters/BP_Judy.uasset | 4 +- .../Characters/Base/ABP_Character.uasset | 4 +- .../Input/BP_MainPlayerController.uasset | 4 +- .../0/91/BERD0JFDCI5RAYAPS4DY1P.uasset | 3 + .../0/XC/EES9G2P00B5EO5FPWE8N4U.uasset | 3 + .../1/LE/RIS6ZA9R1KK7MS3EGVDKZV.uasset | 3 + .../3/JJ/2G4XZ4FX8KSV5ISWLBUX9T.uasset | 3 - .../3/S1/Q0FDQMTTCM0M6RLWXOTPMF.uasset | 2 +- .../3/ZC/SPZ5ZSIG7BW3194FWIBEWC.uasset | 3 + .../4/OH/3YZOO5HQPTMDBNJPPM4RV0.uasset | 3 + .../7/XC/WIQNHKPM06P8T5BPNH23RN.uasset | 2 +- .../9/RQ/JYNZEWOG6SXNE3HGUCSZIE.uasset | 3 + .../9/SL/CVWLA6QDNV8TESDOTZTWDN.uasset | 4 +- .../A/BZ/XZUBN8NU0UZ2W8T2MBWCYN.uasset | 3 + .../A/U2/4ECO0ADAHJEURYSR8OYVEX.uasset | 3 + .../C/BU/19EKBOJAPNXX8XDUPL0Z18.uasset | 4 +- .../D/11/8KRHTI8SRC72YR9XJOITVN.uasset | 3 - .../D/VD/LJAQY01SJR93NPW0FPCPIL.uasset | 3 + Pawn_Unreal/Pawn.sln.DotSettings | 2 + Pawn_Unreal/Pawn.sln.DotSettings.user | 2 + .../Private/Characters/PwnCharacterBase.cpp | 18 ++ .../PwnCharacterMovementComponent.cpp | 299 ++++++++++++++++++ .../Combat/PwnCombatPlatformerPath.cpp | 30 ++ .../PwnGameplayModeSubsystem.cpp | 43 +++ .../Pawn/Public/Characters/PwnCharacterBase.h | 25 ++ .../PwnCharacterMovementComponent.h | 59 ++++ .../Combat/PwnCombatPlatformerPath.h | 30 ++ .../GameplayModes/PwnGameplayModeSubsystem.h | 16 + .../Source/Pawn/Public/Utils/EngineUtils.h | 9 + 30 files changed, 575 insertions(+), 18 deletions(-) create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/91/BERD0JFDCI5RAYAPS4DY1P.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/XC/EES9G2P00B5EO5FPWE8N4U.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/1/LE/RIS6ZA9R1KK7MS3EGVDKZV.uasset delete mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/JJ/2G4XZ4FX8KSV5ISWLBUX9T.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/ZC/SPZ5ZSIG7BW3194FWIBEWC.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/4/OH/3YZOO5HQPTMDBNJPPM4RV0.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/RQ/JYNZEWOG6SXNE3HGUCSZIE.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/BZ/XZUBN8NU0UZ2W8T2MBWCYN.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/U2/4ECO0ADAHJEURYSR8OYVEX.uasset delete mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/11/8KRHTI8SRC72YR9XJOITVN.uasset create mode 100644 Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/VD/LJAQY01SJR93NPW0FPCPIL.uasset create mode 100644 Pawn_Unreal/Pawn.sln.DotSettings create mode 100644 Pawn_Unreal/Pawn.sln.DotSettings.user create mode 100644 Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterBase.cpp create mode 100644 Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp create mode 100644 Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp create mode 100644 Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterBase.h create mode 100644 Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h create mode 100644 Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h create mode 100644 Pawn_Unreal/Source/Pawn/Public/Utils/EngineUtils.h diff --git a/Pawn_Unreal/Config/DefaultInput.ini b/Pawn_Unreal/Config/DefaultInput.ini index 9b1348f..f2288dc 100644 --- a/Pawn_Unreal/Config/DefaultInput.ini +++ b/Pawn_Unreal/Config/DefaultInput.ini @@ -70,7 +70,9 @@ bCaptureMouseOnLaunch=True bEnableLegacyInputScales=True bEnableMotionControls=True bFilterInputByPlatformUser=False +bEnableInputDeviceSubsystem=True bShouldFlushPressedKeysOnViewportFocusLost=True +bEnableDynamicComponentInputBinding=True bAlwaysShowTouchInterface=False bShowConsoleOnFourFingerTap=True bEnableGestureRecognizer=False @@ -85,4 +87,5 @@ DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.Defaul -ConsoleKeys=Tilde +ConsoleKeys=Tilde +ConsoleKeys=Caret ++ConsoleKeys=² diff --git a/Pawn_Unreal/Content/Characters/BP_Judy.uasset b/Pawn_Unreal/Content/Characters/BP_Judy.uasset index b59cae4..1575cff 100644 --- a/Pawn_Unreal/Content/Characters/BP_Judy.uasset +++ b/Pawn_Unreal/Content/Characters/BP_Judy.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c23b59c00a787b2f5457ed34e65f89a34772dc484a8a02669cfd99f603721bf9 -size 174677 +oid sha256:bad47e6ba5d59a3b3b87c4f6f99513931d698e5bda42721987df04f4674c7faa +size 225770 diff --git a/Pawn_Unreal/Content/Characters/Base/ABP_Character.uasset b/Pawn_Unreal/Content/Characters/Base/ABP_Character.uasset index 3ef5d3a..7865e99 100644 --- a/Pawn_Unreal/Content/Characters/Base/ABP_Character.uasset +++ b/Pawn_Unreal/Content/Characters/Base/ABP_Character.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a27fe469a50cd6ade8e513410364d36f8b0fe70e9cd95bb6473d1080e62c2973 -size 266225 +oid sha256:94bbc78f7257a580831f357149d4572a7e5c492a494331c293fb6eaf7e54f308 +size 212741 diff --git a/Pawn_Unreal/Content/Input/BP_MainPlayerController.uasset b/Pawn_Unreal/Content/Input/BP_MainPlayerController.uasset index a4d2ad0..db83481 100644 --- a/Pawn_Unreal/Content/Input/BP_MainPlayerController.uasset +++ b/Pawn_Unreal/Content/Input/BP_MainPlayerController.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5676f86cad9c61fe78944926907296751db39799f680ca324dee7fb11dd25656 -size 442497 +oid sha256:3dd40388fcf8b25c304a4abd4426a14b6cd29096ae5f1a7965974321c4de74cf +size 414085 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/91/BERD0JFDCI5RAYAPS4DY1P.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/91/BERD0JFDCI5RAYAPS4DY1P.uasset new file mode 100644 index 0000000..26931dd --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/91/BERD0JFDCI5RAYAPS4DY1P.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:095b7423feef5e520436ca4ada169891edcdf403846c47993c4b3c326564c4c0 +size 4434 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/XC/EES9G2P00B5EO5FPWE8N4U.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/XC/EES9G2P00B5EO5FPWE8N4U.uasset new file mode 100644 index 0000000..7889f07 --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/0/XC/EES9G2P00B5EO5FPWE8N4U.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b9aa98fa5ada2378494a0a3adb546a25770de0cc6cd8228a0001cd73ba5255e +size 4320 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/1/LE/RIS6ZA9R1KK7MS3EGVDKZV.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/1/LE/RIS6ZA9R1KK7MS3EGVDKZV.uasset new file mode 100644 index 0000000..6086bba --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/1/LE/RIS6ZA9R1KK7MS3EGVDKZV.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:745affce1b7cb5725c8e39f2fc6dbaf9b2cd0bf0b1ccd607aee11be4bf396b4a +size 4320 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/JJ/2G4XZ4FX8KSV5ISWLBUX9T.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/JJ/2G4XZ4FX8KSV5ISWLBUX9T.uasset deleted file mode 100644 index 583c3af..0000000 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/JJ/2G4XZ4FX8KSV5ISWLBUX9T.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8d175baeb9a56d342f674255c6628094ca2ea25ee0a1f4d1fb032dbb126a2356 -size 7349 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/S1/Q0FDQMTTCM0M6RLWXOTPMF.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/S1/Q0FDQMTTCM0M6RLWXOTPMF.uasset index 8f7ee9b..fa36887 100644 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/S1/Q0FDQMTTCM0M6RLWXOTPMF.uasset +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/S1/Q0FDQMTTCM0M6RLWXOTPMF.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18dce8ce6bda74815912bd1a7b7f18470fe3713cc6818760ba67ff11d1d030ee +oid sha256:501e2333ad267b57cc6122c6d3a3e66e49189b324354a6a2807f4ba3115287a3 size 4441 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/ZC/SPZ5ZSIG7BW3194FWIBEWC.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/ZC/SPZ5ZSIG7BW3194FWIBEWC.uasset new file mode 100644 index 0000000..1f8e3db --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/3/ZC/SPZ5ZSIG7BW3194FWIBEWC.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f9ea1c60c5c4f236e2a2a0c625ee11dead9e78959268b6ff5ed5d2cb68b1034 +size 4318 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/4/OH/3YZOO5HQPTMDBNJPPM4RV0.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/4/OH/3YZOO5HQPTMDBNJPPM4RV0.uasset new file mode 100644 index 0000000..c73cd19 --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/4/OH/3YZOO5HQPTMDBNJPPM4RV0.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43e5a125722214af59e8d6753741d618e29e60b4cfe780767c3622a688d98755 +size 4320 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/7/XC/WIQNHKPM06P8T5BPNH23RN.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/7/XC/WIQNHKPM06P8T5BPNH23RN.uasset index 88647a4..505d785 100644 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/7/XC/WIQNHKPM06P8T5BPNH23RN.uasset +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/7/XC/WIQNHKPM06P8T5BPNH23RN.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f3753b65840211d17718c61acd343257d9a8b37f9d86422e7db9583f3decdf2 +oid sha256:7c985f97632fe1b2d621e16da9e725c935156383ff605327acab5987664a9fba size 4363 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/RQ/JYNZEWOG6SXNE3HGUCSZIE.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/RQ/JYNZEWOG6SXNE3HGUCSZIE.uasset new file mode 100644 index 0000000..156b9f7 --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/RQ/JYNZEWOG6SXNE3HGUCSZIE.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d122dde87e7da821fd2442dac088f30bce0029e8966d9ee672bff2bbab0d9ac +size 21547 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/SL/CVWLA6QDNV8TESDOTZTWDN.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/SL/CVWLA6QDNV8TESDOTZTWDN.uasset index 8d01cf2..f1022d4 100644 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/SL/CVWLA6QDNV8TESDOTZTWDN.uasset +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/9/SL/CVWLA6QDNV8TESDOTZTWDN.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a19f7876e98373728d76172520b2fce444ceada9fd15d4df2d5aa4d983453ad4 -size 20389 +oid sha256:ffce8c606a34176a459c81a435acba852d3aad8a529ae2e305aaf23d862de0e9 +size 20105 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/BZ/XZUBN8NU0UZ2W8T2MBWCYN.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/BZ/XZUBN8NU0UZ2W8T2MBWCYN.uasset new file mode 100644 index 0000000..1a4c3ef --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/BZ/XZUBN8NU0UZ2W8T2MBWCYN.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9e0625781eae5876357ad47e5ea94ecd9d495730c6a35b2c59c6e00ddc6207f +size 4320 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/U2/4ECO0ADAHJEURYSR8OYVEX.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/U2/4ECO0ADAHJEURYSR8OYVEX.uasset new file mode 100644 index 0000000..9492931 --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/A/U2/4ECO0ADAHJEURYSR8OYVEX.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:410a4983d36e9dfef96f23e75b4fd6cf2949d669e83f0aefc4afd75970809285 +size 4320 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/C/BU/19EKBOJAPNXX8XDUPL0Z18.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/C/BU/19EKBOJAPNXX8XDUPL0Z18.uasset index c1f09ba..7898209 100644 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/C/BU/19EKBOJAPNXX8XDUPL0Z18.uasset +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/C/BU/19EKBOJAPNXX8XDUPL0Z18.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad5d6fa4613b64176b4e83451f7873c8d5b013b6203af1a7ed1333b0ddb9acdb -size 9103 +oid sha256:3503b03398da6182b14796e8abfaa5fc3ac374d9421c8d5c763a4331fa7e1acc +size 10539 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/11/8KRHTI8SRC72YR9XJOITVN.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/11/8KRHTI8SRC72YR9XJOITVN.uasset deleted file mode 100644 index aaf564c..0000000 --- a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/11/8KRHTI8SRC72YR9XJOITVN.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:221723698e9741459d92e8c08aa2d3bda0f62606727a4edf8a339d91ba924879 -size 46429 diff --git a/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/VD/LJAQY01SJR93NPW0FPCPIL.uasset b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/VD/LJAQY01SJR93NPW0FPCPIL.uasset new file mode 100644 index 0000000..b15ea29 --- /dev/null +++ b/Pawn_Unreal/Content/__ExternalActors__/Maps/Dev/MAP_ControllerGym/D/VD/LJAQY01SJR93NPW0FPCPIL.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b4133eb7b55f9905d9e9547ab19e3acac3636c4821d3d48b7436b0cd5258f40 +size 4320 diff --git a/Pawn_Unreal/Pawn.sln.DotSettings b/Pawn_Unreal/Pawn.sln.DotSettings new file mode 100644 index 0000000..ff71555 --- /dev/null +++ b/Pawn_Unreal/Pawn.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Pawn_Unreal/Pawn.sln.DotSettings.user b/Pawn_Unreal/Pawn.sln.DotSettings.user new file mode 100644 index 0000000..3da0f3b --- /dev/null +++ b/Pawn_Unreal/Pawn.sln.DotSettings.user @@ -0,0 +1,2 @@ + + ForceIncluded \ No newline at end of file diff --git a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterBase.cpp b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterBase.cpp new file mode 100644 index 0000000..c43099b --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterBase.cpp @@ -0,0 +1,18 @@ +#include "Characters/PwnCharacterBase.h" + +#include "Characters/PwnCharacterMovementComponent.h" + +APwnCharacterBase::APwnCharacterBase(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer.SetDefaultSubobjectClass(CharacterMovementComponentName)) { + PrimaryActorTick.bCanEverTick = true; + + PwnCharacterMovementComponent = CastChecked(GetCharacterMovement()); +} + +void APwnCharacterBase::BeginPlay() { + Super::BeginPlay(); +} + +void APwnCharacterBase::Tick(float DeltaTime) { + Super::Tick(DeltaTime); +} diff --git a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp new file mode 100644 index 0000000..1122cbe --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp @@ -0,0 +1,299 @@ +#include "Characters/PwnCharacterMovementComponent.h" + +#include "Characters/PwnCharacterBase.h" +#include "Components/SplineComponent.h" +#include "GameplayModes/PwnGameplayModeSubsystem.h" +#include "GameplayModes/Combat/PwnCombatPlatformerPath.h" +#include "Utils/EngineUtils.h" + +UPwnCharacterMovementComponent::UPwnCharacterMovementComponent() { + PrimaryComponentTick.bCanEverTick = true; +} + +void UPwnCharacterMovementComponent::BeginPlay() { + Super::BeginPlay(); +} + +float UPwnCharacterMovementComponent::GetMaxBrakingDeceleration() const { + if (MovementMode == MOVE_Custom) { + switch (CustomMovementMode) { + case SplineWalking: return BrakingDecelerationWalking; + case SplineFalling: return BrakingDecelerationFalling; + default: break; + } + } + return Super::GetMaxBrakingDeceleration(); +} + +float UPwnCharacterMovementComponent::GetMaxSpeed() const { + if (MovementMode == MOVE_Custom) { + switch (CustomMovementMode) { + case SplineWalking: return IsCrouching() ? MaxWalkSpeedCrouched : MaxWalkSpeed;; + case SplineFalling: return MaxWalkSpeed; + default: break; + } + } + return Super::GetMaxSpeed(); +} + +bool UPwnCharacterMovementComponent::IsMovingOnGround() const { + return Super::IsMovingOnGround() || IsCustomMovementMode(SplineWalking); +} + +void UPwnCharacterMovementComponent::EnterSplineFollowMode() { + SetMovementMode(MOVE_Custom, SplineWalking); + + const UPwnGameplayModeSubsystem* Subsystem = GetWorld()->GetSubsystem(); + check(Subsystem); + + FVector OutLocation; + APwnCombatPlatformerPath* OutCombatPath; + float OutDistanceAloneSpline; + if (Subsystem->FindClosestCombatPathLocation(UpdatedComponent->GetComponentLocation(), OutLocation, OutCombatPath, OutDistanceAloneSpline)) { + DistanceAlongSpline = OutDistanceAloneSpline; + CombatPath = OutCombatPath; + DotDirection = CombatPath->Reversed ? -1.0f : 1.0f; + } +} + +void UPwnCharacterMovementComponent::ExitSplineFollowMode() { + SetMovementMode(MOVE_Walking); +} + +bool UPwnCharacterMovementComponent::IsCustomMovementMode(const ECustomMovementMode Mode) const { + return MovementMode == MOVE_Custom && CustomMovementMode == Mode; +} + +void UPwnCharacterMovementComponent::PhysCustom(const float DeltaTime, const int32 Iterations) { + Super::PhysCustom(DeltaTime, Iterations); + + switch (CustomMovementMode) { + case SplineWalking: PhysSplineFollow(DeltaTime, Iterations); + break; + default: + UE_LOG(LogTemp, Fatal, TEXT("Invalid custom movement mode")); + } +} + +UE_DISABLE_OPTIMIZATION + +void UPwnCharacterMovementComponent::PhysSplineFollow(const float DeltaTime, int32 Iterations) { + if (DeltaTime < MIN_TICK_TIME) { + return; + } + + if (!CharacterOwner || (!CharacterOwner->Controller && !bRunPhysicsWithNoController && !HasAnimRootMotion() && !CurrentRootMotion. + HasOverrideVelocity() && (CharacterOwner->GetLocalRole() != ROLE_SimulatedProxy))) { + Acceleration = FVector::ZeroVector; + Velocity = FVector::ZeroVector; + return; + } + + if (!UpdatedComponent->IsQueryCollisionEnabled()) { + SetMovementMode(MOVE_Walking); + return; + } + + bJustTeleported = false; + bool bCheckedFall = false; + bool bTriedLedgeMove = false; + float RemainingTime = DeltaTime; + // Perform the move + while ((RemainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) && CharacterOwner && (CharacterOwner->Controller || + bRunPhysicsWithNoController || HasAnimRootMotion() || CurrentRootMotion.HasOverrideVelocity() || (CharacterOwner->GetLocalRole() == + ROLE_SimulatedProxy))) { + Iterations++; + bJustTeleported = false; + const float TimeTick = GetSimulationTimeStep(RemainingTime, Iterations); + RemainingTime -= TimeTick; + + // Save current values + UPrimitiveComponent* const OldBase = GetMovementBase(); + const FVector PreviousBaseLocation = OldBase != nullptr ? OldBase->GetComponentLocation() : FVector::ZeroVector; + const FVector OldLocation = UpdatedComponent->GetComponentLocation(); + const FFindFloorResult OldFloor = CurrentFloor; + const FVector OldVelocity = Velocity; + + RestorePreAdditiveRootMotionVelocity(); + MaintainHorizontalGroundVelocity(); + Acceleration.Z = 0.f; + + if (!HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) { + CalcVelocity(TimeTick, GroundFriction, false, GetMaxBrakingDeceleration()); + } + + float VelocityDirection = FMath::Sign(Velocity.X) * DotDirection; + float NewDistanceAlongSpline = DistanceAlongSpline + VelocityDirection * Velocity.Size() * TimeTick; + NewDistanceAlongSpline = FMath::Clamp(NewDistanceAlongSpline, 0.0f, CombatPath->Spline->GetSplineLength()); + + FVector TargetLocation = CombatPath->Spline->GetLocationAtDistanceAlongSpline(NewDistanceAlongSpline, ESplineCoordinateSpace::World); + TargetLocation.Z = OldLocation.Z; + + FVector Direction = (TargetLocation - OldLocation).GetSafeNormal(); + + FHitResult MyHit; + + float DistanceOffset = NewDistanceAlongSpline - DistanceAlongSpline; + FVector Delta2 = TargetLocation - OldLocation; + SafeMoveUpdatedComponent(Delta2, UpdatedComponent->GetComponentQuat(), true, MyHit); + if (MyHit.Time < 1.0f) { + HandleImpact(MyHit, TimeTick, Delta2); + //DistanceAlongSpline += InputDotDirection * Velocity.Size() * TimeTick * MyHit.Distance; + } else { + DistanceAlongSpline = NewDistanceAlongSpline; + } + + if (OldLocation == UpdatedComponent->GetComponentLocation()) { + Velocity = FVector::Zero(); + } + + //continue; + + //Velocity = OldVelocity; + // Apply acceleration + if (!HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) { + //CalcVelocity(TimeTick, GroundFriction, false, GetMaxBrakingDeceleration()); + } + + if (IsFalling()) { + // Root motion could have put us into Falling. + // No movement has taken place this movement tick so we pass on full time/past iteration count + StartNewPhysics(RemainingTime + TimeTick, Iterations - 1); + return; + } + + // Compute move parameters + const FVector MoveVelocity = Velocity; + const FVector Delta = TimeTick * MoveVelocity; + const bool bZeroDelta = Delta.IsNearlyZero(); + FStepDownResult StepDownResult; + + if (bZeroDelta) { + RemainingTime = 0.f; + } else { + /*// try to move forward + MoveAlongFloor(MoveVelocity, TimeTick, &StepDownResult); + + if (IsFalling()) { + // pawn decided to jump up + const float DesiredDist = Delta.Size(); + if (DesiredDist > UE_KINDA_SMALL_NUMBER) { + const float ActualDist = (UpdatedComponent->GetComponentLocation() - OldLocation).Size2D(); + RemainingTime += TimeTick * (1.f - FMath::Min(1.f, ActualDist / DesiredDist)); + } + StartNewPhysics(RemainingTime, Iterations); + return; + } else if (IsSwimming()) //just entered water + { + StartSwimming(OldLocation, OldVelocity, TimeTick, RemainingTime, Iterations); + return; + }*/ + } + + continue; + // Update floor. + // StepUp might have already done it for us. + if (StepDownResult.bComputedFloor) { + CurrentFloor = StepDownResult.FloorResult; + } else { + FindFloor(UpdatedComponent->GetComponentLocation(), CurrentFloor, bZeroDelta, NULL); + } + + // check for ledges here + const bool bCheckLedges = !CanWalkOffLedges(); + if (bCheckLedges && !CurrentFloor.IsWalkableFloor()) { + // calculate possible alternate movement + const FVector GravDir = FVector(0.f, 0.f, -1.f); + const FVector NewDelta = bTriedLedgeMove ? FVector::ZeroVector : GetLedgeMove(OldLocation, Delta, GravDir); + if (!NewDelta.IsZero()) { + // first revert this move + RevertMove(OldLocation, OldBase, PreviousBaseLocation, OldFloor, false); + + // avoid repeated ledge moves if the first one fails + bTriedLedgeMove = true; + + // Try new movement direction + Velocity = NewDelta / TimeTick; + RemainingTime += TimeTick; + continue; + } else { + // see if it is OK to jump + // @todo collision : only thing that can be problem is that oldbase has world collision on + bool bMustJump = bZeroDelta || (OldBase == NULL || (!OldBase->IsQueryCollisionEnabled() && + MovementBaseUtility::IsDynamicBase(OldBase))); + if ((bMustJump || !bCheckedFall) && CheckFall(OldFloor, CurrentFloor.HitResult, Delta, OldLocation, RemainingTime, TimeTick, + Iterations, bMustJump)) { + return; + } + bCheckedFall = true; + + // revert this move + RevertMove(OldLocation, OldBase, PreviousBaseLocation, OldFloor, true); + RemainingTime = 0.f; + break; + } + } else { + // Validate the floor check + if (CurrentFloor.IsWalkableFloor()) { + if (ShouldCatchAir(OldFloor, CurrentFloor)) { + HandleWalkingOffLedge(OldFloor.HitResult.ImpactNormal, OldFloor.HitResult.Normal, OldLocation, TimeTick); + if (IsMovingOnGround()) { + // If still walking, then fall. If not, assume the user set a different mode they want to keep. + StartFalling(Iterations, RemainingTime, TimeTick, Delta, OldLocation); + } + return; + } + + AdjustFloorHeight(); + SetBase(CurrentFloor.HitResult.Component.Get(), CurrentFloor.HitResult.BoneName); + } else if (CurrentFloor.HitResult.bStartPenetrating && RemainingTime <= 0.f) { + // The floor check failed because it started in penetration + // We do not want to try to move downward because the downward sweep failed, rather we'd like to try to pop out of the floor. + FHitResult Hit(CurrentFloor.HitResult); + Hit.TraceEnd = Hit.TraceStart + FVector(0.f, 0.f, MAX_FLOOR_DIST); + const FVector RequestedAdjustment = GetPenetrationAdjustment(Hit); + ResolvePenetration(RequestedAdjustment, Hit, UpdatedComponent->GetComponentQuat()); + bForceNextFloorCheck = true; + } + + // check if just entered water + if (IsSwimming()) { + StartSwimming(OldLocation, Velocity, TimeTick, RemainingTime, Iterations); + return; + } + + // See if we need to start falling. + if (!CurrentFloor.IsWalkableFloor() && !CurrentFloor.HitResult.bStartPenetrating) { + const bool bMustJump = bJustTeleported || bZeroDelta || (OldBase == NULL || (!OldBase->IsQueryCollisionEnabled() && + MovementBaseUtility::IsDynamicBase(OldBase))); + if ((bMustJump || !bCheckedFall) && CheckFall(OldFloor, CurrentFloor.HitResult, Delta, OldLocation, RemainingTime, TimeTick, + Iterations, bMustJump)) { + return; + } + bCheckedFall = true; + } + } + + // Allow overlap events and such to change physics state and velocity + /*if (IsMovingOnGround()) { + // Make velocity reflect actual move + if (!bJustTeleported && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity() && TimeTick >= MIN_TICK_TIME) { + // TODO-RootMotionSource: Allow this to happen during partial override Velocity, but only set allowed axes? + Velocity = (UpdatedComponent->GetComponentLocation() - OldLocation) / TimeTick; + MaintainHorizontalGroundVelocity(); + } + } + + // If we didn't move at all this iteration then abort (since future iterations will also be stuck). + if (UpdatedComponent->GetComponentLocation() == OldLocation) { + RemainingTime = 0.f; + break; + }*/ + } + + if (IsMovingOnGround()) { + MaintainHorizontalGroundVelocity(); + } +} + +UE_ENABLE_OPTIMIZATION diff --git a/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp new file mode 100644 index 0000000..19a06e4 --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp @@ -0,0 +1,30 @@ +#include "GameplayModes/Combat/PwnCombatPlatformerPath.h" + +#include "Components/SplineComponent.h" +#include "GameplayModes/PwnGameplayModeSubsystem.h" + +APwnCombatPlatformerPath::APwnCombatPlatformerPath() { + PrimaryActorTick.bCanEverTick = false; + + Spline = CreateDefaultSubobject(TEXT("Spline")); + SetRootComponent(Spline); + +#if WITH_EDITORONLY_DATA + Spline->EditorSelectedSplineSegmentColor = FColor::FromHex("EBA30AFF"); + Spline->EditorUnselectedSplineSegmentColor = FColor::Red; +#endif +} + +void APwnCombatPlatformerPath::BeginPlay() { + UPwnGameplayModeSubsystem* Subsystem = GetWorld()->GetSubsystem(); + check(Subsystem); + Subsystem->RegisterCombatPath(this); + Super::BeginPlay(); +} + +void APwnCombatPlatformerPath::EndPlay(const EEndPlayReason::Type EndPlayReason) { + if (UPwnGameplayModeSubsystem* Subsystem = GetWorld()->GetSubsystem()) { + Subsystem->UnregisterCombatPath(this); + } + Super::EndPlay(EndPlayReason); +} diff --git a/Pawn_Unreal/Source/Pawn/Private/GameplayModes/PwnGameplayModeSubsystem.cpp b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/PwnGameplayModeSubsystem.cpp index 8cdb663..bd771ad 100644 --- a/Pawn_Unreal/Source/Pawn/Private/GameplayModes/PwnGameplayModeSubsystem.cpp +++ b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/PwnGameplayModeSubsystem.cpp @@ -1,5 +1,8 @@ #include "GameplayModes/PwnGameplayModeSubsystem.h" +#include "Components/SplineComponent.h" +#include "GameplayModes/Combat/PwnCombatPlatformerPath.h" + void UPwnGameplayModeSubsystem::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection); CurrentGameplayMode = EPwnGameplayMode::Narrative; @@ -25,6 +28,46 @@ EPwnGameplayMode UPwnGameplayModeSubsystem::GetCurrentGameplayMode() const { bool UPwnGameplayModeSubsystem::IsNarrativeMode() const { return CurrentGameplayMode == EPwnGameplayMode::Narrative; } + bool UPwnGameplayModeSubsystem::IsCombatMode() const { return CurrentGameplayMode == EPwnGameplayMode::Combat; } + +void UPwnGameplayModeSubsystem::RegisterCombatPath(APwnCombatPlatformerPath* CombatPath) { + CombatPaths.Add(CombatPath); +} + +void UPwnGameplayModeSubsystem::UnregisterCombatPath(APwnCombatPlatformerPath* CombatPath) { + CombatPaths.Remove(CombatPath); +} + +bool UPwnGameplayModeSubsystem::FindClosestCombatPathLocation(const FVector& Location, FVector& OutCombatPathLocation, + APwnCombatPlatformerPath*& OutCombatPath, float& OutDistanceAlongSpline) const { + float ShortestDistance = FLT_MAX; + float ClosestKey = 0.0f; + FVector ClosestLocation = FVector::ZeroVector; + APwnCombatPlatformerPath* ClosestCombatPath = nullptr; + bool Found = false; + + for (APwnCombatPlatformerPath* CombatPath : CombatPaths) { + const USplineComponent* CurrentSpline = CombatPath->Spline; + + const float CurrentKey = CurrentSpline->FindInputKeyClosestToWorldLocation(Location); + FVector CurrentLocation = CurrentSpline->GetLocationAtSplineInputKey(CurrentKey, ESplineCoordinateSpace::World); + const float CurrentDistance = FVector::DistSquared(Location, CurrentLocation); + if (CurrentDistance < ShortestDistance) { + ShortestDistance = CurrentDistance; + ClosestKey = CurrentKey; + ClosestLocation = CurrentLocation; + ClosestCombatPath = CombatPath; + Found = true; + } + } + + if (Found) { + OutCombatPathLocation = ClosestLocation; + OutCombatPath = ClosestCombatPath; + OutDistanceAlongSpline = OutCombatPath->Spline->GetDistanceAlongSplineAtSplineInputKey(ClosestKey); + } + return Found; +} diff --git a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterBase.h b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterBase.h new file mode 100644 index 0000000..270a6dc --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterBase.h @@ -0,0 +1,25 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Character.h" +#include "PwnCharacterBase.generated.h" + +class UPwnCharacterMovementComponent; + +UCLASS() +class PAWN_API APwnCharacterBase : public ACharacter { + GENERATED_BODY() + +public: + APwnCharacterBase(const FObjectInitializer& ObjectInitializer); + +protected: + virtual void BeginPlay() override; + +public: + virtual void Tick(float DeltaTime) override; + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components") + TObjectPtr PwnCharacterMovementComponent; +}; diff --git a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h new file mode 100644 index 0000000..6a2aa12 --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h @@ -0,0 +1,59 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "PwnCharacterMovementComponent.generated.h" + +class APwnCombatPlatformerPath; + +UENUM(BlueprintType) +enum ECustomMovementMode : uint8 { + None UMETA(Hidden), + SplineWalking, + SplineFalling +}; + +UCLASS(meta=(BlueprintSpawnableComponent)) +class PAWN_API UPwnCharacterMovementComponent : public UCharacterMovementComponent { + GENERATED_BODY() + +public: + UPwnCharacterMovementComponent(); + +protected: + virtual void BeginPlay() override; + + virtual float GetMaxBrakingDeceleration() const override; + + virtual float GetMaxSpeed() const override; + + virtual bool IsMovingOnGround() const override; + +public: + UFUNCTION(BlueprintCallable, Category="CharacterMovement") + void EnterSplineFollowMode(); + + UFUNCTION(BlueprintCallable, Category="CharacterMovement") + void ExitSplineFollowMode(); + + UFUNCTION(BlueprintCallable, Category="CharacterMovement") + bool IsCustomMovementMode(const ECustomMovementMode Mode) const; + + virtual void PhysCustom(const float DeltaTime, int32 Iterations) override; + +private: + void PhysSplineFollow(const float DeltaTime, int32 Iterations); + +public: + UPROPERTY(BlueprintReadOnly) + TObjectPtr CombatPath; + + UPROPERTY(BlueprintReadOnly) + float DistanceAlongSpline; + + UPROPERTY(BlueprintReadOnly) + float DotDirection; + + UPROPERTY(BlueprintReadWrite) + float Input; +}; diff --git a/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h new file mode 100644 index 0000000..4b570a9 --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h @@ -0,0 +1,30 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "PwnCombatPlatformerPath.generated.h" + +class USplineComponent; + +UCLASS() +class PAWN_API APwnCombatPlatformerPath : public AActor { + GENERATED_BODY() + +public: + APwnCombatPlatformerPath(); + +protected: + virtual void BeginPlay() override; + + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Components") + TObjectPtr Spline; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat Platformer Path") + bool Reversed; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat Platformer Path") + bool SwapCamera; +}; diff --git a/Pawn_Unreal/Source/Pawn/Public/GameplayModes/PwnGameplayModeSubsystem.h b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/PwnGameplayModeSubsystem.h index 9ee228d..a7b7334 100644 --- a/Pawn_Unreal/Source/Pawn/Public/GameplayModes/PwnGameplayModeSubsystem.h +++ b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/PwnGameplayModeSubsystem.h @@ -4,6 +4,8 @@ #include "Subsystems/WorldSubsystem.h" #include "PwnGameplayModeSubsystem.generated.h" +class APwnCombatPlatformerPath; + UENUM(BlueprintType, DisplayName = "Gameplay Mode") enum class EPwnGameplayMode : uint8 { Narrative, @@ -33,10 +35,24 @@ public: UFUNCTION(BlueprintCallable, BlueprintPure, Category="Gameplay Modes") bool IsCombatMode() const; + UFUNCTION() + void RegisterCombatPath(APwnCombatPlatformerPath* CombatPath); + + UFUNCTION() + void UnregisterCombatPath(APwnCombatPlatformerPath* CombatPath); + + UFUNCTION() + bool FindClosestCombatPathLocation(const FVector& Location, FVector& OutCombatPathLocation, APwnCombatPlatformerPath*& OutCombatPath, + float& OutDistanceAlongSpline) const; + public: UPROPERTY(BlueprintAssignable) FGameplayModeChangedDelegate OnGameplayModeChanged; private: + UPROPERTY() EPwnGameplayMode CurrentGameplayMode; + + UPROPERTY() + TArray> CombatPaths; }; diff --git a/Pawn_Unreal/Source/Pawn/Public/Utils/EngineUtils.h b/Pawn_Unreal/Source/Pawn/Public/Utils/EngineUtils.h new file mode 100644 index 0000000..959acec --- /dev/null +++ b/Pawn_Unreal/Source/Pawn/Public/Utils/EngineUtils.h @@ -0,0 +1,9 @@ +#pragma once + +#define PRINT_STRING(Key, Time, Color, Content, ...) GEngine->AddOnScreenDebugMessage(Key, Time, Color, FString::Printf(TEXT(Content), __VA_ARGS__)); +#define PRINT_STRING_GENERIC(Color, Content, ...) PRINT_STRING(-1, 4.0f, Color, Content, __VA_ARGS__); +#define PRINT_STRING_WHITE(Content, ...) PRINT_STRING_GENERIC(FColor::White, Content, __VA_ARGS__); +#define PRINT_STRING_BLUE(Content, ...) PRINT_STRING_GENERIC(FColor::Blue, Content, __VA_ARGS__); +#define PRINT_STRING_RED(Content, ...) PRINT_STRING_GENERIC(FColor::Red, Content, __VA_ARGS__); +#define PRINT_STRING_YELLOW(Content, ...) PRINT_STRING_GENERIC(FColor::Yellow, Content, __VA_ARGS__); +#define PRINT_STRING_GREEN(Content, ...) PRINT_STRING_GENERIC(FColor::Green, Content, __VA_ARGS__);