diff --git a/.gitignore b/.gitignore index 6582eaf..faf6bd0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Visual Studio 2015 user specific files .vs/ +.idea/ # Compiled Object files *.slo diff --git a/.idea/.idea.TurnBased/.idea/.gitignore b/.idea/.idea.TurnBased/.idea/.gitignore new file mode 100644 index 0000000..bdaabaf --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/contentModel.xml +/projectSettingsUpdater.xml +/.idea.TurnBased.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.TurnBased/.idea/.name b/.idea/.idea.TurnBased/.idea/.name new file mode 100644 index 0000000..496e6cf --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/.name @@ -0,0 +1 @@ +TurnBased \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/encodings.xml b/.idea/.idea.TurnBased/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/indexLayout.xml b/.idea/.idea.TurnBased/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/vcs.xml b/.idea/.idea.TurnBased/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini index e69de29..8b13789 100644 --- a/Config/DefaultEditor.ini +++ b/Config/DefaultEditor.ini @@ -0,0 +1 @@ + diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 50c64f0..57ead6b 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -1,7 +1,7 @@ [/Script/EngineSettings.GameMapsSettings] -EditorStartupMap=/Game/BattleField/BattleFieldMap.BattleFieldMap +EditorStartupMap=/Game/MainMenu/MainMenuLevel.MainMenuLevel LocalMapOptions= TransitionMap=None bUseSplitscreen=True @@ -12,7 +12,7 @@ bOffsetPlayerGamepadIds=False GameInstanceClass=/Script/Engine.GameInstance GameDefaultMap=/Game/MainMenu/MainMenuLevel.MainMenuLevel ServerDefaultMap=/Engine/Maps/Entry.Entry -GlobalDefaultGameMode=/Script/TurnBasedTutorial.MyGameMode +GlobalDefaultGameMode=/Script/Engine.GameMode GlobalDefaultServerGameMode=None [/Script/HardwareTargeting.HardwareTargetingSettings] @@ -26,3 +26,30 @@ AppliedDefaultGraphicsPerformance=Maximum +ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/TurnBasedTutorial") +ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="TurnBasedTutorialGameModeBase") +[CoreRedirects] ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.OnPlayersSide",NewName="/Script/TurnBasedTutorial.Trooper.bOnPlayersSide") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerController.MoveHero",NewName="/Script/TurnBasedTutorial.MyPlayerController.MoveTropper") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerController.MoveTropper",NewName="/Script/TurnBasedTutorial.MyPlayerController.MoveTrooper") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.ManageSquadTrooper.IndexInSquad",NewName="/Script/TurnBasedTutorial.ManageSquadTrooper.Index") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.ManageSquadTrooper.IndexInSquadOrSample",NewName="/Script/TurnBasedTutorial.ManageSquadTrooper.Index") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.GetActionCost",NewName="/Script/TurnBasedTutorial.Trooper.GetActionRadius") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.GetActionCost",NewName="/Script/TurnBasedTutorial.Trooper.GetActionRadius") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.RedMaterialInterface",NewName="/Script/TurnBasedTutorial.Trooper.RedMaterial") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.HighlightEnemy",NewName="/Script/TurnBasedTutorial.Trooper.HighlightAsEnemy") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.bIsDying",NewName="/Script/TurnBasedTutorial.Trooper.bIsDead") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.bIsDying",NewName="/Script/TurnBasedTutorial.Trooper.bIsDead") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyGameInstanceSubsystem",NewName="/Script/TurnBasedTutorial.SessionsGameInstanceSubsystem") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyMainMenu",NewName="/Script/TurnBasedTutorial.MainMenuWidget") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MySessionListEntryWidget",NewName="/Script/TurnBasedTutorial.SessionListEntryWidget") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MySessionListWidget",NewName="/Script/TurnBasedTutorial.SessionListWidget") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyGameMode",NewName="/Script/TurnBasedTutorial.BattleGameMode") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyGameState",NewName="/Script/TurnBasedTutorial.BattleGameState") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyPawn",NewName="/Script/TurnBasedTutorial.BattlePawn") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerController",NewName="/Script/TurnBasedTutorial.BattlePlayerController") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerStart",NewName="/Script/TurnBasedTutorial.BattlePlayerStart") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerState",NewName="/Script/TurnBasedTutorial.BattlePlayerState") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyExplosion",NewName="/Script/TurnBasedTutorial.Explosion") ++ClassRedirects=(OldName="/Script/TurnBasedTutorial.MyProjectile",NewName="/Script/TurnBasedTutorial.Projectile") + +[OnlineSubsystem] +DefaultPlatformService=Null diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 07e992c..3d5b79e 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -78,6 +78,8 @@ DefaultViewportMouseLockMode=LockOnCapture FOVScale=0.011110 DoubleClickTime=0.200000 +ActionMappings=(ActionName="MyAction",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) ++AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) DefaultPlayerInputClass=/Script/Engine.PlayerInput DefaultInputComponentClass=/Script/Engine.InputComponent DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks diff --git a/Content/Animations/BP_TrooperAnimations.uasset b/Content/Animations/BP_TrooperAnimations.uasset new file mode 100644 index 0000000..1dda306 Binary files /dev/null and b/Content/Animations/BP_TrooperAnimations.uasset differ diff --git a/Content/BP_MyGameMode.uasset b/Content/BP_MyGameMode.uasset new file mode 100644 index 0000000..204d94f Binary files /dev/null and b/Content/BP_MyGameMode.uasset differ diff --git a/Content/BattleField/BP_BattlePawn.uasset b/Content/BattleField/BP_BattlePawn.uasset new file mode 100644 index 0000000..a02872f Binary files /dev/null and b/Content/BattleField/BP_BattlePawn.uasset differ diff --git a/Content/BattleField/BP_BattlePlayerController.uasset b/Content/BattleField/BP_BattlePlayerController.uasset new file mode 100644 index 0000000..5f65d44 Binary files /dev/null and b/Content/BattleField/BP_BattlePlayerController.uasset differ diff --git a/Content/BattleField/BP_BattlePlayerState.uasset b/Content/BattleField/BP_BattlePlayerState.uasset new file mode 100644 index 0000000..f9d5f91 Binary files /dev/null and b/Content/BattleField/BP_BattlePlayerState.uasset differ diff --git a/Content/BattleField/BP_BattleUI.uasset b/Content/BattleField/BP_BattleUI.uasset new file mode 100644 index 0000000..8c09052 Binary files /dev/null and b/Content/BattleField/BP_BattleUI.uasset differ diff --git a/Content/BattleField/BP_EndOfGameWidget.uasset b/Content/BattleField/BP_EndOfGameWidget.uasset new file mode 100644 index 0000000..0cdda72 Binary files /dev/null and b/Content/BattleField/BP_EndOfGameWidget.uasset differ diff --git a/Content/BattleField/BP_InventoryUI.uasset b/Content/BattleField/BP_InventoryUI.uasset new file mode 100644 index 0000000..21470fe Binary files /dev/null and b/Content/BattleField/BP_InventoryUI.uasset differ diff --git a/Content/BattleField/BP_MyGameMode.uasset b/Content/BattleField/BP_MyGameMode.uasset new file mode 100644 index 0000000..ef3b99a Binary files /dev/null and b/Content/BattleField/BP_MyGameMode.uasset differ diff --git a/Content/BattleField/Multiplayer/BP_BattleGameMode.uasset b/Content/BattleField/Multiplayer/BP_BattleGameMode.uasset new file mode 100644 index 0000000..ce38b8d Binary files /dev/null and b/Content/BattleField/Multiplayer/BP_BattleGameMode.uasset differ diff --git a/Content/BattleField/Multiplayer/BP_BattleGameState.uasset b/Content/BattleField/Multiplayer/BP_BattleGameState.uasset new file mode 100644 index 0000000..fc721a6 Binary files /dev/null and b/Content/BattleField/Multiplayer/BP_BattleGameState.uasset differ diff --git a/Content/BattleField/Multiplayer/BP_MyGameMode.uasset b/Content/BattleField/Multiplayer/BP_MyGameMode.uasset new file mode 100644 index 0000000..2ac5118 Binary files /dev/null and b/Content/BattleField/Multiplayer/BP_MyGameMode.uasset differ diff --git a/Content/BattleField/BattleFieldMap.umap b/Content/BattleField/Multiplayer/BattleFieldMap.umap similarity index 94% rename from Content/BattleField/BattleFieldMap.umap rename to Content/BattleField/Multiplayer/BattleFieldMap.umap index 8f7cb0e..9d0bed5 100644 Binary files a/Content/BattleField/BattleFieldMap.umap and b/Content/BattleField/Multiplayer/BattleFieldMap.umap differ diff --git a/Content/BattleField/SinglePlayer/BP_SinglePlayerGM.uasset b/Content/BattleField/SinglePlayer/BP_SinglePlayerGM.uasset new file mode 100644 index 0000000..0a6b17d Binary files /dev/null and b/Content/BattleField/SinglePlayer/BP_SinglePlayerGM.uasset differ diff --git a/Content/BattleField/SinglePlayer/BP_SinglePlayerGS.uasset b/Content/BattleField/SinglePlayer/BP_SinglePlayerGS.uasset new file mode 100644 index 0000000..31f2b76 Binary files /dev/null and b/Content/BattleField/SinglePlayer/BP_SinglePlayerGS.uasset differ diff --git a/Content/BattleField/SinglePlayer/OfflineBattleFieldMap.umap b/Content/BattleField/SinglePlayer/OfflineBattleFieldMap.umap new file mode 100644 index 0000000..a70b900 Binary files /dev/null and b/Content/BattleField/SinglePlayer/OfflineBattleFieldMap.umap differ diff --git a/Content/BattleField/UI_images/384-3845034_magic-wand-magic-wands-clipart-black-and-white.uasset b/Content/BattleField/UI_images/384-3845034_magic-wand-magic-wands-clipart-black-and-white.uasset new file mode 100644 index 0000000..4046bae Binary files /dev/null and b/Content/BattleField/UI_images/384-3845034_magic-wand-magic-wands-clipart-black-and-white.uasset differ diff --git a/Content/BattleField/UI_images/69-698852_footprints-png-136006.uasset b/Content/BattleField/UI_images/69-698852_footprints-png-136006.uasset new file mode 100644 index 0000000..1fe4cee Binary files /dev/null and b/Content/BattleField/UI_images/69-698852_footprints-png-136006.uasset differ diff --git a/Content/BattleField/UI_images/explosion-clip-art-33.uasset b/Content/BattleField/UI_images/explosion-clip-art-33.uasset new file mode 100644 index 0000000..8c4fda6 Binary files /dev/null and b/Content/BattleField/UI_images/explosion-clip-art-33.uasset differ diff --git a/Content/BattleField/UI_images/img_525444.uasset b/Content/BattleField/UI_images/img_525444.uasset new file mode 100644 index 0000000..7007f6d Binary files /dev/null and b/Content/BattleField/UI_images/img_525444.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/ArcherBow_Inst.uasset b/Content/CityofBrass_Enemies/Materials/ArcherBow_Inst.uasset new file mode 100644 index 0000000..ef3317e Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/ArcherBow_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Archer_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Archer_Inst.uasset new file mode 100644 index 0000000..b648fed Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Archer_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/BossAxe_Inst.uasset b/Content/CityofBrass_Enemies/Materials/BossAxe_Inst.uasset new file mode 100644 index 0000000..38c3693 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/BossAxe_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Character_Substance_Invisible_Material.uasset b/Content/CityofBrass_Enemies/Materials/Character_Substance_Invisible_Material.uasset new file mode 100644 index 0000000..211ca9f Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Character_Substance_Invisible_Material.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Character_Substance_Layers_Material.uasset b/Content/CityofBrass_Enemies/Materials/Character_Substance_Layers_Material.uasset new file mode 100644 index 0000000..c137e6e Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Character_Substance_Layers_Material.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/CorpseSpear_Inst.uasset b/Content/CityofBrass_Enemies/Materials/CorpseSpear_Inst.uasset new file mode 100644 index 0000000..136c19a Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/CorpseSpear_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Body_Inst2.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Body_Inst2.uasset new file mode 100644 index 0000000..ba92e26 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Body_Inst2.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Helmet_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Helmet_Inst.uasset new file mode 100644 index 0000000..4b62a53 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Helmet_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Inst.uasset new file mode 100644 index 0000000..8535327 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Charger_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Clothes_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Clothes_Inst.uasset new file mode 100644 index 0000000..7c1df12 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Clothes_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Fez_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Fez_Inst.uasset new file mode 100644 index 0000000..a9771ad Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Fez_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Corpse_Melee_Dress_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Corpse_Melee_Dress_Inst.uasset new file mode 100644 index 0000000..8a85657 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Corpse_Melee_Dress_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Enviro_Substance_Material.uasset b/Content/CityofBrass_Enemies/Materials/Enviro_Substance_Material.uasset new file mode 100644 index 0000000..be48d80 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Enviro_Substance_Material.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/FermaleWarrior_Inst.uasset b/Content/CityofBrass_Enemies/Materials/FermaleWarrior_Inst.uasset new file mode 100644 index 0000000..641d9e1 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/FermaleWarrior_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/GrenadierBody_Inst.uasset b/Content/CityofBrass_Enemies/Materials/GrenadierBody_Inst.uasset new file mode 100644 index 0000000..9627385 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/GrenadierBody_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Grenadier_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Grenadier_Inst.uasset new file mode 100644 index 0000000..aed3485 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Grenadier_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Hooker_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Hooker_Inst.uasset new file mode 100644 index 0000000..0ec58f4 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Hooker_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Large_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Large_Inst.uasset new file mode 100644 index 0000000..d42e8a3 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Large_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Player_Sword_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Player_Sword_Inst.uasset new file mode 100644 index 0000000..93bb0b7 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Player_Sword_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/SploderBody_Inst1.uasset b/Content/CityofBrass_Enemies/Materials/SploderBody_Inst1.uasset new file mode 100644 index 0000000..c24dede Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/SploderBody_Inst1.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Sploder_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Sploder_Inst.uasset new file mode 100644 index 0000000..669c953 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Sploder_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Materials/Wizard_Inst.uasset b/Content/CityofBrass_Enemies/Materials/Wizard_Inst.uasset new file mode 100644 index 0000000..243f563 Binary files /dev/null and b/Content/CityofBrass_Enemies/Materials/Wizard_Inst.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer.uasset new file mode 100644 index 0000000..aad61d9 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon.uasset new file mode 100644 index 0000000..8c0c2fc Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_PhysicsAsset.uasset new file mode 100644 index 0000000..7dee666 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_Skeleton.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_Skeleton.uasset new file mode 100644 index 0000000..2002a33 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer_Bow_Weapon_Skeleton.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer__mesh_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer__mesh_PhysicsAsset.uasset new file mode 100644 index 0000000..7bf75fc Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer__mesh_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Aggro.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Aggro.uasset new file mode 100644 index 0000000..4eb0659 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Aggro.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Attack_Close.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Attack_Close.uasset new file mode 100644 index 0000000..39f5e2f Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Attack_Close.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeAttack.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeAttack.uasset new file mode 100644 index 0000000..c591275 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeAttack.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeWall.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeWall.uasset new file mode 100644 index 0000000..801eac3 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_ChargeWall.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Ilde.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Ilde.uasset new file mode 100644 index 0000000..130c546 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Ilde.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Sprint.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Sprint.uasset new file mode 100644 index 0000000..9f0df5b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Sprint.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Stunned.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Stunned.uasset new file mode 100644 index 0000000..4b8d7e8 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_Stunned.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_run.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_run.uasset new file mode 100644 index 0000000..a8a9c8d Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Alert_run.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Death.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Death.uasset new file mode 100644 index 0000000..d0fd0ee Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Death.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Flinch_back.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Flinch_back.uasset new file mode 100644 index 0000000..9263ca6 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Flinch_back.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_KnockDown.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_KnockDown.uasset new file mode 100644 index 0000000..a7c43d5 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_KnockDown.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Ilde.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Ilde.uasset new file mode 100644 index 0000000..c90ffa8 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Ilde.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Walk.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Walk.uasset new file mode 100644 index 0000000..9e9cd4c Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Animation/Charger_Passive_Walk.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger.uasset new file mode 100644 index 0000000..86daa92 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_Helmet.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_Helmet.uasset new file mode 100644 index 0000000..d17b337 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_Helmet.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_PhysicsAsset.uasset new file mode 100644 index 0000000..ea86520 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Charger/Charger_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Skeleton.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Skeleton.uasset new file mode 100644 index 0000000..8a2d4fd Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Skeleton.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword.uasset new file mode 100644 index 0000000..05cae6f Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_BaseColor.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_BaseColor.uasset new file mode 100644 index 0000000..1cd7fa5 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_BaseColor.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_Normal.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_Normal.uasset new file mode 100644 index 0000000..ef4b7e0 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_Normal.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset new file mode 100644 index 0000000..9a5e24d Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_PhysicsAsset.uasset new file mode 100644 index 0000000..b337ea9 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_ShadowPhysics.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_ShadowPhysics.uasset new file mode 100644 index 0000000..eebc999 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_ShadowPhysics.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Turban.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Turban.uasset new file mode 100644 index 0000000..be667bd Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/Corpse_Sword_Turban.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Approach.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Approach.uasset new file mode 100644 index 0000000..c1258cb Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Approach.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic01.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic01.uasset new file mode 100644 index 0000000..1e9316e Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic01.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic02.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic02.uasset new file mode 100644 index 0000000..c49113f Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic02.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic03.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic03.uasset new file mode 100644 index 0000000..52872ad Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic03.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic04.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic04.uasset new file mode 100644 index 0000000..9053c82 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Basic04.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast.uasset new file mode 100644 index 0000000..a0e84be Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast2.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast2.uasset new file mode 100644 index 0000000..88df60a Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Fast2.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Push.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Push.uasset new file mode 100644 index 0000000..b22f295 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Push.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Shield_Push.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Shield_Push.uasset new file mode 100644 index 0000000..6b2dd00 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Shield_Push.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Slow.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Slow.uasset new file mode 100644 index 0000000..b4d6c4a Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Attack_Slow.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death.uasset new file mode 100644 index 0000000..0a67a4e Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death2.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death2.uasset new file mode 100644 index 0000000..c6fefe4 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death2.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death3.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death3.uasset new file mode 100644 index 0000000..8f2b36b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Death3.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Distracted_Grab.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Distracted_Grab.uasset new file mode 100644 index 0000000..e37e06b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Distracted_Grab.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stun_Knock_Back.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stun_Knock_Back.uasset new file mode 100644 index 0000000..4c42817 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stun_Knock_Back.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stunned.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stunned.uasset new file mode 100644 index 0000000..bc0e24b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Stunned.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Taunt.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Taunt.uasset new file mode 100644 index 0000000..2398e1f Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Taunt.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped.uasset new file mode 100644 index 0000000..6364d47 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped_Forward.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped_Forward.uasset new file mode 100644 index 0000000..401b45a Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_Tripped_Forward.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_AddBase.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_AddBase.uasset new file mode 100644 index 0000000..c6fd420 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_AddBase.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_45.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_45.uasset new file mode 100644 index 0000000..3d917f3 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_45.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_90.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_90.uasset new file mode 100644 index 0000000..333f9c1 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Left_90.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Middle.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Middle.uasset new file mode 100644 index 0000000..f4c6a5f Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Middle.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_45.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_45.uasset new file mode 100644 index 0000000..fc8badb Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_45.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_90.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_90.uasset new file mode 100644 index 0000000..2621300 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Alert_turn_Right_90.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Disarm.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Disarm.uasset new file mode 100644 index 0000000..8a43aff Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Disarm.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Back.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Back.uasset new file mode 100644 index 0000000..2d1c951 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Back.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Forward.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Forward.uasset new file mode 100644 index 0000000..3cb17c4 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Forward.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Left.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Left.uasset new file mode 100644 index 0000000..41a6c0a Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Left.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Right.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Right.uasset new file mode 100644 index 0000000..b66ddc5 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_Run_Right.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_attack_right.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_attack_right.uasset new file mode 100644 index 0000000..48c9974 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_attack_right.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_idle.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_idle.uasset new file mode 100644 index 0000000..114a389 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_alert_idle.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_passive_idle.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_passive_idle.uasset new file mode 100644 index 0000000..c4272e7 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse/animation/Corpse_passive_idle.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Corpse_Basic.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Corpse_Basic.uasset new file mode 100644 index 0000000..4a7befe Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Corpse_Basic.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Fez_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Fez_Mesh.uasset new file mode 100644 index 0000000..45b2fdd Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Basic/Fez_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee.uasset new file mode 100644 index 0000000..00474d9 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee_PhysicsAsset.uasset new file mode 100644 index 0000000..29ffd2b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Melee/Corpse_Melee_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Helmet.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Helmet.uasset new file mode 100644 index 0000000..1718f72 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Helmet.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Mesh.uasset new file mode 100644 index 0000000..19c1773 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/CorpseSpear_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Large.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Large.uasset new file mode 100644 index 0000000..ee1a19a Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Large.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Small.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Small.uasset new file mode 100644 index 0000000..3ce2c81 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Corpse_Spear/animation/Spear_Alert_Attack_Small.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Animation/Grenadier_Attack_Throw.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Animation/Grenadier_Attack_Throw.uasset new file mode 100644 index 0000000..2b0add9 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Animation/Grenadier_Attack_Throw.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Hat.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Hat.uasset new file mode 100644 index 0000000..3b6ff5c Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Hat.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Mesh.uasset new file mode 100644 index 0000000..4cc2631 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Grenadier/Grenadier_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Boss_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Boss_Mesh.uasset new file mode 100644 index 0000000..3e250cb Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Boss_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel.uasset new file mode 100644 index 0000000..72c4158 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Physics.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Physics.uasset new file mode 100644 index 0000000..010e136 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Physics.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Skeleton.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Skeleton.uasset new file mode 100644 index 0000000..60a6444 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Claw_Skel_Skeleton.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Mesh.uasset new file mode 100644 index 0000000..d85295b Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Hooker/Hooker_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_Mesh.uasset new file mode 100644 index 0000000..523fd03 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_PhysicsAsset.uasset new file mode 100644 index 0000000..d29a4ad Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Large/Large_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Charger/Large_Charger_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Charger/Large_Charger_Mesh.uasset new file mode 100644 index 0000000..56f4f22 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Charger/Large_Charger_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Sword/Large_Sword.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Sword/Large_Sword.uasset new file mode 100644 index 0000000..531a7ea Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Large_Sword/Large_Sword.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_D.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_D.uasset new file mode 100644 index 0000000..709d7a6 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_M.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_M.uasset new file mode 100644 index 0000000..af87252 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_N.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_N.uasset new file mode 100644 index 0000000..1768667 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/SploderBody_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_D.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_D.uasset new file mode 100644 index 0000000..7515917 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_M.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_M.uasset new file mode 100644 index 0000000..26037cf Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_Mesh.uasset new file mode 100644 index 0000000..4394c39 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_N.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_N.uasset new file mode 100644 index 0000000..f026fde Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sploder/Sploder_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh.uasset new file mode 100644 index 0000000..5252fe0 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Physics.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Physics.uasset new file mode 100644 index 0000000..4190ac8 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Physics.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Skeleton.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Skeleton.uasset new file mode 100644 index 0000000..26a2281 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/Player_Sword_Mesh_Skeleton.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/enemy_Sword_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/enemy_Sword_Mesh.uasset new file mode 100644 index 0000000..99e7212 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Sword/enemy_Sword_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/FemaleWizard_Mesh_PhysicsAsset.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/FemaleWizard_Mesh_PhysicsAsset.uasset new file mode 100644 index 0000000..a3eaa42 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/FemaleWizard_Mesh_PhysicsAsset.uasset differ diff --git a/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/Wizard_Mesh.uasset b/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/Wizard_Mesh.uasset new file mode 100644 index 0000000..b177008 Binary files /dev/null and b/Content/CityofBrass_Enemies/Meshes/Enemy/Wizard/Wizard_Mesh.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_Bow_D.uasset b/Content/CityofBrass_Enemies/Textures/Archer_Bow_D.uasset new file mode 100644 index 0000000..4b1706c Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_Bow_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_Bow_M.uasset b/Content/CityofBrass_Enemies/Textures/Archer_Bow_M.uasset new file mode 100644 index 0000000..c916c50 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_Bow_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_Bow_N.uasset b/Content/CityofBrass_Enemies/Textures/Archer_Bow_N.uasset new file mode 100644 index 0000000..29b6604 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_Bow_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_D.uasset b/Content/CityofBrass_Enemies/Textures/Archer_D.uasset new file mode 100644 index 0000000..205fcb0 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_M.uasset b/Content/CityofBrass_Enemies/Textures/Archer_M.uasset new file mode 100644 index 0000000..ba8cb99 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Archer_N.uasset b/Content/CityofBrass_Enemies/Textures/Archer_N.uasset new file mode 100644 index 0000000..ffd5f36 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Archer_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Charger_Helmet_D.uasset b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_D.uasset new file mode 100644 index 0000000..ccb429e Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Charger_Helmet_Mask.uasset b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_Mask.uasset new file mode 100644 index 0000000..c600d75 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_Mask.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Charger_Helmet_N.uasset b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_N.uasset new file mode 100644 index 0000000..57eafac Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Charger_Helmet_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/CorpseSpear_D.uasset b/Content/CityofBrass_Enemies/Textures/CorpseSpear_D.uasset new file mode 100644 index 0000000..0472196 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/CorpseSpear_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/CorpseSpear_M.uasset b/Content/CityofBrass_Enemies/Textures/CorpseSpear_M.uasset new file mode 100644 index 0000000..6102810 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/CorpseSpear_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/CorpseSpear_N.uasset b/Content/CityofBrass_Enemies/Textures/CorpseSpear_N.uasset new file mode 100644 index 0000000..78e1f7d Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/CorpseSpear_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_BaseColor.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_BaseColor.uasset new file mode 100644 index 0000000..a6a2e10 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_BaseColor.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_Normal.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_Normal.uasset new file mode 100644 index 0000000..194c65c Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_Normal.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset new file mode 100644 index 0000000..b355e5e Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Body_Low_green_OcclusionRoughnessMetallic.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_BaseColor.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_BaseColor.uasset new file mode 100644 index 0000000..7254eca Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_BaseColor.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_Normal.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_Normal.uasset new file mode 100644 index 0000000..b0c1f85 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_Normal.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_OcclusionRoughnessMetallic.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_OcclusionRoughnessMetallic.uasset new file mode 100644 index 0000000..38227c0 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_Sword_Clothes_Low_02_-_Default_OcclusionRoughnessMetallic.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_BaseColor.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_BaseColor.uasset new file mode 100644 index 0000000..f4a0a1b Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_BaseColor.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_Normal.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_Normal.uasset new file mode 100644 index 0000000..b596051 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_Normal.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_OcclusionRoughnessMetallic.uasset b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_OcclusionRoughnessMetallic.uasset new file mode 100644 index 0000000..54568e3 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Corpse_body_Complete_10011_OcclusionRoughnessMetallic.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/DiffuseTextureTest.uasset b/Content/CityofBrass_Enemies/Textures/DiffuseTextureTest.uasset new file mode 100644 index 0000000..0ba4c99 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/DiffuseTextureTest.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/FemaleWarrior_D.uasset b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_D.uasset new file mode 100644 index 0000000..b27e518 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/FemaleWarrior_M.uasset b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_M.uasset new file mode 100644 index 0000000..787112e Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/FemaleWarrior_N.uasset b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_N.uasset new file mode 100644 index 0000000..cce1152 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/FemaleWarrior_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Fez_D.uasset b/Content/CityofBrass_Enemies/Textures/Fez_D.uasset new file mode 100644 index 0000000..a99d182 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Fez_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Fez_Mask.uasset b/Content/CityofBrass_Enemies/Textures/Fez_Mask.uasset new file mode 100644 index 0000000..686b69a Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Fez_Mask.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Fez_N.uasset b/Content/CityofBrass_Enemies/Textures/Fez_N.uasset new file mode 100644 index 0000000..98374e8 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Fez_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/GrenadierBody_M.uasset b/Content/CityofBrass_Enemies/Textures/GrenadierBody_M.uasset new file mode 100644 index 0000000..026fb53 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/GrenadierBody_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/GrenadierBody_N.uasset b/Content/CityofBrass_Enemies/Textures/GrenadierBody_N.uasset new file mode 100644 index 0000000..1254012 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/GrenadierBody_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/GrenadierClothes_D.uasset b/Content/CityofBrass_Enemies/Textures/GrenadierClothes_D.uasset new file mode 100644 index 0000000..7423be1 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/GrenadierClothes_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Grenadier_D.uasset b/Content/CityofBrass_Enemies/Textures/Grenadier_D.uasset new file mode 100644 index 0000000..6983eee Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Grenadier_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Grenadier_M.uasset b/Content/CityofBrass_Enemies/Textures/Grenadier_M.uasset new file mode 100644 index 0000000..6deb413 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Grenadier_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Grenadier_N.uasset b/Content/CityofBrass_Enemies/Textures/Grenadier_N.uasset new file mode 100644 index 0000000..f5a05b9 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Grenadier_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Hooker_D.uasset b/Content/CityofBrass_Enemies/Textures/Hooker_D.uasset new file mode 100644 index 0000000..24c3c15 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Hooker_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Hooker_M.uasset b/Content/CityofBrass_Enemies/Textures/Hooker_M.uasset new file mode 100644 index 0000000..2d1a5ea Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Hooker_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Hooker_N.uasset b/Content/CityofBrass_Enemies/Textures/Hooker_N.uasset new file mode 100644 index 0000000..e6deaae Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Hooker_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Hooker_ygui.uasset b/Content/CityofBrass_Enemies/Textures/Hooker_ygui.uasset new file mode 100644 index 0000000..b68f382 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Hooker_ygui.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Large_D.uasset b/Content/CityofBrass_Enemies/Textures/Large_D.uasset new file mode 100644 index 0000000..771e1d4 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Large_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Large_M.uasset b/Content/CityofBrass_Enemies/Textures/Large_M.uasset new file mode 100644 index 0000000..0a52856 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Large_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Large_N.uasset b/Content/CityofBrass_Enemies/Textures/Large_N.uasset new file mode 100644 index 0000000..8b014b5 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Large_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_D.uasset b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_D.uasset new file mode 100644 index 0000000..0d848d6 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_M.uasset b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_M.uasset new file mode 100644 index 0000000..2fde1c8 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_Normal.uasset b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_Normal.uasset new file mode 100644 index 0000000..0edde7c Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Melee_Clothes_low_Corpse_Melee_Normal.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Stall01_D.uasset b/Content/CityofBrass_Enemies/Textures/Stall01_D.uasset new file mode 100644 index 0000000..71dda17 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Stall01_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Stall01_M.uasset b/Content/CityofBrass_Enemies/Textures/Stall01_M.uasset new file mode 100644 index 0000000..a02d486 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Stall01_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Stall01_N.uasset b/Content/CityofBrass_Enemies/Textures/Stall01_N.uasset new file mode 100644 index 0000000..3b3f20f Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Stall01_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Sword_D.uasset b/Content/CityofBrass_Enemies/Textures/Sword_D.uasset new file mode 100644 index 0000000..1b9d04a Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Sword_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Sword_M.uasset b/Content/CityofBrass_Enemies/Textures/Sword_M.uasset new file mode 100644 index 0000000..cd2f716 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Sword_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Sword_N.uasset b/Content/CityofBrass_Enemies/Textures/Sword_N.uasset new file mode 100644 index 0000000..3dbdd5e Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Sword_N.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Wizard_D.uasset b/Content/CityofBrass_Enemies/Textures/Wizard_D.uasset new file mode 100644 index 0000000..bc59a4a Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Wizard_D.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Wizard_M.uasset b/Content/CityofBrass_Enemies/Textures/Wizard_M.uasset new file mode 100644 index 0000000..a4f4157 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Wizard_M.uasset differ diff --git a/Content/CityofBrass_Enemies/Textures/Wizard_N.uasset b/Content/CityofBrass_Enemies/Textures/Wizard_N.uasset new file mode 100644 index 0000000..724cb73 Binary files /dev/null and b/Content/CityofBrass_Enemies/Textures/Wizard_N.uasset differ diff --git a/Content/CityofBrass_Enemies/maps/Overview.umap b/Content/CityofBrass_Enemies/maps/Overview.umap new file mode 100644 index 0000000..d9007cc Binary files /dev/null and b/Content/CityofBrass_Enemies/maps/Overview.umap differ diff --git a/Content/MainMenu/BP_MainMenuGameMode.uasset b/Content/MainMenu/BP_MainMenuGameMode.uasset new file mode 100644 index 0000000..e269c55 Binary files /dev/null and b/Content/MainMenu/BP_MainMenuGameMode.uasset differ diff --git a/Content/MainMenu/BP_MainMenuPlayerController.uasset b/Content/MainMenu/BP_MainMenuPlayerController.uasset new file mode 100644 index 0000000..a99d706 Binary files /dev/null and b/Content/MainMenu/BP_MainMenuPlayerController.uasset differ diff --git a/Content/MainMenu/BP_MainMenuWidget.uasset b/Content/MainMenu/BP_MainMenuWidget.uasset new file mode 100644 index 0000000..dc53399 Binary files /dev/null and b/Content/MainMenu/BP_MainMenuWidget.uasset differ diff --git a/Content/MainMenu/BP_SessionListEntry.uasset b/Content/MainMenu/BP_SessionListEntry.uasset new file mode 100644 index 0000000..36dc2c5 Binary files /dev/null and b/Content/MainMenu/BP_SessionListEntry.uasset differ diff --git a/Content/MainMenu/BP_SessionListMenu.uasset b/Content/MainMenu/BP_SessionListMenu.uasset new file mode 100644 index 0000000..0f1b13f Binary files /dev/null and b/Content/MainMenu/BP_SessionListMenu.uasset differ diff --git a/Content/MainMenu/MainMenu.uasset b/Content/MainMenu/MainMenu.uasset deleted file mode 100644 index aa2d07e..0000000 Binary files a/Content/MainMenu/MainMenu.uasset and /dev/null differ diff --git a/Content/MainMenu/MainMenuLevel.umap b/Content/MainMenu/MainMenuLevel.umap index dbee8ab..d882ad5 100644 Binary files a/Content/MainMenu/MainMenuLevel.umap and b/Content/MainMenu/MainMenuLevel.umap differ diff --git a/Content/MainMenu/fotor-ai-2023050222244.uasset b/Content/MainMenu/fotor-ai-2023050222244.uasset new file mode 100644 index 0000000..7145ff0 Binary files /dev/null and b/Content/MainMenu/fotor-ai-2023050222244.uasset differ diff --git a/Content/ManageSquadMenu/BP_ManageSquadTrooper.uasset b/Content/ManageSquadMenu/BP_ManageSquadTrooper.uasset new file mode 100644 index 0000000..4595318 Binary files /dev/null and b/Content/ManageSquadMenu/BP_ManageSquadTrooper.uasset differ diff --git a/Content/ManageSquadMenu/ManageSquadLevel.umap b/Content/ManageSquadMenu/ManageSquadLevel.umap new file mode 100644 index 0000000..fca80b0 Binary files /dev/null and b/Content/ManageSquadMenu/ManageSquadLevel.umap differ diff --git a/Content/StarterContent/Architecture/Floor_400x400.uasset b/Content/StarterContent/Architecture/Floor_400x400.uasset index 7ec619f..a08b055 100644 Binary files a/Content/StarterContent/Architecture/Floor_400x400.uasset and b/Content/StarterContent/Architecture/Floor_400x400.uasset differ diff --git a/Content/StarterContent/Maps/Minimal_Default.umap b/Content/StarterContent/Maps/Minimal_Default.umap index 7b52307..e056d46 100644 Binary files a/Content/StarterContent/Maps/Minimal_Default.umap and b/Content/StarterContent/Maps/Minimal_Default.umap differ diff --git a/Content/StarterContent/Particles/Materials/M_Burst.uasset b/Content/StarterContent/Particles/Materials/M_Burst.uasset index 1bc05f7..a48d10c 100644 Binary files a/Content/StarterContent/Particles/Materials/M_Burst.uasset and b/Content/StarterContent/Particles/Materials/M_Burst.uasset differ diff --git a/Content/StarterContent/Particles/Materials/M_Dust_Particle.uasset b/Content/StarterContent/Particles/Materials/M_Dust_Particle.uasset index 9af46f1..1bc4633 100644 Binary files a/Content/StarterContent/Particles/Materials/M_Dust_Particle.uasset and b/Content/StarterContent/Particles/Materials/M_Dust_Particle.uasset differ diff --git a/Content/StarterContent/Particles/Materials/M_Fire_SubUV.uasset b/Content/StarterContent/Particles/Materials/M_Fire_SubUV.uasset index d0f7225..4b2548d 100644 Binary files a/Content/StarterContent/Particles/Materials/M_Fire_SubUV.uasset and b/Content/StarterContent/Particles/Materials/M_Fire_SubUV.uasset differ diff --git a/Content/StarterContent/Particles/Materials/M_Radial_Gradient.uasset b/Content/StarterContent/Particles/Materials/M_Radial_Gradient.uasset index a2dbd9e..2cc7e28 100644 Binary files a/Content/StarterContent/Particles/Materials/M_Radial_Gradient.uasset and b/Content/StarterContent/Particles/Materials/M_Radial_Gradient.uasset differ diff --git a/Content/StarterContent/Particles/Materials/M_explosion_subUV.uasset b/Content/StarterContent/Particles/Materials/M_explosion_subUV.uasset index 9a9041a..15cf20c 100644 Binary files a/Content/StarterContent/Particles/Materials/M_explosion_subUV.uasset and b/Content/StarterContent/Particles/Materials/M_explosion_subUV.uasset differ diff --git a/Content/StarterContent/Particles/Materials/M_smoke_subUV.uasset b/Content/StarterContent/Particles/Materials/M_smoke_subUV.uasset index d96330b..8a89654 100644 Binary files a/Content/StarterContent/Particles/Materials/M_smoke_subUV.uasset and b/Content/StarterContent/Particles/Materials/M_smoke_subUV.uasset differ diff --git a/Content/StarterContent/Props/Materials/M_MaterialSphere.uasset b/Content/StarterContent/Props/Materials/M_MaterialSphere.uasset index 377dd95..f0101ee 100644 Binary files a/Content/StarterContent/Props/Materials/M_MaterialSphere.uasset and b/Content/StarterContent/Props/Materials/M_MaterialSphere.uasset differ diff --git a/Content/StarterContent/Props/Materials/M_MaterialSphere_Plain.uasset b/Content/StarterContent/Props/Materials/M_MaterialSphere_Plain.uasset index cfbfba2..7d6bfe5 100644 Binary files a/Content/StarterContent/Props/Materials/M_MaterialSphere_Plain.uasset and b/Content/StarterContent/Props/Materials/M_MaterialSphere_Plain.uasset differ diff --git a/Content/Troopers/BP_Trooper.uasset b/Content/Troopers/BP_Trooper.uasset new file mode 100644 index 0000000..ae5af02 Binary files /dev/null and b/Content/Troopers/BP_Trooper.uasset differ diff --git a/Content/Troopers/MGreenRing.uasset b/Content/Troopers/MGreenRing.uasset new file mode 100644 index 0000000..68f7ea2 Binary files /dev/null and b/Content/Troopers/MGreenRing.uasset differ diff --git a/Content/Troopers/MRedRing.uasset b/Content/Troopers/MRedRing.uasset new file mode 100644 index 0000000..5f3d9ee Binary files /dev/null and b/Content/Troopers/MRedRing.uasset differ diff --git a/Content/Troopers/RingMaterial.uasset b/Content/Troopers/RingMaterial.uasset new file mode 100644 index 0000000..1d53f42 Binary files /dev/null and b/Content/Troopers/RingMaterial.uasset differ diff --git a/Content/Troopers/TrooperSkeletonMelee.uasset b/Content/Troopers/TrooperSkeletonMelee.uasset new file mode 100644 index 0000000..1b5a4c6 Binary files /dev/null and b/Content/Troopers/TrooperSkeletonMelee.uasset differ diff --git a/Content/Troopers/TrooperWizard.uasset b/Content/Troopers/TrooperWizard.uasset new file mode 100644 index 0000000..fee6f8c Binary files /dev/null and b/Content/Troopers/TrooperWizard.uasset differ diff --git a/Content/Troopers/WBP_HealthBar.uasset b/Content/Troopers/WBP_HealthBar.uasset new file mode 100644 index 0000000..2c2d067 Binary files /dev/null and b/Content/Troopers/WBP_HealthBar.uasset differ diff --git a/Content/Troopers/projectiles/BP_DefaultProjectile.uasset b/Content/Troopers/projectiles/BP_DefaultProjectile.uasset new file mode 100644 index 0000000..18875aa Binary files /dev/null and b/Content/Troopers/projectiles/BP_DefaultProjectile.uasset differ diff --git a/Content/Troopers/projectiles/BP_Fireball.uasset b/Content/Troopers/projectiles/BP_Fireball.uasset new file mode 100644 index 0000000..3a5feb6 Binary files /dev/null and b/Content/Troopers/projectiles/BP_Fireball.uasset differ diff --git a/Content/Troopers/projectiles/BP_MyExplosion.uasset b/Content/Troopers/projectiles/BP_MyExplosion.uasset new file mode 100644 index 0000000..06ea15c Binary files /dev/null and b/Content/Troopers/projectiles/BP_MyExplosion.uasset differ diff --git a/Content/Troopers/projectiles/Materials/Fire_Material.uasset b/Content/Troopers/projectiles/Materials/Fire_Material.uasset new file mode 100644 index 0000000..86dede3 Binary files /dev/null and b/Content/Troopers/projectiles/Materials/Fire_Material.uasset differ diff --git a/Content/Troopers/projectiles/MyMyExplosion.uasset b/Content/Troopers/projectiles/MyMyExplosion.uasset new file mode 100644 index 0000000..52cfe7a Binary files /dev/null and b/Content/Troopers/projectiles/MyMyExplosion.uasset differ diff --git a/Source/TurnBasedTutorial/BattleMode/BattleGameMode.cpp b/Source/TurnBasedTutorial/BattleMode/BattleGameMode.cpp new file mode 100644 index 0000000..016aff9 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattleGameMode.cpp @@ -0,0 +1,214 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "BattleGameMode.h" +#include "Kismet/GameplayStatics.h" +#include "BattlePawn.h" +#include "BattleGameState.h" +#include "BattlePlayerController.h" +#include "BattlePlayerState.h" +#include "Trooper/Trooper.h" + +ABattleGameMode::ABattleGameMode() + : Super() { + UE_LOG(LogTemp, Warning, TEXT("GameMode Constructor")); + GameStateClass = ABattleGameState::StaticClass(); + PlayerControllerClass = ABattlePlayerController::StaticClass(); + PlayerStateClass = ABattlePlayerState::StaticClass(); + DefaultPawnClass = ABattlePawn::StaticClass(); +} + +void ABattleGameMode::BeginPlay() { + Super::BeginPlay(); +} + +auto ABattleGameMode::GetMyGameState() const { + return GetGameState(); +} + + +void ABattleGameMode::InitializeBattleField_Implementation() { + UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); + FVector Location(2000.0f, -1000.0f, 0.0f); + FRotator Rotation(0.0f, 180.0f, 0.0f); + + uint8 TrooperCount = 0; + + TArray bpPaths{ + TEXT( + "Blueprint'/Game/Troopers/TrooperSkeletonMelee.TrooperSkeletonMelee_C'" + ), + TEXT("Blueprint'/Game/Troopers/TrooperWizard.TrooperWizard_C'") + }; + // TArray LoadedBpAssets; + for (int i = 0; i < bpPaths.Num(); ++i) { + TSoftClassPtr ActorBpClass = TSoftClassPtr( + FSoftObjectPath(bpPaths[i]) + ); + LoadedBpAssets.Push(ActorBpClass.LoadSynchronous()); + } + + for (int i = 0; i < 5; ++i) { + FTransform SpawnLocationAndRotation(Rotation); + SpawnLocationAndRotation.SetLocation(Location); + AActor *Spawned = GetWorld()->SpawnActorDeferred( + LoadedBpAssets[i % 2], SpawnLocationAndRotation); + // AActor *Spawned = GetWorld()->SpawnActorDeferred( + // ATrooper::StaticClass(), SpawnLocationAndRotation); + Cast(Spawned)->Initialize( + 0, Location, TrooperCount++); + Spawned->FinishSpawning(SpawnLocationAndRotation); + Spawned->SetActorLocation(Location); + GetMyGameState()->AddTrooper(Cast(Spawned)); + Location += {0.f, 500.f, 0.0f}; + } + if (bIsMultiplayer) { + Location = {-2000.0f, -1000.0f, 0.0f}; + Rotation = {0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 5; ++i) { + FTransform SpawnLocationAndRotation(Rotation); + SpawnLocationAndRotation.SetLocation(Location); + AActor *Spawned = GetWorld()->SpawnActorDeferred( + LoadedBpAssets[i % 2], SpawnLocationAndRotation); + // AActor *Spawned = GetWorld()->SpawnActorDeferred( + // ATrooper::StaticClass(), SpawnLocationAndRotation); + Cast(Spawned)->Initialize( + 1, Location, TrooperCount++); + Spawned->FinishSpawning(SpawnLocationAndRotation); + Spawned->SetActorLocation(Location); + GetMyGameState()->AddTrooper(Cast(Spawned)); + Location += {0.f, 500.f, 0.0f}; + } + } else { + // Cast(GetMyGameState())->GetEnemyAIController()-> + // SetTrooperAssetsAndSpawn( + // LoadedBpAssets, + // TrooperCount); + } +} + +AActor *ABattleGameMode::ChoosePlayerStart_Implementation(AController *Player) { + UE_LOG(LogTemp, Warning, TEXT("GameMode ChoosePlayerStart %d"), + GetNumPlayers()); + InitializeSpawnPointsIfNeeded(Player); + const auto CurrentPlayerStart = *SpawnPoints.Find(GetNumPlayers()); + UE_LOG(LogTemp, Warning, TEXT("GameMode ChoosePlayerStart end %d"), + CurrentPlayerStart->GetPlayerIndex()); + return CurrentPlayerStart; +} + +void ABattleGameMode::InitializeSpawnPointsIfNeeded(AController *Player) { + UE_LOG(LogTemp, Warning, TEXT("InitializeSpawnPointsIfNeeded")); + if (SpawnPoints.Num() != 0) { + UE_LOG(LogTemp, Warning, TEXT("InitializeSpawnPointsIfNeeded Exit %d"), + SpawnPoints.Num()); + return; + } + UE_LOG(LogTemp, Warning, TEXT("Rebuilding spawnpoints")); + const auto World = GetWorld(); + for (TActorIterator PlayerStartIterator(GetWorld()); + PlayerStartIterator; ++PlayerStartIterator) { + const auto PlayerStart = *PlayerStartIterator; + const UClass *PawnClass = GetDefaultPawnClassForController(Player); + const APawn *PawnToFit = PawnClass + ? PawnClass->GetDefaultObject() + : nullptr; + const FVector ActorLocation = PlayerStart->GetActorLocation(); + const FRotator ActorRotation = PlayerStart->GetActorRotation(); + UE_LOG(LogTemp, Warning, TEXT("PlayerStart iterator %d"), + PlayerStartIterator->GetPlayerIndex()); + if (!World->EncroachingBlockingGeometry(PawnToFit, ActorLocation, + ActorRotation)) { + SpawnPoints.Add(PlayerStartIterator->GetPlayerIndex(), + *PlayerStartIterator); + UE_LOG(LogTemp, Warning, TEXT("PlayerStart unoccupied iterator %d"), + PlayerStartIterator->GetPlayerIndex()); + } + } +} + +void ABattleGameMode::PostLogin(APlayerController *NewPlayer) { + Super::PostLogin(NewPlayer); + NewPlayer->SetShowMouseCursor(true); + UE_LOG(LogTemp, Warning, TEXT("PostLogin")); + // PlayerControllers.Add(dynamic_cast(NewPlayer)); + // const auto World = GetWorld(); + const auto CurrentNumberOfPlayers = GetNumPlayers(); + + // 0-indexation + Cast(NewPlayer)->SetPlayerIndex( + CurrentNumberOfPlayers - 1); + UE_LOG(LogTemp, Warning, TEXT("%d"), CurrentNumberOfPlayers); + if (CurrentNumberOfPlayers == 2) { + UE_LOG(LogTemp, Warning, TEXT("Game Start")); + // start the game + // dynamic_cast( + // GetWorld()->GetGameState())->StartGame(); + // InitializeBattleField(); + StartGame(); + // GetMyGameState()->PlayerInTurn()->SetEnemySelection(); + // GetMyGameState()->PlayerNotInTurn()->SetEnemySelection(); + } else { + // delay the game + UE_LOG(LogTemp, Warning, TEXT("Game Delay")); + } +} + +void ABattleGameMode::StartGame_Implementation() { + InitializeBattleField(); + // PlayerNotInTurn()->SetEnemySelection(Troopers); + // PlayerInTurn()->SetEnemySelection(Troopers); + + // PlayerInTurn()->StartTurn(); + GetMyGameState()->StartGame(); +} + + +// void AMyGameMode::StartGame() { +// InitializeBattleField(); +// // PlayerNotInTurn()->SetEnemySelection(Troopers); +// // PlayerInTurn()->SetEnemySelection(Troopers); +// +// // PlayerInTurn()->StartTurn(); +// GetMyGameState()->StartGame(); +// } + + +// AMyPlayerController *AMyGameMode::PlayerInTurn() const { +// return GetMyPlayerController(CurrentPlayerTurn); +// } + +// AMyPlayerController *AMyGameMode::PlayerNotInTurn() const { +// // uint8 PlayerControllerIndexNotInTurn; +// // if (CurrentPlayerTurn == 0) { +// // PlayerControllerIndexNotInTurn = 1; +// // } else { +// // PlayerControllerIndexNotInTurn = 0; +// // } +// // return GetMyPlayerController(PlayerControllerIndexNotInTurn); +// return GetMyPlayerController(!CurrentPlayerTurn); +// } + +// void AMyGameMode::CycleTurns() { +// if (!this) +// return; +// // PlayerInTurn()->EndTurn(); +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr) { +// Trooper->ResetActionPoints(); +// } +// } +// CurrentPlayerTurn = !CurrentPlayerTurn; +// // if (CurrentPlayerTurn == 0) { +// // CurrentPlayerTurn = 1; +// // } else { +// // CurrentPlayerTurn = 0; +// // } +// PlayerInTurn()->StartTurn(); +// } + + +// AMyPlayerController *AMyGameMode::GetMyPlayerController( +// uint8 const PlayerIndex) const { +// return Cast( +// UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex)); +// } diff --git a/Source/TurnBasedTutorial/BattleMode/BattleGameMode.h b/Source/TurnBasedTutorial/BattleMode/BattleGameMode.h new file mode 100644 index 0000000..c411706 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattleGameMode.h @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "EngineUtils.h" +#include "BattlePlayerStart.h" +#include "GameFramework/GameMode.h" +#include "BattleGameMode.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API ABattleGameMode : public AGameMode { + GENERATED_BODY() + +public: + ABattleGameMode(); + + virtual AActor * + ChoosePlayerStart_Implementation(AController *Player) override; + + virtual void PostLogin(APlayerController *NewPlayer) override; + + virtual void BeginPlay() override; + + // + // UFUNCTION(BlueprintCallable) + // void CycleTurns(); + +protected: + UPROPERTY() + TArray LoadedBpAssets; + + UPROPERTY() + bool bIsMultiplayer = true; + + void InitializeSpawnPointsIfNeeded(AController *Player); + + UFUNCTION(Server, Reliable) + void InitializeBattleField(); + + UPROPERTY() + TMap SpawnPoints{}; + + // UPROPERTY() + // mutable TArray Troopers; + + UFUNCTION(Server, Reliable) + void StartGame(); + + + // UFUNCTION(BlueprintPure) + // AMyPlayerController *PlayerInTurn() const; + // + // UFUNCTION(BlueprintPure) + // AMyPlayerController *PlayerNotInTurn() const; + + // UPROPERTY() + // uint8 CurrentPlayerTurn{0}; + + // UFUNCTION() + // AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const; + + auto GetMyGameState() const; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/BattleGameState.cpp b/Source/TurnBasedTutorial/BattleMode/BattleGameState.cpp new file mode 100644 index 0000000..0c71a63 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattleGameState.cpp @@ -0,0 +1,121 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "BattleGameState.h" + +// #include "GameOverWidget.h" +#include "BattlePlayerState.h" +#include "Trooper/Trooper.h" +#include "Blueprint/UserWidget.h" +#include "Net/UnrealNetwork.h" + +auto ABattleGameState::GetMyPlayerState(uint8 PlayerIndex) const { + return Cast(PlayerArray[PlayerIndex]); +} + +ABattleGameState::ABattleGameState() + : Super() { +} + +void ABattleGameState::BeginPlay() { + Super::BeginPlay(); + LivingTroopersCount.SetNum(2); +} + +void ABattleGameState::AddTrooper_Implementation(ATrooper *Trooper) { + if (Trooper->GetPlayerIndex() >= 0 && Trooper->GetPlayerIndex() <= + LivingTroopersCount.Num()) { + if (LivingTroopersCount.Num() < 2) { + LivingTroopersCount.SetNum(2); + } + LivingTroopersCount[Trooper->GetPlayerIndex()]++; + } + Troopers.Add(Trooper); +} + +void ABattleGameState::StartGame_Implementation() { + // PlayerNotInTurn()->SetEnemySelection(); + PlayerInTurn()->SetEnemySelection(); + bGameStarted = true; + PlayerInTurn()->StartTurn(); +} + +void ABattleGameState::CycleTurns_Implementation() { + PlayerInTurn()->EndTurn(); + for (const auto Trooper : Troopers) { + if (Trooper != nullptr) { + Trooper->ResetActionPoints(); + } + } + CurrentPlayerTurn = !CurrentPlayerTurn; + PlayerInTurn()->StartTurn(); +} + +// void AMyGameState::CycleTurns(uint8 CurrentPlayerIndex) { +// if (CurrentPlayerTurn == CurrentPlayerIndex) { +// PlayerInTurn()->EndTurn(); +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr) { +// Trooper->ResetActionPoints(); +// } +// } +// CurrentPlayerTurn = !CurrentPlayerTurn; +// PlayerInTurn()->StartTurn(); +// } +// } + +ABattlePlayerState *ABattleGameState::PlayerInTurn() const { + return GetMyPlayerState(CurrentPlayerTurn); +} + +ABattlePlayerState *ABattleGameState::PlayerNotInTurn() const { + return GetMyPlayerState(!CurrentPlayerTurn); +} + +TArray ABattleGameState::GetTroopers() const { + return Troopers; +} + +bool ABattleGameState::IsInTurn(uint8 PlayerIndex) const { + return PlayerIndex == CurrentPlayerTurn; +} + +bool ABattleGameState::IsGameStarted() const { + return bGameStarted; +} + +void ABattleGameState::DecreaseLivingTroopers(int PlayerIndex) { + if (bGameIsOver) + return; + LivingTroopersCount[PlayerIndex]--; + if (!bIsMultiplayer && PlayerIndex == 1) { + return; + } + if (LivingTroopersCount[PlayerIndex] <= 0) { + UE_LOG(LogTemp, Warning, TEXT("Player %d lose!"), PlayerIndex); + bGameIsOver = true; + GameOver(PlayerIndex); + } +} + +void ABattleGameState::GameOver(int PlayerIndexLose) const { + Cast(PlayerArray[0])->GameOver(PlayerIndexLose); + if (bIsMultiplayer) { + Cast(PlayerArray[1])->GameOver(PlayerIndexLose); + } +} + +// void AMyGameState::GameOver_Implementation(int PlayerIndexLose) { +// UGameOverWidget *CreatedWidget = CreateWidget( +// GetWorld(), GameOverWidgetClass); +// CreatedWidget->AddToViewport(); +// CreatedWidget->SetWidgetText(PlayerIndexLose != ); +// } + + +void ABattleGameState::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(ABattleGameState, Troopers); + DOREPLIFETIME(ABattleGameState, CurrentPlayerTurn); + DOREPLIFETIME(ABattleGameState, bGameStarted); +} diff --git a/Source/TurnBasedTutorial/BattleMode/BattleGameState.h b/Source/TurnBasedTutorial/BattleMode/BattleGameState.h new file mode 100644 index 0000000..bc40ed8 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattleGameState.h @@ -0,0 +1,75 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BattlePlayerState.h" +#include "GameFramework/GameState.h" +#include "BattleGameState.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API ABattleGameState : public AGameState { + GENERATED_BODY() + +public: + ABattleGameState(); + + virtual void BeginPlay() override; + + UFUNCTION(Server, Reliable) + virtual void AddTrooper(ATrooper *Trooper); + + UFUNCTION(Server, Reliable) + void StartGame(); + + UFUNCTION(BlueprintCallable, Server, Reliable) + virtual void CycleTurns(); + + UFUNCTION(BlueprintPure) + ABattlePlayerState *PlayerInTurn() const; + + UFUNCTION(BlueprintPure) + ABattlePlayerState *PlayerNotInTurn() const; + + UFUNCTION() + TArray GetTroopers() const; + + UFUNCTION() + bool IsInTurn(uint8 PlayerIndex) const; + + UFUNCTION() + bool IsGameStarted() const; + + UFUNCTION() + void DecreaseLivingTroopers(int PlayerIndex); + + UFUNCTION() + void GameOver(int PlayerIndexLose) const; + +protected: + // UPROPERTY(EditAnywhere, BlueprintReadWrite) + // TSubclassOf GameOverWidgetClass; + + UPROPERTY() + bool bIsMultiplayer = true; + + UPROPERTY(Replicated) + bool bGameIsOver = false; + + UPROPERTY(Replicated) + TArray Troopers; + + UPROPERTY(Replicated) + TArray LivingTroopersCount; + + UPROPERTY(Replicated) + bool bGameStarted = false; + + UPROPERTY(Replicated) + uint8 CurrentPlayerTurn{0}; + + auto GetMyPlayerState(uint8 PlayerIndex) const; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePawn.cpp b/Source/TurnBasedTutorial/BattleMode/BattlePawn.cpp new file mode 100644 index 0000000..5c4a650 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePawn.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BattlePawn.h" + + +// Sets default values +ABattlePawn::ABattlePawn() { + // 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; +} + +// Called when the game starts or when spawned +void ABattlePawn::BeginPlay() { + Super::BeginPlay(); +} + +void ABattlePawn::MoveForward(float Val) { + if (Val != 0.f) { + if (Controller) { + FRotator ControlSpaceRot = Controller->GetControlRotation(); + ControlSpaceRot.Pitch = 0; + + // transform to world space and add it + AddMovementInput( + FRotationMatrix(ControlSpaceRot).GetScaledAxis(EAxis::X), Val); + } + } +} + +// Called to bind functionality to input +void ABattlePawn::SetupPlayerInputComponent(UInputComponent *PlayerInputComponent) { + Super::SetupPlayerInputComponent(PlayerInputComponent); +} diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePawn.h b/Source/TurnBasedTutorial/BattleMode/BattlePawn.h new file mode 100644 index 0000000..de42606 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePawn.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/SpectatorPawn.h" +#include "BattlePawn.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API ABattlePawn : public ASpectatorPawn { + GENERATED_BODY() + +public: + // Sets default values for this pawn's properties + ABattlePawn(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + virtual void MoveForward(float Val) override; + +public: + // Called to bind functionality to input + virtual void SetupPlayerInputComponent( + class UInputComponent *PlayerInputComponent) override; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.cpp b/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.cpp new file mode 100644 index 0000000..aa67c9f --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.cpp @@ -0,0 +1,317 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "BattlePlayerController.h" +#include "Kismet/GameplayStatics.h" +#include "BattleGameMode.h" +#include "BattleGameState.h" +#include "BattlePlayerState.h" +#include "Blueprint/UserWidget.h" +#include "Net/UnrealNetwork.h" + +ABattlePlayerController::ABattlePlayerController() + : Super()/*, bIsMyTurn(false), SelectedTrooper(nullptr)*/ { + UE_LOG(LogTemp, Warning, TEXT("Player controller created")); + SetShowMouseCursor(true); + PlayerIndex = 0; +} + +void ABattlePlayerController::BeginPlay() { + Super::BeginPlay(); + UUserWidget *CreatedWidget = CreateWidget( + GetWorld(), WidgetClass); + CreatedWidget->AddToViewport(); +} + +void ABattlePlayerController::SetupInputComponent() { + Super::SetupInputComponent(); + InputComponent->BindAction("MyAction", IE_Pressed, this, + &ABattlePlayerController::OnLeftMouseClick); +} + +// void AMyPlayerController::SetMyTurn(bool bMyTurn) { +// bIsMyTurn = bMyTurn; +// if (bIsMyTurn) { +// GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, +// FString::Printf( +// TEXT("CURRENT TURN: %d"), +// PlayerIndex)); +// } +// OnMyTurnChanged.ExecuteIfBound(bIsMyTurn); +// } + +// void AMyPlayerController::StartTurn_Implementation() { +// SetMyTurn(true); +// UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); +// } + +auto ABattlePlayerController::GetMyGameState() const { + return Cast(UGameplayStatics::GetGameState(GetWorld())); +} + +auto ABattlePlayerController::GetMyPlayerState() const { + return GetPlayerState(); +} + + +auto ABattlePlayerController::GetMyGameMode() const { + return Cast( + UGameplayStatics::GetGameMode(GetWorld())); +} + + +void ABattlePlayerController::EndTurn_Implementation() { + // if (GetMyPlayerState()->IsMyTurn()) { + // GetMyGameState()->CycleTurns(); + // } + // GetMyPlayerState()->CycleTurns(); + if (GetMyGameState()->IsInTurn(PlayerIndex)) + GetMyGameState()->CycleTurns(); +} + +// void AMyPlayerController::EndTurn_Implementation() { +// GetMyPlayerState()->EndTurn(); +// } + + +// if (bIsMyTurn) { +// UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex); +// SetMyTurn(false); +// if (SelectedTrooper) { +// SelectedTrooper->SetSelection(false); +// SelectedTrooper = nullptr; +// } +// UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); +// AMyGameMode *gameMode = GetMyGameMode(); +// gameMode->CycleTurns(); +// } +// } + +// AMyGameState *AMyPlayerController::GetMyGameState() const { +// return dynamic_cast( +// GetWorld()->GetGameState()); +// } + +// void AMyPlayerController::MoveTrooper_Implementation( +// ATrooper *Trooper, +// FVector Location) { +// if (Trooper->CheckMoveCorrectness(Location)) { +// Trooper->MoveTrooper(Location); +// // GetMyGameMode()->CycleTurns(); +// } else { +// GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, +// FString::Printf( +// TEXT("Out of move radius!"))); +// } +// } + +// void AMyPlayerController::AttackTrooper_Implementation( +// ATrooper *Attacker, +// ATrooper *Victim) { +// if (Attacker->CheckAttackCorrectness(Victim->GetLocation())) { +// Attacker->Attack(); +// // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, +// // FString::Printf( +// // TEXT("ATTACK!! %d attacked %d"), +// // Attacker->GetId(), +// // Victim->GetId())); +// // GetMyGameMode()->CycleTurns(); +// } else { +// GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, +// FString::Printf( +// TEXT( +// "Attack failed! Out of attack radius!"))); +// } +// } + + +// void AMyPlayerController::Attack_Implementation(ATrooper *Attacker, +// FVector Location, +// int ActionIndex) { +// if (Attacker && CurrentAction >= 1 && CurrentAction <= 2 && +// Attacker->CheckAttackCorrectness(Location, CurrentAction)) { +// Attacker->Attack(CurrentAction); +// } else { +// UE_LOG(LogTemp, Warning, +// TEXT("Out of radius or not enough Action Points")); +// } +// } + +void ABattlePlayerController::SetPlayerIndex(uint8 NewPlayerIndex) { + PlayerIndex = NewPlayerIndex; + + GetMyPlayerState()->SetPlayerIndex(NewPlayerIndex); + // GetMyPlayerState()->PlayerIndex = NewPlayerIndex; +} + +uint8 ABattlePlayerController::GetPlayerIndex() const { + return PlayerIndex; +} + +// float AMyPlayerController::SetCurrentActionAndReturnRadius(int action) { +// return GetMyPlayerState()->SetCurrentActionAndReturnRadius(action); +// +// // CurrentAction = action; +// // UE_LOG(LogTemp, Warning, TEXT("SetCurrentAction: %d on Player Controller " +// // "with index %d"), CurrentAction, PlayerIndex); +// // if (SelectedTrooper) { +// // return SelectedTrooper->GetActionRadius(CurrentAction); +// // } +// // return 0.0f; +// } + + +// void AMyPlayerController::SetEnemySelection_Implementation( +// const TArray &Troopers) const { +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr && Trooper->GetPlayerIndex() != PlayerIndex) { +// Trooper->HighlightAsEnemy(); +// } +// } +// } + + +// void AMyPlayerController::SetEnemySelection_Implementation() { +// if (!GetMyGameMode()) { +// UE_LOG(LogTemp, Warning, TEXT("Failed to get Game mode, Index: %d"), PlayerIndex); +// return; +// } +// const auto &Troopers = GetMyGameMode()->GetTroopers(); +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr && Trooper->GetPlayerIndex() != PlayerIndex) { +// Trooper->HighlightAsEnemy(); +// } +// } +// } + +// void AMyPlayerController::SetEnemySelection(TArray &Troopers) const { +// for (const auto Trooper : Troopers) { +// if (Trooper->GetPlayerIndex() != PlayerIndex) { +// Trooper->HighlightAsEnemy(); +// } +// } +// } + +void ABattlePlayerController::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(ABattlePlayerController, PlayerIndex); + // DOREPLIFETIME(AMyPlayerController, CurrentAction); + // DOREPLIFETIME(AMyPlayerController, bIsMyTurn); + // DOREPLIFETIME(AMyPlayerController, SelectedTrooper); +} + +void ABattlePlayerController::OnLeftMouseClick() { + if (!GetMyPlayerState()->IsMyTurn()) { + return; + } + UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); + // UE_LOG(LogTemp, Warning, TEXT("Current action: %d"), CurrentAction); + FHitResult HitResult; + bool const IsHitResult = GetHitResultUnderCursorForObjects( + TArray>{ObjectTypeQuery1}, false, + HitResult); + // GetHitResultUnderCursorForObjects(); + // bool const IsHitResult = GetHitResultUnderCursorByChannel( + // TraceTypeQuery1, false, HitResult); + if (!IsHitResult) + return; + UE_LOG(LogTemp, Warning, TEXT("Got hit result")); + GetMyPlayerState()->OnPlayerAction(HitResult); + // auto const NewlySelectedLocation = HitResult.Location; + // ATrooper *NewlySelectedTrooper = Cast( + // HitResult.GetActor()); + // + // // skip re-selection + // if (SelectedTrooper == NewlySelectedTrooper) { + // UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + // return; + // } + // + // if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + // IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != + // PlayerIndex) { + // // we selected something that is not a trooper (or trooper in shitty state...) + // // probably we should move to it if we can... + // + // // UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); + // + // // if initial trooper is valid... + // if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { + // switch (CurrentAction) { + // case 0: + // UE_LOG(LogTemp, Warning, TEXT("Do move")); + // // move this mf + // MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // // and reset the selection.... + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // break; + // default: + // // ATTACK! ATTACK! + // UE_LOG(LogTemp, Warning, TEXT("Do attack")); + // Attack(SelectedTrooper, NewlySelectedLocation, + // CurrentAction); + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // break; + // } + // } + // } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> + // IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() == + // PlayerIndex) { + // UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // // our move, selection + // if (SelectedTrooper) { + // SelectedTrooper->SetSelection(false); + // } + // SelectedTrooper = NewlySelectedTrooper; + // SelectedTrooper->SetSelection(true); + // } + + // + // if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + // IsValidLowLevel()) { + // // we selected something that is not a trooper (or trooper in shitty state...) + // // probably we should move to it if we can... + // + // UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); + // + // // if initial trooper is valid... + // if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { + // UE_LOG(LogTemp, Warning, TEXT("Do move")); + // // move this mf + // MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // // and reset the selection.... + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // } + // return; + // } + // UE_LOG(LogTemp, Warning, TEXT("New Selected Player Index %d"), + // NewlySelectedTrooper->GetPlayerIndex()); + // // skip re-selection + // if (SelectedTrooper == NewlySelectedTrooper) { + // UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + // return; + // } + // we selected valid trooper... + // if (NewlySelectedTrooper->GetPlayerIndex() == PlayerIndex) { + // UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // // our move, selection + // if (SelectedTrooper) { + // SelectedTrooper->SetSelection(false); + // } + // SelectedTrooper = NewlySelectedTrooper; + // SelectedTrooper->SetSelection(true); + // } else { + // UE_LOG(LogTemp, Warning, TEXT("Attack or skip...")); + // // maybe selected trooper had gone crazy... + // if (SelectedTrooper == nullptr || !SelectedTrooper->IsValidLowLevel()) + // return; + // UE_LOG(LogTemp, Warning, TEXT("Do attack")); + // // ATTACK!!! ATTACK!!!!!! + // AttackTrooper(SelectedTrooper, NewlySelectedTrooper); + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // } +} diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.h b/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.h new file mode 100644 index 0000000..c5e090d --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerController.h @@ -0,0 +1,79 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "BattlePlayerController.generated.h" + +// DECLARE_DYNAMIC_DELEGATE_OneParam(FOnMyTurnChangedDelegate, bool, bMyTurn); + +UCLASS() +class TURNBASEDTUTORIAL_API ABattlePlayerController : public APlayerController { + GENERATED_BODY() + +public: + virtual void BeginPlay() override; + + // FOnMyTurnChangedDelegate OnMyTurnChanged; + + virtual void SetupInputComponent() override; + + ABattlePlayerController(); + + UFUNCTION(BlueprintCallable, Server, Reliable) + void EndTurn(); + + // UFUNCTION(Client, Reliable) + // void StartTurn(); + + // UFUNCTION(Client, Reliable, BlueprintCallable) + // void EndTurn(); + // + // UFUNCTION(Server, Reliable) + // void MoveTrooper(ATrooper *Trooper, FVector Location); + // + // // // UFUNCTION(Server, Reliable) + // // // void AttackTrooper(ATrooper *Attacker, ATrooper *Victim); + // + // UFUNCTION(Server, Reliable) + // void Attack(ATrooper *Attacker, FVector Location, int ActionIndex); + + UFUNCTION() + void SetPlayerIndex(uint8 NewPlayerIndex); + + UFUNCTION() + uint8 GetPlayerIndex() const; + + // UFUNCTION(BlueprintCallable) + // float SetCurrentActionAndReturnRadius(int action); + + // UFUNCTION(Client, Reliable) + // void SetEnemySelection(const TArray &Troopers) const; + +private: + UPROPERTY(EditAnywhere) + TSubclassOf WidgetClass; + + // UPROPERTY(Replicated) + // bool bIsMyTurn; + // + // UPROPERTY(Replicated) + // int CurrentAction = 0; + // + UPROPERTY(Replicated) + uint8 PlayerIndex; + // + // UPROPERTY(Replicated) + // ATrooper *SelectedTrooper; + + UFUNCTION() + void OnLeftMouseClick(); + + // void SetMyTurn(bool bMyTurn); + + auto GetMyGameMode() const; + + auto GetMyGameState() const; + + auto GetMyPlayerState() const; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.cpp b/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.cpp new file mode 100644 index 0000000..bf290d5 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BattlePlayerStart.h" + +uint8 ABattlePlayerStart::GetPlayerIndex() const { + return PlayerIndex; +} diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.h b/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.h new file mode 100644 index 0000000..3c43457 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerStart.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerStart.h" +#include "BattlePlayerStart.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API ABattlePlayerStart : public APlayerStart { + GENERATED_BODY() + +public: + uint8 GetPlayerIndex() const; + +protected: +private: + UPROPERTY(EditAnywhere, Category="Spawn Info") + uint8 PlayerIndex = 0; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.cpp b/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.cpp new file mode 100644 index 0000000..6c0928c --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.cpp @@ -0,0 +1,219 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "BattlePlayerState.h" + +#include "GameOverWidget.h" +#include "BattleGameState.h" +#include "Kismet/GameplayStatics.h" +#include "Net/UnrealNetwork.h" + +ABattlePlayerState::ABattlePlayerState() + : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { + // PrimaryActorTick.bCanEverTick = true; +} + +void ABattlePlayerState::BeginPlay() { + Super::BeginPlay(); +} + +auto ABattlePlayerState::GetMyGameState() const { + return Cast(GetWorld()->GetGameState()); +} + +// void AMyPlayerState::Tick(float DeltaSeconds) { +// Super::Tick(DeltaSeconds); +// if (GetMyGameState() && GetMyGameState()->IsGameStarted()) { +// // for (const auto Actor : Troopers) { +// // const auto Trooper = Cast(Actor); +// // if (Trooper != nullptr && Trooper->GetPlayerIndex() != +// // PlayerIndex) { +// // Trooper->HighlightAsEnemy(PlayerIndex); +// // } +// // } +// bIsSelectionInitialized = true; +// SetActorTickEnabled(false); +// } +// } + +void ABattlePlayerState::SetPlayerIndex(uint8 NewPlayerIndex) { + PlayerIndex = NewPlayerIndex; +} + +void ABattlePlayerState::GameOver_Implementation(int PlayerLoseIndex) { + UGameOverWidget *CreatedWidget = CreateWidget( + GetWorld(), GameOverWidgetClass); + CreatedWidget->AddToViewport(); + CreatedWidget->SetWidgetText(PlayerLoseIndex != PlayerIndex); +} + +void ABattlePlayerState::SetEnemySelection_Implementation( + /*const TArray &Troopers*/) const { + TArray Troopers; + UGameplayStatics::GetAllActorsOfClass(GetWorld(), + ATrooper::StaticClass(), + Troopers); + for (const auto Actor : Troopers) { + const auto Trooper = Cast(Actor); + if (Trooper != nullptr) { + Trooper->HighlightAsEnemy(PlayerIndex); + } + } +} + +void ABattlePlayerState::MoveTrooper_Implementation(ATrooper *Trooper, + FVector Location) { + Location.Z = 0.0f; + if (Trooper->CheckMoveCorrectness(Location)) { + Trooper->MoveTrooper(Location); + // GetMyGameMode()->CycleTurns(); + } else { + GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, + FString::Printf( + TEXT("Out of move radius!"))); + } +} + +// void AMyPlayerState::Attack_Implementation(ATrooper *Attacker, +// FVector Location, +// int ActionIndex) { +// if (Attacker->CheckAttackCorrectness(Location, ActionIndex)) { +// Attacker->Attack(ActionIndex); +// } else { +// GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, +// FString::Printf( +// TEXT( +// "Out of radius or not enough Action Points!"))); +// } +// } + +void ABattlePlayerState::Attack_Implementation(ATrooper *Attacker, + FVector Location, + int ActionIndex) { + if (Attacker->CheckAttackCorrectness(Location, ActionIndex)) { + Attacker->Attack(ActionIndex, Location); + // for (const auto Trooper : Troopers) { + // if (Attacker->GetPlayerIndex() != Trooper->GetPlayerIndex()) { + // Trooper->TakeDamage(Attacker->GetAbility(ActionIndex)->Damage); + // } + // } + } else { + GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, + FString::Printf( + TEXT( + "Out of radius or not enough Action Points!"))); + } +} + +// void AMyPlayerState::CycleTurns_Implementation() const { +// if (bIsMyTurn) { +// GetMyGameState()->CycleTurns(); +// } +// } + +bool ABattlePlayerState::IsMyTurn() const { + return bIsMyTurn; +} + +void ABattlePlayerState::SetMyTurn(bool bMyTurn) { + bIsMyTurn = bMyTurn; + if (bIsMyTurn) { + GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, + FString::Printf( + TEXT("CURRENT TURN: %d"), + PlayerIndex)); + } +} + +void ABattlePlayerState::StartTurn_Implementation() { + SetMyTurn(true); + UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); +} + +void ABattlePlayerState::EndTurn_Implementation() { + if (bIsMyTurn) { + UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), + PlayerIndex); + SetMyTurn(false); + if (SelectedTrooper) { + SelectedTrooper->SetSelection(false, CurrentAction); + SelectedTrooper = nullptr; + } + UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); + // AMyGameMode *gameMode = GetMyGameMode(); + // gameMode->CycleTurns(); + // Cast(GetWorld()->GetGameState())->CycleTurns(); + } +} + +void ABattlePlayerState::OnPlayerAction(const FHitResult &HitResult) { + auto const NewlySelectedLocation = HitResult.Location; + ATrooper *NewlySelectedTrooper = Cast( + HitResult.GetActor()); + + // skip re-selection + if (SelectedTrooper == NewlySelectedTrooper) { + UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + return; + } + + if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != + PlayerIndex) { + if (SelectedTrooper != nullptr && SelectedTrooper-> + IsValidLowLevel()) { + switch (CurrentAction) { + case 0: + UE_LOG(LogTemp, Warning, TEXT("Do move")); + // move this mf + MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // and reset the selection.... + SelectedTrooper->SetSelection(false, CurrentAction); + SelectedTrooper = nullptr; + break; + default: + // ATTACK! ATTACK! + UE_LOG(LogTemp, Warning, TEXT("Do attack")); + Attack(SelectedTrooper, NewlySelectedLocation, + CurrentAction); + SelectedTrooper->SetSelection(false, CurrentAction); + SelectedTrooper = nullptr; + break; + } + } + } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> + IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() + == + PlayerIndex) { + UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // our move, selection + if (SelectedTrooper) { + SelectedTrooper->SetSelection(false, CurrentAction); + } + SelectedTrooper = NewlySelectedTrooper; + SelectedTrooper->SetSelection(true, CurrentAction); + } +} + +void ABattlePlayerState::SetCurrentAction_Implementation(int Action) { + CurrentAction = Action; + if (SelectedTrooper) { + SelectedTrooper->UpdateSelectionRadius(Action); + } + UE_LOG(LogTemp, Warning, + TEXT("SetCurrentAction: %d on Player Controller " + "with index %d"), CurrentAction, PlayerIndex); +} + +uint8 ABattlePlayerState::GetPlayerIndex() const { + return PlayerIndex; +} + +void ABattlePlayerState::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(ABattlePlayerState, PlayerIndex); + DOREPLIFETIME(ABattlePlayerState, CurrentAction); + DOREPLIFETIME(ABattlePlayerState, bIsMyTurn); + DOREPLIFETIME(ABattlePlayerState, SelectedTrooper); + DOREPLIFETIME(ABattlePlayerState, bIsSelectionInitialized); +} diff --git a/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.h b/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.h new file mode 100644 index 0000000..a68163b --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/BattlePlayerState.h @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Trooper/Trooper.h" +#include "CoreMinimal.h" +#include "GameFramework/PlayerState.h" +#include "BattlePlayerState.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API ABattlePlayerState : public APlayerState { + GENERATED_BODY() + +public: + ABattlePlayerState(); + + virtual void BeginPlay() override; + + // virtual void Tick(float DeltaSeconds) override; + + UFUNCTION(Client, Reliable) + void StartTurn(); + + UFUNCTION(Client, Reliable, BlueprintCallable) + void EndTurn(); + + UFUNCTION(Server, Reliable) + void MoveTrooper(ATrooper *Trooper, FVector Location); + + UFUNCTION(Server, Reliable) + void Attack(ATrooper *Attacker, + FVector Location, + int ActionIndex); + + // UFUNCTION(Client, Reliable) + // void CycleTurns() const; + + UFUNCTION(BlueprintCallable) + bool IsMyTurn() const; + + UFUNCTION() + void OnPlayerAction(const FHitResult &HitResult); + + UFUNCTION(BlueprintCallable, Client, Reliable) + void SetCurrentAction(int Action); + + UFUNCTION(BlueprintCallable) + uint8 GetPlayerIndex() const; + + UFUNCTION() + void SetPlayerIndex(uint8 NewPlayerIndex); + + UFUNCTION(Client, Reliable) + void SetEnemySelection(/*const TArray &Troopers*/) const; + + UFUNCTION(Client, Reliable) + void GameOver(int PlayerLoseIndex); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf GameOverWidgetClass; + + UPROPERTY(Replicated) + bool bIsSelectionInitialized = false; + + UPROPERTY(Replicated) + uint8 PlayerIndex; + + UFUNCTION() + void SetMyTurn(bool bMyTurn); + + UPROPERTY(Replicated) + bool bIsMyTurn; + + UPROPERTY(Replicated) + int CurrentAction = 0; + + UPROPERTY(Replicated) + ATrooper *SelectedTrooper; + + auto GetMyGameState() const; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/GameOverWidget.cpp b/Source/TurnBasedTutorial/BattleMode/GameOverWidget.cpp new file mode 100644 index 0000000..4e25a46 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/GameOverWidget.cpp @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "GameOverWidget.h" +#include "../SessionsGameInstanceSubsystem.h" +#include "Components/Button.h" +#include "Components/TextBlock.h" +#include "Kismet/GameplayStatics.h" + + +void UGameOverWidget::NativeConstruct() { + ButtonToMenu->OnClicked.AddDynamic(this, &ThisClass::QuitCurrentSession); +} + +void UGameOverWidget::QuitCurrentSession() { + const UGameInstance *GameInstance = UGameplayStatics::GetGameInstance( + GetWorld()); + USessionsGameInstanceSubsystem *GameInstanceSubsystem = GameInstance->GetSubsystem + (); + GameInstanceSubsystem->QuitCurrentSession(); +} + + +void UGameOverWidget::SetWidgetText_Implementation(bool HasWon) { + if (HasWon) { + GameOverText->SetText(FText::FromString("You won!")); + } else { + GameOverText->SetText(FText::FromString("You lose!")); + } +} diff --git a/Source/TurnBasedTutorial/BattleMode/GameOverWidget.h b/Source/TurnBasedTutorial/BattleMode/GameOverWidget.h new file mode 100644 index 0000000..82402fe --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/GameOverWidget.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "GameOverWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API UGameOverWidget : public UUserWidget { + GENERATED_BODY() + +public: + virtual void NativeConstruct() override; + + UFUNCTION(Client, Reliable) + void SetWidgetText(bool HasWon); + + UFUNCTION() + void QuitCurrentSession(); + +protected: + UPROPERTY(meta = (BindWidget)) + class UButton *ButtonToMenu; + + UPROPERTY(meta = (BindWidget)) + class UTextBlock *GameOverText; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.cpp b/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.cpp new file mode 100644 index 0000000..68fcde5 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.cpp @@ -0,0 +1,226 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "EnemyAIController.h" +#include "SinglePlayerGS.h" +#include "Kismet/GameplayStatics.h" +#include "GenericPlatform/GenericPlatformMath.h" + +AEnemyAIController::AEnemyAIController() + : Super() { + PrimaryActorTick.bCanEverTick = true; + SetActorTickInterval(2.0f); +} + +void AEnemyAIController::Tick(float DeltaSeconds) { + Super::Tick(DeltaSeconds); + if (bIsAITurn && !bIsActing) { + if (TroopersCursor >= PossessedTroopers.Num()) { + EndTurn(); + } else { + MakeMove(); + } + } +} + + +void AEnemyAIController::StartTurn() { + UE_LOG(LogTemp, Warning, TEXT("Enemy AI StartTurn")); + bIsAITurn = true; + bIsActing = false; + // MakeMove(); +} + +void AEnemyAIController::EndTurn() { + bIsAITurn = false; + TroopersCursor = 0; + bIsEnded = true; +} + +void AEnemyAIController::ActionDone() { + bIsActing = false; +} + +bool AEnemyAIController::IsAITurn() const { + return bIsAITurn; +} + +void AEnemyAIController::SpawnIfNeeded() { + RemoveDeadTroopers(); + while (PossessedTroopers.Num() < MAX_TROOPERS_COUNT) { + const FVector Location = GetFreeLocation(); + const FVector Rotation = {0.0f, 0.0f, 0.0f}; + FTransform SpawnLocationAndRotation(Rotation); + SpawnLocationAndRotation.SetLocation(Location); + const TArray> &LoadedTroopersAssets = GetWorld()-> + GetGameState()->GetTroopersAssets(); + AActor *Spawned = GetWorld()->SpawnActorDeferred( + LoadedTroopersAssets[FMath::RandRange( + 0, LoadedTroopersAssets.Num() - 1)], + SpawnLocationAndRotation); + Cast(Spawned)->Initialize( + 1, Location, TroopersCount++); + Spawned->FinishSpawning(SpawnLocationAndRotation); + Spawned->SetActorLocation(Location); + ATrooper *Trooper = Cast(Spawned); + GetWorld()->GetGameState()->AddTrooper(Trooper); + PossessedTroopers.Add(Trooper); + Trooper->SetAIPossession(this); + Trooper->HighlightAsEnemy(PLAYER_INDEX); + } +} + +// void AEnemyAIController::SetTrooperAssetsAndSpawn( +// TArray TrooperAssets, +// int TrooperCount) { +// LoadedTrooperAssets = MoveTemp(TrooperAssets); +// TroopersCount = TrooperCount; +// SpawnIfNeeded(); +// } + +void AEnemyAIController::RemoveDeadTroopers() { + for (int index = 0; index < PossessedTroopers.Num(); ++index) { + if (!PossessedTroopers[index] || !PossessedTroopers[index]-> + IsValidLowLevel() || + PossessedTroopers[index]->IsDead()) { + PossessedTroopers.RemoveAtSwap(index); + index--; + } + } +} + +FVector AEnemyAIController::GetFreeLocation() const { + for (const auto Location : SpawnPoints) { + bool bIsClose = false; + for (const auto Trooper : PossessedTroopers) { + if ((Location - Trooper->GetLocation()).Size() < 100.0f) { + bIsClose = true; + break; + } + } + if (bIsClose) { + continue; + } + return Location; + } + return {-2000.0f, FMath::RandRange(-2000.0f, 2000.0f), 0.0f}; +} + +void AEnemyAIController::MakeMove() { + while (TroopersCursor < PossessedTroopers.Num()) { + while (TroopersCursor < PossessedTroopers.Num() && ( + !PossessedTroopers[TroopersCursor] || + !PossessedTroopers[TroopersCursor]->IsValidLowLevel() + || PossessedTroopers[TroopersCursor]->IsDead())) { + ++TroopersCursor; + } + if (TroopersCursor >= PossessedTroopers.Num()) { + return; + } + const int Index = GetClosestTrooper(); + if (Index == -1) { + return; + } + bool failed; + if (!IsCloseEnough(Index)) { + failed = MoveTo(Index); + } else { + failed = TryAttack(Index); + } + if (failed) { + TroopersCursor++; + } else { + return; + } + } +} + +bool AEnemyAIController::IsCloseEnough(int TrooperIndex) const { + const ATrooper *CurrentTrooper = PossessedTroopers[TroopersCursor]; + const ATrooper *OtherTrooper = PlayerTroopers[TrooperIndex]; + return (CurrentTrooper->GetLocation() - OtherTrooper->GetLocation()).Size() + <= CurrentTrooper->GetRealActionRadius(1); +} + +bool AEnemyAIController::TryAttack(int TrooperIndex) { + ATrooper *Attacker = PossessedTroopers[TroopersCursor]; + const auto Location = PlayerTroopers[TrooperIndex]->GetLocation(); + constexpr int ActionIndex = 1; + if (Attacker->CheckAttackCorrectness(Location, ActionIndex)) { + bIsActing = true; + Attacker->Attack(ActionIndex, Location); + return false; + } + return true; +} + +bool AEnemyAIController::MoveTo(int TrooperIndex) { + ATrooper *Trooper = PossessedTroopers[TroopersCursor]; + const FVector CurrentLocation = Trooper->GetLocation(); + const FVector Destination = PlayerTroopers[TrooperIndex]->GetLocation(); + constexpr int ActionIndex = 1; + constexpr int MoveActionIndex = 0; + const float AttackRadius = Trooper->GetRealActionRadius(ActionIndex); + const FVector Vector = Destination - CurrentLocation; + const float MaxLength = Trooper->GetRealActionRadius(MoveActionIndex); + float PathLength = Vector.Size() - AttackRadius + 10.f; + PathLength = FMath::Min(PathLength, MaxLength); + FVector Location = CurrentLocation + Vector.GetSafeNormal2D() * + PathLength; + Location.Z = 0.0f; + if (PathLength > 1.0f && Trooper->CheckMoveCorrectness(Location)) { + bIsActing = true; + Trooper->MoveTrooper(Location); + return false; + } + return true; +} + +void AEnemyAIController::InitializeSpawnPoints() { + SpawnPoints.Add(FVector{ + -2000.0f, + -(MAX_TROOPERS_COUNT - 1) * TROOPERS_DISTANCE.Y / 2, + 0.0f + }); + for (int index = 1; index < MAX_TROOPERS_COUNT; ++index) { + SpawnPoints.Add(SpawnPoints[SpawnPoints.Num() - 1] + TROOPERS_DISTANCE); + } +} + +int AEnemyAIController::GetClosestTrooper() const { + float minDistance = 1000000.0f; + int minIndex = -1; + const ATrooper *CurrentTrooper = PossessedTroopers[TroopersCursor]; + for (int index = 0; index < PlayerTroopers.Num(); ++index) { + const ATrooper *OtherTrooper = PlayerTroopers[index]; + if (OtherTrooper->IsValidLowLevel() && !OtherTrooper->IsDead()) { + const float distance = ( + CurrentTrooper->GetLocation() - OtherTrooper-> + GetLocation()).Size(); + if (distance < minDistance) { + minDistance = distance; + minIndex = index; + } + } + } + return minIndex; +} + +void AEnemyAIController::InitializeTroopers( + const TArray &Troopers) { + for (const auto Trooper : Troopers) { + if (Trooper != nullptr) { + if (Trooper->GetPlayerIndex() == AI_INDEX) { + Trooper->SetAIPossession(this); + PossessedTroopers.Add(Trooper); + } else { + PlayerTroopers.Add(Trooper); + } + } + } + InitializeSpawnPoints(); + SpawnIfNeeded(); +} + +void AEnemyAIController::BeginPlay() { + Super::BeginPlay(); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.h b/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.h new file mode 100644 index 0000000..01d9a5d --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/EnemyAIController.h @@ -0,0 +1,95 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "EnemyAIController.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API AEnemyAIController : public AActor { + GENERATED_BODY() + +public: + AEnemyAIController(); + + UFUNCTION() + void StartTurn(); + + UFUNCTION() + void EndTurn(); + + UFUNCTION() + void ActionDone(); + + UFUNCTION() + void InitializeTroopers(const TArray &Troopers); + + virtual void BeginPlay() override; + + virtual void Tick(float DeltaSeconds) override; + + UPROPERTY() + bool bIsEnded = false; + + UFUNCTION() + bool IsAITurn() const; + + UFUNCTION() + void SpawnIfNeeded(); + + // UFUNCTION() + // void SetTrooperAssetsAndSpawn(TArray TrooperAssets, int TrooperCount); + +private: + static constexpr int AI_INDEX = 1; + + static constexpr int PLAYER_INDEX = 0; + + static constexpr int MAX_TROOPERS_COUNT = 3; + + UPROPERTY() + int TroopersCount = 5; + + // UPROPERTY() + // TArray LoadedTrooperAssets; + + UFUNCTION() + void RemoveDeadTroopers(); + + FVector GetFreeLocation() const; + + UFUNCTION() + void MakeMove(); + + UPROPERTY() + int TroopersCursor = 0; + + int GetClosestTrooper() const; + + bool IsCloseEnough(int TrooperIndex) const; + + bool TryAttack(int TrooperIndex); + + bool MoveTo(int TrooperIndex); + + void InitializeSpawnPoints(); + + UPROPERTY() + bool bIsAITurn = false; + + UPROPERTY() + bool bIsActing = false; + + UPROPERTY() + TArray PossessedTroopers; + + UPROPERTY() + TArray PlayerTroopers; + + TArray SpawnPoints; + + const FVector TROOPERS_DISTANCE = {0.0f, 1000.0f, 0.0f}; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.cpp b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.cpp new file mode 100644 index 0000000..64d327a --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.cpp @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SinglePlayerGM.h" +#include "SinglePlayerGS.h" + +ASinglePlayerGM::ASinglePlayerGM() + : Super() { + GameStateClass = ASinglePlayerGS::StaticClass(); + bIsMultiplayer = false; +} + +void ASinglePlayerGM::BeginPlay() { + Super::BeginPlay(); + UE_LOG(LogTemp, Warning, TEXT("SinglePlayer GameMode BeginPlay")); + GameStateClass = ASinglePlayerGS::StaticClass(); + StartGame(); +} + +void ASinglePlayerGM::PostLogin(APlayerController *NewPlayer) { + AGameMode::PostLogin(NewPlayer); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.h b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.h new file mode 100644 index 0000000..08d73ab --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGM.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "../BattleGameMode.h" +#include "SinglePlayerGM.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API ASinglePlayerGM : public ABattleGameMode { + GENERATED_BODY() + +public: + ASinglePlayerGM(); + + virtual void BeginPlay() override; + + virtual void PostLogin(APlayerController *NewPlayer) override; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.cpp b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.cpp new file mode 100644 index 0000000..e272f81 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.cpp @@ -0,0 +1,66 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SinglePlayerGS.h" +#include "Net/UnrealNetwork.h" + +ASinglePlayerGS::ASinglePlayerGS() + : Super() { + bIsMultiplayer = false; + PrimaryActorTick.bCanEverTick = true; + SetActorTickInterval(0.5f); +} + +void ASinglePlayerGS::BeginPlay() { + Super::BeginPlay(); + UE_LOG(LogTemp, Warning, TEXT("SinglePlayer GameState BeginPlay")); + if (LivingTroopersCount.Num() < 2) { + LivingTroopersCount.SetNum(2); + } + EnemyAiManager = GetWorld()->SpawnActor( + AEnemyAIController::StaticClass(), FVector(0.0f, 0.0f, 1000.0f), + FRotator(0.0f, 0.0f, 0.0f), FActorSpawnParameters()); + EnemyAiManager->InitializeTroopers(Troopers); +} + +void ASinglePlayerGS::CycleTurns() { + if (CurrentPlayerTurn == 0) { + PlayerInTurn()->EndTurn(); + } + for (const auto Trooper : Troopers) { + if (Trooper != nullptr) { + Trooper->ResetActionPoints(); + } + } + CurrentPlayerTurn = !CurrentPlayerTurn; + if (CurrentPlayerTurn == 0) { + PlayerInTurn()->StartTurn(); + } else { + EnemyAiManager->StartTurn(); + } +} + +void ASinglePlayerGS::Tick(float DeltaSeconds) { + Super::Tick(DeltaSeconds); + if (EnemyAiManager->bIsEnded) { + EnemyAiManager->bIsEnded = false; + EnemyAiManager->SpawnIfNeeded(); + CycleTurns(); + } else if (CurrentPlayerTurn == 1 && !EnemyAiManager->IsAITurn()) { + CycleTurns(); + } +} + +AEnemyAIController *ASinglePlayerGS::GetEnemyAIController() const { + return EnemyAiManager; +} + +const TArray> &ASinglePlayerGS:: +GetTroopersAssets() const { + return TrooperBpAssets; +} + +void ASinglePlayerGS::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(ASinglePlayerGS, EnemyAiManager); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.h b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.h new file mode 100644 index 0000000..1ca3171 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Singleplayer/SinglePlayerGS.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "EnemyAIController.h" +#include "../BattleGameState.h" +#include "SinglePlayerGS.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API ASinglePlayerGS : public ABattleGameState { + GENERATED_BODY() + +public: + ASinglePlayerGS(); + + virtual void BeginPlay() override; + + virtual void CycleTurns() override; + + virtual void Tick(float DeltaSeconds) override; + + AEnemyAIController *GetEnemyAIController() const; + + const TArray> &GetTroopersAssets() const; + +protected: + UPROPERTY(Replicated) + AEnemyAIController *EnemyAiManager = nullptr; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray> TrooperBpAssets; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.cpp b/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.cpp new file mode 100644 index 0000000..d35f5df --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.cpp @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "Ability.h" + +// Sets default values for this component's properties +UAbility::UAbility() { + PrimaryComponentTick.bCanEverTick = false; +} + +// Called when the game starts +void UAbility::BeginPlay() { + Super::BeginPlay(); +} + +// void UAbility::TickComponent(float DeltaTime, +// ELevelTick TickType, +// FActorComponentTickFunction *ThisTickFunction) { +// Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +// +// } diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.h b/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.h new file mode 100644 index 0000000..079f2b6 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Ability.h @@ -0,0 +1,44 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "Ability.generated.h" + + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class TURNBASEDTUTORIAL_API UAbility : public UActorComponent { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UAbility(); + + // Called when the game starts + virtual void BeginPlay() override; + + UPROPERTY(EditAnywhere) + float ActionCost = 100.0f; + + UPROPERTY(EditAnywhere) + float Damage = 50.0f; + + UPROPERTY(EditAnywhere) + float ActionRadius = 1000.0f; + + UPROPERTY(EditAnywhere) + float SplashRadius = 100.0f; + + UPROPERTY(EditAnywhere) + float LinearWidth = 50.0f; + + UPROPERTY(EditAnywhere) + float Speed = 1500.0f; + + // Called every frame + // virtual void TickComponent(float DeltaTime, + // ELevelTick TickType, + // FActorComponentTickFunction * + // ThisTickFunction) override; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.cpp b/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.cpp new file mode 100644 index 0000000..fa3484f --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.cpp @@ -0,0 +1,66 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Explosion.h" +#include "Trooper.h" +#include "Net/UnrealNetwork.h" +#include "Particles/ParticleSystemComponent.h" + +AExplosion::AExplosion() { + // if (!CollisionComponent) { + // CollisionComponent = CreateDefaultSubobject( + // TEXT("SphereComponent")); + // RootComponent = CollisionComponent; + // } + if (!ParticleSystemComponent) { + ParticleSystemComponent = CreateDefaultSubobject< + UParticleSystemComponent>( + TEXT("ParticleSystemComponent")); + RootComponent = ParticleSystemComponent; + } + InitialLifeSpan = 1.0f; +} + +void AExplosion::Initialize(float damage, + float splashRadius, + uint8 playerIndex) { + Damage = damage; + PlayerIndex = playerIndex; + float Scale = splashRadius / 50; + // CollisionComponent->SetWorldScale3D({Scale, Scale, Scale}); + if (ParticleSystemComponent && ParticleSystemComponent->IsValidLowLevel()) { + ParticleSystemComponent->SetWorldScale3D({Scale, Scale, Scale}); + } +} + +void AExplosion::BeginPlay() { + Super::BeginPlay(); +} + +void AExplosion::NotifyActorBeginOverlap(AActor *OtherActor) { + Super::NotifyActorBeginOverlap(OtherActor); + ATrooper *OtherTrooper = Cast(OtherActor); + if (OtherTrooper) { + UE_LOG(LogTemp, Warning, + TEXT( + "Begin explosion overlap: id: %d, index: %d, damage: %f, my index: %d" + ), + OtherTrooper->GetId(), OtherTrooper->GetPlayerIndex(), Damage, + PlayerIndex); + if (PlayerIndex != -1 && PlayerIndex != OtherTrooper-> + GetPlayerIndex()) { + OtherTrooper->TrooperTakeDamage(Damage); + } + } else { + UE_LOG(LogTemp, Warning, TEXT("Overlapped not a trooper")); + } +} + +void AExplosion::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(AExplosion, Damage); + DOREPLIFETIME(AExplosion, PlayerIndex); + // DOREPLIFETIME(AMyExplosion, CollisionComponent); + DOREPLIFETIME(AExplosion, ParticleSystemComponent); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.h b/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.h new file mode 100644 index 0000000..e72f780 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Explosion.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "Explosion.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API AExplosion : public AActor { + GENERATED_BODY() + +public: + AExplosion(); + + void Initialize(float damage, + float splashRadius, + uint8 playerIndex); + +protected: + virtual void BeginPlay() override; + + virtual void NotifyActorBeginOverlap(AActor *OtherActor) override; + + UPROPERTY(Replicated) + float Damage; + + UPROPERTY(Replicated) + int8 PlayerIndex = -1; + + // UPROPERTY(EditAnywhere, Replicated) + // USphereComponent *CollisionComponent; + + UPROPERTY(EditAnywhere, Replicated) + UParticleSystemComponent *ParticleSystemComponent; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.cpp b/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.cpp new file mode 100644 index 0000000..9a7256e --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.cpp @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HealthBar.h" + +#include "Components/ProgressBar.h" + +void UHealthBar::SetOwnerTrooper(ATrooper *Trooper) { + OwnerTrooper = Trooper; +} + +void UHealthBar::NativeTick(const FGeometry &MyGeometry, float InDeltaTime) { + Super::NativeTick(MyGeometry, InDeltaTime); + if (!OwnerTrooper.IsValid()) + return; + + HealthBar->SetPercent( + OwnerTrooper->GetHitPoints() / OwnerTrooper->GetMaxHitPoints()); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.h b/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.h new file mode 100644 index 0000000..af06f73 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/HealthBar.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Trooper.h" +#include "Blueprint/UserWidget.h" +#include "HealthBar.generated.h" + +/** + * + */ +UCLASS(Abstract) +class TURNBASEDTUTORIAL_API UHealthBar : public UUserWidget { + GENERATED_BODY() + +public: + void SetOwnerTrooper(ATrooper *Trooper); + +protected: + TWeakObjectPtr OwnerTrooper; + + UPROPERTY(meta=(BindWidget)) + class UProgressBar *HealthBar; + + virtual void + NativeTick(const FGeometry &MyGeometry, float InDeltaTime) override; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.cpp b/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.cpp new file mode 100644 index 0000000..f05d525 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.cpp @@ -0,0 +1,139 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Projectile.h" + +#include "Trooper.h" +#include "Net/UnrealNetwork.h" + +AProjectile::AProjectile() { + // if (!RootComponent) { + // RootComponent = CreateDefaultSubobject( + // TEXT("ProjectileSceneComponent")); + // } + // if (!CollisionComponent) { + // CollisionComponent = CreateDefaultSubobject( + // TEXT("SphereComponent")); + // RootComponent = CollisionComponent; + // } + if (!ProjectileMeshComponent) { + ProjectileMeshComponent = CreateDefaultSubobject( + TEXT("ProjectileMeshComponent")); + static ConstructorHelpers::FObjectFinder Mesh( + TEXT( + "StaticMesh'/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere'")); + if (Mesh.Succeeded()) { + ProjectileMeshComponent->SetStaticMesh(Mesh.Object); + RootComponent = ProjectileMeshComponent; + } + } + if (!ProjectileMovementComponent) { + ProjectileMovementComponent = CreateDefaultSubobject< + UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); + ProjectileMovementComponent->SetUpdatedComponent( + // CollisionComponent); + ProjectileMeshComponent); + ProjectileMovementComponent->bRotationFollowsVelocity = true; + ProjectileMovementComponent->InitialSpeed = 1000.0f; + ProjectileMovementComponent->MaxSpeed = 1000.0f; + ProjectileMovementComponent->ProjectileGravityScale = 0.0f; + } + InitialLifeSpan = 2.0f; +} + +void AProjectile::Initialize(const UAbility *Ability, + uint8 playerIndex, + float PathLength) { + ProjectileMovementComponent->InitialSpeed = + ProjectileMovementComponent->MaxSpeed = Ability->Speed; + Damage = Ability->Damage; + SplashRadius = Ability->SplashRadius; + float Scale = Ability->LinearWidth / 100; + // CollisionComponent->SetSphereRadius(Ability->LinearWidth / 2); + ProjectileMeshComponent->SetWorldScale3D({Scale, Scale, Scale}); + PlayerIndex = playerIndex; + SetLifeSpan(PathLength / Ability->Speed); +} + +void AProjectile::Shoot(FVector From, FVector To) const { + ProjectileMovementComponent->Velocity = + (To - From).GetSafeNormal() * ProjectileMovementComponent->InitialSpeed; +} + +void AProjectile::NotifyActorBeginOverlap(AActor *OtherActor) { + Super::NotifyActorBeginOverlap(OtherActor); + ATrooper *OtherTrooper = Cast(OtherActor); + if (OtherTrooper) { + UE_LOG(LogTemp, Warning, + TEXT("Begin overlap: id: %d, index: %d, damage: %f, my index: %d" + ), + OtherTrooper->GetId(), OtherTrooper->GetPlayerIndex(), Damage, + PlayerIndex); + if (PlayerIndex != -1 && PlayerIndex != OtherTrooper-> + GetPlayerIndex()) { + OtherTrooper->TrooperTakeDamage(Damage); + } + } else { + UE_LOG(LogTemp, Warning, TEXT("Overlapped not a trooper")); + } +} + +// void AMyProjectile::NotifyHit(UPrimitiveComponent *MyComp, +// AActor *Other, +// UPrimitiveComponent *OtherComp, +// bool bSelfMoved, +// FVector HitLocation, +// FVector HitNormal, +// FVector NormalImpulse, +// const FHitResult &Hit) { +// Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, +// HitNormal, +// NormalImpulse, Hit); +// ATrooper *OtherTrooper = Cast(Other); +// if (OtherTrooper) { +// UE_LOG(LogTemp, Warning, +// TEXT("On Hit: id: %d, index: %d, damage: %f, my index: %d" +// ), +// OtherTrooper->GetId(), OtherTrooper->GetPlayerIndex(), Damage, +// PlayerIndex); +// if (PlayerIndex != -1 && PlayerIndex != OtherTrooper-> +// GetPlayerIndex()) { +// OtherTrooper->TakeDamage(Damage); +// } +// } else { +// UE_LOG(LogTemp, Warning, TEXT("Overlapped not a trooper")); +// } +// } + + +void AProjectile::BeginPlay() { + Super::BeginPlay(); +} + +void AProjectile::EndPlay(const EEndPlayReason::Type EndPlayReason) { + Super::EndPlay(EndPlayReason); + Explode(); +} + +void AProjectile::Explode_Implementation() const { + const FTransform SpawnTransform = GetTransform(); + FActorSpawnParameters SpawnParameters; + SpawnParameters.Instigator = GetInstigator(); + SpawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + AExplosion *Explosion = GetWorld()->SpawnActor( + ExplosionSubclass, SpawnTransform, SpawnParameters); + Explosion->Initialize(Damage, SplashRadius, PlayerIndex); + Explosion->SetActorLocation(GetActorLocation()); +} + +void AProjectile::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(AProjectile, Damage); + DOREPLIFETIME(AProjectile, PlayerIndex); + // DOREPLIFETIME(AMyProjectile, CollisionComponent); + DOREPLIFETIME(AProjectile, ProjectileMeshComponent); + DOREPLIFETIME(AProjectile, ProjectileMovementComponent); + DOREPLIFETIME(AProjectile, SplashRadius); +} diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.h b/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.h new file mode 100644 index 0000000..9c1a9d2 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Projectile.h @@ -0,0 +1,65 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Ability.h" +#include "Explosion.h" +#include "Components/SphereComponent.h" +#include "GameFramework/Actor.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "Projectile.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API AProjectile : public AActor { + GENERATED_BODY() + +public: + AProjectile(); + + void Initialize(const UAbility *Ability, + uint8 playerIndex, + float PathLength); + + void Shoot(FVector From, FVector To) const; + +protected: + virtual void NotifyActorBeginOverlap(AActor *OtherActor) override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf ExplosionSubclass; + + // virtual void NotifyHit(UPrimitiveComponent *MyComp, + // AActor *Other, + // UPrimitiveComponent *OtherComp, + // bool bSelfMoved, + // FVector HitLocation, + // FVector HitNormal, + // FVector NormalImpulse, + // const FHitResult &Hit) override; + + UPROPERTY(Replicated) + float Damage; + + UPROPERTY(Replicated) + int8 PlayerIndex = -1; + + UPROPERTY(Replicated) + float SplashRadius; + + // UPROPERTY(EditAnywhere, Replicated) + // USphereComponent *CollisionComponent; + + UPROPERTY(EditAnywhere, Replicated) + UStaticMeshComponent *ProjectileMeshComponent; + + UPROPERTY(VisibleAnywhere, Replicated) + UProjectileMovementComponent *ProjectileMovementComponent; + + virtual void BeginPlay() override; + + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + UFUNCTION(Server, Reliable) + void Explode() const; +}; diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.cpp b/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.cpp new file mode 100644 index 0000000..d0f1809 --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.cpp @@ -0,0 +1,411 @@ +#include "Trooper.h" +#include + +#include "HealthBar.h" +#include "../BattleGameState.h" +#include "Projectile.h" +#include "Components/WidgetComponent.h" +#include "Net/UnrealNetwork.h" + +// Sets default values +ATrooper::ATrooper() + : HitPoints(StartHitPoints), ActionPoints(StartActionPoints) { + bReplicates = true; + + PrimaryActorTick.bCanEverTick = true; + Tags.Add(FName("Trooper")); + AttackAbility = CreateDefaultSubobject("AttackAbility"); + SpecialAbility = CreateDefaultSubobject("SpecialAbility"); + + HealthWidgetComponent = CreateDefaultSubobject( + "HealthBar"); + HealthWidgetComponent->AttachToComponent(RootComponent, + FAttachmentTransformRules::KeepRelativeTransform); + + SelectionStaticMesh = CreateDefaultSubobject( + "SelectionMesh"); + static ConstructorHelpers::FObjectFinder MeshToUse(TEXT( + "StaticMesh'/Game/StarterContent/Shapes/Shape_Cylinder.Shape_Cylinder'")); + SelectionStaticMesh->AttachToComponent(RootComponent, + FAttachmentTransformRules::KeepRelativeTransform); + SelectionStaticMesh->SetWorldScale3D({2.0f, 2.0f, 0.01f}); + SelectionStaticMesh->SetVisibility(false); + + if (MeshToUse.Object) { + SelectionStaticMesh->SetStaticMesh(MeshToUse.Object); + } + // SelectionStaticMesh->SetRelativeTransform(FTransform({1000,1000,100}, {0, 0, 0}), false, + // nullptr, ETeleportType::TeleportPhysics); + // SelectionStaticMesh-> + + // MyStaticMesh = CreateDefaultSubobject("Mesh"); + // RootComponent = MyStaticMesh; + // MeshPath = TEXT("StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'"); + // static ConstructorHelpers::FObjectFinder MeshToUse(MeshPath); + // if (MeshToUse.Object) { + // MyStaticMesh->SetStaticMesh(MeshToUse.Object); + // } +} + +// void ATrooper::SetStaticMesh() const { +// static ConstructorHelpers::FObjectFinder MeshToUse( +// TEXT( +// "StaticMesh'/Game/CityofBrass_Enemies/Static/Wizard_StaticMesh.Wizard_StaticMesh'" +// ) +// ); +// if (MeshToUse.Object) { +// MyStaticMesh->SetStaticMesh(MeshToUse.Object); +// } +// } + +// Called when the game starts or when spawned +void ATrooper::BeginPlay() { + Super::BeginPlay(); + Cast(HealthWidgetComponent->GetUserWidgetObject())-> + SetOwnerTrooper(this); +} + +void ATrooper::Initialize(uint8 const NewPlayerIndex, + FVector const SpawnLocation, + uint8 const NewId) { + PlayerIndex = NewPlayerIndex; + bIsMoving = false; + AttackPlayedTime = 0.0f; + TakingDamagePlayedTime = 0.0f; + CurrentLocation = SpawnLocation; + Id = NewId; +} + +void ATrooper::Tick(float const DeltaTime) { + if (bIsAttacking) { + AttackPlayedTime += DeltaTime; + if (bIsWaitingForFire && AttackPlayedTime >= FireAfterTime) { + FireProjectile(); + CurrentAbilityIndex = -1; + CurrentAbilityDestination = {}; + bIsWaitingForFire = false; + } + if (AttackPlayedTime >= AttackDuration) { + AttackPlayedTime = 0.0f; + // bIsAttacking = false; + SetIsAttacking(false); + } + } + if (bIsTakingDamage) { + TakingDamagePlayedTime += DeltaTime; + if (TakingDamagePlayedTime >= TakingDamageDuration) { + TakingDamagePlayedTime = 0.0f; + // bIsTakingDamage = false; + SetIsTakingDamage(false); + } + } + if (bIsMoving) { + FVector PositionVector = (TargetLocation - CurrentLocation); + PositionVector.Normalize(); + PositionVector *= (Speed * DeltaTime); + if (PositionVector.Size() >= (TargetLocation - CurrentLocation). + Size()) { + CurrentLocation = TargetLocation; + // bIsMoving = false; + SetIsMoving(false); + } else { + CurrentLocation += PositionVector; + } + SetActorLocation(CurrentLocation); + } +} + +void ATrooper::SetIsAttacking(bool IsAttacking) { + bIsAttacking = IsAttacking; + if (IsAttacking) { + SetActorTickEnabled(true); + } else { + TryDisableTick(); + } +} + +void ATrooper::SetIsTakingDamage(bool IsTakingDamage) { + bIsTakingDamage = IsTakingDamage; + if (IsTakingDamage) { + SetActorTickEnabled(true); + } else { + TryDisableTick(); + } +} + +void ATrooper::SetIsMoving(bool IsMoving) { + bIsMoving = IsMoving; + if (IsMoving) { + SetActorTickEnabled(true); + } else { + TryDisableTick(); + } +} + +void ATrooper::TryDisableTick() { + if (!bIsAttacking && !bIsTakingDamage && !bIsMoving) { + SetActorTickEnabled(false); + if (AIController && AIController->IsValidLowLevel()) { + AIController->ActionDone(); + } + } +} + +// void ATrooper::OnRepNotify_PlayerIndex() const { +// const AMyPlayerState *player = Cast( +// GetPlayerState()); +// if (!player) +// return; +// const uint8 ClientIndex = player->GetPlayerIndex(); +// UE_LOG(LogTemp, Warning, +// TEXT("On rep notify, index: %d, client index: %d, id: %d"), +// PlayerIndex, +// ClientIndex, Id); +// if (ClientIndex == PlayerIndex) { +// HighlightAsEnemy(); +// } +// } + +void ATrooper::MoveTrooper_Implementation(FVector const NewPos) { + TargetLocation = NewPos; + // bIsMoving = true; + SetIsMoving(true); + ActionPoints -= (NewPos - CurrentLocation).Size() * MoveCost; +} + +uint8 ATrooper::GetId() const { + return Id; +} + +void ATrooper::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(ATrooper, PlayerIndex); + DOREPLIFETIME(ATrooper, CurrentLocation); + DOREPLIFETIME(ATrooper, TargetLocation); + DOREPLIFETIME(ATrooper, bIsMoving); + DOREPLIFETIME(ATrooper, Id); + DOREPLIFETIME(ATrooper, bIsAttacking); + DOREPLIFETIME(ATrooper, HitPoints); + DOREPLIFETIME(ATrooper, ActionPoints); + DOREPLIFETIME(ATrooper, HealthWidgetComponent); + DOREPLIFETIME(ATrooper, AttackPlayedTime); + DOREPLIFETIME(ATrooper, TakingDamagePlayedTime); + DOREPLIFETIME(ATrooper, bIsTakingDamage); + DOREPLIFETIME(ATrooper, bIsDead); + DOREPLIFETIME(ATrooper, CurrentAbilityIndex); + DOREPLIFETIME(ATrooper, CurrentAbilityDestination); +} + +int8 ATrooper::GetPlayerIndex() const { + return PlayerIndex; +} + +// +// ATrooperWizard::ATrooperWizard() { +// MeshPath = TEXT( +// // "StaticMesh'/Game/CityofBrass_Enemies/Static/Wizard_StaticMesh.Wizard_StaticMesh'"); +// "StaticMesh'/Game/CityofBrass_Enemies/Static/SkeletonMelee_StaticMesh.SkeletonMelee_StaticMesh'"); +// SetStaticMesh(); +// } +// +// ATrooperSkeletonMelee::ATrooperSkeletonMelee() { +// MeshPath = TEXT( +// "StaticMesh'/Game/CityofBrass_Enemies/Static/SkeletonMelee_StaticMesh.SkeletonMelee_StaticMesh'"); +// SetStaticMesh(); +// } + +FVector ATrooper::GetLocation() const { + return CurrentLocation; +} + +float ATrooper::GetActionRadius(int action) const { + switch (action) { + case 1: + return AttackAbility->ActionCost <= ActionPoints + ? AttackAbility->ActionRadius + : 0; + case 2: + return SpecialAbility->ActionCost <= ActionPoints + ? SpecialAbility->ActionRadius + : 0; + default: + return ActionPoints / MoveCost; + } +} + +float ATrooper::GetRealActionRadius(int action) const { + switch (action) { + case 1: + return AttackAbility->ActionRadius; + case 2: + return SpecialAbility->ActionRadius; + default: + return ActionPoints / MoveCost; + } +} + +float ATrooper::GetHitPoints() const { + return HitPoints; +} + +float ATrooper::GetMaxHitPoints() const { + return StartHitPoints; +} + +void ATrooper::SetSelection(bool Selection, uint8 ActionType) const { + if (SelectionStaticMesh) { + if (SelectionStaticMesh->GetMaterial(0) != GreenMaterial) { + SelectionStaticMesh->SetMaterial(0, GreenMaterial); + SelectionStaticMesh->SetRelativeLocation({0, 0, 1}); + } + if (Selection) { + UpdateSelectionRadius(ActionType); + } else { + SelectionStaticMesh->SetWorldScale3D({2.f, 2.f, 0.01f}); + } + SelectionStaticMesh->SetVisibility(Selection); + } +} + +void ATrooper::UpdateSelectionRadius(uint8 ActionType) const { + const float radiusScale = + GetActionRadius(ActionType) / PIXELS_IN_RADIUS; + SelectionStaticMesh->SetWorldScale3D( + {radiusScale, radiusScale, 0.01f}); +} + +void ATrooper::HighlightAsEnemy_Implementation(int8 Index) const { + if (PlayerIndex != Index) { + SelectionStaticMesh->SetVisibility(true); + } +} + +void ATrooper::ResetActionPoints() { + ActionPoints = StartActionPoints; +} + +UAbility *ATrooper::GetAbility(int AbilityIndex) const { + switch (AbilityIndex) { + case 1: + return AttackAbility; + case 2: + return SpecialAbility; + default: + return nullptr; + } +} + +void ATrooper::SetAIPossession(AEnemyAIController *EnemyController) { + AIController = EnemyController; +} + +bool ATrooper::IsDead() const { + return bIsDead; +} + +void ATrooper::TrooperTakeDamage_Implementation(float Damage) { + if (bIsTakingDamage || bIsDead) { + return; + } + HitPoints = FMath::Max(0, HitPoints - Damage); + if (HitPoints == 0) { + bIsDead = true; + SetLifeSpan(DyingAnimationDuration); + GetWorld()->GetGameState()->DecreaseLivingTroopers( + PlayerIndex); + } else { + // bIsTakingDamage = true; + SetIsTakingDamage(true); + } +} + +TSubclassOf ATrooper::GetProjectileClass( + uint8 AbilityIndex) const { + switch (AbilityIndex) { + case 1: + return AttackProjectileClass; + case 2: + return SpecialProjectileClass; + default: + return AProjectile::StaticClass(); + } +} + +void ATrooper::FireProjectile_Implementation() { + if (!this || !this->IsValidLowLevel()) + return; + FTransform SpawnTransform( + (CurrentAbilityDestination - CurrentLocation).Rotation()); + const FVector TransformedVector = SpawnTransform.TransformVector( + {GetAbility(CurrentAbilityIndex)->LinearWidth / 2 + 50.0f, 0.0f, + 88.0f}); + const FVector SpawnLocation = CurrentLocation + TransformedVector; + SpawnTransform.SetLocation(SpawnLocation); + FActorSpawnParameters SpawnParameters; + SpawnParameters.Owner = this; + SpawnParameters.Instigator = GetInstigator(); + SpawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + AProjectile *Projectile = GetWorld()->SpawnActor( + GetProjectileClass(CurrentAbilityIndex), SpawnTransform, + SpawnParameters); + Projectile->SetActorLocation(SpawnLocation); + Projectile->Initialize(GetAbility(CurrentAbilityIndex), PlayerIndex, + (CurrentAbilityDestination - SpawnLocation). + Size()); + Projectile->Shoot(SpawnLocation, CurrentAbilityDestination); +} + +int ATrooper::GetAnimationValue() { + if (bIsDead) { + return 4; + } + if (bIsTakingDamage) { + return 3; + } + if (bIsAttacking) { + return 2; + } + if (bIsMoving) { + return 1; + } + return 0; +} + +void ATrooper::Attack_Implementation(int AbilityIndex, FVector ToLocation) { + // bIsAttacking = true; + SetIsAttacking(true); + bIsWaitingForFire = true; + ActionPoints -= GetAbility(AbilityIndex)->ActionCost; + CurrentAbilityIndex = AbilityIndex; + ToLocation.Z = 88.0f; + CurrentAbilityDestination = ToLocation; + // FTransform SpawnTransform((ToLocation - CurrentLocation).Rotation()); + // SpawnTransform.SetLocation( + // CurrentLocation + SpawnTransform.TransformVector( + // {GetAbility(AbilityIndex)->LinearWidth/2 + 50.0f, 0.0f, 0.0f}) + // ); + // FActorSpawnParameters SpawnParameters; + // SpawnParameters.Owner = this; + // SpawnParameters.Instigator = GetInstigator(); + // SpawnParameters.SpawnCollisionHandlingOverride = + // ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + // AMyProjectile *Projectile = GetWorld()->SpawnActor( + // GetProjectileClass(AbilityIndex), SpawnTransform, SpawnParameters); + // Projectile->Initialize(GetAbility(AbilityIndex)); + // Projectile->Shoot(CurrentLocation, ToLocation); +} + +bool ATrooper::CheckMoveCorrectness(const FVector newPos) const { + return (newPos - CurrentLocation).Size() * MoveCost <= ActionPoints; + // return (newPos - CurrentLocation).Size() <= MoveRadius; +} + +bool ATrooper::CheckAttackCorrectness(const FVector attackLocation, + int abilityIndex) const { + return GetAbility(abilityIndex) != nullptr && ( + attackLocation - CurrentLocation).Size() < GetActionRadius( + abilityIndex); + // return (attackLocation - CurrentLocation).Size() <= AttackRadius; +} diff --git a/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.h b/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.h new file mode 100644 index 0000000..f3de3bc --- /dev/null +++ b/Source/TurnBasedTutorial/BattleMode/Trooper/Trooper.h @@ -0,0 +1,222 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Ability.h" +#include "../Singleplayer/EnemyAIController.h" +#include "GameFramework/Character.h" +#include "Trooper.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API ATrooper : public ACharacter { + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ATrooper(); + + void Initialize(uint8 const NewPlayerIndex, + FVector const SpawnLocation, + uint8 const NewId); + + UFUNCTION() + int8 GetPlayerIndex() const; + + UFUNCTION(Server, Reliable) + void MoveTrooper(FVector const NewPos); + + UFUNCTION() + uint8 GetId() const; + + UFUNCTION() + bool CheckMoveCorrectness(const FVector newPos) const; + + UFUNCTION() + bool CheckAttackCorrectness(const FVector attackLocation, + int abilityIndex) const; + + UFUNCTION() + FVector GetLocation() const; + + UFUNCTION(BlueprintCallable) + int GetAnimationValue(); + + UFUNCTION(Server, Reliable) + void Attack(int AbilityIndex, FVector ToLocation); + + UFUNCTION() + float GetActionRadius(int action) const; + + UFUNCTION() + float GetRealActionRadius(int action) const; + + UFUNCTION() + float GetHitPoints() const; + + UFUNCTION() + float GetMaxHitPoints() const; + + UFUNCTION() + void SetSelection(bool Selected, uint8 ActionType) const; + + UFUNCTION() + void UpdateSelectionRadius(uint8 ActionType) const; + + UFUNCTION(Client, Reliable) + void HighlightAsEnemy(int8 Index) const; + + UFUNCTION() + void ResetActionPoints(); + + UFUNCTION() + UAbility *GetAbility(int AbilityIndex) const; + + UFUNCTION(Server, Reliable) + void TrooperTakeDamage(float Damage); + + UFUNCTION() + void SetAIPossession(AEnemyAIController *EnemyController); + + UFUNCTION() + bool IsDead() const; + +protected: + constexpr static float PIXELS_IN_RADIUS = 50; + + UPROPERTY() + AEnemyAIController *AIController = nullptr; + + UPROPERTY(EditAnywhere) + UMaterialInterface *GreenMaterial = nullptr; + + UPROPERTY(EditAnywhere) + UMaterialInterface *RedMaterial = nullptr; + + UPROPERTY(EditAnywhere) + UAbility *AttackAbility; + + UPROPERTY(EditAnywhere) + UAbility *SpecialAbility; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf AttackProjectileClass; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf SpecialProjectileClass; + + UFUNCTION() + TSubclassOf GetProjectileClass(uint8 AbilityIndex) const; + + UFUNCTION(Server, Reliable) + void FireProjectile(); + + UPROPERTY(Replicated) + uint8 CurrentAbilityIndex = -1; + + UPROPERTY(Replicated) + FVector CurrentAbilityDestination = {}; + + UPROPERTY(EditAnywhere) + float Speed = 300.0f; + + UPROPERTY(EditAnywhere) + float StartHitPoints = 100.0f; + + UPROPERTY(EditAnywhere) + float MoveCost = 0.0667f; + + UPROPERTY(EditAnywhere) + float StartActionPoints = 100.0f; + + UPROPERTY(Replicated) + float HitPoints; + + UPROPERTY(Replicated) + float ActionPoints; + + UPROPERTY(Replicated) + bool bIsAttacking = false; + + UPROPERTY(Replicated) + float AttackPlayedTime; + + const float AttackDuration = 1.16667f; + + const float FireAfterTime = 0.6f; + + UPROPERTY(Replicated) + bool bIsWaitingForFire = false; + + UPROPERTY(Replicated) + bool bIsTakingDamage = false; + + UPROPERTY(Replicated) + float TakingDamagePlayedTime; + + const float TakingDamageDuration = 1.46667f; + + const float DyingAnimationDuration = 2.83333f; + + UPROPERTY(Replicated) + bool bIsDead = false; + + virtual void BeginPlay() override; + + virtual void Tick(float const DeltaTime) override; + + UPROPERTY(VisibleAnywhere, Replicated) + class UWidgetComponent *HealthWidgetComponent; + + // void SetStaticMesh() const; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + UStaticMeshComponent *SelectionStaticMesh; + + // UPROPERTY(EditAnywhere, BlueprintReadWrite) + // USkeletalMeshComponent *MySkeletalMesh; + + // const TCHAR *MeshPath = nullptr; + + // UFUNCTION() + // void OnRepNotify_PlayerIndex() const; + + UPROPERTY(Replicated/*Using = OnRepNotify_PlayerIndex*/) + int8 PlayerIndex = -1; + + UPROPERTY(Replicated) + uint8 Id; + + UPROPERTY(Replicated) + FVector CurrentLocation; + + UPROPERTY(Replicated) + FVector TargetLocation; + + UPROPERTY(Replicated) + bool bIsMoving = false; + + void SetIsAttacking(bool IsAttacking); + + void SetIsTakingDamage(bool IsTakingDamage); + + void SetIsMoving(bool IsMoving); + + void TryDisableTick(); +}; + +// UCLASS() +// class ATrooperWizard : public ATrooper { +// GENERATED_BODY() +// +// public: +// ATrooperWizard(); +// +// }; +// +// UCLASS() +// class ATrooperSkeletonMelee : public ATrooper { +// GENERATED_BODY() +// +// public: +// ATrooperSkeletonMelee(); +// +// }; diff --git a/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.cpp b/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.cpp new file mode 100644 index 0000000..02ca458 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MainMenuPlayerController.h" +#include "Blueprint/UserWidget.h" + +void AMainMenuPlayerController::BeginPlay() { + Super::BeginPlay(); + SetShowMouseCursor(true); + UUserWidget *CreatedWidget = CreateWidget( + GetWorld(), WidgetClass); + CreatedWidget->AddToViewport(); +} diff --git a/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.h b/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.h new file mode 100644 index 0000000..8ad88e6 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/MainMenuPlayerController.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "MainMenuPlayerController.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API + AMainMenuPlayerController : public APlayerController { + GENERATED_BODY() + + virtual void BeginPlay() override; + +protected: + UPROPERTY(EditAnywhere) + TSubclassOf WidgetClass; +}; diff --git a/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.cpp b/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.cpp new file mode 100644 index 0000000..0baf22f --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.cpp @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MainMenuWidget.h" +#include "Components/Button.h" +#include "Kismet/GameplayStatics.h" + +void UMainMenuWidget::NativeConstruct() { + Super::NativeConstruct(); + + HostOnlineGameButton->OnClicked.AddDynamic( + this, &ThisClass::UMainMenuWidget::OnHostOnlineGameButtonClicked); + + GetMyGameSubsystem()->OnCreateSessionCompleteEvent.AddDynamic( + this, &ThisClass::StartSessionWhenCreatingSessonComplete); +} + +void UMainMenuWidget::OnHostOnlineGameButtonClicked() { + // Ensure we have left any session + GetMyGameSubsystem()->DestroySession(); + + GetMyGameSubsystem()->CreateSession( + "Lobby " + FString::FromInt(FMath::RandRange(1, 1e6)), 2, true); +} + +void UMainMenuWidget::StartSessionWhenCreatingSessonComplete(bool bSuccess) { + if (!bSuccess) { + return; + } + GetMyGameSubsystem()->StartSession(); +} + + +USessionsGameInstanceSubsystem *UMainMenuWidget::GetMyGameSubsystem() const { + const UGameInstance *GameInstance = UGameplayStatics::GetGameInstance( + GetWorld()); + USessionsGameInstanceSubsystem *GameInstanceSubsystem = GameInstance-> + GetSubsystem(); + return GameInstanceSubsystem; +} diff --git a/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.h b/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.h new file mode 100644 index 0000000..992d040 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/MainMenuWidget.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "../SessionsGameInstanceSubsystem.h" + +#include "MainMenuWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API UMainMenuWidget : public UUserWidget { + GENERATED_BODY() + +public: + UPROPERTY(meta = (BindWidget)) + class UButton *HostOnlineGameButton; + + virtual void NativeConstruct() override; + +protected: + UFUNCTION() + void OnHostOnlineGameButtonClicked(); + + UFUNCTION() + void StartSessionWhenCreatingSessonComplete(bool bSuccess); + +private: + USessionsGameInstanceSubsystem *GetMyGameSubsystem() const; +}; diff --git a/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.cpp b/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.cpp new file mode 100644 index 0000000..849328b --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SessionListEntryWidget.h" +#include "OnlineSessionSettings.h" +#include "Components/TextBlock.h" + +void USessionListEntryWidget::Update(int SessionIndex, + const FOnlineSessionSearchResult & + Session) { + SessionId = SessionIndex; + IndexText->SetText(FText::AsNumber(SessionIndex + 1)); + + Session.Session.SessionSettings.Get(SETTING_MAPNAME, SessionName); + SessionNameText->SetText(FText::FromString(SessionName)); + + const int MaxPlayerCount = Session.Session.SessionSettings. + NumPublicConnections; + const int CurPlayerCount = MaxPlayerCount - Session.Session. + NumOpenPublicConnections; + + PlayersCountText->SetText(FText::AsNumber(CurPlayerCount)); + PingText->SetText(FText::AsNumber(Session.PingInMs)); +} diff --git a/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.h b/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.h new file mode 100644 index 0000000..8c74028 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/SessionListEntryWidget.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "SessionListEntryWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API USessionListEntryWidget : public UUserWidget { + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock *IndexText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock *SessionNameText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock *PlayersCountText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock *PingText; + + void Update(int SessionIndex, const FOnlineSessionSearchResult &Session); + + int SessionId; + FString SessionName; +}; diff --git a/Source/TurnBasedTutorial/MainMenu/SessionListWidget.cpp b/Source/TurnBasedTutorial/MainMenu/SessionListWidget.cpp new file mode 100644 index 0000000..af32814 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/SessionListWidget.cpp @@ -0,0 +1,83 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SessionListWidget.h" +#include "../SessionsGameInstanceSubsystem.h" +#include "Components/VerticalBox.h" +#include "SessionListEntryWidget.h" +#include "Components/Button.h" +#include "Kismet/GameplayStatics.h" + +void USessionListWidget::NativeConstruct() { + Super::NativeConstruct(); + + RefreshListButton->OnClicked.AddDynamic( + this, &ThisClass::OnRefreshListButtonClicked); + ConnectToSelectedSessionButton->OnClicked.AddDynamic( + this, &ThisClass::ConnectToFirstSession); + + const auto MyGameInstanceSubsystem = GetMyGameSubsystem(); + MyGameInstanceSubsystem->OnFindSessionsCompleteEvent.AddUObject( + this, &ThisClass::RefreshList); + MyGameInstanceSubsystem->OnJoinSessionCompleteEvent.AddUObject( + this, &ThisClass::OnJoinSessionSuccess); + + // Ensure we have left any session + GetMyGameSubsystem()->DestroySession(); + + // Initiate search + MyGameInstanceSubsystem->FindSessions(10, true); +} + +void USessionListWidget::RefreshList( + const TArray &SessionResults, + bool bSuccessful) { + if (!bSuccessful) { + UE_LOG(LogTemp, Error, TEXT("Find sessions FAILED!!!!")); + // TODO: Mark find sessions error + return; + } + SessionListBox->ClearChildren(); + for (const auto &Session : SessionResults) { + auto *ItemWidget = CreateWidget( + this, EntryClass); + ItemWidget->Update(SessionListBox->GetChildrenCount(), Session); + SessionListBox->AddChild(ItemWidget); + } +} + + +void USessionListWidget::OnRefreshListButtonClicked() { + // TODO: Show that we started searching... + // Initiate search + SessionListBox->ClearChildren(); + GetMyGameSubsystem()->FindSessions(10, true); +} + +void USessionListWidget::ConnectToFirstSession() { + GetMyGameSubsystem()->JoinSession(0); +} + + +void USessionListWidget::OnJoinSessionSuccess( + EOnJoinSessionCompleteResult::Type Result) { + if (Result != EOnJoinSessionCompleteResult::Success) { + UE_LOG(LogTemp, Error, TEXT("Failed to connect to session!!")); + return; + } + if (!GetMyGameSubsystem()->TryConnectToCurrentSession()) { + UE_LOG(LogTemp, Error, TEXT("Failed to travel client to session!!")); + return; + } + UE_LOG(LogTemp, Display, TEXT("Connected and travelled to session!!!")); +} + + +USessionsGameInstanceSubsystem * +USessionListWidget::GetMyGameSubsystem() const { + const UGameInstance *GameInstance = UGameplayStatics::GetGameInstance( + GetWorld()); + USessionsGameInstanceSubsystem *GameInstanceSubsystem = GameInstance-> + GetSubsystem(); + return GameInstanceSubsystem; +} diff --git a/Source/TurnBasedTutorial/MainMenu/SessionListWidget.h b/Source/TurnBasedTutorial/MainMenu/SessionListWidget.h new file mode 100644 index 0000000..e0b43ef --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenu/SessionListWidget.h @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "../SessionsGameInstanceSubsystem.h" +#include "Blueprint/UserWidget.h" +#include "SessionListWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API USessionListWidget : public UUserWidget { + GENERATED_BODY() + +protected: + virtual void NativeConstruct() override; + + UPROPERTY(meta = (BindWidget)) + class UButton *ConnectToSelectedSessionButton; + + UPROPERTY(meta = (BindWidget)) + class UButton *GoBackToMainMenuButton; + + UPROPERTY(meta = (BindWidget)) + class UButton *RefreshListButton; + + UPROPERTY(meta = (BindWidget)) + class UVerticalBox *SessionListBox; + + UPROPERTY(EditDefaultsOnly, Category="Session Info Class") + TSubclassOf EntryClass; + + void RefreshList(const TArray &SessionResults, + bool bSuccessful); + + void OnJoinSessionSuccess(EOnJoinSessionCompleteResult::Type Result); + +private: + USessionsGameInstanceSubsystem *GetMyGameSubsystem() const; + + UFUNCTION() + void OnRefreshListButtonClicked(); + + UFUNCTION() + void ConnectToFirstSession(); +}; diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.cpp b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.cpp new file mode 100644 index 0000000..529481b --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.cpp @@ -0,0 +1,11 @@ +#include "ManageSquadGameMode.h" + +#include "ManageSquadGameState.h" +#include "ManageSquadPawn.h" +#include "ManageSquadPlayerController.h" + +AManageSquadGameMode::AManageSquadGameMode() { + PlayerControllerClass = AManageSquadPlayerController::StaticClass(); + DefaultPawnClass = AManageSquadPawn::StaticClass(); + GameStateClass = AManageSquadGameState::StaticClass(); +} diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.h b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.h new file mode 100644 index 0000000..7abdf6f --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameMode.h @@ -0,0 +1,13 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameMode.h" +#include "ManageSquadGameMode.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API AManageSquadGameMode : public AGameMode { + GENERATED_BODY() + +public: + AManageSquadGameMode(); +}; diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.cpp b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.cpp new file mode 100644 index 0000000..da48053 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ManageSquadGameState.h" + +AManageSquadGameState::AManageSquadGameState() { + TroopersKinds = {0, 0, 0, 0, 0}; +} + +void AManageSquadGameState::ChangeSquad(int TrooperIndex, int TrooperKind) { + TroopersKinds[TrooperIndex] = TrooperKind; +} diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.h b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.h new file mode 100644 index 0000000..1198780 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadGameState.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameState.h" +#include "ManageSquadGameState.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API AManageSquadGameState : public AGameState { + GENERATED_BODY() + +public: + AManageSquadGameState(); + + UFUNCTION() + void ChangeSquad(int TrooperIndex, int TrooperKind); + +private: + UPROPERTY() + TArray TroopersKinds; +}; diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.cpp b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.cpp new file mode 100644 index 0000000..1fafe54 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.cpp @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ManageSquadPawn.h" + +// Called when the game starts or when spawned +void AManageSquadPawn::BeginPlay() { + Super::BeginPlay(); +} + +// Called every frame +void AManageSquadPawn::Tick(float DeltaTime) { + Super::Tick(DeltaTime); +} + +// Called to bind functionality to input +void AManageSquadPawn::SetupPlayerInputComponent( + UInputComponent *PlayerInputComponent) { + // Super::SetupPlayerInputComponent(PlayerInputComponent); +} diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.h b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.h new file mode 100644 index 0000000..dace062 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPawn.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/DefaultPawn.h" +#include "ManageSquadPawn.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API AManageSquadPawn : public ADefaultPawn { + GENERATED_BODY() + +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; +}; diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.cpp b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.cpp new file mode 100644 index 0000000..72d4c77 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.cpp @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ManageSquadPlayerController.h" + +#include "ManageSquadGameState.h" + +AManageSquadPlayerController::AManageSquadPlayerController() { + SetShowMouseCursor(true); +} + +void AManageSquadPlayerController::SetupInputComponent() { + Super::SetupInputComponent(); + InputComponent->BindAction("MyAction", IE_Pressed, this, + &AManageSquadPlayerController::OnLeftMouseClick); +} + +void AManageSquadPlayerController::OnLeftMouseClick() { + UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); + FHitResult HitResult; + bool const IsHitResult = GetHitResultUnderCursorForObjects( + TArray>{ObjectTypeQuery1}, false, + HitResult); + if (!IsHitResult) + return; + + UE_LOG(LogTemp, Warning, TEXT("Got hit result")); + // auto const NewlySelectedLocation = HitResult.Location; + AManageSquadTrooper *NewlySelectedTrooper = Cast + ( + HitResult.GetActor()); + + if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + IsValidLowLevel()) { + // we selected something that is not a trooper (or trooper in shitty state...) + UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); + return; + } + // skip re-selection + if (SelectedTrooper == NewlySelectedTrooper) { + UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + return; + } + UE_LOG(LogTemp, Warning, TEXT("Trooper")); + switch (NewlySelectedTrooper->GetType()) { + case ETrooperType::TROOPER_SAMPLE: + if (SelectedTrooper) { + UE_LOG(LogTemp, Warning, TEXT("Trooper replacement")); + SelectedTrooper->ChangeSkeletalMesh(NewlySelectedTrooper); + Cast( + GetWorld()->GetGameState())->ChangeSquad( + SelectedTrooper->GetIndex(), + NewlySelectedTrooper->GetIndex() + ); + } + break; + case ETrooperType::TROOPER_IN_SQUAD: + SelectedTrooper = NewlySelectedTrooper; + UE_LOG(LogTemp, Warning, TEXT("Changed selection")); + break; + default: + break; + } +} diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.h b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.h new file mode 100644 index 0000000..12749f0 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadPlayerController.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "ManageSquadTrooper.h" +#include "ManageSquadPlayerController.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API AManageSquadPlayerController + : public APlayerController { + GENERATED_BODY() + +public: + AManageSquadPlayerController(); + + virtual void SetupInputComponent() override; + +private: + UPROPERTY() + AManageSquadTrooper *SelectedTrooper; + + UFUNCTION() + void OnLeftMouseClick(); +}; diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.cpp b/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.cpp new file mode 100644 index 0000000..3e140f4 --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.cpp @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ManageSquadTrooper.h" + +AManageSquadTrooper::AManageSquadTrooper() { + GetMesh()->SetCollisionResponseToAllChannels( + ECollisionResponse::ECR_Overlap); +} + +// Called when the game starts or when spawned +void AManageSquadTrooper::BeginPlay() { + Super::BeginPlay(); +} + +// Called every frame +void AManageSquadTrooper::Tick(float DeltaTime) { + Super::Tick(DeltaTime); +} + +void AManageSquadTrooper:: +ChangeSkeletalMesh(const AManageSquadTrooper *OtherTrooper) const { + GetMesh()->SetSkeletalMesh(OtherTrooper->GetMesh()->SkeletalMesh); +} + +ETrooperType AManageSquadTrooper::GetType() const { + return Type; +} + +int AManageSquadTrooper::GetIndex() const { + return Index; +} diff --git a/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.h b/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.h new file mode 100644 index 0000000..2da243b --- /dev/null +++ b/Source/TurnBasedTutorial/ManageSquad/ManageSquadTrooper.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Character.h" +#include "ManageSquadTrooper.generated.h" + +UENUM() +enum ETrooperType { + TROOPER_SAMPLE, + TROOPER_IN_SQUAD +}; + +UCLASS() +class TURNBASEDTUTORIAL_API AManageSquadTrooper : public ACharacter { + GENERATED_BODY() + + AManageSquadTrooper(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + UPROPERTY(EditAnywhere) + int Index = -1; + + UPROPERTY(EditAnywhere) + TEnumAsByte Type; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + UFUNCTION() + void ChangeSkeletalMesh(const AManageSquadTrooper *OtherTrooper) const; + + UFUNCTION() + ETrooperType GetType() const; + + UFUNCTION() + int GetIndex() const; +}; diff --git a/Source/TurnBasedTutorial/MyGameMode.cpp b/Source/TurnBasedTutorial/MyGameMode.cpp deleted file mode 100644 index d09b49d..0000000 --- a/Source/TurnBasedTutorial/MyGameMode.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#include "MyGameMode.h" -#include "Kismet/GameplayStatics.h" -#include "Trooper.h" - -AMyGameMode::AMyGameMode() : Super() { - UE_LOG(LogTemp, Warning, TEXT("GameMode Constructor")); - PlayerControllerClass = AMyPlayerController::StaticClass(); -} - -void AMyGameMode::BeginPlay() { - Super::BeginPlay(); - ATrooper::InitNumberOfTroopersForId(); - UE_LOG(LogTemp, Warning, TEXT("GameMode BeginPlay")); - if (GetWorld()->GetMapName().Contains("BattleFieldMap")) { - UE_LOG(LogTemp, Warning, TEXT("Player Logined")); - StartGame(); - } -} - -void AMyGameMode::StartGame() { - FVector Location(2000.0f, -1000.0f, 0.0f); - FRotator Rotation(0.0f, 180.0f, 0.0f); - FActorSpawnParameters SpawnInfo; - for (int i = 0; i < 5; ++i) { - AActor *spawned = GetWorld()->SpawnActor(Location, Rotation, SpawnInfo); - dynamic_cast(spawned)->InitTrooper(Location, true); - Location += { 0.f, 500.f, 0.0f }; - } - Location = { -2000.0f, -1000.0f, 0.0f }; - Rotation = { 0.0f, 0.0f, 0.0f }; - for (int i = 0; i < 5; ++i) { - AActor* spawned = GetWorld()->SpawnActor(Location, Rotation, SpawnInfo); - dynamic_cast(spawned)->InitTrooper(Location, false); - Location += { 0.f, 500.f, 0.0f }; - } - GetPlayerController()->StartTurn(); -} - -AMyPlayerController *AMyGameMode::GetPlayerController() { - return dynamic_cast( - UGameplayStatics::GetPlayerController(GetWorld(), 0) - ); -} diff --git a/Source/TurnBasedTutorial/MyGameMode.h b/Source/TurnBasedTutorial/MyGameMode.h deleted file mode 100644 index f7cccbe..0000000 --- a/Source/TurnBasedTutorial/MyGameMode.h +++ /dev/null @@ -1,26 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "MyPlayerController.h" -#include "GameFramework/GameMode.h" -#include "MyGameMode.generated.h" - - - -UCLASS() -class TURNBASEDTUTORIAL_API AMyGameMode : public AGameMode -{ - GENERATED_BODY() - -public: - AMyGameMode(); - - void BeginPlay() override; - -private: - void StartGame(); - - AMyPlayerController *GetPlayerController(); -}; diff --git a/Source/TurnBasedTutorial/MyPlayerController.cpp b/Source/TurnBasedTutorial/MyPlayerController.cpp deleted file mode 100644 index f069d84..0000000 --- a/Source/TurnBasedTutorial/MyPlayerController.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#include "MyPlayerController.h" - -AMyPlayerController::AMyPlayerController() : Super(), IsMyTurn(false), SelectedTrooper(nullptr) { - UE_LOG(LogTemp, Warning, TEXT("Player controller created")); -} - -void AMyPlayerController::SetupInputComponent() { - Super::SetupInputComponent(); - InputComponent->BindAction("MyAction", IE_Pressed, this, - &AMyPlayerController::OnLeftMouseClick); -} - -void AMyPlayerController::StartTurn() { - IsMyTurn = true; - UE_LOG(LogTemp, Warning, TEXT("Your turn")); -} - -void AMyPlayerController::EndTurn() { - IsMyTurn = false; - UE_LOG(LogTemp, Warning, TEXT("Not your turn")); -} - -void AMyPlayerController::SetTrooperIsMoving(bool isMoving) { - IsThereTrooperMoving = isMoving; -} - -void AMyPlayerController::OnLeftMouseClick() { - if (IsThereTrooperMoving) { - return; - } - UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); - FHitResult HitResult; - bool IsHitResult = GetHitResultUnderCursorByChannel(TraceTypeQuery1, false, HitResult); - if (IsHitResult) { - AActor *actor = HitResult.Actor.Get(); - if (actor->ActorHasTag(FName("Trooper"))) { - ATrooper* trooper = dynamic_cast(actor); - if (trooper != nullptr && trooper != SelectedTrooper) { - if (trooper->IsOnPlayersSide()) { - UE_LOG(LogTemp, Warning, TEXT("Hitted trooper id: %d, on our side"), - trooper->GetId()); - SelectedTrooper = trooper; - } - else { - UE_LOG(LogTemp, Warning, TEXT("Hitted trooper id: %d, enemy"), - trooper->GetId()); - UE_LOG(LogTemp, Warning, TEXT("Trooper #%d hit enemy trooper #%d"), - SelectedTrooper->GetId(), trooper->GetId()); - } - } - } - else if (actor->ActorHasTag(FName("Floor"))) { - UE_LOG(LogTemp, Warning, TEXT("Hitted floor: %f, %f, %f"), HitResult.Location.X, - HitResult.Location.Y, HitResult.Location.Z); - if (SelectedTrooper != nullptr) { - SelectedTrooper->MoveTrooper(HitResult.Location); - IsThereTrooperMoving = true; - } - } - } -} diff --git a/Source/TurnBasedTutorial/MyPlayerController.h b/Source/TurnBasedTutorial/MyPlayerController.h deleted file mode 100644 index 90fb98a..0000000 --- a/Source/TurnBasedTutorial/MyPlayerController.h +++ /dev/null @@ -1,37 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. -#pragma once - -#include "CoreMinimal.h" -#include "Trooper.h" -#include "GameFramework/PlayerController.h" -#include "MyPlayerController.generated.h" - -/** - * - */ -UCLASS() -class TURNBASEDTUTORIAL_API AMyPlayerController : public APlayerController -{ - GENERATED_BODY() - -public: - AMyPlayerController(); - - void StartTurn(); - - void EndTurn(); - - virtual void SetupInputComponent() override; - - void SetTrooperIsMoving(bool isMoving); - -private: - bool IsMyTurn; - - bool IsThereTrooperMoving = false; - - ATrooper* SelectedTrooper; - - void OnLeftMouseClick(); - -}; diff --git a/Source/TurnBasedTutorial/MyPlayerState.cpp b/Source/TurnBasedTutorial/MyPlayerState.cpp deleted file mode 100644 index 00bda13..0000000 --- a/Source/TurnBasedTutorial/MyPlayerState.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "MyPlayerState.h" - diff --git a/Source/TurnBasedTutorial/MyPlayerState.h b/Source/TurnBasedTutorial/MyPlayerState.h deleted file mode 100644 index 991a5cb..0000000 --- a/Source/TurnBasedTutorial/MyPlayerState.h +++ /dev/null @@ -1,17 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/PlayerState.h" -#include "MyPlayerState.generated.h" - -/** - * - */ -UCLASS() -class TURNBASEDTUTORIAL_API AMyPlayerState : public APlayerState -{ - GENERATED_BODY() - -}; diff --git a/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.cpp b/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.cpp new file mode 100644 index 0000000..8f1de33 --- /dev/null +++ b/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.cpp @@ -0,0 +1,399 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SessionsGameInstanceSubsystem.h" + +#include "BattleMode/BattlePlayerController.h" +#include "OnlineSubsystemUtils.h" +#include "GameFramework/GameModeBase.h" +#include "Kismet/GameplayStatics.h" + +USessionsGameInstanceSubsystem::USessionsGameInstanceSubsystem() + : bIsHost(false), + CreateSessionCompleteDelegate( + FOnCreateSessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnCreateSessionCompleted)), + UpdateSessionCompleteDelegate( + FOnUpdateSessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnUpdateSessionCompleted)), + StartSessionCompleteDelegate( + FOnStartSessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnStartSessionCompleted)), + EndSessionCompleteDelegate( + FOnEndSessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnEndSessionCompleted)), + DestroySessionCompleteDelegate( + FOnDestroySessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnDestroySessionCompleted)), + FindSessionsCompleteDelegate( + FOnFindSessionsCompleteDelegate::CreateUObject( + this, &ThisClass::OnFindSessionsCompleted)), + JoinSessionCompleteDelegate( + FOnJoinSessionCompleteDelegate::CreateUObject( + this, &ThisClass::OnJoinSessionCompleted)) { +} + + +void USessionsGameInstanceSubsystem::CreateSession(FString SessionName, + int32 NumPublicConnections, + bool bIsLANMatch) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnCreateSessionCompleteEvent.Broadcast(false); + return; + } + + LastSessionSettings = MakeShareable(new FOnlineSessionSettings()); + LastSessionSettings->NumPrivateConnections = 0; + LastSessionSettings->NumPublicConnections = NumPublicConnections; + LastSessionSettings->bAllowInvites = true; + LastSessionSettings->bAllowJoinInProgress = true; + LastSessionSettings->bAllowJoinViaPresence = true; + LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true; + LastSessionSettings->bUsesPresence = true; + LastSessionSettings->bIsLANMatch = bIsLANMatch; + LastSessionSettings->bShouldAdvertise = true; + + LastSessionSettings->Set(SETTING_MAPNAME, SessionName, + EOnlineDataAdvertisementType::ViaOnlineService); + + CreateSessionCompleteDelegateHandle = SessionInterface-> + AddOnCreateSessionCompleteDelegate_Handle( + CreateSessionCompleteDelegate); + + const ULocalPlayer *localPlayer = GetWorld()-> + GetFirstLocalPlayerFromController(); + if (!SessionInterface->CreateSession( + *localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, + *LastSessionSettings)) { + SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle( + CreateSessionCompleteDelegateHandle); + + OnCreateSessionCompleteEvent.Broadcast(false); + } +} + +void USessionsGameInstanceSubsystem::OnCreateSessionCompleted( + FName SessionName, + bool bSuccessful) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle( + CreateSessionCompleteDelegateHandle); + } + + bIsHost = true; + + OnCreateSessionCompleteEvent.Broadcast(bSuccessful); +} + +void USessionsGameInstanceSubsystem::UpdateSession() { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnCreateSessionCompleteEvent.Broadcast(false); + return; + } + + const TSharedPtr UpdatedSessionSettings = + MakeShareable( + new FOnlineSessionSettings(*LastSessionSettings)); + + // Here we can insert any changes we want + UpdatedSessionSettings->Set(SETTING_MAPNAME, FString("Updated Level Name"), + EOnlineDataAdvertisementType::ViaOnlineService); + + UpdateSessionCompleteDelegateHandle = + SessionInterface->AddOnUpdateSessionCompleteDelegate_Handle( + UpdateSessionCompleteDelegate); + + if (!SessionInterface->UpdateSession(NAME_GameSession, + *UpdatedSessionSettings)) { + SessionInterface->ClearOnUpdateSessionCompleteDelegate_Handle( + UpdateSessionCompleteDelegateHandle); + + OnUpdateSessionCompleteEvent.Broadcast(false); + } else { + LastSessionSettings = UpdatedSessionSettings; + } +} + +void USessionsGameInstanceSubsystem::OnUpdateSessionCompleted( + FName SessionName, + bool bSuccessful) { + const IOnlineSessionPtr sessionInterface = Online::GetSessionInterface( + GetWorld()); + if (sessionInterface.IsValid()) { + sessionInterface->ClearOnUpdateSessionCompleteDelegate_Handle( + UpdateSessionCompleteDelegateHandle); + } + + OnUpdateSessionCompleteEvent.Broadcast(bSuccessful); +} + + +void USessionsGameInstanceSubsystem::StartSession() { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnCreateSessionCompleteEvent.Broadcast(false); + return; + } + StartSessionCompleteDelegateHandle = SessionInterface-> + AddOnStartSessionCompleteDelegate_Handle( + StartSessionCompleteDelegate); + + if (!SessionInterface->StartSession(NAME_GameSession)) { + SessionInterface->ClearOnStartSessionCompleteDelegate_Handle( + StartSessionCompleteDelegateHandle); + + OnStartSessionCompleteEvent.Broadcast(false); + } +} + + +void USessionsGameInstanceSubsystem::OnStartSessionCompleted( + FName SessionName, + bool bSuccessful) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnStartSessionCompleteDelegate_Handle( + StartSessionCompleteDelegateHandle); + } + OnStartSessionCompleteEvent.Broadcast(bSuccessful); + + // TODO: Move this from gameinstance subsystem. This should not be here. + UGameplayStatics::OpenLevel(GetWorld(), "BattleFieldMap", true, "listen"); +} + + +void USessionsGameInstanceSubsystem::EndSession() { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnCreateSessionCompleteEvent.Broadcast(false); + return; + } + + EndSessionCompleteDelegateHandle = SessionInterface-> + AddOnEndSessionCompleteDelegate_Handle( + EndSessionCompleteDelegate); + + if (!SessionInterface->EndSession(NAME_GameSession)) { + SessionInterface->ClearOnEndSessionCompleteDelegate_Handle( + EndSessionCompleteDelegateHandle); + + OnEndSessionCompleteEvent.Broadcast(false); + } +} + + +void USessionsGameInstanceSubsystem::OnEndSessionCompleted( + FName SessionName, + bool bSuccessful) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnEndSessionCompleteDelegate_Handle( + EndSessionCompleteDelegateHandle); + } + + OnEndSessionCompleteEvent.Broadcast(bSuccessful); +} + + +void USessionsGameInstanceSubsystem::DestroySession() { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnDestroySessionCompleteEvent.Broadcast(false); + return; + } + + DestroySessionCompleteDelegateHandle = SessionInterface-> + AddOnDestroySessionCompleteDelegate_Handle( + DestroySessionCompleteDelegate); + + if (!SessionInterface->DestroySession(NAME_GameSession)) { + SessionInterface->ClearOnDestroySessionCompleteDelegate_Handle( + EndSessionCompleteDelegateHandle); + + OnDestroySessionCompleteEvent.Broadcast(false); + } +} + + +void USessionsGameInstanceSubsystem::OnDestroySessionCompleted( + FName SessionName, + bool bSuccessful) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnDestroySessionCompleteDelegate_Handle( + DestroySessionCompleteDelegateHandle); + } + + OnDestroySessionCompleteEvent.Broadcast(bSuccessful); +} + + +void USessionsGameInstanceSubsystem::FindSessions(int32 MaxSearchResults, + bool bIsLANQuery) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnFindSessionsCompleteEvent.Broadcast( + TArray(), false); + return; + } + + FindSessionsCompleteDelegateHandle = SessionInterface-> + AddOnFindSessionsCompleteDelegate_Handle( + FindSessionsCompleteDelegate); + + LastSessionSearch = MakeShareable(new FOnlineSessionSearch()); + LastSessionSearch->MaxSearchResults = MaxSearchResults; + LastSessionSearch->bIsLanQuery = bIsLANQuery; + + // Disable dedicated server search (maybe enable later, when dedicated server is implemented) + // LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); + + const ULocalPlayer *LocalPlayer = GetWorld()-> + GetFirstLocalPlayerFromController(); + if (!SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), + LastSessionSearch.ToSharedRef())) { + SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle( + FindSessionsCompleteDelegateHandle); + + OnFindSessionsCompleteEvent.Broadcast( + TArray(), false); + } +} + + +void USessionsGameInstanceSubsystem::OnFindSessionsCompleted(bool bSuccessful) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle( + FindSessionsCompleteDelegateHandle); + } + + if (LastSessionSearch->SearchResults.Num() <= 0) { + OnFindSessionsCompleteEvent.Broadcast( + TArray(), bSuccessful); + return; + } + + OnFindSessionsCompleteEvent.Broadcast(LastSessionSearch->SearchResults, + bSuccessful); +} + + +void USessionsGameInstanceSubsystem::JoinSession( + const FOnlineSessionSearchResult &SessionSearchResult) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnJoinSessionCompleteEvent.Broadcast( + EOnJoinSessionCompleteResult::UnknownError); + return; + } + + JoinSessionCompleteDelegateHandle = SessionInterface-> + AddOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegate); + + const ULocalPlayer *LocalPlayer = GetWorld()-> + GetFirstLocalPlayerFromController(); + if (!SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), + NAME_GameSession, SessionSearchResult)) { + SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegateHandle); + + OnJoinSessionCompleteEvent.Broadcast( + EOnJoinSessionCompleteResult::UnknownError); + } +} + +void USessionsGameInstanceSubsystem::JoinSession(const int32 Index) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + OnJoinSessionCompleteEvent.Broadcast( + EOnJoinSessionCompleteResult::UnknownError); + return; + } + if (!LastSessionSearch.IsValid() || Index >= LastSessionSearch-> + SearchResults.Num()) { + OnJoinSessionCompleteEvent.Broadcast( + EOnJoinSessionCompleteResult::UnknownError); + return; + } + + JoinSessionCompleteDelegateHandle = SessionInterface-> + AddOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegate); + + const ULocalPlayer *LocalPlayer = GetWorld()-> + GetFirstLocalPlayerFromController(); + if (!SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), + NAME_GameSession, + LastSessionSearch->SearchResults[ + Index])) { + SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegateHandle); + + OnJoinSessionCompleteEvent.Broadcast( + EOnJoinSessionCompleteResult::UnknownError); + } +} + + +void USessionsGameInstanceSubsystem::OnJoinSessionCompleted( + FName SessionName, + EOnJoinSessionCompleteResult::Type Result) { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (SessionInterface.IsValid()) { + SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegateHandle); + } + + OnJoinSessionCompleteEvent.Broadcast(Result); +} + + +bool USessionsGameInstanceSubsystem::TryConnectToCurrentSession() const { + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface( + GetWorld()); + if (!SessionInterface.IsValid()) { + return false; + } + + FString ConnectString; + if (!SessionInterface->GetResolvedConnectString( + NAME_GameSession, ConnectString)) { + return false; + } + + APlayerController *PlayerController = GetWorld()-> + GetFirstPlayerController(); + PlayerController->ClientTravel(ConnectString, TRAVEL_Absolute); + return true; +} + +void USessionsGameInstanceSubsystem::QuitCurrentSession() { + if (bIsHost) { + UGameplayStatics::GetGameMode(GetWorld())->ReturnToMainMenuHost(); + } else { + APlayerController *LocalController = GEngine-> + GetFirstLocalPlayerController(GetWorld()); + LocalController->ClientReturnToMainMenuWithTextReason( + FText::FromString("Session ended")); + } + bIsHost = false; + DestroySession(); +} diff --git a/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.h b/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.h new file mode 100644 index 0000000..fd7d84d --- /dev/null +++ b/Source/TurnBasedTutorial/SessionsGameInstanceSubsystem.h @@ -0,0 +1,116 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "OnlineSessionSettings.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "SessionsGameInstanceSubsystem.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnCreateSessionComplete, bool, + bSuccessful); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnUpdateSessionComplete, bool, + bSuccessful); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnStartSessionCompete, bool, + bSuccessful); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnEndSessionComplete, bool, + bSuccessful); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnDestroySessionComplete, bool, + bSuccessful); + +DECLARE_MULTICAST_DELEGATE_TwoParams(FMyOnFindSessionsComplete, + const TArray& + SessionResults, bool bSuccessful); + +DECLARE_MULTICAST_DELEGATE_OneParam(FMyOnJoinSessionCompele, + EOnJoinSessionCompleteResult::Type Result); +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API USessionsGameInstanceSubsystem + : public UGameInstanceSubsystem { + GENERATED_BODY() + +public: + USessionsGameInstanceSubsystem(); + + void CreateSession(FString SessionName, + int32 NumPublicConnections, + bool bIsLANMatch); + + void UpdateSession(); + + void StartSession(); + + void EndSession(); + + void DestroySession(); + + void FindSessions(int32 MaxSearchResults, bool bIsLANQuery); + + void JoinSession(const FOnlineSessionSearchResult &SessionSearchResult); + + void JoinSession(const int32 Index); + + bool TryConnectToCurrentSession() const; + + void QuitCurrentSession(); + + void UpdateSessionName(FString NewSessionName); + + FMyOnCreateSessionComplete OnCreateSessionCompleteEvent; + FMyOnUpdateSessionComplete OnUpdateSessionCompleteEvent; + FMyOnStartSessionCompete OnStartSessionCompleteEvent; + FMyOnEndSessionComplete OnEndSessionCompleteEvent; + FMyOnDestroySessionComplete OnDestroySessionCompleteEvent; + FMyOnFindSessionsComplete OnFindSessionsCompleteEvent; + FMyOnJoinSessionCompele OnJoinSessionCompleteEvent; + +protected: + void OnCreateSessionCompleted(FName SessionName, bool bSuccessful); + + void OnUpdateSessionCompleted(FName SessionName, bool bSuccessful); + + void OnStartSessionCompleted(FName SessionName, bool bSuccessful); + + void OnEndSessionCompleted(FName SessionName, bool bSuccessful); + + void OnDestroySessionCompleted(FName SessionName, bool bSuccessful); + + void OnFindSessionsCompleted(bool bSuccessful); + + void OnJoinSessionCompleted(FName SessionName, + EOnJoinSessionCompleteResult::Type Result); + +private: + bool bIsHost; + + FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate; + FDelegateHandle CreateSessionCompleteDelegateHandle; + TSharedPtr LastSessionSettings; + + FOnUpdateSessionCompleteDelegate UpdateSessionCompleteDelegate; + FDelegateHandle UpdateSessionCompleteDelegateHandle; + + FOnStartSessionCompleteDelegate StartSessionCompleteDelegate; + FDelegateHandle StartSessionCompleteDelegateHandle; + + FOnEndSessionCompleteDelegate EndSessionCompleteDelegate; + FDelegateHandle EndSessionCompleteDelegateHandle; + + FOnDestroySessionCompleteDelegate DestroySessionCompleteDelegate; + FDelegateHandle DestroySessionCompleteDelegateHandle; + + FOnFindSessionsCompleteDelegate FindSessionsCompleteDelegate; + FDelegateHandle FindSessionsCompleteDelegateHandle; + TSharedPtr LastSessionSearch; + + FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate; + FDelegateHandle JoinSessionCompleteDelegateHandle; +}; diff --git a/Source/TurnBasedTutorial/Trooper.cpp b/Source/TurnBasedTutorial/Trooper.cpp deleted file mode 100644 index 2315b23..0000000 --- a/Source/TurnBasedTutorial/Trooper.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "Trooper.h" -#include -#include "MyPlayerController.h" - -// Sets default values -ATrooper::ATrooper() { - PrimaryActorTick.bCanEverTick = true; - Tags.Add(FName("Trooper")); - Id = NumberOfTroopersForId++; - Position.Set(0, 0, 0); - Mesh = CreateDefaultSubobject("Mesh"); - RootComponent = Mesh; - static ConstructorHelpers::FObjectFinder MeshToUse(TEXT( - "StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'" - )); - if (MeshToUse.Object) - { - Mesh->SetStaticMesh(MeshToUse.Object); - } -} - -// Called when the game starts or when spawned -void ATrooper::BeginPlay() -{ - Super::BeginPlay(); -} - -void ATrooper::Tick(float deltaTime) { - if (IsMoving) { - FVector vector = (MoveToVector - Position); - vector.Normalize(); - vector *= (Speed * deltaTime); - if (vector.Size() >= (MoveToVector - Position).Size()) { - Position = MoveToVector; - IsMoving = false; - dynamic_cast( - UGameplayStatics::GetPlayerController(GetWorld(), 0) - )->SetTrooperIsMoving(false); - } - else { - Position += vector; - } - SetActorLocation(Position); - } -} - -void ATrooper::MoveTrooper(FVector newPos) { - MoveToVector = newPos; - IsMoving = true; -} - -int ATrooper::NumberOfTroopersForId = 0; - -void ATrooper::InitNumberOfTroopersForId() { - NumberOfTroopersForId = 0; -} - -FVector ATrooper::GetPosition() { - return Position; -} - -bool ATrooper::IsOnPlayersSide() { - return OnPlayersSide; -} - -int ATrooper::GetId() { - return Id; -} - -void ATrooper::InitTrooper(FVector position, bool onPlayersSide) { - Position = position; - OnPlayersSide = onPlayersSide; -} diff --git a/Source/TurnBasedTutorial/Trooper.h b/Source/TurnBasedTutorial/Trooper.h deleted file mode 100644 index c6d2b75..0000000 --- a/Source/TurnBasedTutorial/Trooper.h +++ /dev/null @@ -1,56 +0,0 @@ - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/Actor.h" -#include "Components/StaticMeshComponent.h" -#include "Trooper.generated.h" - -UCLASS() -class TURNBASEDTUTORIAL_API ATrooper : public AActor -{ - GENERATED_BODY() - -public: - // Sets default values for this actor's properties - ATrooper(); - -protected: - static int NumberOfTroopersForId; - - virtual void BeginPlay() override; - - virtual void Tick(float deltaTime) override; - - UPROPERTY() - FVector Position; - - UPROPERTY() - bool OnPlayersSide; - - UPROPERTY() - int Id; - - UPROPERTY(VisibleAnywhere, BlueprintReadOnly) - UStaticMeshComponent* Mesh; - - UPROPERTY() - float Speed = 300.0f; - - bool IsMoving = false; - - FVector MoveToVector; - -public: - void MoveTrooper(FVector newPos); - - static void InitNumberOfTroopersForId(); - - FVector GetPosition(); - - bool IsOnPlayersSide(); - - int GetId(); - - void InitTrooper(FVector position, bool onPlayersSide); -}; diff --git a/Source/TurnBasedTutorial/TurnBasedTutorial.Build.cs b/Source/TurnBasedTutorial/TurnBasedTutorial.Build.cs index 7f99bb8..de07b92 100644 --- a/Source/TurnBasedTutorial/TurnBasedTutorial.Build.cs +++ b/Source/TurnBasedTutorial/TurnBasedTutorial.Build.cs @@ -16,7 +16,7 @@ public class TurnBasedTutorial : ModuleRules // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // Uncomment if you are using online features - // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + PrivateDependencyModuleNames.AddRange(new string[] {"OnlineSubsystem", "OnlineSubsystemUtils"}); // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true } diff --git a/Source/TurnBasedTutorial/TurnBasedTutorial.cpp b/Source/TurnBasedTutorial/TurnBasedTutorial.cpp index 967bcf2..dad6184 100644 --- a/Source/TurnBasedTutorial/TurnBasedTutorial.cpp +++ b/Source/TurnBasedTutorial/TurnBasedTutorial.cpp @@ -3,4 +3,5 @@ #include "TurnBasedTutorial.h" #include "Modules/ModuleManager.h" -IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, TurnBasedTutorial, "TurnBasedTutorial" ); +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, TurnBasedTutorial, + "TurnBasedTutorial"); diff --git a/Source/TurnBasedTutorial/TurnBasedTutorial.h b/Source/TurnBasedTutorial/TurnBasedTutorial.h index 677c8e2..018672a 100644 --- a/Source/TurnBasedTutorial/TurnBasedTutorial.h +++ b/Source/TurnBasedTutorial/TurnBasedTutorial.h @@ -2,5 +2,4 @@ #pragma once -#include "CoreMinimal.h" - +#include "Core.h" diff --git a/TurnBased.sln.DotSettings.user b/TurnBased.sln.DotSettings.user new file mode 100644 index 0000000..f591ba1 --- /dev/null +++ b/TurnBased.sln.DotSettings.user @@ -0,0 +1,2 @@ + + INFO \ No newline at end of file diff --git a/TurnBased.uproject b/TurnBased.uproject index 7454dbb..8485d6b 100644 --- a/TurnBased.uproject +++ b/TurnBased.uproject @@ -1,6 +1,6 @@ { "FileVersion": 3, - "EngineAssociation": "{B4FE6467-4579-3D84-B22A-558A3D607596}", + "EngineAssociation": "4.27", "Category": "", "Description": "", "Modules": [ @@ -9,7 +9,8 @@ "Type": "Runtime", "LoadingPhase": "Default", "AdditionalDependencies": [ - "Engine" + "Engine", + "UMG" ] } ] diff --git a/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt b/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt new file mode 100644 index 0000000..f1f2447 --- /dev/null +++ b/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt @@ -0,0 +1,25 @@ +TurnBased/Binaries/Win64/TurnBasedTutorial.exe 2023-03-16T03:05:02.259Z +TurnBased/Binaries/Win64/OpenImageDenoise.dll 2023-03-16T01:52:15.842Z +TurnBased/Binaries/Win64/tbb12.dll 2023-03-16T01:52:15.844Z +Engine/Extras/Redist/en-us/UE4PrereqSetup_x64.exe 2023-03-16T01:46:38.646Z +Engine/Binaries/ThirdParty/Oculus/OVRPlugin/OVRPlugin/Win64/OVRPlugin.dll 2023-03-16T01:41:33.496Z +Engine/Binaries/ThirdParty/DbgHelp/dbghelp.dll 2023-03-16T01:41:25.090Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PxFoundationPROFILE_x64.dll 2023-03-16T01:41:46.155Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PxPvdSDKPROFILE_x64.dll 2023-03-16T01:41:46.339Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3PROFILE_x64.dll 2023-03-16T01:41:45.025Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3CookingPROFILE_x64.dll 2023-03-16T01:41:45.005Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3CommonPROFILE_x64.dll 2023-03-16T01:41:44.869Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/APEX_ClothingPROFILE_x64.dll 2023-03-16T01:41:41.229Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/APEX_LegacyPROFILE_x64.dll 2023-03-16T01:41:42.482Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/ApexFrameworkPROFILE_x64.dll 2023-03-16T01:41:43.065Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/NvClothPROFILE_x64.dll 2023-03-16T01:41:43.666Z +Engine/Binaries/ThirdParty/Ogg/Win64/VS2015/libogg_64.dll 2023-03-16T01:41:33.497Z +Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbis_64.dll 2023-03-16T01:41:53.464Z +Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbisfile_64.dll 2023-03-16T01:41:53.464Z +Engine/Binaries/ThirdParty/NVIDIA/NVaftermath/Win64/GFSDK_Aftermath_Lib.x64.dll 2023-03-16T01:41:32.651Z +Engine/Binaries/ThirdParty/OpenXR/win64/openxr_loader.dll 2023-03-16T01:41:33.921Z +Engine/Binaries/ThirdParty/OpenVR/OpenVRv1_5_17/Win64/openvr_api.dll 2023-03-16T01:41:33.917Z +Engine/Binaries/ThirdParty/NVIDIA/GeForceNOW/Win64/GfnRuntimeSdk.dll 2023-03-16T01:41:32.648Z +Engine/Binaries/ThirdParty/Windows/WinPixEventRuntime/x64/WinPixEventRuntime.dll 2023-03-16T01:41:53.487Z +Engine/Binaries/ThirdParty/Windows/XAudio2_9/x64/xaudio2_9redist.dll 2023-03-16T01:41:54.149Z +TurnBasedTutorial.exe 2023-03-16T03:07:14.267Z diff --git a/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak b/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak new file mode 100644 index 0000000..549883f Binary files /dev/null and b/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak differ