From c99be9e314c04e16f4f304c9b0c3e68cc1bccf9d Mon Sep 17 00:00:00 2001 From: wy Date: Fri, 16 Jan 2026 21:34:51 +0900 Subject: [PATCH] first --- README.md | 1 + .../Commands/CustomExtensionCommands.cpp | 71 + .../Commands/CustomExtensionCommands.h | 53 + .../EditorSlateStyle/CustomSlateStyle.cpp | 58 + .../EditorSlateStyle/CustomSlateStyle.h | 30 + .../EditorUtilityModule.build.cs | 21 + .../EditorUtilityModule.cpp | 132 ++ .../EditorUtilityModule/EditorUtilityModule.h | 24 + .../SystemMessage/MessageAlert.cpp | 24 + .../SystemMessage/MessageAlert.h | 18 + Source/ProjectT.Target.cs | 15 + .../Data/Gen/GenerateEnumContentType.h | 55 + .../Data/Gen/GenerateEnumDataTableKey.h | 54 + .../Data/Gen/GenerateEnumEffectSubTypes.h | 41 + .../Data/Gen/GenerateEnumEffectTypes.h | 25 + .../ProjectT/Data/Gen/GenerateEnumEnemyNpc.h | 25 + .../ProjectT/Data/Gen/GenerateEnumItemTypes.h | 25 + .../Data/Gen/GenerateEnumLevelObjectTypes.h | 23 + .../ProjectT/Data/Gen/GenerateEnumNpcTypes.h | 25 + .../Data/Gen/GenerateEnumObjectiveSubTypes.h | 27 + .../Data/Gen/GenerateEnumObjectiveTypes.h | 23 + .../Data/Gen/GenerateEnumSkillTypes.h | 27 + Source/ProjectT/Data/Gen/GenerateEnumStage.h | 37 + .../Data/Gen/GenerateEnumUnlockTypes.h | 25 + .../Data/Gen/GenerateStructAnimationSet.h | 33 + .../Data/Gen/GenerateStructCharacterMeshSet.h | 41 + .../Data/Gen/GenerateStructCharacterUnlock.h | 45 + .../ProjectT/Data/Gen/GenerateStructEffect.h | 57 + .../Data/Gen/GenerateStructEnemyNpc.h | 101 + .../Data/Gen/GenerateStructHapticList.h | 33 + Source/ProjectT/Data/Gen/GenerateStructItem.h | 53 + .../ProjectT/Data/Gen/GenerateStructItemSet.h | 41 + .../Data/Gen/GenerateStructLevelObject.h | 37 + .../Data/Gen/GenerateStructLocalization.h | 37 + .../Data/Gen/GenerateStructMeshList.h | 33 + .../Data/Gen/GenerateStructObjective.h | 49 + .../Data/Gen/GenerateStructPlayerCharacter.h | 117 + .../ProjectT/Data/Gen/GenerateStructSkill.h | 101 + .../Data/Gen/GenerateStructSocketList.h | 33 + .../Data/Gen/GenerateStructSoundList.h | 49 + .../ProjectT/Data/Gen/GenerateStructStage.h | 77 + .../ProjectT/Data/Gen/GenerateStructVfxList.h | 33 + Source/ProjectT/Data/Npc/NpcDataModel.cpp | 4 + Source/ProjectT/Data/Npc/NpcDataModel.h | 153 ++ .../Data/Paths/BaseDataPathLibrary.cpp | 25 + .../ProjectT/Data/Paths/BaseDataPathLibrary.h | 38 + .../Data/Paths/Core/CoreDataPathLibrary.cpp | 16 + .../Data/Paths/Core/CoreDataPathLibrary.h | 22 + .../Data/Paths/Level/LevelDataPathLibrary.cpp | 16 + .../Data/Paths/Level/LevelDataPathLibrary.h | 23 + .../Data/Paths/UI/UIDataPathLibrary.cpp | 10 + .../Data/Paths/UI/UIDataPathLibrary.h | 18 + .../Player/Inventory/PlayerInventoryModel.cpp | 4 + .../Player/Inventory/PlayerInventoryModel.h | 48 + .../ProjectT/Data/Player/PlayerDataModel.cpp | 4 + Source/ProjectT/Data/Player/PlayerDataModel.h | 146 ++ Source/ProjectT/Data/User/UserDataModel.cpp | 5 + Source/ProjectT/Data/User/UserDataModel.h | 134 ++ Source/ProjectT/ProjectT.Build.cs | 44 + Source/ProjectT/ProjectT.cpp | 6 + Source/ProjectT/ProjectT.h | 75 + .../Animations/AnimNotify/AbnormalAnimEnd.cpp | 17 + .../Animations/AnimNotify/AbnormalAnimEnd.h | 16 + .../Animations/AnimNotify/NonInputAnimEnd.cpp | 21 + .../Animations/AnimNotify/NonInputAnimEnd.h | 18 + .../Animations/AnimNotify/SkillHitEnabled.cpp | 36 + .../Animations/AnimNotify/SkillHitEnabled.h | 18 + .../NotifyState/SkillFXEnabledState.cpp | 56 + .../NotifyState/SkillFXEnabledState.h | 22 + .../NotifyState/SkillHitEnabledState.cpp | 59 + .../NotifyState/SkillHitEnabledState.h | 18 + .../Core/Characters/CombatCharacter.cpp | 258 +++ .../System/Core/Characters/CombatCharacter.h | 69 + .../System/Core/Characters/CoreCharacter.cpp | 37 + .../System/Core/Characters/CoreCharacter.h | 33 + .../AI/Blackboard/BlackboardKeyLibrary.cpp | 22 + .../NPC/AI/Blackboard/BlackboardKeyLibrary.h | 63 + .../NPC/AI/Controllers/AIControllerBase.cpp | 154 ++ .../NPC/AI/Controllers/AIControllerBase.h | 76 + .../AI/Controllers/AIHearingController.cpp | 44 + .../NPC/AI/Controllers/AIHearingController.h | 27 + .../AI/Controllers/AIPerceptionController.cpp | 185 ++ .../AI/Controllers/AIPerceptionController.h | 39 + .../NPC/AI/Controllers/AISightController.cpp | 47 + .../NPC/AI/Controllers/AISightController.h | 28 + .../Controllers/AISightHearingController.cpp | 53 + .../AI/Controllers/AISightHearingController.h | 30 + .../NPC/Animations/NpcAnimInstance.cpp | 22 + .../NPC/Animations/NpcAnimInstance.h | 32 + .../NPC/Animations/NpcFixedAnimInstance.cpp | 11 + .../NPC/Animations/NpcFixedAnimInstance.h | 20 + .../System/Core/Characters/NPC/CoreNpc.cpp | 951 +++++++++ .../System/Core/Characters/NPC/CoreNpc.h | 282 +++ .../PlayerCharacterAnimInstance.cpp | 149 ++ .../PlayerCharacterAnimInstance.h | 107 + .../Characters/Player/CorePlayerCharacter.cpp | 1881 +++++++++++++++++ .../Characters/Player/CorePlayerCharacter.h | 360 ++++ .../AnimInstance/SkillObjectAnimInstance.cpp | 22 + .../AnimInstance/SkillObjectAnimInstance.h | 28 + .../Core/Characters/Skill/CoreSkill.cpp | 277 +++ .../System/Core/Characters/Skill/CoreSkill.h | 133 ++ .../Core/Characters/Skill/HealingPotion.cpp | 45 + .../Core/Characters/Skill/HealingPotion.h | 28 + .../Core/Characters/Skill/HolisterAtk.cpp | 149 ++ .../Core/Characters/Skill/HolisterAtk.h | 43 + .../Core/Characters/Skill/HolisterSkill.cpp | 149 ++ .../Core/Characters/Skill/HolisterSkill.h | 43 + .../System/Core/Characters/Skill/IcienAtk.cpp | 194 ++ .../System/Core/Characters/Skill/IcienAtk.h | 59 + .../Core/Characters/Skill/IcienSkill.cpp | 154 ++ .../System/Core/Characters/Skill/IcienSkill.h | 51 + .../System/Core/Characters/Skill/NoxAtk.cpp | 257 +++ .../System/Core/Characters/Skill/NoxAtk.h | 75 + .../System/Core/Characters/Skill/NoxSkill.cpp | 296 +++ .../System/Core/Characters/Skill/NoxSkill.h | 77 + .../System/Core/Characters/Skill/NpcGAtk.cpp | 141 ++ .../System/Core/Characters/Skill/NpcGAtk.h | 45 + .../System/Core/Characters/Skill/NpcRAtk.cpp | 224 ++ .../System/Core/Characters/Skill/NpcRAtk.h | 71 + .../System/Core/Characters/Skill/PyroAtk.cpp | 133 ++ .../System/Core/Characters/Skill/PyroAtk.h | 43 + .../Core/Characters/Skill/PyroSkill.cpp | 281 +++ .../System/Core/Characters/Skill/PyroSkill.h | 77 + .../Core/Characters/Skill/SmokeShell.cpp | 317 +++ .../System/Core/Characters/Skill/SmokeShell.h | 88 + .../Core/Characters/Skill/SneakoAtk.cpp | 145 ++ .../System/Core/Characters/Skill/SneakoAtk.h | 47 + .../Core/Characters/Skill/SneakoSkill.cpp | 152 ++ .../Core/Characters/Skill/SneakoSkill.h | 51 + .../System/Core/Characters/Skill/TumaiToy.cpp | 266 +++ .../System/Core/Characters/Skill/TumaiToy.h | 85 + .../ObjectiveCharacterAnimInstance.cpp | 18 + .../ObjectiveCharacterAnimInstance.h | 17 + .../Target/CoreObjectiveCharacter.cpp | 65 + .../Target/CoreObjectiveCharacter.h | 41 + .../Characters/Target/CoreSaveCharacter.cpp | 37 + .../Characters/Target/CoreSaveCharacter.h | 28 + .../System/Core/Common/AssetUtilsLibrary.cpp | 125 ++ .../System/Core/Common/AssetUtilsLibrary.h | 71 + .../System/Core/Common/EditorUtilsLibrary.cpp | 325 +++ .../System/Core/Common/EditorUtilsLibrary.h | 91 + .../System/Core/Common/GlobalUtilsLibrary.cpp | 424 ++++ .../System/Core/Common/GlobalUtilsLibrary.h | 281 +++ .../Core/Components/CoreCameraComponent.cpp | 136 ++ .../Core/Components/CoreCameraComponent.h | 70 + .../Components/ObstacleFilterComponent.cpp | 123 ++ .../Core/Components/ObstacleFilterComponent.h | 71 + .../Core/Components/PathFollowComponent.cpp | 118 ++ .../Core/Components/PathFollowComponent.h | 55 + .../Components/PlayerInventoryComponent.cpp | 183 ++ .../Components/PlayerInventoryComponent.h | 53 + .../Core/Components/PlayerStatusComponent.cpp | 185 ++ .../Core/Components/PlayerStatusComponent.h | 106 + .../Core/Components/VisionConeComponent.cpp | 234 ++ .../Core/Components/VisionConeComponent.h | 184 ++ .../Components/WidgetManagerComponent.cpp | 134 ++ .../Core/Components/WidgetManagerComponent.h | 64 + Source/ProjectT/System/Core/Core.zip | Bin 0 -> 2672 bytes .../ProjectT/System/Core/CoreGameInstance.cpp | 118 ++ .../ProjectT/System/Core/CoreGameInstance.h | 60 + Source/ProjectT/System/Core/ELoadingPhase.h | 12 + .../System/Core/GameModes/CoreGameMode.cpp | 87 + .../System/Core/GameModes/CoreGameMode.h | 34 + .../System/Core/GameModes/CoreGameState.cpp | 25 + .../System/Core/GameModes/CoreGameState.h | 25 + .../Core/GameModes/CorePlayerController.cpp | 110 + .../Core/GameModes/CorePlayerController.h | 47 + .../System/Core/GameModes/CorePlayerState.cpp | 5 + .../System/Core/GameModes/CorePlayerState.h | 17 + .../System/Core/GameModes/WorldGameMode.cpp | 358 ++++ .../System/Core/GameModes/WorldGameMode.h | 67 + .../ProjectT/System/Core/Input/KeyTrigger.cpp | 15 + .../ProjectT/System/Core/Input/KeyTrigger.h | 21 + .../System/Core/Interfaces/AISettings.cpp | 4 + .../System/Core/Interfaces/AISettings.h | 92 + .../System/Core/Interfaces/ContentType.cpp | 7 + .../System/Core/Interfaces/ContentType.h | 39 + .../Core/Interfaces/CoreCameraControl.cpp | 7 + .../Core/Interfaces/CoreCameraControl.h | 38 + .../Core/Interfaces/CoreObjectProvider.cpp | 7 + .../Core/Interfaces/CoreObjectProvider.h | 22 + .../System/Core/Interfaces/Damageable.cpp | 7 + .../System/Core/Interfaces/Damageable.h | 36 + .../Core/Interfaces/DebugHitCollision.cpp | 7 + .../Core/Interfaces/DebugHitCollision.h | 29 + .../Core/Interfaces/GlobalObjectProvider.cpp | 4 + .../Core/Interfaces/GlobalObjectProvider.h | 37 + .../Core/Interfaces/ItemObjectControl.cpp | 6 + .../Core/Interfaces/ItemObjectControl.h | 30 + .../System/Core/Interfaces/LoadableObject.cpp | 7 + .../System/Core/Interfaces/LoadableObject.h | 27 + .../Core/Interfaces/MouseInteraction.cpp | 7 + .../System/Core/Interfaces/MouseInteraction.h | 23 + .../Interfaces/ObjectInteractionControl.cpp | 7 + .../Interfaces/ObjectInteractionControl.h | 62 + .../System/Core/Interfaces/PoolableActor.cpp | 7 + .../System/Core/Interfaces/PoolableActor.h | 31 + .../Core/Interfaces/ProcessStateControl.cpp | 7 + .../Core/Interfaces/ProcessStateControl.h | 44 + .../System/Core/Interfaces/Visualizable.cpp | 7 + .../System/Core/Interfaces/Visualizable.h | 28 + .../Core/Interfaces/WidgetInputHandler.cpp | 6 + .../Core/Interfaces/WidgetInputHandler.h | 47 + .../Core/Interfaces/WorldObjectProvider.cpp | 5 + .../Core/Interfaces/WorldObjectProvider.h | 28 + .../System/Core/Managers/CoreCheatManager.cpp | 441 ++++ .../System/Core/Managers/CoreCheatManager.h | 197 ++ .../Core/Managers/CoreWidgetManager.cpp | 19 + .../System/Core/Managers/CoreWidgetManager.h | 23 + .../ProjectT/System/Core/Managers/DataDam.cpp | 128 ++ .../ProjectT/System/Core/Managers/DataDam.h | 103 + .../System/Core/Managers/LoadingManager.cpp | 328 +++ .../System/Core/Managers/LoadingManager.h | 83 + .../Core/Managers/NotificationCenter.cpp | 110 + .../System/Core/Managers/NotificationCenter.h | 114 + .../System/Core/Managers/OptionManager.cpp | 72 + .../System/Core/Managers/OptionManager.h | 109 + .../Core/Managers/PooledActorManager.cpp | 99 + .../System/Core/Managers/PooledActorManager.h | 26 + .../System/Core/Managers/QuestManager.cpp | 209 ++ .../System/Core/Managers/QuestManager.h | 204 ++ .../System/Core/Managers/ResourceManager.cpp | 37 + .../System/Core/Managers/ResourceManager.h | 31 + .../System/Core/Managers/SequenceManager.cpp | 202 ++ .../System/Core/Managers/SequenceManager.h | 69 + .../System/Core/Managers/SoundManager.cpp | 220 ++ .../System/Core/Managers/SoundManager.h | 124 ++ .../System/Core/Managers/StageManager.cpp | 212 ++ .../System/Core/Managers/StageManager.h | 78 + .../System/Core/Mouse/LinearVisualObject.cpp | 74 + .../System/Core/Mouse/LinearVisualObject.h | 40 + Source/ProjectT/System/Core/Mouse/Mouse.cpp | 261 +++ Source/ProjectT/System/Core/Mouse/Mouse.h | 70 + .../Core/Mouse/ParabolaVisualObject.cpp | 66 + .../System/Core/Mouse/ParabolaVisualObject.h | 34 + .../Core/Objects/LevelObject/CeilObject.cpp | 19 + .../Core/Objects/LevelObject/CeilObject.h | 26 + .../LevelObject/CoreInteractionObject.cpp | 85 + .../LevelObject/CoreInteractionObject.h | 49 + .../Core/Objects/LevelObject/CoreObject.cpp | 34 + .../Core/Objects/LevelObject/CoreObject.h | 32 + .../Core/Objects/LevelObject/ExitPoint.cpp | 49 + .../Core/Objects/LevelObject/ExitPoint.h | 35 + .../Core/Objects/LevelObject/ItemObject.cpp | 400 ++++ .../Core/Objects/LevelObject/ItemObject.h | 102 + .../Objects/LevelObject/LevelCastObject.cpp | 91 + .../Objects/LevelObject/LevelCastObject.h | 38 + .../LevelObject/LevelInteractionObject.cpp | 141 ++ .../LevelObject/LevelInteractionObject.h | 57 + .../Objects/LevelObject/LevelTrapObject.cpp | 8 + .../Objects/LevelObject/LevelTrapObject.h | 20 + .../System/Core/SaveGame/UserSaveGame.cpp | 91 + .../System/Core/SaveGame/UserSaveGame.h | 50 + .../GameSettings/CoreGameUserSettings.cpp | 210 ++ .../GameSettings/CoreGameUserSettings.h | 237 +++ .../CoreGameGeneralSettings.cpp | 22 + .../GeneralSettings/CoreGameGeneralSettings.h | 71 + .../CoreLoadingScreenSettings.cpp | 13 + .../CoreLoadingScreenSettings.h | 43 + .../ProjectT/System/Core/Widget/CommonHUD.cpp | 20 + .../ProjectT/System/Core/Widget/CommonHUD.h | 21 + .../System/Lobby/GameModes/LobbyGameMode.cpp | 182 ++ .../System/Lobby/GameModes/LobbyGameMode.h | 57 + .../System/Lobby/GameModes/LobbyGameState.cpp | 19 + .../System/Lobby/GameModes/LobbyGameState.h | 28 + .../System/Lobby/GameModes/LobbyPawn.cpp | 30 + .../System/Lobby/GameModes/LobbyPawn.h | 33 + .../Lobby/GameModes/LobbyPlayerController.cpp | 15 + .../Lobby/GameModes/LobbyPlayerController.h | 23 + .../Lobby/Interfaces/LobbyObjectProvider.cpp | 6 + .../Lobby/Interfaces/LobbyObjectProvider.h | 30 + .../Lobby/Managers/LobbyWidgetManager.cpp | 52 + .../Lobby/Managers/LobbyWidgetManager.h | 115 + .../Lobby/Objects/LobbyPreviewCharacter.cpp | 126 ++ .../Lobby/Objects/LobbyPreviewCharacter.h | 35 + .../BTDecorator_CheckAtArriveLocation.cpp | 50 + .../BTDecorator_CheckAtArriveLocation.h | 33 + .../BTDecorator_CheckAtArriveLocationLoop.cpp | 51 + .../BTDecorator_CheckAtArriveLocationLoop.h | 29 + .../Decorators/BTDecorator_CheckEffect.cpp | 25 + .../Decorators/BTDecorator_CheckEffect.h | 26 + .../Decorators/BTDecorator_CheckHp.cpp | 26 + .../Decorators/BTDecorator_CheckHp.h | 22 + .../Decorators/BTDecorator_InAtkDistance.cpp | 31 + .../Decorators/BTDecorator_InAtkDistance.h | 22 + .../Decorators/BTDecorator_OnNavMesh.cpp | 53 + .../Decorators/BTDecorator_OnNavMesh.h | 22 + .../Services/BTService_CheckAtkDistance.cpp | 38 + .../Services/BTService_CheckAtkDistance.h | 20 + .../Services/BTService_UpdateTargetInfo.cpp | 32 + .../Services/BTService_UpdateTargetInfo.h | 21 + .../AI/BehaviorTree/Tasks/BTTask_Alert.cpp | 31 + .../NPC/AI/BehaviorTree/Tasks/BTTask_Alert.h | 20 + .../AI/BehaviorTree/Tasks/BTTask_Attack.cpp | 30 + .../NPC/AI/BehaviorTree/Tasks/BTTask_Attack.h | 20 + .../Tasks/BTTask_ChangeAgentAnim.cpp | 40 + .../Tasks/BTTask_ChangeAgentAnim.h | 30 + .../Tasks/BTTask_ChangeBlackboardKey.cpp | 70 + .../Tasks/BTTask_ChangeBlackboardKey.h | 51 + .../BehaviorTree/Tasks/BTTask_ChangeSpeed.cpp | 25 + .../BehaviorTree/Tasks/BTTask_ChangeSpeed.h | 25 + .../Tasks/BTTask_MoveToLocation.cpp | 68 + .../Tasks/BTTask_MoveToLocation.h | 28 + .../Tasks/BTTask_MoveToNearestNavPoint.cpp | 83 + .../Tasks/BTTask_MoveToNearestNavPoint.h | 32 + .../AI/BehaviorTree/Tasks/BTTask_Patrol.cpp | 53 + .../NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.h | 22 + .../BehaviorTree/Tasks/BTTask_RotateHead.cpp | 82 + .../AI/BehaviorTree/Tasks/BTTask_RotateHead.h | 33 + .../Tasks/BTTask_RotateToDefault.cpp | 52 + .../Tasks/BTTask_RotateToDefault.h | 29 + .../Tasks/BTTask_RotateToTargetDirection.cpp | 100 + .../Tasks/BTTask_RotateToTargetDirection.h | 37 + .../Tasks/BTTask_SelectNextPatrolType.cpp | 24 + .../Tasks/BTTask_SelectNextPatrolType.h | 19 + .../Tasks/BTTask_SelectRandomPatrolDir.cpp | 31 + .../Tasks/BTTask_SelectRandomPatrolDir.h | 22 + .../Tasks/BTTask_UpdateDoubtGauge.cpp | 80 + .../Tasks/BTTask_UpdateDoubtGauge.h | 35 + .../NPC/Animations/SPNpcAgentAnimInstance.cpp | 141 ++ .../NPC/Animations/SPNpcAgentAnimInstance.h | 63 + .../SinglePlay/Characters/NPC/SPNpcAgent.cpp | 1290 +++++++++++ .../SinglePlay/Characters/NPC/SPNpcAgent.h | 169 ++ .../SinglePlay/Characters/NPC/SPNpcFixed.cpp | 303 +++ .../SinglePlay/Characters/NPC/SPNpcFixed.h | 78 + .../SinglePlay/Characters/NPC/SPNpcPatrol.cpp | 233 ++ .../SinglePlay/Characters/NPC/SPNpcPatrol.h | 46 + .../Characters/NPC/SPNpcStationary.cpp | 72 + .../Characters/NPC/SPNpcStationary.h | 25 + .../Characters/Player/SPHolister.cpp | 42 + .../SinglePlay/Characters/Player/SPHolister.h | 24 + .../SinglePlay/Characters/Player/SPIcien.cpp | 167 ++ .../SinglePlay/Characters/Player/SPIcien.h | 28 + .../SinglePlay/Characters/Player/SPNox.cpp | 184 ++ .../SinglePlay/Characters/Player/SPNox.h | 24 + .../Characters/Player/SPPlayerCharacter.cpp | 24 + .../Characters/Player/SPPlayerCharacter.h | 25 + .../Characters/Player/SPPyroMania.cpp | 102 + .../Characters/Player/SPPyroMania.h | 24 + .../SinglePlay/Characters/Player/SPSneako.cpp | 108 + .../SinglePlay/Characters/Player/SPSneako.h | 37 + .../Components/SPNpcStatusComponent.cpp | 202 ++ .../Components/SPNpcStatusComponent.h | 129 ++ .../SinglePlay/GameModes/SPGameModeBase.cpp | 409 ++++ .../SinglePlay/GameModes/SPGameModeBase.h | 69 + .../SinglePlay/GameModes/SPGameStateBase.cpp | 63 + .../SinglePlay/GameModes/SPGameStateBase.h | 30 + .../GameModes/SPPlayerController.cpp | 4 + .../SinglePlay/GameModes/SPPlayerController.h | 16 + .../Interfaces/SPObjectProvider.cpp | 7 + .../SinglePlay/Interfaces/SPObjectProvider.h | 29 + .../Managers/SPEnemyVisionManager.cpp | 127 ++ .../Managers/SPEnemyVisionManager.h | 41 + .../SinglePlay/Managers/SPWidgetManager.cpp | 132 ++ .../SinglePlay/Managers/SPWidgetManager.h | 142 ++ .../System/SinglePlay/Objects/NPCSpawner.cpp | 78 + .../System/SinglePlay/Objects/NPCSpawner.h | 32 + .../SinglePlay/Objects/SPLevelObject.cpp | 26 + .../System/SinglePlay/Objects/SPLevelObject.h | 25 + .../System/SinglePlay/Widget/SPCommonHUD.cpp | 103 + .../System/SinglePlay/Widget/SPCommonHUD.h | 67 + Source/ProjectTEditor.Target.cs | 15 + 362 files changed, 30208 insertions(+) create mode 100644 README.md create mode 100644 Source/EditorUtilityModule/Commands/CustomExtensionCommands.cpp create mode 100644 Source/EditorUtilityModule/Commands/CustomExtensionCommands.h create mode 100644 Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.cpp create mode 100644 Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.h create mode 100644 Source/EditorUtilityModule/EditorUtilityModule.build.cs create mode 100644 Source/EditorUtilityModule/EditorUtilityModule.cpp create mode 100644 Source/EditorUtilityModule/EditorUtilityModule.h create mode 100644 Source/EditorUtilityModule/SystemMessage/MessageAlert.cpp create mode 100644 Source/EditorUtilityModule/SystemMessage/MessageAlert.h create mode 100644 Source/ProjectT.Target.cs create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumContentType.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumDataTableKey.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumEffectTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumEnemyNpc.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumItemTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumLevelObjectTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumNpcTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumSkillTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumStage.h create mode 100644 Source/ProjectT/Data/Gen/GenerateEnumUnlockTypes.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructAnimationSet.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructCharacterUnlock.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructEffect.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructEnemyNpc.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructHapticList.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructItem.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructItemSet.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructLevelObject.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructLocalization.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructMeshList.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructObjective.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructPlayerCharacter.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructSkill.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructSocketList.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructSoundList.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructStage.h create mode 100644 Source/ProjectT/Data/Gen/GenerateStructVfxList.h create mode 100644 Source/ProjectT/Data/Npc/NpcDataModel.cpp create mode 100644 Source/ProjectT/Data/Npc/NpcDataModel.h create mode 100644 Source/ProjectT/Data/Paths/BaseDataPathLibrary.cpp create mode 100644 Source/ProjectT/Data/Paths/BaseDataPathLibrary.h create mode 100644 Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.cpp create mode 100644 Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.h create mode 100644 Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.cpp create mode 100644 Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.h create mode 100644 Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.cpp create mode 100644 Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.h create mode 100644 Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.cpp create mode 100644 Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.h create mode 100644 Source/ProjectT/Data/Player/PlayerDataModel.cpp create mode 100644 Source/ProjectT/Data/Player/PlayerDataModel.h create mode 100644 Source/ProjectT/Data/User/UserDataModel.cpp create mode 100644 Source/ProjectT/Data/User/UserDataModel.h create mode 100644 Source/ProjectT/ProjectT.Build.cs create mode 100644 Source/ProjectT/ProjectT.cpp create mode 100644 Source/ProjectT/ProjectT.h create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.h create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.h create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.h create mode 100644 Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.h create mode 100644 Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.h create mode 100644 Source/ProjectT/System/Core/Characters/CombatCharacter.cpp create mode 100644 Source/ProjectT/System/Core/Characters/CombatCharacter.h create mode 100644 Source/ProjectT/System/Core/Characters/CoreCharacter.cpp create mode 100644 Source/ProjectT/System/Core/Characters/CoreCharacter.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.h create mode 100644 Source/ProjectT/System/Core/Characters/NPC/CoreNpc.cpp create mode 100644 Source/ProjectT/System/Core/Characters/NPC/CoreNpc.h create mode 100644 Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h create mode 100644 Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/CoreSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/CoreSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HealingPotion.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HealingPotion.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/IcienAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/IcienAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/IcienSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/IcienSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NoxAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NoxAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NoxSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NoxSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/PyroAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/PyroAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/PyroSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/PyroSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SmokeShell.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SmokeShell.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.h create mode 100644 Source/ProjectT/System/Core/Characters/Skill/TumaiToy.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Skill/TumaiToy.h create mode 100644 Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.h create mode 100644 Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.h create mode 100644 Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.cpp create mode 100644 Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.h create mode 100644 Source/ProjectT/System/Core/Common/AssetUtilsLibrary.cpp create mode 100644 Source/ProjectT/System/Core/Common/AssetUtilsLibrary.h create mode 100644 Source/ProjectT/System/Core/Common/EditorUtilsLibrary.cpp create mode 100644 Source/ProjectT/System/Core/Common/EditorUtilsLibrary.h create mode 100644 Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.cpp create mode 100644 Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.h create mode 100644 Source/ProjectT/System/Core/Components/CoreCameraComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/CoreCameraComponent.h create mode 100644 Source/ProjectT/System/Core/Components/ObstacleFilterComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/ObstacleFilterComponent.h create mode 100644 Source/ProjectT/System/Core/Components/PathFollowComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/PathFollowComponent.h create mode 100644 Source/ProjectT/System/Core/Components/PlayerInventoryComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/PlayerInventoryComponent.h create mode 100644 Source/ProjectT/System/Core/Components/PlayerStatusComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/PlayerStatusComponent.h create mode 100644 Source/ProjectT/System/Core/Components/VisionConeComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/VisionConeComponent.h create mode 100644 Source/ProjectT/System/Core/Components/WidgetManagerComponent.cpp create mode 100644 Source/ProjectT/System/Core/Components/WidgetManagerComponent.h create mode 100644 Source/ProjectT/System/Core/Core.zip create mode 100644 Source/ProjectT/System/Core/CoreGameInstance.cpp create mode 100644 Source/ProjectT/System/Core/CoreGameInstance.h create mode 100644 Source/ProjectT/System/Core/ELoadingPhase.h create mode 100644 Source/ProjectT/System/Core/GameModes/CoreGameMode.cpp create mode 100644 Source/ProjectT/System/Core/GameModes/CoreGameMode.h create mode 100644 Source/ProjectT/System/Core/GameModes/CoreGameState.cpp create mode 100644 Source/ProjectT/System/Core/GameModes/CoreGameState.h create mode 100644 Source/ProjectT/System/Core/GameModes/CorePlayerController.cpp create mode 100644 Source/ProjectT/System/Core/GameModes/CorePlayerController.h create mode 100644 Source/ProjectT/System/Core/GameModes/CorePlayerState.cpp create mode 100644 Source/ProjectT/System/Core/GameModes/CorePlayerState.h create mode 100644 Source/ProjectT/System/Core/GameModes/WorldGameMode.cpp create mode 100644 Source/ProjectT/System/Core/GameModes/WorldGameMode.h create mode 100644 Source/ProjectT/System/Core/Input/KeyTrigger.cpp create mode 100644 Source/ProjectT/System/Core/Input/KeyTrigger.h create mode 100644 Source/ProjectT/System/Core/Interfaces/AISettings.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/AISettings.h create mode 100644 Source/ProjectT/System/Core/Interfaces/ContentType.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/ContentType.h create mode 100644 Source/ProjectT/System/Core/Interfaces/CoreCameraControl.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/CoreCameraControl.h create mode 100644 Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.h create mode 100644 Source/ProjectT/System/Core/Interfaces/Damageable.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/Damageable.h create mode 100644 Source/ProjectT/System/Core/Interfaces/DebugHitCollision.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/DebugHitCollision.h create mode 100644 Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.h create mode 100644 Source/ProjectT/System/Core/Interfaces/ItemObjectControl.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/ItemObjectControl.h create mode 100644 Source/ProjectT/System/Core/Interfaces/LoadableObject.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/LoadableObject.h create mode 100644 Source/ProjectT/System/Core/Interfaces/MouseInteraction.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/MouseInteraction.h create mode 100644 Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.h create mode 100644 Source/ProjectT/System/Core/Interfaces/PoolableActor.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/PoolableActor.h create mode 100644 Source/ProjectT/System/Core/Interfaces/ProcessStateControl.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/ProcessStateControl.h create mode 100644 Source/ProjectT/System/Core/Interfaces/Visualizable.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/Visualizable.h create mode 100644 Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.h create mode 100644 Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.cpp create mode 100644 Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.h create mode 100644 Source/ProjectT/System/Core/Managers/CoreCheatManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/CoreCheatManager.h create mode 100644 Source/ProjectT/System/Core/Managers/CoreWidgetManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/CoreWidgetManager.h create mode 100644 Source/ProjectT/System/Core/Managers/DataDam.cpp create mode 100644 Source/ProjectT/System/Core/Managers/DataDam.h create mode 100644 Source/ProjectT/System/Core/Managers/LoadingManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/LoadingManager.h create mode 100644 Source/ProjectT/System/Core/Managers/NotificationCenter.cpp create mode 100644 Source/ProjectT/System/Core/Managers/NotificationCenter.h create mode 100644 Source/ProjectT/System/Core/Managers/OptionManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/OptionManager.h create mode 100644 Source/ProjectT/System/Core/Managers/PooledActorManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/PooledActorManager.h create mode 100644 Source/ProjectT/System/Core/Managers/QuestManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/QuestManager.h create mode 100644 Source/ProjectT/System/Core/Managers/ResourceManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/ResourceManager.h create mode 100644 Source/ProjectT/System/Core/Managers/SequenceManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/SequenceManager.h create mode 100644 Source/ProjectT/System/Core/Managers/SoundManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/SoundManager.h create mode 100644 Source/ProjectT/System/Core/Managers/StageManager.cpp create mode 100644 Source/ProjectT/System/Core/Managers/StageManager.h create mode 100644 Source/ProjectT/System/Core/Mouse/LinearVisualObject.cpp create mode 100644 Source/ProjectT/System/Core/Mouse/LinearVisualObject.h create mode 100644 Source/ProjectT/System/Core/Mouse/Mouse.cpp create mode 100644 Source/ProjectT/System/Core/Mouse/Mouse.h create mode 100644 Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.cpp create mode 100644 Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.h create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.cpp create mode 100644 Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.h create mode 100644 Source/ProjectT/System/Core/SaveGame/UserSaveGame.cpp create mode 100644 Source/ProjectT/System/Core/SaveGame/UserSaveGame.h create mode 100644 Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.cpp create mode 100644 Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h create mode 100644 Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.cpp create mode 100644 Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h create mode 100644 Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.cpp create mode 100644 Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.h create mode 100644 Source/ProjectT/System/Core/Widget/CommonHUD.cpp create mode 100644 Source/ProjectT/System/Core/Widget/CommonHUD.h create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.cpp create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.h create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyGameState.cpp create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyGameState.h create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyPawn.cpp create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyPawn.h create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.cpp create mode 100644 Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.h create mode 100644 Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.cpp create mode 100644 Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.h create mode 100644 Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.cpp create mode 100644 Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.h create mode 100644 Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.cpp create mode 100644 Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.h create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.h create mode 100644 Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.cpp create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.cpp create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.h create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.cpp create mode 100644 Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.h create mode 100644 Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h create mode 100644 Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h create mode 100644 Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.h create mode 100644 Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.h create mode 100644 Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.h create mode 100644 Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.cpp create mode 100644 Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.h create mode 100644 Source/ProjectTEditor.Target.cs diff --git a/README.md b/README.md new file mode 100644 index 0000000..fbbfd63 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# ProjectM \ No newline at end of file diff --git a/Source/EditorUtilityModule/Commands/CustomExtensionCommands.cpp b/Source/EditorUtilityModule/Commands/CustomExtensionCommands.cpp new file mode 100644 index 0000000..a34538e --- /dev/null +++ b/Source/EditorUtilityModule/Commands/CustomExtensionCommands.cpp @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#if WITH_EDITOR + +#include "CustomExtensionCommands.h" + +//Uncomment if you are necessary + +//#include "Misc/MessageDialog.h" +//#include "LevelEditor.h" + +//#include "Engine/Selection.h" +//#include "Editor/EditorEngine.h" +#include "Editor/Blutility/Classes/EditorUtilityWidget.h" +#include "EditorUtilitySubsystem.h" +#include "EditorUtilityWidgetBlueprint.h" +//#include "Misc/FileHelper.h" +//#include "HAL/FileManagerGeneric.h" +//#include "NotificationHelper.h" + + +#define LOCTEXT_NAMESPACE "IGCCommand" + +void CustomExtensionCommands::RegisterCommands() +{ + UI_COMMAND(Command1, "LevelTool", "Button1", EUserInterfaceActionType::Button, FInputGesture()); + UI_COMMAND(Command2, "IGCCommand2", "Button2", EUserInterfaceActionType::Button, FInputGesture()); + UI_COMMAND(Command3, "IGCCommand3", "Button3", EUserInterfaceActionType::Button, FInputGesture()); +} + +void FIGCExtensionActions::Action1() +{ + UEditorUtilityWidgetBlueprint* LevelToolWBPU = LoadObject(nullptr, L"/Game/System/Core/Blutilities/WBPU_LevelToolByTable"); + UWorld* World = GEditor->GetEditorWorldContext().World(); + if(World) + { + if(UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem()) + { + if(LevelToolWBPU != nullptr) + { + EditorUtilitySubsystem->SpawnAndRegisterTab(LevelToolWBPU); + } + } + } +} + +void FIGCExtensionActions::Action2() +{ + /*Active Action when Press Button2*/ +} + +void FIGCExtensionActions::Action3() +{ + /*Active Action when Press Button3*/ +} + +void FIGCExtensionActions::Action4(ECheckBoxState state) +{ + /*Active Action when Checking to CheckBox1*/ +} + +void FIGCExtensionActions::Action5(ECheckBoxState state) +{ + /*Active Action when Checking to CheckBox2*/ +} + +void FIGCExtensionActions::Action6(TSharedPtr NewSelection) +{ + /*Active Action when Selecting to ComboBox's value */ +} + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/Commands/CustomExtensionCommands.h b/Source/EditorUtilityModule/Commands/CustomExtensionCommands.h new file mode 100644 index 0000000..d20e207 --- /dev/null +++ b/Source/EditorUtilityModule/Commands/CustomExtensionCommands.h @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#if WITH_EDITOR + +#include "CoreMinimal.h" +#include "Framework/Commands/Commands.h" +#include "../EditorSlateStyle/CustomSlateStyle.h" + + +/** + * + */ +class EDITORUTILITYMODULE_API CustomExtensionCommands : public TCommands +{ +public: + + + CustomExtensionCommands() + :TCommands(TEXT("CustomExtensionCommands"), NSLOCTEXT("CustomExtensionCommands", "CustomExtensionCommands", "CustomExtensionCommands"), NAME_None, CustomSlateStyle::GetStyleSetName()) + { + + } + + virtual void RegisterCommands()override; + +public: + + //Slate button commands + + TSharedPtr< FUICommandInfo > Command1; + TSharedPtr< FUICommandInfo > Command2; + TSharedPtr< FUICommandInfo > Command3; + +}; + + +/*Actions by Slate UI*/ +class FIGCExtensionActions +{ +public: + static void Action1(); + static void Action2(); + static void Action3(); + static void Action4(ECheckBoxState state); + static void Action5(ECheckBoxState state); + static void Action6(TSharedPtr NewSelection); +}; + + + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.cpp b/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.cpp new file mode 100644 index 0000000..d50a98e --- /dev/null +++ b/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.cpp @@ -0,0 +1,58 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#if WITH_EDITOR + +#include "CustomSlateStyle.h" +#include "Slate/SlateGameResources.h" +#include "Styling/SlateStyleRegistry.h" + +TSharedPtr< FSlateStyleSet > CustomSlateStyle::StyleInstance = nullptr; + +#define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ ) + +const FVector2D Icon16x16(16.0f, 16.0f); +const FVector2D Icon20x20(20.0f, 20.0f); +const FVector2D Icon40x40(40.0f, 40.0f); +const FVector2D DebugToolBtn(64.f, 64.f); + + +void CustomSlateStyle::Initialize() +{ + if(!StyleInstance.IsValid()) + { + // StyleInstance = Create(); + // FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); + } +} + +void CustomSlateStyle::Shutdown() +{ +// FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance); +// ensure(StyleInstance.IsUnique()); +// StyleInstance.Reset(); +} + +const ISlateStyle& CustomSlateStyle::Get() +{ + return *StyleInstance; +} + +FName CustomSlateStyle::GetStyleSetName() +{ + static FName StyleSetName(TEXT("IGCExtensionStyle")); + return StyleSetName; +} + +//TSharedRef CustomSlateStyle::Create() +//{ +// TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("IGCExtensionStyle")); +// +// /*Style->SetContentRoot(FPaths::EngineContentDir() / TEXT("Editor/Slate")); +// Style->Set("IGCToolbarIcon.Command2", new IMAGE_BRUSH("Old/Kismet2/compile_512px", DebugToolBtn)); +// Style->Set("IGCToolbarIcon.Command3", new IMAGE_BRUSH("Old/TrashCan", DebugToolBtn));*/ +// +// return Style; +//} + +#undef IMAGE_BRUSH + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.h b/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.h new file mode 100644 index 0000000..c2f50c6 --- /dev/null +++ b/Source/EditorUtilityModule/EditorSlateStyle/CustomSlateStyle.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#if WITH_EDITOR + +#include "CoreMinimal.h" + +/** + * + */ +class EDITORUTILITYMODULE_API CustomSlateStyle +{ +public: + + + static void Initialize(); + static void Shutdown(); + + static const ISlateStyle& Get(); + static FName GetStyleSetName(); + +private: +// static TSharedRef< class FSlateStyleSet > Create(); + +private: + static TSharedPtr< class FSlateStyleSet > StyleInstance; +}; + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/EditorUtilityModule.build.cs b/Source/EditorUtilityModule/EditorUtilityModule.build.cs new file mode 100644 index 0000000..f9cdbe0 --- /dev/null +++ b/Source/EditorUtilityModule/EditorUtilityModule.build.cs @@ -0,0 +1,21 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class EditorUtilityModule : ModuleRules +{ + public EditorUtilityModule(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Slate", "SlateCore" }); + + + if (Target.Type == TargetRules.TargetType.Editor) + { + PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd", "LevelEditor" }); + PrivateDependencyModuleNames.AddRange(new string[] { "UMG", "Blutility", "UMGEditor" }); + } + + } +} diff --git a/Source/EditorUtilityModule/EditorUtilityModule.cpp b/Source/EditorUtilityModule/EditorUtilityModule.cpp new file mode 100644 index 0000000..02b4a13 --- /dev/null +++ b/Source/EditorUtilityModule/EditorUtilityModule.cpp @@ -0,0 +1,132 @@ + +#if WITH_EDITOR + +#include "EditorUtilityModule.h" +#include "Commands/CustomExtensionCommands.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "LevelEditor.h" + +IMPLEMENT_MODULE(FEditorUtilityModule, EditorUtilityModule); + + +#define LOCTEXT_NAMESPACE "IGCMenu" + +void FEditorUtilityModule::StartupModule() +{ + CustomSlateStyle::Initialize(); + + CustomExtensionCommands::Register(); + + IGCCommandList = MakeShareable(new FUICommandList()); + IGCCommandList->MapAction(CustomExtensionCommands::Get().Command1, FExecuteAction::CreateStatic(&FIGCExtensionActions::Action1), FCanExecuteAction()); + IGCCommandList->MapAction(CustomExtensionCommands::Get().Command2, FExecuteAction::CreateStatic(&FIGCExtensionActions::Action2), FCanExecuteAction()); + IGCCommandList->MapAction(CustomExtensionCommands::Get().Command3, FExecuteAction::CreateStatic(&FIGCExtensionActions::Action3), FCanExecuteAction()); + + FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked("LevelEditor"); + + static bool IsCheckedBox1; + static bool IsCheckedBox2; + static TArray> ComboboxOptions; + static TSharedPtr SelectedOption; + + ComboboxOptions.Add(MakeShareable(new FString("Value1"))); + ComboboxOptions.Add(MakeShareable(new FString("Value2"))); + ComboboxOptions.Add(MakeShareable(new FString("Value3"))); + + struct IGCToolbar + { + static void CreateIGCToolbar(FToolBarBuilder& ToolbarBuilder) + { + ToolbarBuilder.BeginSection("IGCToolbar"); + { + ToolbarBuilder.AddToolBarWidget( + SNew(SButton) + .OnClicked_Lambda([]()->FReply { FIGCExtensionActions::Action1(); return FReply::Handled(); }) + [ + SNew(STextBlock) + .Text(FText::FromString("LevelTool")) + ] + ); + + ToolbarBuilder.AddToolBarButton( + CustomExtensionCommands::Get().Command2, + NAME_None, + TAttribute(), + TAttribute(), + FSlateIcon(), + NAME_None + ); + ToolbarBuilder.AddToolBarButton( + CustomExtensionCommands::Get().Command3, + NAME_None, + TAttribute(), + TAttribute(), + FSlateIcon(), + NAME_None + ); + + ToolbarBuilder.AddToolBarWidget( + SNew(SCheckBox) + .OnCheckStateChanged_Lambda(&FIGCExtensionActions::Action4) + .IsChecked(IsCheckedBox1), + LOCTEXT("SCCheckBox", "CheckBox1") + ); + + + ToolbarBuilder.AddToolBarWidget( + SNew(SCheckBox) + .OnCheckStateChanged_Lambda(&FIGCExtensionActions::Action5) + .IsChecked(IsCheckedBox2), + LOCTEXT("SCCheckBox", "CheckBox2") + ); + + ToolbarBuilder.AddToolBarWidget( + SNew(SBox) + .Padding(FMargin(20.f, 0.f, 0.f, 0.f)) + [ + SNew(SComboBox>) + .OptionsSource(&ComboboxOptions) + .ToolTipText(LOCTEXT("PlatformComboBox", "Change Build Platform")) + .OnGenerateWidget_Lambda([](TSharedPtr Option) + { + return SNew(STextBlock).Text(FText::FromString(*Option.Get())); + }) + .OnSelectionChanged_Lambda([](TSharedPtr NewSelection, ESelectInfo::Type SelectInfo) + { + if (NewSelection.IsValid()) + { + SelectedOption = NewSelection; + FIGCExtensionActions::Action6(SelectedOption); + } + }) + .InitiallySelectedItem(SelectedOption) + .Content() + [ + SNew(STextBlock) + .Text_Lambda([]() + { + return SelectedOption.IsValid() ? FText::FromString(*SelectedOption) : LOCTEXT("NoSelection", "선택없음"); + }) + ] + ] + , LOCTEXT("SCComboBox", "ComboBox")); + } + ToolbarBuilder.EndSection(); + } + + }; + + TSharedPtr IGCToolbarExtender = MakeShareable(new FExtender()); + IGCToolbarExtender->AddToolBarExtension("Play", EExtensionHook::After, IGCCommandList, + FToolBarExtensionDelegate::CreateStatic(&IGCToolbar::CreateIGCToolbar)); + LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(IGCToolbarExtender); +} + +void FEditorUtilityModule::ShutdownModule() +{ + CustomExtensionCommands::Unregister(); + CustomSlateStyle::Shutdown(); +} + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/EditorUtilityModule.h b/Source/EditorUtilityModule/EditorUtilityModule.h new file mode 100644 index 0000000..a9eb45e --- /dev/null +++ b/Source/EditorUtilityModule/EditorUtilityModule.h @@ -0,0 +1,24 @@ +#if WITH_EDITOR + +#pragma once + + +#include "Engine.h" +#include "Modules/ModuleInterface.h" +#include "Modules/ModuleManager.h" + +class FEditorUtilityModule : public IModuleInterface +{ +public: + + virtual void StartupModule()override; + virtual void ShutdownModule()override; + +private: + + TSharedPtr IGCCommandList; + + +}; + +#endif \ No newline at end of file diff --git a/Source/EditorUtilityModule/SystemMessage/MessageAlert.cpp b/Source/EditorUtilityModule/SystemMessage/MessageAlert.cpp new file mode 100644 index 0000000..34b34b7 --- /dev/null +++ b/Source/EditorUtilityModule/SystemMessage/MessageAlert.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MessageAlert.h" +#include "Widgets/Notifications/SNotificationList.h" +#include "Framework/Notifications/NotificationManager.h" + +MessageAlert::MessageAlert() +{ +} + +MessageAlert::~MessageAlert() +{ +} + +void MessageAlert::ShowNotifyInfo(const FString& Msg) +{ + FNotificationInfo NotifyInfo(FText::FromString(Msg)); + + NotifyInfo.bUseLargeFont = true; + NotifyInfo.FadeOutDuration = 5.f; + + FSlateNotificationManager::Get().AddNotification(NotifyInfo); +} diff --git a/Source/EditorUtilityModule/SystemMessage/MessageAlert.h b/Source/EditorUtilityModule/SystemMessage/MessageAlert.h new file mode 100644 index 0000000..ba6e326 --- /dev/null +++ b/Source/EditorUtilityModule/SystemMessage/MessageAlert.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +/** + * 에디터 우측 하단 시스템 알림을 위한 클래스 + */ +class EDITORUTILITYMODULE_API MessageAlert +{ +public: + MessageAlert(); + ~MessageAlert(); + +public: + static void ShowNotifyInfo(const FString& Msg); +}; diff --git a/Source/ProjectT.Target.cs b/Source/ProjectT.Target.cs new file mode 100644 index 0000000..547428d --- /dev/null +++ b/Source/ProjectT.Target.cs @@ -0,0 +1,15 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class ProjectTTarget : TargetRules +{ + public ProjectTTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V5; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_5; + ExtraModuleNames.AddRange(new string[] { "ProjectT" , "EditorUtilityModule"}); + } +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumContentType.h b/Source/ProjectT/Data/Gen/GenerateEnumContentType.h new file mode 100644 index 0000000..25ed17c --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumContentType.h @@ -0,0 +1,55 @@ +//Generated ContentType Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EContentType : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Stage = 10 UMETA(DisplayName= "Stage"), + Objective = 11 UMETA(DisplayName= "Objective"), + CharacterUnlock = 14 UMETA(DisplayName= "CharacterUnlock"), + PlayerCharacter = 20 UMETA(DisplayName= "PlayerCharacter"), + EnemyNpc = 21 UMETA(DisplayName= "EnemyNpc"), + ObjectiveNpc = 22 UMETA(DisplayName= "ObjectiveNpc"), + Effect = 30 UMETA(DisplayName= "Effect"), + Skill = 31 UMETA(DisplayName= "Skill"), + Item = 40 UMETA(DisplayName= "Item"), + ItemSet = 41 UMETA(DisplayName= "ItemSet"), + LevelObject = 42 UMETA(DisplayName= "LevelObject"), + Localization = 60 UMETA(DisplayName= "Localization"), + Mesh = 80 UMETA(DisplayName= "Mesh"), + MeshSet = 81 UMETA(DisplayName= "MeshSet"), + Animation = 82 UMETA(DisplayName= "Animation"), + Sound = 91 UMETA(DisplayName= "Sound"), + Haptic = 93 UMETA(DisplayName= "Haptic"), + Vfx = 94 UMETA(DisplayName= "Vfx"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EContentType,EContentType::Stage,EContentType::Vfx); + +static FString EnumToString(EContentType InEnum) +{ + switch (InEnum) + { + case EContentType::Stage: return TEXT("Stage"); + case EContentType::Objective: return TEXT("Objective"); + case EContentType::CharacterUnlock: return TEXT("CharacterUnlock"); + case EContentType::PlayerCharacter: return TEXT("PlayerCharacter"); + case EContentType::EnemyNpc: return TEXT("EnemyNpc"); + case EContentType::ObjectiveNpc: return TEXT("ObjectiveNpc"); + case EContentType::Effect: return TEXT("Effect"); + case EContentType::Skill: return TEXT("Skill"); + case EContentType::Item: return TEXT("Item"); + case EContentType::ItemSet: return TEXT("ItemSet"); + case EContentType::LevelObject: return TEXT("LevelObject"); + case EContentType::Localization: return TEXT("Localization"); + case EContentType::Mesh: return TEXT("Mesh"); + case EContentType::MeshSet: return TEXT("MeshSet"); + case EContentType::Animation: return TEXT("Animation"); + case EContentType::Sound: return TEXT("Sound"); + case EContentType::Haptic: return TEXT("Haptic"); + case EContentType::Vfx: return TEXT("Vfx"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumDataTableKey.h b/Source/ProjectT/Data/Gen/GenerateEnumDataTableKey.h new file mode 100644 index 0000000..4251166 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumDataTableKey.h @@ -0,0 +1,54 @@ +//Generated DataTableKey Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EDataTableKey : uint8 +{ + AnimationSet UMETA(DisplayName = "AnimationSet"), + CharacterMeshSet UMETA(DisplayName = "CharacterMeshSet"), + CharacterUnlock UMETA(DisplayName = "CharacterUnlock"), + Effect UMETA(DisplayName = "Effect"), + EnemyNpc UMETA(DisplayName = "EnemyNpc"), + HapticList UMETA(DisplayName = "HapticList"), + Item UMETA(DisplayName = "Item"), + ItemSet UMETA(DisplayName = "ItemSet"), + LevelObject UMETA(DisplayName = "LevelObject"), + Localization UMETA(DisplayName = "Localization"), + MeshList UMETA(DisplayName = "MeshList"), + Objective UMETA(DisplayName = "Objective"), + PlayerCharacter UMETA(DisplayName = "PlayerCharacter"), + Skill UMETA(DisplayName = "Skill"), + SocketList UMETA(DisplayName = "SocketList"), + SoundList UMETA(DisplayName = "SoundList"), + Stage UMETA(DisplayName = "Stage"), + VfxList UMETA(DisplayName = "VfxList"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EDataTableKey,EDataTableKey::AnimationSet,EDataTableKey::VfxList); + +static FString EnumToString(EDataTableKey InEnum) +{ + switch (InEnum) + { + case EDataTableKey::AnimationSet: return TEXT("AnimationSet"); + case EDataTableKey::CharacterMeshSet: return TEXT("CharacterMeshSet"); + case EDataTableKey::CharacterUnlock: return TEXT("CharacterUnlock"); + case EDataTableKey::Effect: return TEXT("Effect"); + case EDataTableKey::EnemyNpc: return TEXT("EnemyNpc"); + case EDataTableKey::HapticList: return TEXT("HapticList"); + case EDataTableKey::Item: return TEXT("Item"); + case EDataTableKey::ItemSet: return TEXT("ItemSet"); + case EDataTableKey::LevelObject: return TEXT("LevelObject"); + case EDataTableKey::Localization: return TEXT("Localization"); + case EDataTableKey::MeshList: return TEXT("MeshList"); + case EDataTableKey::Objective: return TEXT("Objective"); + case EDataTableKey::PlayerCharacter: return TEXT("PlayerCharacter"); + case EDataTableKey::Skill: return TEXT("Skill"); + case EDataTableKey::SocketList: return TEXT("SocketList"); + case EDataTableKey::SoundList: return TEXT("SoundList"); + case EDataTableKey::Stage: return TEXT("Stage"); + case EDataTableKey::VfxList: return TEXT("VfxList"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h new file mode 100644 index 0000000..ccd7c23 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h @@ -0,0 +1,41 @@ +//Generated EffectSubTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EEffectSubTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Hitback UMETA(DisplayName= "Hitback"), + Jumpback UMETA(DisplayName= "Jumpback"), + Stun UMETA(DisplayName= "Stun"), + Bind UMETA(DisplayName= "Bind"), + Surge UMETA(DisplayName= "Surge"), + Unrecog UMETA(DisplayName= "Unrecog"), + CogImmune UMETA(DisplayName= "CogImmune"), + HitbackImmune UMETA(DisplayName= "HitbackImmune"), + Fast UMETA(DisplayName= "Fast"), + Slow UMETA(DisplayName= "Slow"), + Heal UMETA(DisplayName= "Heal"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EEffectSubTypes,EEffectSubTypes::Hitback,EEffectSubTypes::Heal); + +static FString EnumToString(EEffectSubTypes InEnum) +{ + switch (InEnum) + { + case EEffectSubTypes::Hitback: return TEXT("Hitback"); + case EEffectSubTypes::Jumpback: return TEXT("Jumpback"); + case EEffectSubTypes::Stun: return TEXT("Stun"); + case EEffectSubTypes::Bind: return TEXT("Bind"); + case EEffectSubTypes::Surge: return TEXT("Surge"); + case EEffectSubTypes::Unrecog: return TEXT("Unrecog"); + case EEffectSubTypes::CogImmune: return TEXT("CogImmune"); + case EEffectSubTypes::HitbackImmune: return TEXT("HitbackImmune"); + case EEffectSubTypes::Fast: return TEXT("Fast"); + case EEffectSubTypes::Slow: return TEXT("Slow"); + case EEffectSubTypes::Heal: return TEXT("Heal"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumEffectTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumEffectTypes.h new file mode 100644 index 0000000..c018102 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumEffectTypes.h @@ -0,0 +1,25 @@ +//Generated EffectTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EEffectTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + CC UMETA(DisplayName= "CC"), + Utility UMETA(DisplayName= "Utility"), + Status UMETA(DisplayName= "Status"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EEffectTypes,EEffectTypes::CC,EEffectTypes::Status); + +static FString EnumToString(EEffectTypes InEnum) +{ + switch (InEnum) + { + case EEffectTypes::CC: return TEXT("CC"); + case EEffectTypes::Utility: return TEXT("Utility"); + case EEffectTypes::Status: return TEXT("Status"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumEnemyNpc.h b/Source/ProjectT/Data/Gen/GenerateEnumEnemyNpc.h new file mode 100644 index 0000000..a39b62a --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumEnemyNpc.h @@ -0,0 +1,25 @@ +//Generated EnemyNpc Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EEnemyNpc : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Stationary UMETA(DisplayName= "Stationary"), + Patrol UMETA(DisplayName= "Patrol"), + Fixed UMETA(DisplayName= "Fixed"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EEnemyNpc,EEnemyNpc::Stationary,EEnemyNpc::Fixed); + +static FString EnumToString(EEnemyNpc InEnum) +{ + switch (InEnum) + { + case EEnemyNpc::Stationary: return TEXT("Stationary"); + case EEnemyNpc::Patrol: return TEXT("Patrol"); + case EEnemyNpc::Fixed: return TEXT("Fixed"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumItemTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumItemTypes.h new file mode 100644 index 0000000..2487fb2 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumItemTypes.h @@ -0,0 +1,25 @@ +//Generated ItemTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EItemTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Gimick UMETA(DisplayName= "Gimick"), + Usable UMETA(DisplayName= "Usable"), + Collection UMETA(DisplayName= "Collection"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EItemTypes,EItemTypes::Gimick,EItemTypes::Collection); + +static FString EnumToString(EItemTypes InEnum) +{ + switch (InEnum) + { + case EItemTypes::Gimick: return TEXT("Gimick"); + case EItemTypes::Usable: return TEXT("Usable"); + case EItemTypes::Collection: return TEXT("Collection"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumLevelObjectTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumLevelObjectTypes.h new file mode 100644 index 0000000..0cb80bf --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumLevelObjectTypes.h @@ -0,0 +1,23 @@ +//Generated LevelObjectTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class ELevelObjectTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Cast UMETA(DisplayName= "Cast"), + Trap UMETA(DisplayName= "Trap"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(ELevelObjectTypes,ELevelObjectTypes::Cast,ELevelObjectTypes::Trap); + +static FString EnumToString(ELevelObjectTypes InEnum) +{ + switch (InEnum) + { + case ELevelObjectTypes::Cast: return TEXT("Cast"); + case ELevelObjectTypes::Trap: return TEXT("Trap"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumNpcTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumNpcTypes.h new file mode 100644 index 0000000..155fe2e --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumNpcTypes.h @@ -0,0 +1,25 @@ +//Generated NpcTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class ENpcTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Stationary UMETA(DisplayName= "Stationary"), + Patrol UMETA(DisplayName= "Patrol"), + Fixed UMETA(DisplayName= "Fixed"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(ENpcTypes,ENpcTypes::Stationary,ENpcTypes::Fixed); + +static FString EnumToString(ENpcTypes InEnum) +{ + switch (InEnum) + { + case ENpcTypes::Stationary: return TEXT("Stationary"); + case ENpcTypes::Patrol: return TEXT("Patrol"); + case ENpcTypes::Fixed: return TEXT("Fixed"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h new file mode 100644 index 0000000..31ae611 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h @@ -0,0 +1,27 @@ +//Generated ObjectiveSubTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EObjectiveSubTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Save UMETA(DisplayName= "Save"), + Collect UMETA(DisplayName= "Collect"), + Avoid UMETA(DisplayName= "Avoid"), + Kill UMETA(DisplayName= "Kill"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EObjectiveSubTypes,EObjectiveSubTypes::Save,EObjectiveSubTypes::Kill); + +static FString EnumToString(EObjectiveSubTypes InEnum) +{ + switch (InEnum) + { + case EObjectiveSubTypes::Save: return TEXT("Save"); + case EObjectiveSubTypes::Collect: return TEXT("Collect"); + case EObjectiveSubTypes::Avoid: return TEXT("Avoid"); + case EObjectiveSubTypes::Kill: return TEXT("Kill"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h new file mode 100644 index 0000000..9b198ff --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h @@ -0,0 +1,23 @@ +//Generated ObjectiveTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EObjectiveTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Mission UMETA(DisplayName= "Mission"), + Quest UMETA(DisplayName= "Quest"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EObjectiveTypes,EObjectiveTypes::Mission,EObjectiveTypes::Quest); + +static FString EnumToString(EObjectiveTypes InEnum) +{ + switch (InEnum) + { + case EObjectiveTypes::Mission: return TEXT("Mission"); + case EObjectiveTypes::Quest: return TEXT("Quest"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumSkillTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumSkillTypes.h new file mode 100644 index 0000000..98dc193 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumSkillTypes.h @@ -0,0 +1,27 @@ +//Generated SkillTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class ESkillTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Melee UMETA(DisplayName= "Melee"), + Direct UMETA(DisplayName= "Direct"), + Indirect UMETA(DisplayName= "Indirect"), + Buff UMETA(DisplayName= "Buff"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(ESkillTypes,ESkillTypes::Melee,ESkillTypes::Buff); + +static FString EnumToString(ESkillTypes InEnum) +{ + switch (InEnum) + { + case ESkillTypes::Melee: return TEXT("Melee"); + case ESkillTypes::Direct: return TEXT("Direct"); + case ESkillTypes::Indirect: return TEXT("Indirect"); + case ESkillTypes::Buff: return TEXT("Buff"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumStage.h b/Source/ProjectT/Data/Gen/GenerateEnumStage.h new file mode 100644 index 0000000..9f7b4b5 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumStage.h @@ -0,0 +1,37 @@ +//Generated Stage Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EStage : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + L_SP_Office_01 UMETA(DisplayName= "L_SP_Office_01"), + L_SP_Office_02 UMETA(DisplayName= "L_SP_Office_02"), + L_SP_Office_03 UMETA(DisplayName= "L_SP_Office_03"), + L_SP_Office_04 UMETA(DisplayName= "L_SP_Office_04"), + L_SP_Office_05 UMETA(DisplayName= "L_SP_Office_05"), + L_SP_Test_00 UMETA(DisplayName= "L_SP_Test_00"), + L_Entry UMETA(DisplayName= "L_Entry"), + L_Lobby UMETA(DisplayName= "L_Lobby"), + L_Intro UMETA(DisplayName= "L_Intro"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EStage,EStage::L_SP_Office_01,EStage::L_Intro); + +static FString EnumToString(EStage InEnum) +{ + switch (InEnum) + { + case EStage::L_SP_Office_01: return TEXT("L_SP_Office_01"); + case EStage::L_SP_Office_02: return TEXT("L_SP_Office_02"); + case EStage::L_SP_Office_03: return TEXT("L_SP_Office_03"); + case EStage::L_SP_Office_04: return TEXT("L_SP_Office_04"); + case EStage::L_SP_Office_05: return TEXT("L_SP_Office_05"); + case EStage::L_SP_Test_00: return TEXT("L_SP_Test_00"); + case EStage::L_Entry: return TEXT("L_Entry"); + case EStage::L_Lobby: return TEXT("L_Lobby"); + case EStage::L_Intro: return TEXT("L_Intro"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateEnumUnlockTypes.h b/Source/ProjectT/Data/Gen/GenerateEnumUnlockTypes.h new file mode 100644 index 0000000..c185388 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateEnumUnlockTypes.h @@ -0,0 +1,25 @@ +//Generated UnlockTypes Index to Enum + +#pragma once + +UENUM(BlueprintType) +enum class EUnlockTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Default UMETA(DisplayName= "Default"), + Mission UMETA(DisplayName= "Mission"), + Quest UMETA(DisplayName= "Quest"), +}; +ENUM_RANGE_BY_FIRST_AND_LAST(EUnlockTypes,EUnlockTypes::Default,EUnlockTypes::Quest); + +static FString EnumToString(EUnlockTypes InEnum) +{ + switch (InEnum) + { + case EUnlockTypes::Default: return TEXT("Default"); + case EUnlockTypes::Mission: return TEXT("Mission"); + case EUnlockTypes::Quest: return TEXT("Quest"); + default: checkf(false, TEXT("Error")); + } + return FString(); +} diff --git a/Source/ProjectT/Data/Gen/GenerateStructAnimationSet.h b/Source/ProjectT/Data/Gen/GenerateStructAnimationSet.h new file mode 100644 index 0000000..3202548 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructAnimationSet.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructAnimationSet.generated.h" + +USTRUCT(BlueprintType) +struct FAnimationSet : public FTableRowBase +{ + GENERATED_BODY() + + FAnimationSet() : + sIdleAniPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = AnimationSet) + FString sIdleAniPath; + + bool operator==(const FAnimationSet& Other) const + { + return sIdleAniPath == Other.sIdleAniPath; + } + bool operator!=(const FAnimationSet& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sIdleAniPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h b/Source/ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h new file mode 100644 index 0000000..e0d4bec --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructCharacterMeshSet.generated.h" + +USTRUCT(BlueprintType) +struct FCharacterMeshSet : public FTableRowBase +{ + GENERATED_BODY() + + FCharacterMeshSet() : + iBodyMeshId(), + iWeaponMeshId(), + iWeaponSocketId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterMeshSet) + int32 iBodyMeshId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterMeshSet) + int32 iWeaponMeshId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterMeshSet) + int32 iWeaponSocketId; + + bool operator==(const FCharacterMeshSet& Other) const + { + return iBodyMeshId == Other.iBodyMeshId && iWeaponMeshId == Other.iWeaponMeshId && iWeaponSocketId == Other.iWeaponSocketId; + } + bool operator!=(const FCharacterMeshSet& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return iBodyMeshId == 0 && iWeaponMeshId == 0 && iWeaponSocketId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructCharacterUnlock.h b/Source/ProjectT/Data/Gen/GenerateStructCharacterUnlock.h new file mode 100644 index 0000000..7b2523e --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructCharacterUnlock.h @@ -0,0 +1,45 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructCharacterUnlock.generated.h" + +USTRUCT(BlueprintType) +struct FCharacterUnlock : public FTableRowBase +{ + GENERATED_BODY() + + FCharacterUnlock() : + sUnlockType(), + iPlayerCharId(), + iClearStage(), + iUnlockDescId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterUnlock) + FString sUnlockType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterUnlock) + int32 iPlayerCharId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterUnlock) + int32 iClearStage; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = CharacterUnlock) + int32 iUnlockDescId; + + bool operator==(const FCharacterUnlock& Other) const + { + return sUnlockType == Other.sUnlockType && iPlayerCharId == Other.iPlayerCharId && iClearStage == Other.iClearStage && iUnlockDescId == Other.iUnlockDescId; + } + bool operator!=(const FCharacterUnlock& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sUnlockType.IsEmpty() && iPlayerCharId == 0 && iClearStage == 0 && iUnlockDescId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructEffect.h b/Source/ProjectT/Data/Gen/GenerateStructEffect.h new file mode 100644 index 0000000..9edd42e --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructEffect.h @@ -0,0 +1,57 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructEffect.generated.h" + +USTRUCT(BlueprintType) +struct FEffect : public FTableRowBase +{ + GENERATED_BODY() + + FEffect() : + sEffectType(), + sEffect(), + fEffectValue(), + fEffectDuration(), + iEffectNameId(), + iEffectDescId(), + sEffectIconPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + FString sEffectType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + FString sEffect; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + float fEffectValue; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + float fEffectDuration; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + int32 iEffectNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + int32 iEffectDescId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Effect) + FString sEffectIconPath; + + bool operator==(const FEffect& Other) const + { + return sEffectType == Other.sEffectType && sEffect == Other.sEffect && fEffectValue == Other.fEffectValue && fEffectDuration == Other.fEffectDuration && iEffectNameId == Other.iEffectNameId && iEffectDescId == Other.iEffectDescId && sEffectIconPath == Other.sEffectIconPath; + } + bool operator!=(const FEffect& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sEffectType.IsEmpty() && sEffect.IsEmpty() && fEffectValue == 0 && fEffectDuration == 0 && iEffectNameId == 0 && iEffectDescId == 0 && sEffectIconPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructEnemyNpc.h b/Source/ProjectT/Data/Gen/GenerateStructEnemyNpc.h new file mode 100644 index 0000000..73e5c5b --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructEnemyNpc.h @@ -0,0 +1,101 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructEnemyNpc.generated.h" + +USTRUCT(BlueprintType) +struct FEnemyNpc : public FTableRowBase +{ + GENERATED_BODY() + + FEnemyNpc() : + sNpcType(), + fNpcHp(), + fNpcMove(), + fNpcRun(), + fSightLength(), + fSightAngle(), + fAttackLength(), + fChaseLength(), + fRotationAngle(), + fRotationSpeed(), + fDoubtTime(), + fNpcNoise(), + fMoveProb(), + fSearchProb(), + fScoutProb(), + iNpcAttackId(), + iNpcNameId(), + iNpcMeshSetId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + FString sNpcType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fNpcHp; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fNpcMove; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fNpcRun; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fSightLength; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fSightAngle; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fAttackLength; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fChaseLength; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fRotationAngle; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fRotationSpeed; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fDoubtTime; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fNpcNoise; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fMoveProb; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fSearchProb; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + float fScoutProb; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + int32 iNpcAttackId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + int32 iNpcNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = EnemyNpc) + int32 iNpcMeshSetId; + + bool operator==(const FEnemyNpc& Other) const + { + return sNpcType == Other.sNpcType && fNpcHp == Other.fNpcHp && fNpcMove == Other.fNpcMove && fNpcRun == Other.fNpcRun && fSightLength == Other.fSightLength && fSightAngle == Other.fSightAngle && fAttackLength == Other.fAttackLength && fChaseLength == Other.fChaseLength && fRotationAngle == Other.fRotationAngle && fRotationSpeed == Other.fRotationSpeed && fDoubtTime == Other.fDoubtTime && fNpcNoise == Other.fNpcNoise && fMoveProb == Other.fMoveProb && fSearchProb == Other.fSearchProb && fScoutProb == Other.fScoutProb && iNpcAttackId == Other.iNpcAttackId && iNpcNameId == Other.iNpcNameId && iNpcMeshSetId == Other.iNpcMeshSetId; + } + bool operator!=(const FEnemyNpc& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sNpcType.IsEmpty() && fNpcHp == 0 && fNpcMove == 0 && fNpcRun == 0 && fSightLength == 0 && fSightAngle == 0 && fAttackLength == 0 && fChaseLength == 0 && fRotationAngle == 0 && fRotationSpeed == 0 && fDoubtTime == 0 && fNpcNoise == 0 && fMoveProb == 0 && fSearchProb == 0 && fScoutProb == 0 && iNpcAttackId == 0 && iNpcNameId == 0 && iNpcMeshSetId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructHapticList.h b/Source/ProjectT/Data/Gen/GenerateStructHapticList.h new file mode 100644 index 0000000..3bee55c --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructHapticList.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructHapticList.generated.h" + +USTRUCT(BlueprintType) +struct FHapticList : public FTableRowBase +{ + GENERATED_BODY() + + FHapticList() : + sHapticPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = HapticList) + FString sHapticPath; + + bool operator==(const FHapticList& Other) const + { + return sHapticPath == Other.sHapticPath; + } + bool operator!=(const FHapticList& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sHapticPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructItem.h b/Source/ProjectT/Data/Gen/GenerateStructItem.h new file mode 100644 index 0000000..61647b8 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructItem.h @@ -0,0 +1,53 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructItem.generated.h" + +USTRUCT(BlueprintType) +struct FItem : public FTableRowBase +{ + GENERATED_BODY() + + FItem() : + sItemType(), + iItemSkillId(), + iItemMeshId(), + sItemIconPath(), + iItemNameId(), + iItemDescId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + FString sItemType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + int32 iItemSkillId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + int32 iItemMeshId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + FString sItemIconPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + int32 iItemNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Item) + int32 iItemDescId; + + bool operator==(const FItem& Other) const + { + return sItemType == Other.sItemType && iItemSkillId == Other.iItemSkillId && iItemMeshId == Other.iItemMeshId && sItemIconPath == Other.sItemIconPath && iItemNameId == Other.iItemNameId && iItemDescId == Other.iItemDescId; + } + bool operator!=(const FItem& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sItemType.IsEmpty() && iItemSkillId == 0 && iItemMeshId == 0 && sItemIconPath.IsEmpty() && iItemNameId == 0 && iItemDescId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructItemSet.h b/Source/ProjectT/Data/Gen/GenerateStructItemSet.h new file mode 100644 index 0000000..5f0d280 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructItemSet.h @@ -0,0 +1,41 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructItemSet.generated.h" + +USTRUCT(BlueprintType) +struct FItemSet : public FTableRowBase +{ + GENERATED_BODY() + + FItemSet() : + iItemGroupId(), + iItemId(), + iProbWeight() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = ItemSet) + int32 iItemGroupId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = ItemSet) + int32 iItemId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = ItemSet) + int32 iProbWeight; + + bool operator==(const FItemSet& Other) const + { + return iItemGroupId == Other.iItemGroupId && iItemId == Other.iItemId && iProbWeight == Other.iProbWeight; + } + bool operator!=(const FItemSet& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return iItemGroupId == 0 && iItemId == 0 && iProbWeight == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructLevelObject.h b/Source/ProjectT/Data/Gen/GenerateStructLevelObject.h new file mode 100644 index 0000000..9928030 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructLevelObject.h @@ -0,0 +1,37 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructLevelObject.generated.h" + +USTRUCT(BlueprintType) +struct FLevelObject : public FTableRowBase +{ + GENERATED_BODY() + + FLevelObject() : + sLevelObjType(), + iCastItemId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = LevelObject) + FString sLevelObjType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = LevelObject) + int32 iCastItemId; + + bool operator==(const FLevelObject& Other) const + { + return sLevelObjType == Other.sLevelObjType && iCastItemId == Other.iCastItemId; + } + bool operator!=(const FLevelObject& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sLevelObjType.IsEmpty() && iCastItemId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructLocalization.h b/Source/ProjectT/Data/Gen/GenerateStructLocalization.h new file mode 100644 index 0000000..5a64b31 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructLocalization.h @@ -0,0 +1,37 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructLocalization.generated.h" + +USTRUCT(BlueprintType) +struct FLocalization : public FTableRowBase +{ + GENERATED_BODY() + + FLocalization() : + sKorean(), + sEnglish() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Localization) + FString sKorean; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Localization) + FString sEnglish; + + bool operator==(const FLocalization& Other) const + { + return sKorean == Other.sKorean && sEnglish == Other.sEnglish; + } + bool operator!=(const FLocalization& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sKorean.IsEmpty() && sEnglish.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructMeshList.h b/Source/ProjectT/Data/Gen/GenerateStructMeshList.h new file mode 100644 index 0000000..e2e4852 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructMeshList.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructMeshList.generated.h" + +USTRUCT(BlueprintType) +struct FMeshList : public FTableRowBase +{ + GENERATED_BODY() + + FMeshList() : + sMeshPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = MeshList) + FString sMeshPath; + + bool operator==(const FMeshList& Other) const + { + return sMeshPath == Other.sMeshPath; + } + bool operator!=(const FMeshList& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sMeshPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructObjective.h b/Source/ProjectT/Data/Gen/GenerateStructObjective.h new file mode 100644 index 0000000..912d7a4 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructObjective.h @@ -0,0 +1,49 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructObjective.generated.h" + +USTRUCT(BlueprintType) +struct FObjective : public FTableRowBase +{ + GENERATED_BODY() + + FObjective() : + sObjectiveType(), + sObjectiveSubType(), + iObjectiveItemId(), + iObjectiveCount(), + iObjectiveDescId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Objective) + FString sObjectiveType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Objective) + FString sObjectiveSubType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Objective) + int32 iObjectiveItemId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Objective) + int32 iObjectiveCount; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Objective) + int32 iObjectiveDescId; + + bool operator==(const FObjective& Other) const + { + return sObjectiveType == Other.sObjectiveType && sObjectiveSubType == Other.sObjectiveSubType && iObjectiveItemId == Other.iObjectiveItemId && iObjectiveCount == Other.iObjectiveCount && iObjectiveDescId == Other.iObjectiveDescId; + } + bool operator!=(const FObjective& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sObjectiveType.IsEmpty() && sObjectiveSubType.IsEmpty() && iObjectiveItemId == 0 && iObjectiveCount == 0 && iObjectiveDescId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructPlayerCharacter.h b/Source/ProjectT/Data/Gen/GenerateStructPlayerCharacter.h new file mode 100644 index 0000000..c5064cc --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructPlayerCharacter.h @@ -0,0 +1,117 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructPlayerCharacter.generated.h" + +USTRUCT(BlueprintType) +struct FPlayerCharacter : public FTableRowBase +{ + GENERATED_BODY() + + FPlayerCharacter() : + fCharHp(), + fCharMove(), + fCharMoveSound(), + fCharRun(), + fCharRunSound(), + fStamina(), + fStaRecovery(), + iItemSlot(), + iCharAttackId(), + iCharSkillId(), + iCharNameId(), + iCharDescId(), + iPassiveName1Id(), + iPassiveDesc1Id(), + iPassiveName2Id(), + iPassiveDesc2Id(), + iPassiveName3Id(), + iPassiveDesc3Id(), + iCharMeshSetId(), + iCharAniSetId(), + sCharBlueprintPath(), + sCharIconPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fCharHp; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fCharMove; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fCharMoveSound; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fCharRun; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fCharRunSound; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fStamina; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + float fStaRecovery; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iItemSlot; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharAttackId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharSkillId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharDescId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveName1Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveDesc1Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveName2Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveDesc2Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveName3Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iPassiveDesc3Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharMeshSetId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + int32 iCharAniSetId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + FString sCharBlueprintPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = PlayerCharacter) + FString sCharIconPath; + + bool operator==(const FPlayerCharacter& Other) const + { + return fCharHp == Other.fCharHp && fCharMove == Other.fCharMove && fCharMoveSound == Other.fCharMoveSound && fCharRun == Other.fCharRun && fCharRunSound == Other.fCharRunSound && fStamina == Other.fStamina && fStaRecovery == Other.fStaRecovery && iItemSlot == Other.iItemSlot && iCharAttackId == Other.iCharAttackId && iCharSkillId == Other.iCharSkillId && iCharNameId == Other.iCharNameId && iCharDescId == Other.iCharDescId && iPassiveName1Id == Other.iPassiveName1Id && iPassiveDesc1Id == Other.iPassiveDesc1Id && iPassiveName2Id == Other.iPassiveName2Id && iPassiveDesc2Id == Other.iPassiveDesc2Id && iPassiveName3Id == Other.iPassiveName3Id && iPassiveDesc3Id == Other.iPassiveDesc3Id && iCharMeshSetId == Other.iCharMeshSetId && iCharAniSetId == Other.iCharAniSetId && sCharBlueprintPath == Other.sCharBlueprintPath && sCharIconPath == Other.sCharIconPath; + } + bool operator!=(const FPlayerCharacter& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return fCharHp == 0 && fCharMove == 0 && fCharMoveSound == 0 && fCharRun == 0 && fCharRunSound == 0 && fStamina == 0 && fStaRecovery == 0 && iItemSlot == 0 && iCharAttackId == 0 && iCharSkillId == 0 && iCharNameId == 0 && iCharDescId == 0 && iPassiveName1Id == 0 && iPassiveDesc1Id == 0 && iPassiveName2Id == 0 && iPassiveDesc2Id == 0 && iPassiveName3Id == 0 && iPassiveDesc3Id == 0 && iCharMeshSetId == 0 && iCharAniSetId == 0 && sCharBlueprintPath.IsEmpty() && sCharIconPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructSkill.h b/Source/ProjectT/Data/Gen/GenerateStructSkill.h new file mode 100644 index 0000000..a28b0af --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructSkill.h @@ -0,0 +1,101 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructSkill.generated.h" + +USTRUCT(BlueprintType) +struct FSkill : public FTableRowBase +{ + GENERATED_BODY() + + FSkill() : + sSkillName(), + sSkillType(), + sSkillIconPath(), + fCooldown(), + fDamage(), + fCriDmg(), + fSkillNoise(), + fCorrectRange(), + fSkillRange(), + fProjectileSpeed(), + fEffectRange(), + iEffect1Id(), + iEffect2Id(), + iEffect3Id(), + sSkillBpPath(), + iSkillSocketId(), + iSkillNameId(), + iSkillDescId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + FString sSkillName; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + FString sSkillType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + FString sSkillIconPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fCooldown; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fDamage; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fCriDmg; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fSkillNoise; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fCorrectRange; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fSkillRange; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fProjectileSpeed; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + float fEffectRange; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iEffect1Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iEffect2Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iEffect3Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + FString sSkillBpPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iSkillSocketId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iSkillNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Skill) + int32 iSkillDescId; + + bool operator==(const FSkill& Other) const + { + return sSkillName == Other.sSkillName && sSkillType == Other.sSkillType && sSkillIconPath == Other.sSkillIconPath && fCooldown == Other.fCooldown && fDamage == Other.fDamage && fCriDmg == Other.fCriDmg && fSkillNoise == Other.fSkillNoise && fCorrectRange == Other.fCorrectRange && fSkillRange == Other.fSkillRange && fProjectileSpeed == Other.fProjectileSpeed && fEffectRange == Other.fEffectRange && iEffect1Id == Other.iEffect1Id && iEffect2Id == Other.iEffect2Id && iEffect3Id == Other.iEffect3Id && sSkillBpPath == Other.sSkillBpPath && iSkillSocketId == Other.iSkillSocketId && iSkillNameId == Other.iSkillNameId && iSkillDescId == Other.iSkillDescId; + } + bool operator!=(const FSkill& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sSkillName.IsEmpty() && sSkillType.IsEmpty() && sSkillIconPath.IsEmpty() && fCooldown == 0 && fDamage == 0 && fCriDmg == 0 && fSkillNoise == 0 && fCorrectRange == 0 && fSkillRange == 0 && fProjectileSpeed == 0 && fEffectRange == 0 && iEffect1Id == 0 && iEffect2Id == 0 && iEffect3Id == 0 && sSkillBpPath.IsEmpty() && iSkillSocketId == 0 && iSkillNameId == 0 && iSkillDescId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructSocketList.h b/Source/ProjectT/Data/Gen/GenerateStructSocketList.h new file mode 100644 index 0000000..442a990 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructSocketList.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructSocketList.generated.h" + +USTRUCT(BlueprintType) +struct FSocketList : public FTableRowBase +{ + GENERATED_BODY() + + FSocketList() : + sSocketName() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SocketList) + FString sSocketName; + + bool operator==(const FSocketList& Other) const + { + return sSocketName == Other.sSocketName; + } + bool operator!=(const FSocketList& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sSocketName.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructSoundList.h b/Source/ProjectT/Data/Gen/GenerateStructSoundList.h new file mode 100644 index 0000000..e8659b7 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructSoundList.h @@ -0,0 +1,49 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructSoundList.generated.h" + +USTRUCT(BlueprintType) +struct FSoundList : public FTableRowBase +{ + GENERATED_BODY() + + FSoundList() : + sSoundClass(), + sSoundType(), + sSoundPath(), + sAttenPath(), + bLooping() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SoundList) + FString sSoundClass; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SoundList) + FString sSoundType; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SoundList) + FString sSoundPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SoundList) + FString sAttenPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = SoundList) + bool bLooping; + + bool operator==(const FSoundList& Other) const + { + return sSoundClass == Other.sSoundClass && sSoundType == Other.sSoundType && sSoundPath == Other.sSoundPath && sAttenPath == Other.sAttenPath && bLooping == Other.bLooping; + } + bool operator!=(const FSoundList& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sSoundClass.IsEmpty() && sSoundType.IsEmpty() && sSoundPath.IsEmpty() && sAttenPath.IsEmpty() && bLooping == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructStage.h b/Source/ProjectT/Data/Gen/GenerateStructStage.h new file mode 100644 index 0000000..c4aeb20 --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructStage.h @@ -0,0 +1,77 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructStage.generated.h" + +USTRUCT(BlueprintType) +struct FStage : public FTableRowBase +{ + GENERATED_BODY() + + FStage() : + iMissionId(), + iQuest1Id(), + iQuest2Id(), + iQuest3Id(), + iTimeLimit(), + iNextStageId(), + sStageName(), + sStagePath(), + sStageThumbnailPath(), + sStageBackgroundPath(), + iStageNameId(), + iStageDescId() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iMissionId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iQuest1Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iQuest2Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iQuest3Id; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iTimeLimit; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iNextStageId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + FString sStageName; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + FString sStagePath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + FString sStageThumbnailPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + FString sStageBackgroundPath; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iStageNameId; + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = Stage) + int32 iStageDescId; + + bool operator==(const FStage& Other) const + { + return iMissionId == Other.iMissionId && iQuest1Id == Other.iQuest1Id && iQuest2Id == Other.iQuest2Id && iQuest3Id == Other.iQuest3Id && iTimeLimit == Other.iTimeLimit && iNextStageId == Other.iNextStageId && sStageName == Other.sStageName && sStagePath == Other.sStagePath && sStageThumbnailPath == Other.sStageThumbnailPath && sStageBackgroundPath == Other.sStageBackgroundPath && iStageNameId == Other.iStageNameId && iStageDescId == Other.iStageDescId; + } + bool operator!=(const FStage& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return iMissionId == 0 && iQuest1Id == 0 && iQuest2Id == 0 && iQuest3Id == 0 && iTimeLimit == 0 && iNextStageId == 0 && sStageName.IsEmpty() && sStagePath.IsEmpty() && sStageThumbnailPath.IsEmpty() && sStageBackgroundPath.IsEmpty() && iStageNameId == 0 && iStageDescId == 0; + } +}; + diff --git a/Source/ProjectT/Data/Gen/GenerateStructVfxList.h b/Source/ProjectT/Data/Gen/GenerateStructVfxList.h new file mode 100644 index 0000000..c4bc00e --- /dev/null +++ b/Source/ProjectT/Data/Gen/GenerateStructVfxList.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataTable.h" +#include "GenerateStructVfxList.generated.h" + +USTRUCT(BlueprintType) +struct FVfxList : public FTableRowBase +{ + GENERATED_BODY() + + FVfxList() : + sVfxPath() + { + } + + UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = VfxList) + FString sVfxPath; + + bool operator==(const FVfxList& Other) const + { + return sVfxPath == Other.sVfxPath; + } + bool operator!=(const FVfxList& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return sVfxPath.IsEmpty(); + } +}; + diff --git a/Source/ProjectT/Data/Npc/NpcDataModel.cpp b/Source/ProjectT/Data/Npc/NpcDataModel.cpp new file mode 100644 index 0000000..3b5d22a --- /dev/null +++ b/Source/ProjectT/Data/Npc/NpcDataModel.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NpcDataModel.h" diff --git a/Source/ProjectT/Data/Npc/NpcDataModel.h b/Source/ProjectT/Data/Npc/NpcDataModel.h new file mode 100644 index 0000000..ecb22d3 --- /dev/null +++ b/Source/ProjectT/Data/Npc/NpcDataModel.h @@ -0,0 +1,153 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "NpcDataModel.generated.h" + +USTRUCT(Blueprintable) +struct FCrowdSettingsInfo +{ + GENERATED_BODY() + + FCrowdSettingsInfo() : + bUseCrowdSeparation(true), + SeparationWeight(10.f), + AvoidanceRangeMultiplier(1.f) + {} + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CrowdSettings") + uint8 bUseCrowdSeparation : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CrowdSettings", meta = (EditCondition = "bUseCrowdSeparation"), meta = (Tooltip = "NPC 간 거리 유지 강도")) + float SeparationWeight; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CrowdSettings", meta = (EditCondition = "bUseCrowdSeparation"), meta = (Tooltip = "회피 반응 배율")) + float AvoidanceRangeMultiplier; +}; + +UENUM(BlueprintType) +enum class EHeadRotationType : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Search UMETA(DisplayName = "Search"), + Guard UMETA(DisplayName = "Guard"), + LoopSearch UMETA(DisplayName = "LoopSearch"), + Pause UMETA(DisplayName = "Pause"), + TurnToTarget UMETA(DisplayName = "TurnToTarget") +}; + +UENUM(BlueprintType) +enum class ENpcState : uint8 +{ + Default = 0 UMETA(DisplayName = "Default"), + Returning UMETA(DisplayName = "Returning"), + Doubt UMETA(DisplayName = "Doubt"), + Chase UMETA(DisplayName = "Chase"), + Attack UMETA(DisplayName = "Attack"), + Guard UMETA(DisplayName = "Guard"), + Hit UMETA(DisplayName = "Hit"), + Dead UMETA(DisplayName = "Dead"), +}; + +UENUM(BlueprintType) +enum class ENpcSpeedType : uint8 +{ + Walk = 0 UMETA(DisplayName = "Walk"), + Run UMETA(DisplayName = "Run"), + Stop UMETA(DisplayName = "Stop"), +}; + +UENUM(BlueprintType) +enum class EPatrolType : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Patrol UMETA(DisplayName = "Patrol"), + Search UMETA(DisplayName = "Search"), + SearchPatrol UMETA(DisplayName = "SearchPatrol"), +}; + +UENUM(BlueprintType) +enum class EDoubtState : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Increasing UMETA(DisplayName = "Increasing"), + Decreasing UMETA(DisplayName = "Decreasing"), +}; + +UENUM(BlueprintType) +enum class EVisionMode : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Cone UMETA(DisplayName = "Cone"), + Line UMETA(DisplayName = "Line"), +}; + +UENUM(BlueprintType) +enum class ENpcNormalAnimState : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Idle UMETA(DisplayName = "Idle"), + Walk UMETA(DisplayName = "Walk"), + Run UMETA(DisplayName = "Run"), +}; + +UENUM(BlueprintType) +enum class ENpcAbnormalAnimState : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + HitBack UMETA(DisplayName = "HitBack"), + JumpBack UMETA(DisplayName = "JumpBack"), + FallDown UMETA(DisplayName = "FallDown"), + GetUp UMETA(DisplayName = "GetUp"), + Stun UMETA(DisplayName = "Stun"), + DeadStart UMETA(DisplayName = "DeadStart"), + DeadLoop UMETA(DisplayName = "DeadLoop"), +}; + +USTRUCT(Blueprintable) +struct FNpcSimpleRatio +{ + GENERATED_BODY() + FNpcSimpleRatio() : + CurrentValue(0.f), + MaxValue(0.f) + { + } + + UPROPERTY(EditAnywhere) + float CurrentValue; + + UPROPERTY(EditAnywhere) + float MaxValue; +}; + +USTRUCT(Blueprintable) +struct FNpcEffectValue +{ + GENERATED_BODY() + FNpcEffectValue() : + RemainTime(0.f), + MaxTime(0.f), + EffectValue(0.f) + { + } + + UPROPERTY(EditAnywhere) + float RemainTime; + + UPROPERTY(EditAnywhere) + float MaxTime; + + UPROPERTY(EditAnywhere) + float EffectValue; +}; + +UCLASS() +class PROJECTT_API UNpcDataModel : public UObject +{ + GENERATED_BODY() + +}; diff --git a/Source/ProjectT/Data/Paths/BaseDataPathLibrary.cpp b/Source/ProjectT/Data/Paths/BaseDataPathLibrary.cpp new file mode 100644 index 0000000..33e2022 --- /dev/null +++ b/Source/ProjectT/Data/Paths/BaseDataPathLibrary.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BaseDataPathLibrary.h" + +namespace BaseDataPaths +{ + const FString RootDir = "/Game/"; + const FString SystemDir = RootDir + "System/"; + const FString CoreDir = SystemDir + "Core/"; + const FString EnvsDir = RootDir + "Envs/"; + const FString CharactersDir = RootDir + "Characters/"; + const FString LevelsDir = RootDir + "Levels/"; + const FString UIDir = RootDir + "UI/"; + const FString FXDir = RootDir + "FX/"; + const FString SoundDir = RootDir + "Sound/"; + const FString ResourcesDir = RootDir + "Resources/"; + + namespace Sound + { + const FString BGMDir = SoundDir + "BGM/"; + const FString SFXDir = SoundDir + "SFX/"; + } +} + diff --git a/Source/ProjectT/Data/Paths/BaseDataPathLibrary.h b/Source/ProjectT/Data/Paths/BaseDataPathLibrary.h new file mode 100644 index 0000000..2dfc19f --- /dev/null +++ b/Source/ProjectT/Data/Paths/BaseDataPathLibrary.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "BaseDataPathLibrary.generated.h" + +namespace BaseDataPaths +{ + extern const FString RootDir; + extern const FString SystemDir; + extern const FString CoreDir; + extern const FString EnvsDir; + extern const FString CharactersDir; + extern const FString LevelsDir; + extern const FString UIDir; + extern const FString FXDir; + extern const FString SoundDir; + extern const FString ResourcesDir; + + namespace Sound + { + extern const FString BGMDir; + extern const FString SFXDir; + } + +} + +UCLASS() +class PROJECTT_API UBaseDataPathLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (ToolTip = "../Sound/")) + static FString GetSoundDir() { return BaseDataPaths::SoundDir; } + +}; diff --git a/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.cpp b/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.cpp new file mode 100644 index 0000000..6a03f00 --- /dev/null +++ b/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.cpp @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreDataPathLibrary.h" +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" + +namespace CoreDataPaths +{ + const FString DataDir = BaseDataPaths::CoreDir + "Data/"; + + namespace Data + { + const FString DatatableDir = DataDir + "DataTable/"; + } +} + diff --git a/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.h b/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.h new file mode 100644 index 0000000..f735573 --- /dev/null +++ b/Source/ProjectT/Data/Paths/Core/CoreDataPathLibrary.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CoreDataPathLibrary.generated.h" + +namespace CoreDataPaths +{ + extern const FString DataDir; + namespace Data + { + extern const FString DatatableDir; + } +} + +UCLASS() +class PROJECTT_API UCoreDataPathLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.cpp b/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.cpp new file mode 100644 index 0000000..0c790b7 --- /dev/null +++ b/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.cpp @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LevelDataPathLibrary.h" + +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" + +namespace LevelDataPaths +{ + const FString MultiPlay = BaseDataPaths::LevelsDir + "MultiPlay/"; + const FString SinglePlay = BaseDataPaths::LevelsDir + "SinglePlay/"; + namespace Office + { + extern const FString SPOfficeDir = SinglePlay + "Office/"; + } +} diff --git a/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.h b/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.h new file mode 100644 index 0000000..45b2f7a --- /dev/null +++ b/Source/ProjectT/Data/Paths/Level/LevelDataPathLibrary.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "LevelDataPathLibrary.generated.h" + +namespace LevelDataPaths +{ + extern const FString MultiPlay; + extern const FString SinglePlay; + namespace Office + { + extern const FString OfficeDir; + } +} + +UCLASS() +class PROJECTT_API ULevelDataPathLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.cpp b/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.cpp new file mode 100644 index 0000000..a891d11 --- /dev/null +++ b/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.cpp @@ -0,0 +1,10 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "UIDataPathLibrary.h" +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" + +namespace UIDataPaths +{ + const FString DebugDir = BaseDataPaths::UIDir + "Debug/"; +} diff --git a/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.h b/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.h new file mode 100644 index 0000000..c81fe55 --- /dev/null +++ b/Source/ProjectT/Data/Paths/UI/UIDataPathLibrary.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UIDataPathLibrary.generated.h" + +namespace UIDataPaths +{ + extern const FString DebugDir; +} + +UCLASS() +class PROJECTT_API UUIDataPathLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.cpp b/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.cpp new file mode 100644 index 0000000..ed4072b --- /dev/null +++ b/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PlayerInventoryModel.h" diff --git a/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.h b/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.h new file mode 100644 index 0000000..f97c7c3 --- /dev/null +++ b/Source/ProjectT/Data/Player/Inventory/PlayerInventoryModel.h @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateStructItem.h" +#include "UObject/Object.h" +#include "PlayerInventoryModel.generated.h" + +USTRUCT(Blueprintable) +struct FPlayerGimmickSlotData +{ + GENERATED_BODY() + FPlayerGimmickSlotData() : + ItemRowName("None"), + ItemCount(0) + { + } + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item) + FName ItemRowName; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item) + FItem ItemData; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item) + int32 ItemCount; +}; + +USTRUCT(Blueprintable) +struct FPlayerSpendSlotData +{ + GENERATED_BODY() + FPlayerSpendSlotData() : + ItemRowName("None") + { + } + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item) + FName ItemRowName; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item) + FItem ItemData; +}; + +UCLASS() +class PROJECTT_API UPlayerInventoryModel : public UObject +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/Data/Player/PlayerDataModel.cpp b/Source/ProjectT/Data/Player/PlayerDataModel.cpp new file mode 100644 index 0000000..355031d --- /dev/null +++ b/Source/ProjectT/Data/Player/PlayerDataModel.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PlayerDataModel.h" diff --git a/Source/ProjectT/Data/Player/PlayerDataModel.h b/Source/ProjectT/Data/Player/PlayerDataModel.h new file mode 100644 index 0000000..136a431 --- /dev/null +++ b/Source/ProjectT/Data/Player/PlayerDataModel.h @@ -0,0 +1,146 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "InputAction.h" +#include "UObject/Object.h" +#include "PlayerDataModel.generated.h" + +UENUM(BlueprintType) +enum class EPlayerSkillState: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Start UMETA(DisplayName = "Start"), + Aim UMETA(DisplayName = "Aim"), + Activate UMETA(DispalyName = "Activate"), + Cancel UMETA(DIsplayeName = "Cancel"), + Release UMETA(DisplayName = "Release"), + Finish UMETA(DisplayName = "Finish") +}; + +USTRUCT(Blueprintable) +struct FPlayerActionTypes +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr AxisMoveAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr RunAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr MeleeAttackAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr SkillAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr InteractionAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr UseSlot1Action; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr UseSlot2Action; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr UseSlot3Action; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr MinimapAction; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr PauseAction; +}; + +USTRUCT(Blueprintable) +struct FPlayerChordedActionTypes +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr CtrlAction; +}; + +USTRUCT(Blueprintable) +struct FPlayerDebugActionTypes +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleCheat; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleInvincible; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugTogglePlayerDamage; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugTogglePlayerSpeed; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleFrustum; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleHitCollision; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleTimeStop; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleSlomo; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugCharacterSelect; + + UPROPERTY(EditAnywhere, Category = Input) + TObjectPtr DebugToggleCam; + +}; + +USTRUCT(Blueprintable) +struct FPlayerSimpleRatio +{ + GENERATED_BODY() + FPlayerSimpleRatio() : + CurrentValue(0.f), + MaxValue(0.f) + { + } + + UPROPERTY(EditAnywhere) + float CurrentValue; + + UPROPERTY(EditAnywhere) + float MaxValue; +}; + +USTRUCT(Blueprintable) +struct FPlayerEffectValue +{ + GENERATED_BODY() + FPlayerEffectValue() : + RemainTime(0.f), + MaxTime(0.f), + EffectValue(0.f) + { + } + + UPROPERTY(EditAnywhere) + float RemainTime; + + UPROPERTY(EditAnywhere) + float MaxTime; + + UPROPERTY(EditAnywhere) + float EffectValue; +}; + +UCLASS() +class PROJECTT_API UPlayerDataModel : public UObject +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/Data/User/UserDataModel.cpp b/Source/ProjectT/Data/User/UserDataModel.cpp new file mode 100644 index 0000000..ddc3933 --- /dev/null +++ b/Source/ProjectT/Data/User/UserDataModel.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "UserDataModel.h" + diff --git a/Source/ProjectT/Data/User/UserDataModel.h b/Source/ProjectT/Data/User/UserDataModel.h new file mode 100644 index 0000000..c97ab29 --- /dev/null +++ b/Source/ProjectT/Data/User/UserDataModel.h @@ -0,0 +1,134 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "UserDataModel.generated.h" + + +USTRUCT() +struct FSubQuestData +{ + GENERATED_BODY() + + FSubQuestData() {} + bool operator==(const FUserSaveData& Other) const + { + return (*this == Other); + } + bool operator!=(const FUserSaveData& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return true; + } +}; + +USTRUCT(BlueprintType) +struct FUnlockCharacterData +{ + GENERATED_BODY() + + FUnlockCharacterData() : bCleared(false) {} + FUnlockCharacterData(const FString& InRowName, bool InCleared = false) : + UnlockCharacterRowName(InRowName), bCleared(InCleared) { + } + + bool operator==(const FUserSaveData& Other) const + { + return (*this == Other); + } + bool operator!=(const FUserSaveData& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return UnlockCharacterRowName.IsEmpty() && !bCleared; + } + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString UnlockCharacterRowName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bCleared; +}; + +USTRUCT(BlueprintType) +struct FStageData +{ + GENERATED_BODY() + + FStageData() : bCleared(false) {} + FStageData(const FString& InRowName, bool InCleared = false) : + StageRowName(InRowName), bCleared(InCleared) { + } + + bool operator==(const FUserSaveData& Other) const + { + return (*this == Other); + } + bool operator!=(const FUserSaveData& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return StageRowName.IsEmpty() && !bCleared; + } + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FString StageRowName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bCleared; +}; + +USTRUCT() +struct FUserSaveData +{ + GENERATED_BODY() + + FUserSaveData() + { + if(UnlockCharacterData.IsEmpty()) + UnlockCharacterData.Push(FUnlockCharacterData(TEXT("200001"), true)); + + if(UnlockStageData.IsEmpty()) + UnlockStageData.Push(FStageData(TEXT("100101"), true)); + } + bool operator==(const FUserSaveData& Other) const + { + return (*this == Other); + } + bool operator!=(const FUserSaveData& Other) const + { + return !(*this == Other); + } + bool IsDefault() const + { + return SubQuestData.IsDefault() && UnlockStageData.IsEmpty() && UnlockCharacterData.IsEmpty(); + } + + UPROPERTY() + FSubQuestData SubQuestData; + + UPROPERTY() + TArray UnlockStageData; + + UPROPERTY() + TArray UnlockCharacterData; + + UPROPERTY() + FString SelectedCharacterData; +}; + + +UCLASS() +class PROJECTT_API UUserDataModel : public UObject +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/ProjectT.Build.cs b/Source/ProjectT/ProjectT.Build.cs new file mode 100644 index 0000000..64d5b1a --- /dev/null +++ b/Source/ProjectT/ProjectT.Build.cs @@ -0,0 +1,44 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class ProjectT : ModuleRules +{ + public ProjectT(ReadOnlyTargetRules Target) : base(Target) + { + PublicDependencyModuleNames.AddRange(new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "EnhancedInput", + "LevelSequence", + "MovieScene", + "Slate", + "SlateCore", + "UMG", + "Niagara", + "AIModule", + "ProceduralMeshComponent", + "NavigationSystem", + "MoviePlayer" + }); + if (Target.bBuildEditor) + { + PrivateDependencyModuleNames.AddRange(new string[] {"UnrealEd","MaterialEditor", "LevelEditor" , "EditorUtilityModule"}); + } + else + { + PrivateDependencyModuleNames.AddRange(new string[] { }); + } + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + } +} diff --git a/Source/ProjectT/ProjectT.cpp b/Source/ProjectT/ProjectT.cpp new file mode 100644 index 0000000..598e86a --- /dev/null +++ b/Source/ProjectT/ProjectT.cpp @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "ProjectT.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, ProjectT, "ProjectT" ); diff --git a/Source/ProjectT/ProjectT.h b/Source/ProjectT/ProjectT.h new file mode 100644 index 0000000..8c6050f --- /dev/null +++ b/Source/ProjectT/ProjectT.h @@ -0,0 +1,75 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + +#define CONTENT_DIGIT 2 + +#define NOT_IMPLEMENTED_MSG(Str) UE_LOG(LogTemp, Warning, TEXT("Not Implemented %s() -> Line:%d -> Desc:%s"), TEXT(__FUNCTION__), __LINE__, TEXT(Str)) +#define NOT_IMPLEMENTED() UE_LOG(LogTemp, Warning, TEXT("Not Implemented %s() -> Line:%d"), TEXT(__FUNCTION__), __LINE__) +#define CHECK_FREE(Str) Str.Equals("FREE") + +#define NMT_CHECKF(Object) checkf((Object), TEXT("%s Is Fail. Please Check %s() -> Line:%d"), TEXT(#Object), TEXT(__FUNCTION__), __LINE__) +#define NMT_ENSURE(Object) ensureMsgf((Object), TEXT("%s Is Fail. Please Check %s() -> Line:%d"), TEXT(#Object), TEXT(__FUNCTION__), __LINE__) + +#define NMT_MSG_CHECKF(Object, FormatStr, ...) checkf((Object), TEXT(FormatStr), ##__VA_ARGS__) +#define NMT_MSG_ENSURE(Object, FormatStr, ...) ensureMsgf((Object), TEXT(FormatStr), ##__VA_ARGS__) + +#define JOIN_STRINGS(Delimiter, ...) (*(FString::Join>({__VA_ARGS__}, Delimiter))) + +#define FROM_INT(Num) (*FString::FromInt(Num)) +#define STRING_TO_INTEGER(Str) (FCString::Atoi(Str)) +#define NAME_TO_INTEGER(Name) (FCString::Atoi(Name.ToString())) + +#define SHOW_NMT_LOG 1 +#define NMT_LOG_TYPE Warning + +#ifndef IGN_PARAM +#define IGN_PARAM(X) { (void)X; } +#endif + +#define NMT_LOGF(FormatStr, ...) \ +if(SHOW_NMT_LOG) \ +{ \ + UE_LOG(LogTemp, NMT_LOG_TYPE, TEXT(FormatStr), ##__VA_ARGS__); \ +} + +#define NMT_LOG(FormatStr) \ +if(SHOW_NMT_LOG) \ +{ \ + UE_LOG(LogTemp, NMT_LOG_TYPE, TEXT(FormatStr)); \ +} + +#ifdef __COUNTER__ +#define NMT_DEBUG_PRINT(Duration, FormatStr, ...) \ +if (GEngine) \ +{ \ + GEngine->AddOnScreenDebugMessage( \ + uint64(sizeof(__FILE__) + sizeof(__func__) + __LINE__ + __COUNTER__), \ + Duration, \ + FColor::Orange, \ + FString::Printf(TEXT(FormatStr), ##__VA_ARGS__), \ + false, \ + FVector2D(0.9, 0.9)); \ +} + +#define NMT_DEBUG_PRINT_ONCE(FormatStr, ...) \ +NMT_DEBUG_PRINT(-1.f, FormatStr, ##__VA_ARGS__) + +#define NMT_DEBUG_POS_PRINT(Duration, Position, FormatStr,...) \ +if (GEngine) \ +{ \ + GEngine->AddOnScreenDebugMessage( \ + uint64(sizeof(__FILE__) + sizeof(__func__) + __LINE__ + __COUNTER__), \ + Duration, \ + FColor::Orange, \ + FString::Printf(TEXT(FormatStr), ##__VA_ARGS__), \ + false, \ + Position \ + ); \ +} +#define NMT_DEBUG_POS_PRINT_ONCE(Position, FormatStr, ...) \ +NMT_DEBUG_POS_PRINT(-1.f, Position, FormatStr) + +#endif diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.cpp b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.cpp new file mode 100644 index 0000000..c14cb43 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AbnormalAnimEnd.h" + +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +void UAbnormalAnimEnd::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) +{ + Super::Notify(MeshComp, Animation, EventReference); + + ASPNpcAgent* AgentNpc = Cast(MeshComp->GetOwner()); + if (AgentNpc) + { + AgentNpc->DetermineNextStateAfterAbnormal(); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.h b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.h new file mode 100644 index 0000000..341fe49 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/AbnormalAnimEnd.h @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotify.h" +#include "AbnormalAnimEnd.generated.h" + + +UCLASS() +class PROJECTT_API UAbnormalAnimEnd : public UAnimNotify +{ + GENERATED_BODY() + + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; +}; diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.cpp b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.cpp new file mode 100644 index 0000000..d787442 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.cpp @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NonInputAnimEnd.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h" + +void UNonInputAnimEnd::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + const FAnimNotifyEventReference& EventReference) +{ + Super::Notify(MeshComp, Animation, EventReference); + ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner()); + if(LocPlayerCharacter) + { + UPlayerCharacterAnimInstance* LocPlayerAnimInstance; + LocPlayerCharacter->GetAnimInstance(LocPlayerAnimInstance); + LocPlayerAnimInstance->NonInputAnimFinished(); + return; + } +} diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.h b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.h new file mode 100644 index 0000000..73ae598 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/NonInputAnimEnd.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotify.h" +#include "NonInputAnimEnd.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UNonInputAnimEnd : public UAnimNotify +{ + GENERATED_BODY() + + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; +}; diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.cpp b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.cpp new file mode 100644 index 0000000..52b9976 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.cpp @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SkillHitEnabled.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +void USkillHitEnabled::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + const FAnimNotifyEventReference& EventReference) +{ + Super::Notify(MeshComp, Animation, EventReference); + if(const ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner())) + { + ACoreSkill* LocCurrentSkill; + LocPlayerCharacter->GetCurrentSkill(LocCurrentSkill); + if (LocCurrentSkill) + LocCurrentSkill->SkillHitEnable(true); + return; + } + + if(const ASPNpcAgent* LocASPNpcAgent = Cast(MeshComp->GetOwner())) + { + ACoreSkill* LocCurrentSkill = LocASPNpcAgent->GetCurrentSkill(); + if (LocCurrentSkill) + LocCurrentSkill->SkillHitEnable(true); + + return; + } + + if(ACoreSkill* LocACoreSkill = Cast(MeshComp->GetOwner())) + { + LocACoreSkill->SkillObjectHitEnable(true); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.h b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.h new file mode 100644 index 0000000..a4dec5a --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/AnimNotify/SkillHitEnabled.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotify.h" +#include "SkillHitEnabled.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API USkillHitEnabled : public UAnimNotify +{ + GENERATED_BODY() + + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; +}; diff --git a/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.cpp b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.cpp new file mode 100644 index 0000000..678144d --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.cpp @@ -0,0 +1,56 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SkillFXEnabledState.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +void USkillFXEnabledState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + float TotalDuration, const FAnimNotifyEventReference& EventReference) +{ + Super::NotifyBegin(MeshComp, Animation, TotalDuration, EventReference); + ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner()); + if(LocPlayerCharacter) + { + ACoreSkill* LocCurrentSkill; + LocPlayerCharacter->GetCurrentSkill(LocCurrentSkill); + if (LocCurrentSkill) + LocCurrentSkill->SkillFXEnable(true, FXIndex); + return; + } + + ASPNpcAgent* LocASPNpcAgent = Cast(MeshComp->GetOwner()); + if(LocASPNpcAgent) + { + ACoreSkill* LocCurrentSkill = LocASPNpcAgent->GetCurrentSkill(); + if (LocCurrentSkill) + LocCurrentSkill->SkillFXEnable(true, FXIndex); + return; + } +} + +void USkillFXEnabledState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + const FAnimNotifyEventReference& EventReference) +{ + Super::NotifyEnd(MeshComp, Animation, EventReference); + ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner()); + if(LocPlayerCharacter) + { + ACoreSkill* LocCurrentSkill; + LocPlayerCharacter->GetCurrentSkill(LocCurrentSkill); + if (LocCurrentSkill) + LocCurrentSkill->SkillFXEnable(false, FXIndex); + return; + } + + ASPNpcAgent* LocASPNpcAgent = Cast(MeshComp->GetOwner()); + if(LocASPNpcAgent) + { + ACoreSkill* LocCurrentSkill = LocASPNpcAgent->GetCurrentSkill(); + if (LocCurrentSkill) + LocCurrentSkill->SkillFXEnable(false, FXIndex); + return; + } +} diff --git a/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.h b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.h new file mode 100644 index 0000000..669420c --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillFXEnabledState.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotifyState.h" +#include "SkillFXEnabledState.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API USkillFXEnabledState : public UAnimNotifyState +{ + GENERATED_BODY() + virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference) override; + virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; + +protected: + UPROPERTY(EditAnywhere) + int32 FXIndex = 0; +}; diff --git a/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.cpp b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.cpp new file mode 100644 index 0000000..fd391f9 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.cpp @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SkillHitEnabledState.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +void USkillHitEnabledState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, + float TotalDuration, const FAnimNotifyEventReference& EventReference) +{ + Super::NotifyBegin(MeshComp, Animation, TotalDuration, EventReference); + ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner()); + if(LocPlayerCharacter) + { + ACoreSkill* LocCurrentSkill; + LocPlayerCharacter->GetCurrentSkill(LocCurrentSkill); + if(LocCurrentSkill) + { + LocCurrentSkill->SkillHitEnable(true); + } + return; + } + + ASPNpcAgent* LocASPNpcAgent = Cast(MeshComp->GetOwner()); + if(LocASPNpcAgent) + { + ACoreSkill* LocCurrentSkill = LocASPNpcAgent->GetCurrentSkill(); + if (LocCurrentSkill) + LocCurrentSkill->SkillHitEnable(true); + return; + } +} + +void USkillHitEnabledState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) +{ + Super::NotifyEnd(MeshComp, Animation, EventReference); + ACorePlayerCharacter* LocPlayerCharacter = Cast(MeshComp->GetOwner()); + if(LocPlayerCharacter) + { + ACoreSkill* LocCurrentSkill; + LocPlayerCharacter->GetCurrentSkill(LocCurrentSkill); + if (LocCurrentSkill) + { + LocCurrentSkill->SkillHitEnable(false); + } + return; + } + + ASPNpcAgent* LocASPNpcAgent = Cast(MeshComp->GetOwner()); + if(LocASPNpcAgent) + { + ACoreSkill* LocCurrentSkill = LocASPNpcAgent->GetCurrentSkill(); + if (LocCurrentSkill) + LocCurrentSkill->SkillHitEnable(false); + return; + } +} diff --git a/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.h b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.h new file mode 100644 index 0000000..ebb29e5 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Animations/NotifyState/SkillHitEnabledState.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotifyState.h" +#include "SkillHitEnabledState.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API USkillHitEnabledState : public UAnimNotifyState +{ + GENERATED_BODY() + virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference) override; + virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; +}; diff --git a/Source/ProjectT/System/Core/Characters/CombatCharacter.cpp b/Source/ProjectT/System/Core/Characters/CombatCharacter.cpp new file mode 100644 index 0000000..13ff737 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/CombatCharacter.cpp @@ -0,0 +1,258 @@ +#include "CombatCharacter.h" +#include "Components/CapsuleComponent.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h" +#include "ProjectT/Data/Gen/GenerateStructEnemyNPC.h" +#include "ProjectT/Data/Gen/GenerateStructMeshList.h" +#include "ProjectT/Data/Gen/GenerateStructPlayerCharacter.h" +#include "ProjectT/Data/Gen/GenerateStructSocketList.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +class CharacterDataLoader +{ +public: + static void From(const FName& RowName, FName& OutMeshRowName, FCharacterMeshSet& OutMeshList, const FTableRowBase*& OutContentData) + { + FName FoundMeshRowName; + EContentType NewContentType = UGlobalUtilsLibrary::GetContentTypeFromIndex(RowName); + UDataTable* DataTable = nullptr; + switch(NewContentType) + { + case EContentType::PlayerCharacter: + { + DataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::PlayerCharacter); + FPlayerCharacter* CharacterDataRow = DataTable->FindRow(RowName, TEXT("Not Found FPlayerCharacter")); + if(!NMT_ENSURE(CharacterDataRow)) return; + FoundMeshRowName = FROM_INT(CharacterDataRow->iCharMeshSetId); + OutContentData = CharacterDataRow; + break; + } + case EContentType::EnemyNpc: + { + DataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::EnemyNpc); + FEnemyNpc* CharacterDataRow = DataTable->FindRow(RowName, TEXT("Not Found FEnemyNPC")); + if(!NMT_ENSURE(CharacterDataRow)) return; + FoundMeshRowName = FROM_INT(CharacterDataRow->iNpcMeshSetId); + OutContentData = CharacterDataRow; + break; + } + default: return; + } + DataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::CharacterMeshSet); + if(FCharacterMeshSet* RowData = DataTable->FindRow(FoundMeshRowName, TEXT("FCharacterMeshSet"))) + { + OutMeshList = *RowData; + OutMeshRowName = FoundMeshRowName; + } + } +}; + +ACombatCharacter::ACombatCharacter() : + AccessoryMeshComponent(nullptr), + WeaponStaticComponent(nullptr), + WeaponDynamicComponent(nullptr), + DefaultBodyMesh(nullptr) +{ + GetCapsuleComponent()->SetCapsuleHalfHeight(50.0f); + GetCapsuleComponent()->SetCapsuleRadius(20.0f); + GetMesh()->SetRelativeLocation(FVector(0.0f, 0.0f, -52.0f)); + + AccessoryMeshComponent = CreateDefaultSubobject(TEXT("AccessoryMeshComponent")); + WeaponStaticComponent = CreateDefaultSubobject(TEXT("WeaponStaticComponent")); + WeaponDynamicComponent = CreateDefaultSubobject(TEXT("WeaponDynamicComponent")); + NMT_CHECKF(AccessoryMeshComponent && WeaponStaticComponent && WeaponDynamicComponent); + + UGlobalUtilsLibrary::EnableComponent(AccessoryMeshComponent, false); + UGlobalUtilsLibrary::EnableComponent(WeaponStaticComponent, false); + UGlobalUtilsLibrary::EnableComponent(WeaponDynamicComponent, false); +} + +void ACombatCharacter::PostLoad() +{ + Super::PostLoad(); +} + +void ACombatCharacter::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); + +#if WITH_EDITOR + const FString LabelRowName = *GetActorLabel(); + if(LabelRowName.IsNumeric()) ApplyCharacterConfiguration(*LabelRowName); +#endif +} + +EContentType ACombatCharacter::GetContentType_Implementation() +{ + return IContentType::GetContentType_Implementation(); +} + +FString ACombatCharacter::GetContentTypeNumber_Implementation() +{ + return IContentType::GetContentTypeNumber_Implementation(); +} + +void ACombatCharacter::BeginPlay() +{ + Super::BeginPlay(); + +#if WITH_EDITOR + const FString LabelRowName = *GetActorLabel(); + if(LabelRowName.IsNumeric()) ApplyCharacterConfiguration(*LabelRowName); + else if(!CharacterRowName.IsNone() && CharacterRowName.ToString().IsNumeric()) ApplyCharacterConfiguration(CharacterRowName); +#endif + + GetCapsuleComponent()->OnClicked.AddUniqueDynamic(this, &ACombatCharacter::ExecuteClickedEvent); + GetCapsuleComponent()->OnBeginCursorOver.AddUniqueDynamic(this, &ACombatCharacter::ExecuteBeginCursorOverEvent); + GetCapsuleComponent()->OnEndCursorOver.AddUniqueDynamic(this, &ACombatCharacter::ExecuteEndCursorOverEvent); +} + +#if WITH_EDITOR +void ACombatCharacter::ApplyCharacterConfiguration(const FName& RowName) +{ + if(RowName.IsNone()) + { + RestoreCharacterSet(); + RestoreCharacterData(); + return; + } + + const EContentType NewContentType = UGlobalUtilsLibrary::GetContentTypeFromIndex(RowName); + if(EContentType::PlayerCharacter != NewContentType && EContentType::EnemyNpc != NewContentType) + { + RestoreCharacterSet(); + RestoreCharacterData(); + return; + } + + FName MeshSetRowName; + FCharacterMeshSet NewMeshSet; + const FTableRowBase* CharacterData = nullptr; + CharacterDataLoader::From(RowName, MeshSetRowName, NewMeshSet, CharacterData); + if(MeshSetRowName.IsNone()) + { + RestoreCharacterSet(); + return; + } + + if(ApplyCharacterSet(MeshSetRowName)) + { + CurrentMeshSet = NewMeshSet; + CharacterRowName = RowName; + } + else RestoreCharacterSet(); + + if(CharacterData) ApplyCharacterData(CharacterData); +} + +bool ACombatCharacter::ApplyCharacterSet(const FName& RowName) +{ + UDataTable* CMSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::CharacterMeshSet); + FCharacterMeshSet* CMSData = CMSTable->FindRow(RowName, TEXT("FCharacterMeshSet")); + if(!CMSData) return false; + + UDataTable* MLSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::MeshList); + FMeshList* BodyData = MLSTable->FindRow(FROM_INT(CMSData->iBodyMeshId), TEXT("FMeshList")); + if(!BodyData) return false; + + USkeletalMesh* BodyMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(BodyData->sMeshPath); + if(!BodyMesh) return false; + GetMesh()->SetSkeletalMesh(BodyMesh); + + FMeshList* WeaponData = nullptr; + if(CMSData->iWeaponMeshId != 0) WeaponData = MLSTable->FindRow(FROM_INT(CMSData->iWeaponMeshId), TEXT("FMeshList")); + + /** + * NOTE: Weapon Data는 항상 유효성을 보장하지 않음 + */ + if(!WeaponData) return true; + if(!CHECK_FREE(WeaponData->sMeshPath)) + { + UMeshComponent* WeaponComponent = nullptr; + FString ScriptType = UGlobalUtilsLibrary::GetScriptTypeByRefPath(WeaponData->sMeshPath); + if(ScriptType.Equals(TEXT("StaticMesh"))) + { + UStaticMesh* WeaponMesh = UAssetUtilsLibrary::GetStaticMeshFromPath(WeaponData->sMeshPath); + WeaponStaticComponent->SetStaticMesh(WeaponMesh); + UGlobalUtilsLibrary::EnableComponent(WeaponStaticComponent, true); + WeaponComponent = WeaponStaticComponent; + } + else if(ScriptType.Equals(TEXT("SkeletalMesh"))) + { + USkeletalMesh* WeaponMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(WeaponData->sMeshPath); + WeaponDynamicComponent->SetSkeletalMesh(WeaponMesh); + UGlobalUtilsLibrary::EnableComponent(WeaponDynamicComponent, true); + WeaponComponent = WeaponDynamicComponent; + } + else NMT_MSG_CHECKF(0, "%s: type is not supported", *WeaponData->sMeshPath); + + CMSData->iWeaponSocketId; + UDataTable* SocketTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::SocketList); + FSocketList* SocketData = SocketTable->FindRow(FROM_INT(CMSData->iWeaponSocketId), TEXT("FSocketList")); + if(CHECK_FREE(SocketData->sSocketName)) + { + NMT_MSG_ENSURE(0, "Socket Name Is FREE [%s][%s]", FROM_INT(CMSData->iWeaponSocketId), *SocketData->sSocketName); + return true; + } + + WeaponComponent->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, *SocketData->sSocketName); + } + + return true; +} + +void ACombatCharacter::ApplyCharacterData(const FTableRowBase* RowData) +{ + NMT_MSG_ENSURE(0, "Function should be overridden in the child class."); +} + +void ACombatCharacter::RestoreCharacterData() +{ + ApplyCharacterData(nullptr); +} + +void ACombatCharacter::RestoreCharacterSet() +{ + AccessoryMeshComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + UGlobalUtilsLibrary::EnableComponent(AccessoryMeshComponent, false); + + WeaponStaticComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + UGlobalUtilsLibrary::EnableComponent(WeaponStaticComponent, false); + + WeaponDynamicComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + UGlobalUtilsLibrary::EnableComponent(WeaponDynamicComponent, false); + + FString LocDefaultSKMeshPath = "/Script/Engine.SkeletalMesh'/Game/Characters/Pyro/Assets/SK_Pyro_Invalid.SK_Pyro_Invalid'"; + DefaultBodyMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(LocDefaultSKMeshPath); + if(DefaultBodyMesh != nullptr) + { + GetMesh()->SetSkeletalMesh(DefaultBodyMesh); + } + + CurrentMeshSet = FCharacterMeshSet(); + CharacterRowName = TEXT("None"); +} +#endif + +void ACombatCharacter::Respawn() +{ + NOT_IMPLEMENTED(); +} + +void ACombatCharacter::ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed) +{ + Super::ExecuteClickedEvent(InTouchedComponent, InButtonPressed); +} + +void ACombatCharacter::ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + Super::ExecuteBeginCursorOverEvent(InTouchedComponent); +} + +void ACombatCharacter::ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + Super::ExecuteEndCursorOverEvent(InTouchedComponent); +} diff --git a/Source/ProjectT/System/Core/Characters/CombatCharacter.h b/Source/ProjectT/System/Core/Characters/CombatCharacter.h new file mode 100644 index 0000000..8e7455b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/CombatCharacter.h @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreCharacter.h" +#include "ProjectT/System/Core/Characters/CoreCharacter.h" +#include "ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h" +#include "ProjectT/System/Core/Interfaces/ContentType.h" +#include "ProjectT/System/Core/Interfaces/ObjectInteractionControl.h" +#include "CombatCharacter.generated.h" + +class USkeletalMesh; +class UStaticMeshComponent; + +UCLASS() +class PROJECTT_API ACombatCharacter : public ACoreCharacter, public IContentType +{ + GENERATED_BODY() + +public: + ACombatCharacter(); + virtual void PostLoad() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual EContentType GetContentType_Implementation() override; + virtual FString GetContentTypeNumber_Implementation() override; + void GetWeaponStaticComponent(TObjectPtr& OutStaticWeapon) const { OutStaticWeapon = WeaponStaticComponent; } + +protected: + virtual void BeginPlay() override; + +#if WITH_EDITOR + virtual void ApplyCharacterConfiguration(const FName& RowName); + virtual bool ApplyCharacterSet(const FName& RowName); + virtual void ApplyCharacterData(const FTableRowBase* RowData); + void RestoreCharacterSet(); + void RestoreCharacterData(); +#endif + + virtual void Respawn(); + + virtual void ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed) override; + virtual void ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent) override; + virtual void ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent) override; + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Design|CharacterSet") + TObjectPtr AccessoryMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Design|CharacterSet") + TObjectPtr WeaponStaticComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Design|CharacterSet") + TObjectPtr WeaponDynamicComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design|CharacterSet") + FName CharacterRowName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design|CharacterSet", meta = (AllowPrivateAccess = "true")) + FCharacterMeshSet CurrentMeshSet; + + UPROPERTY() + TObjectPtr DefaultBodyMesh; + +private: + UPROPERTY() + FName PrevCharacterRowName; + +}; diff --git a/Source/ProjectT/System/Core/Characters/CoreCharacter.cpp b/Source/ProjectT/System/Core/Characters/CoreCharacter.cpp new file mode 100644 index 0000000..79ff612 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/CoreCharacter.cpp @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreCharacter.h" +#include "ProjectT/ProjectT.h" + +ACoreCharacter::ACoreCharacter() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ACoreCharacter::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ACoreCharacter::ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed) +{ + NOT_IMPLEMENTED(); +} + +void ACoreCharacter::ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + NOT_IMPLEMENTED(); +} + +void ACoreCharacter::ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + NOT_IMPLEMENTED(); +} + +void ACoreCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + diff --git a/Source/ProjectT/System/Core/Characters/CoreCharacter.h b/Source/ProjectT/System/Core/Characters/CoreCharacter.h new file mode 100644 index 0000000..c01e893 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/CoreCharacter.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Character.h" +#include "CoreCharacter.generated.h" + +UCLASS() +class PROJECTT_API ACoreCharacter : public ACharacter +{ + GENERATED_BODY() + +public: + ACoreCharacter(); + +protected: + virtual void BeginPlay() override; + + UFUNCTION() + virtual void ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed); + + UFUNCTION() + virtual void ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent); + + UFUNCTION() + virtual void ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent); + +public: + virtual void Tick(float DeltaTime) override; + + +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.cpp new file mode 100644 index 0000000..36f1f1c --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BlackboardKeyLibrary.h" + +namespace NpcBaseKeys +{ + const FName TargetActor = FName("TargetActor"); + const FName TargetLocation = FName("TargetLocation"); + const FName TargetDir = FName("TargetDir"); + const FName ReturnLocation = FName("ReturnLocation"); + const FName CurrentState = FName("CurrentState"); + const FName bCanAttack = FName("bCanAttack"); + const FName bCanRotateWhileAttack = FName("bCanRotateWhileAttack"); + const FName CurrentDoubtState = FName("CurrentDoubtState"); + + namespace PatrolKeys + { + FName bMoveReverse = FName("bMoveReverse"); + FName PatrolType = FName("PatrolType"); + } +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h new file mode 100644 index 0000000..9c5b21d --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "BlackboardKeyLibrary.generated.h" + +namespace NpcBaseKeys +{ + extern const FName TargetActor; + extern const FName TargetLocation; + extern const FName TargetDir; + extern const FName ReturnLocation; + extern const FName CurrentState; + extern const FName bCanAttack; + extern const FName bCanRotateWhileAttack; + extern const FName CurrentDoubtState; + + namespace PatrolKeys + { + extern FName bMoveReverse; + extern FName PatrolType; + } +} + +UCLASS() +class PROJECTT_API UBlackboardKeyLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintPure, meta = (ToolTip = "TargetActor")) + static FName GetTargetActorKey() { return NpcBaseKeys::TargetActor; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "TargetLocation")) + static FName GetTargetLocationKey() { return NpcBaseKeys::TargetLocation; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "TargetDir")) + static FName GetTargetDirKey() { return NpcBaseKeys::TargetDir; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "ReturnLocation")) + static FName GetReturnLocationKey() { return NpcBaseKeys::ReturnLocation; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "NpcState")) + static FName GetCurrentStateKey() { return NpcBaseKeys::CurrentState; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "CanAttack")) + static FName GetCanAttack() { return NpcBaseKeys::bCanAttack; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "CanRotateWhileAttack")) + static FName GetCanRotateWhileAttack() { return NpcBaseKeys::bCanRotateWhileAttack; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "CurrentDoubtState")) + static FName GetCurrentDoubtState() { return NpcBaseKeys::CurrentDoubtState; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "bMoveReverse")) + static FName GetMoveReverseKey() { return NpcBaseKeys::PatrolKeys::bMoveReverse; } + + UFUNCTION(BlueprintPure, meta = (ToolTip = "PatrolType")) + static FName GetPatrolTypeKey() { return NpcBaseKeys::PatrolKeys::PatrolType; } + +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.cpp new file mode 100644 index 0000000..3c19729 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.cpp @@ -0,0 +1,154 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AIControllerBase.h" + +#include "BrainComponent.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/BlackboardData.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" + +AAIControllerBase::AAIControllerBase(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer), + bCanDetect(true) +{ +} + +void AAIControllerBase::BeginPlay() +{ + Super::BeginPlay(); +} + +class UBlackboardComponent* AAIControllerBase::GetCheckedBlackboardComponent() +{ + UBlackboardComponent* BBC = GetBlackboardComponent(); + NMT_CHECKF(BBC) + return BBC; +} + +void AAIControllerBase::PostInitializeComponents() +{ + Super::PostInitializeComponents(); +} + +void AAIControllerBase::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + + SetGenericTeamId(FGenericTeamId(0)); +} + +void AAIControllerBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AAIControllerBase::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + OnDetectTarget.Clear(); + OnForgetTarget.Clear(); +} + +void AAIControllerBase::UpdateTargetInfo(AActor* InTarget) +{ + GetCheckedBlackboardComponent()->SetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey(), InTarget); + + if(InTarget != nullptr) + { + UpdateTargetLocation(InTarget->GetActorLocation()); + UpdateTargetDirection(InTarget); + + OnDetectTarget.Broadcast(); + } + else + { + OnForgetTarget.Broadcast(); + } +} + +void AAIControllerBase::UpdateTargetLocation(const FVector& InLocation) +{ + GetCheckedBlackboardComponent()->SetValueAsVector(UBlackboardKeyLibrary::GetTargetLocationKey(), InLocation); +} + +void AAIControllerBase::UpdateTargetDirection(const AActor* InTarget) +{ + FVector Dir = InTarget->GetActorLocation() - GetPawn()->GetActorLocation(); + Dir.Normalize(); + GetCheckedBlackboardComponent()->SetValueAsVector(UBlackboardKeyLibrary::GetTargetDirKey(), Dir); +} + +void AAIControllerBase::UpdateTargetDirection(const FVector& InTargetDirection) +{ + GetCheckedBlackboardComponent()->SetValueAsVector(UBlackboardKeyLibrary::GetTargetDirKey(), InTargetDirection); +} + +void AAIControllerBase::ChangeNpcStateKey(const ENpcState InState) +{ + GetCheckedBlackboardComponent()->SetValueAsEnum(UBlackboardKeyLibrary::GetCurrentStateKey(), static_cast(InState)); +} + +void AAIControllerBase::StartAI() +{ + NMT_CHECKF(BrainComponent) + BrainComponent->StartLogic(); +} + +void AAIControllerBase::StopAI(const FString& Reason, const bool bControlPerception) +{ + NMT_CHECKF(BrainComponent) + BrainComponent->StopLogic(Reason); +} + +AActor* AAIControllerBase::GetTargetActor() const +{ + return Cast(GetBlackboardComponent()->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey())); +} + +void AAIControllerBase::ActivateBehaviorTree(APawn* InPawn) +{ + if(InPawn->GetClass()->ImplementsInterface(UAISettings::StaticClass())) + { + UBlackboardData* BB = IAISettings::Execute_GetBlackboardData(InPawn); + BehaviorTree = IAISettings::Execute_GetBehaviorTree(InPawn); + + if(!NMT_ENSURE(BB && BehaviorTree)) return; + + UBlackboardComponent* BlackboardComponent = Blackboard.Get(); + + if(UseBlackboard(BB, BlackboardComponent)) + { + RunBehaviorTree(BehaviorTree); + } + } +} + +void AAIControllerBase::UpdateReturnLocation(const FVector& InLocation) +{ + GetCheckedBlackboardComponent()->SetValueAsVector(UBlackboardKeyLibrary::GetReturnLocationKey(), InLocation); +} + +void AAIControllerBase::UpdateNextPatrolType(const EPatrolType InPatrolType) +{ + GetCheckedBlackboardComponent()->SetValueAsEnum(UBlackboardKeyLibrary::GetPatrolTypeKey(), static_cast(InPatrolType)); +} + +void AAIControllerBase::UpdateDoubtState(const EDoubtState InDoubtState) +{ + GetCheckedBlackboardComponent()->SetValueAsEnum(UBlackboardKeyLibrary::GetCurrentDoubtState(), static_cast(InDoubtState)); +} + +void AAIControllerBase::SetEnableAttack(const bool InbEnable) +{ + GetCheckedBlackboardComponent()->SetValueAsBool(UBlackboardKeyLibrary::GetCanAttack(), InbEnable); +} + +void AAIControllerBase::SetCanRotateWhileAttack(const bool InbEnable) +{ + GetCheckedBlackboardComponent()->SetValueAsBool(UBlackboardKeyLibrary::GetCanRotateWhileAttack(), InbEnable); +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h new file mode 100644 index 0000000..b04f576 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h @@ -0,0 +1,76 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/AIModule/Classes/AIController.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "AIControllerBase.generated.h" + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDetectTarget); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnForgetTarget); + +enum class EEffectSubTypes : uint8; + +UCLASS() +class PROJECTT_API AAIControllerBase : public AAIController +{ + GENERATED_BODY() + +public: + AAIControllerBase(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + + virtual void PostInitializeComponents() override; + virtual void OnPossess(APawn* InPawn) override; + virtual void Tick(float DeltaTime) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + UFUNCTION(BlueprintCallable) + void UpdateTargetInfo(AActor* InTarget); + + UFUNCTION(BlueprintCallable) + void ChangeNpcStateKey(const ENpcState InState); + + UFUNCTION(BlueprintCallable) + virtual void StartAI(); + + UFUNCTION(BlueprintCallable) + virtual void StopAI(const FString& Reason, const bool bControlPerception = true); + + class AActor* GetTargetActor() const; + FORCEINLINE void SetCanDetect(bool InbCanDetect) { bCanDetect = InbCanDetect; } + FORCEINLINE bool GetCanDetect() const { return bCanDetect; } + virtual void ActivateBehaviorTree(APawn* InPawn); + void UpdateTargetLocation(const FVector& InLocation); + void UpdateTargetDirection(const AActor* InTarget); + void UpdateTargetDirection(const FVector& InTargetDirection); + void UpdateReturnLocation(const FVector& InLocation); + void UpdateNextPatrolType(const EPatrolType InPatrolType); + void UpdateDoubtState(const EDoubtState InDoubtState); + void SetEnableAttack(const bool InbEnable); + void SetCanRotateWhileAttack(const bool InbEnable); + +protected: + virtual void BeginPlay() override; + class UBlackboardComponent* GetCheckedBlackboardComponent(); + +protected: + UPROPERTY(BlueprintAssignable) + FOnDetectTarget OnDetectTarget; + + UPROPERTY(BlueprintAssignable) + FOnForgetTarget OnForgetTarget; + + UPROPERTY() + TObjectPtr CrowdFollowingComponent; + + uint8 bCanDetect : 1; + +private: + + UPROPERTY() + TObjectPtr BehaviorTree; + +}; + diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.cpp new file mode 100644 index 0000000..4cf6995 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.cpp @@ -0,0 +1,44 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AIHearingController.h" +#include "Perception/AISenseConfig_Hearing.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" + + +AAIHearingController::AAIHearingController(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer) +{ + PrimaryActorTick.bCanEverTick = true; + + HearingConfig = AddHearingConfig(); +} + +void AAIHearingController::BeginPlay() +{ + Super::BeginPlay(); +} + +void AAIHearingController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + + NMT_CHECKF(HearingConfig); + NMT_CHECKF(GetPawn()); + + if(GetPawn()->GetClass()->ImplementsInterface(UAISettings::StaticClass())) + { + FHearingInfo HearingInfo = IAISettings::Execute_GetHearingInfo(InPawn); + + HearingConfig->HearingRange = HearingInfo.HearingRange; + HearingConfig->SetMaxAge(HearingInfo.HearingMaxAge); + } + + UpdatePerceptionSystem(); +} + +void AAIHearingController::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.h new file mode 100644 index 0000000..5f8c74b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIHearingController.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIPerceptionController.h" +#include "AIHearingController.generated.h" + +UCLASS() +class PROJECTT_API AAIHearingController : public AAIPerceptionController +{ + GENERATED_BODY() + +public: + AAIHearingController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + +protected: + virtual void BeginPlay() override; + +public: + virtual void OnPossess(APawn* InPawn) override; + virtual void Tick(float DeltaTime) override; + +public: + UPROPERTY(EditAnywhere, Category = "AIPerception") + class UAISenseConfig_Hearing* HearingConfig; +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.cpp new file mode 100644 index 0000000..dc628ac --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.cpp @@ -0,0 +1,185 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AIPerceptionController.h" + +#include "BehaviorTree/BlackboardComponent.h" +#include "Navigation/CrowdFollowingComponent.h" +#include "Perception/AIPerceptionComponent.h" +#include "Perception/AISenseConfig_Hearing.h" +#include "Perception/AISenseConfig_Sight.h" +#include "Perception/AISense_Sight.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + + +AAIPerceptionController::AAIPerceptionController(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer.SetDefaultSubobjectClass(TEXT("PathFollowingComponent"))) +{ + SetPerceptionComponent(*CreateOptionalDefaultSubobject(TEXT("AIPerceptionComponent"))); +} + +void AAIPerceptionController::BeginPlay() +{ + Super::BeginPlay(); + + if(ASPNpcAgent* NpcAgent = Cast(GetPawn())) + { + CrowdFollowingComponent = Cast(GetPathFollowingComponent()); + NMT_CHECKF(CrowdFollowingComponent); + SetupCrowdSettings(NpcAgent->CrowdSettingsInfo); + } +} + +void AAIPerceptionController::SetupCrowdSettings(const FCrowdSettingsInfo& InCrowdSettings) const +{ + if(!NMT_ENSURE(CrowdFollowingComponent)) + return; + + if(InCrowdSettings.bUseCrowdSeparation) + { + CrowdFollowingComponent->SetCrowdSeparation(InCrowdSettings.bUseCrowdSeparation); + CrowdFollowingComponent->SetCrowdSeparationWeight(InCrowdSettings.SeparationWeight); + CrowdFollowingComponent->SetCrowdAvoidanceRangeMultiplier(InCrowdSettings.AvoidanceRangeMultiplier); + CrowdFollowingComponent->SetCrowdRotateToVelocity(false); + } +} + +void AAIPerceptionController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); +} + +void AAIPerceptionController::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AAIPerceptionController::StartAI() +{ + Super::StartAI(); + SetPerceptionActive(true); +} + +void AAIPerceptionController::StopAI(const FString& InReason, const bool InbControlPerception) +{ + if(InbControlPerception) + SetPerceptionActive(false); + + Super::StopAI(InReason, InbControlPerception); +} + +void AAIPerceptionController::ActivateBehaviorTree(APawn* InPawn) +{ + Super::ActivateBehaviorTree(InPawn); + + if(InPawn->GetClass()->ImplementsInterface(UAISettings::StaticClass())) + { + bool bUseSense = IAISettings::Execute_GetUseSight(InPawn) || IAISettings::Execute_GetUseHearing(InPawn); + if(bUseSense) + SetPerceptionActive(true); + } +} + +void AAIPerceptionController::UpdatedTargetPerception(AActor* InTarget, FAIStimulus InStimulus) +{ + if(!NMT_ENSURE(GetPawn())) return; + + ACorePlayerCharacter* Player = Cast(InTarget); + if(GetPawn()->GetClass()->ImplementsInterface(UAISettings::StaticClass()) && Player) + { + if(InStimulus.WasSuccessfullySensed()) + { + bool PlayerUndetect; + Player->GetUnDetectState(PlayerUndetect); + if(PlayerUndetect || bUnDetect) + return; + + TSubclassOf Sense = UAIPerceptionSystem::GetSenseClassForStimulus(GetWorld(), InStimulus); + + if(IAISettings::Execute_GetUseSight(GetPawn()) && Sense == UAISense_Sight::StaticClass()) + { + IAISettings::Execute_DetectTargetBySight(GetPawn(), InTarget, InStimulus); + } + + UpdateTargetInfo(InTarget); + } + else + { + if(GetCheckedBlackboardComponent()->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey()) != nullptr) + { + IAISettings::Execute_ForgetTarget(GetPawn(), InTarget); + } + } + } +} + +void AAIPerceptionController::SetPerceptionActive(const bool InbEnable) +{ + NMT_CHECKF(PerceptionComponent) + if(InbEnable) + { + PerceptionComponent->OnTargetPerceptionUpdated.AddUniqueDynamic(this, &AAIPerceptionController::UpdatedTargetPerception); + } + else + { + GetCheckedBlackboardComponent()->SetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey(), nullptr); + PerceptionComponent->OnTargetPerceptionUpdated.Clear(); + } +} + +void AAIPerceptionController::UpdatePerceptionSystem() const +{ + NMT_CHECKF(PerceptionComponent) + PerceptionComponent->RequestStimuliListenerUpdate(); + PerceptionComponent->SetCanEverAffectNavigation(true); +} + +void AAIPerceptionController::ForceUpdatePerception() const +{ + NMT_CHECKF(PerceptionComponent) + if(PerceptionComponent->OnTargetPerceptionUpdated.IsBound()) + { + TArray LocPerceivedActors; + PerceptionComponent->GetCurrentlyPerceivedActors(UAISense_Sight::StaticClass(), LocPerceivedActors); + if(LocPerceivedActors.Num() > 0) + { + for(AActor* LocPerceiveActor : LocPerceivedActors) + { + FActorPerceptionBlueprintInfo LocPerceptionInfo; + PerceptionComponent->GetActorsPerception(LocPerceiveActor, LocPerceptionInfo); + PerceptionComponent->OnTargetPerceptionUpdated.Broadcast(LocPerceiveActor, LocPerceptionInfo.LastSensedStimuli[0]); + } + } + } +} + +class UAISenseConfig_Sight* AAIPerceptionController::AddSightConfig() +{ + UAISenseConfig_Sight* SightConfig = CreateOptionalDefaultSubobject(TEXT("SightConfig")); + SightConfig->DetectionByAffiliation.bDetectEnemies = true; + SightConfig->DetectionByAffiliation.bDetectNeutrals = false; + SightConfig->DetectionByAffiliation.bDetectFriendlies = false; + + NMT_CHECKF(PerceptionComponent) + PerceptionComponent->SetDominantSense(*SightConfig->GetSenseImplementation()); + PerceptionComponent->ConfigureSense(*SightConfig); + + return SightConfig; +} + +class UAISenseConfig_Hearing* AAIPerceptionController::AddHearingConfig() +{ + UAISenseConfig_Hearing* HearingConfig = CreateOptionalDefaultSubobject(TEXT("HearingConfig")); + HearingConfig->DetectionByAffiliation.bDetectEnemies = true; + HearingConfig->DetectionByAffiliation.bDetectNeutrals = false; + HearingConfig->DetectionByAffiliation.bDetectFriendlies = false; + + NMT_CHECKF(PerceptionComponent) + PerceptionComponent->SetDominantSense(*HearingConfig->GetSenseImplementation()); + PerceptionComponent->ConfigureSense(*HearingConfig); + + return HearingConfig; +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.h new file mode 100644 index 0000000..cf47ff8 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIControllerBase.h" +#include "AIPerceptionController.generated.h" + +UCLASS() +class PROJECTT_API AAIPerceptionController : public AAIControllerBase +{ + GENERATED_BODY() + +public: + AAIPerceptionController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + + virtual void OnPossess(APawn* InPawn) override; + virtual void Tick(float DeltaTime) override; + virtual void StartAI() override; + virtual void StopAI(const FString& InReason, const bool InbControlPerception = true) override; + virtual void ActivateBehaviorTree(APawn* InPawn) override; + + void UpdatePerceptionSystem() const; + void ForceUpdatePerception() const; + void SetPerceptionActive(const bool InbEnable); + FORCEINLINE void SetUnDetect(const bool InbUnDetect) { bUnDetect = InbUnDetect; } + +protected: + virtual void BeginPlay() override; + void SetupCrowdSettings(const FCrowdSettingsInfo& InCrowdSettings) const; + + UFUNCTION() + void UpdatedTargetPerception(AActor* InTarget, FAIStimulus InStimulus); + + class UAISenseConfig_Sight* AddSightConfig(); + class UAISenseConfig_Hearing* AddHearingConfig(); + + uint8 bUnDetect; +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.cpp new file mode 100644 index 0000000..a988c78 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.cpp @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AISightController.h" + +#include "Perception/AISenseConfig_Sight.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" + + +AAISightController::AAISightController(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer) +{ + PrimaryActorTick.bCanEverTick = true; + + SightConfig = AddSightConfig(); +} + +void AAISightController::BeginPlay() +{ + Super::BeginPlay(); +} + +void AAISightController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + + NMT_CHECKF(SightConfig); + NMT_CHECKF(GetPawn()); + + if(GetPawn()->GetClass()->ImplementsInterface(UAISettings::StaticClass())) + { + FSightInfo SightInfo = IAISettings::Execute_GetSightInfo(GetPawn()); + + SightConfig->SightRadius = SightInfo.SightRange; + SightConfig->LoseSightRadius = SightInfo.LoseSightRange; + SightConfig->PeripheralVisionAngleDegrees = SightInfo.SightAngle / 2.f; + SightConfig->SetMaxAge(SightInfo.SightMaxAge); + } + + UpdatePerceptionSystem(); +} + +void AAISightController::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.h new file mode 100644 index 0000000..99e479d --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIPerceptionController.h" +#include "AISightController.generated.h" + +UCLASS() +class PROJECTT_API AAISightController : public AAIPerceptionController +{ + GENERATED_BODY() + +public: + AAISightController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + +protected: + virtual void BeginPlay() override; + +public: + virtual void OnPossess(APawn* InPawn) override; + virtual void Tick(float DeltaTime) override; + +public: + UPROPERTY(EditAnywhere, Category = "AIPerception") + class UAISenseConfig_Sight* SightConfig; +}; + diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.cpp b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.cpp new file mode 100644 index 0000000..d3052b9 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.cpp @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AISightHearingController.h" + +#include "Perception/AISenseConfig_Hearing.h" +#include "Perception/AISenseConfig_Sight.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" + +AAISightHearingController::AAISightHearingController(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer) +{ + PrimaryActorTick.bCanEverTick = true; + + HearingConfig = AddHearingConfig(); + SightConfig = AddSightConfig(); +} + +void AAISightHearingController::BeginPlay() +{ + Super::BeginPlay(); +} + +void AAISightHearingController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + + NMT_CHECKF(SightConfig && HearingConfig); + NMT_CHECKF(GetPawn()); + + if(GetPawn()->GetClass()->ImplementsInterface(UAISettings::StaticClass())) + { + FSightInfo SightInfo = IAISettings::Execute_GetSightInfo(GetPawn()); + + SightConfig->SightRadius = SightInfo.SightRange; + SightConfig->LoseSightRadius = SightInfo.LoseSightRange; + SightConfig->PeripheralVisionAngleDegrees = SightInfo.SightAngle / 2.f; + SightConfig->SetMaxAge(SightInfo.SightMaxAge); + + FHearingInfo HearingInfo = IAISettings::Execute_GetHearingInfo(InPawn); + + HearingConfig->HearingRange = HearingInfo.HearingRange; + HearingConfig->SetMaxAge(HearingInfo.HearingMaxAge); + } + + UpdatePerceptionSystem(); +} + +void AAISightHearingController::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.h b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.h new file mode 100644 index 0000000..efb7353 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightHearingController.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIPerceptionController.h" +#include "AISightHearingController.generated.h" + +UCLASS() +class PROJECTT_API AAISightHearingController : public AAIPerceptionController +{ + GENERATED_BODY() + +public: + AAISightHearingController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); + +protected: + virtual void BeginPlay() override; + +public: + virtual void OnPossess(APawn* InPawn) override; + virtual void Tick(float DeltaTime) override; + +public: + UPROPERTY(EditAnywhere, Category = "AIPerception") + class UAISenseConfig_Sight* SightConfig; + + UPROPERTY(EditAnywhere, Category = "AIPerception") + class UAISenseConfig_Hearing* HearingConfig; +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.cpp b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.cpp new file mode 100644 index 0000000..81f957e --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NpcAnimInstance.h" + + +UNpcAnimInstance::UNpcAnimInstance() : + ForwardHeadRotation(FRotator(0.0, -90.0, 21.0)), + HeadRotation(ForwardHeadRotation), + HeadRotAlpha(0.f) +{ +} + +void UNpcAnimInstance::NativeInitializeAnimation() +{ + Super::NativeInitializeAnimation(); +} + +void UNpcAnimInstance::NativeUpdateAnimation(float DeltaSeconds) +{ + Super::NativeUpdateAnimation(DeltaSeconds); +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h new file mode 100644 index 0000000..d639933 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "NpcAnimInstance.generated.h" + + +UCLASS() +class PROJECTT_API UNpcAnimInstance : public UAnimInstance +{ + GENERATED_BODY() + +public: + UNpcAnimInstance(); + + virtual void NativeInitializeAnimation() override; + virtual void NativeUpdateAnimation(float DeltaSeconds) override; + +public: + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + FRotator ForwardHeadRotation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + FRotator HeadRotation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + float HeadRotAlpha; +}; + + + diff --git a/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.cpp b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.cpp new file mode 100644 index 0000000..88e4748 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NpcFixedAnimInstance.h" + +UNpcFixedAnimInstance::UNpcFixedAnimInstance() +{ + ForwardHeadRotation = FRotator(0.0, 0.0, 90.0); + HeadRotation = ForwardHeadRotation; + HeadRotAlpha = 0.f; +} diff --git a/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.h b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.h new file mode 100644 index 0000000..2159cef --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "NpcAnimInstance.h" +#include "NpcFixedAnimInstance.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UNpcFixedAnimInstance : public UNpcAnimInstance +{ + GENERATED_BODY() + +public: + UNpcFixedAnimInstance(); + +}; diff --git a/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.cpp b/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.cpp new file mode 100644 index 0000000..9e5a473 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.cpp @@ -0,0 +1,951 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreNpc.h" + +#include "NiagaraComponent.h" +#include "AI/Controllers/AISightController.h" +#include "Components/CapsuleComponent.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "GameFramework/SpringArmComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h" +#include "ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Components/ObstacleFilterComponent.h" +#include "ProjectT/System/Core/Components/VisionConeComponent.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + +#define ACTIVATE_CHARACTER 1 + +ACoreNpc::ACoreNpc() : + DefaultLocation(), + DefaultRotation(), + bReachedHeadRotation(false), + bCanRotateHeadToTarget(false), + bEnableRespawn(0), + RespawnTime(0), + BehaviorTree(nullptr), + Blackboard(nullptr), + SpringArmComponent(nullptr), + VisionHead(nullptr), + VisionConeComponent(nullptr), + NpcStatusComponent(nullptr), + AlertComponent(nullptr), + CurrentState(ENpcState::Default), + PerceptionMaxAge(3.f), + NpcAnimInstance(nullptr), + bActivatedOnStart(true), + PrevState(ENpcState::Default), + CurrentDoubtState(EDoubtState::None), + EyeSocketName(TEXT("SKT_NPC_Vision")), + AlertSphereProfileName(TEXT("SoundRange")), + LoseSightOffset(10.f), + HeadRotSpeedMultiplier(4.f), + bCanTriggerAlert(true), + bUnDetect(false), + bFrustumCullingTimerSet(true), + bActivate(true), + bUseSocketTransformForVision(true) +{ + PrimaryActorTick.bCanEverTick = true; + + AIControllerClass = AAIControllerBase::StaticClass(); + AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned; + + GetCharacterMovement()->bUseControllerDesiredRotation = true; + GetCharacterMovement()->bOrientRotationToMovement = false; + GetCharacterMovement()->GetNavMovementProperties()->bUseAccelerationForPaths = true; + bUseControllerRotationYaw = false; + + GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint); + GetMesh()->SetAnimInstanceClass(UNpcAnimInstance::StaticClass()); + + SubRootComponent = CreateDefaultSubobject(TEXT("SubRootComponent")); + WidgetRootComponent = CreateDefaultSubobject(TEXT("WidgetRootComponent")); + SpringArmComponent = CreateDefaultSubobject(TEXT("SpringArmComponent")); + VisionHead = CreateDefaultSubobject(TEXT("VisionHead")); + VisionConeComponent = CreateDefaultSubobject(TEXT("VisionConeComponent")); + AlertComponent = CreateDefaultSubobject(TEXT("AlertComponent")); + NpcStatusComponent = CreateDefaultSubobject(TEXT("NpcStatusComponent")); + NoiseFXComponent = CreateDefaultSubobject(TEXT("NoiseFXComponent")); + NMT_CHECKF(WidgetRootComponent && SubRootComponent && SpringArmComponent && VisionHead && VisionConeComponent && AlertComponent && NpcStatusComponent && NoiseFXComponent) + + SubRootComponent->SetupAttachment(RootComponent); + WidgetRootComponent->SetupAttachment(RootComponent); + + SpringArmComponent->SetupAttachment(SubRootComponent); + SpringArmComponent->bDoCollisionTest = false; + SpringArmComponent->TargetArmLength = 0.f; + SpringArmComponent->bInheritRoll = false; + SpringArmComponent->bInheritPitch = false; + SpringArmComponent->bEnableCameraLag = true; + SpringArmComponent->CameraLagSpeed = 0.f; + + SpringArmComponent->bEnableCameraRotationLag = true; + SpringArmComponent->CameraRotationLagSpeed = 7.f; + SpringArmComponent->SetCanEverAffectNavigation(false); + + VisionHead->SetupAttachment(SpringArmComponent); + VisionConeComponent->SetupAttachment(SpringArmComponent); + + AlertComponent->SetupAttachment(SubRootComponent); + AlertComponent->DeactivateFiltering(); + AlertComponent->SetCollisionProfileName(AlertSphereProfileName); + + NoiseFXComponent->SetupAttachment(SubRootComponent); + NoiseFXComponent->bAutoActivate = false; + + if(HeadRotationPatterns.IsEmpty()) + SetupHeadRotationPattern(); +} + +void ACoreNpc::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); + + DefaultLocation = GetActorLocation(); + DefaultRotation = GetActorRotation(); +} + +void ACoreNpc::BeginPlay() +{ + Super::BeginPlay(); + + ActivateCharacter(false); + InitializeProperty(); + InitializeEvents(); +} + +void ACoreNpc::PostInitializeComponents() +{ + Super::PostInitializeComponents(); +} + +void ACoreNpc::Enable_Implementation() +{ + IPoolableActor::Enable_Implementation(); +} + +void ACoreNpc::Disable_Implementation() +{ + IPoolableActor::Disable_Implementation(); +} + +void ACoreNpc::Pushed_Implementation() +{ + IPoolableActor::Pushed_Implementation(); +} + +void ACoreNpc::Obtained_Implementation() +{ + IPoolableActor::Obtained_Implementation(); +} + +void ACoreNpc::GetCurrentEffectTypes_Implementation(TArray& OutEffectSubTypes) +{ + TArray LocReturnCurrentEffects; + EffectTimeMap.GetKeys(LocReturnCurrentEffects); + if(LocReturnCurrentEffects.Num() > 0) + { + OutEffectSubTypes = LocReturnCurrentEffects; + } + else + { + LocReturnCurrentEffects.Add(EEffectSubTypes::None); + OutEffectSubTypes = LocReturnCurrentEffects; + } +} + +void ACoreNpc::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + if(!bFrustumCullingTimerSet) + { + bFrustumCullingTimerSet = true; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().SetTimer(UpdateActiveComponentHandle, this, &ACoreNpc::UpdateActiveComponentInFrustum, DeltaTime, true); + } + + if(HeadRotationInfo.bOverrideHeadRotation) + UpdateHeadRotation(DeltaTime); + + if(HeadRotationInfo.bChangeAlpha) + UpdateHeadRotationAlpha(DeltaTime); + + SetSpringArmRotation(); + if(VisionConeComponent->IsDrawing()) + VisionConeComponent->UpdateVision(VisionHead->GetComponentRotation()); +} + +void ACoreNpc::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().ClearTimer(UpdateActiveComponentHandle); + World->GetTimerManager().ClearTimer(RespawnTimerHandle); + World->GetTimerManager().ClearTimer(CompleteAlertTimerHandle); + World->GetTimerManager().ClearTimer(EffectTimerHandle); + + OnNpcDead.Clear(); + OnNpcRespawn.Clear(); + OnNpcIndicatorChanged.Clear(); +} + +void ACoreNpc::GetActorEyesViewPoint(FVector& Location, FRotator& Rotation) const +{ + if(!VisionHead) return; + Location = VisionHead->GetComponentLocation(); + Rotation = VisionHead->GetComponentRotation(); +} + +FEnemyNpc ACoreNpc::GetCurrentNpcStatus() const +{ + if(!NMT_ENSURE(NpcStatusComponent)) + return FEnemyNpc(); + + return NpcStatusComponent->GetCurrentNpcStatus(); +} + +void ACoreNpc::InitializeStatus(const FEnemyNpc InNpcStatus) +{ + if(!NMT_ENSURE(NpcStatusComponent)) + return; + + bool bNpcDataValid = !InNpcStatus.IsDefault(); + if(!NMT_ENSURE(bNpcDataValid)) return; + +#if WITH_EDITOR + NpcStatusComponent->InitializeStatus(InNpcStatus); +#endif +} + +void ACoreNpc::InitializeProperty() +{ + NpcAnimInstance = Cast(GetMesh()->GetAnimInstance()); + NMT_CHECKF(NpcAnimInstance && NpcStatusComponent) + + FObstacleFilterInfo FilterInfo; + FilterInfo.SphereRadius = NpcStatusComponent->GetStatusNpcNoise(); + FilterInfo.CheckOutOfRange = false; + AlertComponent->InitializeProperty(FilterInfo); + AlertComponent->DeactivateFiltering(); +} + +void ACoreNpc::InitializeEvents() +{ + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(this)); + + NC->AddObserverStatic(this, ENotificationTypes::GameState_Victory, FNotificationCenterStatic::CreateWeakLambda(this, [this]() + { + ResetStateAfterGameEnd(); + })); + NC->AddObserverStatic(this, ENotificationTypes::GameState_Defeat, FNotificationCenterStatic::CreateWeakLambda(this, [this]() + { + ResetStateAfterGameEnd();; + })); + // FIXME + // NC->AddObserverStatic(this, ENotificationTypes::UI_DefeatActionCleared, FNotificationCenterStatic::CreateWeakLambda(this, [this]() + // { + // SetActorLocationAndRotation(DefaultLocation, DefaultRotation); + // SetActorHiddenInGame(true); + // NMT_LOG("UI_DefeatActionCleared") + // })); + // NC->AddObserverStatic(this, ENotificationTypes::UI_VictoryActionCleared, FNotificationCenterStatic::CreateWeakLambda(this, [this]() + // { + // SetActorLocationAndRotation(DefaultLocation, DefaultRotation); + // SetActorHiddenInGame(true); + // NMT_LOG("UI_VictoryActionCleared") + // })); +} + +void ACoreNpc::Respawn() +{ + Super::Respawn(); + + SetActorEnableCollision(true); + GetMesh()->bPauseAnims = false; + GetAIControllerBase()->StartAI(); + SetActorHiddenInGame(false); + SetActorTickEnabled(true); + NpcStatusComponent->ReInitializeStatus(); + + ChangeNpcState(ENpcState::Default); + OnNpcRespawn.Broadcast(); +} + +void ACoreNpc::ChangeHeadRotationState(const EHeadRotationType InHeadRotationType) +{ + bReachedHeadRotation = false; + switch(InHeadRotationType) + { + case EHeadRotationType::Pause: + { + NpcStatusComponent->SetStatusNpcRotationSpeed(NpcStatusComponent->GetPreviousNpcStatus().fRotationSpeed); + HeadRotationInfo.bOverrideHeadRotation = false; + break; + } + case EHeadRotationType::Search: case EHeadRotationType::LoopSearch: + { + NpcStatusComponent->SetStatusNpcRotationSpeed(NpcStatusComponent->GetPreviousNpcStatus().fRotationSpeed); + CurrentPhaseLists = *HeadRotationPatterns.Find(InHeadRotationType); + if(!CurrentPhaseLists.IsEmpty()) + { + HeadRotationInfo.CurrentPhaseIdx = 0; + HeadRotationInfo.bOverrideHeadRotation = true; + } + break; + } + case EHeadRotationType::Guard: + { + NpcStatusComponent->SetStatusNpcRotationSpeed(NpcStatusComponent->GetPreviousNpcStatus().fRotationSpeed * HeadRotSpeedMultiplier); + CurrentPhaseLists = *HeadRotationPatterns.Find(InHeadRotationType); + if(!CurrentPhaseLists.IsEmpty()) + { + HeadRotationInfo.CurrentPhaseIdx = 0; + HeadRotationInfo.bOverrideHeadRotation = true; + } + break; + } + case EHeadRotationType::TurnToTarget: + { + NpcStatusComponent->SetStatusNpcRotationSpeed(NpcStatusComponent->GetPreviousNpcStatus().fRotationSpeed * HeadRotSpeedMultiplier); + HeadRotationInfo.bOverrideHeadRotation = true; + break; + } + case EHeadRotationType::None: + { + NpcStatusComponent->SetStatusNpcRotationSpeed(NpcStatusComponent->GetPreviousNpcStatus().fRotationSpeed); + break; + } + } + + HeadRotationInfo.HeadRotationType = InHeadRotationType; +} + +void ACoreNpc::SetHeadRotationEnable(const bool InbEnable) +{ + HeadRotationInfo.bChangeAlpha = true; + + InbEnable ? HeadRotationInfo.TargetAlpha = 1.f : HeadRotationInfo.TargetAlpha = 0.f; +} + +bool ACoreNpc::IsAggressiveState(const ENpcState InState) const +{ + return InState == ENpcState::Chase || InState == ENpcState::Attack; +} + +bool ACoreNpc::IsDamagedState(const ENpcState InState) const +{ + return (InState == ENpcState::Hit || InState == ENpcState::Dead) || GetNpcStatusComponent()->IsDead(); +} + +void ACoreNpc::SetupHeadRotationPattern() +{ + TArray List; + + List.Append({EHeadRotationPhase::TurnRight, EHeadRotationPhase::TurnLeft, EHeadRotationPhase::TurnForward}); + HeadRotationPatterns.Add(EHeadRotationType::Search, List); + + List.Empty(); + List.Append({EHeadRotationPhase::TurnRight, EHeadRotationPhase::TurnLeft, EHeadRotationPhase::TurnForward}); + HeadRotationPatterns.Add(EHeadRotationType::Guard, List); + + List.Empty(); + List.Append({EHeadRotationPhase::TurnRight, EHeadRotationPhase::TurnLeft}); + HeadRotationPatterns.Add(EHeadRotationType::LoopSearch, List); + +} + +void ACoreNpc::UpdateHeadRotation(float InDeltaTime) +{ + if(!NMT_ENSURE(NpcStatusComponent)) + return; + + switch(HeadRotationInfo.HeadRotationType) + { + case EHeadRotationType::LoopSearch: + { + if(!NMT_MSG_ENSURE(CurrentPhaseLists.IsValidIndex(HeadRotationInfo.CurrentPhaseIdx), "Not ValidIndex in CurrentPhaseLists %d", HeadRotationInfo.CurrentPhaseIdx)) + { + ResetHeadRotation(); + bReachedHeadRotation = true; + HeadRotationInfo.bOverrideHeadRotation = false; + return; + } + + if(CurrentPhaseLists[HeadRotationInfo.CurrentPhaseIdx] == EHeadRotationPhase::TurnRight) + { + HeadRotationInfo.TargetRotation = FRotator(NpcAnimInstance->ForwardHeadRotation.Pitch, NpcAnimInstance->ForwardHeadRotation.Yaw + NpcStatusComponent->GetStatusNpcHalfRotationAngle(), NpcAnimInstance->ForwardHeadRotation.Roll); + } + else if(CurrentPhaseLists[HeadRotationInfo.CurrentPhaseIdx] == EHeadRotationPhase::TurnLeft) + { + HeadRotationInfo.TargetRotation = FRotator(NpcAnimInstance->ForwardHeadRotation.Pitch, NpcAnimInstance->ForwardHeadRotation.Yaw - NpcStatusComponent->GetStatusNpcHalfRotationAngle(), NpcAnimInstance->ForwardHeadRotation.Roll); + } + + if(NpcAnimInstance->HeadRotation.Equals(HeadRotationInfo.TargetRotation, 0.1f)) + { + HeadRotationInfo.CurrentPhaseIdx == 0 ? HeadRotationInfo.CurrentPhaseIdx++ : HeadRotationInfo.CurrentPhaseIdx--; + } + NpcAnimInstance->HeadRotation = FMath::RInterpTo(NpcAnimInstance->HeadRotation, HeadRotationInfo.TargetRotation, InDeltaTime, NpcStatusComponent->GetStatusNpcRotationSpeed()); + break; + } + case EHeadRotationType::Search: case EHeadRotationType::Guard: + { + if(!NMT_MSG_ENSURE(CurrentPhaseLists.IsValidIndex(HeadRotationInfo.CurrentPhaseIdx), "Not ValidIndex in CurrentPhaseLists %d", HeadRotationInfo.CurrentPhaseIdx)) + { + ResetHeadRotation(); + bReachedHeadRotation = true; + HeadRotationInfo.bOverrideHeadRotation = false; + return; + } + + if(CurrentPhaseLists[HeadRotationInfo.CurrentPhaseIdx] == EHeadRotationPhase::TurnRight) + { + HeadRotationInfo.TargetRotation = FRotator(NpcAnimInstance->ForwardHeadRotation.Pitch, NpcAnimInstance->ForwardHeadRotation.Yaw + NpcStatusComponent->GetStatusNpcHalfRotationAngle(), NpcAnimInstance->ForwardHeadRotation.Roll); + } + else if(CurrentPhaseLists[HeadRotationInfo.CurrentPhaseIdx] == EHeadRotationPhase::TurnLeft) + { + HeadRotationInfo.TargetRotation = FRotator(NpcAnimInstance->ForwardHeadRotation.Pitch, NpcAnimInstance->ForwardHeadRotation.Yaw - NpcStatusComponent->GetStatusNpcHalfRotationAngle(), NpcAnimInstance->ForwardHeadRotation.Roll); + } + else if(CurrentPhaseLists[HeadRotationInfo.CurrentPhaseIdx] == EHeadRotationPhase::TurnForward) + { + HeadRotationInfo.TargetRotation = NpcAnimInstance->ForwardHeadRotation; + } + + if(NpcAnimInstance->HeadRotation.Equals(HeadRotationInfo.TargetRotation, 0.1f)) + { + HeadRotationInfo.CurrentPhaseIdx++; + if(HeadRotationInfo.CurrentPhaseIdx >= CurrentPhaseLists.Num()) + { + bReachedHeadRotation = true; + ResetHeadRotation(); + } + } + NpcAnimInstance->HeadRotation = FMath::RInterpTo(NpcAnimInstance->HeadRotation, HeadRotationInfo.TargetRotation, InDeltaTime, NpcStatusComponent->GetStatusNpcRotationSpeed()); + break; + } + case EHeadRotationType::TurnToTarget: + { + if(NpcAnimInstance->HeadRotation.Equals(HeadRotationInfo.TargetRotation, 0.1f)) + { + bReachedHeadRotation = true; + HeadRotationInfo.bOverrideHeadRotation = false; + ResetHeadRotation(); + } + NpcAnimInstance->HeadRotation = FMath::RInterpTo(NpcAnimInstance->HeadRotation, HeadRotationInfo.TargetRotation, InDeltaTime, NpcStatusComponent->GetStatusNpcRotationSpeed()); + break; + } + case EHeadRotationType::Pause: case EHeadRotationType::None: + break; + default : NMT_MSG_ENSURE(0, "Not Valid HeadRotation Type"); + } +} + +void ACoreNpc::UpdateHeadRotationAlpha(float InDeltaTime) +{ + if(FMath::IsNearlyEqual(NpcAnimInstance->HeadRotAlpha, HeadRotationInfo.TargetAlpha)) + { + NpcAnimInstance->HeadRotAlpha = HeadRotationInfo.TargetAlpha; + HeadRotationInfo.bChangeAlpha = false; + } + + NpcAnimInstance->HeadRotAlpha = FMath::FInterpTo(NpcAnimInstance->HeadRotAlpha, HeadRotationInfo.TargetAlpha, InDeltaTime, 5.f); +} + +void ACoreNpc::ResetHeadRotation() +{ + HeadRotationInfo.CurrentPhaseIdx = 0; + HeadRotationInfo.HeadRotationType = EHeadRotationType::None; +} + +void ACoreNpc::SetUnDetectTarget(const bool InbUnDetect) +{ + bUnDetect = InbUnDetect; +} + +void ACoreNpc::PostAlert() const +{ + AlertComponent->DeactivateFiltering(); +} + +bool ACoreNpc::CheckEffectTime(const FEffect& InEffect) +{ + bool LocbRefreshEffect = false; + EEffectSubTypes LocEffectSubType = UGlobalUtilsLibrary::GetStringToEnum(InEffect.sEffect); + if(EffectTimeMap.Find(LocEffectSubType)) + { + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue > InEffect.fEffectValue) + return LocbRefreshEffect; + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue == InEffect.fEffectValue) + { + if(EffectTimeMap.Find(LocEffectSubType)->RemainTime < InEffect.fEffectDuration) + LocbRefreshEffect = true; + } + else + LocbRefreshEffect = true; + } + else + LocbRefreshEffect = true; + + return LocbRefreshEffect; +} + +void ACoreNpc::AddEffectTimeMap(const FEffect& InEffect) +{ + FNpcEffectValue LocEffectValue; + EEffectSubTypes LocEffectSubType = UGlobalUtilsLibrary::GetStringToEnum(InEffect.sEffect); + if(EffectTimeMap.Find(LocEffectSubType)) + { + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue > InEffect.fEffectValue) return; + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue == InEffect.fEffectValue) + { + if(EffectTimeMap.Find(LocEffectSubType)->RemainTime < InEffect.fEffectDuration) + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + } + else + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + } + else + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + if(!GetWorld()->GetTimerManager().IsTimerActive(EffectTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(EffectTimerHandle, this, &ACoreNpc::EffectTimeDown, GetWorld()->DeltaTimeSeconds, true); +} + + +void ACoreNpc::EffectTimeDown() +{ + TArray LocEffectSubType; + EffectTimeMap.GetKeys(LocEffectSubType); + FEffect LocRemoveEffect; + for(EEffectSubTypes LocKey : LocEffectSubType) + { + float LocCurRemainTime = EffectTimeMap.Find(LocKey)->RemainTime; + LocCurRemainTime = LocCurRemainTime - GetWorld()->DeltaTimeSeconds; + if(LocCurRemainTime <= 0.f) + { + TArray LocRemoveEffects; + LocRemoveEffect.sEffect = EnumToString(LocKey); + LocRemoveEffect.fEffectValue = EffectTimeMap.Find(LocKey)->EffectValue; + LocRemoveEffects.Add(LocRemoveEffect); + ApplyRecoveryEvent_Implementation(LocRemoveEffects); + } + else + { + EffectTimeMap.Find(LocKey)->RemainTime = LocCurRemainTime; + } + } +} + +void ACoreNpc::SetReturnLocationFromDefault() const +{ + if(GetNpcState() == ENpcState::Default) + GetAIControllerBase()->UpdateReturnLocation(GetActorLocation()); +} + +void ACoreNpc::ChangeIndicatorState(const ENpcState InState) +{ + if(NpcStatusComponent->IsDead()) + return; + + ENpcIndicatorState NewIndicatorState = LastIndicatorState; + + switch(InState) + { + case ENpcState::Doubt: case ENpcState::Guard: + { + NewIndicatorState = ENpcIndicatorState::Question; + break; + } + case ENpcState::Chase: case ENpcState::Attack: + { + NewIndicatorState = ENpcIndicatorState::Exclamation; + break; + } + case ENpcState::Default: case ENpcState::Returning: case ENpcState::Hit: case ENpcState::Dead: + break; + default: NMT_LOG("Not Valid Type") + } + + if(NewIndicatorState != LastIndicatorState) + { + LastIndicatorState = NewIndicatorState; + OnNpcIndicatorChanged.Broadcast(NewIndicatorState); + } +} + +void ACoreNpc::ChangeToChaseInDoubtGauge() +{ + GetAIControllerBase()->UpdateReturnLocation(GetActorLocation()); + ChangeNpcState(ENpcState::Chase); + ApplyStateToQuest(ENpcState::Chase); +} + +void ACoreNpc::DebugToggleFrustum() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(UpdateActiveComponentHandle.IsValid()) + { + if(CCM->GetDebugStatus().bDebugVision) + { + World->GetTimerManager().PauseTimer(UpdateActiveComponentHandle); + VisionConeComponent->ToggleDraw(true); + } + else + { + VisionConeComponent->ToggleDraw(false); + World->GetTimerManager().UnPauseTimer(UpdateActiveComponentHandle); + } + } +} + +class AAIControllerBase* ACoreNpc::GetAIControllerBase() const +{ + AAIControllerBase* AIC = Cast(GetController()); + NMT_CHECKF(AIC) + + return AIC; +} + +bool ACoreNpc::CanDetectTargetFromNoise() const +{ + return !bUnDetect && !GetNpcStatusComponent()->IsDead() && !GetAIControllerBase()->GetTargetActor() && CurrentState != ENpcState::Attack; +} + +void ACoreNpc::ApplyStateToQuest(const ENpcState InState) +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* GM = UGlobalUtilsLibrary::GetGameModeChecked(World); + UQuestManager* QM = IWorldObjectProvider::Execute_GetQuestManager(GM); + NMT_CHECKF(QM); + + switch(InState) + { + case ENpcState::Chase: + { + NMT_LOG("Avoid") + QM->CheckObjectiveSatisfied(EObjectiveSubTypes::Avoid); + break; + } + case ENpcState::Dead: + { + QM->CheckObjectiveSatisfied(EObjectiveSubTypes::Kill); + break; + } + case ENpcState::Guard: + case ENpcState::Hit: + case ENpcState::Attack: + case ENpcState::Default: + case ENpcState::Returning: + case ENpcState::Doubt: + default: NOT_IMPLEMENTED(); break; + } +} + +void ACoreNpc::Alert(const FVector& InTargetLocation) +{ + if(!bCanTriggerAlert || GetNpcStatusComponent()->IsDead()) + return; + + NMT_CHECKF(NpcStatusComponent) + NMT_LOG("Alert") + + bCanTriggerAlert = false; + AlertComponent->ActivateFiltering(); + + TArray DetectedNpcs = AlertComponent->GetNonBlockedActors(InTargetLocation); + for(AActor* Npc : DetectedNpcs) + { + ACoreNpc* OtherNpc = Cast(Npc); + if(!OtherNpc) + continue; + + OtherNpc->SetDetectLocationFromNoise(InTargetLocation); + } + + NoiseFXComponent->SetFloatParameter(FName("Wave Radius"), NpcStatusComponent->GetStatusNpcNoise()); + NoiseFXComponent->Activate(true); + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().SetTimer(CompleteAlertTimerHandle, this, &ACoreNpc::PostAlert, 0.5f, false); +} + +void ACoreNpc::SetDetectTargetFromNoise(AActor* InTarget) +{ + if(!CanDetectTargetFromNoise()) + return; + + GetAIControllerBase()->UpdateTargetInfo(InTarget); + HandleForceDetectFromNoise(true); + + NMT_LOG("SetDetectTargetFromNoise") +} + +void ACoreNpc::SetDetectLocationFromNoise(const FVector& InTargetLocation) +{ + if(!CanDetectTargetFromNoise()) + return; + + GetAIControllerBase()->UpdateTargetLocation(InTargetLocation); + GetAIControllerBase()->UpdateTargetDirection((InTargetLocation - GetActorLocation()).GetSafeNormal()); + HandleForceDetectFromNoise(false); + + NMT_LOG("SetDetectLocationFromNoise") +} + +void ACoreNpc::UpdateDoubtVisualize(const float InCurrentDoubtTime) +{ + double GaugeLength = UKismetMathLibrary::MapRangeClamped(InCurrentDoubtTime, 0.f, NpcStatusComponent->GetStatusPreviousNpcDoubtTime(), 20.f, NpcStatusComponent->GetStatusNpcSightLength()); + VisionConeComponent->UpdateVisionGauge(GaugeLength); + + AActor* Target = GetAIControllerBase()->GetTargetActor(); + if(!Target) + return; + + if(GaugeLength >= GetHorizontalDistanceTo(Target)) + { + ChangeToChaseInDoubtGauge(); + } +} + +void ACoreNpc::UpdateDoubtTime(const float InCurrentDoubtTime) +{ + NMT_CHECKF(NpcStatusComponent) + NpcStatusComponent->UpdateCurrentDoubtTime(FMath::Clamp(InCurrentDoubtTime, 0.f, NpcStatusComponent->GetPreviousNpcStatus().fDoubtTime)); + UpdateDoubtVisualize(InCurrentDoubtTime); +} + +void ACoreNpc::ChangeDoubtState(const EDoubtState InDoubtState) +{ + CurrentDoubtState = InDoubtState; + GetAIControllerBase()->UpdateDoubtState(InDoubtState); + + switch(InDoubtState) + { + case EDoubtState::None: + { + UpdateDoubtTime(0.f); + UpdateDoubtVisualize(0.f); + + break; + } + case EDoubtState::Increasing: case EDoubtState::Decreasing: break; + default: NOT_IMPLEMENTED(); + } +} + +void ACoreNpc::SetHeadTargetRotation(const FVector& InTargetLocation) +{ + NMT_CHECKF(NpcStatusComponent) + FVector EyeLocation = GetMesh()->GetSocketLocation(EyeSocketName); + FRotator EyeRotation = GetMesh()->GetSocketRotation(EyeSocketName); + FRotator WorldLookRotator = UKismetMathLibrary::FindLookAtRotation(EyeLocation, InTargetLocation); + FRotator CompLookRotator = WorldLookRotator - EyeRotation; + + float TargetYaw = FMath::Clamp(NpcAnimInstance->ForwardHeadRotation.Yaw + CompLookRotator.Yaw, NpcAnimInstance->ForwardHeadRotation.Yaw - NpcStatusComponent->GetStatusNpcHalfRotationAngle(), NpcAnimInstance->ForwardHeadRotation.Yaw + NpcStatusComponent->GetStatusNpcHalfRotationAngle()); + HeadRotationInfo.TargetRotation = FRotator(NpcAnimInstance->ForwardHeadRotation.Pitch, TargetYaw, NpcAnimInstance->ForwardHeadRotation.Roll); +} + +TArray ACoreNpc::GetCurrentEffects() const +{ + TArray LocReturnCurrentEffects; + EffectTimeMap.GetKeys(LocReturnCurrentEffects); + if(LocReturnCurrentEffects.Num() > 0) + return LocReturnCurrentEffects; + + LocReturnCurrentEffects.Add(EEffectSubTypes::None); + return LocReturnCurrentEffects; +} + +void ACoreNpc::HandleForceDetectFromNoise(const bool InbDetectTarget) +{ + bCanTriggerAlert = false; + SetReturnLocationFromDefault(); + if(!IsDamagedState(CurrentState)) + { + ChangeNpcState(ENpcState::Chase); + if(InbDetectTarget && (PrevState != ENpcState::Attack && PrevState != ENpcState::Hit)) + { + ApplyStateToQuest(ENpcState::Chase); + } + } +} + +void ACoreNpc::ChangeNpcState(const ENpcState InState) +{ + PrevState = CurrentState; + if(CurrentState != InState) + { + switch(InState) + { + case ENpcState::Guard: + { + bCanTriggerAlert = true; + break; + } + case ENpcState::Chase: case ENpcState::Attack: case ENpcState::Default: case ENpcState::Doubt: case ENpcState::Returning: case ENpcState::Hit: case ENpcState::Dead: + break; + default: NMT_LOG("Not Valid ENpcState"); + } + + CurrentState = InState; + GetAIControllerBase()->ChangeNpcStateKey(InState); + } +} + +void ACoreNpc::StartDisableNpc() +{ + OnNpcDead.Broadcast(); + SetActorEnableCollision(false); + GetCharacterMovement()->SetMovementMode(MOVE_None); + GetAIControllerBase()->StopAI("Death"); + + NMT_LOG("DisableNpc") +} + +void ACoreNpc::CompleteDisableNpc() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + SetActorHiddenInGame(true); + SetActorTickEnabled(false); + SetActorLocation(DefaultLocation); + SetActorRotation(DefaultRotation); + ChangeDoubtState(EDoubtState::None); + LastIndicatorState = ENpcIndicatorState::None; + + if(bEnableRespawn) + { + World->GetTimerManager().SetTimer(RespawnTimerHandle, this, &ACoreNpc::Respawn, RespawnTime, false); + } +} + +void ACoreNpc::ResetStateAfterGameEnd() +{ + if(!bActivate) + return; + + AAIControllerBase* AIC = GetAIControllerBase(); + if(AIC->GetTargetActor()) + AIC->UpdateTargetInfo(nullptr); + + ChangeNpcState(ENpcState::Default); + ChangeDoubtState(EDoubtState::None); + NpcStatusComponent->ReInitializeStatus(); + LastIndicatorState = ENpcIndicatorState::None; + AIC->StopAI("Ending", false); + SetActorTickEnabled(false); +} + +void ACoreNpc::ActivateCharacter(const bool InbEnable) +{ + SetActorTickEnabled(InbEnable); + SetActorHiddenInGame(!InbEnable); + + TArray Components; + GetComponents(Components); + + for (USceneComponent* Component : Components) + { + Component->SetComponentTickEnabled(InbEnable); + } + + if(InbEnable) + { + bFrustumCullingTimerSet = false; + GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics); + GetAIControllerBase()->ActivateBehaviorTree(this); + } + else + { + GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision); + } + + bActivate = InbEnable; +} + +void ACoreNpc::SetSpringArmRotation() +{ + if(!bUseSocketTransformForVision) + return; + + FRotator ArmRotator = SpringArmComponent->GetComponentRotation(); + SpringArmComponent->SetWorldRotation(UKismetMathLibrary::MakeRotator(ArmRotator.Roll, ArmRotator.Pitch, GetMesh()->GetSocketRotation(EyeSocketName).Yaw)); +} + +void ACoreNpc::SetVisionMode(EVisionMode InSightMode) +{ + NOT_IMPLEMENTED() +} + +void ACoreNpc::UpdateActiveComponentInFrustum() const +{ + APlayerController* PC = UGameplayStatics::GetPlayerController(this, 0); + NMT_CHECKF(PC) + + if(ULocalPlayer* LocalPlayer = PC->GetLocalPlayer()) + { + FSceneViewProjectionData ProjectionData; + if(LocalPlayer->GetProjectionData(LocalPlayer->ViewportClient->Viewport, ProjectionData)) + { + const FMatrix ViewProjectionMatrix = ProjectionData.ComputeViewProjectionMatrix(); + + FConvexVolume Frustum; + GetViewFrustumBounds(Frustum, ViewProjectionMatrix, true); + bool bInFrustum = Frustum.IntersectSphere(RootComponent->GetComponentLocation(), VisionConeComponent->SightRange); + bool bDoNotDraw = IsDamagedState(CurrentState) || bUnDetect; + bDoNotDraw |= IsAggressiveState(CurrentState); + + if(VisionConeComponent->IsAllowedDrawing()) + VisionConeComponent->ToggleDraw(bInFrustum && !bDoNotDraw); + } + } +} + +class USPNpcStatusComponent* ACoreNpc::GetNpcStatusComponent() const +{ + NMT_CHECKF(NpcStatusComponent) + return NpcStatusComponent; +} + +#if WITH_EDITOR +void ACoreNpc::ApplyCharacterData(const FTableRowBase* RowData) +{ + if(!GEditor) return; + if(!RowData) + { + UE_LOG(LogTemp, Error, TEXT("RowName Is Not Valid")) + InitializeStatus(FEnemyNpc()); + return; + } + + const FEnemyNpc* GetData = static_cast(RowData); + NMT_CHECKF(GetData) + if(*GetData == NpcStatusComponent->GetCurrentNpcStatus()) return; + if(GEditor->GetEditorWorldContext().World()) + InitializeStatus(*GetData); +} +#endif diff --git a/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.h b/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.h new file mode 100644 index 0000000..020c8e4 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/NPC/CoreNpc.h @@ -0,0 +1,282 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "ProjectT/Data/Gen/GenerateStructEnemyNPC.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "ProjectT/System/Core/Characters/CombatCharacter.h" +#include "ProjectT/System/Core/Interfaces/Damageable.h" +#include "ProjectT/System/Core/Interfaces/PoolableActor.h" +#include "CoreNpc.generated.h" + +struct FEnemyNpc; + +UENUM(BlueprintType) +enum class EHeadRotationPhase : uint8 +{ + TurnForward = 0 UMETA(DisplayName = "TurnForward"), + TurnRight UMETA(DisplayName = "TurnRight"), + TurnLeft UMETA(DisplayName = "TurnLeft"), +}; + +UENUM(BlueprintType) +enum class ENpcIndicatorState : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Hide UMETA(DisplayName = "Hide"), + Question UMETA(DisplayName = "Question"), + Exclamation UMETA(DisplayName = "Exclamation"), +}; + +USTRUCT(BlueprintType) +struct FHeadRotationInfo +{ + GENERATED_BODY() + + FHeadRotationInfo() : + bOverrideHeadRotation(false), + bChangeAlpha(false), + TargetRotation(FRotator::ZeroRotator), + HeadRotationType(EHeadRotationType::None), + CurrentPhaseIdx(0), + RotationSpeed(0.f), + RotationHalfAngle(0.f), + TargetAlpha(0.f) + {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + uint8 bOverrideHeadRotation : 1; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + uint8 bChangeAlpha; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + FRotator TargetRotation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + EHeadRotationType HeadRotationType; + + UPROPERTY(BlueprintReadOnly) + int32 CurrentPhaseIdx; + + UPROPERTY(BlueprintReadOnly) + float RotationSpeed; + + UPROPERTY(BlueprintReadOnly) + float RotationHalfAngle; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + float TargetAlpha; + +}; + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnNpcDead); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnNpcRespawn); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNpcIndicatorChanged, ENpcIndicatorState, IndicatorState); +UCLASS() +class PROJECTT_API ACoreNpc : public ACombatCharacter, public IPoolableActor, public IDamageable +{ + GENERATED_BODY() + CONTENT_TYPE_NUMBER(EContentType::EnemyNpc) + +public: + ACoreNpc(); + + virtual void OnConstruction(const FTransform& Transform) override; + virtual void Tick(float DeltaTime) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void GetActorEyesViewPoint( FVector& Location, FRotator& Rotation) const override; + virtual void PostInitializeComponents() override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void GetCurrentEffectTypes_Implementation(TArray& OutEffectSubTypes) override; + virtual void CompleteDisableNpc(); + virtual void ActivateCharacter(const bool InbEnable); + virtual void SetDetectTargetFromNoise(AActor* InTarget); + virtual void SetDetectLocationFromNoise(const FVector& InTargetLocation); + virtual void SetVisionMode(EVisionMode InSightMode); + virtual void UpdateDoubtTime(const float InCurrentDoubtTime); + virtual void ChangeDoubtState(const EDoubtState InDoubtState); + void UpdateDoubtVisualize(const float InCurrentDoubtTime); + + UFUNCTION(BlueprintCallable) + virtual void StartDisableNpc(); + + UFUNCTION(BlueprintCallable) + class USPNpcStatusComponent* GetNpcStatusComponent() const; + + UFUNCTION(BlueprintPure) + FORCEINLINE ENpcState GetNpcState() const { return CurrentState; } + + UFUNCTION(BlueprintPure) + FORCEINLINE ENpcState GetNpcPrevState() const { return PrevState; } + + UFUNCTION(BlueprintPure) + FORCEINLINE FVector GetRespawnLocation() const { return DefaultLocation; } + + UFUNCTION(BlueprintCallable) + void ChangeHeadRotationState(const EHeadRotationType InHeadRotationType); + + UFUNCTION(BlueprintCallable) + virtual void ChangeNpcState(const ENpcState InState); + + FORCEINLINE bool GetCanTriggerAlert() const { return bCanTriggerAlert; } + FORCEINLINE bool GetActivatedOnStart() { return bActivatedOnStart; } + FORCEINLINE void SetActivatedOnStart(bool InbActivate) { bActivatedOnStart = InbActivate; } + FORCEINLINE EDoubtState GetCurrentDoubtState() const { return CurrentDoubtState; } + FORCEINLINE EVisionMode GetCurrentVisionMode() const { return CurrentVisionMode; } + FORCEINLINE EHeadRotationType GetHeadRotationType() const { return HeadRotationInfo.HeadRotationType; } + + void UpdateActiveComponentInFrustum() const; + void SetCanTriggerAlert(const bool InbCanTrigger) { bCanTriggerAlert = InbCanTrigger; } + void SetHeadRotationEnable(const bool InbEnable); + bool IsAggressiveState(const ENpcState InState) const; + bool IsDamagedState(const ENpcState InState) const; + void Alert(const FVector& InTargetLocation); + void HandleForceDetectFromNoise(const bool InbDetectTarget); + FEnemyNpc GetCurrentNpcStatus() const; + class AAIControllerBase* GetAIControllerBase() const; + bool CanDetectTargetFromNoise() const; + void ApplyStateToQuest(const ENpcState InState); + void ChangeToChaseInDoubtGauge(); + void DebugToggleFrustum(); + void SetHeadTargetRotation(const FVector& InTargetLocation); + TArray GetCurrentEffects() const; + +protected: + virtual void BeginPlay() override; + +#if WITH_EDITOR + virtual void ApplyCharacterData(const FTableRowBase* RowData) override; +#endif + + virtual void InitializeStatus(const FEnemyNpc InNpcStatus); + virtual void InitializeProperty(); + virtual void InitializeEvents(); + virtual void Respawn() override; + virtual void ResetStateAfterGameEnd(); + virtual void SetSpringArmRotation(); + virtual void SetUnDetectTarget(const bool InbUnDetect); + virtual void ChangeIndicatorState(const ENpcState InState); + void SetupHeadRotationPattern(); + void UpdateHeadRotation(float InDeltaTime); + void UpdateHeadRotationAlpha(float InDeltaTime); + void ResetHeadRotation(); + void PostAlert() const; + bool CheckEffectTime(const FEffect& InEffect); + void AddEffectTimeMap(const FEffect& InEffect); + void EffectTimeDown(); + void SetReturnLocationFromDefault() const; + +public: + UPROPERTY(BlueprintAssignable) + FOnNpcDead OnNpcDead; + + UPROPERTY(BlueprintAssignable) + FOnNpcRespawn OnNpcRespawn; + + UPROPERTY(BlueprintAssignable) + FOnNpcIndicatorChanged OnNpcIndicatorChanged; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FVector DefaultLocation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FRotator DefaultRotation; + + uint8 bReachedHeadRotation : 1; + uint8 bCanRotateHeadToTarget : 1; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AISetting") + uint8 bEnableRespawn : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AISetting", meta = (EditCondition = "bEnableRespawn", EditConditionHides)) + float RespawnTime; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AISetting") + TObjectPtr BehaviorTree; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AISetting") + TObjectPtr Blackboard; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr SubRootComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr WidgetRootComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr SpringArmComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr VisionHead; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr VisionConeComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component") + TObjectPtr NpcStatusComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component") + TObjectPtr AlertComponent; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Animation") + FHeadRotationInfo HeadRotationInfo; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr NoiseFXComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component", meta = (AllowPrivateAccess = "true")) + ENpcState CurrentState; + + UPROPERTY(EditAnywhere) + float PerceptionMaxAge; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + ENpcIndicatorState LastIndicatorState; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TMap EffectTimeMap; + + UPROPERTY() + TObjectPtr NpcAnimInstance; + + UPROPERTY() + TArray CurrentPhaseLists; + + UPROPERTY() + FTimerHandle UpdateActiveComponentHandle; + + UPROPERTY() + FTimerHandle RespawnTimerHandle; + + UPROPERTY() + FTimerHandle EffectTimerHandle; + + UPROPERTY() + FTimerHandle CompleteAlertTimerHandle; + + UPROPERTY() + uint8 bActivatedOnStart : 1; + + ENpcState PrevState; + EDoubtState CurrentDoubtState; + EVisionMode CurrentVisionMode; + FName EyeSocketName; + FName AlertSphereProfileName; + TMap> HeadRotationPatterns; + float LoseSightOffset; + float HeadRotSpeedMultiplier; + uint8 bCanTriggerAlert : 1; + uint8 bUnDetect : 1; + uint8 bFrustumCullingTimerSet : 1; + uint8 bActivate : 1; + uint8 bUseSocketTransformForVision : 1; + +}; diff --git a/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.cpp b/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.cpp new file mode 100644 index 0000000..9602a34 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.cpp @@ -0,0 +1,149 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PlayerCharacterAnimInstance.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" + +UPlayerCharacterAnimInstance::UPlayerCharacterAnimInstance() : + OwnerPlayerCharacter(nullptr), + bPlayerInputable(true), + bIdle(true), + bRest(false), + bWalk(false), + bRun(false), + bAction(false), + bModify(false), + PlayerActionMontage(nullptr), + PlayerCommonMontage(nullptr), + PlayerIdleAnimation(nullptr), + PlayerMoveAnimation(nullptr), + PlayerRunAnimation(nullptr), + ModifyIdleAnimation(nullptr), + ModifyMoveAnimation(nullptr), + ModifyRunAnimation(nullptr), + NonInputAnimState(ENonInputAnimState::None) +{ +} + +void UPlayerCharacterAnimInstance::SetDefaultProperty(AActor* InOwner) +{ + ACorePlayerCharacter* LocOwnerCharacter = Cast(InOwner); + if(!LocOwnerCharacter) return; + OwnerPlayerCharacter = LocOwnerCharacter; + UAnimMontage* LocPlayerActionMontage; + OwnerPlayerCharacter->GetActionMontage(LocPlayerActionMontage); + SetActionMontage(LocPlayerActionMontage); + TObjectPtr LocSetSequence = nullptr; + OwnerPlayerCharacter->GetIdleAnimSequence(LocSetSequence); + if(LocSetSequence) PlayerIdleAnimation = LocSetSequence; + OwnerPlayerCharacter->GetRestAnimSequence(LocSetSequence); + if(LocSetSequence) PlayerRestAnimation = LocSetSequence; + OwnerPlayerCharacter->GetMoveAnimSequence(LocSetSequence); + if(LocSetSequence) PlayerMoveAnimation = LocSetSequence; + OwnerPlayerCharacter->GetRunAnimSequence(LocSetSequence); + if(LocSetSequence) PlayerRunAnimation = LocSetSequence; +} + +void UPlayerCharacterAnimInstance::SetModifyAnimation(const TObjectPtr& InIdleSequence, const TObjectPtr& InMoveSequence, const TObjectPtr& InRunSequence) +{ + InIdleSequence? ModifyIdleAnimation = InIdleSequence : ModifyIdleAnimation = PlayerIdleAnimation; + InMoveSequence? ModifyMoveAnimation = InMoveSequence : ModifyMoveAnimation = PlayerMoveAnimation; + InRunSequence? ModifyRunAnimation = InRunSequence : ModifyRunAnimation = PlayerRunAnimation; +} + +void UPlayerCharacterAnimInstance::SetActionMontage(UAnimMontage* InSetActionMontage) +{ + if(InSetActionMontage) PlayerActionMontage = InSetActionMontage; +} + +void UPlayerCharacterAnimInstance::SetNonInputAnimState(ENonInputAnimState InSetState) +{ + OwnerPlayerCharacter->SetInputable(false); + bool LocbChangeState = true; + switch(InSetState) + { + case ENonInputAnimState::Tired: + { + LocbChangeState = false; + NonInputAnimState = InSetState; + OwnerPlayerCharacter->SetInputable(true); + break; + } + case ENonInputAnimState::HitBack: + { + LocbChangeState = !(NonInputAnimState == ENonInputAnimState::JumpBackStart || + NonInputAnimState == ENonInputAnimState::JumpBackLoop || + NonInputAnimState == ENonInputAnimState::JumpBackEnd || + NonInputAnimState == ENonInputAnimState::GetUp || + NonInputAnimState == ENonInputAnimState::Dead); + break; + } + case ENonInputAnimState::JumpBackStart: + { + LocbChangeState = !(NonInputAnimState == ENonInputAnimState::JumpBackStart || + NonInputAnimState == ENonInputAnimState::JumpBackLoop || + NonInputAnimState == ENonInputAnimState::JumpBackEnd || + NonInputAnimState == ENonInputAnimState::GetUp || + NonInputAnimState == ENonInputAnimState::Dead); + break; + } + case ENonInputAnimState::JumpBackLoop: break; + case ENonInputAnimState::JumpBackEnd: break; + case ENonInputAnimState::GetUp: break; + case ENonInputAnimState::Stun: break; + case ENonInputAnimState::Dead: break; + case ENonInputAnimState::Defeat: break; + case ENonInputAnimState::Victory: break; + default: NMT_LOG("Non Input Anim state Invalid"); break; + } + if(LocbChangeState) + { + bPlayerInputable = false; + NonInputAnimState = InSetState; + } +} + +void UPlayerCharacterAnimInstance::StateChangeTest() +{ +} + +void UPlayerCharacterAnimInstance::NonInputAnimFinished() +{ + switch(NonInputAnimState) + { + case ENonInputAnimState::Tired: + { + NonInputAnimState = ENonInputAnimState::None; + break; + } + case ENonInputAnimState::HitBack: + { + OwnerPlayerCharacter->SetInputable(true); + bPlayerInputable = true; + NonInputAnimState = ENonInputAnimState::None; + break; + } + case ENonInputAnimState::JumpBackStart: break; + case ENonInputAnimState::JumpBackLoop: break; + case ENonInputAnimState::JumpBackEnd: + { + SetNonInputAnimState(ENonInputAnimState::GetUp); + break; + } + case ENonInputAnimState::GetUp: + { + bPlayerInputable = true; + NonInputAnimState = ENonInputAnimState::None; + OwnerPlayerCharacter->SetInputable(true); + OwnerPlayerCharacter->SetInvincible(false); + break; + } + case ENonInputAnimState::Stun: break; + case ENonInputAnimState::Dead: break; + case ENonInputAnimState::Defeat: break; + case ENonInputAnimState::Victory: break; + default: NMT_LOG("Non Input Anim state Invalid"); break; + } +} diff --git a/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h b/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h new file mode 100644 index 0000000..5972ff2 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h @@ -0,0 +1,107 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimInstance.h" +#include "PlayerCharacterAnimInstance.generated.h" +UENUM(BlueprintType) +enum class ENonInputAnimState: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Tired UMETA(DisplayName = "Tired"), + HitBack UMETA(DisplayName = "HitBack"), + JumpBackStart UMETA(DisplayName = "JumpBackStart"), + JumpBackLoop UMETA(DisplayName = "JumpBackLoop"), + JumpBackEnd UMETA(DisplayName = "JumpBackEnd"), + GetUp UMETA(DisplayName = "GetUp"), + Stun UMETA(DisplayName = "Stun"), + Dead UMETA(DisplayName = "Dead"), + Defeat UMETA(DisplayName = "Defeat"), + Victory UMETA(DisplayName = "Victory") +}; + +UCLASS() +class PROJECTT_API UPlayerCharacterAnimInstance : public UAnimInstance +{ + GENERATED_BODY() + +public: + UPlayerCharacterAnimInstance(); + void SetDefaultProperty(AActor* InOwner); + void SetActionState(const bool InbActivate) { bAction = InbActivate; } + void SetModifyState(const bool InbModify) { bModify = InbModify; } + void NonInputAnimFinished(); + void GetCommonMontage(UAnimMontage*& OutCommonMontage) const { OutCommonMontage = PlayerCommonMontage; } + void SetModifyAnimation(const TObjectPtr& InIdleSequence = nullptr, const TObjectPtr& InMoveSequence = nullptr, + const TObjectPtr& InRunSequence = nullptr); + ENonInputAnimState GetCurrentNonInputState() { return NonInputAnimState; } + + FORCEINLINE ENonInputAnimState GetCurrentNonInputState() const { return NonInputAnimState; } + + + UFUNCTION(BlueprintCallable) + void SetActionMontage(UAnimMontage* InSetActionMontage); + + UFUNCTION(BlueprintCallable) + void SetNonInputAnimState(ENonInputAnimState InSetState); + + UFUNCTION(BlueprintCallable) + void StateChangeTest(); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + class ACorePlayerCharacter* OwnerPlayerCharacter; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bPlayerInputable; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bIdle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bRest; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bWalk; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bRun; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bAction; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + bool bModify; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerActionMontage; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerCommonMontage; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerIdleAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerRestAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerMoveAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr PlayerRunAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr ModifyIdleAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr ModifyMoveAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr ModifyRunAnimation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + ENonInputAnimState NonInputAnimState; +}; diff --git a/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.cpp b/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.cpp new file mode 100644 index 0000000..066c6ed --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.cpp @@ -0,0 +1,1881 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CorePlayerCharacter.h" + +#if WITH_EDITOR +#include "Subsystems/AssetEditorSubsystem.h" +#endif + +#include "GameFramework/CharacterMovementComponent.h" +#include "GameFramework/SpringArmComponent.h" +#include "EnhancedInputSubsystems.h" +#include "EnhancedInputComponent.h" +#include "Animations/AnimInstance/PlayerCharacterAnimInstance.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Components/CoreCameraComponent.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "InputMappingContext.h" +#include "NiagaraComponent.h" +#include "NiagaraSystem.h" +#include "Components/CapsuleComponent.h" +#include "Components/PoseableMeshComponent.h" +#include "Components/SphereComponent.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h" +#include "ProjectT/Data/Gen/GenerateEnumSkillTypes.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Components/PlayerInventoryComponent.h" +#include "ProjectT/System/Core/Components/PlayerStatusComponent.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Managers/PooledActorManager.h" +#include "ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h" +#include "ProjectT/System/Core/Characters/Skill/PyroAtk.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Objects/LevelObject/ItemObject.h" +#include "ProjectT/System/Core/Objects/LevelObject/LevelCastObject.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h" +#include "ProjectT/System/Core/GameModes/CorePlayerController.h" +#include "ProjectT/System/Core/Interfaces/MouseInteraction.h" +#include "ProjectT/System/Core/Mouse/Mouse.h" +#include "ProjectT/System/Core/Widget/CommonHUD.h" +// Temp Only KeyBoard State +#define ONLY_KEYBOARD 1 + +ACorePlayerCharacter::ACorePlayerCharacter() : + SkillRootScene(nullptr), + MovingActionForward(), + MouseCursorRotation(), + bInvincible(false), + bDead(false), + CalibrateYawValue(0.f), + RestTime(0.f), + ActionMontage(nullptr), + IdleAnimation(nullptr), + MoveAnimation(nullptr), + RunAnimation(nullptr), + PlayerStatusComponent(nullptr), + PlayerInventoryComponent(nullptr), + AudioListener(nullptr), + PlayerAnimInstance(nullptr), + TransformMeshComponent(nullptr), + InteractionAreaCollision(nullptr), + NoiseAreaCollision(nullptr), + SkillCalibrateAreaCollision(nullptr), + CameraBoom(nullptr), + CoreCameraComponent(nullptr), + DefaultMappingContext(nullptr), + RunFXComponent(nullptr), + NoiseFXComponent(nullptr), + CurrentUsingSkill(nullptr), + InteractableObject(nullptr), + AxisMoveSpeed(0.f), + CharacterMoveAxis(), + bInputAble(false), + bUnDetect(false), + CurrentSlotCursor(-1), + CorePlayerController(nullptr), + CurrentEnhancedInputComponent(nullptr), + bMovingAction(true), + MeleeAtkDecreaseSpeedRatio(0.f), + SkillDecreaseSpeedRatio(0.f), + bCalibrateSkill(true) +{ + PrimaryActorTick.bCanEverTick = true; + CameraBoom = CreateDefaultSubobject(TEXT("CameraBoom")); + CoreCameraComponent = CreateDefaultSubobject(TEXT("CoreCameraComponent")); + PlayerStatusComponent = CreateDefaultSubobject(TEXT("PlayerStatusComponent")); + PlayerInventoryComponent = CreateDefaultSubobject(TEXT("PlayerInventoryComponent")); + AudioListener = CreateDefaultSubobject(TEXT("SceneComponent")); + TransformMeshComponent = CreateDefaultSubobject(TEXT("TransformMeshComponent")); + InteractionAreaCollision = CreateDefaultSubobject(TEXT("InteractionAreaComponent")); + NoiseAreaCollision = CreateDefaultSubobject(TEXT("NoiseAreaComponent")); + SkillCalibrateAreaCollision = CreateDefaultSubobject(TEXT("SkillCalibrateAreaComponent")); + SkillRootScene = CreateDefaultSubobject(TEXT("SkillRootScene")); + RunFXComponent = CreateDefaultSubobject(TEXT("RunFXComponent")); + NoiseFXComponent = CreateDefaultSubobject(TEXT("NoiseFXComponent")); + NMT_CHECKF(CameraBoom && CoreCameraComponent && PlayerStatusComponent && PlayerInventoryComponent && AudioListener && InteractionAreaCollision && NoiseAreaCollision + && SkillCalibrateAreaCollision && SkillRootScene && RunFXComponent && NoiseFXComponent); + + bUseControllerRotationYaw = false; + GetCharacterMovement()->MaxStepHeight = 0.f; + GetCharacterMovement()->bOrientRotationToMovement = true; + GetCharacterMovement()->RotationRate = (FRotator(0, -1.f, 0)); + + GetCapsuleComponent()->SetCollisionProfileName(TEXT("Player")); + GetCapsuleComponent()->ComponentTags.Add("PlayerCapsule"); + + CameraBoom->SetupAttachment(RootComponent); + CameraBoom->TargetArmLength = 500.0f; + CameraBoom->bDoCollisionTest = false; + CameraBoom->SetRelativeRotation(FRotator(-55.f, 0, 0)); + + CoreCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); + + TransformMeshComponent->SetupAttachment(GetMesh()); + + InteractionAreaCollision->SetupAttachment(RootComponent); + InteractionAreaCollision->SetCollisionProfileName(TEXT("InteractionRange")); + InteractionAreaCollision->OnComponentBeginOverlap.AddDynamic(this, &ACorePlayerCharacter::InteractionAreaBeginOverlap); + InteractionAreaCollision->OnComponentEndOverlap.AddDynamic(this, &ACorePlayerCharacter::InteractionAreaEndOverlap); + + NoiseAreaCollision->SetupAttachment(RootComponent); + NoiseAreaCollision->SetCollisionProfileName(TEXT("SoundRange")); + NoiseAreaCollision->OnComponentBeginOverlap.AddDynamic(this, &ACorePlayerCharacter::NoiseAreaBeginOverlap); + NoiseAreaCollision->OnComponentEndOverlap.AddDynamic(this, &ACorePlayerCharacter::NoiseAreaEndOverlap); + + SkillCalibrateAreaCollision->SetupAttachment(RootComponent); + SkillCalibrateAreaCollision->SetCollisionProfileName(TEXT("InteractionRange")); + SkillCalibrateAreaCollision->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + + SkillRootScene->SetupAttachment(GetMesh()); + SkillRootScene->SetRelativeLocation(FVector(0.f, 0.f, 50.f)); + + RunFXComponent->SetupAttachment(GetMesh()); + RunFXComponent->bAutoActivate = false; + NoiseFXComponent->SetupAttachment(GetMesh()); + NoiseFXComponent->bAutoActivate = false; + + AudioListener->SetupAttachment(RootComponent); + AudioListener->SetUsingAbsoluteRotation(true); + AudioListener->SetWorldRotation(GetActorRotation()); + + //TODO : Load Relative Path From Table After Added + if(UNiagaraSystem* LocFindNoiseAsset = Cast(StaticLoadObject(UNiagaraSystem::StaticClass(),nullptr,TEXT("/Script/Niagara.NiagaraSystem'/Game/FX/NiagaraSystem/Common/NS_Common_SoundNoiseEffects.NS_Common_SoundNoiseEffects'")))) + NoiseFXComponent->SetAsset(LocFindNoiseAsset); + + SetupPlayerInputActions(); +} + +void ACorePlayerCharacter::PostLoad() +{ + Super::PostLoad(); + +#if WITH_EDITOR + if(CharacterRowName.IsNone()) return; + if(!CharacterRowName.ToString().IsNumeric()) return; + ApplyCharacterConfiguration(CharacterRowName); +#endif +} + +void ACorePlayerCharacter::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); + +#if WITH_EDITOR + if(!GEditor) return; + GEditor->GetEditorSubsystem()->OnAssetOpenedInEditor().AddLambda([this](UObject* Asset, IAssetEditorInstance*) + { + if(UBlueprint* Blueprint = Cast(Asset)) + { + if(!Blueprint->GeneratedClass->IsChildOf(ACorePlayerCharacter::StaticClass())) return; + + if(ACorePlayerCharacter* CDO = Cast(Blueprint->GeneratedClass->GetDefaultObject())) + { + CDO->Modify(); + CDO->ApplyCharacterConfiguration(CDO->CharacterRowName); + if(!CDO->MarkPackageDirty()) + NMT_LOG("Failed to modify ACorePlayerCharacter CDO"); + } + } + }); +#endif +} + +void ACorePlayerCharacter::BeginPlay() +{ + Super::BeginPlay(); + InitPlayerCharacter(); +} + +void ACorePlayerCharacter::InitPlayerCharacter() +{ + InitializeProperty(); + //FIXME : Edit After Appear Animation Added + //AppearPlayerCharacter(); +} + +void ACorePlayerCharacter::InitializeProperty() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + APlayerController* PC = UGameplayStatics::GetPlayerController(World, 0); + NMT_CHECKF(PC); + + ULocalPlayer* LocPlayer = Cast(PC->GetLocalPlayer()); + NMT_CHECKF(LocPlayer); + + UEnhancedInputLocalPlayerSubsystem* InputSystem = LocPlayer->GetSubsystem(); + NMT_CHECKF(InputSystem); + + InputSystem->AddMappingContext(DefaultMappingContext, 0); + + GetMesh()->SetUsingAbsoluteRotation(true); + + CorePlayerController = Cast(UGameplayStatics::GetPlayerController(World, 0)); + + PlayerAnimInstance = Cast(GetMesh()->GetAnimInstance()); + NMT_CHECKF(PlayerAnimInstance); + PlayerAnimInstance->SetDefaultProperty(this); + + CameraBoom->bInheritYaw = false; + CalibrateYawValue = GetActorRotation().Yaw; + CameraBoom->AddRelativeRotation(FRotator(0, CalibrateYawValue, 0)); + + NoiseAreaCollision->SetSphereRadius(PlayerStatusComponent->GetStatusCharMoveSound()); + GetCharacterMovement()->MaxWalkSpeed = PlayerStatusComponent->GetStatusCharMove(); +} + +void ACorePlayerCharacter::SetSkillClass() +{ + UDataTable* LocSkillDataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + TSubclassOf LocSkillClass; + FPlayerCharacter LocChracterData; + GetPlayerCharacterData(LocChracterData); + + FString LocSkillRowName = FString::FromInt(LocChracterData.iCharAttackId); + FSkill* LocSkillDataRow = LocSkillDataTable->FindRow(*LocSkillRowName, TEXT("Not Found FSkill")); + FString LocTempPath = LocSkillDataRow->sSkillBpPath; + if(!CHECK_FREE(LocTempPath)) + { + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(LocTempPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + + LocSkillClass = TSubclassOf(LoadedClass); + PlayerAtkSkillClass = LocSkillClass; + } + + LocSkillRowName = FString::FromInt(LocChracterData.iCharSkillId); + LocSkillDataRow = LocSkillDataTable->FindRow(*LocSkillRowName, TEXT("Not Found FSkill")); + LocTempPath = LocSkillDataRow->sSkillBpPath; + if(!CHECK_FREE(LocTempPath)) + { + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(LocTempPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + + LocSkillClass = TSubclassOf(LoadedClass); + PlayerSkillClass = LocSkillClass; + } +} + +void ACorePlayerCharacter::AxisMoveStarted() +{ + if(MeshRotateCalibrateTimerHandle.IsValid()) + { + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + MeshRotateCalibrateTimerHandle.Invalidate(); + } + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(World->GetTimerManager().IsTimerActive(RestTimerHandle)) + World->GetTimerManager().ClearTimer(RestTimerHandle); +} + +void ACorePlayerCharacter::AxisMoveTriggered(const FInputActionValue& Value) +{ + if(!bInputAble) return; + CharacterMoveAxis = Value.Get(); + RotateMeshAxisForward(true); + if(CharacterMoveAxis.Length() == 0) + { + ActivateNoiseFX(false); + ChangeValueOnRun(false); + PlayerAnimInstance->bIdle = true; + PlayerAnimInstance->bWalk = false; + SetDecreaseStaminaTimer(false); + return; + } + + PlayerAnimInstance->bIdle = false; + PlayerAnimInstance->bWalk = true; + const FVector2D LocNormalizeMoveAxis = UKismetMathLibrary::Normal2D(CharacterMoveAxis); + if(Controller != nullptr) + { + ActivateNoiseFX(true); + FVector2D LocSelectAxis; + ChangeValueOnRun(PlayerAnimInstance->bRun); + CharacterMoveAxis.Length() >= 1.f ? LocSelectAxis = LocNormalizeMoveAxis : LocSelectAxis = CharacterMoveAxis; + LocSelectAxis = LocSelectAxis.GetRotated(CalibrateYawValue); + AddMovementInput(FVector(LocSelectAxis.X, LocSelectAxis.Y, 0), 1); + SetDecreaseStaminaTimer(PlayerAnimInstance->bRun && !PlayerAnimInstance->bAction); + } +} + +void ACorePlayerCharacter::AxisMoveCompleted() +{ + ActivateNoiseFX(false); + CharacterMoveAxis = FVector2d(0.f, 0.f); + ChangeValueOnRun(false); + SetDecreaseStaminaTimer(false); + RotateMeshAxisForward(false); + PlayerAnimInstance->bIdle = true; + PlayerAnimInstance->bWalk = false; + RestTimerStart(); +} + +void ACorePlayerCharacter::RunTriggered(const FInputActionValue& Value) +{ + if(PlayerAnimInstance->GetCurrentNonInputState() == ENonInputAnimState::Tired || CurrentUsingSkill) + { + PlayerAnimInstance->bRun = false; + } + else + { + PlayerAnimInstance->bRun = Value.Get(); + } +} + +void ACorePlayerCharacter::RunCompleted() +{ + ChangeValueOnRun(false); + PlayerAnimInstance->bRun = false; +} + +void ACorePlayerCharacter::ChangeValueOnRun(bool InbRun) +{ + if((bMovingAction && PlayerAnimInstance->bAction) || CurrentUsingSkill) + { + GetCharacterMovement()->MaxWalkSpeed = PlayerStatusComponent->GetStatusCharMove(); + NoiseAreaCollision->SetSphereRadius(PlayerStatusComponent->GetStatusCharMoveSound()); + RunFXComponent->Deactivate(); + return; + } + if(InbRun) + { + GetCharacterMovement()->MaxWalkSpeed = PlayerStatusComponent->GetStatusCharRun(); + NoiseAreaCollision->SetSphereRadius(PlayerStatusComponent->GetStatusCharRunSound()); + RunFXComponent->Activate(false); + } + else + { + GetCharacterMovement()->MaxWalkSpeed = PlayerStatusComponent->GetStatusCharMove(); + NoiseAreaCollision->SetSphereRadius(PlayerStatusComponent->GetStatusCharMoveSound()); + RunFXComponent->Deactivate(); + } +} + +void ACorePlayerCharacter::ActivateMeleeAttack() +{ + if(CurrentUsingSkill) + { + if(CurrentUsingSkill.GetClass() == PlayerAtkSkillClass || !bInputAble) return; + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + if(CurrentUsingSkill.GetClass() == PlayerSkillClass) + { + if(!CurrentUsingSkill->GetActivated()) SetSkillState(EPlayerSkillState::Activate, LocSkillData); + } + else + { + SetItemSkillState(EPlayerSkillState::Activate, LocSkillData); + } + return; + } + if(!bInputAble || SkillCoolTimeMap.Contains(PlayerAtkSkillClass)) return; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + if(UPooledActorManager* LocPoolManager = IWorldObjectProvider::Execute_GetPooledActorManager(LocGameMode)) + { + CurrentUsingSkill = Cast(LocPoolManager->Obtain(PlayerAtkSkillClass)); + CurrentUsingSkill->SetSkillOwner(this); + FSkill LocMeleeAtkSkillData; + CurrentUsingSkill->GetSkillData(LocMeleeAtkSkillData); + SetMeleeAtkSkillState(EPlayerSkillState::Start,LocMeleeAtkSkillData); + } + SetDecreaseStaminaTimer(false); + ChangeValueOnRun(false); +} + +void ACorePlayerCharacter::ActivateSkill() +{ + if(CurrentUsingSkill) + { + if(PlayerSkillClass == CurrentUsingSkill->GetClass() && !SkillCoolTimeMap.Contains(PlayerSkillClass)) + { + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + SetSkillState(EPlayerSkillState::Release, LocSkillData); + } + return; + } + if(!bInputAble || SkillCoolTimeMap.Contains(PlayerSkillClass)) return; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + if(UPooledActorManager* LocPoolManager = IWorldObjectProvider::Execute_GetPooledActorManager(LocGameMode)) + { + CurrentUsingSkill = Cast(LocPoolManager->Obtain(PlayerSkillClass)); + CurrentUsingSkill->SetSkillOwner(this); + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + SetSkillState(EPlayerSkillState::Start, LocSkillData); + } + SetDecreaseStaminaTimer(false); + ChangeValueOnRun(false); +} + +void ACorePlayerCharacter::ActivateItemSkill(int InCurrentInput, int InItemSkillId) +{ + FString LocItemSkillRow = FString::FromInt(InItemSkillId); + UDataTable* LocDataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + FSkill* LocSkillDataRow = LocDataTable->FindRow(*LocItemSkillRow, TEXT("Not Found FSkill")); + if(!LocSkillDataRow) return; + + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(LocSkillDataRow->sSkillBpPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + if(!NMT_MSG_ENSURE(LoadedClass, "Skill Class Not Found : %s", *ClassPath)) return; + + TSubclassOf LocItemClass = TSubclassOf(LoadedClass); + if(CurrentUsingSkill) + { + if(InCurrentInput != CurrentSlotCursor) return; + if(LocItemClass == CurrentUsingSkill->GetClass()) + { + SetItemSkillState(EPlayerSkillState::Release); + if(ItemSlotActivate.IsBound()) ItemSlotActivate.Broadcast(CurrentSlotCursor, false); + CurrentSlotCursor = -1; + } + return; + } + if(PlayerAnimInstance->bAction) return; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + if(UPooledActorManager* LocPoolManager = IWorldObjectProvider::Execute_GetPooledActorManager(LocGameMode)) + { + CurrentUsingSkill = Cast(LocPoolManager->Obtain(LocItemClass)); + CurrentUsingSkill->SetSkillOwner(this); + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + CurrentSlotCursor = InCurrentInput; + if(ItemSlotActivate.IsBound()) ItemSlotActivate.Broadcast(CurrentSlotCursor, true); + ESkillTypes LocItemSkillType = UGlobalUtilsLibrary::GetStringToEnum(LocSkillData.sSkillType); + LocItemSkillType == ESkillTypes::Buff? SetItemSkillState(EPlayerSkillState::Activate, LocSkillData) : SetItemSkillState(EPlayerSkillState::Start, LocSkillData); + } + SetDecreaseStaminaTimer(false); +} + +void ACorePlayerCharacter::SetInputable(bool InbEnable) +{ + bInputAble = InbEnable; +} + +void ACorePlayerCharacter::SetInvincible(bool InbInvincible) +{ + bInvincible = InbInvincible; +} + +void ACorePlayerCharacter::StartCountDown_Implementation() +{ + NOT_IMPLEMENTED() +} + +void ACorePlayerCharacter::PlayActionMontage(FName InSectionName, FOnMontageEnded InEndedFunction, FOnMontageBlendingOutStarted InBlendOutFunction) const +{ + if(!ActionMontage) return; + PlayerAnimInstance->Montage_Play(ActionMontage, 1, EMontagePlayReturnType::MontageLength, 0, true); + FOnMontageEnded LocDefaultEndedDelegate; + FOnMontageBlendingOutStarted LocDefaultBlendingOutDelegate; + PlayerAnimInstance->Montage_SetEndDelegate(LocDefaultEndedDelegate, ActionMontage); + PlayerAnimInstance->Montage_SetBlendingOutDelegate(LocDefaultBlendingOutDelegate, ActionMontage); + PlayerAnimInstance->Montage_SetEndDelegate(InEndedFunction,ActionMontage); + PlayerAnimInstance->Montage_SetBlendingOutDelegate(InBlendOutFunction,ActionMontage); + PlayerAnimInstance->Montage_JumpToSection(InSectionName); + PlayerAnimInstance->bAction = true; +} + +void ACorePlayerCharacter::PlayCommonMontage(FName InSectionName, FOnMontageEnded InEndedFunction, FOnMontageBlendingOutStarted InBlendOutFunction) const +{ + UAnimMontage* LocCommonMontage; + PlayerAnimInstance->GetCommonMontage(LocCommonMontage); + if(LocCommonMontage) + { + FOnMontageEnded LocDefaultEndedDelegate; + FOnMontageBlendingOutStarted LocDefaultBlendingOutDelegate; + PlayerAnimInstance->Montage_Play(LocCommonMontage, 1, EMontagePlayReturnType::MontageLength, 0, true); + PlayerAnimInstance->Montage_SetEndDelegate(LocDefaultEndedDelegate, LocCommonMontage); + PlayerAnimInstance->Montage_SetBlendingOutDelegate(LocDefaultBlendingOutDelegate, LocCommonMontage); + + PlayerAnimInstance->Montage_SetEndDelegate(InEndedFunction); + PlayerAnimInstance->Montage_SetBlendingOutDelegate(InBlendOutFunction); + PlayerAnimInstance->Montage_JumpToSection(InSectionName); + PlayerAnimInstance->bAction = true; + } +} + +void ACorePlayerCharacter::StopActionMontage() const +{ + if(!ActionMontage) return; + if(PlayerAnimInstance->GetInstanceForMontage(ActionMontage)) + { + FAnimMontageInstance* LocMontageInstance = PlayerAnimInstance->GetInstanceForMontage(ActionMontage); + if(LocMontageInstance->OnMontageEnded.IsBound()) + { + LocMontageInstance->OnMontageEnded.Unbind(); + } + } + PlayerAnimInstance->Montage_Stop(0.f, ActionMontage); + PlayerAnimInstance->bAction = false; +} + +void ACorePlayerCharacter::SetCurrentSkill(bool InbSet, ACoreSkill* InSetSkill) +{ + InbSet ? CurrentUsingSkill = InSetSkill : CurrentUsingSkill = nullptr; +} + +void ACorePlayerCharacter::GetSkillClass(TSubclassOf& OutAtkSkillClass, TSubclassOf& OutSkillClass) const +{ + OutAtkSkillClass = PlayerAtkSkillClass; + OutSkillClass = PlayerSkillClass; +} + +void ACorePlayerCharacter::GetPlayerCharacterData(FPlayerCharacter& OutPlayerCharacterData) const +{ + OutPlayerCharacterData = PlayerStatusComponent->GetPreviousPlayerStatus(); + + TArray Actors; +} + + +void ACorePlayerCharacter::InteractionStarted() +{ + if(InteractableObject != nullptr) + { + SetInputable(false); + PlayerAnimInstance->bIdle = true; + PlayerAnimInstance->bWalk = false; + SetDecreaseStaminaTimer(false); + + EInteractionObjectType LocInteractionType = IObjectInteractionControl::Execute_GetInteractionObjectType(InteractableObject); + IObjectInteractionControl* LocInterface = Cast(InteractableObject); + switch(LocInteractionType) + { + case EInteractionObjectType::Item: + { + LocInterface->TryInteraction(FInteractionData(),FOnInteractionSuccess::CreateLambda([this](const EInteractionResultType InResultType) + { + if(InResultType == EInteractionResultType::SuccessComplete) + { + if(PlayerInventoryComponent->TryAddData(InteractableObject)) + { + IItemObjectControl::Execute_ObtainItem(InteractableObject); + } + InteractionCompleted(); + } + })); + break; + } + case EInteractionObjectType::LevelObject: + { + FInteractionData LocCurData; + TArray LocReserveRowNames; + PlayerInventoryComponent->GetReserveItemRowNames(LocReserveRowNames); + if(LocReserveRowNames.Num() <= 0) + { + InteractionCompleted(); + return; + } + LocCurData.RowNames = LocReserveRowNames; + LocInterface->TryInteraction(LocCurData, FOnInteractionSuccess::CreateLambda([this](const EInteractionResultType InResultType) + { + switch(InResultType) + { + case EInteractionResultType::Fail: + { + InteractionCompleted(); + break; + } + case EInteractionResultType::SuccessPre: + { + //TODO : GetCastId From Interface If Create Other Class(Type) + ALevelCastObject* LocTest = Cast(InteractableObject); + int LocMatchSlot; + PlayerInventoryComponent->GetMatchSlotNumber(*FString::FromInt(LocTest->GetCastItemID()),LocMatchSlot); + if(LocMatchSlot != -1) PlayerInventoryComponent->UseGimmickSlotItem(LocMatchSlot); + InteractionCompleted(); + break; + } + case EInteractionResultType::SuccessUpdate: break; + case EInteractionResultType::SuccessComplete: break; + default: NMT_LOG("Result Type None"); break; + } + })); + break; + } + case EInteractionObjectType::ObjectiveCharacter: + { + LocInterface->TryInteraction(FInteractionData(), FOnInteractionSuccess::CreateLambda([this](const EInteractionResultType InResultType) + { + switch(InResultType) + { + case EInteractionResultType::SuccessPre: + { + InteractionCompleted(); + break; + } + case EInteractionResultType::SuccessComplete: + { + //TODO : Complete Action Bind + SetInputable(true); + break; + } + default: NMT_LOG("Result Type None") break; + } + })); + break; + } + default: NMT_LOG("Interaction Type None"); + } + } +} + +void ACorePlayerCharacter::InteractionCompleted() +{ + SetInputable(true); + if(InteractableObject != nullptr) + { + IVisualizable::Execute_HideVisual(InteractableObject); + } + InteractableObject = nullptr; +} + +void ACorePlayerCharacter::UseItemSlot1() +{ + int LocItemSkillId; + PlayerInventoryComponent->UseSpendSlotItem(0, LocItemSkillId); + if(LocItemSkillId == -1) return; + ActivateItemSkill(0, LocItemSkillId); +} + +void ACorePlayerCharacter::UseItemSlot2() +{ + int LocItemSkillId; + PlayerInventoryComponent->UseSpendSlotItem(1, LocItemSkillId); + if(LocItemSkillId == -1) return; + ActivateItemSkill(1, LocItemSkillId); +} + +void ACorePlayerCharacter::UseItemSlot3() +{ + int LocItemSkillId; + PlayerInventoryComponent->UseSpendSlotItem(2, LocItemSkillId); + if(LocItemSkillId == -1) return; + ActivateItemSkill(2, LocItemSkillId); +} + +void ACorePlayerCharacter::ToggleGameMenu() +{ + ACorePlayerController* CPC = Cast(CorePlayerController); + NMT_CHECKF(CPC); + UCommonHUD* CHUD = Cast(CPC->GetCurrentCommonHUD()); + NMT_CHECKF(CHUD); + CHUD->ToggleGameMenuEvent(); +} + +void ACorePlayerCharacter::DebugToggleCheat(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleCheat(); +} + +void ACorePlayerCharacter::DebugToggleInvincible(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugTogglePlayerInvincibleHP(); +} + +void ACorePlayerCharacter::DebugTogglePlayerDamage(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugTogglePlayerDamage(); +} + +void ACorePlayerCharacter::DebugTogglePlayerSpeed(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugTogglePlayerSpeed(); +} + +void ACorePlayerCharacter::DebugToggleFrustum(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleVision(); +} + +void ACorePlayerCharacter::DebugToggleHitCollision(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleHitCollision(); +} + +void ACorePlayerCharacter::DebugToggleTimeStop(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleTimeStop(); +} + +void ACorePlayerCharacter::DebugToggleSlomo(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleSlomo(); +} + +void ACorePlayerCharacter::DebugCharacterSelect(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugToggleSlomo(); +} + +void ACorePlayerCharacter::DebugToggleSpectatorPawn(const FInputActionValue& InputActionValue) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + CCM->DebugSpectatorPlay(); +} + +void ACorePlayerCharacter::RespawnCharacter() +{ + //FIXME : camera fade and finish function Bind at gamemode + // CoreCameraComponent->StartFade(EFadeType::FadeOut,FOnStaticFinishCameraFade::CreateLambda([&] + // { + // if(PlayerDeadDone.IsBound()) PlayerDeadDone.Broadcast(); + // ResetCharacterData(); + // }),1.5f,0.1f); +} + +void ACorePlayerCharacter::ResetCharacterData() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + TArray LocSpawnPoints; + LocGameMode->GetPlayerSpawnPoints(LocSpawnPoints); + int LocSelectIndex = FMath::RandRange(0, LocSpawnPoints.Num() - 1); + SetActorLocation(LocSpawnPoints[LocSelectIndex]->GetActorLocation()); + PlayerStatusComponent->ResetStatusDefault(); + UNotificationCenter* LocNotiCenter = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(this)); + LocNotiCenter->Post(ENotificationTypes::GameState_Restarted); + AppearPlayerCharacter(); +} + +void ACorePlayerCharacter::AppearPlayerCharacter() +{ + if(bDead) + { + bDead = false; + } + PlayerAnimInstance->SetNonInputAnimState(ENonInputAnimState::GetUp); +} + +void ACorePlayerCharacter::SetSkillCoolTime(const TSubclassOf& InSkillClass, const FSkill& InSkillData) +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + if(CCM->GetDebugStatus().bDebugPlayerInvincibleSkill) + { + if(World->GetTimerManager().IsTimerActive(SkillCoolDownTimerHandle)) + World->GetTimerManager().ClearTimer(SkillCoolDownTimerHandle); + + SkillCoolTimeMap.Empty(); + return; + } + + if(!TSubclassOf(InSkillClass)) return; + TSubclassOf LocCastClass = TSubclassOf(InSkillClass); + FPlayerSimpleRatio LocSkillCoolTimeRatio; + LocSkillCoolTimeRatio.CurrentValue = InSkillData.fCooldown; + LocSkillCoolTimeRatio.MaxValue = InSkillData.fCooldown; + SkillCoolTimeMap.Add(LocCastClass, LocSkillCoolTimeRatio); + + if(!World->GetTimerManager().IsTimerActive(SkillCoolDownTimerHandle)) + World->GetTimerManager().SetTimer(SkillCoolDownTimerHandle, this, &ACorePlayerCharacter::SkillCoolTimeDown, World->DeltaTimeSeconds, true); +} + +void ACorePlayerCharacter::SetUnDetectState(bool InbUnDetect) +{ + bUnDetect = InbUnDetect; +} + +void ACorePlayerCharacter::SetSlotCursor(int InSetSlotCursor) +{ + CurrentSlotCursor = InSetSlotCursor; +} + +void ACorePlayerCharacter::GetAudioListener(USceneComponent*& OutAudioListener) +{ + OutAudioListener = AudioListener; +} + +void ACorePlayerCharacter::SkillCoolTimeDown() +{ + TArray> LocSkillClass; + SkillCoolTimeMap.GetKeys(LocSkillClass); + for(TSubclassOf LocKey : LocSkillClass) + { + float LocCurRemainTime = SkillCoolTimeMap.Find(LocKey)->CurrentValue; + LocCurRemainTime = LocCurRemainTime - GetWorld()->DeltaTimeSeconds; + if(LocCurRemainTime <= 0.f) + { + SkillCoolTimeMap.Remove(LocKey); + if(SkillCoolTimeMap.IsEmpty()) + { + GetWorld()->GetTimerManager().ClearTimer(SkillCoolDownTimerHandle); + SkillCoolDownTimerHandle.Invalidate(); + if(RefreshSkillCoolTime.IsBound()) RefreshSkillCoolTime.Broadcast(LocKey, 0.f, true); + } + } + else + { + SkillCoolTimeMap.Find(LocKey)->CurrentValue = LocCurRemainTime; + float LocCurRemainRatio = SkillCoolTimeMap.Find(LocKey)->CurrentValue / SkillCoolTimeMap.Find(LocKey)->MaxValue; + if(RefreshSkillCoolTime.IsBound()) RefreshSkillCoolTime.Broadcast(LocKey, LocCurRemainRatio, false); + } + } +} + +bool ACorePlayerCharacter::CheckEffectTime(const FEffect& InEffect) +{ + bool LocbRefreshEffect = false; + EEffectSubTypes LocEffectSubType = UGlobalUtilsLibrary::GetStringToEnum(InEffect.sEffect); + if(EffectTimeMap.Find(LocEffectSubType)) + { + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue > InEffect.fEffectValue) return LocbRefreshEffect; + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue == InEffect.fEffectValue) + { + if(EffectTimeMap.Find(LocEffectSubType)->RemainTime < InEffect.fEffectDuration) LocbRefreshEffect = true; + } + else LocbRefreshEffect = true; + } + else LocbRefreshEffect = true; + return LocbRefreshEffect; +} + +void ACorePlayerCharacter::AddEffectTimeMap(const FEffect& InEffect) +{ + FPlayerEffectValue LocEffectValue; + EEffectSubTypes LocEffectSubType = UGlobalUtilsLibrary::GetStringToEnum(InEffect.sEffect); + if(EffectTimeMap.Find(LocEffectSubType)) + { + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue > InEffect.fEffectValue) return; + if(EffectTimeMap.Find(LocEffectSubType)->EffectValue == InEffect.fEffectValue) + { + if(EffectTimeMap.Find(LocEffectSubType)->RemainTime < InEffect.fEffectDuration) + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + } + else + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + } + else + { + LocEffectValue.RemainTime = InEffect.fEffectDuration; + LocEffectValue.MaxTime = InEffect.fEffectDuration; + LocEffectValue.EffectValue = InEffect.fEffectValue; + EffectTimeMap.Add(LocEffectSubType, LocEffectValue); + } + if(!GetWorld()->GetTimerManager().IsTimerActive(EffectActiveTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(EffectActiveTimerHandle, this, &ACorePlayerCharacter::EffectTimeDown, GetWorld()->DeltaTimeSeconds, true); +} + +void ACorePlayerCharacter::EffectTimeDown() +{ + TArray LocEffectSubType; + EffectTimeMap.GetKeys(LocEffectSubType); + FEffect LocRemoveEffect; + for(EEffectSubTypes LocKey : LocEffectSubType) + { + float LocCurRemainTime = EffectTimeMap.Find(LocKey)->RemainTime; + LocCurRemainTime = LocCurRemainTime - GetWorld()->DeltaTimeSeconds; + if(LocCurRemainTime <= 0.f) + { + TArray LocRemoveEffects; + LocRemoveEffect.sEffect = EnumToString(LocKey); + LocRemoveEffect.fEffectValue = EffectTimeMap.Find(LocKey)->EffectValue; + LocRemoveEffects.Add(LocRemoveEffect); + ApplyRecoveryEvent_Implementation(LocRemoveEffects); + } + else + { + EffectTimeMap.Find(LocKey)->RemainTime = LocCurRemainTime; + float LocCurRemainRatio = LocCurRemainTime / EffectTimeMap.Find(LocKey)->MaxTime; + if(RefreshEffectTime.IsBound()) RefreshEffectTime.Broadcast(LocKey, LocCurRemainRatio, false); + } + } +} + +void ACorePlayerCharacter::PlayerJumpBack(AActor* InOccurActor) +{ + //TODO : Velocity From Ouucr Actor Edit + SetDecreaseStaminaTimer(false); + PlayerAnimInstance->SetNonInputAnimState(ENonInputAnimState::JumpBackStart); + float LocPower = 100.f; + FVector LocBackVector = LocPower * (GetActorForwardVector() * -1.f); + FVector LocLaunchVelocity; + UGlobalUtilsLibrary::SuggestProjectileVelocityAtLocation(GetWorld(), LocLaunchVelocity, GetActorLocation(), GetActorLocation() + LocBackVector, 30.f, 0.f, 1.f); + LaunchCharacter(LocLaunchVelocity, true, true); + if(!GetWorld()->GetTimerManager().IsTimerActive(JumpBackTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(JumpBackTimerHandle, this, &ACorePlayerCharacter::CheckPlayerFalling, GetWorld()->DeltaTimeSeconds, true); +} + +void ACorePlayerCharacter::CheckPlayerFalling() +{ + if(!GetMovementComponent()->IsFalling()) + { + GetWorld()->GetTimerManager().ClearTimer(JumpBackTimerHandle); + JumpBackTimerHandle.Invalidate(); + UPlayerCharacterAnimInstance* LocAnimInstance; + GetAnimInstance(LocAnimInstance); + LocAnimInstance->SetNonInputAnimState(ENonInputAnimState::JumpBackEnd); + } +} + +void ACorePlayerCharacter::ActivateNoiseFX(bool InActivate) +{ + if(InActivate) + { + if(!NoiseFXComponent->IsActive()) NoiseFXComponent->Activate(true); + float LocFXRadius = PlayerAnimInstance->bRun ? LocFXRadius = PlayerStatusComponent->GetStatusCharRunSound() * 2.f + : LocFXRadius = PlayerStatusComponent->GetStatusCharMoveSound() * 2.f; + NoiseFXComponent->SetFloatParameter(TEXT("Wave Radius"), LocFXRadius); + } + else + { + NoiseFXComponent->Deactivate(); + } +} + +void ACorePlayerCharacter::StatusSlow(float InSlowValue, bool InbRecovery) const +{ + float LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Slow)? LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Slow)->EffectValue : LocBeforeValue = 0.f; + if(LocBeforeValue == InSlowValue) return; + if(!InbRecovery) InSlowValue = InSlowValue * -1.f; + float LocSlowValue = InSlowValue - LocBeforeValue; + PlayerStatusComponent->AddStatusCharMove(LocSlowValue); + PlayerStatusComponent->AddStatusCharRun(LocSlowValue); +} + +void ACorePlayerCharacter::StatusFast(float InFastValue, bool InbRecovery) const +{ + float LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Fast)? LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Fast)->EffectValue : LocBeforeValue = 0.f; + if(LocBeforeValue == InFastValue) return; + if(InbRecovery) InFastValue = InFastValue * -1.f; + float LocFastValue = InFastValue - LocBeforeValue; + PlayerStatusComponent->AddStatusCharMove(LocFastValue); + PlayerStatusComponent->AddStatusCharRun(LocFastValue); +} + +void ACorePlayerCharacter::StartMouseCursorLinear(const bool InbStart, bool InbSustain) +{ + if(InbStart) + { + FSkill LocCurrentSkillData; + CurrentUsingSkill->GetSkillData(LocCurrentSkillData); + float LocRange = LocCurrentSkillData.fSkillRange != 0.f ? LocRange = LocCurrentSkillData.fSkillRange : LocRange = 0; + float LocAffectRange = LocCurrentSkillData.fEffectRange != 0.f ? LocAffectRange = LocCurrentSkillData.fEffectRange : LocAffectRange = 0; + TArray LocAffectActors; + LocAffectActors.Add(CurrentUsingSkill); + if(InbSustain) + { + CorePlayerController->MouseAimTracing(true, this, LocAffectActors, LocRange, LocAffectRange, EMouseResultType::Linear); + } + else + { + FHitResult LocHitResult = CorePlayerController->GetMouseCursorHitResult(this, LocAffectActors, LocRange, EMouseResultType::Linear); + IMouseInteraction::Execute_RefreshCursorHitResult(CurrentUsingSkill,LocHitResult); + } + } + else + { + TArray LocAffectActors; + CorePlayerController->MouseAimTracing(false, nullptr, LocAffectActors, 0.f, 0.f, EMouseResultType::None); + } +} + +void ACorePlayerCharacter::StartMouseCursorParabola(const bool InbStart, bool InbSustain, bool InbPathVisible) +{ + if(InbStart) + { + FSkill LocCurrentSkillData; + CurrentUsingSkill->GetSkillData(LocCurrentSkillData); + float LocRange = LocCurrentSkillData.fSkillRange != 0.f ? LocRange = LocCurrentSkillData.fSkillRange : LocRange = 0; + float LocAffectRange = LocCurrentSkillData.fEffectRange != 0.f ? LocAffectRange = LocCurrentSkillData.fEffectRange : LocAffectRange = 0; + TArray LocAffectActors; + LocAffectActors.Add(CurrentUsingSkill); + if(InbSustain) + { + CorePlayerController->MouseAimTracing(true, this, LocAffectActors, LocRange, LocAffectRange, EMouseResultType::Parabola, InbPathVisible); + } + else + { + FHitResult LocHitResult = CorePlayerController->GetMouseCursorHitResult(this, LocAffectActors, LocRange, EMouseResultType::Parabola); + IMouseInteraction::Execute_RefreshCursorHitResult(CurrentUsingSkill,LocHitResult); + } + } + else + { + TArray LocAffectActors; + CorePlayerController->MouseAimTracing(false, nullptr, LocAffectActors, 0.f, 0.f, EMouseResultType::None); + } +} + +void ACorePlayerCharacter::RestTimerStart() +{ + RestTime = 0.f; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(!World->GetTimerManager().IsTimerActive(RestTimerHandle)) + World->GetTimerManager().SetTimer(RestTimerHandle, this, &ACorePlayerCharacter::RefreshRestTime, World->DeltaTimeSeconds, true); +} + +void ACorePlayerCharacter::RefreshRestTime() +{ + if(RestTime > 3.f) + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(World) + World->GetTimerManager().ClearTimer(RestTimerHandle); + PlayerAnimInstance->bRest = true; + } + else + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + RestTime = RestTime + World->DeltaTimeSeconds; + } + +} + +void ACorePlayerCharacter::SetDecreaseStaminaTimer(bool InbDecrease) +{ + if(InbDecrease) + { + if(GetWorld()->GetTimerManager().IsTimerActive(RecoverStaminaTimerHandle)) + { + GetWorld()->GetTimerManager().ClearTimer(RecoverStaminaTimerHandle); + RecoverStaminaTimerHandle.Invalidate(); + } + if(!GetWorld()->GetTimerManager().IsTimerActive(DecreaseStaminaTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(DecreaseStaminaTimerHandle, this, &ACorePlayerCharacter::DecreaseStamina, GetWorld()->DeltaTimeSeconds, true); + } + else + { + if(GetWorld()->GetTimerManager().IsTimerActive(DecreaseStaminaTimerHandle)) + { + GetWorld()->GetTimerManager().ClearTimer(DecreaseStaminaTimerHandle); + DecreaseStaminaTimerHandle.Invalidate(); + } + if(!GetWorld()->GetTimerManager().IsTimerActive(RecoverStaminaTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(RecoverStaminaTimerHandle, this, &ACorePlayerCharacter::RecoverStamina, GetWorld()->DeltaTimeSeconds, true); + } +} + +void ACorePlayerCharacter::DecreaseStamina() +{ + if(PlayerStatusComponent->GetStatusStamina() <= 0.f) + { + bInputAble = false; + GetWorld()->GetTimerManager().ClearTimer(DecreaseStaminaTimerHandle); + DecreaseStaminaTimerHandle.Invalidate(); + PlayerAnimInstance->SetNonInputAnimState(ENonInputAnimState::Tired); + SetDecreaseStaminaTimer(false); + ChangeValueOnRun(false); + } + else + { + PlayerStatusComponent->SpendPlayerStamina(true); + } +} + +void ACorePlayerCharacter::SetActorRotationToMouseCursor() +{ + APlayerController* LocController = UGameplayStatics::GetPlayerController(GetWorld(),0); + if(!LocController) return; + FHitResult LocCursorHitResult; + LocController->GetHitResultUnderCursorByChannel(TraceTypeQuery3, true, LocCursorHitResult); + if(LocCursorHitResult.bBlockingHit) + { + FRotator LocToCursorRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), LocCursorHitResult.Location).Yaw, 0.f); + SetActorRotation(LocToCursorRotator); + } +} + +void ACorePlayerCharacter::RotateMeshToMouseCursor() +{ + APlayerController* LocController = UGameplayStatics::GetPlayerController(GetWorld(),0); + if(!LocController) return; + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + FHitResult LocCursorHitResult; + LocController->GetHitResultUnderCursorByChannel(TraceTypeQuery3, true, LocCursorHitResult); + if(LocCursorHitResult.bBlockingHit) + { + FRotator LocToCursorRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), LocCursorHitResult.Location).Yaw, 0.f); + GetMesh()->SetWorldRotation(LocToCursorRotator); + } +} + +void ACorePlayerCharacter::RecoverStamina() +{ + if(PlayerStatusComponent->GetStatusStamina() >= PlayerStatusComponent->GetStatusPreviousStamina()) + { + GetWorld()->GetTimerManager().ClearTimer(RecoverStaminaTimerHandle); + RecoverStaminaTimerHandle.Invalidate(); + PlayerStatusComponent->SetStatusStamina(PlayerStatusComponent->GetStatusPreviousStamina()); + } + else + { + PlayerStatusComponent->SpendPlayerStamina(false); + if(PlayerAnimInstance->GetCurrentNonInputState() == ENonInputAnimState::Tired) + { + if(PlayerStatusComponent->GetStatusStamina() > PlayerStatusComponent->GetStatusPreviousStamina() * 0.3f) + PlayerAnimInstance->NonInputAnimFinished(); + } + } +} + +void ACorePlayerCharacter::RotateMeshAxisForward(bool InbMove) +{ + if(!bInputAble) return; + if(InbMove) + { + if(!PlayerAnimInstance->bAction) + { + FRotator LocMeshRotator = GetMesh()->GetComponentRotation(); + FRotator LocActorRotator = GetActorRotation(); + GetMesh()->SetWorldRotation(FMath::RInterpTo(LocMeshRotator, LocActorRotator, 0.3f, 1.0f)); + } + } + else + { + GetWorld()->GetTimerManager().SetTimer(MeshRotateCalibrateTimerHandle, this, &ACorePlayerCharacter::CalibrateMeshAxisForward, GetWorld()->DeltaTimeSeconds, true); + } +} + +bool ACorePlayerCharacter::CheckSkillCalibrateRange(const FSkill& InSkillData, AActor*& OutNearActor) const +{ + if(!CurrentUsingSkill) return false; + if(InSkillData.fCorrectRange > 0) + { + SkillCalibrateAreaCollision->SetSphereRadius(InSkillData.fCorrectRange); + SkillCalibrateAreaCollision->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + TArray LocOverlapNpc; + SkillCalibrateAreaCollision->GetOverlappingActors(LocOverlapNpc, ACoreNpc::StaticClass()); + SkillCalibrateAreaCollision->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + TArray LocFixedNpcs; + for(AActor* LocFixedNpc : LocOverlapNpc) + { + if(ASPNpcFixed* LocCastFixedNpc = Cast(LocFixedNpc)) LocFixedNpcs.Add(LocCastFixedNpc); + } + if(LocFixedNpcs.Num()>0) + for(AActor* LocRemoveFixedNpc : LocFixedNpcs) + { + LocOverlapNpc.Remove(LocRemoveFixedNpc); + } + if(LocOverlapNpc.Num()>0) + { + float LocClosestDistance = 10000; + AActor* LocClosestActor = nullptr; + for(AActor* LocNpc : LocOverlapNpc) + { + if(LocClosestDistance > FVector::DistXY(LocNpc->GetActorLocation(), GetActorLocation())) + { + LocClosestActor = LocNpc; + LocClosestDistance = FVector::DistXY(GetActorLocation(), LocNpc->GetActorLocation()); + } + } + OutNearActor = LocClosestActor; + return true; + } + } + OutNearActor = nullptr; + return false; +} + +void ACorePlayerCharacter::CalibrateMeshNearActor(const AActor* InNearActor) +{ + FRotator LocToCursorRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), InNearActor->GetActorLocation()).Yaw, 0.f); + MovingActionForward = LocToCursorRotator; + SetActorRotation(LocToCursorRotator); + RotateMeshAxisForward(false); +} + +void ACorePlayerCharacter::CalibrateMeshMouseCursor() +{ + APlayerController* LocController = UGameplayStatics::GetPlayerController(GetWorld(),0); + if(!LocController) return; + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + FHitResult LocCursorHitResult; + LocController->GetHitResultUnderCursorByChannel(TraceTypeQuery3, false, LocCursorHitResult); + if(LocCursorHitResult.bBlockingHit) + { + FRotator LocToCursorRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), LocCursorHitResult.Location).Yaw, 0.f); + MovingActionForward = LocToCursorRotator; + SetActorRotation(LocToCursorRotator); + RotateMeshAxisForward(false); + } +} + +void ACorePlayerCharacter::CalibrateMeshAxisForward() +{ + FRotator LocCheckFinish; + PlayerAnimInstance->bAction? LocCheckFinish = MovingActionForward : LocCheckFinish = GetActorRotation(); + if(UKismetMathLibrary::EqualEqual_RotatorRotator(GetMesh()->GetComponentRotation(), LocCheckFinish, 1.f)) + { + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + MeshRotateCalibrateTimerHandle.Invalidate(); + } + else + { + if(bMovingAction && PlayerAnimInstance->bAction) + { + FRotator LocMeshRotator = GetMesh()->GetComponentRotation(); + GetMesh()->SetWorldRotation(FMath::RInterpTo(LocMeshRotator, MovingActionForward, 0.5f, 1.0f)); + } + else + { + FRotator LocMeshRotator = GetMesh()->GetComponentRotation(); + FRotator LocActorRotator = GetActorRotation(); + GetMesh()->SetWorldRotation(FMath::RInterpTo(LocMeshRotator, LocActorRotator, 0.5f, 1.0f)); + } + } +} + +void ACorePlayerCharacter::CheckClosestObject() +{ + TArray OutActors; + InteractionAreaCollision->GetOverlappingActors(OutActors, AActor::StaticClass()); + + TArray FillteredActors = UGlobalUtilsLibrary::GetFilteredCurrentActors(OutActors, {GetClass(), ACoreNpc::StaticClass()/*, ALevelCastObject::StaticClass()*/}, + {UObjectInteractionControl::StaticClass()}); + + if(FillteredActors.IsEmpty()) return; + + FVector LocCharacterLocation = GetActorLocation(); + for(auto It = FillteredActors.CreateConstIterator(); It; ++It) + { + if(!InteractableObject) + { + InteractableObject = *It; + continue; + } + float LocCurDistance = FVector::DistXY(LocCharacterLocation, (*It)->GetActorLocation()); + float LocClosestDistance = FVector::DistXY(LocCharacterLocation, InteractableObject->GetActorLocation()); + if(LocClosestDistance > LocCurDistance) InteractableObject = *It; + } + + if(InteractableObject->IsA(ALevelCastObject::StaticClass()) == false) + { + IVisualizable::Execute_ShowVisual(InteractableObject); + } + + FillteredActors.RemoveSwap(InteractableObject); + + for(AActor* FillteredActor : FillteredActors) IVisualizable::Execute_HideVisual(FillteredActor); +} + +void ACorePlayerCharacter::InteractionAreaBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(OtherActor->IsA(ACoreInteractionObject::StaticClass()) || OtherActor->Implements()) + { + if(!GetWorld()->GetTimerManager().IsTimerActive(ClosestObjectTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(ClosestObjectTimerHandle, this, + &ACorePlayerCharacter::CheckClosestObject, + GetWorld()->DeltaTimeSeconds, true); + + if(OtherActor->IsA(ALevelCastObject::StaticClass())) + { + ALevelCastObject* CastObject = Cast(OtherActor); + if(!NMT_ENSURE(CastObject)) return; + + TArray GimmickData = PlayerInventoryComponent->GetGimmickSlot(); + int SlotIDX = 0; + for(auto FindData : GimmickData) + { + if(FindData.ItemRowName == FROM_INT(CastObject->GetCastItemID())) + { + OnRequestInteractIcon.Execute(FString(), false); + IVisualizable::Execute_ShowVisual(OtherActor); + return; + } + SlotIDX++; + } + + IVisualizable::Execute_HideVisual(OtherActor); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GetGameInstance()); + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Item); + uint8* FoundData = FoundTable->FindRowUnchecked(FROM_INT(CastObject->GetCastItemID())); + NMT_MSG_CHECKF(FoundData, "CastItemId[%s]: Failed to locate item data. Index [%s] may be out of range—confirm this entry in Item.csv.", FROM_INT(CastObject->GetCastItemID()), + FROM_INT(CastObject->GetCastItemID())); + + FItem* ItemData = reinterpret_cast(FoundData); + OnRequestInteractIcon.Execute(ItemData->sItemIconPath, true); + } + else + { + if(OnRequestInteractIcon.IsBound()) OnRequestInteractIcon.Execute(FString(), false); + if(RefreshInteractionVisibility.IsBound()) RefreshInteractionVisibility.Broadcast(true); + } + } +} + +void ACorePlayerCharacter::InteractionAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + if(OtherActor->IsA(ACoreInteractionObject::StaticClass()) || OtherActor->Implements()) + { + IVisualizable::Execute_HideVisual(OtherActor); + TArray LocOverlappedActors; + InteractionAreaCollision->GetOverlappingActors(LocOverlappedActors, AActor::StaticClass()); + + TArray FillteredActors = UGlobalUtilsLibrary::GetFilteredCurrentActors(LocOverlappedActors, {GetClass(), ACoreNpc::StaticClass()}, + {UObjectInteractionControl::StaticClass()}); + + if(FillteredActors.IsEmpty()) + { + InteractableObject = nullptr; + GetWorld()->GetTimerManager().ClearTimer(ClosestObjectTimerHandle); + ClosestObjectTimerHandle.Invalidate(); + if(RefreshInteractionVisibility.IsBound()) RefreshInteractionVisibility.Broadcast(false); + } + } +} + +void ACorePlayerCharacter::NoiseAreaBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(ACoreNpc* LocCurOverlapNpc = Cast(OtherActor)) + { + LocCurOverlapNpc->Alert(GetActorLocation()); + LocCurOverlapNpc->SetDetectTargetFromNoise(this); + } +} + +void ACorePlayerCharacter::NoiseAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + NOT_IMPLEMENTED(); +} + +void ACorePlayerCharacter::InitializeCharacterSet() +{ + NOT_IMPLEMENTED(); +} + +void ACorePlayerCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACorePlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); + + if(UEnhancedInputComponent* EnhancedInputComponent = Cast(PlayerInputComponent)) + { + EnhancedInputComponent->BindAction(PlayerActions.AxisMoveAction, ETriggerEvent::Started, this, &ACorePlayerCharacter::AxisMoveStarted); + EnhancedInputComponent->BindAction(PlayerActions.AxisMoveAction, ETriggerEvent::Triggered, this, &ACorePlayerCharacter::AxisMoveTriggered); + EnhancedInputComponent->BindAction(PlayerActions.AxisMoveAction, ETriggerEvent::Completed, this, &ACorePlayerCharacter::AxisMoveCompleted); + EnhancedInputComponent->BindAction(PlayerActions.RunAction, ETriggerEvent::Triggered, this, &ACorePlayerCharacter::RunTriggered); + EnhancedInputComponent->BindAction(PlayerActions.RunAction, ETriggerEvent::Completed, this, &ACorePlayerCharacter::RunCompleted); + EnhancedInputComponent->BindAction(PlayerActions.MeleeAttackAction, ETriggerEvent::Started, this, &ACorePlayerCharacter::ActivateMeleeAttack); + EnhancedInputComponent->BindAction(PlayerActions.SkillAction, ETriggerEvent::Started, this, &ACorePlayerCharacter::ActivateSkill); + EnhancedInputComponent->BindAction(PlayerActions.InteractionAction, ETriggerEvent::Started, this, &ACorePlayerCharacter::InteractionStarted); + EnhancedInputComponent->BindAction(PlayerActions.UseSlot1Action, ETriggerEvent::Started, this, &ACorePlayerCharacter::UseItemSlot1); + EnhancedInputComponent->BindAction(PlayerActions.UseSlot2Action, ETriggerEvent::Started, this, &ACorePlayerCharacter::UseItemSlot2); + EnhancedInputComponent->BindAction(PlayerActions.UseSlot3Action, ETriggerEvent::Started, this, &ACorePlayerCharacter::UseItemSlot3); + EnhancedInputComponent->BindAction(PlayerActions.PauseAction, ETriggerEvent::Started, this, &ACorePlayerCharacter::ToggleGameMenu); + + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugCharacterSelect, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugCharacterSelect); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleCheat, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleCheat); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleFrustum, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleFrustum); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleInvincible, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleInvincible); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleSlomo, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleSlomo); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleHitCollision, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleHitCollision); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugTogglePlayerDamage, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugTogglePlayerDamage); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugTogglePlayerSpeed, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugTogglePlayerSpeed); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleTimeStop, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleTimeStop); + EnhancedInputComponent->BindAction(PlayerDebugActions.DebugToggleCam, ETriggerEvent::Started, this, &ACorePlayerCharacter::DebugToggleSpectatorPawn); + + CurrentEnhancedInputComponent = EnhancedInputComponent; + PlayerDeadDone.AddDynamic(this, &ACorePlayerCharacter::EventOnDead); + } + else + { + NMT_MSG_CHECKF(0, "Fail to set input") + } +} + +void ACorePlayerCharacter::ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + float FinalDamage = CCM->GetDebugStatus().bDebugPlayerDamage? InDamage + 1000.f : InDamage; + + if(PlayerStatusComponent->ApplyDamage(FinalDamage)) + { + if(bDead || bInvincible) return; + bDead = true; + PlayerAnimInstance->SetNonInputAnimState(ENonInputAnimState::Dead); + UNotificationCenter* LocNotiCenter = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(this)); + LocNotiCenter->Post(ENotificationTypes::Player_Dead); + if(PlayerDeadDone.IsBound()) PlayerDeadDone.Broadcast(); + RespawnCharacter(); + } + else + { + if(CCM->GetDebugStatus().bDebugPlayerInvincibleStatusEffect) return; + if(InSkillEffects.Num() >= 1) + { + for(FEffect LocCurEffect : InSkillEffects) + { + EEffectSubTypes LocCurEffectType = UGlobalUtilsLibrary::GetStringToEnum(LocCurEffect.sEffect); + if(CheckEffectTime(LocCurEffect)) + { + switch(LocCurEffectType) + { + case EEffectSubTypes::Hitback: + { + if(CurrentUsingSkill != nullptr) + { + StopActionMontage(); + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + CurrentUsingSkill.GetClass() == PlayerAtkSkillClass + ? SetMeleeAtkSkillState(EPlayerSkillState::Cancel, LocSkillData) + : SetSkillState(EPlayerSkillState::Cancel, LocSkillData); + } + PlayerAnimInstance->SetNonInputAnimState(ENonInputAnimState::HitBack); + break; + } + case EEffectSubTypes::Jumpback: + { + if(CurrentUsingSkill != nullptr) + { + StopActionMontage(); + FSkill LocSkillData; + CurrentUsingSkill->GetSkillData(LocSkillData); + CurrentUsingSkill.GetClass() == PlayerAtkSkillClass + ? SetMeleeAtkSkillState(EPlayerSkillState::Cancel, LocSkillData) + : SetSkillState(EPlayerSkillState::Cancel, LocSkillData); + } + if(!bInvincible) + { + bInvincible = true; + PlayerJumpBack(nullptr); + } + break; + } + case EEffectSubTypes::Unrecog: + { + NOT_IMPLEMENTED_MSG("EEffectSubTypes::Unrecog"); + break; + } + case EEffectSubTypes::Fast: + { + StatusFast(LocCurEffect.fEffectValue); + break; + } + case EEffectSubTypes::Slow: + { + StatusSlow(LocCurEffect.fEffectValue); + break; + } + case EEffectSubTypes::CogImmune: + { + SetUnDetectState(true); + break; + } + case EEffectSubTypes::Heal: + { + if(PlayerStatusComponent->GetStatusPreviousCharHp() > PlayerStatusComponent->GetStatusCharHp() + LocCurEffect.fEffectValue) + { + PlayerStatusComponent->SetStatusCharHp(PlayerStatusComponent->GetStatusCharHp() + LocCurEffect.fEffectValue); + } + else + { + PlayerStatusComponent->SetStatusCharHp(PlayerStatusComponent->GetStatusPreviousCharHp()); + } + PlayerStatusComponent->UpdatePlayerHpPercent.Broadcast(PlayerStatusComponent->GetStatusCharHp() / PlayerStatusComponent->GetStatusPreviousCharHp()); + } + default: NMT_LOG("No Effect Type"); + } + AddEffectTimeMap(LocCurEffect); + } + } + } + } +} + +void ACorePlayerCharacter::ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) +{ + + for(FEffect LocCurReleaseEffect : InReleaseEffects) + { + EEffectSubTypes LocCurRecoveryTypes = UGlobalUtilsLibrary::GetStringToEnum(LocCurReleaseEffect.sEffect); + EffectTimeMap.Remove(LocCurRecoveryTypes); + if(EffectTimeMap.IsEmpty()) + { + GetWorld()->GetTimerManager().ClearTimer(EffectActiveTimerHandle); + if(RefreshEffectTime.IsBound()) RefreshEffectTime.Broadcast(LocCurRecoveryTypes, 0.f, true); + } + switch(LocCurRecoveryTypes) + { + case EEffectSubTypes::Hitback: + { + NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::Hitback"); + break; + } + case EEffectSubTypes::Jumpback: + { + NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::Jumpback"); + break; + } + case EEffectSubTypes::Unrecog: + { + NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::Unrecog"); + break; + } + case EEffectSubTypes::Fast: + { + StatusFast(LocCurReleaseEffect.fEffectValue, true); + break; + } + case EEffectSubTypes::Slow: + { + StatusSlow(LocCurReleaseEffect.fEffectValue, true); + break; + } + case EEffectSubTypes::CogImmune: + { + SetUnDetectState(false); + break; + } + default: NMT_LOG("No Release Effect Type"); + } + } +} + +void ACorePlayerCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + GetWorld()->GetTimerManager().ClearTimer(SkillCoolDownTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(EffectActiveTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(ClosestObjectTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(DecreaseStaminaTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(RecoverStaminaTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(FadeTimerHandle); + GetWorld()->GetTimerManager().ClearTimer(JumpBackTimerHandle); + Super::EndPlay(EndPlayReason); +} + +void ACorePlayerCharacter::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(bMovingAction) + { + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusCharMove() * SkillDecreaseSpeedRatio); + PlayerAnimInstance->SetActionState(true); + } + else + { + SetInputable(false); + } + CurrentUsingSkill->StartSkill(); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(),InSkillData); + CurrentUsingSkill->CancelSkill(); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + break; + } + case EPlayerSkillState::Release: + { + CurrentUsingSkill->CancelSkill(); + SetCurrentSkill(false); + if(bMovingAction) + { + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + PlayerAnimInstance->SetActionState(false); + } + else + { + PlayerAnimInstance->SetActionState(false); + SetInputable(true); + } + break; + } + case EPlayerSkillState::Activate: break; + case EPlayerSkillState::Finish: break; + default: NMT_LOG("PlayerSkill State None"); break; + } +} + +void ACorePlayerCharacter::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(bCalibrateSkill) + { + AActor* LocNearActor = nullptr; + if(CheckSkillCalibrateRange(InSkillData,LocNearActor)) + { + CalibrateMeshNearActor(LocNearActor); + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + + if(bMovingAction) + { + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusCharMove() * MeleeAtkDecreaseSpeedRatio); + } + else + { + SetInputable(false); + } + CurrentUsingSkill->StartSkill(); + PlayActionMontage(*InSkillData.sSkillName,FOnMontageEnded::CreateLambda([InSkillData, this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) SetMeleeAtkSkillState(EPlayerSkillState::Finish,InSkillData); + })); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + CurrentUsingSkill->CancelSkill(); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + if(bMovingAction) + { + SetActorRotation(GetMesh()->GetComponentRotation()); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + } + else + { + SetInputable(true); + } + break; + } + case EPlayerSkillState::Release: break; + case EPlayerSkillState::Finish: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + CurrentUsingSkill->FinishSkill(); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + if(bMovingAction) + { + SetActorRotation(GetMesh()->GetComponentRotation()); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + } + else + { + SetInputable(true); + } + break; + } + default: NMT_LOG("PlayerAtk State None"); break; + } +} + +void ACorePlayerCharacter::SetItemSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + // TODO: Edit Immediately Skill, AimSkill Set From Type + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + #if ONLY_KEYBOARD + //CalibrateMeshMouseCursor(); + #endif + //FIXME : Const Item Aim Decrease Value Speed Edit + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusCharMove() * 0.5f); + //SetInputable(false); + //PlayCommonMontage(*InSkillData.sSkillName, nullptr); + //SetItemSkillState(EPlayerSkillState::Aim); + CurrentUsingSkill->StartSkill(); + ESkillTypes LocItemSkillType = UGlobalUtilsLibrary::GetStringToEnum(InSkillData.sSkillType); + if(LocItemSkillType == ESkillTypes::Indirect || LocItemSkillType == ESkillTypes::Direct) + SetItemSkillState(EPlayerSkillState::Aim, InSkillData); + break; + } + case EPlayerSkillState::Aim: + { + ESkillTypes LocItemSkillType = UGlobalUtilsLibrary::GetStringToEnum(InSkillData.sSkillType); + if(LocItemSkillType == ESkillTypes::Indirect) + { + StartMouseCursorParabola(true); + } + else if(LocItemSkillType == ESkillTypes::Direct) + { + StartMouseCursorLinear(true); + } + CurrentUsingSkill->AimSkill(); + if(bMovingAction) + { + PlayerAnimInstance->SetActionState(false); + } + else + { + SetInputable(false); + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + GetWorld()->GetTimerManager().SetTimer(MouseCursorTimerHandle, this, &ACorePlayerCharacter::RotateMeshToMouseCursor, GetWorld()->DeltaTimeSeconds, true); + } + break; + } + case EPlayerSkillState::Cancel: + { + StartMouseCursorParabola(false); + StartMouseCursorLinear(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + CurrentUsingSkill->CancelSkill(); + SetItemSkillState(EPlayerSkillState::Finish); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + break; + } + case EPlayerSkillState::Release: + { + StartMouseCursorParabola(false); + StartMouseCursorLinear(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + CurrentUsingSkill->ReleaseSkill(); + SetItemSkillState(EPlayerSkillState::Finish); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + break; + } + case EPlayerSkillState::Activate: + { + StartMouseCursorParabola(false); + StartMouseCursorLinear(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + CurrentUsingSkill->ActivateSkill(); + ESkillTypes LocItemSkillType = UGlobalUtilsLibrary::GetStringToEnum(InSkillData.sSkillType); + int LocSlotNumber; + GetSlotCursor(LocSlotNumber); + GetPlayerInventory()->EmptySpendSlotItem(LocSlotNumber); + SetSlotCursor(-1); + if(LocItemSkillType != ESkillTypes::Buff) + { + FName LocActivateSection = TEXT("CommonItemThrow"); + PlayCommonMontage(LocActivateSection, FOnMontageEnded::CreateLambda([this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) SetItemSkillState(EPlayerSkillState::Finish); + })); + SetActorRotationToMouseCursor(); + CalibrateMeshMouseCursor(); + SetInputable(false); + } + else + { + SetItemSkillState(EPlayerSkillState::Finish); + } + break; + } + case EPlayerSkillState::Finish: + { + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + SetInputable(true); + break; + } + default: NMT_LOG("PlayerItem State None"); break; + } +} + +void ACorePlayerCharacter::SetupPlayerInputActions() +{ + //TODO : Specific Path -> Relative Data Path + DefaultMappingContext = UGlobalUtilsLibrary::FindObject("/Script/EnhancedInput.InputMappingContext'/Game/System/Core/Input/InputMappingContext/IMC_LocalPlayerV1.IMC_LocalPlayerV1'"); + + auto LocFindInputAction = UGlobalUtilsLibrary::FindObject; + PlayerActions.AxisMoveAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_AxisMove.IA_AxisMove'"); + PlayerActions.RunAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Run.IA_Run'"); + PlayerActions.MeleeAttackAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_MeleeAttack.IA_MeleeAttack'"); + PlayerActions.SkillAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_ActiveSkill.IA_ActiveSkill'"); + PlayerActions.InteractionAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Interaction.IA_Interaction'"); + PlayerActions.UseSlot1Action = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Slot1.IA_Slot1'"); + PlayerActions.UseSlot2Action = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Slot2.IA_Slot2'"); + PlayerActions.UseSlot3Action = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Slot3.IA_Slot3'"); + PlayerActions.MinimapAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_ToggleMap.IA_ToggleMap'"); + PlayerActions.PauseAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/IA_Pause.IA_Pause'"); + + PlayerDebugActions.DebugCharacterSelect = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugCharacterSelect.IA_DebugCharacterSelect'"); + PlayerDebugActions.DebugToggleCheat = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleCheat.IA_DebugToggleCheat'"); + PlayerDebugActions.DebugToggleFrustum = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleFrustum.IA_DebugToggleFrustum'"); + PlayerDebugActions.DebugToggleInvincible = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleInvincible.IA_DebugToggleInvincible'"); + PlayerDebugActions.DebugToggleSlomo = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleSlomo.IA_DebugToggleSlomo'"); + PlayerDebugActions.DebugToggleHitCollision = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleHitCollision.IA_DebugToggleHitCollision'"); + PlayerDebugActions.DebugTogglePlayerDamage = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugTogglePlayerDamage.IA_DebugTogglePlayerDamage'"); + PlayerDebugActions.DebugTogglePlayerSpeed = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugTogglePlayerSpeed.IA_DebugTogglePlayerSpeed'"); + PlayerDebugActions.DebugToggleTimeStop = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleTimeStop.IA_DebugToggleTimeStop'"); + PlayerDebugActions.DebugToggleCam = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugToggleCam.IA_DebugToggleCam'"); + + PlayerChordedActions.CtrlAction = LocFindInputAction("/Script/EnhancedInput.InputAction'/Game/System/Core/Input/InputAction/CheatAction/IA_DebugCharacterSelect.IA_DebugCharacterSelect'"); +} + +void ACorePlayerCharacter::EventOnDead() +{ + CurrentEnhancedInputComponent->ClearActionBindings(); +} + +void ACorePlayerCharacter::UpdateRequestInteractionIcon(const FOnRequestInteractIcon& Callback) +{ + if(!Callback.IsBound()) return; + OnRequestInteractIcon = Callback; +} + +#if WITH_EDITOR +void ACorePlayerCharacter::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); + ApplyCharacterConfiguration(CharacterRowName); +} + +void ACorePlayerCharacter::ApplyCharacterData(const FTableRowBase* RowData) +{ + if(!GEditor) return; + if(!RowData) + { + PlayerStatusComponent->InitializeStatusData(FPlayerCharacter()); + return; + } + const FPlayerCharacter* GetData = static_cast(RowData); + NMT_CHECKF(GetData); + + if(*GetData == PlayerStatusComponent->CurrentPlayerStatus) return; + if(GEditor->GetEditorWorldContext().World()) + { + PlayerStatusComponent->InitializeStatusData(*GetData); + SetSkillClass(); + } +} +#endif diff --git a/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h b/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h new file mode 100644 index 0000000..5907298 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h @@ -0,0 +1,360 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GenericTeamAgentInterface.h" +#include "ProjectT/System/Core/Characters/CombatCharacter.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "ProjectT/Data/Gen/GenerateStructPlayerCharacter.h" +#include "ProjectT/System/Core/Interfaces/Damageable.h" +#include "ProjectT/Data/Player/PlayerDataModel.h" +#include "CorePlayerCharacter.generated.h" + +struct FInputActionValue; +class UInputAction; +class UInputMappingContext; +class UCoreCameraComponent; +class USpringArmComponent; +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnRequestInteractIcon, const FString&, ThumnailPath, const bool, bVisibility); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FItemSlotActivate, const int&, SlotNumber, const bool, bActivate); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FSkillCoolTime, TSubclassOf, SkillClass, float, RemainTimeRatio, bool, bCoolDownComplete); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FEffectTime, EEffectSubTypes, EffectSubTypes, float, RemainTimeRatio, bool, bEffectRecover); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FInteractionIconVisibility, bool, bVisible); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPlayerDeadDone); + +UCLASS() +class PROJECTT_API ACorePlayerCharacter : public ACombatCharacter, public IGenericTeamAgentInterface, public IDamageable +{ + GENERATED_BODY() + CONTENT_TYPE_NUMBER(EContentType::PlayerCharacter) + +public: + ACorePlayerCharacter(); + virtual FGenericTeamId GetGenericTeamId() const override { return FGenericTeamId(1); } + virtual void PostLoad() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + virtual void ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) override; + virtual void ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + void SetupPlayerInputActions(); + void SetCurrentSkill(bool InbSet, ACoreSkill* InSetSkill = nullptr); + void PlayActionMontage(FName InSectionName, FOnMontageEnded InEndedFunction = nullptr, FOnMontageBlendingOutStarted InBlendOutFunction = nullptr) const; + void PlayCommonMontage(FName InSectionName, FOnMontageEnded InEndedFunction = nullptr, FOnMontageBlendingOutStarted InBlendOutFunction = nullptr) const; + void StopActionMontage() const; + void SetUnDetectState(bool InbUnDetect); + void SetSlotCursor(int InSetSlotCursor); + + void GetAudioListener(USceneComponent*& OutAudioListener); + void GetCameraComponent(TObjectPtr& OutCoreCameraComponent) const { OutCoreCameraComponent = CoreCameraComponent; } + void GetAnimInstance(class UPlayerCharacterAnimInstance*& OutAnimInstance) const { OutAnimInstance = PlayerAnimInstance; } + void GetCurrentSkill(ACoreSkill*& OutCurrentSkill) const { OutCurrentSkill = CurrentUsingSkill; } + void GetInvincible(bool& OutbInvincible) const { OutbInvincible = bInvincible; } + void GetSkillClass(TSubclassOf& OutAtkSkillClass, TSubclassOf& OutSkillClass) const; + void GetActionMontage(UAnimMontage*& OutActionMontage) const { OutActionMontage = ActionMontage; } + void GetIdleAnimSequence(TObjectPtr& OutIdleAnimSequence) const { OutIdleAnimSequence = IdleAnimation; } + void GetRestAnimSequence(TObjectPtr& OutIdleAnimSequence) const { OutIdleAnimSequence = RestAnimation; } + void GetMoveAnimSequence(TObjectPtr& OutMoveAnimSequence) const { OutMoveAnimSequence = MoveAnimation; } + void GetRunAnimSequence(TObjectPtr& OutRunAnimSequence) const { OutRunAnimSequence = RunAnimation; } + void GetPlayerCharacterData(FPlayerCharacter& OutPlayerCharacterData) const; + void GetUnDetectState(bool& OutUnDetect) const { OutUnDetect = bUnDetect; } + void GetSlotCursor(int& OutCurrentCursor) const { OutCurrentCursor = CurrentSlotCursor; } + FORCEINLINE class UPlayerInventoryComponent* GetPlayerInventory() { return PlayerInventoryComponent; } + FORCEINLINE class UPlayerStatusComponent* GetPlayerStatus() { return PlayerStatusComponent; } + + UFUNCTION(BlueprintCallable) + void SetInputable(bool InbEnable); + + UFUNCTION(BlueprintCallable) + void SetInvincible(bool InbInvincible); + + UFUNCTION(BlueprintNativeEvent) + void StartCountDown(); + + UFUNCTION() + void EventOnDead(); + + //FIXME: 임시용 상호작용 불가능 아이콘 표시를 띄우기 위한 델리게이트 추가 + UFUNCTION(BlueprintCallable) + void UpdateRequestInteractionIcon(const FOnRequestInteractIcon& Callback); + +protected: +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; + virtual void ApplyCharacterData(const FTableRowBase* RowData) override; +#endif + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()); + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()); + virtual void SetItemSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()); + void InitPlayerCharacter(); + void InitializeProperty(); + void SetSkillClass(); + + void AxisMoveStarted(); + void AxisMoveTriggered(const FInputActionValue& Value); + void AxisMoveCompleted(); + void RunTriggered(const FInputActionValue& Value); + virtual void ChangeValueOnRun(bool InbRun); + void RunCompleted(); + void ActivateMeleeAttack(); + void ActivateSkill(); + void ActivateItemSkill(int InCurrentInput, int InItemSkillId); + void InteractionStarted(); + void InteractionCompleted(); + void UseItemSlot1(); + void UseItemSlot2(); + void UseItemSlot3(); + void ToggleGameMenu(); + + void DebugToggleCheat(const FInputActionValue& InputActionValue); + void DebugToggleInvincible(const FInputActionValue& InputActionValue); + void DebugTogglePlayerDamage(const FInputActionValue& InputActionValue); + void DebugTogglePlayerSpeed(const FInputActionValue& InputActionValue); + void DebugToggleFrustum(const FInputActionValue& InputActionValue); + void DebugToggleHitCollision(const FInputActionValue& InputActionValue); + void DebugToggleTimeStop(const FInputActionValue& InputActionValue); + void DebugToggleSlomo(const FInputActionValue& InputActionValue); + void DebugCharacterSelect(const FInputActionValue& InputActionValue); + void DebugToggleSpectatorPawn(const FInputActionValue& InputActionValue); + + void RespawnCharacter(); + void AppearPlayerCharacter(); + void SetSkillCoolTime(const TSubclassOf& InSkillClass, const FSkill& InSkillData); + void SkillCoolTimeDown(); + bool CheckEffectTime(const FEffect& InEffect); + void AddEffectTimeMap(const FEffect& InEffect); + void EffectTimeDown(); + void RecoverStamina(); + void DecreaseStamina(); + void SetActorRotationToMouseCursor(); + void RotateMeshToMouseCursor(); + virtual void RotateMeshAxisForward(bool InbMove); + bool CheckSkillCalibrateRange(const FSkill& InSkillData, AActor*& OutNearActor) const; + void CalibrateMeshNearActor(const AActor* InNearActor); + void CalibrateMeshMouseCursor(); + void CalibrateMeshAxisForward(); + void CheckClosestObject(); + void CheckPlayerFalling(); + void ActivateNoiseFX(bool InActivate); + void StatusSlow(float InSlowValue, bool InbRecovery = false) const; + void StatusFast(float InFastValue, bool InbRecovery = false) const; + void StartMouseCursorLinear(bool InbStart, bool InbSustain = true); + void StartMouseCursorParabola(bool InbStart, bool InbSustain = true, bool InbPathVisible = true); + + UFUNCTION(BlueprintCallable) + void RestTimerStart(); + + UFUNCTION(BlueprintCallable) + void RefreshRestTime(); + + UFUNCTION(BlueprintCallable) + void PlayerJumpBack(AActor* InOccurActor); + + UFUNCTION() + void ResetCharacterData(); + + UFUNCTION() + void InteractionAreaBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void InteractionAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + + UFUNCTION() + void NoiseAreaBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void NoiseAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + + UFUNCTION(BlueprintCallable) + void SetDecreaseStaminaTimer(bool InbDecrease); + + +private: + void InitializeCharacterSet(); + +public: + //FIXME: 임시용 상호작용 불가능 아이콘 표시를 띄우기 위한 델리게이트 추가 + UPROPERTY() + FOnRequestInteractIcon OnRequestInteractIcon; + + UPROPERTY(BlueprintAssignable) + FInteractionIconVisibility RefreshInteractionVisibility; + + UPROPERTY(BlueprintAssignable) + FPlayerDeadDone PlayerDeadDone; + + UPROPERTY(BlueprintAssignable) + FSkillCoolTime RefreshSkillCoolTime; + + UPROPERTY(BlueprintAssignable) + FEffectTime RefreshEffectTime; + + UPROPERTY(BlueprintAssignable) + FItemSlotActivate ItemSlotActivate; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly,Category = PlayerSkill, meta = (AllowPrivateAccess = "true")) + TObjectPtr SkillRootScene; + +protected: + FRotator MovingActionForward; + FRotator MouseCursorRotation; + bool bInvincible; + bool bDead; + float CalibrateYawValue; + float RestTime; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr ActionMontage; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr IdleAnimation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr RestAnimation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr MoveAnimation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr RunAnimation; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TObjectPtr PlayerStatusComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TObjectPtr PlayerInventoryComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TObjectPtr AudioListener; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + UPlayerCharacterAnimInstance* PlayerAnimInstance; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr TransformMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction, meta = (AllowPrivateAccess = "true")) + TObjectPtr InteractionAreaCollision; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction, meta = (AllowPrivateAccess = "true")) + TObjectPtr NoiseAreaCollision; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction, meta = (AllowPrivateAccess = "true")) + TObjectPtr SkillCalibrateAreaCollision; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + TObjectPtr CameraBoom; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + TObjectPtr CoreCameraComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true")) + TObjectPtr DefaultMappingContext; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr RunFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr NoiseFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TObjectPtr CurrentUsingSkill; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TObjectPtr InteractableObject; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input) + FPlayerActionTypes PlayerActions; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input) + FPlayerDebugActionTypes PlayerDebugActions; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input) + FPlayerChordedActionTypes PlayerChordedActions; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input) + float AxisMoveSpeed; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + FVector2D CharacterMoveAxis; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true")) + bool bInputAble; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true")) + bool bUnDetect; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true")) + int CurrentSlotCursor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + FPlayerCharacter CurrentPlayerData; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TMap, FPlayerSimpleRatio> SkillCoolTimeMap; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TMap EffectTimeMap; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TSubclassOf PlayerAtkSkillClass; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + TSubclassOf PlayerSkillClass; + + UPROPERTY() + class ACorePlayerController* CorePlayerController; + + UPROPERTY() + TArray ContainEffects; + + UPROPERTY() + FTimerHandle SkillCoolDownTimerHandle; + + UPROPERTY() + FTimerHandle EffectActiveTimerHandle; + + UPROPERTY() + FTimerHandle ClosestObjectTimerHandle; + + UPROPERTY() + FTimerHandle DecreaseStaminaTimerHandle; + + UPROPERTY() + FTimerHandle RecoverStaminaTimerHandle; + + UPROPERTY() + FTimerHandle MeshRotateCalibrateTimerHandle; + + UPROPERTY() + FTimerHandle FadeTimerHandle; + + UPROPERTY() + FTimerHandle JumpBackTimerHandle; + + UPROPERTY() + FTimerHandle MouseCursorTimerHandle; + + UPROPERTY() + FTimerHandle RestTimerHandle; + + UPROPERTY() + UEnhancedInputComponent* CurrentEnhancedInputComponent; + + UPROPERTY(EditDefaultsOnly, Category = "MovingAction") + bool bMovingAction; + + UPROPERTY(EditDefaultsOnly, Category = "MovingAction") + float MeleeAtkDecreaseSpeedRatio; + + UPROPERTY(EditDefaultsOnly, Category = "MovingAction") + float SkillDecreaseSpeedRatio; + + UPROPERTY(EditDefaultsOnly, Category = "Skill") + bool bCalibrateSkill; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.cpp b/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.cpp new file mode 100644 index 0000000..e8b042a --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SkillObjectAnimInstance.h" + +USkillObjectAnimInstance::USkillObjectAnimInstance() : + ObjectMontage(nullptr), + ObjectIdleAnimation(nullptr) +{ +} + +void USkillObjectAnimInstance::SetDefaultProperty(TObjectPtr InIdleSequence, TObjectPtr InObjectMontage) +{ + if(InIdleSequence) + { + ObjectIdleAnimation = InIdleSequence; + } + if(InObjectMontage) + { + ObjectMontage = InObjectMontage; + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.h b/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.h new file mode 100644 index 0000000..050165b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/Animations/AnimInstance/SkillObjectAnimInstance.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimInstance.h" +#include "SkillObjectAnimInstance.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API USkillObjectAnimInstance : public UAnimInstance +{ + GENERATED_BODY() + +public: + USkillObjectAnimInstance(); + void SetDefaultProperty(TObjectPtr InIdleSequence, TObjectPtr InObjectMontage); + TObjectPtr GetSkillObjectMontage() { return ObjectMontage; } + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr ObjectMontage; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerAnimationState) + TObjectPtr ObjectIdleAnimation; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.cpp new file mode 100644 index 0000000..dd623b6 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.cpp @@ -0,0 +1,277 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreSkill.h" + +#include "NiagaraComponent.h" +#include "NiagaraSystem.h" +#include "Components/SphereComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/PooledActorManager.h" + +ACoreSkill::ACoreSkill(): + SkillRowName(TEXT("None")), + RootSceneComponent(nullptr), + NoiseSphereComponent(nullptr), + HitFXSystem(nullptr), + NoiseFXComponent(nullptr), + SkillPoolsize(10), + SkillOwner(nullptr), + SkillId(0), + bAimState(false), + bCanceled(false), + bReleased(false), + bActivated(false), + BodyHitComponent(nullptr), + RangeHitComponent(nullptr) +{ + PrimaryActorTick.bCanEverTick = true; + + RootSceneComponent = CreateDefaultSubobject(TEXT("RootSceneComponent")); + NoiseSphereComponent = CreateDefaultSubobject(TEXT("NoiseSphereComponent")); + NoiseFXComponent = CreateDefaultSubobject(TEXT("NoiseFXComponent")); + + RootComponent = RootSceneComponent; + + NoiseSphereComponent->SetupAttachment(RootSceneComponent); + NoiseSphereComponent->SetCollisionProfileName(TEXT("PlayerHit")); + NoiseSphereComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + NoiseFXComponent->SetupAttachment(NoiseSphereComponent); + NoiseFXComponent->bAutoActivate = false; +} + +void ACoreSkill::InitializeSkillData() +{ + if(SkillRowName.IsNone()) return; + LinearTraceQuery = UEngineTypes::ConvertToTraceType(ECC_GameTraceChannel3); + UDataTable* LocDataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + FSkill* LocSkillDataRow = LocDataTable->FindRow(SkillRowName, TEXT("Not Found FSkill")); + if(!NMT_ENSURE(LocSkillDataRow)) return; + SkillData = *LocSkillDataRow; + TArray LocEffectArray; + if(SkillData.iEffect1Id != 0) LocEffectArray.Add(SkillData.iEffect1Id); + if(SkillData.iEffect2Id != 0) LocEffectArray.Add(SkillData.iEffect2Id); + if(SkillData.iEffect3Id != 0) LocEffectArray.Add(SkillData.iEffect3Id); + if(LocEffectArray.Num() > 0) + for(int32 LocEffectID : LocEffectArray) + { + FName LocEffectRowName = *FString::FromInt(LocEffectID); + LocDataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Effect); + FEffect* LocEffectDataRow = LocDataTable->FindRow(LocEffectRowName, TEXT("Not Found FSkill")); + SkillEffects.Add(*LocEffectDataRow); + } + NoiseSphereComponent->SetSphereRadius(SkillData.fSkillNoise); + //TODO : Load Relative Path From Table After Added + if(UNiagaraSystem* LocFindNoiseAsset = Cast(StaticLoadObject(UNiagaraSystem::StaticClass(),nullptr,TEXT("/Script/Niagara.NiagaraSystem'/Game/FX/NiagaraSystem/Common/NS_Common_SoundEangeEffects.NS_Common_SoundEangeEffects'")))) + NoiseFXComponent->SetAsset(LocFindNoiseAsset); + + if(UNiagaraSystem* LocFindNoiseAsset = Cast(StaticLoadObject(UNiagaraSystem::StaticClass(),nullptr,TEXT("/Script/Niagara.NiagaraSystem'/Game/FX/NiagaraSystem/Common/NS_Common_Hit.NS_Common_Hit'")))) + HitFXSystem = LocFindNoiseAsset; + + +} + +void ACoreSkill::SetSkillOwner(AActor* InSkillOwner) +{ + SkillOwner = InSkillOwner; +} + +void ACoreSkill::GetSkillData(FSkill& OutCurrentSkillData) +{ + OutCurrentSkillData = SkillData; +} + +float ACoreSkill::GetFinalDamage(AActor* InHitActor, bool InbLocationSelf) +{ + float LocFinalDamage = 0.f; + if(SkillOwner) + { + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + FVector2D LocOccurForward; + InbLocationSelf ? LocOccurForward = FVector2D(InHitActor->GetActorLocation().X - GetActorLocation().X, InHitActor->GetActorLocation().Y - GetActorLocation().Y) + : LocOccurForward = FVector2D(LocPlayerCharacter->GetMesh()->GetForwardVector().X, LocPlayerCharacter->GetMesh()->GetForwardVector().Y); + FVector2D LocNpcForward(InHitActor->GetActorForwardVector().X,InHitActor->GetActorForwardVector().Y); + float LocDotValue = UKismetMathLibrary::DotProduct2D(LocOccurForward,LocNpcForward); + if(LocDotValue >= 0) + SkillData.fCriDmg <= 0.f ? LocFinalDamage = SkillData.fDamage : LocFinalDamage = SkillData.fCriDmg; + else + LocFinalDamage = SkillData.fDamage; + } + return LocFinalDamage; +} + +void ACoreSkill::SetParabolaLaunchVelocity() +{ + FVector LocEndPoint = CursorCalibrateHitResult.Location; + FVector LocCalibLocation(GetActorLocation().X, GetActorLocation().Y, LocEndPoint.Z); + float LocFinalDistance = FVector::Distance(LocCalibLocation, LocEndPoint); + UGlobalUtilsLibrary::SuggestProjectileVelocityAtLocation(GetWorld(), LaunchVelocity, GetActorLocation(), + LocEndPoint, 110.f, 0.f, + LocFinalDistance / 100.f); +} + +UPrimitiveComponent* ACoreSkill::GetBodyHitComponent() const +{ + return BodyHitComponent; +} + +UPrimitiveComponent* ACoreSkill::GetRangeHitComponent() const +{ + return RangeHitComponent; +} + +void ACoreSkill::StartSkill() +{ +} + +void ACoreSkill::AimSkill() +{ +} + +void ACoreSkill::ActivateSkill() +{ +} + +void ACoreSkill::ReleaseSkill() +{ +} + +void ACoreSkill::CancelSkill() +{ +} + +void ACoreSkill::FinishSkill() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + UPooledActorManager* LocPoolManager = IWorldObjectProvider::Execute_GetPooledActorManager(LocGameMode); + if(LocPoolManager) + { + LocPoolManager->Push(this); + } +} + +void ACoreSkill::SkillHitEnable(bool InbEnable) +{ +} + +void ACoreSkill::SkillObjectHitEnable(bool InbEnable) +{ +} + +void ACoreSkill::SkillFXEnable(bool InbEnable, int32 InIndex) +{ +} + +void ACoreSkill::MakeSkillNoise(bool InbLocationSelf, UPrimitiveComponent* InAttachedComponent) +{ + if(SkillData.fSkillNoise == 0) return; + if(InbLocationSelf) + { + if(InAttachedComponent != nullptr) + { + NoiseFXComponent->AttachToComponent(InAttachedComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + } + } + else + { + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + NoiseFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale); + } + } + NoiseFXComponent->Activate(true); + NoiseFXComponent->SetFloatParameter(TEXT("Wave Radius"), SkillData.fSkillNoise * 2.f); + NoiseSphereComponent->SetSphereRadius(SkillData.fSkillNoise); + NoiseSphereComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + TArray OverlappedActors; + NoiseSphereComponent->GetOverlappingActors(OverlappedActors, ACoreNpc::StaticClass()); + TArray LocIgnoreActors; + if(OverlappedActors.Num() >= 1) + { + for(AActor* LocOverlapActor : OverlappedActors) + { + if(ACoreNpc* LocOverlapNpc = Cast(LocOverlapActor)) + { + LocOverlapNpc->SetDetectLocationFromNoise(GetActorLocation()); + } + } + } + NoiseSphereComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); +} + +void ACoreSkill::ResetDefaultState() +{ +} + +void ACoreSkill::MovedComponentToHitPoint(AActor* InHitActor, UPrimitiveComponent* InMovedComponent) +{ + TArray LocIgnoreActors; + LocIgnoreActors.Add(SkillOwner); + FHitResult LocTraceHitResult; + UKismetSystemLibrary::LineTraceSingle(this, GetActorLocation(), InHitActor->GetActorLocation(), + TraceTypeQuery1, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(LocTraceHitResult.bBlockingHit) + { + InMovedComponent->SetWorldLocation(LocTraceHitResult.Location); + } +} + +void ACoreSkill::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACoreSkill::Enable_Implementation() +{ + IPoolableActor::Enable_Implementation(); +} + +void ACoreSkill::Disable_Implementation() +{ + IPoolableActor::Disable_Implementation(); + if(UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this)) + { + if(CCM->GetDebugStatus().bDebugHitCollision) + { + if(BodyHitComponent) BodyHitComponent->SetHiddenInGame(true); + if(RangeHitComponent) RangeHitComponent->SetHiddenInGame(true); + } + } +} + +void ACoreSkill::Pushed_Implementation() +{ + IPoolableActor::Pushed_Implementation(); +} + +void ACoreSkill::Obtained_Implementation() +{ + IPoolableActor::Obtained_Implementation(); + if(UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this)) + { + if(CCM->GetDebugStatus().bDebugHitCollision) + { + BodyHitComponent->SetHiddenInGame(false); + RangeHitComponent->SetHiddenInGame(false); + } + } +} + +void ACoreSkill::RefreshCursorHitResult_Implementation(FHitResult InHitResult) +{ + IMouseInteraction::RefreshCursorHitResult_Implementation(InHitResult); + CursorCalibrateHitResult = InHitResult; +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.h b/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.h new file mode 100644 index 0000000..b14d26b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/CoreSkill.h @@ -0,0 +1,133 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectT/Data/Gen/GenerateStructEffect.h" +#include "ProjectT/Data/Gen/GenerateStructSkill.h" +#include "ProjectT/System/Core/Interfaces/MouseInteraction.h" +#include "ProjectT/System/Core/Interfaces/PoolableActor.h" +#include "CoreSkill.generated.h" + +DECLARE_DELEGATE(FSkillTimeEnd) +UCLASS() +class PROJECTT_API ACoreSkill : public AActor, public IPoolableActor, public IMouseInteraction +{ + GENERATED_BODY() + +public: + ACoreSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void RefreshCursorHitResult_Implementation(FHitResult InHitResult) override; + + void InitializeSkillData(); + void SetSkillOwner(AActor* InSkillOwner); + void GetSkillData(FSkill& OutCurrentSkillData); + bool GetAimState() const { return bAimState; } + bool GetActivated() const { return bActivated; } + int32 GetSkillId() const { return SkillId; } + int GetSkillPoolSize() const { return SkillPoolsize; } + void SetCursorHitResult(const FHitResult& InHitResult) { CursorCalibrateHitResult = InHitResult; }; + float GetFinalDamage(AActor* InHitActor, bool InbLocationSelf = false); + void SetParabolaLaunchVelocity(); + UPrimitiveComponent* GetBodyHitComponent() const; + UPrimitiveComponent* GetRangeHitComponent() const; + + FORCEINLINE FSkill GetSkillData() const { return SkillData; } + + UFUNCTION(BlueprintCallable) + virtual void StartSkill(); + + UFUNCTION(BlueprintCallable) + virtual void AimSkill(); + + UFUNCTION(BlueprintCallable) + virtual void ActivateSkill(); + + UFUNCTION(BlueprintCallable) + virtual void ReleaseSkill(); + + UFUNCTION(BlueprintCallable) + virtual void CancelSkill(); + + UFUNCTION(BlueprintCallable) + virtual void FinishSkill(); + + UFUNCTION(BlueprintCallable) + virtual void SkillHitEnable(bool InbEnable); + + UFUNCTION(BlueprintCallable) + virtual void SkillObjectHitEnable(bool InbEnable); + + UFUNCTION(BlueprintCallable) + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0); + + UFUNCTION(BlueprintCallable) + virtual void MakeSkillNoise(bool InbLocationSelf = false, UPrimitiveComponent* InAttachedComponent = nullptr); + + UFUNCTION(BlueprintCallable) + virtual void ResetDefaultState(); + + UFUNCTION(BlueprintCallable) + void MovedComponentToHitPoint(AActor* InHitActor, UPrimitiveComponent* InMovedComponent); + +public: + FSkillTimeEnd SkillTimeEnd; + +protected: + ETraceTypeQuery LinearTraceQuery; + FHitResult CursorCalibrateHitResult; + FVector LaunchVelocity; + FName SkillRowName; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Skill") + TObjectPtr RootSceneComponent; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Skill") + TObjectPtr NoiseSphereComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr HitFXSystem; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr NoiseFXComponent; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Skill") + int SkillPoolsize; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Skill") + FSkill SkillData; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Skill") + TArray SkillEffects; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + AActor* SkillOwner; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + int32 SkillId; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + bool bAimState; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + bool bCanceled; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + bool bReleased; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Skill") + bool bActivated; + + UPROPERTY() + UPrimitiveComponent* BodyHitComponent; + + UPROPERTY() + UPrimitiveComponent* RangeHitComponent; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.cpp b/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.cpp new file mode 100644 index 0000000..75c31e8 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.cpp @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HealingPotion.h" + +#include "NiagaraFunctionLibrary.h" +#include "Components/AudioComponent.h" +#include "ProjectT/System/Core/Characters/CombatCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/Damageable.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +AHealingPotion::AHealingPotion() : + HealFXAsset(nullptr), + HealSFXComponent(nullptr) +{ + SkillPoolsize = 3; + SkillRowName = "313403"; + SkillId = 313403; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; +} + +void AHealingPotion::BeginPlay() +{ + Super::BeginPlay(); +} + +void AHealingPotion::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AHealingPotion::ActivateSkill() +{ + if(!SkillOwner) return; + MakeSkillNoise(); + if(HealSFXComponent) HealSFXComponent.Get()->Stop(); + HealSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831021"), SkillOwner->GetRootComponent(), EAttachLocation::Type::SnapToTarget,TEXT("None")); + IDamageable::Execute_ApplyDamageEvent(SkillOwner, this, GetActorLocation(), SkillData.fDamage, SkillEffects); + USkeletalMeshComponent* LocMesh = Cast(SkillOwner)->GetMesh(); + UNiagaraFunctionLibrary::SpawnSystemAttached(HealFXAsset, LocMesh, FName("SOK_Root_Fx"),FVector::Zero(),FRotator::ZeroRotator,EAttachLocation::Type::SnapToTarget,true,true); + FinishSkill(); +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.h b/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.h new file mode 100644 index 0000000..de28337 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HealingPotion.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "HealingPotion.generated.h" + +UCLASS() +class PROJECTT_API AHealingPotion : public ACoreSkill +{ + GENERATED_BODY() + +public: + AHealingPotion(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + +protected: + virtual void ActivateSkill() override; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr HealFXAsset; + + UPROPERTY() + TObjectPtr HealSFXComponent; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.cpp new file mode 100644 index 0000000..698248b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.cpp @@ -0,0 +1,149 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HolisterAtk.h" + +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/BoxComponent.h" +#include "Kismet/KismetSystemLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +AHolisterAtk::AHolisterAtk() : + HolisterAtkRootSceneComponent(nullptr), + HolisterAtkCollisionComponent(nullptr), + HolisterAtkFXComponent(nullptr) +{ + + SkillPoolsize = 5; + SkillRowName = "311103"; + SkillId = 311103; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + HolisterAtkRootSceneComponent = CreateDefaultSubobject(TEXT("HolisterAtkRootSceneComponent")); + HolisterAtkCollisionComponent = CreateDefaultSubobject(TEXT("HolisterAtkCollisionComponent")); + HolisterAtkFXComponent = CreateDefaultSubobject(TEXT("HolisterAtkFXComponent")); + + HolisterAtkRootSceneComponent->SetupAttachment(RootComponent); + HolisterAtkCollisionComponent->SetupAttachment(HolisterAtkRootSceneComponent); + HolisterAtkCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + HolisterAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + HolisterAtkCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&AHolisterAtk::BoxCollisionBeginOverlap); + + HolisterAtkFXComponent->SetupAttachment(RootComponent); + HolisterAtkFXComponent->bAutoActivate = false; + + BodyHitComponent = HolisterAtkCollisionComponent; + RangeHitComponent = HolisterAtkCollisionComponent; +} + +void AHolisterAtk::BeginPlay() +{ + Super::BeginPlay(); + +} + +void AHolisterAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AHolisterAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void AHolisterAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + if (SkillOwner == nullptr) return; + SkillOwner = nullptr; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void AHolisterAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void AHolisterAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void AHolisterAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); +} + +void AHolisterAtk::StartSkill() +{ + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToComponent(LocPlayerCharacter->SkillRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + TObjectPtr LocHolisterShotgunMesh; + LocPlayerCharacter->GetWeaponStaticComponent(LocHolisterShotgunMesh); + HolisterAtkFXComponent->AttachToComponent(LocHolisterShotgunMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Shoot")); + } +} + +void AHolisterAtk::CancelSkill() +{ + SkillHitEnable(false); + SkillFXEnable(false); + Super::CancelSkill(); +} + +void AHolisterAtk::FinishSkill() +{ + Super::FinishSkill(); +} + +void AHolisterAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + HolisterAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + MakeSkillNoise(); + HolisterAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } + else + { + HolisterAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } +} + +void AHolisterAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(!HolisterAtkFXComponent->GetAsset()) return; + if(InbEnable) + { + HolisterAtkFXComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + HolisterAtkFXComponent->Activate(true); + } + else + { + HolisterAtkFXComponent->Deactivate(); + } +} + +void AHolisterAtk::BoxCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(ACoreNpc* LocHitNpc = Cast(OtherActor)) + { + TArray LocIgnoreActors; + FHitResult LocTraceHitResult; + UKismetSystemLibrary::LineTraceSingle(this, GetActorLocation(), LocHitNpc->GetActorLocation(), + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(!LocTraceHitResult.bBlockingHit) + { + IDamageable::Execute_ApplyDamageEvent(LocHitNpc, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocHitNpc), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocHitNpc->GetActorLocation()); + } + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.h b/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.h new file mode 100644 index 0000000..8b54ac7 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HolisterAtk.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "HolisterAtk.generated.h" + +UCLASS() +class PROJECTT_API AHolisterAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + AHolisterAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + + UFUNCTION() + void BoxCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr HolisterAtkRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr HolisterAtkCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr HolisterAtkFXComponent; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.cpp new file mode 100644 index 0000000..8557160 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.cpp @@ -0,0 +1,149 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "HolisterSkill.h" + +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/BoxComponent.h" +#include "Kismet/KismetSystemLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +AHolisterSkill::AHolisterSkill() : + HolisterSkillRootSceneComponent(nullptr), + HolisterSkillCollisionComponent(nullptr), + HolisterSkillFXComponent(nullptr) +{ + SkillPoolsize = 3; + SkillRowName = "312103"; + SkillId = 312103; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + HolisterSkillRootSceneComponent = CreateDefaultSubobject(TEXT("HolisterAtkRootSceneComponent")); + HolisterSkillCollisionComponent = CreateDefaultSubobject(TEXT("HolisterAtkCollisionComponent")); + HolisterSkillFXComponent = CreateDefaultSubobject(TEXT("HolisterAtkFXComponent")); + + HolisterSkillRootSceneComponent->SetupAttachment(RootComponent); + HolisterSkillCollisionComponent->SetupAttachment(HolisterSkillRootSceneComponent); + HolisterSkillCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + HolisterSkillCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + HolisterSkillCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&AHolisterSkill::BoxCollisionBeginOverlap); + + HolisterSkillFXComponent->SetupAttachment(RootComponent); + HolisterSkillFXComponent->bAutoActivate = false; + + BodyHitComponent = HolisterSkillCollisionComponent; + RangeHitComponent = HolisterSkillCollisionComponent; +} + +void AHolisterSkill::BeginPlay() +{ + Super::BeginPlay(); + +} + +void AHolisterSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AHolisterSkill::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void AHolisterSkill::Disable_Implementation() +{ + Super::Disable_Implementation(); + if (SkillOwner == nullptr) return; + SkillOwner = nullptr; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void AHolisterSkill::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void AHolisterSkill::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void AHolisterSkill::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); +} + +void AHolisterSkill::StartSkill() +{ + Super::StartSkill(); + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToComponent(LocPlayerCharacter->SkillRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + TObjectPtr LocHolisterShotgunMesh; + LocPlayerCharacter->GetWeaponStaticComponent(LocHolisterShotgunMesh); + HolisterSkillFXComponent->AttachToComponent(LocHolisterShotgunMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Shoot")); + } +} + +void AHolisterSkill::CancelSkill() +{ + SkillHitEnable(false); + SkillFXEnable(false); + Super::CancelSkill(); +} + +void AHolisterSkill::FinishSkill() +{ + Super::FinishSkill(); +} + +void AHolisterSkill::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + HolisterSkillCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + MakeSkillNoise(); + HolisterSkillCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } + else + { + HolisterSkillCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } +} + +void AHolisterSkill::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(!HolisterSkillFXComponent->GetAsset()) return; + if(InbEnable) + { + HolisterSkillFXComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + HolisterSkillFXComponent->Activate(true); + } + else + { + HolisterSkillFXComponent->Deactivate(); + } +} + +void AHolisterSkill::BoxCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(ACoreNpc* LocHitNpc = Cast(OtherActor)) + { + TArray LocIgnoreActors; + FHitResult LocTraceHitResult; + UKismetSystemLibrary::LineTraceSingle(this, GetActorLocation(), LocHitNpc->GetActorLocation(), + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(!LocTraceHitResult.bBlockingHit) + { + IDamageable::Execute_ApplyDamageEvent(LocHitNpc, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocHitNpc), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocHitNpc->GetActorLocation()); + } + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.h b/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.h new file mode 100644 index 0000000..6bd498e --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/HolisterSkill.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "HolisterSkill.generated.h" + +UCLASS() +class PROJECTT_API AHolisterSkill : public ACoreSkill +{ + GENERATED_BODY() + +public: + AHolisterSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + + UFUNCTION() + void BoxCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr HolisterSkillRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr HolisterSkillCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr HolisterSkillFXComponent; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.cpp new file mode 100644 index 0000000..595ed5f --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.cpp @@ -0,0 +1,194 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "IcienAtk.h" + +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/SphereComponent.h" +#include "Kismet/KismetSystemLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +AIcienAtk::AIcienAtk() : + IcienAtkRootScene(nullptr), + IcienAtkHitCollisionComponent(nullptr), + IcienAtkFXComponent(nullptr), + IcienHandLFXComponent(nullptr), + IcienHandRFXComponent(nullptr), + AtkSFXComponent(nullptr) +{ + SkillPoolsize = 5; + SkillRowName = "311305"; + SkillId = 311305; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + IcienAtkRootScene = CreateDefaultSubobject(TEXT("IcienAtkRootScene")); + IcienAtkHitCollisionComponent = CreateDefaultSubobject(TEXT("IcienAtkHitCollisionComponent")); + IcienAtkFXComponent = CreateDefaultSubobject(TEXT("IcienAtkFXComponent")); + IcienHandLFXComponent = CreateDefaultSubobject(TEXT("IcienHandLFXComponent")); + IcienHandRFXComponent = CreateDefaultSubobject(TEXT("IcienHandRFXComponent")); + + IcienAtkRootScene->SetupAttachment(RootComponent); + IcienAtkHitCollisionComponent->SetupAttachment(RootComponent); + IcienAtkHitCollisionComponent->SetSphereRadius(SkillData.fEffectRange); + IcienAtkHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + IcienAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + + IcienAtkFXComponent->SetupAttachment(IcienAtkHitCollisionComponent); + IcienAtkFXComponent->bAutoActivate = false; + IcienHandLFXComponent->SetupAttachment(RootComponent); + IcienHandLFXComponent->bAutoActivate = false; + IcienHandRFXComponent->SetupAttachment(RootComponent); + IcienHandRFXComponent->bAutoActivate = false; + + NoiseSphereComponent->SetupAttachment(IcienAtkHitCollisionComponent); +} + +void AIcienAtk::BeginPlay() +{ + Super::BeginPlay(); +} + +void AIcienAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AIcienAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void AIcienAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void AIcienAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void AIcienAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void AIcienAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(FXDeactivate); + } + Super::EndPlay(EndPlayReason); +} + +void AIcienAtk::StartSkill() +{ + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToActor(LocPlayerCharacter,FAttachmentTransformRules::SnapToTargetNotIncludingScale); + IcienHandLFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_L_Hand")); + IcienHandRFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_R_Hand")); + IcienAtkHitCollisionComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform); + IcienAtkHitCollisionComponent->SetWorldLocation(CursorCalibrateHitResult.Location); + } +} + +void AIcienAtk::ActivateSkill() +{ + AtkSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831012"), IcienAtkHitCollisionComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + bActivated = true; + IcienAtkFXComponent->Activate(true); + IcienAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + TArray OverlappedActors; + IcienAtkHitCollisionComponent->GetOverlappingActors(OverlappedActors, ACoreNpc::StaticClass()); + if (OverlappedActors.Num() >= 1) + { + for (AActor* LocOverlapActor : OverlappedActors) + { + TArray LocIgnoreActors; + FHitResult LocTraceHitResult; + FVector LocTraceStart(IcienAtkHitCollisionComponent->GetComponentLocation().X, IcienAtkHitCollisionComponent->GetComponentLocation().Y, GetActorLocation().Z); + UKismetSystemLibrary::LineTraceSingle(this, LocTraceStart, LocOverlapActor->GetActorLocation(), + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(!LocTraceHitResult.bBlockingHit) + { + IDamageable::Execute_ApplyDamageEvent(LocOverlapActor, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocOverlapActor), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocOverlapActor->GetActorLocation()); + } + } + } + IcienAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(FXDeactivate, this, &AIcienAtk::CheckFXDeactivate, LocWorld->DeltaTimeSeconds, true); + } + MakeSkillNoise(true, IcienAtkHitCollisionComponent); +} + +void AIcienAtk::CancelSkill() +{ + if(!bActivated) + { + bCanceled = true; + SkillHitEnable(false); + SkillFXEnable(false); + Super::CancelSkill(); + } +} + +void AIcienAtk::FinishSkill() +{ + Super::FinishSkill(); +} + +void AIcienAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + ActivateSkill(); + } +} + +void AIcienAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + IcienHandLFXComponent->Activate(true); + IcienHandRFXComponent->Activate(true); + } + else + { + IcienHandLFXComponent->Deactivate(); + IcienHandRFXComponent->Deactivate(); + } +} + +void AIcienAtk::ResetDefaultState() +{ + Super::ResetDefaultState(); + if (SkillOwner != nullptr) + { + SkillOwner = nullptr; + } + bCanceled = false; + bActivated = false; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void AIcienAtk::CheckFXDeactivate() +{ + if(IcienAtkFXComponent->IsActive()) return; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(FXDeactivate); + FinishSkill(); + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.h b/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.h new file mode 100644 index 0000000..db93dc1 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/IcienAtk.h @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "IcienAtk.generated.h" + +UCLASS() +class PROJECTT_API AIcienAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + AIcienAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void ActivateSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + virtual void ResetDefaultState() override; + void CheckFXDeactivate(); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr IcienAtkRootScene; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr IcienAtkHitCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienAtkFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienHandLFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienHandRFXComponent; + + UPROPERTY() + TObjectPtr AtkSFXComponent; + +private: + FVector ActivateLocation; + FRotator SetRotation; + + UPROPERTY() + FTimerHandle FXDeactivate; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.cpp new file mode 100644 index 0000000..c8b7172 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.cpp @@ -0,0 +1,154 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "IcienSkill.h" + +#include "NiagaraComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +AIcienSkill::AIcienSkill() : + IcienSkillRootSceneComponent(nullptr), + IcienSkillFXComponent(nullptr), + IcienHandLFXComponent(nullptr), + IcienHandRFXComponent(nullptr), + CurrentActivateTime(0.f) +{ + SkillPoolsize = 2; + SkillRowName = "312405"; + SkillId = 312405; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + PrimaryActorTick.bCanEverTick = true; + + IcienSkillRootSceneComponent = CreateDefaultSubobject(TEXT("IcienSkillRootSceneComponent")); + IcienSkillFXComponent = CreateDefaultSubobject(TEXT("IcienSkillFXComponent")); + IcienHandLFXComponent = CreateDefaultSubobject(TEXT("IcienHandLFXComponent")); + IcienHandRFXComponent = CreateDefaultSubobject(TEXT("IcienHandRFXComponent")); + + IcienSkillFXComponent->SetupAttachment(RootComponent); + IcienSkillFXComponent->bAutoActivate = false; + IcienHandLFXComponent->SetupAttachment(RootComponent); + IcienHandLFXComponent->bAutoActivate = false; + IcienHandRFXComponent->SetupAttachment(RootComponent); + IcienHandRFXComponent->bAutoActivate = false; +} + +void AIcienSkill::BeginPlay() +{ + Super::BeginPlay(); + +} + +void AIcienSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AIcienSkill::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void AIcienSkill::Disable_Implementation() +{ + Super::Disable_Implementation(); + if (SkillOwner == nullptr) return; + bActivated = false; + bCanceled = false; + SkillOwner = nullptr; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + CurrentActivateTime = 0.f; + SkillTimeEnd.Unbind(); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void AIcienSkill::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void AIcienSkill::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void AIcienSkill::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + } + Super::EndPlay(EndPlayReason); +} + +void AIcienSkill::StartSkill() +{ + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToActor(LocPlayerCharacter,FAttachmentTransformRules::SnapToTargetNotIncludingScale); + IcienSkillFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SOK_Root_Fx")); + IcienHandLFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_L_Hand")); + IcienHandRFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_R_Hand")); + } +} + +void AIcienSkill::ActivateSkill() +{ + IcienSkillFXComponent->Activate(true); + MakeSkillNoise(); + bActivated = true; + IDamageable::Execute_ApplyDamageEvent(SkillOwner, nullptr, FVector(), 0.f, SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(ActivateTimerHandle, this, &AIcienSkill::CheckActiveTime, LocWorld->DeltaTimeSeconds, true); + } +} + +void AIcienSkill::CancelSkill() +{ + if(!bActivated) + { + bCanceled = true; + SkillHitEnable(false); + SkillFXEnable(false); + Super::CancelSkill(); + } +} + +void AIcienSkill::FinishSkill() +{ + Super::FinishSkill(); +} + +void AIcienSkill::SkillHitEnable(bool InbEnable) +{ +} + +void AIcienSkill::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + IcienHandLFXComponent->Activate(true); + IcienHandRFXComponent->Activate(true); + } + else + { + IcienHandLFXComponent->Deactivate(); + IcienHandRFXComponent->Deactivate(); + } +} + +void AIcienSkill::CheckActiveTime() +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + CurrentActivateTime = CurrentActivateTime + LocWorld->DeltaTimeSeconds; + if(CurrentActivateTime >= SkillEffects[0].fEffectDuration) + { + IcienSkillFXComponent->Deactivate(); + LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + if(SkillTimeEnd.IsBound()) SkillTimeEnd.Execute(); + } + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.h b/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.h new file mode 100644 index 0000000..d18fee3 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/IcienSkill.h @@ -0,0 +1,51 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "IcienSkill.generated.h" + +UCLASS() +class PROJECTT_API AIcienSkill : public ACoreSkill +{ + GENERATED_BODY() + +public: + AIcienSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void ActivateSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + void CheckActiveTime(); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr IcienSkillRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienSkillFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienHandLFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr IcienHandRFXComponent; + +private: + float CurrentActivateTime; + + UPROPERTY() + FTimerHandle ActivateTimerHandle; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.cpp new file mode 100644 index 0000000..80615da --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.cpp @@ -0,0 +1,257 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NoxAtk.h" + +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/SphereComponent.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "Kismet/KismetSystemLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +ANoxAtk::ANoxAtk() : + NoxAtkRootSceneComponent(nullptr), + NoxAtkHitCollisionComponent(nullptr), + NoxAtkEffectCollisionComponent(nullptr), + ThrowFXComponent(nullptr), + WandFXComponent(nullptr), + BindFXAsset(nullptr), + ProjectileMovementComponent(nullptr), + bHit(false), + BindTime(0.f) +{ + SkillPoolsize = 5; + SkillRowName = "311204"; + SkillId = 311204; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + NoxAtkRootSceneComponent = CreateDefaultSubobject(TEXT("NoxAtkRootScene")); + NoxAtkHitCollisionComponent = CreateDefaultSubobject(TEXT("NoxAtkCollisionComponent")); + NoxAtkEffectCollisionComponent = CreateDefaultSubobject(TEXT("NoxAtkEffectCollisionComponent")); + ThrowFXComponent = CreateDefaultSubobject(TEXT("ThrowFXComponent")); + WandFXComponent = CreateDefaultSubobject(TEXT("WandFXComponent")); + ProjectileMovementComponent= CreateDefaultSubobject(TEXT("ProjectileMovementComponent")); + + NoxAtkRootSceneComponent->SetupAttachment(RootComponent); + + NoxAtkHitCollisionComponent->SetupAttachment(RootComponent); + NoxAtkHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + NoxAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + NoxAtkHitCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&ANoxAtk::DefaultCollisionBeginOverlap); + + NoxAtkEffectCollisionComponent->SetupAttachment(RootComponent); + NoxAtkEffectCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + NoxAtkEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + NoxAtkEffectCollisionComponent->SetSphereRadius(SkillData.fEffectRange); + + ThrowFXComponent->SetupAttachment(RootComponent); + ThrowFXComponent->bAutoActivate = false; + WandFXComponent->SetupAttachment(RootComponent); + WandFXComponent->bAutoActivate = false; + + ProjectileMovementComponent->SetUpdatedComponent(RootComponent); + ProjectileMovementComponent->InitialSpeed = ProjectileMovementComponent->MaxSpeed = SkillData.fProjectileSpeed; + ProjectileMovementComponent->ProjectileGravityScale = 0.f; + ProjectileMovementComponent->bAutoActivate = false; + ProjectileMovementComponent->Deactivate(); + + BodyHitComponent = NoxAtkHitCollisionComponent; + RangeHitComponent = NoxAtkHitCollisionComponent; +} + +void ANoxAtk::BeginPlay() +{ + Super::BeginPlay(); +} + +void ANoxAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ANoxAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ANoxAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void ANoxAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ANoxAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ANoxAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(RangeCheckTimer); + LocWorld->GetTimerManager().ClearTimer(BindEffectTimer); + LocWorld->GetTimerManager().ClearTimer(BindCheckTimer); + } + Super::EndPlay(EndPlayReason); +} + +void ANoxAtk::StartSkill() +{ + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + if(!LocPlayerCharacter) return; + bCanceled = false; + TObjectPtr LocNoxWandMesh; + LocPlayerCharacter->GetWeaponStaticComponent(LocNoxWandMesh); + AttachToComponent(LocNoxWandMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Gem")); +} + +void ANoxAtk::CancelSkill() +{ + SkillHitEnable(false); + SkillFXEnable(false, 0); + Super::CancelSkill(); +} + +void ANoxAtk::FinishSkill() +{ + Super::FinishSkill(); +} + +void ANoxAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + ProjectileNoxBall(); + } + else + { + ThrowFXComponent->Deactivate(); + ProjectileMovementComponent->Deactivate(); + NoxAtkEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(RangeCheckTimer); + LocWorld->GetTimerManager().SetTimer(BindCheckTimer, this, &ANoxAtk::CheckActiveBind, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ANoxAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + WandFXComponent->Activate(true); + } + else + { + WandFXComponent->Deactivate(); + } +} + +void ANoxAtk::ResetDefaultState() +{ + if(ProjectileMovementComponent->IsActive()) return; + Super::ResetDefaultState(); + bHit = false; + bCanceled = false; + bAimState = false; + bActivated = false; + bReleased = false; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ThrowFXComponent->Deactivate(); +} + +void ANoxAtk::ProjectileNoxBall() +{ + if (SkillOwner) + { + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + if(!LocPlayerCharacter) return; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ThrowFXComponent->Activate(true); + ThrowFXComponent->SetFloatParameter(TEXT("All Rate"), 1.f); + FVector LocMaxLocation = LocPlayerCharacter->SkillRootScene->GetComponentLocation() + + UKismetMathLibrary::GetForwardVector(LocPlayerCharacter->SkillRootScene->GetComponentRotation()) * SkillData.fSkillRange; + FRotator LocLookAtMaxLocation = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(),LocMaxLocation); + SetActorRotation(LocLookAtMaxLocation); + ProjectileMovementComponent->Velocity = GetActorForwardVector() * SkillData.fProjectileSpeed; + ProjectileMovementComponent->Activate(); + NoxAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + InitLocation = GetActorLocation(); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(RangeCheckTimer, this, &ANoxAtk::CheckDistance, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ANoxAtk::ExplosionNoxBall() +{ + bHit = true; + NoxAtkHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + ThrowFXComponent->Deactivate(); + ThrowFXComponent->SetFloatParameter(TEXT("All Rate"), 0.f); + NoxAtkEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + TArray OverlappedActors; + NoxAtkEffectCollisionComponent->GetOverlappingActors(OverlappedActors, ACoreNpc::StaticClass()); + if (OverlappedActors.Num() >= 1) + { + for (AActor* LocOverlapActor : OverlappedActors) + { + TArray LocIgnoreActors; + FHitResult LocTraceHitResult; + UKismetSystemLibrary::LineTraceSingle(this, GetActorLocation(), LocOverlapActor->GetActorLocation(), + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(!LocTraceHitResult.bBlockingHit) + { + IDamageable::Execute_ApplyDamageEvent(LocOverlapActor, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocOverlapActor, true), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocOverlapActor->GetActorLocation()); + USkeletalMeshComponent* LocMesh = Cast(LocOverlapActor)->GetMesh(); + UNiagaraFunctionLibrary::SpawnSystemAttached(BindFXAsset, LocMesh, FName("None"),FVector::Zero(),FRotator::ZeroRotator,EAttachLocation::Type::SnapToTarget,true,true); + } + } + } + MakeSkillNoise(true); + SkillHitEnable(false); +} + +void ANoxAtk::CheckDistance() +{ + if(UKismetMathLibrary::Vector_Distance(InitLocation, GetActorLocation()) > SkillData.fSkillRange) + { + ExplosionNoxBall(); + } +} + +void ANoxAtk::CheckActiveBind() +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + BindTime = BindTime + LocWorld->DeltaTimeSeconds; + if(BindTime < SkillEffects[0].fEffectDuration) return; + BindTime = 0.f; + LocWorld->GetTimerManager().ClearTimer(BindCheckTimer); + FinishSkill(); + } +} + +void ANoxAtk::DefaultCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(!bHit && OtherActor != SkillOwner) + { + MovedComponentToHitPoint(OtherActor, NoxAtkEffectCollisionComponent); + ExplosionNoxBall(); + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.h b/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.h new file mode 100644 index 0000000..26b1f5a --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NoxAtk.h @@ -0,0 +1,75 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "NoxAtk.generated.h" + +UCLASS() +class PROJECTT_API ANoxAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + ANoxAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex) override; + virtual void ResetDefaultState() override; + void ProjectileNoxBall(); + void ExplosionNoxBall(); + void CheckDistance(); + void CheckActiveBind(); + + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr NoxAtkRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr NoxAtkHitCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr NoxAtkEffectCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ThrowFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr WandFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr BindFXAsset; + + UPROPERTY() + TObjectPtr ProjectileMovementComponent; + +private: + bool bHit; + float BindTime; + FVector InitLocation; + + UPROPERTY() + FTimerHandle RangeCheckTimer; + + UPROPERTY() + FTimerHandle BindEffectTimer; + + UPROPERTY() + FTimerHandle BindCheckTimer; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.cpp new file mode 100644 index 0000000..c0c4759 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.cpp @@ -0,0 +1,296 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NoxSkill.h" +#include "NiagaraComponent.h" +#include "Components/SphereComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h" + +ANoxSkill::ANoxSkill() : + NoxSkillRootScene(nullptr), + WandFXComponent(nullptr), + SurgeFXComponent(nullptr), + NoxSkillHitCollisionComponent(nullptr), + SurgeSFXComponent(nullptr), + SurgeWaveDelayMax(1.f / 3.f), + SurgeWaveDelay(0.f), + AppearLength(0.3f), + ActivateTime(0.f), + SurgeFXSwitchValue(0.f) +{ + SkillPoolsize = 2; + SkillRowName = "312304"; + SkillId = 312304; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + NoxSkillRootScene =CreateDefaultSubobject(TEXT("NoxSkillRootScene")); + WandFXComponent=CreateDefaultSubobject(TEXT("WandFXComponent")); + SurgeFXComponent=CreateDefaultSubobject(TEXT("ExplosionFXComponent")); + NoxSkillHitCollisionComponent=CreateDefaultSubobject(TEXT("NoxSkillHitCollisionComponent")); + + NoxSkillRootScene->SetupAttachment(RootComponent); + WandFXComponent->SetupAttachment(RootComponent); + WandFXComponent->bAutoActivate = false; + SurgeFXComponent->SetupAttachment(RootComponent); + SurgeFXComponent->bAutoActivate = false; + + NoxSkillHitCollisionComponent->SetupAttachment(RootComponent); + NoxSkillHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + NoxSkillHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + NoxSkillHitCollisionComponent->SetSphereRadius(8.f); + NoxSkillHitCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ANoxSkill::SkillAreaBeginOverlap); + NoxSkillHitCollisionComponent->OnComponentEndOverlap.AddDynamic(this, &ANoxSkill::SkillAreaEndOverlap); + + BodyHitComponent = NoxSkillHitCollisionComponent; + RangeHitComponent = NoxSkillHitCollisionComponent; +} + +void ANoxSkill::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ANoxSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + if(CurrentAffectNpc.Num() > 0) + { + for(ACoreNpc* LocSurgedNpc : CurrentAffectNpc) + { + FVector LocSubtract(GetActorLocation().X - LocSurgedNpc->GetActorLocation().X, GetActorLocation().Y - LocSurgedNpc->GetActorLocation().Y, 0.f); + if(LocSubtract.Length() > 20) + { + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocSubtract.Normalize(); + FVector LocSurgedOffset = LocSubtract * (SkillEffects[0].fEffectValue * LocWorld->DeltaTimeSeconds); + LocSurgedNpc->AddActorWorldOffset(LocSurgedOffset, true); + } + } + } + } +} + +void ANoxSkill::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ANoxSkill::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void ANoxSkill::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ANoxSkill::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ANoxSkill::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(SurgeFXDeactivate); + } + Super::EndPlay(EndPlayReason); +} + +void ANoxSkill::StartSkill() +{ + if(bAimState) ReleaseSkill(); +} + +void ANoxSkill::AimSkill() +{ + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + if(!LocPlayerCharacter) return; + bCanceled = false; + bAimState = true; + AttachToActor(LocPlayerCharacter,FAttachmentTransformRules::SnapToTargetNotIncludingScale); + TObjectPtr LocNoxWandMesh; + LocPlayerCharacter->GetWeaponStaticComponent(LocNoxWandMesh); + WandFXComponent->AttachToComponent(LocNoxWandMesh, FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Gem")); + SetActorTickEnabled(true); +} + +void ANoxSkill::ActivateSkill() +{ + if(bActivated) return; + bAimState = false; + bActivated = true; +} + +void ANoxSkill::ReleaseSkill() +{ + bCanceled = true; + bReleased = true; + FinishSkill(); +} + +void ANoxSkill::CancelSkill() +{ + bCanceled = true; + FinishSkill(); +} + +void ANoxSkill::FinishSkill() +{ + Super::FinishSkill(); +} + +void ANoxSkill::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + MakeSkillNoise(true); + NoxSkillHitCollisionComponent->SetSphereRadius(SkillData.fEffectRange); + NoxSkillHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + LocPlayerCharacter->SetCurrentSkill(false); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + SetActorLocation(CursorCalibrateHitResult.Location); + SurgeFXComponent->Activate(true); + SurgeFXComponent->SetFloatParameter(TEXT("BlackHole Switch"), SurgeFXSwitchValue); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(SurgeActivate, this, &ANoxSkill::CheckSurgeActivateTime, LocWorld->DeltaTimeSeconds, true); + } + } + else + { + SurgeFXComponent->Deactivate(); + NoxSkillHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(SurgeFXDeactivate, this, &ANoxSkill::CheckSurgeDeactivate, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ANoxSkill::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + WandFXComponent->Activate(true); + } + else + { + WandFXComponent->Deactivate(); + } +} + +void ANoxSkill::ResetDefaultState() +{ + Super::ResetDefaultState(); + SetActorTickEnabled(false); + if (SkillOwner != nullptr) + { + SkillOwner = nullptr; + } + SurgeFXSwitchValue = 0.f; + ActivateTime = 0.f; + bCanceled = false; + bAimState = false; + bActivated = false; + bReleased = false; + SurgeSFXComponent = nullptr; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + WandFXComponent->Deactivate(); + CurrentAffectNpc.Empty(); +} + +void ANoxSkill::CheckSurgeActivateTime() +{ + const UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this); + if(LocWorld == nullptr) return; + SurgeWaveDelay + LocWorld->DeltaTimeSeconds < SurgeWaveDelayMax ? SurgeWaveDelay = SurgeWaveDelay + LocWorld->DeltaTimeSeconds : SurgeWaveDelay = SurgeWaveDelayMax; + if(SurgeWaveDelay < SurgeWaveDelayMax) return; + if(SurgeFXSwitchValue != 1.f) + { + SurgeFXSwitchValue + LocWorld->DeltaTimeSeconds / AppearLength > 1.f ? SurgeFXSwitchValue = 1.f : SurgeFXSwitchValue = SurgeFXSwitchValue + LocWorld->DeltaTimeSeconds / AppearLength; + SurgeFXComponent->SetFloatParameter(TEXT("BlackHole Switch"), SurgeFXSwitchValue); + } + else + { + if(!SurgeSFXComponent) + SurgeSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831011"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + } + ActivateTime = ActivateTime + LocWorld->DeltaTimeSeconds; + if(ActivateTime > SkillEffects[0].fEffectDuration) + { + RecoverySurgedNpc(); + NoxSkillHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SurgeWaveDelay = 0.f; + LocWorld->GetTimerManager().ClearTimer(SurgeActivate); + LocWorld->GetTimerManager().SetTimer(SurgeFXDeactivate, this, &ANoxSkill::CheckSurgeDeactivate, LocWorld->DeltaTimeSeconds, true); + } +} + +void ANoxSkill::CheckSurgeDeactivate() +{ + const UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this); + if(LocWorld == nullptr) return; + if(SurgeFXComponent->IsActive()) + { + if(SurgeFXSwitchValue - LocWorld->DeltaTimeSeconds / AppearLength > 0.f) + { + SurgeFXSwitchValue = SurgeFXSwitchValue - LocWorld->DeltaTimeSeconds / AppearLength; + SurgeFXComponent->SetFloatParameter(TEXT("BlackHole Switch"), SurgeFXSwitchValue); + } + else + { + SurgeFXComponent->SetFloatParameter(TEXT("BlackHole Switch"), SurgeFXSwitchValue); + SurgeFXComponent->Deactivate(); + } + } + else + { + LocWorld->GetTimerManager().ClearTimer(SurgeFXDeactivate); + SurgeFXDeactivate.Invalidate(); + FinishSkill(); + } +} + +void ANoxSkill::RecoverySurgedNpc() +{ + if(CurrentAffectNpc.Num() > 0) + { + for(ACoreNpc* LocNpc : CurrentAffectNpc) + { + IDamageable::Execute_ApplyRecoveryEvent(LocNpc, SkillEffects); + } + } +} + +void ANoxSkill::SkillAreaBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(ACoreNpc* LocNpc = Cast(OtherActor)) + { + if(!Cast(OtherActor)) + { + IDamageable::Execute_ApplyDamageEvent(LocNpc, Cast(SkillOwner), GetActorLocation(), SkillData.fDamage, SkillEffects); + CurrentAffectNpc.Add(LocNpc); + } + } +} + +void ANoxSkill::SkillAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + if(ACoreNpc* LocNpc = Cast(OtherActor)) + { + if(!Cast(OtherActor)) + CurrentAffectNpc.Remove(LocNpc); + } +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.h b/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.h new file mode 100644 index 0000000..711810d --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NoxSkill.h @@ -0,0 +1,77 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "NoxSkill.generated.h" + +UCLASS() +class PROJECTT_API ANoxSkill : public ACoreSkill +{ + GENERATED_BODY() + +public: + ANoxSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void AimSkill() override; + virtual void ActivateSkill() override; + virtual void ReleaseSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex) override; + virtual void ResetDefaultState() override; + void CheckSurgeActivateTime(); + void CheckSurgeDeactivate(); + void RecoverySurgedNpc(); + + UFUNCTION() + void SkillAreaBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult); + + UFUNCTION() + void SkillAreaEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr NoxSkillRootScene; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr WandFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr SurgeFXComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr NoxSkillHitCollisionComponent; + + UPROPERTY() + TObjectPtr SurgeSFXComponent; + + UPROPERTY() + TArray CurrentAffectNpc; + +private: + float SurgeWaveDelayMax; + float SurgeWaveDelay; + float AppearLength; + float ActivateTime; + float SurgeFXSwitchValue; + FRotator SetRotation; + + UPROPERTY() + FTimerHandle SurgeActivate; + + UPROPERTY() + FTimerHandle SurgeFXDeactivate; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.cpp new file mode 100644 index 0000000..f4acae9 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.cpp @@ -0,0 +1,141 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NpcGAtk.h" + +#include "NiagaraComponent.h" +#include "Components/BoxComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +ANpcGAtk::ANpcGAtk() : + MeleeAttackCollisionComponent(nullptr), + MeleeSwingFXComponent(nullptr), + MeleeHitFXComponent(nullptr), + SkillNpcOwner(nullptr) +{ + SkillRowName = "311152"; + SkillId = 311152; + SkillPoolsize = 5; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + MeleeAttackCollisionComponent = CreateDefaultSubobject(TEXT("MeleeAttackCollisionComponent")); + MeleeSwingFXComponent = CreateDefaultSubobject(TEXT("MeleeSwingFXComponent")); + MeleeHitFXComponent = CreateDefaultSubobject(TEXT("MeleeHitFXComponent")); + NMT_CHECKF(MeleeAttackCollisionComponent && MeleeSwingFXComponent && MeleeHitFXComponent) + + MeleeAttackCollisionComponent->SetCollisionProfileName(TEXT("EnemyHit")); + MeleeAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + MeleeAttackCollisionComponent->SetupAttachment(RootComponent); + MeleeAttackCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ANpcGAtk::DefaultCollisionBeginOverlap); + + MeleeSwingFXComponent->SetupAttachment(MeleeAttackCollisionComponent); + MeleeSwingFXComponent->bAutoActivate = false; + + MeleeHitFXComponent->SetupAttachment(MeleeAttackCollisionComponent); + MeleeHitFXComponent->bAutoActivate = false; + + BodyHitComponent = MeleeAttackCollisionComponent; + RangeHitComponent = MeleeAttackCollisionComponent; +} + +void ANpcGAtk::BeginPlay() +{ + Super::BeginPlay(); + + SetActorTickEnabled(false); +} + +void ANpcGAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ANpcGAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ANpcGAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + + ResetDefaultState(); +} + +void ANpcGAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ANpcGAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ANpcGAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + MeleeSwingFXComponent->Activate(true); + } + else + { + MeleeSwingFXComponent->Deactivate(); + } +} + +void ANpcGAtk:: ResetDefaultState() +{ + Super::ResetDefaultState(); + + SetActorTickEnabled(false); + SetSkillOwner(nullptr); + SkillHitEnable(false); + SkillFXEnable(false); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + SetActorLocation(FVector::ZeroVector); +} + +void ANpcGAtk::StartSkill() +{ + SkillNpcOwner = Cast(SkillOwner); + if(SkillNpcOwner) + { + AttachToActor(SkillNpcOwner, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + MeleeSwingFXComponent->AttachToComponent(SkillNpcOwner->GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, TEXT("SKT_AgentG_Baton_R")); + SetActorTickEnabled(true); + } +} + +void ANpcGAtk::FinishSkill() +{ + Super::FinishSkill(); +} + +void ANpcGAtk::SkillHitEnable(bool InbEnable) +{ + if(!SkillNpcOwner) + return; + + if(InbEnable) + { + MeleeAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + } + else + { + MeleeAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } +} + +void ANpcGAtk::DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(Cast(OtherActor)) + { + IDamageable::Execute_ApplyDamageEvent(OtherActor, Cast(SkillOwner), SkillNpcOwner->GetActorLocation(), SkillData.fDamage, SkillEffects); + MeleeHitFXComponent->Activate(true); + SkillHitEnable(false); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.h b/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.h new file mode 100644 index 0000000..2314e67 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NpcGAtk.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "NpcGAtk.generated.h" + +UCLASS() +class PROJECTT_API ANpcGAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + ANpcGAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + +protected: + virtual void StartSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr MeleeAttackCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr MeleeSwingFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr MeleeHitFXComponent; + + UPROPERTY() + TObjectPtr SkillNpcOwner; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.cpp new file mode 100644 index 0000000..2f497b8 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.cpp @@ -0,0 +1,224 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NpcRAtk.h" + +#include "NiagaraComponent.h" +#include "Components/SphereComponent.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + + +ANpcRAtk::ANpcRAtk() : + DirectAttackCollisionComponent(nullptr), + BulletMeshComponent(nullptr), + ShootFXComponent(nullptr), + BulletTrailFXComponent(nullptr), + BulletHitFXComponent(nullptr), + ProjectileMovementComponent(nullptr), + SkillNpcOwner(nullptr), + StartLocation(FVector::ZeroVector), + bHit(false) +{ + SkillRowName = "311251"; + SkillId = 311251; + SkillPoolsize = 10; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + DirectAttackCollisionComponent = CreateDefaultSubobject(TEXT("DirectAttackCollisionComponent")); + ProjectileMovementComponent = CreateDefaultSubobject(TEXT("ProjectileMovementComponent")); + BulletMeshComponent = CreateDefaultSubobject(TEXT("BulletMeshComponent")); + ShootFXComponent = CreateDefaultSubobject(TEXT("ShootFXComponent")); + BulletHitFXComponent = CreateDefaultSubobject(TEXT("BulletHitFXComponent")); + BulletTrailFXComponent = CreateDefaultSubobject(TEXT("BulletTrailFXComponent")); + NMT_CHECKF(DirectAttackCollisionComponent && ProjectileMovementComponent && BulletMeshComponent && ShootFXComponent && BulletHitFXComponent && BulletTrailFXComponent) + + DirectAttackCollisionComponent->SetSphereRadius(16.f); + DirectAttackCollisionComponent->SetCollisionProfileName(TEXT("EnemyHit")); + DirectAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + DirectAttackCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ANpcRAtk::DefaultCollisionBeginOverlap); + DirectAttackCollisionComponent->SetupAttachment(RootComponent); + DirectAttackCollisionComponent->SetUseCCD(true); + + ProjectileMovementComponent->SetUpdatedComponent(RootComponent); + ProjectileMovementComponent->InitialSpeed = ProjectileMovementComponent->MaxSpeed = SkillData.fProjectileSpeed; + ProjectileMovementComponent->ProjectileGravityScale = 0.f; + ProjectileMovementComponent->bAutoActivate = false; + ProjectileMovementComponent->Deactivate(); + + BulletMeshComponent->SetupAttachment(RootComponent); + BulletMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + BulletMeshComponent->SetHiddenInGame(true); + + ShootFXComponent->SetupAttachment(RootComponent); + ShootFXComponent->bAutoActivate = false; + + BulletHitFXComponent->SetupAttachment(RootComponent); + BulletHitFXComponent->bAutoActivate = false; + + BulletTrailFXComponent->SetupAttachment(RootComponent); + BulletTrailFXComponent->bAutoActivate = false; + + BodyHitComponent = DirectAttackCollisionComponent; + RangeHitComponent = DirectAttackCollisionComponent; +} + +void ANpcRAtk::BeginPlay() +{ + Super::BeginPlay(); + + SetActorTickEnabled(false); +} + +void ANpcRAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ANpcRAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().ClearTimer(RangeCheckTimerHandle); + World->GetTimerManager().ClearTimer(ShootPoseCoolDownTimerHandle); +} + +void ANpcRAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ANpcRAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + + ResetDefaultState(); +} + +void ANpcRAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ANpcRAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ANpcRAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + ShootFXComponent->Activate(true); + } + else + { + ShootFXComponent->Deactivate(); + } +} + +void ANpcRAtk::ResetDefaultState() +{ + Super::ResetDefaultState(); + + SetActorTickEnabled(false); + SetSkillOwner(nullptr); + SkillHitEnable(false); + SkillFXEnable(false); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + SetActorLocation(FVector::ZeroVector); + bHit = false; +} + +void ANpcRAtk::StartSkill() +{ + Super::StartSkill(); +} + +void ANpcRAtk::ActivateSkill() +{ + Super::ActivateSkill(); + + SkillNpcOwner = Cast(SkillOwner); + if(SkillNpcOwner) + { + AttachToComponent(SkillNpcOwner->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_NPC_Gun_R")); + ShootFXComponent->AttachToComponent(SkillNpcOwner->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_NPC_Gun_R")); + } +} + +void ANpcRAtk::FinishSkill() +{ + SkillHitEnable(false); + SetActorTickEnabled(false); + + Super::FinishSkill(); +} + +void ANpcRAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + DirectAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + BulletMeshComponent->SetHiddenInGame(false); + ShootProjectile(); + } + else + { + DirectAttackCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + BulletMeshComponent->SetHiddenInGame(true); + + GetWorldTimerManager().ClearTimer(RangeCheckTimerHandle); + RangeCheckTimerHandle.Invalidate(); + + ProjectileMovementComponent->Deactivate(); + BulletTrailFXComponent->Deactivate(); + } +} + +void ANpcRAtk::DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if(OtherActor != SkillNpcOwner && !Cast(OtherActor)) + { + if(Cast(OtherActor)) + { + IDamageable::Execute_ApplyDamageEvent(OtherActor, Cast(SkillOwner), GetActorLocation(), SkillData.fDamage, SkillEffects); + } + bHit = true; + BulletHitFXComponent->Activate(true); + SkillHitEnable(false); + } +} + +void ANpcRAtk::ShootProjectile() +{ + if(SkillNpcOwner) + { + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ProjectileMovementComponent->Velocity = SkillNpcOwner->GetActorForwardVector() * SkillData.fProjectileSpeed; + ProjectileMovementComponent->Activate(); + StartLocation = GetActorLocation(); + BulletTrailFXComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + BulletTrailFXComponent->Activate(true); + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().SetTimer(RangeCheckTimerHandle, this, &ANpcRAtk::CheckDistance, World->GetDeltaSeconds(), true); + if(bHit) + { + SkillHitEnable(false); + } + } +} + +void ANpcRAtk::CheckDistance() +{ + if(UKismetMathLibrary::Vector_Distance(StartLocation, GetActorLocation()) > SkillData.fSkillRange) + { + SkillHitEnable(false); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.h b/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.h new file mode 100644 index 0000000..b862566 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/NpcRAtk.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "NpcRAtk.generated.h" + +UCLASS() +class PROJECTT_API ANpcRAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + ANpcRAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + +protected: + virtual void StartSkill() override; + virtual void ActivateSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +private: + void ShootProjectile(); + void CheckDistance(); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr DirectAttackCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr BulletMeshComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ShootFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr BulletTrailFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr BulletHitFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ProjectileMovementComponent; + + UPROPERTY() + TObjectPtr SkillNpcOwner; + + UPROPERTY() + FTimerHandle RangeCheckTimerHandle; + + UPROPERTY() + FTimerHandle ShootPoseCoolDownTimerHandle; + + FVector StartLocation; + uint8 bHit : 1; + +}; + diff --git a/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.cpp new file mode 100644 index 0000000..dac4046 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.cpp @@ -0,0 +1,133 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PyroAtk.h" +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/BoxComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +APyroAtk::APyroAtk() : + PyroAtkRootSceneComponent(nullptr), + PyroAtkCollisionComponent(nullptr), + PyroAtkFXComponent(nullptr) +{ + SkillPoolsize = 2; + SkillRowName = "311101"; + SkillId = 311101; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + PyroAtkRootSceneComponent = CreateDefaultSubobject(TEXT("PyroAtkRootSceneComponent")); + PyroAtkCollisionComponent = CreateDefaultSubobject(TEXT("PyroAtkCollisionComponent")); + PyroAtkFXComponent = CreateDefaultSubobject(TEXT("PyroAtkFXComponent")); + + PyroAtkRootSceneComponent->SetupAttachment(RootComponent); + PyroAtkCollisionComponent->SetupAttachment(PyroAtkRootSceneComponent); + PyroAtkCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + PyroAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + PyroAtkCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&APyroAtk::BoxCollisionBeginOverlap); + + PyroAtkFXComponent->SetupAttachment(RootComponent); + PyroAtkFXComponent->bAutoActivate = false; + + BodyHitComponent = PyroAtkCollisionComponent; + RangeHitComponent = PyroAtkCollisionComponent; +} + +void APyroAtk::BeginPlay() +{ + Super::BeginPlay(); +} + +void APyroAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void APyroAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void APyroAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + if (SkillOwner == nullptr) return; + SkillOwner = nullptr; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void APyroAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void APyroAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void APyroAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); +} + +void APyroAtk::StartSkill() +{ + ; + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToComponent(LocPlayerCharacter->SkillRootScene,FAttachmentTransformRules::SnapToTargetNotIncludingScale); + PyroAtkFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Pyro_Firepunch_L")); + } +} + +void APyroAtk::CancelSkill() +{ + SkillHitEnable(false); + SkillFXEnable(false); + Super::FinishSkill(); +} + +void APyroAtk::FinishSkill() +{ + Super::FinishSkill(); +} + +void APyroAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + PyroAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + MakeSkillNoise(); + } + else + { + PyroAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } +} + +void APyroAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(InbEnable) + { + PyroAtkFXComponent->Activate(true); + } + else + { + PyroAtkFXComponent->Deactivate(); + } +} + +void APyroAtk::BoxCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, + UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(ACoreNpc* LocHitNpc = Cast(OtherActor)) + { + IDamageable::Execute_ApplyDamageEvent(LocHitNpc, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocHitNpc), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocHitNpc->GetActorLocation()); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.h b/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.h new file mode 100644 index 0000000..275c676 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/PyroAtk.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "PyroAtk.generated.h" + +UCLASS() +class PROJECTT_API APyroAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + APyroAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + + UFUNCTION() + void BoxCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr PyroAtkRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr PyroAtkCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr PyroAtkFXComponent; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.cpp new file mode 100644 index 0000000..4e61e5b --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.cpp @@ -0,0 +1,281 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PyroSkill.h" +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/AudioComponent.h" +#include "Components/SphereComponent.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "Kismet/GameplayStatics.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +APyroSkill::APyroSkill() : + FireBallRootScene(nullptr), + ThrowFXComponent(nullptr), + ExplosionFXComponent(nullptr), + FireBallMeshComponent(nullptr), + FireBallHitCollisionComponent(nullptr), + FireBallEffectCollisionComponent(nullptr), + ThrowSFXComponent(nullptr), + ExplosionSFXComponent(nullptr), + ProjectileMovementComponent(nullptr), + bHit(false) +{ + SkillPoolsize = 5; + SkillRowName = "312201"; + SkillId = 312201; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + FireBallRootScene = CreateDefaultSubobject(TEXT("FireBallRootScene")); + FireBallMeshComponent = CreateDefaultSubobject(TEXT("FireBallMeshComponent")); + FireBallHitCollisionComponent = CreateDefaultSubobject(TEXT("FireBallHitCollisionComponent")); + FireBallEffectCollisionComponent = CreateDefaultSubobject(TEXT("FireBallEffectCollisionComponent")); + ProjectileMovementComponent = CreateDefaultSubobject(TEXT("ProjectileMovementComponent")); + ThrowFXComponent = CreateDefaultSubobject(TEXT("ThrowFxComponent")); + ExplosionFXComponent = CreateDefaultSubobject(TEXT("ExplosionFxComponent")); + + FireBallRootScene->SetupAttachment(RootComponent); + + FireBallMeshComponent->SetupAttachment(FireBallRootScene); + FireBallMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + FireBallMeshComponent->SetHiddenInGame(true); + + FireBallHitCollisionComponent->SetupAttachment(FireBallMeshComponent); + FireBallHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + FireBallHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + FireBallHitCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&APyroSkill::DefaultCollisionBeginOverlap); + + FireBallEffectCollisionComponent->SetupAttachment(RootComponent); + FireBallEffectCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + FireBallEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + FireBallEffectCollisionComponent->SetSphereRadius(SkillData.fEffectRange); + + ProjectileMovementComponent->SetUpdatedComponent(RootComponent); + ProjectileMovementComponent->InitialSpeed = ProjectileMovementComponent->MaxSpeed = SkillData.fProjectileSpeed; + ProjectileMovementComponent->ProjectileGravityScale = 0.f; + ProjectileMovementComponent->bAutoActivate = false; + ProjectileMovementComponent->Deactivate(); + + ThrowFXComponent->SetupAttachment(FireBallRootScene); + ThrowFXComponent->bAutoActivate = false; + ExplosionFXComponent->SetupAttachment(FireBallRootScene); + ExplosionFXComponent->bAutoActivate = false; + + BodyHitComponent = FireBallHitCollisionComponent; + RangeHitComponent = FireBallEffectCollisionComponent; +} + +void APyroSkill::BeginPlay() +{ + Super::BeginPlay(); + SetActorTickEnabled(false); +} + +void APyroSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void APyroSkill::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void APyroSkill::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void APyroSkill::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void APyroSkill::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void APyroSkill::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(RangeCheckTimer); + LocWorld->GetTimerManager().ClearTimer(ExplosionCheckTimer); + } + Super::EndPlay(EndPlayReason); +} + +void APyroSkill::StartSkill() +{ + if(bAimState) ReleaseSkill(); +} + +void APyroSkill::AimSkill() +{ + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + if(!LocPlayerCharacter) return; + bCanceled = false; + bAimState = true; + AttachToActor(LocPlayerCharacter,FAttachmentTransformRules::SnapToTargetNotIncludingScale); + ThrowFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale,TEXT("SKT_Pyro_Fireball_R")); + ThrowFXComponent->Activate(true); +} + +void APyroSkill::ActivateSkill() +{ + if(bActivated) return; + bAimState = false; + bActivated = true; +} + +void APyroSkill::ReleaseSkill() +{ + bCanceled = true; + bReleased = true; + FinishSkill(); +} + +void APyroSkill::CancelSkill() +{ + bCanceled = true; + FinishSkill(); +} + +void APyroSkill::FinishSkill() +{ + Super::FinishSkill(); +} + +void APyroSkill::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + FireBallMeshComponent->SetHiddenInGame(false); + ProjectileFireBall(); + FireBallHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + NMT_CHECKF(SkillOwner); + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + LocPlayerCharacter->SetCurrentSkill(false); + } + else + { + UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this); + if(!LocWorld) return; + FireBallEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + ThrowFXComponent->Deactivate(); + FireBallMeshComponent->SetHiddenInGame(true); + LocWorld->GetTimerManager().ClearTimer(RangeCheckTimer); + RangeCheckTimer.Invalidate(); + LocWorld->GetTimerManager().SetTimer(ExplosionCheckTimer, this, &APyroSkill::CheckActiveExplosion, LocWorld->DeltaTimeSeconds, true); + } +} + +void APyroSkill::ResetDefaultState() +{ + Super::ResetDefaultState(); + if (SkillOwner != nullptr) + { + SkillOwner = nullptr; + } + bHit = false; + bCanceled = false; + bAimState = false; + bActivated = false; + bReleased = false; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ThrowFXComponent->Deactivate(); +} + +void APyroSkill::ProjectileFireBall() +{ + if (SkillOwner) + { + ThrowSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831002"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + ThrowFXComponent->AttachToComponent(FireBallRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale,TEXT("SKT_Pyro_Fireball_R")); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + FVector LocMaxLocation = LocPlayerCharacter->SkillRootScene->GetComponentLocation() + + UKismetMathLibrary::GetForwardVector(LocPlayerCharacter->SkillRootScene->GetComponentRotation()) * SkillData.fSkillRange; + FRotator LocLookAtMaxLocation = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(),LocMaxLocation); + SetActorRotation(LocLookAtMaxLocation); + ProjectileMovementComponent->Velocity = GetActorForwardVector() * SkillData.fProjectileSpeed; + ProjectileMovementComponent->Activate(); + InitLocation = GetActorLocation(); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(RangeCheckTimer, this, &APyroSkill::CheckDistance, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void APyroSkill::ExplosionFireBall() +{ + bHit = true; + if(ThrowSFXComponent) ThrowSFXComponent.Get()->StopDelayed(0.15f); + UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831003"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + ProjectileMovementComponent->Deactivate(); + FireBallHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + FireBallEffectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + TArray OverlappedActors; + FireBallEffectCollisionComponent->GetOverlappingActors(OverlappedActors, ACoreNpc::StaticClass()); + ExplosionFXComponent->Activate(true); + if (OverlappedActors.Num() >= 1) + { + for (AActor* LocOverlapActor : OverlappedActors) + { + TArray LocIgnoreActors; + FHitResult LocTraceHitResult; + UKismetSystemLibrary::LineTraceSingle(this, GetActorLocation(), LocOverlapActor->GetActorLocation(), + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocTraceHitResult, true); + if(!LocTraceHitResult.bBlockingHit) + { + IDamageable::Execute_ApplyDamageEvent(LocOverlapActor, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(LocOverlapActor, true), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocOverlapActor->GetActorLocation()); + } + } + } + } + MakeSkillNoise(true); + SkillHitEnable(false); +} + +void APyroSkill::CheckDistance() +{ + if(UKismetMathLibrary::Vector_Distance(InitLocation, GetActorLocation()) > SkillData.fSkillRange) + { + ExplosionFireBall(); + } +} + +void APyroSkill::CheckActiveExplosion() +{ + if(ExplosionFXComponent->IsActive()) return; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(ExplosionCheckTimer); + ExplosionCheckTimer.Invalidate(); + FinishSkill(); + } +} + +void APyroSkill::DefaultCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, + UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(!bHit && OtherActor != SkillOwner) + { + MovedComponentToHitPoint(OtherActor, FireBallEffectCollisionComponent); + ExplosionFireBall(); + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.h b/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.h new file mode 100644 index 0000000..cee5c85 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/PyroSkill.h @@ -0,0 +1,77 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "PyroSkill.generated.h" + +UCLASS() +class PROJECTT_API APyroSkill : public ACoreSkill +{ + GENERATED_BODY() + +public: + APyroSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; +protected: + virtual void StartSkill() override; + virtual void AimSkill() override; + virtual void ActivateSkill() override; + virtual void ReleaseSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + void ProjectileFireBall(); + void ExplosionFireBall(); + void CheckDistance(); + void CheckActiveExplosion(); + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr FireBallRootScene; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ThrowFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ExplosionFXComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr FireBallMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr FireBallHitCollisionComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr FireBallEffectCollisionComponent; + + UPROPERTY() + TObjectPtr ThrowSFXComponent; + + UPROPERTY() + TObjectPtr ExplosionSFXComponent; + + UPROPERTY() + TObjectPtr ProjectileMovementComponent; + +private: + bool bHit; + FVector InitLocation; + + UPROPERTY() + FTimerHandle RangeCheckTimer; + + UPROPERTY() + FTimerHandle ExplosionCheckTimer; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.cpp b/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.cpp new file mode 100644 index 0000000..0c6d9db --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.cpp @@ -0,0 +1,317 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SmokeShell.h" +#include "NiagaraComponent.h" +#include "Components/BoxComponent.h" +#include "Components/SphereComponent.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +ASmokeShell::ASmokeShell() : + SmokeShellRootScene(nullptr), + ThrowFXComponent(nullptr), + ExplosionFXComponent(nullptr), + SmokeShellMeshComponent(nullptr), + SmokeShellHitCollisionComponent(nullptr), + UnDetectCollisionComponent(nullptr), + SmokeShellSFXComponent(nullptr), + ProjectileMovementComponent(nullptr), + CurrentActiveTime(0.f), + bHit(false), + CurrentOverlapPlayer(nullptr) +{ + SkillPoolsize = 5; + SkillRowName = "313301"; + SkillId = 313301; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + SmokeShellRootScene = CreateDefaultSubobject(TEXT("SmokeShellRootScene")); + SmokeShellMeshComponent = CreateDefaultSubobject(TEXT("SmokeShellMeshComponent")); + SmokeShellHitCollisionComponent = CreateDefaultSubobject(TEXT("SmokeShellHitCollisionComponent")); + UnDetectCollisionComponent = CreateDefaultSubobject(TEXT("UnDectCollisionComponent")); + ThrowFXComponent = CreateDefaultSubobject(TEXT("ThrowFXComponent")); + ExplosionFXComponent = CreateDefaultSubobject(TEXT("ExplosionFXComponent")); + ProjectileMovementComponent = CreateDefaultSubobject(TEXT("ProjectileMovementComponent")); + + SmokeShellRootScene->SetupAttachment(RootComponent); + + SmokeShellMeshComponent->SetupAttachment(SmokeShellRootScene); + SmokeShellMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + + SmokeShellHitCollisionComponent->SetupAttachment(SmokeShellMeshComponent); + SmokeShellHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + SmokeShellHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SmokeShellHitCollisionComponent->SetSphereRadius(1.f); + SmokeShellHitCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&ASmokeShell::DefaultCollisionBeginOverlap); + + UnDetectCollisionComponent->SetupAttachment(RootComponent); + UnDetectCollisionComponent->SetCollisionProfileName(TEXT("InteractionRange")); + UnDetectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + UnDetectCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&ASmokeShell::UnDetectCollisionBeginOverlap); + UnDetectCollisionComponent->OnComponentEndOverlap.AddDynamic(this,&ASmokeShell::UnDetectCollisionEndOverlap); + + ProjectileMovementComponent->SetUpdatedComponent(RootComponent); + ProjectileMovementComponent->bAutoActivate = false; + ProjectileMovementComponent->Deactivate(); + + ExplosionFXComponent->SetupAttachment(SmokeShellRootScene); + ExplosionFXComponent->bAutoActivate = false; + + BodyHitComponent = SmokeShellHitCollisionComponent; + RangeHitComponent = UnDetectCollisionComponent; +} + +void ASmokeShell::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASmokeShell::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASmokeShell::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ASmokeShell::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void ASmokeShell::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ASmokeShell::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ASmokeShell::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(UnDetectTimerHandle); + LocWorld->GetTimerManager().ClearTimer(RotatorTimerHandle); + } + Super::EndPlay(EndPlayReason); +} + +void ASmokeShell::StartSkill() +{ + if(bAimState) ReleaseSkill(); +} + +void ASmokeShell::AimSkill() +{ + bCanceled = false; + bAimState = true; + AttachToActor(SkillOwner, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + ACombatCharacter* LocPlayerCharacter = Cast(SkillOwner); + SmokeShellMeshComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale,TEXT("hand_r")); + SmokeShellMeshComponent->SetHiddenInGame(false); + ThrowFXComponent->Activate(true); +} + +void ASmokeShell::ActivateSkill() +{ + if(bActivated) return; + bActivated = true; + bAimState = false; +} + +void ASmokeShell::ReleaseSkill() +{ + bCanceled = true; + bReleased = true; + FinishSkill(); +} + +void ASmokeShell::CancelSkill() +{ + bCanceled = true; + FinishSkill(); +} + +void ASmokeShell::FinishSkill() +{ + Super::FinishSkill(); +} + +void ASmokeShell::SkillHitEnable(bool InbEnable) +{ + if (InbEnable) + { + ProjectileSmokeShell(); + SmokeShellHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + LocPlayerCharacter->SetCurrentSkill(false); + } + else + { + ThrowFXComponent->Deactivate(); + ProjectileMovementComponent->Deactivate(); + SmokeShellHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SmokeShellMeshComponent->SetHiddenInGame(true); + UnDetectCollisionComponent->SetBoxExtent(FVector(SkillData.fEffectRange)); + UnDetectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(UnDetectTimerHandle, this, &ASmokeShell::CheckActiveTime, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ASmokeShell::ResetDefaultState() +{ + Super::ResetDefaultState(); + if(SkillOwner != nullptr) SkillOwner = nullptr; + CurrentActiveTime = 0.f; + bHit = false; + bCanceled = false; + bAimState = false; + bActivated = false; + bReleased = false; + SmokeShellMeshComponent->SetHiddenInGame(true); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ThrowFXComponent->Deactivate(); + ExplosionFXComponent->Deactivate(); + if(CurrentOverlapPlayer) ReleaseEffects(CurrentOverlapPlayer); + ReleaseNpc(); + UnDetectCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); +} + +void ASmokeShell::ProjectileSmokeShell() +{ + if (SkillOwner) + { + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + ThrowFXComponent->AttachToComponent(SmokeShellRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + SmokeShellMeshComponent->AttachToComponent(SmokeShellRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + SetParabolaLaunchVelocity(); + ProjectileMovementComponent->Velocity = LaunchVelocity; + InitLocation = GetActorLocation(); + ProjectileMovementComponent->Activate(); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(RotatorTimerHandle, this, &ASmokeShell::RotateSmokeMesh, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ASmokeShell::ExplosionSmokeShell() +{ + MakeSkillNoise(true); + SmokeShellSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831019"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) LocWorld->GetTimerManager().ClearTimer(RotatorTimerHandle); + ExplosionFXComponent->Activate(true); + ExplosionFXComponent->SetFloatParameter(TEXT("Size"), SkillData.fEffectRange / 100.f); + ExplosionFXComponent->SetIntParameter(TEXT("LoopCount"), SkillEffects[0].fEffectDuration); + bHit = true; + SkillHitEnable(false); +} + +void ASmokeShell::CheckActiveTime() +{ + const UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this); + if(LocWorld == nullptr) return; + if(CurrentActiveTime > SkillEffects[0].fEffectDuration) + { + LocWorld->GetTimerManager().ClearTimer(UnDetectTimerHandle); + Super::FinishSkill(); + } + else + { + CurrentActiveTime = CurrentActiveTime + LocWorld->DeltaTimeSeconds; + } +} + +void ASmokeShell::RotateSmokeMesh() const +{ + FRotator LocAddRotator(10.f,3.f,1.f); + SmokeShellMeshComponent->AddLocalRotation(LocAddRotator); +} + +void ASmokeShell::ReleaseEffects(AActor* InReleaseActor) +{ + TArray LocReleaseEffects; + FEffect LocReleaseEffect; + if(Cast(InReleaseActor)) + { + LocReleaseEffect.sEffect = EnumToString(EEffectSubTypes::CogImmune); + LocReleaseEffects.Add(LocReleaseEffect); + } + if(Cast(InReleaseActor)) + { + LocReleaseEffect.sEffect = EnumToString(EEffectSubTypes::Unrecog); + LocReleaseEffects.Add(LocReleaseEffect); + } + IDamageable::Execute_ApplyRecoveryEvent(InReleaseActor, LocReleaseEffects); +} + +void ASmokeShell::ReleaseNpc() const +{ + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(this); + TArray LocNpcCharacters; + LocGameMode->GetNpcCharacters(LocNpcCharacters); + for(AActor* LocNpc : LocNpcCharacters) + { + TArray LocNpcEffectTypes; + IDamageable::Execute_GetCurrentEffectTypes(LocNpc, LocNpcEffectTypes); + if(!LocNpcEffectTypes.Contains(EEffectSubTypes::Unrecog)) + { + TArray LocEffects; + FEffect LocEffect; + const FString LocUnrecogString = UGlobalUtilsLibrary::GetEnumToString(EEffectSubTypes::Unrecog); + LocEffect.sEffect = LocUnrecogString; + LocEffects.Add(LocEffect); + IDamageable::Execute_ApplyRecoveryEvent(LocNpc, LocEffects); + } + } +} + +void ASmokeShell::DefaultCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, + UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(!bHit && OtherComp->GetCollisionProfileName() == TEXT("Ground")) ExplosionSmokeShell(); +} + +void ASmokeShell::UnDetectCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, + UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(ACorePlayerCharacter* LocPlayer = Cast(OtherActor)) + { + CurrentOverlapPlayer = LocPlayer; + IDamageable::Execute_ApplyDamageEvent(OtherActor, Cast(SkillOwner), GetActorLocation(), SkillData.fDamage, SkillEffects); + } + if(ACoreNpc* LocNpc = Cast(OtherActor)) + { + CurrentOverlapNpc.AddUnique(LocNpc); + IDamageable::Execute_ApplyDamageEvent(LocNpc, Cast(SkillOwner), GetActorLocation(), SkillData.fDamage, SkillEffects); + } +} + +void ASmokeShell::UnDetectCollisionEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + if(ACorePlayerCharacter* LocPlayer = Cast(OtherActor)) + { + CurrentOverlapPlayer = nullptr; + ReleaseEffects(LocPlayer); + } + if(ACoreNpc* LocNpc = Cast(OtherActor)) + { + CurrentOverlapNpc.Remove(LocNpc); + ReleaseEffects(LocNpc); + } +} diff --git a/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.h b/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.h new file mode 100644 index 0000000..924b208 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SmokeShell.h @@ -0,0 +1,88 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "SmokeShell.generated.h" + +UCLASS() +class PROJECTT_API ASmokeShell : public ACoreSkill +{ + GENERATED_BODY() + +public: + ASmokeShell(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void AimSkill() override; + virtual void ActivateSkill() override; + virtual void ReleaseSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + void ProjectileSmokeShell(); + void ExplosionSmokeShell(); + void CheckActiveTime(); + void RotateSmokeMesh() const; + void ReleaseEffects(AActor* InReleaseActor); + void ReleaseNpc() const; + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void UnDetectCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void UnDetectCollisionEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr SmokeShellRootScene; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ThrowFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr ExplosionFXComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr SmokeShellMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr SmokeShellHitCollisionComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr UnDetectCollisionComponent; + + UPROPERTY() + TObjectPtr SmokeShellSFXComponent; + + UPROPERTY() + TObjectPtr ProjectileMovementComponent; + +private: + TArray CurrentOverlapNpc; + FVector InitLocation; + float CurrentActiveTime; + bool bHit; + + UPROPERTY() + FTimerHandle UnDetectTimerHandle; + + UPROPERTY() + FTimerHandle RotatorTimerHandle; + + UPROPERTY() + class ACorePlayerCharacter* CurrentOverlapPlayer; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.cpp b/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.cpp new file mode 100644 index 0000000..c71bff6 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.cpp @@ -0,0 +1,145 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SneakoAtk.h" + +#include "NiagaraComponent.h" +#include "NiagaraFunctionLibrary.h" +#include "Components/BoxComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +ASneakoAtk::ASneakoAtk() : + SneakoAtkRootSceneComponent(nullptr), + SneakoAtkCollisionComponent(nullptr), + SneakoAtkFXComponent(nullptr) +{ + SkillPoolsize = 3; + SkillRowName = "311102"; + SkillId = 311102; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + SneakoAtkRootSceneComponent = CreateDefaultSubobject(TEXT("SneakoAtkRootSceneComponent")); + SneakoAtkCollisionComponent = CreateDefaultSubobject(TEXT("SneakoAtkCollisionComponent")); + SneakoAtkFXComponent = CreateDefaultSubobject(TEXT("SneakoAtkFXComponent")); + + SneakoAtkRootSceneComponent->SetupAttachment(RootComponent); + SneakoAtkCollisionComponent->SetupAttachment(SneakoAtkRootSceneComponent); + SneakoAtkCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + SneakoAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SneakoAtkCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&ASneakoAtk::BoxCollisionBeginOverlap); + + BodyHitComponent = SneakoAtkCollisionComponent; + RangeHitComponent = SneakoAtkCollisionComponent; + + SneakoAtkFXComponent->bAutoActivate = false; +} + +void ASneakoAtk::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASneakoAtk::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASneakoAtk::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ASneakoAtk::Disable_Implementation() +{ + Super::Disable_Implementation(); + if(SkillOwner == nullptr) return; + SneakoAtkFXComponent->Deactivate(); + SkillOwner = nullptr; + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void ASneakoAtk::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ASneakoAtk::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ASneakoAtk::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(FXDeactivateTimerHandle); + } + Super::EndPlay(EndPlayReason); +} + +void ASneakoAtk::StartSkill() +{ + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToComponent(LocPlayerCharacter->SkillRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + SneakoAtkFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Sneako_Dagger_R")); + } +} + +void ASneakoAtk::CancelSkill() +{ + SkillHitEnable(false); + SkillFXEnable(false); + Super::FinishSkill(); +} + +void ASneakoAtk::FinishSkill() +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(FXDeactivateTimerHandle, this, &ASneakoAtk::CheckFXDeactivated, LocWorld->DeltaTimeSeconds, true); + } +} + +void ASneakoAtk::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + SneakoAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + MakeSkillNoise(); + SneakoAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } + else + { + SneakoAtkCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + } +} + +void ASneakoAtk::SkillFXEnable(bool InbEnable, int32 InIndex) +{ + if(!SneakoAtkFXComponent->GetAsset()) return; + if(InbEnable) SneakoAtkFXComponent->Activate(true); +} + +void ASneakoAtk::CheckFXDeactivated() +{ + if(SneakoAtkFXComponent->IsActive()) return; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(FXDeactivateTimerHandle); + FinishSkill(); + } +} + +void ASneakoAtk::BoxCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(ACoreNpc* LocHitNpc = Cast(OtherActor)) + { + IDamageable::Execute_ApplyDamageEvent(LocHitNpc, Cast(SkillOwner), GetActorLocation(), GetFinalDamage(OtherActor), SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) UNiagaraFunctionLibrary::SpawnSystemAtLocation(LocWorld, HitFXSystem, LocHitNpc->GetActorLocation()); + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.h b/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.h new file mode 100644 index 0000000..6853f76 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SneakoAtk.h @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "SneakoAtk.generated.h" + +UCLASS() +class PROJECTT_API ASneakoAtk : public ACoreSkill +{ + GENERATED_BODY() + +public: + ASneakoAtk(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillFXEnable(bool InbEnable, int32 InIndex = 0) override; + void CheckFXDeactivated(); + + UFUNCTION() + void BoxCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SneakoAtkRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SneakoAtkCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr SneakoAtkFXComponent; + + UPROPERTY() + FTimerHandle FXDeactivateTimerHandle; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.cpp b/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.cpp new file mode 100644 index 0000000..0ce0cd6 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.cpp @@ -0,0 +1,152 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SneakoSkill.h" + +#include "NiagaraComponent.h" +#include "Components/AudioComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +ASneakoSkill::ASneakoSkill() : + SneakoSkillRootSceneComponent(nullptr), + SneakoSkillMeshComponent(nullptr), + SneakoSkillFXComponent(nullptr), + TransformSFXComponent(nullptr), + CurrentActivateTime(0.f) +{ + SkillPoolsize = 2; + SkillRowName = "312402"; + SkillId = 312402; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + SneakoSkillRootSceneComponent = CreateDefaultSubobject(TEXT("SneakoSkillRootSceneComponent")); + SneakoSkillMeshComponent = CreateDefaultSubobject(TEXT("SneakoSkillMeshComponent")); + SneakoSkillFXComponent = CreateDefaultSubobject(TEXT("SneakoSkillFXComponent")); + + SneakoSkillRootSceneComponent->SetupAttachment(RootComponent); + SneakoSkillMeshComponent->SetupAttachment(RootComponent); + SneakoSkillMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SneakoSkillMeshComponent->SetHiddenInGame(true); + SneakoSkillFXComponent->bAutoActivate = false; +} + +void ASneakoSkill::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASneakoSkill::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASneakoSkill::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ASneakoSkill::Disable_Implementation() +{ + Super::Disable_Implementation(); + if (SkillOwner == nullptr) return; + bActivated = false; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + CurrentActivateTime = 0.f; + SneakoSkillMeshComponent->SetHiddenInGame(true); + SkillTimeEnd.Unbind(); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void ASneakoSkill::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ASneakoSkill::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ASneakoSkill::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + } + Super::EndPlay(EndPlayReason); +} + +void ASneakoSkill::StartSkill() +{ + bActivated ? ReleaseSkill() : ActivateSkill(); +} + +void ASneakoSkill::ActivateSkill() +{ + if(ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner)) + { + AttachToActor(LocPlayerCharacter, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + MakeSkillNoise(); + if(TransformSFXComponent) TransformSFXComponent.Get()->Stop(); + TransformSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831005"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + bActivated = true; + IDamageable::Execute_ApplyDamageEvent(SkillOwner, nullptr, FVector(), 0.f, SkillEffects); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(ActivateTimerHandle, this, &ASneakoSkill::CheckActiveTime, LocWorld->DeltaTimeSeconds, true); + } + SneakoSkillMeshComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + SneakoSkillMeshComponent->SetRelativeRotation(FRotator(0.f, 0.f, 0.f)); + SneakoSkillMeshComponent->SetHiddenInGame(false); + SneakoSkillFXComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Sneako_Box")); + SneakoSkillMeshComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("SKT_Sneako_Box")); + SneakoSkillFXComponent->Activate(true); + } +} + +void ASneakoSkill::ReleaseSkill() +{ + IDamageable::Execute_ApplyRecoveryEvent(SkillOwner, SkillEffects); + Super::ReleaseSkill(); + FinishSkill(); +} + +void ASneakoSkill::CancelSkill() +{ + IDamageable::Execute_ApplyRecoveryEvent(SkillOwner, SkillEffects); + Super::CancelSkill(); + FinishSkill(); +} + +void ASneakoSkill::FinishSkill() +{ + if(TransformSFXComponent) TransformSFXComponent.Get()->Stop(); + TransformSFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831005"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + SneakoSkillFXComponent->Activate(true); + Super::FinishSkill(); +} + +void ASneakoSkill::SkillHitEnable(bool InbEnable) +{ +} + +void ASneakoSkill::ResetDefaultState() +{ + Super::ResetDefaultState(); +} + +void ASneakoSkill::CheckActiveTime() +{ + const UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this); + if(LocWorld == nullptr) return; + CurrentActivateTime = CurrentActivateTime + LocWorld->DeltaTimeSeconds; + if(CurrentActivateTime >= SkillEffects[0].fEffectDuration) + { + LocWorld->GetTimerManager().ClearTimer(ActivateTimerHandle); + if(SkillTimeEnd.IsBound()) SkillTimeEnd.Execute(); + } +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.h b/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.h new file mode 100644 index 0000000..d36f146 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/SneakoSkill.h @@ -0,0 +1,51 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "SneakoSkill.generated.h" +UCLASS() +class PROJECTT_API ASneakoSkill : public ACoreSkill +{ + GENERATED_BODY() + +public: + ASneakoSkill(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void ActivateSkill() override; + virtual void ReleaseSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + void CheckActiveTime(); + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SneakoSkillRootSceneComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SneakoSkillMeshComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TObjectPtr SneakoSkillFXComponent; + + UPROPERTY() + TObjectPtr TransformSFXComponent; + +private: + float CurrentActivateTime; + + UPROPERTY() + FTimerHandle ActivateTimerHandle; +}; diff --git a/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.cpp b/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.cpp new file mode 100644 index 0000000..7fb5f0e --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.cpp @@ -0,0 +1,266 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "TumaiToy.h" + +#include "NiagaraComponent.h" +#include "Animations/AnimInstance/SkillObjectAnimInstance.h" +#include "Components/SphereComponent.h" +#include "GameFramework/ProjectileMovementComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" + +ATumaiToy::ATumaiToy() : + TumaiToyRootScene(nullptr), + MeshRootSceneComponent(nullptr), + TumaiToyMeshComponent(nullptr), + TumaiToyHitCollisionComponent(nullptr), + TumaiToyIdleAnimSequence(nullptr), + TumaiToyMontage(nullptr), + DissolveMaterialInstance(nullptr), + TumaiToySFXComponent(nullptr), + ProjectileMovementComponent(nullptr), + CurrentActiveTime(0.f), + DissolveValue(1.f), + bHit(false) +{ + SkillPoolsize = 5; + SkillRowName = "313302"; + SkillId = 313302; + InitializeSkillData(); + PrimaryActorTick.bCanEverTick = true; + + TumaiToyRootScene = CreateDefaultSubobject(TEXT("TumaiToyRootScene")); + MeshRootSceneComponent = CreateDefaultSubobject(TEXT("MeshRootScene")); + TumaiToyMeshComponent = CreateDefaultSubobject(TEXT("TumaiToyMeshComponent")); + TumaiToyHitCollisionComponent = CreateDefaultSubobject(TEXT("TumaiToyHitCollisionComponent")); + ProjectileMovementComponent = CreateDefaultSubobject(TEXT("ProjectileMovementComponent")); + + TumaiToyRootScene->SetupAttachment(RootComponent); + MeshRootSceneComponent->SetupAttachment(RootComponent); + + TumaiToyMeshComponent->SetupAttachment(MeshRootSceneComponent); + TumaiToyMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + TumaiToyMeshComponent->SetHiddenInGame(true); + + TumaiToyHitCollisionComponent->SetupAttachment(MeshRootSceneComponent); + TumaiToyHitCollisionComponent->SetCollisionProfileName(TEXT("PlayerHit")); + TumaiToyHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + TumaiToyHitCollisionComponent->SetSphereRadius(1.f); + TumaiToyHitCollisionComponent->OnComponentBeginOverlap.AddDynamic(this,&ATumaiToy::DefaultCollisionBeginOverlap); + + TumaiToyMeshComponent->SetHiddenInGame(true); + + ProjectileMovementComponent->SetUpdatedComponent(RootComponent); + ProjectileMovementComponent->bAutoActivate = false; + ProjectileMovementComponent->Deactivate(); + + BodyHitComponent = TumaiToyHitCollisionComponent; + RangeHitComponent = NoiseSphereComponent; +} + +void ATumaiToy::BeginPlay() +{ + Super::BeginPlay(); + if(USkillObjectAnimInstance* LocAnimInstance = Cast(TumaiToyMeshComponent->GetAnimInstance())) + LocAnimInstance->SetDefaultProperty(TumaiToyIdleAnimSequence, TumaiToyMontage); + if(DissolveMaterialInstance) TumaiToyMeshComponent->SetMaterial(0, DissolveMaterialInstance); +} + +void ATumaiToy::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ATumaiToy::Enable_Implementation() +{ + Super::Enable_Implementation(); +} + +void ATumaiToy::Disable_Implementation() +{ + Super::Disable_Implementation(); + ResetDefaultState(); +} + +void ATumaiToy::Pushed_Implementation() +{ + Super::Pushed_Implementation(); +} + +void ATumaiToy::Obtained_Implementation() +{ + Super::Obtained_Implementation(); +} + +void ATumaiToy::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(RotatorTimerHandle); + LocWorld->GetTimerManager().ClearTimer(FXDeactivateTimerHandle); + LocWorld->GetTimerManager().ClearTimer(DissolveTimerHandle); + } + Super::EndPlay(EndPlayReason); +} + +void ATumaiToy::StartSkill() +{ + if(bAimState) ReleaseSkill(); +} + +void ATumaiToy::AimSkill() +{ + bCanceled = false; + bAimState = true; + AttachToActor(SkillOwner, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + if(USkillObjectAnimInstance* LocAnimInstance = Cast(TumaiToyMeshComponent->GetAnimInstance())) + { + LocAnimInstance->Montage_Play(LocAnimInstance->GetSkillObjectMontage()); + } + ACombatCharacter* LocPlayerCharacter = Cast(SkillOwner); + TumaiToyMeshComponent->AttachToComponent(LocPlayerCharacter->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale,TEXT("hand_r")); + TumaiToyMeshComponent->SetHiddenInGame(false); + SetActorTickEnabled(true); +} + +void ATumaiToy::ActivateSkill() +{ + if(bActivated) return; + bActivated = true; + bAimState = false; +} + +void ATumaiToy::ReleaseSkill() +{ + bCanceled = true; + bReleased = true; + FinishSkill(); +} + +void ATumaiToy::CancelSkill() +{ + bCanceled = true; + FinishSkill(); +} + +void ATumaiToy::FinishSkill() +{ + Super::FinishSkill(); +} + +void ATumaiToy::SkillHitEnable(bool InbEnable) +{ + if(InbEnable) + { + ProjectileTumaiToy(); + TumaiToyMeshComponent->AttachToComponent(MeshRootSceneComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + TumaiToyHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly); + ACorePlayerCharacter* LocPlayerCharacter = Cast(SkillOwner); + LocPlayerCharacter->SetCurrentSkill(false); + } + else + { + ProjectileMovementComponent->Deactivate(); + TumaiToyHitCollisionComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + RootComponent->SetRelativeRotation(FRotator(0.f, RootComponent->GetRelativeRotation().Yaw, 0.f)); + if(USkillObjectAnimInstance* LocAnimInstance = Cast(TumaiToyMeshComponent->GetAnimInstance())) + { + LocAnimInstance->Montage_Play(LocAnimInstance->GetSkillObjectMontage()); + LocAnimInstance->Montage_JumpToSection(TEXT("GetUp"),LocAnimInstance->GetSkillObjectMontage()); + } + } +} + +void ATumaiToy::SkillObjectHitEnable(bool InbEnable) +{ + if(InbEnable) + { + MakeSkillNoise(true,TumaiToyMeshComponent); + NoiseFXComponent->SetWorldLocation(FVector(NoiseFXComponent->GetComponentLocation().X, NoiseFXComponent->GetComponentLocation().Y, 0.1f)); + TumaiToySFXComponent = UGlobalUtilsLibrary::GetSharedSoundManager(this)->PlaySound3DAttached(TEXT("831020"), RootComponent, EAttachLocation::Type::SnapToTarget,TEXT("None")); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(FXDeactivateTimerHandle, this, &ATumaiToy::CheckFXDeactivated, LocWorld->DeltaRealTimeSeconds, true); + } + } +} + +void ATumaiToy::ResetDefaultState() +{ + Super::ResetDefaultState(); + SetActorTickEnabled(false); + if(SkillOwner != nullptr) SkillOwner = nullptr; + CurrentActiveTime = 0.f; + bHit = false; + bCanceled = false; + bAimState = false; + bActivated = false; + bReleased = false; + TumaiToyMeshComponent->SetHiddenInGame(true); + DissolveValue = 1.f; + TumaiToyMeshComponent->SetScalarParameterValueOnMaterials(TEXT("Dissolve"), DissolveValue); + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); +} + +void ATumaiToy::ProjectileTumaiToy() +{ + if (SkillOwner) + { + DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); + TumaiToyMeshComponent->AttachToComponent(TumaiToyRootScene, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + SetParabolaLaunchVelocity(); + ProjectileMovementComponent->Velocity = LaunchVelocity; + InitLocation = GetActorLocation(); + ProjectileMovementComponent->Activate(); + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().SetTimer(RotatorTimerHandle, this, &ATumaiToy::RotateTumaiToyMesh, LocWorld->DeltaTimeSeconds, true); + } + } +} + +void ATumaiToy::ExplosionTumaiToy() +{ + bHit = true; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) LocWorld->GetTimerManager().ClearTimer(RotatorTimerHandle); + SkillHitEnable(false); +} + +void ATumaiToy::RotateTumaiToyMesh() const +{ + FRotator LocAddRotator(10.f,0.f,0.f); + RootComponent->AddLocalRotation(LocAddRotator); +} + +void ATumaiToy::CheckFXDeactivated() +{ + if(NoiseFXComponent->IsActive()) return; + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + LocWorld->GetTimerManager().ClearTimer(FXDeactivateTimerHandle); + LocWorld->GetTimerManager().SetTimer(DissolveTimerHandle, this, &ATumaiToy::CheckDissolveDeactivated, LocWorld->DeltaTimeSeconds, true); + } +} + +void ATumaiToy::CheckDissolveDeactivated() +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + DissolveValue - LocWorld->DeltaTimeSeconds < 0.f ? DissolveValue = 0.f : DissolveValue = DissolveValue - LocWorld->DeltaTimeSeconds; + TumaiToyMeshComponent->SetScalarParameterValueOnMaterials(TEXT("Dissolve"), DissolveValue); + if(DissolveValue <= 0.f) + { + LocWorld->GetTimerManager().ClearTimer(DissolveTimerHandle); + FinishSkill(); + } + } +} + +void ATumaiToy::DefaultCollisionBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, + const FHitResult& SweepResult) +{ + if (!bHit && OtherComp->GetCollisionProfileName() == TEXT("Ground")) ExplosionTumaiToy(); +} + diff --git a/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.h b/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.h new file mode 100644 index 0000000..6c38089 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Skill/TumaiToy.h @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreSkill.h" +#include "TumaiToy.generated.h" + +UCLASS() +class PROJECTT_API ATumaiToy : public ACoreSkill +{ + GENERATED_BODY() + +public: + ATumaiToy(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void Enable_Implementation() override; + virtual void Disable_Implementation() override; + virtual void Pushed_Implementation() override; + virtual void Obtained_Implementation() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +protected: + virtual void StartSkill() override; + virtual void AimSkill() override; + virtual void ActivateSkill() override; + virtual void ReleaseSkill() override; + virtual void CancelSkill() override; + virtual void FinishSkill() override; + virtual void SkillHitEnable(bool InbEnable) override; + virtual void SkillObjectHitEnable(bool InbEnable) override; + virtual void ResetDefaultState() override; + void ProjectileTumaiToy(); + void ExplosionTumaiToy(); + void RotateTumaiToyMesh() const; + void CheckFXDeactivated(); + void CheckDissolveDeactivated(); + + UFUNCTION() + void DefaultCollisionBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr TumaiToyRootScene; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr MeshRootSceneComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr TumaiToyMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr TumaiToyHitCollisionComponent; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) + TObjectPtr TumaiToyIdleAnimSequence; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) + TObjectPtr TumaiToyMontage; + + UPROPERTY(EditDefaultsOnly,BlueprintReadOnly) + TObjectPtr DissolveMaterialInstance; + + UPROPERTY() + TObjectPtr TumaiToySFXComponent; + + UPROPERTY() + TObjectPtr ProjectileMovementComponent; + +private: + FVector InitLocation; + float CurrentActiveTime; + float DissolveValue; + bool bHit; + + UPROPERTY() + FTimerHandle RotatorTimerHandle; + + UPROPERTY() + FTimerHandle FXDeactivateTimerHandle; + + UPROPERTY() + FTimerHandle DissolveTimerHandle; +}; diff --git a/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.cpp b/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.cpp new file mode 100644 index 0000000..2c28c57 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.cpp @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ObjectiveCharacterAnimInstance.h" + +UObjectiveCharacterAnimInstance::UObjectiveCharacterAnimInstance() +{ +} + +void UObjectiveCharacterAnimInstance::NativeInitializeAnimation() +{ + Super::NativeInitializeAnimation(); +} + +void UObjectiveCharacterAnimInstance::NativeUpdateAnimation(float DeltaSeconds) +{ + Super::NativeUpdateAnimation(DeltaSeconds); +} diff --git a/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.h b/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.h new file mode 100644 index 0000000..97ed2ae --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/Animations/ObjectiveCharacterAnimInstance.h @@ -0,0 +1,17 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimInstance.h" +#include "ObjectiveCharacterAnimInstance.generated.h" + +UCLASS() +class PROJECTT_API UObjectiveCharacterAnimInstance : public UAnimInstance +{ + GENERATED_BODY() + +public: + UObjectiveCharacterAnimInstance(); + + virtual void NativeInitializeAnimation() override; + virtual void NativeUpdateAnimation(float DeltaSeconds) override; +}; diff --git a/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.cpp b/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.cpp new file mode 100644 index 0000000..a601305 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.cpp @@ -0,0 +1,65 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreObjectiveCharacter.h" +#include "ProjectT/ProjectT.h" + +ACoreObjectiveCharacter::ACoreObjectiveCharacter(): + bActionOnce(0) +{ + PrimaryActorTick.bCanEverTick = true; + InteractionObjectType = EInteractionObjectType::ObjectiveCharacter; +} + +void ACoreObjectiveCharacter::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreObjectiveCharacter::TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) +{ + if(bActionOnce) + { + if(Callback.IsBound()) Callback.Execute(EInteractionResultType::SuccessComplete); + return; + } + if(OnInteractionSuccess.IsBound()) return; + bActionOnce = true; + OnInteractionSuccess = Callback; + Callback.Execute(EInteractionResultType::SuccessPre); + StartAction(); +} + +EInteractionObjectType ACoreObjectiveCharacter::GetInteractionObjectType_Implementation() +{ + return InteractionObjectType; +} + +void ACoreObjectiveCharacter::ShowVisual_Implementation() +{ +} + +void ACoreObjectiveCharacter::HideVisual_Implementation() +{ +} + +void ACoreObjectiveCharacter::StartAction_Implementation() +{ +} + +void ACoreObjectiveCharacter::EndAction_Implementation() +{ + if(!OnInteractionSuccess.IsBound()) return; + OnInteractionSuccess.Execute(EInteractionResultType::SuccessComplete); +} + +void ACoreObjectiveCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACoreObjectiveCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + diff --git a/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.h b/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.h new file mode 100644 index 0000000..12d3d01 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/CoreObjectiveCharacter.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Characters/CombatCharacter.h" +#include "ProjectT/System/Core/Interfaces/Visualizable.h" +#include "CoreObjectiveCharacter.generated.h" + +UCLASS() +class PROJECTT_API ACoreObjectiveCharacter : public ACoreCharacter, public IObjectInteractionControl, public IVisualizable +{ + GENERATED_BODY() + +public: + ACoreObjectiveCharacter(); + +protected: + virtual void BeginPlay() override; + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) override; + virtual EInteractionObjectType GetInteractionObjectType_Implementation() override; + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + void StartAction(); + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + void EndAction(); + +public: + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + EInteractionObjectType InteractionObjectType; + +private: + FOnInteractionSuccess OnInteractionSuccess; + uint8 bActionOnce:1; +}; diff --git a/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.cpp b/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.cpp new file mode 100644 index 0000000..1c852b6 --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.cpp @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreSaveCharacter.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h" + +ACoreSaveCharacter::ACoreSaveCharacter(): + ObjectiveType(EObjectiveSubTypes::Save) +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ACoreSaveCharacter::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreSaveCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACoreSaveCharacter::EndAction_Implementation() +{ + Super::EndAction_Implementation(); + + const UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + ASPGameModeBase* GM = UGlobalUtilsLibrary::GetGameModeChecked(World); + + UQuestManager* QM = IWorldObjectProvider::Execute_GetQuestManager(GM); + NMT_CHECKF(QM); + + QM->CheckObjectiveSatisfied(ObjectiveType, 0); +} diff --git a/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.h b/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.h new file mode 100644 index 0000000..6a376da --- /dev/null +++ b/Source/ProjectT/System/Core/Characters/Target/CoreSaveCharacter.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreObjectiveCharacter.h" +#include "CoreSaveCharacter.generated.h" + +struct FInteractionData; +enum class EObjectiveSubTypes : uint8; + +UCLASS() +class PROJECTT_API ACoreSaveCharacter : public ACoreObjectiveCharacter +{ + GENERATED_BODY() + +public: + ACoreSaveCharacter(); + virtual void Tick(float DeltaTime) override; + virtual void EndAction_Implementation() override; + +protected: + virtual void BeginPlay() override; + +private: + EObjectiveSubTypes ObjectiveType; + +}; diff --git a/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.cpp b/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.cpp new file mode 100644 index 0000000..5b5f47f --- /dev/null +++ b/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.cpp @@ -0,0 +1,125 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AssetUtilsLibrary.h" + +#include "LevelSequence.h" +#include "Particles/ParticleSystem.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Paths/Core/CoreDataPathLibrary.h" + + +UStaticMesh* UAssetUtilsLibrary::GetStaticMeshFromPath(const FString& Path) +{ + UStaticMesh* Ret = Cast(StaticLoadObject(UStaticMesh::StaticClass(), nullptr, *Path)); + return Ret; +} + +USkeletalMesh* UAssetUtilsLibrary::GetSkeletalMeshFromPath(const FString& Path) +{ + USkeletalMesh* Ret = Cast(StaticLoadObject(USkeletalMesh::StaticClass(), nullptr, *Path)); + return Ret; +} + +UTexture2D* UAssetUtilsLibrary::GetTexture2DFromPath(const FString& Path) +{ + UTexture2D* Ret = Cast(StaticLoadObject(UTexture2D::StaticClass(), nullptr, *Path)); + return Ret; +} + +UFXSystemAsset* UAssetUtilsLibrary::GetFXSystemFromPath(const FString& Path) +{ + UFXSystemAsset* Ret = Cast(StaticLoadObject(UFXSystemAsset::StaticClass(), nullptr, *Path)); + return Ret; +} + +ULevelSequence* UAssetUtilsLibrary::GetLevelSequenceFromPath(const FString& Path) +{ + ULevelSequence* Ret = Cast(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *Path)); + return Ret; +} + +USoundBase* UAssetUtilsLibrary::GetSoundBaseFromPath(const FString& Path) +{ + USoundBase* Ret = Cast(StaticLoadObject(USoundBase::StaticClass(), nullptr, *Path)); + return Ret; +} + +USoundAttenuation* UAssetUtilsLibrary::GetSoundAttenuationFromPath(const FString& Path) +{ + USoundAttenuation* Ret = Cast(StaticLoadObject(USoundAttenuation::StaticClass(), nullptr, *Path)); + return Ret; +} +UAnimSequence* UAssetUtilsLibrary::GetAnimSequenceFromPath(const FString& Path) +{ + UAnimSequence* Ret = Cast(StaticLoadObject(UAnimSequence::StaticClass(), nullptr, *Path)); + return Ret; +} + +USoundBase* UAssetUtilsLibrary::GetSoundBaseByName(const FName& InAssetName) +{ + FString SoundFolder = UBaseDataPathLibrary::GetSoundDir(); + + FString BGMPath = SoundFolder + TEXT("BGM/") + InAssetName.ToString(); + FString SFXPath = SoundFolder + TEXT("SFX/") + InAssetName.ToString(); + + UObject* LoadedObject = StaticLoadObject(USoundBase::StaticClass(), nullptr, *BGMPath); + + if(LoadedObject) + return Cast(LoadedObject); + else + return Cast(StaticLoadObject(USoundBase::StaticClass(), nullptr, *SFXPath)); +} + +FString UAssetUtilsLibrary::AssetReferencePathToClassPath(const FString& Path) +{ + FString Ret, Str; + Path.Split("\'", nullptr, &Str); + Ret = Str.LeftChop(1); + Ret.Append(TEXT("_C")); + return Ret; +} + +UClass* UAssetUtilsLibrary::GetClassFromAssetData(const FAssetData& InAssetData) +{ + FString ObjPath = InAssetData.GetSoftObjectPath().ToString().Append("_C"); + + return StaticLoadClass(UObject::StaticClass(), nullptr, *ObjPath, nullptr, LOAD_None, nullptr); +} + +UDataTable* UAssetUtilsLibrary::LoadDataTableByName(const FString& DataTableName) +{ + UDataTable* Ret = nullptr; + FString ReferenceFilePath = JOIN_STRINGS(TEXT(""), CoreDataPaths::Data::DatatableDir, DataTableName, TEXT("."), DataTableName); + UObject* StaticLoadObj = StaticLoadObject(UDataTable::StaticClass(), nullptr, *ReferenceFilePath); + NMT_ENSURE(StaticLoadObj); + Ret = CastChecked(StaticLoadObj); + return Ret; +} + +UDataTable* UAssetUtilsLibrary::LoadDataTableByEnumKey(const EDataTableKey DataTableEnumKey) +{ + FString TotalName = JOIN_STRINGS(TEXT(""), TEXT("DT_"), EnumToString(DataTableEnumKey)); + FString ReferenceFilePath = JOIN_STRINGS(TEXT(""), CoreDataPaths::Data::DatatableDir, TotalName, TEXT("."), TotalName); + UObject* StaticLoadObj = StaticLoadObject(UDataTable::StaticClass(), nullptr, *ReferenceFilePath); + if(!NMT_ENSURE(StaticLoadObj)) return nullptr; + + UDataTable* Ret = CastChecked(StaticLoadObj); + return Ret; +} + +bool UAssetUtilsLibrary::IsValidRowInDataTable(const EDataTableKey DataTableEnumKey, const FString& RowName) +{ + UDataTable* LoadDT = LoadDataTableByEnumKey(DataTableEnumKey); + bool IsValid = false; + + if (LoadDT != nullptr) + { + TArray RowNameArray = LoadDT->GetRowNames(); + IsValid = RowNameArray.Contains(RowName); + } + + return IsValid; +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.h b/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.h new file mode 100644 index 0000000..418b559 --- /dev/null +++ b/Source/ProjectT/System/Core/Common/AssetUtilsLibrary.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "AssetUtilsLibrary.generated.h" + +enum class EDataTableKey: uint8; +UCLASS() +class PROJECTT_API UAssetUtilsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable) + static UClass* GetClassFromAssetData(const FAssetData& InAssetData); + + UFUNCTION(BlueprintCallable) + static class UDataTable* LoadDataTableByName(const FString& DataTableName); + + UFUNCTION(BlueprintCallable) + static class UDataTable* LoadDataTableByEnumKey(EDataTableKey DataTableEnumKey); + + UFUNCTION(BlueprintCallable) + static bool IsValidRowInDataTable(const EDataTableKey DataTableEnumKey, const FString& RowName); + + UFUNCTION(Blueprintpure) + static class UStaticMesh* GetStaticMeshFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class USkeletalMesh* GetSkeletalMeshFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class UTexture2D* GetTexture2DFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class UFXSystemAsset* GetFXSystemFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class ULevelSequence* GetLevelSequenceFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class USoundBase* GetSoundBaseFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class USoundAttenuation* GetSoundAttenuationFromPath(const FString& Path); + + UFUNCTION(BlueprintPure) + static class UAnimSequence* GetAnimSequenceFromPath(const FString& Path); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "Sound")) + static class USoundBase* GetSoundBaseByName(const FName& InAssetName); + + UFUNCTION(BlueprintPure) + static FString AssetReferencePathToClassPath(const FString& Path); + + template + static T* GetStaticLoadObjectChecked(const FString& Path) + { + T* Ret = CastChecked(StaticLoadObject(T::StaticClass(), nullptr, *Path)); + return Ret; + } + + template + static T* GetStaticLoadObjectUnChecked(const FString& Path) + { + T* Ret = Cast(StaticLoadObject(T::StaticClass(), nullptr, *Path)); + return Ret; + } +}; diff --git a/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.cpp b/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.cpp new file mode 100644 index 0000000..769361c --- /dev/null +++ b/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.cpp @@ -0,0 +1,325 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "EditorUtilsLibrary.h" + +#include "GlobalUtilsLibrary.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "ProjectT/ProjectT.h" + +#if WITH_EDITOR +#include "Engine/Level.h" +#include "LevelUtils.h" +#include "UnrealEd.h" + +#include "MaterialEditingLibrary.h" +#include "Rendering/SkeletalMeshRenderData.h" +#include "EditorUtilityModule/SystemMessage/MessageAlert.h" +#endif + + +#if WITH_EDITOR +void UEditorUtilsLibrary::ExecuteBatchFile(const FString& FilePath) +{ + NMT_CHECKF(FPaths::FileExists(FilePath)); + FString RelativePath = FPaths::ConvertRelativePathToFull(FilePath); + auto Handle = FPlatformProcess::CreateProc(*RelativePath, nullptr, true, false, false, nullptr, 0, nullptr, + nullptr); + + NMT_CHECKF(Handle.IsValid()); + FPlatformProcess::CloseProc(Handle); +} + +TSet UEditorUtilsLibrary::FindAllDependenciesObjectPath(UObject* InAssetToFindRef) +{ + if(!InAssetToFindRef) return TSet(); + + TSet RefPaths; + + FName PackageName = FName(*InAssetToFindRef->GetPackage()->GetName()); + RecursivelyFindDependencies(RefPaths, PackageName); + + return RefPaths; +} +void UEditorUtilsLibrary::RecursivelyFindDependencies(TSet& AllDependencies, FName InPackageName) +{ + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); + + TArray TempArray; + AssetRegistryModule.Get().GetDependencies(InPackageName, TempArray); + + if(TempArray.Num() == 0) return; + + for(const FName& NameElem : TempArray) + { + AllDependencies.Add(NameElem); + + RecursivelyFindDependencies(AllDependencies, NameElem); + } +} + +void UEditorUtilsLibrary::SetSubLevelTransform(FString SubLevelName, ULevelStreaming* StreamingLevel, const FVector Location, + float Yaw, bool& bOutSuccess, FString& OutInfoMessage) +{ + UWorld* World = GEditor->GetEditorWorldContext().World(); + ULevel* Sublevel = GetSubLevelFromWorld(World, SubLevelName, bOutSuccess, OutInfoMessage); + + if(Sublevel == nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("Sublevel is null")) + return; + } + + if(StreamingLevel == nullptr) + { + UE_LOG(LogTemp, Warning, TEXT("StreamingLevel is null")) + return; + } + + FLevelUtils::SetEditorTransform(StreamingLevel, FTransform(FRotator(0.0f, Yaw, 0.0f), Location)); + + bOutSuccess = true; + OutInfoMessage = FString::Printf(TEXT("Set transforming sublevels Succeeded - %s"), *SubLevelName); +} + +ULevel* UEditorUtilsLibrary::GetSubLevelFromWorld(UWorld* World, FString SubLevelName, bool& bOutSuccess, + FString& OutInfoMessage) +{ + if(World == nullptr) + { + bOutSuccess = false; + OutInfoMessage = FString::Printf(TEXT("GetSublevelfromWorld failed - %s"), *SubLevelName); + return nullptr; + } + + ULevel* Sublevel = nullptr; + + for(ULevel* PotentialLevel : World->GetLevels()) + { + Sublevel = PotentialLevel; + break; + } + + if(Sublevel == nullptr) + { + bOutSuccess = false; + OutInfoMessage = FString::Printf(TEXT("GetSublevelfromWorld failed - %s"), *SubLevelName); + return nullptr; + } + + bOutSuccess = true; + OutInfoMessage = FString::Printf(TEXT("GetSublevelfromWorld Succeeded - %s"), *SubLevelName); + return Sublevel; +} + +void UEditorUtilsLibrary::GetUsedTexturesInCurrentLevel(TSet& OutTextures) +{ + TSet UniqueTextures; + + UWorld* World = GEditor->GetEditorWorldContext().World(); + if (!World) + { + return; + } + + for (TActorIterator It(World); It; ++It) + { + AActor* Actor = *It; + TArray MeshComponents; + Actor->GetComponents(MeshComponents); + + for (UMeshComponent* MeshComp : MeshComponents) + { + int32 MatCount = MeshComp->GetNumMaterials(); + for (int32 i = 0; i < MatCount; ++i) + { + UMaterialInterface* Mat = MeshComp->GetMaterial(i); + if (Mat) + { + TArray Textures; + Mat->GetUsedTextures(Textures, EMaterialQualityLevel::High, true, ERHIFeatureLevel::SM5, true); + for (UTexture* Tex : Textures) + { + UniqueTextures.Add(Tex); + } + } + } + } + } + + OutTextures = UniqueTextures; + +} + +void UEditorUtilsLibrary::GetUsedMaterialInCurrentLevel(TSet& OutMaterials) +{ + TSet UniqueMaterials; + + UWorld* World = GEditor->GetEditorWorldContext().World(); + if (!World) + { + return; + } + + for (TActorIterator It(World); It; ++It) + { + AActor* Actor = *It; + TArray MeshComponents; + Actor->GetComponents(MeshComponents); + + for (UMeshComponent* MeshComp : MeshComponents) + { + int32 MatCount = MeshComp->GetNumMaterials(); + for (int32 i = 0; i < MatCount; ++i) + { + UMaterialInterface* Mat = MeshComp->GetMaterial(i); + if (Mat) + { + UniqueMaterials.Add(Mat); + } + } + } + } + + OutMaterials = UniqueMaterials; +} + +void UEditorUtilsLibrary::GetMaterialInfoInCurrentLevel(TArray InMaterials, TArray& OutData) +{ + TSet DetectMaterials; + FMaterialInfoData TempMaterialInfo; + + GetUsedMaterialInCurrentLevel(DetectMaterials); + InMaterials = DetectMaterials.Array(); + + for (int i = 0; i < InMaterials.Num(); i++) + { + TempMaterialInfo.DetectedMaterial = InMaterials[i]; + TempMaterialInfo.PixelInstructions = UMaterialEditingLibrary::GetStatistics(InMaterials[i]).NumPixelShaderInstructions; + TempMaterialInfo.VertexInstructions = UMaterialEditingLibrary::GetStatistics(InMaterials[i]).NumVertexShaderInstructions; + + OutData.Emplace(TempMaterialInfo); + } + + OutData.Sort([](const FMaterialInfoData& A, const FMaterialInfoData& B) { + + return A.PixelInstructions > B.PixelInstructions; + + }); +} + +void UEditorUtilsLibrary::GetUsedMeshesInCurrentLevel(TSet& OutMeshes) +{ + TSet UniqueMeshes; + + UWorld* World = GEditor->GetEditorWorldContext().World(); + if (!World) + { + return; + } + + for (TActorIterator It(World); It; ++It) + { + AActor* Actor = *It; + TArray MeshComponents; + Actor->GetComponents(MeshComponents); + + for (UMeshComponent* MeshComp : MeshComponents) + { + UniqueMeshes.Add(MeshComp); + } + } + + OutMeshes = UniqueMeshes; +} + +void UEditorUtilsLibrary::GetMeshInfoInCurrentLevel(TArray InMeshes, TArray& OutData) +{ + TSet DetectMeshes; + FMeshInfoData TempMeshInfo; + + GetUsedMeshesInCurrentLevel(DetectMeshes); + InMeshes = DetectMeshes.Array(); + + for (int i = 0; i < InMeshes.Num(); i++) + { + TempMeshInfo.DetectedMesh = InMeshes[i]; + + if (UStaticMeshComponent* SMC = Cast(InMeshes[i])) + { + if (SMC->GetStaticMesh() != nullptr) + { + TempMeshInfo.PolygonCounts = SMC->GetStaticMesh()->GetRenderData()->LODResources[0].GetNumTriangles(); + TempMeshInfo.LODCounts = SMC->GetStaticMesh()->GetRenderData()->LODResources.Num(); + } + else + { + TempMeshInfo.PolygonCounts = 0; + TempMeshInfo.LODCounts = 0; + } + } + + if (USkeletalMeshComponent* SKC = Cast(InMeshes[i])) + { + if (SKC->GetSkeletalMeshAsset() != nullptr) + { + TempMeshInfo.PolygonCounts = SKC->GetSkeletalMeshAsset()->GetResourceForRendering()->LODRenderData[0].GetTotalFaces(); + TempMeshInfo.LODCounts = SKC->GetSkeletalMeshAsset()->GetResourceForRendering()->LODRenderData.Num(); + } + else + { + TempMeshInfo.PolygonCounts = 0; + TempMeshInfo.LODCounts = 0; + } + } + + OutData.Emplace(TempMeshInfo); + } + + OutData.Sort([](const FMeshInfoData& A, const FMeshInfoData& B) { + + return A.PolygonCounts > B.PolygonCounts; + + }); +} + +bool UEditorUtilsLibrary::LoadFileToString(FString RelativePathUnderContent, FString& Output) +{ + return FFileHelper::LoadFileToString(Output, *(FPaths::ProjectDir() + "Content\\" + RelativePathUnderContent)); +} + +bool UEditorUtilsLibrary::SaveFileToString(FString InSaveText, FString FilePath) +{ + InSaveText.ReplaceInline(TEXT("\r"),TEXT("")); + InSaveText.ReplaceInline(TEXT("\n"),TEXT("\r\n")); + return FFileHelper::SaveStringToFile(InSaveText,*(FPaths::ProjectDir() + "Content\\" + FilePath), FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM); +} + +void UEditorUtilsLibrary::GetCSVFilesList(const FString& RelativePathUnderContent, TArray& OutputFilesList) +{ + FString FullPath = FPaths::ProjectDir() + "Content\\" + RelativePathUnderContent + TEXT("\\*.csv"); + IFileManager::Get().FindFiles(OutputFilesList, *FullPath, true, false); +} + +void UEditorUtilsLibrary::ResetComponentToDefaults(UActorComponent* Component) +{ + NMT_CHECKF(Component); + + UObject* CDO = Component->GetClass()->GetDefaultObject(); + for (TFieldIterator It(Component->GetClass()); It; ++It) + { + FProperty* Property = *It; + if (!Property->HasAnyPropertyFlags(CPF_Edit | CPF_BlueprintVisible)) continue; + void* Dest = Property->ContainerPtrToValuePtr(Component); + void* Src = Property->ContainerPtrToValuePtr(CDO); + Property->CopyCompleteValue(Dest, Src); + } + Component->ReregisterComponent(); +} +/*Only Editor Function!*/ +void UEditorUtilsLibrary::ShowMessageAlert(FString Message) +{ + MessageAlert::ShowNotifyInfo(Message); +} + +#endif diff --git a/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.h b/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.h new file mode 100644 index 0000000..8c5dc9b --- /dev/null +++ b/Source/ProjectT/System/Core/Common/EditorUtilsLibrary.h @@ -0,0 +1,91 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "EditorUtilsLibrary.generated.h" + +USTRUCT(Blueprintable) +struct FMaterialInfoData +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly) + TObjectPtr DetectedMaterial = nullptr; + + UPROPERTY(BlueprintReadOnly) + int32 VertexInstructions = 0; + + UPROPERTY(BlueprintReadOnly) + int32 PixelInstructions = 0; +}; + +USTRUCT(Blueprintable) +struct FMeshInfoData +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly) + TObjectPtr DetectedMesh = nullptr; + + UPROPERTY(BlueprintReadOnly) + int32 PolygonCounts = 0; + + UPROPERTY(BlueprintReadOnly) + int32 LODCounts = 0; +}; + +UCLASS() +class PROJECTT_API UEditorUtilsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: +#if WITH_EDITOR + UFUNCTION(BlueprintCallable) + static void ExecuteBatchFile(const FString& FilePath); + + UFUNCTION(BlueprintCallable) + static TSet FindAllDependenciesObjectPath(UObject* InAssetToFindRef); + + static void RecursivelyFindDependencies(TSet& AllDependencies, FName InPackageName); + + UFUNCTION(BlueprintCallable) + static void SetSubLevelTransform(FString SubLevelName, ULevelStreaming* StreamingLevel, FVector Location, float Yaw, + bool& bOutSuccess, FString& OutInfoMessage); + + static ULevel* GetSubLevelFromWorld(UWorld* World, FString SubLevelName, bool& bOutSuccess, + FString& OutInfoMessage); + + UFUNCTION(BlueprintCallable) + static void GetUsedTexturesInCurrentLevel(TSet& OutTextures); + + UFUNCTION(BlueprintCallable) + static void GetUsedMaterialInCurrentLevel(TSet& OutMaterials); + + UFUNCTION(BlueprintCallable) + static void GetMaterialInfoInCurrentLevel(TArray InMaterials, TArray& OutData); + + UFUNCTION(BlueprintCallable) + static void GetUsedMeshesInCurrentLevel(TSet& OutMeshes); + + UFUNCTION(BlueprintCallable) + static void GetMeshInfoInCurrentLevel(TArray InMeshes, TArray& OutData); + + UFUNCTION(BlueprintCallable,Category="VSVersion") + static bool LoadFileToString(FString RelativePathUnderContent,FString&Output); + + UFUNCTION(BlueprintCallable) + static bool SaveFileToString(FString InSaveText,FString FileName); + + UFUNCTION(BlueprintPure) + static void GetCSVFilesList(const FString& RelativePathUnderContent, TArray& OutputFilesList); + + static void ResetComponentToDefaults(UActorComponent* Component); + + UFUNCTION(BlueprintCallable) + static void ShowMessageAlert(FString Message); + +#endif +}; diff --git a/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.cpp b/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.cpp new file mode 100644 index 0000000..8be0f2f --- /dev/null +++ b/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.cpp @@ -0,0 +1,424 @@ +#include "GlobalUtilsLibrary.h" +#include "Algo/Transform.h" +#include "Misc/Paths.h" +#include "HAL/PlatformProcess.h" +#include "Kismet/KismetMathLibrary.h" +#include "Components/SkeletalMeshComponent.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/CoreGameInstance.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateStructLocalization.h" +#include "ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h" + + +bool UGlobalUtilsLibrary::IsValueInRange(const int32 Value, const int32 A, const int32 B, bool GreaterEqual, bool LessEqual) +{ + bool G = GreaterEqual ? (Value >= A) : (Value > A); + bool L = LessEqual ? (Value <= B) : (Value < B); + return G && L; +} + +UWorld* UGlobalUtilsLibrary::GetValidWorld(UObject* Object) +{ + UWorld* World = Object->GetWorld(); + NMT_CHECKF(World); + return World; +} + +UDataDam* UGlobalUtilsLibrary::GetSharedDataDam(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UDataDam* Ret = IGlobalObjectProvider::Execute_GetDataDam(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +UStageManager* UGlobalUtilsLibrary::GetSharedLevelManager(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UStageManager* Ret = IGlobalObjectProvider::Execute_GetStageManager(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +UOptionManager* UGlobalUtilsLibrary::GetSharedOptionManager(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UOptionManager* Ret = IGlobalObjectProvider::Execute_GetOptionManager(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +USoundManager* UGlobalUtilsLibrary::GetSharedSoundManager(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + USoundManager* Ret = IGlobalObjectProvider::Execute_GetSoundManager(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +UCoreCheatManager* UGlobalUtilsLibrary::GetSharedCoreCheatManager(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UCoreCheatManager* Ret = IGlobalObjectProvider::Execute_GetCoreCheatManager(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +UNotificationCenter* UGlobalUtilsLibrary::GetSharedNotificationCenter(UObject* Object) +{ + NMT_CHECKF(Object); + + UWorld* World = GetValidWorld(Object); + NMT_CHECKF(World); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UNotificationCenter* Ret = IGlobalObjectProvider::Execute_GetNotificationCenter(GI); + NMT_CHECKF(Ret); + + return Ret; +} + +bool UGlobalUtilsLibrary::IsStandalonePlay(UObject* Object) +{ + NMT_CHECKF(Object); + ENetMode NetMode = Object->GetWorld()->GetNetMode(); + return NetMode == NM_Standalone; +} + +TArray UGlobalUtilsLibrary::ParseStringIndices(const TCHAR* Delimiter, const FString& Indices) +{ + TArray Ret; + Indices.ParseIntoArray(Ret, TEXT(";")); + return Ret; +} + +FString UGlobalUtilsLibrary::GetScriptTypeByRefPath(const FString& RefPath) +{ + FString Ret; + if (RefPath.Split(TEXT("."), nullptr, &Ret)) + Ret.Split(TEXT("'"), &Ret, nullptr); + + return Ret; +} + +EContentType UGlobalUtilsLibrary::GetContentTypeFromIndex(FName InRowName) +{ + FString RowString = InRowName.ToString(); + FString SliceString = DivideString(2, RowString); + int32 ContentTypeNumber = FCString::Atoi(*SliceString); + return StaticCast(ContentTypeNumber); +} + +TArray UGlobalUtilsLibrary::ParseStringIndices(const FString& Indices, const FString& Delimeter) +{ + TArray Ret; + Indices.ParseIntoArray(Ret, *Delimeter); + return Ret; +} + +TArray UGlobalUtilsLibrary::GetFilteredCurrentActors(const TArray& InActors, + const TArray& IgnoreClasses, const TArray& IncludeClasses) +{ + bool bActorSubclass = false; + bool bInterfaceClass = false; + for (UClass* Class : IgnoreClasses) + { + bActorSubclass = Class->IsChildOf(AActor::StaticClass()); + bInterfaceClass = Class->IsChildOf(UInterface::StaticClass()); + NMT_MSG_CHECKF(bActorSubclass || bInterfaceClass, "%s Contains a class that isn’t allowed: %s", TEXT("IgnoreClasses"), *Class->GetName()); + } + + for (UClass* Class : IncludeClasses) + { + bActorSubclass = Class->IsChildOf(AActor::StaticClass()); + bInterfaceClass = Class->IsChildOf(UInterface::StaticClass()); + NMT_MSG_CHECKF(bActorSubclass || bInterfaceClass, "%s Contains a class that isn’t allowed: %s", TEXT("IncludeClasses"), *Class->GetName()); + } + + TArray::ElementType> Ret = InActors.FilterByPredicate([&IgnoreClasses, &IncludeClasses](const AActor* Actor) + { + UClass* CurrentActorClass = Actor->GetClass(); + if(IgnoreClasses.Contains(CurrentActorClass)) return false; + + for(UClass* Class : IgnoreClasses) + { + if(Actor->IsA(Class)) return false; + if(CurrentActorClass->ImplementsInterface(Class)) return false; + } + + if(IncludeClasses.Num() == 0) return true; + if(IncludeClasses.Contains(CurrentActorClass)) return true; + + for(UClass* Class : IncludeClasses) + { + if(Actor->IsA(Class)) return true; + if(CurrentActorClass->ImplementsInterface(Class)) return true; + } + return false; + }); + + return Ret; +} + +FString UGlobalUtilsLibrary::ReferencePathToFilePath(const FString& ReferencePath) +{ + FString Ret, Str; + ReferencePath.Split("\'", nullptr, &Str); + Str.Split(".", &Ret, nullptr); + return Ret; +} + +FString UGlobalUtilsLibrary::Uint32ToBase64String(uint32 Value) +{ + const FString Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@"; + FString Result = ""; + if (Value == 0) Result = Alphabet.Mid(0, 1); + for (int i = 1; i < 6; i++) + { + uint32 Index = Value % Alphabet.Len(); + Result = Alphabet.Mid(Index, 1) + Result; + Value = Value / Alphabet.Len(); + } + return Result; +} + +TSoftClassPtr UGlobalUtilsLibrary::GetSoftWidgetClassFromPath(FString Path) +{ + return GetStringToSoftClass(Path); +} + +bool UGlobalUtilsLibrary::IsEditorPlay() +{ +#if WITH_EDITOR + return true; + +#else + return false; + +#endif +} + +void UGlobalUtilsLibrary::EnableComponent(UActorComponent* Component, bool bEnable) +{ + NMT_CHECKF(Component); + + Component->SetComponentTickEnabled(bEnable); + if (UPrimitiveComponent* PrimitiveComponent = Cast(Component)) + { + PrimitiveComponent->SetVisibility(bEnable, true); + PrimitiveComponent->SetHiddenInGame(!bEnable, true); + PrimitiveComponent->SetCollisionEnabled(bEnable ? ECollisionEnabled::QueryAndPhysics : ECollisionEnabled::NoCollision); + } +} + +FString UGlobalUtilsLibrary::GetLocalizedStringFromTable(const FName& TableRow) +{ + UWorld* World = GEngine->GameViewport->GetWorld(); + if (!World) return FString(); + + UDataDam* DD = GetSharedDataDam(World); + NMT_CHECKF(DD); + + const UDataTable* LocalizeDT = DD->GetDataTableByEnum(EDataTableKey::Localization); + FLocalization* LocalizeST = LocalizeDT->FindRow(TableRow, LocalizeDT->GetName()); + if (!LocalizeST) return FString(); + + UCoreGameUserSettings* UserSetting = UCoreGameUserSettings::GetCoreGameUserSettings(); + EGameLanguage CurLanguage = UserSetting->GetGamePlayOption().Setting_Language; + + FString OutputString = FString(); + + switch (CurLanguage) + { + case EGameLanguage::Korea: + { + OutputString = LocalizeST->sKorean; + break; + } + case EGameLanguage::English: + { + OutputString = LocalizeST->sEnglish; + break; + } + default: + { + OutputString = LocalizeST->sEnglish; + break; + } + } + return OutputString; +} + +/*NOTE: +베지에 곡선의 드 카스텔조 알고리즘을 사용하여 주어진 제어점 Points에 대한 시간 t에서의 보정위치를 구한다. +Points 배열의 첫번째 인덱스에는 시작점, 마지막 인덱스에는 끝점이 위치해야 한다. +*/ +FVector UGlobalUtilsLibrary::GetBezierPointByDeCasteljau(const TArray& Points, float t) +{ + if(Points.Num() == 1) + return Points[0]; + + TArray NextLevel; + for(int i = 0; i < Points.Num() - 1; ++i) + { + FVector LerpPoint = FMath::Lerp(Points[i], Points[i + 1], t); + NextLevel.Add(LerpPoint); + } + + return GetBezierPointByDeCasteljau(NextLevel, t); +} + +// FIXME: 프로젝트 이주로 기존에 쓰던 데이터는 삭제됨 새로운 데이터 구조에 맞춰서 수정필요 +int32 UGlobalUtilsLibrary::GetEnumIndexFromString(EDataTableKey InEnum, FString InString) +{ + int32 Ret = 0; + FString FindEnumType = "E" + EnumToString(InEnum); + UEnum* EnumPtr = FindFirstObjectSafe(*FindEnumType); + if (EnumPtr == nullptr) return Ret; + { + Ret = EnumPtr->GetIndexByNameString(InString); + return Ret; + } +} + +FVector UGlobalUtilsLibrary::GetCenterPointBetweenTwoVectors(FVector A, FVector B) +{ + return (A + B) * 0.5f; +} + +double UGlobalUtilsLibrary::FindAngleBetweenTwoVectors2D(FVector2D A, FVector2D B) +{ + A.Normalize(); + B.Normalize(); + + double Scalar = A | B; + double Angle = UKismetMathLibrary::DegAcos(Scalar); + Angle = (A ^ B) > 0 ? Angle : Angle * -1.0; + return Angle; +} + +double UGlobalUtilsLibrary::FindAngleBetweenTwoVectors3D(FVector A, FVector B, EFindAngleAxis EFindAxis) +{ + A.Normalize(); + B.Normalize(); + + double Scalar = A | B; + double Angle = UKismetMathLibrary::DegAcos(Scalar); + FVector CrossVector = A ^ B; + switch (EFindAxis) + { + case EFindAngleAxis::EForward: + Angle = CrossVector.X > 0 ? Angle : Angle * -1.0; + break; + case EFindAngleAxis::EUp: + Angle = CrossVector.Z > 0 ? Angle : Angle * -1.0; + break; + case EFindAngleAxis::ERight: + Angle = CrossVector.Y > 0 ? Angle : Angle * -1.0; + break; + } + return Angle; +} + +bool UGlobalUtilsLibrary::SuggestProjectileVelocityAtLocation(const UObject* WorldContextObject, + FVector& OutLaunchVelocity, const FVector& ProjectileStartLocation, const FVector& TargetLocation, const float DesiredArcHeight, double GravityZOverride, + double TimeToTarget) +{ + if (!GEngine) return false; + if (TargetLocation == FVector::ZeroVector) return false; + + const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!World) return false; + + const double Gravity = FMath::IsNearlyZero(GravityZOverride) ? World->GetGravityZ() : GravityZOverride; + const double StartZ = ProjectileStartLocation.Z; + const double TargetZ = TargetLocation.Z; + const double ApexZ = TargetZ + DesiredArcHeight; + if (ApexZ <= StartZ || ApexZ <= TargetZ) return false; + + const double Sqrt = FMath::Sqrt(2.0 * FMath::Abs(Gravity) * (ApexZ - StartZ)); + const double Up = Sqrt / FMath::Abs(Gravity); + const double Down = FMath::Sqrt(2.0 * (ApexZ - TargetZ) / FMath::Abs(Gravity)); + const double Time = Up + Down; + const FVector Delta = TargetLocation - ProjectileStartLocation; + const FVector DeltaXY = FVector(Delta.X, Delta.Y, 0.0); + const FVector VelXY = DeltaXY / Time; + OutLaunchVelocity = FVector(VelXY.X, VelXY.Y, Sqrt); + + return true; +} + +// EX: (X=0.0000,Y=0.0000,Z=0.0000) -> FVector3D +FVector UGlobalUtilsLibrary::StringToVector3D(FString& InString) +{ + FString S = InString.Mid(1, InString.Len() - 2); + TArray ParseString; + S.ParseIntoArray(ParseString, TEXT(",")); + NMT_MSG_CHECKF(ParseString.Num() == 3, "String Vector Has Fewer Than Three Elements"); + + float X = FCString::Atod(*ParseString[0] + 2); + float Y = FCString::Atod(*ParseString[1] + 2); + float Z = FCString::Atod(*ParseString[2] + 2); + FVector Ret = FVector(X, Y, Z); + + return Ret; +} + +FString UGlobalUtilsLibrary::DivideString(const int Count, FString& InString) +{ + if (InString.Len() < Count) return FString(); + FString Ret = InString.Left(Count); + InString.RemoveAt(0, Count); + return Ret; +} + +void UGlobalUtilsLibrary::DebugBreak(const FString& MessageString) +{ + checkf(0, TEXT("%s"), *MessageString); +} diff --git a/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.h b/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.h new file mode 100644 index 0000000..efd3e2e --- /dev/null +++ b/Source/ProjectT/System/Core/Common/GlobalUtilsLibrary.h @@ -0,0 +1,281 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/GameplayStatics.h" +#include "ProjectT/ProjectT.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Engine/AssetManager.h" +#include "Engine/StreamableManager.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "GlobalUtilsLibrary.generated.h" + +struct FNActionData; +enum class EDataTableKey : uint8; + +UENUM(BlueprintType) +enum class EFindAngleAxis :uint8 +{ + EForward UMETA(DisplayName="EForward"), + EUp UMETA(DisplayName="EUp"), + ERight UMETA(DisplayName="ERight") +}; + +UCLASS() +class PROJECTT_API UGlobalUtilsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + static UWorld* GetValidWorld(UObject* Object); + static class UDataDam* GetSharedDataDam(UObject* Object); + static class UStageManager* GetSharedLevelManager(UObject* Object); + static class UOptionManager* GetSharedOptionManager(UObject* Object); + static class USoundManager* GetSharedSoundManager(UObject* Object); + static class UCoreCheatManager* GetSharedCoreCheatManager(UObject* Object); + static class UNotificationCenter* GetSharedNotificationCenter(UObject* Object); + static bool IsStandalonePlay(UObject* Object); + + static TArray ParseStringIndices(const TCHAR* Delimiter, const FString& Indices); + static TArray ParseStringIndices(const FString& Indices, const FString& Delimeter); + + UFUNCTION(BlueprintCallable) + static FString DivideString(const int Count, FString& InString); + + static int32 GetEnumIndexFromString(EDataTableKey InEnum, FString InString); + static FString Uint32ToBase64String(uint32 Value); + + template + static FString GetEnumToString(EnumType FindEnumData) + { + const UEnum* FindPtr = StaticEnum(); + if (!FindPtr) return FString(); + + const int32 Idx = static_cast(FindEnumData); + if (Idx == 0) return FString(); + + FString Ret = FindPtr->GetNameStringByIndex(Idx); + return Ret; + } + + template + static EnumType GetStringToEnum(const FString& FindEnumTypeString) + { + EnumType Ret = StaticCast(0); + for (EnumType e : TEnumRange()) + { + FString Name = UGlobalUtilsLibrary::GetEnumToString(e); + if (FindEnumTypeString.Equals(Name)) + return e; + } + return Ret; + } + + template + static TSoftClassPtr GetStringToSoftClass(FString& InString) + { + FSoftClassPath SoftClassPath(InString.Append("_C")); + return TSoftClassPtr(SoftClassPath); + } + + template + static void AsyncLoadClassAsset(FString AssetPath, TFunction Callback) + { + FStreamableManager& Streamable = UAssetManager::GetStreamableManager(); + FSoftObjectPath AssetRef(AssetPath); + Streamable.RequestAsyncLoad(AssetRef,[AssetRef, Callback]() + { + T* LoadedAsset = Cast(AssetRef.TryLoad()); + LoadedAsset = LoadedAsset ? LoadedAsset : nullptr; + Callback(LoadedAsset); + }); + } + + template + static void AsyncLoadSubClass(TSoftClassPtr SoftClassPtr, TFunction)> Callback) + { + if (SoftClassPtr.IsValid()) + { + Callback(SoftClassPtr.Get()); + return; + } + + FStreamableManager& Streamable = UAssetManager::GetStreamableManager(); + Streamable.RequestAsyncLoad(SoftClassPtr.ToSoftObjectPath(), [SoftClassPtr, Callback]() + { + TSubclassOf LoadedClass = SoftClassPtr.Get(); + Callback(LoadedClass); + } + ); + } + + template + static T* FindObject(const FString& FilePath) + { + T* Object = ConstructorHelpers::FObjectFinder(*FilePath).Object; + NMT_ENSURE(Object); + + return Object; + } + + template + static ConstructorHelpers::FClassFinder FindClass(const FString& FilePath) + { + ConstructorHelpers::FClassFinder ClassFinder(*FilePath); + NMT_ENSURE(ClassFinder.Succeeded()); + + return ClassFinder; + } + + template + static T* FindActorInLevel(ULevelStreaming* Level) + { + if(!NMT_ENSURE(Level && Level->IsLevelLoaded())) return nullptr; + ULevel* LV = Level->GetLoadedLevel(); + + if(!NMT_ENSURE(LV)) return nullptr; + for(AActor* Actor : LV->Actors) + if(T* Ret = Cast(Actor)) return Ret; + + return nullptr; + } + + template + static T* GetGameModeChecked(const UObject* WorldContextObject) + { + return CastChecked(UGameplayStatics::GetGameMode(WorldContextObject)); + } + + template + static T* GetGameStateChecked(const UObject* WorldContextObject) + { + return CastChecked(UGameplayStatics::GetGameState(WorldContextObject)); + } + + template + static T* GetLocalPlayerChecked(const UObject* WorldContextObject) + { + return CastChecked(UGameplayStatics::GetPlayerCharacter(WorldContextObject, 0)); + } + + template + static T* GetLocalPlayerUnChecked(const UObject* WorldContextObject) + { + return Cast(UGameplayStatics::GetPlayerCharacter(WorldContextObject, 0)); + } + + template + static T* GetLocalPlayerControllerChecked(const UObject* WorldContextObject) + { + return CastChecked(UGameplayStatics::GetPlayerController(WorldContextObject, 0)); + } + + template + static T* GetLocalPlayerControllerUnChecked(const UObject* WorldContextObject) + { + return Cast(UGameplayStatics::GetPlayerController(WorldContextObject, 0)); + } + + template + static void ShuffleArray(const TArray& TargetArray) + { + int32 LastIndex = TargetArray.Num() - 1; + for (int32 i = 0; i < LastIndex; ++i) + { + int32 Index = FMath::RandRange(i, LastIndex); + if (i != Index) + { + const_cast*>(&TargetArray)->Swap(i, Index); + } + } + } + + static FString GetScriptTypeByRefPath(const FString& RefPath); + static EContentType GetContentTypeFromIndex(FName InRowName); + + template + static FString GetStringFieldInStruct(T* StructInstance, const FName& FieldName) + { + UStruct* StructType = StructInstance->StaticStruct(); + FProperty* Prop = StructType->FindPropertyByName(FieldName); + const FStrProperty* PropType = CastField(Prop); + FString Ret = PropType->GetPropertyValue_InContainer(StructInstance); + return Ret; + } + + template + static float GetFloatFieldInStruct(T* StructInstance, const FName& FieldName) + { + UStruct* StructType = StructInstance->StaticStruct(); + FProperty* Prop = StructType->FindPropertyByName(FieldName); + const FFloatProperty* PropType = CastField(Prop); + float Ret = PropType->GetPropertyValue_InContainer(StructInstance); + return Ret; + } + + template + static int32 GetIntFieldInStruct(T* StructInstance, const FName& FieldName) + { + UStruct* StructType = StructInstance->StaticStruct(); + FProperty* Prop = StructType->FindPropertyByName(FieldName); + const FIntProperty* PropType = CastField(Prop); + int32 Ret = PropType->GetPropertyValue_InContainer(StructInstance); + return Ret; + } + + template + static bool GetBoolFieldInStruct(T* StructInstance, const FName& FieldName) + { + UStruct* StructType = StructInstance->StaticStruct(); + FProperty* Prop = StructType->FindPropertyByName(FieldName); + const FBoolProperty* PropType = CastField(Prop); + bool Ret = PropType->GetPropertyValue_InContainer(StructInstance); + return Ret; + } + + static TArray GetFilteredCurrentActors(const TArray& InActors, const TArray& IgnoreClasses, const TArray& IncludeClasses); + + UFUNCTION(BlueprintCallable) + static FString ReferencePathToFilePath(const FString& ReferencePath); + + UFUNCTION(BlueprintPure) + static bool IsValueInRange(const int32 Value, const int32 A, const int32 B, bool GreaterEqual, bool LessEqual); + + UFUNCTION(BlueprintPure) + static FVector GetCenterPointBetweenTwoVectors(FVector A, FVector B); + + UFUNCTION(BlueprintPure) + static double FindAngleBetweenTwoVectors2D(FVector2D A, FVector2D B); + + UFUNCTION(BlueprintPure) + static double FindAngleBetweenTwoVectors3D(FVector A, FVector B, EFindAngleAxis EFindAxis); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject")) + static bool SuggestProjectileVelocityAtLocation(const UObject* WorldContextObject, FVector& OutLaunchVelocity, + const FVector& ProjectileStartLocation, const FVector& TargetLocation, const float DesiredArcHeight, + double GravityZOverride, double TimeToTarget); + + UFUNCTION(BlueprintCallable) + static FVector StringToVector3D( FString& InString); + + UFUNCTION(BlueprintCallable) + static void DebugBreak(const FString& MessageString = TEXT("An intentional crash has occurred at the current node.")); + + UFUNCTION(BlueprintPure) + static TSoftClassPtr GetSoftWidgetClassFromPath(FString Path); + + UFUNCTION(BlueprintPure) + static bool IsEditorPlay(); + + UFUNCTION(BlueprintCallable) + static void EnableComponent(UActorComponent* Component, bool bEnable); + + UFUNCTION(BlueprintCallable) + static FString GetLocalizedStringFromTable(const FName& TableRow); + + UFUNCTION(BlueprintCallable) + static FVector GetBezierPointByDeCasteljau(const TArray& Points, float t); + + +}; \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Components/CoreCameraComponent.cpp b/Source/ProjectT/System/Core/Components/CoreCameraComponent.cpp new file mode 100644 index 0000000..649aebe --- /dev/null +++ b/Source/ProjectT/System/Core/Components/CoreCameraComponent.cpp @@ -0,0 +1,136 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreCameraComponent.h" + +#include "Components/DrawFrustumComponent.h" +#include "Kismet/GameplayStatics.h" +#include "Kismet/KismetMathLibrary.h" +#include "GameFramework/SpringArmComponent.h" +#include "ProjectT/System/Core/Interfaces/CoreCameraControl.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +UCoreCameraComponent::UCoreCameraComponent(): + ZoomLerpCurve(nullptr), + EnableLag_Location(0), + EnableLag_Rotation(0), + LocationLag(10), + RotationLag(10), + CameraZoomTimeline(nullptr), + CameraZoomInOut(), + CurrentCameraZoom(0), + ZoomValue(0) +{ + PrimaryComponentTick.bCanEverTick = true; + CameraZoomTimeline = CreateDefaultSubobject(TEXT("CameraZoomTimeline")); +} + +void UCoreCameraComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void UCoreCameraComponent::BeginPlay() +{ + Super::BeginPlay(); + + if (USpringArmComponent* ParentArm = Cast(GetAttachParent())) + { + ParentArm->bEnableCameraLag = EnableLag_Location; + ParentArm->bEnableCameraRotationLag = EnableLag_Rotation; + ParentArm->CameraLagSpeed = LocationLag; + ParentArm->CameraRotationLagSpeed = RotationLag; + } +} + +void UCoreCameraComponent::StartFade(EFadeType FadeType, FOnStaticFinishCameraFade FinishEvent, float Duration, float StartDelay) +{ + APlayerCameraManager* CameraManager = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0); + NMT_CHECKF(CameraManager); + + if(StartDelay > 0) + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().SetTimer(FadeActionHandle, [this, World, FadeType, CameraManager, Duration, FinishEvent]() + { + switch (FadeType) + { + case EFadeType::FadeIn: + { + CameraManager->StartCameraFade(1.f, 0.f, Duration, FLinearColor(0.f, 0.f, 0.f), false, true); + break; + } + case EFadeType::FadeOut: + { + CameraManager->StartCameraFade(0.f, 1.f, Duration, FLinearColor(0.f, 0.f, 0.f), false, true); + break; + } + default: NMT_MSG_CHECKF(0, "Does not allow value."); + } + + FTimerHandle FinishHandle; + World->GetTimerManager().SetTimer(FinishHandle, FTimerDelegate::CreateLambda([this, FinishEvent]() + { + if(FinishEvent.IsBound()) + FinishEvent.Execute(); + + }), Duration, false); + }, StartDelay, false); + } +} + +void UCoreCameraComponent::StartZoom(EZoomType ZoomType, float ZoomFactor, float Duration) +{ + CurrentCameraZoom = OrthoWidth; + ZoomValue = ZoomFactor; + + Duration = UKismetMathLibrary::FClamp(Duration, 0.01, Duration); + + if (ZoomLerpCurve != nullptr) + { + CameraZoomInOut = ZoomType; + + InterpFunction.BindDynamic(this, &UCoreCameraComponent::CameraZoomUpdate); + CameraZoomTimeline->AddInterpFloat(ZoomLerpCurve, InterpFunction, FName("doUpdate")); + CameraZoomTimeline->SetLooping(false); + CameraZoomTimeline->SetPlayRate(1 / Duration); + CameraZoomTimeline->SetTimelineLengthMode(TL_LastKeyFrame); + CameraZoomTimeline->PlayFromStart(); + } +} + +void UCoreCameraComponent::CameraFade(EFadeType FadeType, FOnFinishCameraFade FinishEvent, float Duration, float StartDelay) +{ + StartFade(FadeType, FOnStaticFinishCameraFade::CreateLambda([FinishEvent](){ + if(FinishEvent.IsBound()) + FinishEvent.Execute(); + }), Duration, StartDelay); +} + +void UCoreCameraComponent::CameraZoom(EZoomType ZoomType, float ZoomFactor, float Duration) +{ + StartZoom(ZoomType, ZoomFactor, Duration); +} + +void UCoreCameraComponent::CameraZoomUpdate(float Value) +{ + float NewZoom = 0.f; + + switch (CameraZoomInOut) + { + case EZoomType::ZoomIn: + { + NewZoom = UKismetMathLibrary::Lerp(CurrentCameraZoom, CurrentCameraZoom - ZoomValue, Value); + break; + } + case EZoomType::ZoomOut: + { + NewZoom = UKismetMathLibrary::Lerp(CurrentCameraZoom, CurrentCameraZoom + ZoomValue, Value); + break; + } + default: NMT_MSG_CHECKF(0, "Does not allow value."); + } + + SetOrthoWidth(NewZoom); +} diff --git a/Source/ProjectT/System/Core/Components/CoreCameraComponent.h b/Source/ProjectT/System/Core/Components/CoreCameraComponent.h new file mode 100644 index 0000000..c94e82b --- /dev/null +++ b/Source/ProjectT/System/Core/Components/CoreCameraComponent.h @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Camera/CameraComponent.h" +#include "Components/TimelineComponent.h" +#include "Curves/CurveFloat.h" +#include "ProjectT/System/Core/Interfaces/CoreCameraControl.h" +#include "CoreCameraComponent.generated.h" + +DECLARE_DYNAMIC_DELEGATE(FOnFinishCameraFade); + +UCLASS() +class PROJECTT_API UCoreCameraComponent : public UCameraComponent, public ICoreCameraControl +{ + GENERATED_BODY() + +public: + UCoreCameraComponent(); + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + +protected: + virtual void BeginPlay()override; + +public: + virtual void StartFade(EFadeType FadeType, FOnStaticFinishCameraFade FinishEvent, float Duration, float StartDelay) override; + virtual void StartZoom(EZoomType ZoomType, float ZoomFactor, float Duration) override; + + UFUNCTION(BlueprintCallable, Category = "Design | CameraFade") + void CameraFade(EFadeType FadeType, FOnFinishCameraFade FinishEvent, float Duration, float StartDelay = 1.f); + + UFUNCTION(BlueprintCallable, Category = "Design | CameraZoom") + void CameraZoom(EZoomType ZoomType, float ZoomFactor, float Duration); + +private: + UFUNCTION() + void CameraZoomUpdate(float Value); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design | CameraZoom") + UCurveFloat* ZoomLerpCurve; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design | CameraLag") + uint8 EnableLag_Location : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design | CameraLag") + uint8 EnableLag_Rotation : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design | CameraLag", meta = (EditCondition = "EnableLag_Location")) + float LocationLag; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design | CameraLag", meta = (EditCondition = "EnableLag_Rotation")) + float RotationLag; + + UPROPERTY() + FOnFinishCameraFade OnFinishCameraFade; + +private: + UPROPERTY() + UTimelineComponent* CameraZoomTimeline; + + UPROPERTY() + FTimerHandle FadeActionHandle; + + EZoomType CameraZoomInOut; + float CurrentCameraZoom; + float ZoomValue; + FOnTimelineFloat InterpFunction; +}; diff --git a/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.cpp b/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.cpp new file mode 100644 index 0000000..4da75cd --- /dev/null +++ b/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.cpp @@ -0,0 +1,123 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ObstacleFilterComponent.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" + +UObstacleFilterComponent::UObstacleFilterComponent() +{ + PrimaryComponentTick.bCanEverTick = true; +} + +void UObstacleFilterComponent::BeginPlay() +{ + Super::BeginPlay(); +} + +void UObstacleFilterComponent::OnObstacleFilterBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(!Cast(OtherActor)) + return; + + if(OnEnterSphereRange.IsBound()) + { + OnEnterSphereRange.Broadcast(OtherActor); + } +} + +void UObstacleFilterComponent::OnObstacleFilterEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + if(!Cast(OtherActor)) + return; + + if(OnExitedSphereRange.IsBound()) + { + OnExitedSphereRange.Broadcast(); + NMT_LOG("OnExitedSphereRange"); + } +} + +void UObstacleFilterComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void UObstacleFilterComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + OnEnterSphereRange.Clear(); + OnExitedSphereRange.Clear(); +} + +void UObstacleFilterComponent::InitializeProperty(const FObstacleFilterInfo& InObstacleFilterInfo) +{ + ObstacleFilterInfo = InObstacleFilterInfo; + SetSphereRadius(ObstacleFilterInfo.SphereRadius); + + for(ECollisionChannel ObstacleChannel : ObstacleFilterInfo.TraceCollisionChannels) + { + ObjectQueryParams.AddObjectTypesToQuery(ObstacleChannel); + } + + OnComponentBeginOverlap.AddUniqueDynamic(this, &UObstacleFilterComponent::OnObstacleFilterBeginOverlap); + if(ObstacleFilterInfo.CheckOutOfRange) + { + OnComponentEndOverlap.AddUniqueDynamic(this, &UObstacleFilterComponent::OnObstacleFilterEndOverlap); + } +} + +void UObstacleFilterComponent::ActivateFiltering() +{ + SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics); + SetComponentTickEnabled(true); +} + +void UObstacleFilterComponent::DeactivateFiltering() +{ + if(OnExitedSphereRange.IsBound()) + OnExitedSphereRange.Clear(); + + SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + SetComponentTickEnabled(false); +} + +TArray UObstacleFilterComponent::GetNonBlockedActors(const FVector& InStartTrace, const FVector& InEndTrace) const +{ + TArray NonBlockedActors; + TArray OverlappedActors; + + GetOverlappingActors(OverlappedActors); + + for(AActor* Actor : OverlappedActors) + { + if(Actor == GetOwner()) + continue; + + FVector EndTraceLocation; + InEndTrace == FVector::ZeroVector ? EndTraceLocation = Actor->GetActorLocation() : EndTraceLocation = InEndTrace; + FHitResult HitResult; + GetWorld()->LineTraceSingleByObjectType(HitResult, InStartTrace, EndTraceLocation, ObjectQueryParams, FCollisionQueryParams()); + FColor HitColor = FColor::Red; + if(ObstacleFilterInfo.TraceCollisionChannels.IsEmpty()) + { + HitColor = FColor::Green; + NonBlockedActors.Add(Actor); + } + else + { + if(!HitResult.bBlockingHit) + { + HitColor = FColor::Green; + NonBlockedActors.Add(Actor); + } + } + +#if WITH_EDITOR + // DrawDebugLine(GetWorld(), InStartTrace, InEndTrace, HitColor, false, 0.1f, 0, 1.0f); +#endif + } + + return NonBlockedActors; +} diff --git a/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.h b/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.h new file mode 100644 index 0000000..3d12690 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/ObstacleFilterComponent.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/SphereComponent.h" +#include "ObstacleFilterComponent.generated.h" + + +USTRUCT(Blueprintable) +struct FObstacleFilterInfo +{ + GENERATED_BODY() + + FObstacleFilterInfo() : + SphereRadius(0.f), + CheckOutOfRange(false) + {} + + FObstacleFilterInfo(FName InSphereProfile, float InSphereRadius, bool InCheckOutOfRange) : + SphereRadius(InSphereRadius), + CheckOutOfRange(InCheckOutOfRange) + {} + + UPROPERTY() + TArray> TraceCollisionChannels; + + UPROPERTY() + float SphereRadius; + + UPROPERTY() + bool CheckOutOfRange; +}; + + +DECLARE_MULTICAST_DELEGATE_OneParam(FOnEnterSphereRange, AActor*); +DECLARE_MULTICAST_DELEGATE(FOnExitedSphereRange); +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class PROJECTT_API UObstacleFilterComponent : public USphereComponent +{ + GENERATED_BODY() + +public: + UObstacleFilterComponent(); + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + void InitializeProperty(const FObstacleFilterInfo& InObstacleFilterInfo); + void ActivateFiltering(); + void DeactivateFiltering(); + TArray GetNonBlockedActors(const FVector& InStartTrace, const FVector& InEndTrace = FVector::ZeroVector) const; + +protected: + virtual void BeginPlay() override; + + UFUNCTION() + void OnObstacleFilterBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void OnObstacleFilterEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + +public: + FOnEnterSphereRange OnEnterSphereRange; + FOnExitedSphereRange OnExitedSphereRange; + +private: + UPROPERTY() + FObstacleFilterInfo ObstacleFilterInfo; + + FCollisionObjectQueryParams ObjectQueryParams; +}; diff --git a/Source/ProjectT/System/Core/Components/PathFollowComponent.cpp b/Source/ProjectT/System/Core/Components/PathFollowComponent.cpp new file mode 100644 index 0000000..34ec131 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PathFollowComponent.cpp @@ -0,0 +1,118 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PathFollowComponent.h" +#include "Components/SplineComponent.h" +#include "AIController.h" +#include "Kismet/GameplayStatics.h" +#include "GameFramework/Character.h" + + +UPathFollowComponent::UPathFollowComponent() +{ + Direction = true; + SplineComponent = nullptr; + Destination = FVector::ZeroVector; + CurrentSplinePoint = 0; +} + +void UPathFollowComponent::BeginPlay() +{ + Super::BeginPlay(); + + ACharacter* OwnerCharacter = Cast(GetOwner()); + if (!OwnerCharacter) return; + + AAIController* AIController = Cast(OwnerCharacter->GetController()); + if (!AIController) return; + + SplineComponent = Cast(OwnerCharacter->GetComponentByClass(USplineComponent::StaticClass())); + + OwnerController = AIController; + OwnerController->ReceiveMoveCompleted.AddDynamic(this, &UPathFollowComponent::UpdatePath); +} + +void UPathFollowComponent::UpdatePath(FAIRequestID RequestID, EPathFollowingResult::Type Result) +{ + if (Result == EPathFollowingResult::Success) + { + if(ForcedActionMap.Contains(CurrentSplinePoint)) + { + OnSuccessMove.Broadcast(true, *ForcedActionMap.Find(CurrentSplinePoint)); + } + else + { + OnSuccessMove.Broadcast(false, EPatrolType::Patrol); + } + + if (Direction) + { + if (CurrentSplinePoint == SplineComponent->GetNumberOfSplinePoints() - 1) + { + if (SplineComponent->IsClosedLoop()) + { + CurrentSplinePoint = 0; + MoveToNextWayPoint(); + return; + } + else + { + Direction = ~Direction; + } + } + } + else + { + if (CurrentSplinePoint == 0) + { + if (SplineComponent->IsClosedLoop()) + { + CurrentSplinePoint = SplineComponent->GetNumberOfSplinePoints() - 1; + MoveToNextWayPoint(); + return; + } + + else + { + Direction = ~Direction; + } + } + } + + Direction ? CurrentSplinePoint += 1 : CurrentSplinePoint -= 1; + MoveToNextWayPoint(); + + } +} + +void UPathFollowComponent::MoveToNextWayPoint(bool ReverseDirection) +{ + if (OwnerController->ReceiveMoveCompleted.IsBound() == false) + { + OwnerController->ReceiveMoveCompleted.AddDynamic(this, &UPathFollowComponent::UpdatePath); + } + + Destination = SplineComponent->GetLocationAtSplinePoint(CurrentSplinePoint, ESplineCoordinateSpace::World); + OwnerController->MoveTo(Destination); + ReverseDirection ? Direction = ~Direction : Direction; +} + +void UPathFollowComponent::StopMove() +{ + if (OwnerController->ReceiveMoveCompleted.IsBound()) + { + OwnerController->ReceiveMoveCompleted.Clear(); + } + OwnerController->StopMovement(); +} + +void UPathFollowComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void UPathFollowComponent::OnComponentDestroyed(bool bDestroyingHierarchy) +{ + Super::OnComponentDestroyed(bDestroyingHierarchy); +} + diff --git a/Source/ProjectT/System/Core/Components/PathFollowComponent.h b/Source/ProjectT/System/Core/Components/PathFollowComponent.h new file mode 100644 index 0000000..ec8b223 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PathFollowComponent.h @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "Navigation/PathFollowingComponent.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "PathFollowComponent.generated.h" + +class AAIController; +class USplineComponent; + +DECLARE_MULTICAST_DELEGATE_TwoParams(FOnSuccessMove,bool,EPatrolType); + + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class PROJECTT_API UPathFollowComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UPathFollowComponent(); + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override; + + UFUNCTION() + void UpdatePath(FAIRequestID RequestID, EPathFollowingResult::Type Result); + + UFUNCTION(BlueprintCallable, Category = "Patrol") + void MoveToNextWayPoint(bool ReverseDirection = false); + + UFUNCTION(BlueprintCallable, Category = "Patrol") + void StopMove(); + +protected: + virtual void BeginPlay() override; + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPCAction") + TMap ForcedActionMap; + + FOnSuccessMove OnSuccessMove; + +private: + UPROPERTY() + TObjectPtr OwnerController; + + UPROPERTY() + TObjectPtr SplineComponent; + + int32 CurrentSplinePoint; + FVector Destination; + uint8 Direction : 1; +}; diff --git a/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.cpp b/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.cpp new file mode 100644 index 0000000..44b1a32 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.cpp @@ -0,0 +1,183 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PlayerInventoryComponent.h" + +#include "EnvironmentQuery/EnvQueryDebugHelpers.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Interfaces/WorldObjectProvider.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h" +#include "ProjectT/System/Core/Objects/LevelObject/ItemObject.h" + +class AWorldGameMode; + +UPlayerInventoryComponent::UPlayerInventoryComponent() +{ + PrimaryComponentTick.bCanEverTick = true; +} + +void UPlayerInventoryComponent::BeginPlay() +{ + Super::BeginPlay(); + + //fixme initialize from character inven data ex.slot num + for (int i = 0; i < 3; i++) + { + GimmickSlot.Add(FPlayerGimmickSlotData()); + } + for (int i = 0; i < 3; i++) + { + SpendSlot.Add(FPlayerSpendSlotData()); + } +} + +void UPlayerInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +bool UPlayerInventoryComponent::TryAddData(AActor* InGetObject) +{ + bool LocbRet = false; + if(!InGetObject->GetClass()->IsChildOf(AItemObject::StaticClass())) return false; + AItemObject* LocItemObject = Cast(InGetObject); + switch(IObjectInteractionControl::Execute_GetInteractionObjectType(InGetObject)) + { + case EInteractionObjectType::Item: + { + switch (LocItemObject->GetItemType()) + { + case EItemTypes::Gimick: + { + LocbRet = RefreshGimmickSlotData(LocItemObject); + break; + } + case EItemTypes::Usable: + { + LocbRet = RefreshSpendSlotData(LocItemObject); + break; + } + case EItemTypes::Collection: LocbRet = true; break; + default: case EItemTypes::None: NMT_CHECKF(0); + } + break; + } + case EInteractionObjectType::LevelObject: NOT_IMPLEMENTED(); break; + default: case EInteractionObjectType::None: NMT_CHECKF(0); + } + return LocbRet; +} + +bool UPlayerInventoryComponent::RefreshGimmickSlotData(AItemObject* InGetItem) +{ + bool LocbValidSlot = false; + bool bAddedSuccess = false; + int LocValidSlotIndex = -1; + for (int i = 0; i < GimmickSlot.Num(); i++) + { + if(GimmickSlot[i].ItemRowName == InGetItem->GetObjectRowName()) + { + LocValidSlotIndex = i; + LocbValidSlot = true; + break; + } + } + + if(LocbValidSlot) + { + GimmickSlot[LocValidSlotIndex].ItemCount ++; + if (UpdateGimmickInventoryData.IsBound()) UpdateGimmickInventoryData.Broadcast(InGetItem->GetObjectRowName(), GimmickSlot[LocValidSlotIndex], LocValidSlotIndex, 1); + bAddedSuccess = true; + } + else + { + for (int i = 0; i < GimmickSlot.Num(); i++) + { + if (GimmickSlot[i].ItemCount == 0) + { + GimmickSlot[i].ItemRowName = InGetItem->GetObjectRowName(); + GimmickSlot[i].ItemData = InGetItem->GetItemData(); + GimmickSlot[i].ItemCount ++; + if (UpdateGimmickInventoryData.IsBound()) UpdateGimmickInventoryData.Broadcast(InGetItem->GetObjectRowName(), GimmickSlot[i], i, 1); + bAddedSuccess = true; + break; + } + } + } + return bAddedSuccess; +} + +bool UPlayerInventoryComponent::RefreshSpendSlotData(AItemObject* InGetItem) +{ + bool LocbValidSlot = false; + int LocValidSlotIndex = -1; + for (int i = 0; i < SpendSlot.Num(); i++) + { + if(SpendSlot[i].ItemRowName == TEXT("None")) + { + LocValidSlotIndex = i; + LocbValidSlot = true; + break; + } + } + if(LocbValidSlot) + { + SpendSlot[LocValidSlotIndex].ItemRowName = InGetItem->GetObjectRowName(); + SpendSlot[LocValidSlotIndex].ItemData = InGetItem->GetItemData(); + if(UpdateSpendInventoryData.IsBound()) UpdateSpendInventoryData.Broadcast(InGetItem->GetObjectRowName(), InGetItem->GetItemData(), LocValidSlotIndex, 1); + } + else + { + NMT_LOG("Spend Slot Full Empty Slot") + } + return LocbValidSlot; +} + +void UPlayerInventoryComponent::UseGimmickSlotItem(int InSlotNumber) +{ + GimmickSlot[InSlotNumber].ItemCount--; + if (UpdateGimmickInventoryData.IsBound()) UpdateGimmickInventoryData.Broadcast(GimmickSlot[InSlotNumber].ItemRowName, GimmickSlot[InSlotNumber], InSlotNumber, -1); + if (GimmickSlot[InSlotNumber].ItemCount == 0) GimmickSlot[InSlotNumber] = FPlayerGimmickSlotData(); +} + +void UPlayerInventoryComponent::UseSpendSlotItem(int InSlotNumber, int& OutSkillId) +{ + if (SpendSlot[InSlotNumber].ItemRowName == TEXT("None")) OutSkillId = -1; + else OutSkillId = SpendSlot[InSlotNumber].ItemData.iItemSkillId; +} + +void UPlayerInventoryComponent::EmptySpendSlotItem(int InSlotNumber) +{ + SpendSlot[InSlotNumber] = FPlayerSpendSlotData(); + if (UpdateSpendInventoryData.IsBound()) UpdateSpendInventoryData.Broadcast("None", FItem(), InSlotNumber, -1); +} + +void UPlayerInventoryComponent::GetReserveItemRowNames(TArray& OutReserveRowNames) +{ + OutReserveRowNames.Empty(); + TArray LocReserveRowNames; + for(FPlayerGimmickSlotData LocCurItem : GimmickSlot) + { + if(LocCurItem.ItemRowName != "None") + LocReserveRowNames.Add(LocCurItem.ItemRowName); + } + OutReserveRowNames = LocReserveRowNames; +} + +void UPlayerInventoryComponent::GetMatchSlotNumber(FName InRowName, int& OutSlotNumber) +{ + int LocIndex = -1; + for(int i = 0; i < GimmickSlot.Num(); i++) + { + if(GimmickSlot[i].ItemRowName == InRowName) + { + LocIndex = i; + break; + } + } + OutSlotNumber = LocIndex; +} + diff --git a/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.h b/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.h new file mode 100644 index 0000000..f72cb6a --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PlayerInventoryComponent.h @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "ProjectT/Data/Gen/GenerateStructItem.h" +#include "ProjectT/Data/Player/Inventory/PlayerInventoryModel.h" +#include "PlayerInventoryComponent.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FUpdateGimmickInventory, const FName&, RowName, const FPlayerGimmickSlotData&, ItemData, const int32, SlotIndex, const int32, ResultCount); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FUpdateSpendInventory, const FName&, RowName, const FItem&, ItemData, const int32, SlotIndex, const int32, ResultCount); + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class PROJECTT_API UPlayerInventoryComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UPlayerInventoryComponent(); + virtual void BeginPlay() override; + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + void UseSpendSlotItem(int InSlotNumber, int& OutSkillId); + void EmptySpendSlotItem(int InSlotNumber); + void GetReserveItemRowNames(TArray& OutReserveRowNames); + void GetMatchSlotNumber(FName InRowName, int& OutSlotNumber); + FORCEINLINE TArray GetGimmickSlot() { return GimmickSlot; } + + UFUNCTION(BlueprintCallable) + bool TryAddData(AActor* InGetObject); + + UFUNCTION(BlueprintCallable) + void UseGimmickSlotItem(int InSlotNumber); + +protected: + bool RefreshGimmickSlotData(class AItemObject* InGetItem); + bool RefreshSpendSlotData(AItemObject* InGetItem); + +public: + UPROPERTY(BlueprintAssignable) + FUpdateGimmickInventory UpdateGimmickInventoryData; + + UPROPERTY(BlueprintAssignable) + FUpdateSpendInventory UpdateSpendInventoryData; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray GimmickSlot; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray SpendSlot; + + +}; diff --git a/Source/ProjectT/System/Core/Components/PlayerStatusComponent.cpp b/Source/ProjectT/System/Core/Components/PlayerStatusComponent.cpp new file mode 100644 index 0000000..28f5dee --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PlayerStatusComponent.cpp @@ -0,0 +1,185 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PlayerStatusComponent.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" + +UPlayerStatusComponent::UPlayerStatusComponent() +{ + + PrimaryComponentTick.bCanEverTick = true; + +} + +void UPlayerStatusComponent::BeginPlay() +{ + Super::BeginPlay(); + +} + +void UPlayerStatusComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + +} + +void UPlayerStatusComponent::InitializeStatusData(FPlayerCharacter InPlayerData) +{ + PreviousPlayerStatus = InPlayerData; + CurrentPlayerStatus = InPlayerData; +} + +void UPlayerStatusComponent::ResetStatusDefault() +{ + CurrentPlayerStatus = PreviousPlayerStatus; +} + +bool UPlayerStatusComponent::ApplyDamage(float InApplyDamage) +{ + ACorePlayerCharacter* LocOwner = Cast(GetOwner()); + if(!LocOwner) return false; + bool LocPlayerInvincible; + LocOwner->GetInvincible(LocPlayerInvincible); + + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + LocPlayerInvincible = CCM->GetDebugStatus().bDebugPlayerInvincibleHP ? true : LocPlayerInvincible; + + if(!LocPlayerInvincible) + { + CurrentPlayerStatus.fCharHp = CurrentPlayerStatus.fCharHp - InApplyDamage; + if(UpdatePlayerHpPercent.IsBound()) UpdatePlayerHpPercent.Broadcast(CurrentPlayerStatus.fCharHp / PreviousPlayerStatus.fCharHp); + } + return CurrentPlayerStatus.fCharHp <= 0.f; +} + +void UPlayerStatusComponent::SpendPlayerStamina(bool InbSpend) +{ + float LocUpdateStaminaValue; + if(InbSpend) + { + LocUpdateStaminaValue = -20.f * GetWorld()->DeltaTimeSeconds; + } + else + { + LocUpdateStaminaValue = PreviousPlayerStatus.fStaRecovery * GetWorld()->DeltaTimeSeconds; + } + CurrentPlayerStatus.fStamina = CurrentPlayerStatus.fStamina + LocUpdateStaminaValue; + if(UpdatePlayerStaminaPercent.IsBound()) UpdatePlayerStaminaPercent.Broadcast(CurrentPlayerStatus.fStamina / PreviousPlayerStatus.fStamina); +} + +FPlayerCharacter UPlayerStatusComponent::GetPreviousPlayerStatus() +{ + return PreviousPlayerStatus; +} + +FPlayerCharacter UPlayerStatusComponent::GetCurrentPlayerStatus() +{ + return CurrentPlayerStatus; +} + +float UPlayerStatusComponent::GetStatusPreviousCharHp() +{ + return PreviousPlayerStatus.fCharHp; +} + +float UPlayerStatusComponent::GetStatusCharHp() +{ + return CurrentPlayerStatus.fCharHp; +} + +void UPlayerStatusComponent::SetStatusCharHp(float InSetValue) +{ + CurrentPlayerStatus.fCharHp = InSetValue; +} + +float UPlayerStatusComponent::GetStatusPreviousCharMove() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return PreviousPlayerStatus.fCharMove * (CCM->GetDebugStatus().bDebugPlayerSpeed ? 2.f : 1.f); +} + +float UPlayerStatusComponent::GetStatusCharMove() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return CurrentPlayerStatus.fCharMove * (CCM->GetDebugStatus().bDebugPlayerSpeed ? 2.f : 1.f); +} + +void UPlayerStatusComponent::SetStatusCharMove(float InSetValue) +{ + CurrentPlayerStatus.fCharMove = InSetValue; +} + +void UPlayerStatusComponent::AddStatusCharMove(float InAddValue) +{ + CurrentPlayerStatus.fCharMove = GetStatusCharMove() + InAddValue; +} + +float UPlayerStatusComponent::GetStatusCharMoveSound() +{ + return CurrentPlayerStatus.fCharMoveSound; +} + +void UPlayerStatusComponent::SetStatusCharMoveSound(float InSetValue) +{ + CurrentPlayerStatus.fCharMoveSound = InSetValue; +} + +float UPlayerStatusComponent::GetStatusPreviousCharRun() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return CurrentPlayerStatus.fCharRun * (CCM->GetDebugStatus().bDebugPlayerSpeed ? 2.f : 1.f); +} + +float UPlayerStatusComponent::GetStatusCharRun() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return CurrentPlayerStatus.fCharRun * (CCM->GetDebugStatus().bDebugPlayerSpeed ? 2.f : 1.f); +} + +void UPlayerStatusComponent::SetStatusCharRun(float InSetValue) +{ + CurrentPlayerStatus.fCharRun = InSetValue; +} + +void UPlayerStatusComponent::AddStatusCharRun(float InAddValue) +{ + CurrentPlayerStatus.fCharRun = GetStatusCharRun() + InAddValue; +} + +float UPlayerStatusComponent::GetStatusCharRunSound() +{ + return CurrentPlayerStatus.fCharRunSound; +} + +void UPlayerStatusComponent::SetStatusCharRunSound(float InSetValue) +{ + CurrentPlayerStatus.fCharRunSound = InSetValue; +} + +float UPlayerStatusComponent::GetStatusPreviousStamina() +{ + return PreviousPlayerStatus.fStamina; +} + +float UPlayerStatusComponent::GetStatusStamina() +{ + return CurrentPlayerStatus.fStamina; +} + +void UPlayerStatusComponent::SetStatusStamina(float InSetValue) +{ + CurrentPlayerStatus.fStamina = InSetValue; +} + +float UPlayerStatusComponent::GetStatusStaRecovery() +{ + return CurrentPlayerStatus.fStaRecovery; +} + +void UPlayerStatusComponent::SetStatusStaRecovery(float InSetValue) +{ + CurrentPlayerStatus.fStaRecovery = InSetValue; +} + diff --git a/Source/ProjectT/System/Core/Components/PlayerStatusComponent.h b/Source/ProjectT/System/Core/Components/PlayerStatusComponent.h new file mode 100644 index 0000000..35213ba --- /dev/null +++ b/Source/ProjectT/System/Core/Components/PlayerStatusComponent.h @@ -0,0 +1,106 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateStructPlayerCharacter.h" +#include "Components/ActorComponent.h" +#include "PlayerStatusComponent.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUpdatePlayerHp, const float, HpPercent); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUpdatePlayerStamina, const float, StaminaPercent); + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class PROJECTT_API UPlayerStatusComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UPlayerStatusComponent(); + + virtual void BeginPlay() override; + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + void InitializeStatusData(FPlayerCharacter InPlayerData); + void ResetStatusDefault(); + bool ApplyDamage(float InApplyDamage); + void SpendPlayerStamina(bool InbSpend); + + UFUNCTION(BlueprintCallable, BlueprintPure) + FPlayerCharacter GetPreviousPlayerStatus(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + FPlayerCharacter GetCurrentPlayerStatus(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousCharHp(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusCharHp(); + + UFUNCTION(BlueprintCallable) + void SetStatusCharHp(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousCharMove(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusCharMove(); + + UFUNCTION(BlueprintCallable) + void SetStatusCharMove(float InSetValue); + + UFUNCTION(BlueprintCallable) + void AddStatusCharMove(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusCharMoveSound(); + + UFUNCTION(BlueprintCallable) + void SetStatusCharMoveSound(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousCharRun(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusCharRun(); + + UFUNCTION(BlueprintCallable) + void SetStatusCharRun(float InSetValue); + + UFUNCTION(BlueprintCallable) + void AddStatusCharRun(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusCharRunSound(); + + UFUNCTION(BlueprintCallable) + void SetStatusCharRunSound(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousStamina(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusStamina(); + + UFUNCTION(BlueprintCallable) + void SetStatusStamina(float InSetValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusStaRecovery(); + + UFUNCTION(BlueprintCallable) + void SetStatusStaRecovery(float InSetValue); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + FPlayerCharacter PreviousPlayerStatus; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PlayerStatus, meta = (AllowPrivateAccess = "true")) + FPlayerCharacter CurrentPlayerStatus; + + UPROPERTY(BlueprintAssignable) + FUpdatePlayerHp UpdatePlayerHpPercent; + + UPROPERTY(BlueprintAssignable) + FUpdatePlayerStamina UpdatePlayerStaminaPercent; +}; diff --git a/Source/ProjectT/System/Core/Components/VisionConeComponent.cpp b/Source/ProjectT/System/Core/Components/VisionConeComponent.cpp new file mode 100644 index 0000000..6702712 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/VisionConeComponent.cpp @@ -0,0 +1,234 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "VisionConeComponent.h" + +#include "Kismet/KismetSystemLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" + +UVisionConeComponent::UVisionConeComponent(const FObjectInitializer& ObjectInitializer) : + Super(ObjectInitializer), + bDebugIsEnabled(false), + bUpdateEveryFrame(true), + SightRange(500.f), + SightAngle(90.f), + TriangleCount(10), + VisionRangeTraceChannel(ECC_GameTraceChannel2), // NOTE : Vision + TraceStartLocation(FVector::ZeroVector), + VisionMaterial(nullptr), + VisionParamName(TEXT("BaseColor")), + VisionGaugeName(TEXT("Amount")), + VisionRangeName(TEXT("MaxRange")), + DefaultColor(FLinearColor(0.f, 1.f, 0.f, 0.3f)), + HitColor(FLinearColor(1.f, 0.f, 0.f, 0.3f)), + MeshOffset(50.f), + bAllowDraw(false), + bDrawing(false), + bUpdatedOnce(false) +{ + PrimaryComponentTick.bCanEverTick = true; + PrimaryComponentTick.bStartWithTickEnabled = false; + BodyInstance.SetCollisionProfileName(TEXT("NoCollision")); + BodyInstance.SetCollisionEnabled(ECollisionEnabled::NoCollision); + SetCanEverAffectNavigation(false); +} + +void UVisionConeComponent::BeginPlay() +{ + Super::BeginPlay(); + + if(IsValid(VisionMaterial)) + { + VisionDynamicMaterial = CreateAndSetMaterialInstanceDynamicFromMaterial(0, VisionMaterial); + } + + InitializeMeshGeometry(); + VisionRangeTypeQuery = UEngineTypes::ConvertToTraceType(VisionRangeTraceChannel); + bDrawing ? SetComponentTickEnabled(true) : SetComponentTickEnabled(false); + + VisionDynamicMaterial->SetScalarParameterValue(VisionRangeName, SightRange); +} + +void UVisionConeComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +#if WITH_EDITOR +void UVisionConeComponent::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); + + InitializeMeshGeometry(); +} +#endif + +void UVisionConeComponent::InitializeMeshGeometry() +{ + DivideAngleSize = SightAngle / TriangleCount; + + MeshGeometryData.VertexCount = TriangleCount + 2; + MeshGeometryData.Vertices.SetNum(MeshGeometryData.VertexCount); + MeshGeometryData.Vertices[0] = -FVector(0, 0, MeshOffset); + + MeshGeometryData.IndexCount = (MeshGeometryData.VertexCount - 2) * 3; + MeshGeometryData.Indices.SetNum(MeshGeometryData.IndexCount); + + for(int32 Index = 0; Index < MeshGeometryData.Vertices.Num() - 1; ++Index) + { + if(Index < MeshGeometryData.VertexCount - 2) + { + MeshGeometryData.Indices[Index * 3 + 2] = 0; + MeshGeometryData.Indices[Index * 3 + 1] = Index + 1; + MeshGeometryData.Indices[Index * 3] = Index + 2; + } + } +} + +void UVisionConeComponent::DrawLineOfSight(const FRotator& InViewRotation) +{ + TArray ViewPoints; + + for(int32 Index = 0; Index < TriangleCount + 1; ++Index) + { + float Angle = InViewRotation.Yaw - (SightAngle / 2.0f) + (DivideAngleSize * Index); + FSightTraceInfo SightTraceInfo = GetSightTraceInfo(Angle); + ViewPoints.Add(SightTraceInfo.Point); + } + + if(PrevViewPoints.Num() == ViewPoints.Num() && PrevViewPoints == ViewPoints) + return; + + for(int32 Index = 0; Index < ViewPoints.Num(); ++Index) + { + MeshGeometryData.Vertices[Index + 1] = GetComponentTransform().InverseTransformPosition(ViewPoints[Index] - FVector(0, 0, MeshOffset)); + } + + if(GetProcMeshSection(0) == nullptr) + { + CreateMeshSection_LinearColor(0, MeshGeometryData.Vertices, MeshGeometryData.Indices, MeshGeometryData.Normals, MeshGeometryData.UV, MeshGeometryData.VertexColors, MeshGeometryData.Tangents, false); + } + else + { + UpdateMeshSection_LinearColor(0, MeshGeometryData.Vertices, MeshGeometryData.Normals, MeshGeometryData.UV, MeshGeometryData.VertexColors, MeshGeometryData.Tangents); + } + + PrevViewPoints = ViewPoints; +} + +void UVisionConeComponent::UpdateMaterialState(const FLinearColor& InColor) +{ + // if (!NMT_ENSURE(VisionDynamicMaterial)) + // return; + + if(VisionDynamicMaterial == nullptr) + return; + + if(CurrentColor == InColor) + return; + + VisionDynamicMaterial->SetVectorParameterValue(VisionParamName, InColor); + CurrentColor = InColor; +} + +FSightTraceInfo UVisionConeComponent::GetSightTraceInfo(float InAngle) const +{ + FHitResult OutHit; + FVector Dir = FRotator(0.f, InAngle, 0.f).Vector(); + FVector Start; + GetOwner()->GetClass()->ImplementsInterface(UAISettings::StaticClass()) ? Start = IAISettings::Execute_GetViewTransform(GetOwner()).GetLocation() : Start = GetComponentLocation(); + + FVector End = (Dir * SightRange) + Start; + +#if WITH_EDITOR + EDrawDebugTrace::Type DrawDebugType = bDebugIsEnabled ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None; + TArray ActorsToIgnore; + + if(UKismetSystemLibrary::LineTraceSingle(this, Start, End, VisionRangeTypeQuery, false, ActorsToIgnore, DrawDebugType, OutHit, true)) + { + return FSightTraceInfo(OutHit.Location, OutHit.Distance, InAngle); + } +#else + if (GetWorld()->LineTraceSingleByChannel(OutHit, Start, End, VisionRangeTraceChannel)) + { + return FSightTraceInfo(OutHit.Location, OutHit.Distance, InAngle); + } +#endif + + + return FSightTraceInfo(OutHit.TraceEnd, SightRange, InAngle); +} + +void UVisionConeComponent::SetupSightSettings(const float InSightRange, const float InSightAngle) +{ + SightRange = InSightRange; + SightAngle = InSightAngle; +} + +void UVisionConeComponent::UpdateVisionColor(const bool InbHit) +{ + InbHit ? UpdateMaterialState(HitColor) : UpdateMaterialState(DefaultColor); +} + +void UVisionConeComponent::UpdateVision(const FRotator& InViewRotation) +{ + if(bUpdateEveryFrame) + { + DrawLineOfSight(InViewRotation); + } + else + { + if(!bUpdatedOnce) + { + DrawLineOfSight(InViewRotation); + bUpdatedOnce = true; + } + } +} + +void UVisionConeComponent::UpdateVisionGauge(const float InGauge) const +{ + VisionDynamicMaterial->SetScalarParameterValue(VisionGaugeName, InGauge); +} + +void UVisionConeComponent::ToggleDraw(const bool InbDraw) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + bool bDraw = InbDraw | CCM->GetDebugStatus().bDebugVision; + if(IsMeshSectionVisible(0) != bDraw) + { + if(bDraw) + { + bAllowDraw = true; + SetMeshSectionVisible(0, true); + SetComponentTickEnabled(true); + } + else + { + bAllowDraw = false; + SetMeshSectionVisible(0, false); + SetComponentTickEnabled(false); + } + + bDrawing = bDraw; + } +} + +bool UVisionConeComponent::IsAllowedDrawing() const +{ + return bAllowDraw; +} + +void UVisionConeComponent::EnableVision() +{ + SetComponentTickEnabled(true); + SetMeshSectionVisible(0, true); +} + +void UVisionConeComponent::DisableVision() +{ + SetMeshSectionVisible(0, false); + SetComponentTickEnabled(false); +} diff --git a/Source/ProjectT/System/Core/Components/VisionConeComponent.h b/Source/ProjectT/System/Core/Components/VisionConeComponent.h new file mode 100644 index 0000000..2de4aeb --- /dev/null +++ b/Source/ProjectT/System/Core/Components/VisionConeComponent.h @@ -0,0 +1,184 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProceduralMeshComponent.h" +#include "VisionConeComponent.generated.h" + +USTRUCT() +struct FSightTraceInfo +{ + GENERATED_BODY() + + FSightTraceInfo() : + Point(FVector::ZeroVector), + Range(0.f), + Angle(0.f) + {} + + FSightTraceInfo(const FVector& InPoint, const float InRange, const float InAngle) : + Point(InPoint), + Range(InRange), + Angle(InAngle) + {} + + UPROPERTY() + FVector Point; + + UPROPERTY() + float Range; + + UPROPERTY() + float Angle; +}; + +USTRUCT() +struct FMeshGeometryData +{ + GENERATED_BODY() + + FMeshGeometryData() : + VertexCount(0), + IndexCount(0) + {} + + FMeshGeometryData(int32 InVertexCount, int32 InIndexCount) : + VertexCount(InVertexCount), + IndexCount(InIndexCount) + {} + + UPROPERTY() + int32 VertexCount; + + UPROPERTY() + int32 IndexCount; + + UPROPERTY() + TArray Vertices; + + UPROPERTY() + TArray Indices; + + UPROPERTY() + TArray Normals; + + UPROPERTY() + TArray UV; + + UPROPERTY() + TArray VertexColors; + + UPROPERTY() + TArray Tangents; +}; + +UCLASS(ClassGroup = Rendering, meta = (BlueprintSpawnableComponent)) +class PROJECTT_API UVisionConeComponent : public UProceduralMeshComponent +{ + GENERATED_BODY() + +public: + UVisionConeComponent(const FObjectInitializer& ObjectInitializer); + + virtual void BeginPlay() override; + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + +#if WITH_EDITOR + virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + + UFUNCTION(BlueprintCallable) + void ToggleDraw(const bool InbDraw); + + FORCEINLINE bool IsDrawing() const { return bDrawing; } + FORCEINLINE void SetAllowDrawing(const bool InbAllowDrawing) { bAllowDraw = InbAllowDrawing; } + bool IsAllowedDrawing() const; + void SetupSightSettings(const float InSightRange, const float InSightAngle); + void UpdateVisionColor(const bool InbHit); + void UpdateVision(const FRotator& InViewRotation); + void UpdateVisionGauge(const float InGauge) const; + +private: + UFUNCTION() + void EnableVision(); + + UFUNCTION() + void DisableVision(); + + void InitializeMeshGeometry(); + void DrawLineOfSight(const FRotator& InViewRotation); + void UpdateMaterialState(const FLinearColor& InColor); + FSightTraceInfo GetSightTraceInfo(float InAngle) const; + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + uint8 bDebugIsEnabled : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + uint8 bUpdateEveryFrame : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + float SightRange; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight", meta = (ClampMin = 0, ClampMax = 360)) + float SightAngle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + int32 TriangleCount; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + TEnumAsByte VisionRangeTraceChannel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight") + FVector TraceStartLocation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + UMaterialInterface* VisionMaterial; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + FName VisionParamName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + FName VisionGaugeName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + FName VisionRangeName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + FLinearColor DefaultColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + FLinearColor HitColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight|MeshInfo") + float MeshOffset; + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LineOfSight", meta = (AllowprivateAccess = "true")) + uint8 bAllowDraw : 1; + + UPROPERTY(VisibleAnywhere) + uint8 bDrawing : 1; + + UPROPERTY() + float DivideAngleSize; + + UPROPERTY() + FMeshGeometryData MeshGeometryData; + + UPROPERTY() + TArray PrevViewPoints; + + UPROPERTY() + TObjectPtr VisionDynamicMaterial; + + UPROPERTY() + FLinearColor CurrentColor; + + UPROPERTY() + TEnumAsByte VisionRangeTypeQuery; + + uint8 bUpdatedOnce; +}; + diff --git a/Source/ProjectT/System/Core/Components/WidgetManagerComponent.cpp b/Source/ProjectT/System/Core/Components/WidgetManagerComponent.cpp new file mode 100644 index 0000000..c53f61d --- /dev/null +++ b/Source/ProjectT/System/Core/Components/WidgetManagerComponent.cpp @@ -0,0 +1,134 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WidgetManagerComponent.h" +#include "Blueprint/UserWidget.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +UWidgetManagerComponent::UWidgetManagerComponent() +{ + PrimaryComponentTick.bCanEverTick = true; +} + +// Called when the game starts +void UWidgetManagerComponent::BeginPlay() +{ + Super::BeginPlay(); + + + /*OnClosedAllWidget.AddLambda([this] + { + ActiveWidget = nullptr; + ToggleGameUIInput(false); + });*/ +} + +// Called every frame +void UWidgetManagerComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void UWidgetManagerComponent::AsyncOpenWidget(const TSoftClassPtr& InWidgetClass) +{ + UGlobalUtilsLibrary::AsyncLoadSubClass(InWidgetClass, [this](const TSubclassOf& LoadedWidgetClass) + { + if(LoadedWidgetClass) + { + OpenWidget(LoadedWidgetClass); + + if(OnCompletedCreateWidget.IsBound()) + { + OnCompletedCreateWidget.Execute(); + } + } + }); +} + +void UWidgetManagerComponent::AsyncOpenWidgetWithCallback(const TSoftClassPtr& InWidgetClass, FOnCompletedCreateWidget InCallback) +{ + UGlobalUtilsLibrary::AsyncLoadSubClass(InWidgetClass, [this, InCallback](const TSubclassOf& LoadedWidgetClass) + { + if(LoadedWidgetClass) + { + OnCompletedCreateWidget = InCallback; + OpenWidget(LoadedWidgetClass); + OnCompletedCreateWidget.Execute(); + } + }); +} + +void UWidgetManagerComponent::OpenWidget(const TSubclassOf& InWidgetClass) +{ + if(!WidgetStack.IsEmpty()) + { + ActiveWidget->SetVisibility(ESlateVisibility::Collapsed); + } + + ActiveWidget = CreateWidget(GetWorld(), InWidgetClass); + ActiveWidget->AddToViewport(); + ActiveWidget->SetVisibility(ESlateVisibility::Visible); + + if(WidgetStack.IsEmpty()) + { + ToggleGameUIInput(); + } + + WidgetStack.Emplace(ActiveWidget); +} + +void UWidgetManagerComponent::CloseWidget() +{ + if(WidgetStack.IsEmpty()) return; + + WidgetStack.Last()->RemoveFromParent(); + WidgetStack.Pop(); + + if(!WidgetStack.IsEmpty()) + { + ActiveWidget = WidgetStack.Last(); + ActiveWidget->SetVisibility(ESlateVisibility::Visible); + } + else + { + if(OnClosedAllWidget.IsBound()) + { + OnClosedAllWidget.Execute(); + } + } +} + +void UWidgetManagerComponent::FlushAllWidget(FOnClosedAllWidget InCallBack) +{ + for(UUserWidget* Widget : WidgetStack) + { + Widget->RemoveFromParent(); + } + + WidgetStack.Empty(); + + OnClosedAllWidget = InCallBack; + + if(OnClosedAllWidget.IsBound()) + { + OnClosedAllWidget.Execute(); + } +} + +void UWidgetManagerComponent::FlushAllWidget() +{ + for(UUserWidget* Widget : WidgetStack) + { + Widget->RemoveFromParent(); + } + + WidgetStack.Empty(); +} + +void UWidgetManagerComponent::ToggleGameUIInput(const bool InbGameAndUI/* = true*/) const +{ + APlayerController* PC = GetWorld()->GetFirstPlayerController(); + if(!NMT_ENSURE(PC)) return; + + InbGameAndUI ? PC->SetInputMode(FInputModeGameAndUI()) : PC->SetInputMode(FInputModeGameOnly()); +} diff --git a/Source/ProjectT/System/Core/Components/WidgetManagerComponent.h b/Source/ProjectT/System/Core/Components/WidgetManagerComponent.h new file mode 100644 index 0000000..5bc2222 --- /dev/null +++ b/Source/ProjectT/System/Core/Components/WidgetManagerComponent.h @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "WidgetManagerComponent.generated.h" + + +enum class ECommonInputType : uint8; + +DECLARE_DYNAMIC_DELEGATE(FOnCompletedCreateWidget); +DECLARE_DYNAMIC_DELEGATE(FOnClosedAllWidget); + +UCLASS(ClassGroup="UI", meta=(BlueprintSpawnableComponent)) +class PROJECTT_API UWidgetManagerComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UWidgetManagerComponent(); + +protected: + virtual void BeginPlay() override; + +public: + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + UFUNCTION(BlueprintCallable) + void AsyncOpenWidget(const TSoftClassPtr& InWidgetClass); + + UFUNCTION(BlueprintCallable) + void CloseWidget(); + + UFUNCTION(BlueprintCallable) + void FlushAllWidget(FOnClosedAllWidget InCallBack); + + void FlushAllWidget(); + + UFUNCTION(BlueprintPure) + FORCEINLINE UUserWidget* GetActiveWidget() const { return ActiveWidget; }; + + UFUNCTION(BlueprintCallable) + void AsyncOpenWidgetWithCallback(const TSoftClassPtr& InWidgetClass, FOnCompletedCreateWidget InCallback); + + void ToggleGameUIInput(const bool InbGameAndUI = true) const; + +private: + void OpenWidget(const TSubclassOf& InWidgetClass); + +public: + + UPROPERTY() + FOnCompletedCreateWidget OnCompletedCreateWidget; + UPROPERTY() + FOnClosedAllWidget OnClosedAllWidget; + +private: + UPROPERTY() + TObjectPtr ActiveWidget; + + UPROPERTY() + TArray> WidgetStack; +}; diff --git a/Source/ProjectT/System/Core/Core.zip b/Source/ProjectT/System/Core/Core.zip new file mode 100644 index 0000000000000000000000000000000000000000..aec1fcb5b367550362123d8962bb5af25ad9a894 GIT binary patch literal 2672 zcmZvecTf{Z8;3*a1fm3Kp-Ar?M5=V@y*Gu>OF{<$F-HfHUPG7O1;G&7K~O*erHk~A z)DIO5MIaw{^W8T$bGJLQzu9+Z=lN%M-p5FnkmwEo03ZV_g77v;#W-kN7q-EofHU5|UL|ddZJEbC4nyS{)SB_Uht`gn z!`3Z3^u?6o|3kU`gd}8LKmgv<@`d2`nK@k2=9S=EXcowfRif6iojm_>*_W6-;0hzX zOJq~&_w}=ws+kO03xUd<6GyX2ipX1?8*{*!x2R6+h^!$E}Lm zvlIS?dxNg^xL@m1_QHscC21dMTJyxd-++#%Ey^OVM<2?{yMG*05;M4vBd;LMuS|z- ze5D0Q9wZ-aOtZDz=djK7GX798S)%psu4O`^YBHaAA`3^x?Gi4brpzqxNgEI+qXEj% zHV`PolKJKMRwH0yKRN)*fMJS0Ypf@SVjM_rpe&qaNBpN_pLVJGXQIEJ$SqJ)3g`TDc{(#u*t-Y{NNA%@xVevx>AO&%vE@+77RXVsw*2-KYm*0%)Ae~k} z+hRVC`WWgFb!#%19TbwREIQ4dBr8AbCPe=>)V6$-Bp^k*bO_D1%7eD&5ccu>fi$(U zc98&$V7h)|nWBsLH>hZ;`XQs{J=tG~sWeFtGC)-g=dfiCntXM54d4(StM+1Z(y8>_oWGft;R8QT_@+!Hpi zHcpqqScx!3v6Z9UiOis0Q}z4UQ`qLOO7?+syIASa9h-;1O&np2S)E09m|BA!{83Y^ z<(zX)=X6Y3fDnDXw^{<1kgJ|Ff%)3n9vMY1i1qE`N)r@zf^%=SG(IK4J9%49`ng3_ zj@ztdjat8HHUV8Y6&hO5ur3;%oRwSFO*TEhOD8Zcc!G@(H@X}nwPF~Sqc>{(s*qB? zv+@1=cbI8WXM>lwh#WpkhZZ=1=$y>euYIFqf9;cMO=jQv#FlkqGm`1!e)0X2d^3i0 zS)Qs(YG&oU+u^T}YCR>VVX5G&tC06Ap>s&zalGHJv)S_H9^UsW;SkX{i6e79%KA&`SO}P5(zqA zARRh7!UdzlRx1mRS_YKp7VDC+Pq~ghW6i`M8`Ze zVfHbg%uk6Lo5$=!B$aFCoO>eepIHy{{_GYiYdJZPC~N~$-Hlc<5Ns~lU$mO0wlRfD z$gQ^(WL;&HVVdzh?Op2yqaVLd6dmYbknQ-BapdLr%KUyrZ!F-e5|VflE_Tq1*;m5z zz?i^p)3Om5D{_m#nxO8N1}X@a)WLIR^IS{U5ZN~|(lZ1?h0-PZnK@g1^$C)l)CE)P zz-Ip(ntBp|V$e6kR+>l6yz_}8*0>A@qZlY?dn|FQ0$u_?VL9i0B@P=!C8ACQr*2KyXp%*V$c?+k`}VnswZ{ zyJS2ocs_xZtJdE&I1V&7hfkeVzMhx7+p^GwETB;J zbh>vNS|hC-+U3qdK{|({Zmr=T1KtrglPNODR4%0y9>uh`P8GWpn2$PG)FT4P^P8SW zde$vui}O~z4iTiyJI}WmahfETvN!M;0ANR$Fx0qLrJLx=jIa>OayIo(3KEf0p-L}J zr`0QV)-`tf5*5$^wNh$(k91ep2l2cMgbySeNp-Q&ex|=jjsD-oxO=Z{wpl(o<^ur$ zX;J_H@^4+tJ=x6IXI`1|8A&4EAxKore5+?EZJw)HFG~y}bx6*V$b{%z)W`)v@^LHs zAP;)Tu+bg<)4A(|*4`%yas2c^Gmq6$9jcb$Tlv-UgeHuvoWA6)@vAUuuVSVqu1z5g zBhlvRz59bCs#0+yZ5XB#(ksIbSC2vE4-EB^xh;G&F-)2sPq#DN^cD{h`E-U=cI!_D zB~Dx%8Dh~2du9_~T;h`5_zsiu8Bd&1v2g;P8fTNG&m6_+Hc&>kJW-777lL&c(?42%mSp99=H|*SkAPvH13!a2mq4kg!<=YzT6~CYjSgy>{Q9NJ%pBO; zR8HQx%IVw~Hla)!F&nU*D(JHj7T|+p2rW=v&+y2hs*Wt&V2y%)c!Kl(`>cPEu*5M5#{Ga&56rR`=Hy?oTVt9;o2QN>>U(K|UJU9R<~W zS1vT*i=mqE*TE80nln9N;Z6DaZCWlowS zc73!Qdm2rEpBB6#sgH^=bukrJmF>?3{BUJ9?;avUO-G6LQp-yp;CzN*z>iaS4#PIF zNE{4P_=cTeIIPn{{j^ZeH^rgYD1t-~Ei@f2RZh1^|Tv)WnBik>IaXWrHlI?ky1fo$}8g^LNVN ojSc?80^R@4U_h41z-}0Sr3d0K2Jy{Z004M1hi@{C{Eyv#0qfY#ApigX literal 0 HcmV?d00001 diff --git a/Source/ProjectT/System/Core/CoreGameInstance.cpp b/Source/ProjectT/System/Core/CoreGameInstance.cpp new file mode 100644 index 0000000..de5ac38 --- /dev/null +++ b/Source/ProjectT/System/Core/CoreGameInstance.cpp @@ -0,0 +1,118 @@ + +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreGameInstance.h" + +#include "HAL/PlatformTime.h" +#include "TimerManager.h" +#include "Blueprint/UserWidget.h" +#include "Common/AssetUtilsLibrary.h" +#include "Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Managers/OptionManager.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" +#include "ProjectT/System/Core/Managers/StageManager.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "Widgets/Images/SThrobber.h" + +static double GLoadingStartTime = 0.0; + +UCoreGameInstance::UCoreGameInstance() : + DataDam(nullptr), + StageManager(nullptr), + OptionManager(nullptr), + SoundManager(nullptr), + CoreCheatManager(nullptr), + NotificationCenter(nullptr) +{ +} + +void UCoreGameInstance::Init() +{ + Super::Init(); + + Execute_GetDataDam(this)->Initialize(); + + StageManager = NewObject(this); + OptionManager = NewObject(this); + SoundManager = NewObject(this); + CoreCheatManager = NewObject(this); +} + +void UCoreGameInstance::BeginDestroy() +{ + Super::BeginDestroy(); + + DataDam = nullptr; + StageManager = nullptr; + OptionManager = nullptr; + SoundManager = nullptr; + CoreCheatManager = nullptr; +} + +UDataDam* UCoreGameInstance::GetDataDam_Implementation() +{ + if (!DataDam) + { + DataDam = NewObject(this); + } + return DataDam; +} + +UStageManager* UCoreGameInstance::GetStageManager_Implementation() +{ + if(!StageManager) + { + StageManager = NewObject(this); + } + return StageManager; +} + +UOptionManager* UCoreGameInstance::GetOptionManager_Implementation() +{ + if (!OptionManager->IsValidLowLevel()) + { + OptionManager = NewObject(this); + } + return OptionManager; +} + +USoundManager* UCoreGameInstance::GetSoundManager_Implementation() +{ + if (!SoundManager->IsValidLowLevel()) + { + SoundManager = NewObject(this); + } + return SoundManager; +} + +UCoreCheatManager* UCoreGameInstance::GetCoreCheatManager_Implementation() +{ + if(!CoreCheatManager->IsValidLowLevel()) + { + CoreCheatManager = NewObject(this); + } + return CoreCheatManager; +} + +UNotificationCenter* UCoreGameInstance::GetNotificationCenter_Implementation() +{ + if(!NotificationCenter) + { + NotificationCenter = NewObject(this); + } + return NotificationCenter; +} + +bool UCoreGameInstance::IsRunningInDevelopment() +{ + EBuildTargetType BT = FApp::GetBuildTargetType(); + EBuildConfiguration BC = FApp::GetBuildConfiguration(); + + if(BT == EBuildTargetType::Editor) return true; + else if(BT == EBuildTargetType::Game && BC == EBuildConfiguration::DebugGame) return true; + else if(BT == EBuildTargetType::Game && BC == EBuildConfiguration::Development) return true; + else return false; +} diff --git a/Source/ProjectT/System/Core/CoreGameInstance.h b/Source/ProjectT/System/Core/CoreGameInstance.h new file mode 100644 index 0000000..97719c1 --- /dev/null +++ b/Source/ProjectT/System/Core/CoreGameInstance.h @@ -0,0 +1,60 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/GameInstance.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "Interfaces/GlobalObjectProvider.h" +#include "Managers/StageManager.h" +#include "CoreGameInstance.generated.h" + + +class UNotificationCenter; +class USoundManager; +class UOptionManager; +class UCoreCheatManager; +class UQuestManager; + +DECLARE_DELEGATE_OneParam(FOnLevelDataChanged, EStage); +UCLASS() +class PROJECTT_API UCoreGameInstance : public UGameInstance, public IGlobalObjectProvider +{ + GENERATED_BODY() + +public: + UCoreGameInstance(); + + virtual void Init() override; + virtual void BeginDestroy() override; + + virtual UDataDam* GetDataDam_Implementation() override; + virtual UStageManager* GetStageManager_Implementation() override; + virtual UOptionManager* GetOptionManager_Implementation() override; + virtual USoundManager* GetSoundManager_Implementation() override; + virtual UCoreCheatManager* GetCoreCheatManager_Implementation() override; + virtual UNotificationCenter* GetNotificationCenter_Implementation() override; + +public: + UFUNCTION(BlueprintCallable, Category = "IsRunningInDevelopment") + bool IsRunningInDevelopment(); + +private: + UPROPERTY() + TObjectPtr DataDam; + + UPROPERTY() + TObjectPtr StageManager; + + UPROPERTY() + TObjectPtr OptionManager; + + UPROPERTY() + TObjectPtr SoundManager; + + UPROPERTY() + TObjectPtr CoreCheatManager; + + UPROPERTY() + TObjectPtr NotificationCenter; +}; diff --git a/Source/ProjectT/System/Core/ELoadingPhase.h b/Source/ProjectT/System/Core/ELoadingPhase.h new file mode 100644 index 0000000..132427a --- /dev/null +++ b/Source/ProjectT/System/Core/ELoadingPhase.h @@ -0,0 +1,12 @@ +#pragma once + +#include "CoreMinimal.h" + +UENUM(BlueprintType) +enum class ELoadingPhase : uint8 +{ + None, + MapLoading, + ShaderCompiling, + Finished +}; diff --git a/Source/ProjectT/System/Core/GameModes/CoreGameMode.cpp b/Source/ProjectT/System/Core/GameModes/CoreGameMode.cpp new file mode 100644 index 0000000..84a2ffd --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CoreGameMode.cpp @@ -0,0 +1,87 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreGameMode.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/LoadingManager.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" +#include "ProjectT/System/Core/Managers/StageManager.h" + +ACoreGameMode::ACoreGameMode() : + CoreWidgetManager(nullptr) +{ +} + +UCoreWidgetManager* ACoreGameMode::GetCoreWidgetManager_Implementation() +{ + return CoreWidgetManager; +} + +void ACoreGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) +{ + Super::InitGame(MapName, Options, ErrorMessage); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + + UGameInstance* GI = GetGameInstance(); + NMT_CHECKF(GI); + + UStageManager* StageMgr = IGlobalObjectProvider::Execute_GetStageManager(GI); + NMT_CHECKF(StageMgr); + + const FString& CurrentLevelName = UGameplayStatics::GetCurrentLevelName(World); + StageMgr->InitializeManager(World, CurrentLevelName); + + USoundManager* SoundMgr = IGlobalObjectProvider::Execute_GetSoundManager(GI); + NMT_CHECKF(SoundMgr); + SoundMgr->InitializeManager(World); + + UCoreCheatManager* CheatMgr = IGlobalObjectProvider::Execute_GetCoreCheatManager(GI); + NMT_CHECKF(CheatMgr); + CheatMgr->InitializeManager(World); +} + +void ACoreGameMode::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreGameMode::BeginDestroy() +{ + Super::BeginDestroy(); +} + +void ACoreGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + UGameInstance* GI = GetGameInstance(); + NMT_CHECKF(GI); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GI); + NC->ReleaseNotificationCenter(); + + USoundManager* SoundMgr = IGlobalObjectProvider::Execute_GetSoundManager(GI); + SoundMgr->ReleaseManager(); + + UStageManager* StageMgr = IGlobalObjectProvider::Execute_GetStageManager(GI); + StageMgr->ReleaseManager(); + + UCoreCheatManager* CheatMgr = IGlobalObjectProvider::Execute_GetCoreCheatManager(GI); + NMT_CHECKF(CheatMgr); + CheatMgr->ReleaseManager(); + +} + +void ACoreGameMode::InitializeManagers() +{ +} + +void ACoreGameMode::InitializeUI() +{ +} diff --git a/Source/ProjectT/System/Core/GameModes/CoreGameMode.h b/Source/ProjectT/System/Core/GameModes/CoreGameMode.h new file mode 100644 index 0000000..7c069b8 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CoreGameMode.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameMode.h" +#include "ProjectT/System/Core/Interfaces/CoreObjectProvider.h" +#include "CoreGameMode.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ACoreGameMode : public AGameMode, public ICoreObjectProvider +{ + GENERATED_BODY() + +public: + ACoreGameMode(); + virtual UCoreWidgetManager* GetCoreWidgetManager_Implementation() override; + + +protected: + virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override; + virtual void BeginPlay() override; + virtual void BeginDestroy() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void InitializeManagers(); + virtual void InitializeUI(); + +protected: + UPROPERTY() + TObjectPtr CoreWidgetManager; +}; diff --git a/Source/ProjectT/System/Core/GameModes/CoreGameState.cpp b/Source/ProjectT/System/Core/GameModes/CoreGameState.cpp new file mode 100644 index 0000000..4a5f031 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CoreGameState.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreGameState.h" + +ACoreGameState::ACoreGameState() +{ + +} + +void ACoreGameState::ChangeProcessState_Implementation(EProcessState NewState) +{ + IProcessStateControl::ChangeProcessState_Implementation(NewState); +} + +EProcessState ACoreGameState::GetProcessState_Implementation() +{ + return IProcessStateControl::GetProcessState_Implementation(); +} + +void ACoreGameState::BeginPlay() +{ + Super::BeginPlay(); +} + diff --git a/Source/ProjectT/System/Core/GameModes/CoreGameState.h b/Source/ProjectT/System/Core/GameModes/CoreGameState.h new file mode 100644 index 0000000..08e7372 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CoreGameState.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 "ProjectT/System/Core/Interfaces/ProcessStateControl.h" +#include "CoreGameState.generated.h" + + +DECLARE_DELEGATE_RetVal_OneParam(bool, FOnChangedProcessEvent, const EProcessState); + +UCLASS() +class PROJECTT_API ACoreGameState : public AGameState, public IProcessStateControl +{ + GENERATED_BODY() + +public: + ACoreGameState(); + virtual void ChangeProcessState_Implementation(EProcessState NewState) override; + virtual EProcessState GetProcessState_Implementation() override; + +protected: + virtual void BeginPlay() override; +}; diff --git a/Source/ProjectT/System/Core/GameModes/CorePlayerController.cpp b/Source/ProjectT/System/Core/GameModes/CorePlayerController.cpp new file mode 100644 index 0000000..254a0ae --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CorePlayerController.cpp @@ -0,0 +1,110 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CorePlayerController.h" + +#include "Blueprint/UserWidget.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h" +#include "ProjectT/System/Core/Components/WidgetManagerComponent.h" +#include "ProjectT/System/Core/Mouse/Mouse.h" + +ACorePlayerController::ACorePlayerController(): + bInitializePossessed(0) +{ + bEnableMouseOverEvents = true; + bEnableClickEvents = true; + + ClickEventKeys.Add(EKeys::RightMouseButton); +} + +void ACorePlayerController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + + if(!bInitializePossessed) + { + if(ACorePlayerCharacter* CPC = Cast(InPawn)) + { + USceneComponent* Listener = nullptr; + CPC->GetAudioListener(Listener); + NMT_CHECKF(Listener); + SetAudioListenerOverride(Listener, {}, {}); + + Mouse = NewObject(this); + if(Mouse) Mouse->InitializeMouse(); + } + } + bInitializePossessed = true; +} + +void ACorePlayerController::OnUnPossess() +{ + Super::OnUnPossess(); + bInitializePossessed = false; +} + +void ACorePlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + if (EndPlayReason == EEndPlayReason::Type::Quit) + { + if (WidgetManagerComp->IsValidLowLevel()) + { + WidgetManagerComp->FlushAllWidget(); + } + } +} + +void ACorePlayerController::InitializePlayerScreen() const +{ + if(NMT_ENSURE(CommonHUD)) + { + CommonHUD->AddToViewport(); + } +} + +void ACorePlayerController::MouseAimTracing(const bool InbStart, AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const float InAffectRange, const EMouseResultType InResultType, bool InbPathVisible) const +{ + NMT_CHECKF(Mouse); + Mouse->AimTracing(InbStart, InStandardActor, InAffectActors, InRange, InAffectRange, InResultType, InbPathVisible); +} + +FHitResult ACorePlayerController::GetMouseCursorHitResult(AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const EMouseResultType InResultType) const +{ + NMT_CHECKF(Mouse); + FHitResult LocHitResult; + if(Mouse != nullptr) LocHitResult = Mouse->GetCursorHitResult(InStandardActor, InAffectActors, InRange, InResultType); + return LocHitResult; +} + +void ACorePlayerController::BeginPlay() +{ + Super::BeginPlay(); + + //FIXME: 독립형 실행때 강제 스크린적용문제가 발생하여 임시로 주석 처리 + // UCoreGameUserSettings::GetCoreGameUserSettings()->InitializeUserSettings(); + + FInputModeGameAndUI UIInputMode; + UIInputMode.SetHideCursorDuringCapture(false); + SetInputMode(UIInputMode); + bShowMouseCursor = true; +} + +UWidgetManagerComponent* ACorePlayerController::GetWidgetManager() +{ + if (WidgetManagerComp->IsValidLowLevel()) + { + return WidgetManagerComp; + } + + return WidgetManagerComp = Cast(AddComponentByClass(UWidgetManagerComponent::StaticClass(), false, FTransform::Identity, false)); +} + +UUserWidget* ACorePlayerController::GetCurrentCommonHUD() +{ + NMT_ENSURE(CommonHUD); + return CommonHUD; +} + diff --git a/Source/ProjectT/System/Core/GameModes/CorePlayerController.h b/Source/ProjectT/System/Core/GameModes/CorePlayerController.h new file mode 100644 index 0000000..037d0f5 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CorePlayerController.h @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "CorePlayerController.generated.h" + +enum class EMouseResultType : uint8; + +UCLASS() +class PROJECTT_API ACorePlayerController : public APlayerController +{ + GENERATED_BODY() + +public: + ACorePlayerController(); + + virtual void OnPossess(APawn* InPawn) override; + virtual void OnUnPossess() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + void InitializePlayerScreen() const; + + void MouseAimTracing(const bool InbStart, AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const float InAffectRange, const EMouseResultType InResultType, bool InbPathVisible = true) const; + FHitResult GetMouseCursorHitResult(AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const EMouseResultType InResultType) const; + + UFUNCTION(BlueprintPure) + class UWidgetManagerComponent* GetWidgetManager(); + + UFUNCTION(BlueprintPure) + UUserWidget* GetCurrentCommonHUD(); + +protected: + virtual void BeginPlay() override; + +private: + UPROPERTY() + TObjectPtr WidgetManagerComp; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = true)) + TObjectPtr CommonHUD; + + UPROPERTY() + TObjectPtr Mouse; + + uint8 bInitializePossessed : 1; +}; diff --git a/Source/ProjectT/System/Core/GameModes/CorePlayerState.cpp b/Source/ProjectT/System/Core/GameModes/CorePlayerState.cpp new file mode 100644 index 0000000..e8b5c00 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CorePlayerState.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CorePlayerState.h" + diff --git a/Source/ProjectT/System/Core/GameModes/CorePlayerState.h b/Source/ProjectT/System/Core/GameModes/CorePlayerState.h new file mode 100644 index 0000000..a15d0ec --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/CorePlayerState.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerState.h" +#include "CorePlayerState.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ACorePlayerState : public APlayerState +{ + GENERATED_BODY() + +}; diff --git a/Source/ProjectT/System/Core/GameModes/WorldGameMode.cpp b/Source/ProjectT/System/Core/GameModes/WorldGameMode.cpp new file mode 100644 index 0000000..2b74100 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/WorldGameMode.cpp @@ -0,0 +1,358 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WorldGameMode.h" + + +#include "CorePlayerController.h" +#include "Kismet/GameplayStatics.h" +#include "GameFramework/PlayerStart.h" +#include "Kismet/DataTableFunctionLibrary.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Skill/NpcRAtk.h" +#include "ProjectT/System/Core/Characters/Skill/NpcGAtk.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/ProcessStateControl.h" +#include "ProjectT/System/Core/Managers/StageManager.h" +#include "ProjectT/System/Core/Managers/SequenceManager.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Managers/OptionManager.h" +#include "ProjectT/System/Core/Managers/SoundManager.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Managers/PooledActorManager.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/Core/Objects/LevelObject/ItemObject.h" +#include "ProjectT/System/Core/SaveGame/UserSaveGame.h" +#include "ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.h" + +AWorldGameMode::AWorldGameMode() : + SequenceManager(nullptr) +{ +} + +void AWorldGameMode::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); +} + +USequenceManager* AWorldGameMode::GetSequenceManager_Implementation() +{ + return SequenceManager; +} + +UPooledActorManager* AWorldGameMode::GetPooledActorManager_Implementation() +{ + return PooledActorManager; +} + +UQuestManager* AWorldGameMode::GetQuestManager_Implementation() +{ + return QuestManager; +} + +UCoreWidgetManager* AWorldGameMode::GetCoreWidgetManager_Implementation() +{ + return Super::GetCoreWidgetManager_Implementation(); +} + +void AWorldGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) +{ + Super::InitGame(MapName, Options, ErrorMessage); +} + +void AWorldGameMode::BeginPlay() +{ + Super::BeginPlay(); + InitializeManagers(); + InitializePlayerSpawnPoints(); +} + +void AWorldGameMode::BeginDestroy() +{ + Super::BeginDestroy(); +} + +void AWorldGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + UGameInstance* GI = GetGameInstance(); + NMT_CHECKF(GI); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GI); + NC->ReleaseNotificationCenter(); + + USoundManager* SoundMgr = IGlobalObjectProvider::Execute_GetSoundManager(GI); + SoundMgr->ReleaseManager(); + + UOptionManager* OptionMgr = IGlobalObjectProvider::Execute_GetOptionManager(GI); + OptionMgr->ReleaseManager(); + + UStageManager* StageMgr = IGlobalObjectProvider::Execute_GetStageManager(GI); + StageMgr->ReleaseManager(); + + UCoreCheatManager* CheatMgr = IGlobalObjectProvider::Execute_GetCoreCheatManager(GI); + CheatMgr->ReleaseManager(); + + SequenceManager->ReleaseManager(); + SequenceManager = nullptr; + + QuestManager->ReleaseManager(); + QuestManager = nullptr; + + PooledActorManager->ReleaseManager(); + PooledActorManager = nullptr; + + GetWorld()->GetTimerManager().ClearAllTimersForObject(this); +} + +void AWorldGameMode::InitializeManagers() +{ + Super::InitializeManagers(); + + UWorld* World = GetWorld(); + NMT_CHECKF(World); + + if (!SequenceManager) + { + SequenceManager = NewObject(this); + SequenceManager->InitializeSequenceManager(World); + NMT_CHECKF(SequenceManager); + } + + if (!PooledActorManager) + { + PooledActorManager = NewObject(this); + NMT_CHECKF(PooledActorManager); + } + + if(!QuestManager) + { + QuestManager = NewObject(this); + QuestManager->InitializeManager(this); + NMT_CHECKF(QuestManager); + } +} + +void AWorldGameMode::InitializeNotification() +{ + NOT_IMPLEMENTED() +} + +void AWorldGameMode::InitializePlayerSpawnPoints() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + + UGameplayStatics::GetAllActorsOfClass(World, APlayerStart::StaticClass(), PlayerSpawnPoints); + if(PlayerSpawnPoints.IsEmpty()) + { + AActor* Temp = World->SpawnActor(AActor::StaticClass(), FVector(), FRotator()); + PlayerSpawnPoints.Push(Temp); + NMT_MSG_ENSURE(0, "Player Spawn Points is Empty"); + } +} + +void AWorldGameMode::InitializePlayer() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + UGlobalUtilsLibrary::ShuffleArray(PlayerSpawnPoints); + + UUserSaveGame* USG = nullptr; + UUserSaveGame::LoadUserSaveGame(USG); + + FString SCD; + USG->GetSelectedCharacterData(SCD); + if(SCD.IsEmpty()) + { + TArray UCD; + USG->GetUnlockCharacterData(UCD); + SCD = UCD[0].UnlockCharacterRowName; + USG->SetCurrentSelectedCharacterData(SCD); + } + + FString FoundBlueprintPath; + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GetGameInstance()); + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::PlayerCharacter); + TMap RowMap = FoundTable->GetRowMap(); + for(TTuple Pair : RowMap) + { + if(Pair.Key.IsEqual(*SCD)) + { + FPlayerCharacter* FoundData = reinterpret_cast(Pair.Value); + FoundBlueprintPath = FoundData->sCharBlueprintPath; + break; + } + } + + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(FoundBlueprintPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + + FVector Location = PlayerSpawnPoints[0]->GetActorLocation(); + FRotator Rotator = PlayerSpawnPoints[0]->GetActorRotation(); + AActor* SpawnActor = World->SpawnActor(LoadedClass, &Location, &Rotator); + + ACorePlayerCharacter* Player = Cast(SpawnActor); + NMT_MSG_CHECKF(Player, "%s: Character Class Not Found PlayerCharacter.csv -> RowName[%s] ", *LoadedClass->GetName(), *SCD) + + ACorePlayerController* CPC = UGlobalUtilsLibrary::GetLocalPlayerControllerChecked(Player); + CPC->Possess(Player); + + TSubclassOf LocAtkSkillClass; + TSubclassOf LocSkillClass; + Player->GetSkillClass(LocAtkSkillClass, LocSkillClass); + + const int32 LocAtkPoolSize = TSubclassOf(LocAtkSkillClass).GetDefaultObject()->GetSkillPoolSize(); + const int32 LocSkillPoolSize = TSubclassOf(LocSkillClass).GetDefaultObject()->GetSkillPoolSize(); + + PooledActorManager->CreatePool(LocAtkSkillClass, LocAtkPoolSize); + PooledActorManager->CreatePool(LocSkillClass, LocSkillPoolSize); +} + +void AWorldGameMode::InitializeUI() +{ + NOT_IMPLEMENTED(); +} + +void AWorldGameMode::InitializeItemObject() +{ + UDataTable* FoundTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + TArray LocItemArray; + TArray LocItemSkillIds; + UGameplayStatics::GetAllActorsOfClass(GetWorld(), AItemObject::StaticClass(),LocItemArray); + for(AActor* LocItem : LocItemArray) + { + AItemObject* LocCastItem = Cast(LocItem); + if(LocCastItem) + { + if(LocCastItem->GetItemData().iItemSkillId != 0) + LocItemSkillIds.AddUnique(LocCastItem->GetItemData().iItemSkillId); + } + } + for(int LocSkillId : LocItemSkillIds) + { + FString LocSkillRow = FString::FromInt(LocSkillId); + FSkill* SkillDataRow = FoundTable->FindRow(*LocSkillRow, TEXT("Not Found FSkill")); + FString TempPath = SkillDataRow->sSkillBpPath; + if (!CHECK_FREE(TempPath)) + { + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(TempPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + + PooledActorManager->CreatePool(LoadedClass, 1); + } + } +} + +void AWorldGameMode::InitializeEnemyCharacters() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + UDataTable* SkillTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + NMT_CHECKF(SkillTable); + + UGameplayStatics::GetAllActorsOfClass(World, ACoreNpc::StaticClass(), NpcCharacters); + if(NpcCharacters.IsEmpty()) NMT_MSG_ENSURE(0, "Npc Character is Empty"); + + TMap> SKillMap; + FSkill* SkillData = nullptr; + for(AActor* Enemy : NpcCharacters) + { + ACoreNpc* CN = CastChecked(Enemy); + uint8* FoundData = SkillTable->FindRowUnchecked(FROM_INT(CN->GetCurrentNpcStatus().iNpcAttackId)); + if(!FoundData) continue; + + SkillData = reinterpret_cast(FoundData); + NMT_CHECKF(SkillData); + + TPair& SkillCount = SKillMap.FindOrAdd(SkillData->sSkillName); + SkillCount.Key = SkillData->sSkillBpPath; + SkillCount.Value += 1; + } + + for(TTuple> Item : SKillMap) + { + FString SkilClassPath = Item.Value.Key; + if(!CHECK_FREE(SkilClassPath)) + { + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(SkilClassPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + + TSubclassOf NpcAtkSkillClass = TSubclassOf(LoadedClass); + PooledActorManager->CreatePool(NpcAtkSkillClass, Item.Value.Value * 1); + } + } +} + +void AWorldGameMode::PauseGame_Implementation() +{ + UWorld* World = GetWorld(); + NMT_CHECKF(World); + + if(World->IsPaused()) + return; + + UGameplayStatics::SetGamePaused(World, true); +} + +void AWorldGameMode::UnPauseGame_Implementation() +{ + UWorld* World = GetWorld(); + NMT_CHECKF(World); + + if(!World->IsPaused()) + return; + + UGameplayStatics::SetGamePaused(World, false); +} + +bool AWorldGameMode::ChangedProcessEvent(const EProcessState ProcessState) +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + switch (ProcessState) + { + case EProcessState::Ready: + { + InitializeNotification(); + break; + } + case EProcessState::Intro: break; + case EProcessState::PreGame: break; + case EProcessState::GamePlaying: break; + case EProcessState::Victory: break; + case EProcessState::Defeat: break; + case EProcessState::Reward: + { + break; + } + case EProcessState::Finish: break; + case EProcessState::None: default: NMT_CHECKF(0); + } + return true; +} + +void AWorldGameMode::GetPlayerSpawnPoints(TArray& OutSpawnPoints) const +{ + OutSpawnPoints = PlayerSpawnPoints; +} + +ACorePlayerCharacter* AWorldGameMode::GetPlayerCharacter() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + + ACorePlayerCharacter* Ret = UGlobalUtilsLibrary::GetLocalPlayerUnChecked(World); + if(!Ret) + { + AActor* FoundActor = UGameplayStatics::GetActorOfClass(World, ACorePlayerCharacter::StaticClass()); + NMT_CHECKF(FoundActor); + Ret = CastChecked(FoundActor); + } + + return Ret; +} diff --git a/Source/ProjectT/System/Core/GameModes/WorldGameMode.h b/Source/ProjectT/System/Core/GameModes/WorldGameMode.h new file mode 100644 index 0000000..f85b5d6 --- /dev/null +++ b/Source/ProjectT/System/Core/GameModes/WorldGameMode.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreGameMode.h" +#include "ProjectT/System/Core/GameModes/CoreGameMode.h" +#include "ProjectT/System/Core/Interfaces/WorldObjectProvider.h" +#include "WorldGameMode.generated.h" + +enum class EProcessState : uint8; + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnChangeProcess, EProcessState, ProcessState); + +UCLASS() +class PROJECTT_API AWorldGameMode : public ACoreGameMode, public IWorldObjectProvider +{ + GENERATED_BODY() + +public: + AWorldGameMode(); + virtual void Tick(float DeltaSeconds) override; + virtual USequenceManager* GetSequenceManager_Implementation() override; + virtual UPooledActorManager* GetPooledActorManager_Implementation() override; + virtual UQuestManager* GetQuestManager_Implementation() override; + virtual UCoreWidgetManager* GetCoreWidgetManager_Implementation() override; + virtual bool ChangedProcessEvent(const EProcessState ProcessState); + void GetPlayerSpawnPoints(TArray& OutSpawnPoints) const; + class ACorePlayerCharacter* GetPlayerCharacter(); + void GetNpcCharacters(TArray& OutNpcCharacters) const { OutNpcCharacters = NpcCharacters; } + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent) + void PauseGame(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent) + void UnPauseGame(); + +protected: + virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override; + virtual void BeginPlay() override; + virtual void BeginDestroy() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void InitializeManagers() override; + virtual void InitializeNotification(); + virtual void InitializeEnemyCharacters(); + virtual void InitializePlayer(); + virtual void InitializeUI() override; + + void InitializeItemObject(); + void InitializePlayerSpawnPoints(); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) + TObjectPtr SequenceManager; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) + TObjectPtr PooledActorManager; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) + TObjectPtr QuestManager; + + UPROPERTY() + TArray PlayerSpawnPoints; + + UPROPERTY() + TArray NpcCharacters; +}; diff --git a/Source/ProjectT/System/Core/Input/KeyTrigger.cpp b/Source/ProjectT/System/Core/Input/KeyTrigger.cpp new file mode 100644 index 0000000..6f703ff --- /dev/null +++ b/Source/ProjectT/System/Core/Input/KeyTrigger.cpp @@ -0,0 +1,15 @@ +#include "ProjectT/System/Core/Input/KeyTrigger.h" +#include "EnhancedPlayerInput.h" + +ETriggerState UKeyTrigger::UpdateState_Implementation(const UEnhancedPlayerInput* PlayerInput, + FInputActionValue ModifiedValue, float DeltaTime) +{ + ETriggerState ParentState = Super::UpdateState_Implementation(PlayerInput, ModifiedValue, DeltaTime); + + for (const FKey& Key : AdditionalKeys) + { + if (PlayerInput->IsPressed(Key) == false) return ETriggerState::Ongoing; + } + + return ParentState; +} diff --git a/Source/ProjectT/System/Core/Input/KeyTrigger.h b/Source/ProjectT/System/Core/Input/KeyTrigger.h new file mode 100644 index 0000000..2b726f9 --- /dev/null +++ b/Source/ProjectT/System/Core/Input/KeyTrigger.h @@ -0,0 +1,21 @@ +#pragma once + +#include "CoreMinimal.h" +#include "InputTriggers.h" +#include "KeyTrigger.generated.h" + +UCLASS() +class PROJECTT_API UKeyTrigger : public UInputTrigger +{ + GENERATED_BODY() + + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = InputTrigger) + TArray AdditionalKeys; + +protected: + virtual ETriggerType GetTriggerType_Implementation() const override { return ETriggerType::Implicit;} + virtual ETriggerState UpdateState_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue ModifiedValue, float DeltaTime) override; + +}; diff --git a/Source/ProjectT/System/Core/Interfaces/AISettings.cpp b/Source/ProjectT/System/Core/Interfaces/AISettings.cpp new file mode 100644 index 0000000..8bea077 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/AISettings.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AISettings.h" diff --git a/Source/ProjectT/System/Core/Interfaces/AISettings.h b/Source/ProjectT/System/Core/Interfaces/AISettings.h new file mode 100644 index 0000000..b699aac --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/AISettings.h @@ -0,0 +1,92 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Perception/AIPerceptionTypes.h" +#include "UObject/Interface.h" +#include "AISettings.generated.h" + +USTRUCT(BlueprintType) +struct FSightInfo +{ + GENERATED_BODY() + + FSightInfo() : + SightRange(300.f), + LoseSightRange(450.f), + SightAngle(90.f), + SightMaxAge(3.f) + {} + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Sight") + float SightRange; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Sight") + float LoseSightRange; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Sight") + float SightAngle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Sight") + float SightMaxAge; +}; + +USTRUCT(BlueprintType) +struct FHearingInfo +{ + GENERATED_BODY() + + FHearingInfo() : + HearingRange(300.f), + HearingMaxAge(3.f) + {} + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Hearing") + float HearingRange; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Perception|Hearing") + float HearingMaxAge; +}; + + +UINTERFACE(MinimalAPI) +class UAISettings : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IAISettings +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + bool GetUseSight(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + bool GetUseHearing(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + FSightInfo GetSightInfo(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + FHearingInfo GetHearingInfo(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting") + class UBehaviorTree* GetBehaviorTree(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting") + class UBlackboardData* GetBlackboardData(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + void DetectTargetBySight(AActor* InTarget, FAIStimulus InStimulus); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting|Perception") + void ForgetTarget(AActor* InTarget); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "AISetting") + FTransform GetViewTransform(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/ContentType.cpp b/Source/ProjectT/System/Core/Interfaces/ContentType.cpp new file mode 100644 index 0000000..a5bc59a --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ContentType.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ContentType.h" + + +// Add default functionality here for any IContentType functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/ContentType.h b/Source/ProjectT/System/Core/Interfaces/ContentType.h new file mode 100644 index 0000000..77e7570 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ContentType.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "ContentType.generated.h" + +#define CONTENT_TYPE_NUMBER(Number) \ +public:\ + virtual FString GetContentTypeNumber_Implementation() \ + { \ + return FROM_INT(StaticCast(Number)); \ + } \ + virtual EContentType GetContentType_Implementation() \ + { \ + return StaticCast(Number); \ + } \ +private: + +enum class EContentType : uint8; + +UINTERFACE() +class UContentType : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IContentType +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "ContentType")) + FString GetContentTypeNumber(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "ContentType")) + EContentType GetContentType(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.cpp b/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.cpp new file mode 100644 index 0000000..07f14ca --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreCameraControl.h" + + +// Add default functionality here for any ICoreCameraControl functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.h b/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.h new file mode 100644 index 0000000..5a22517 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/CoreCameraControl.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "CoreCameraControl.generated.h" + +UENUM(BlueprintType) +enum class EFadeType : uint8 +{ + FadeIn = 0, + FadeOut = 1 +}; + +UENUM(BlueprintType) +enum class EZoomType : uint8 +{ + ZoomIn = 0, + ZoomOut = 1 +}; + +DECLARE_DELEGATE(FOnStaticFinishCameraFade) + +UINTERFACE(MinimalAPI, Blueprintable) +class UCoreCameraControl : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API ICoreCameraControl +{ + GENERATED_BODY() + +public: + virtual void StartFade(EFadeType FadeType, FOnStaticFinishCameraFade FinishEvent, float Duration, float StartDelay = 1.f) = 0; + virtual void StartZoom(EZoomType ZoomType, float ZoomFactor, float Duration) = 0; +}; diff --git a/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.cpp b/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.cpp new file mode 100644 index 0000000..72c23b5 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreObjectProvider.h" + + +// Add default functionality here for any ICoreObjectProvider functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.h b/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.h new file mode 100644 index 0000000..0f508ba --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/CoreObjectProvider.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "CoreObjectProvider.generated.h" + +UINTERFACE() +class UCoreObjectProvider : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API ICoreObjectProvider +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "CoreObjectProvider")) + class UCoreWidgetManager* GetCoreWidgetManager(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/Damageable.cpp b/Source/ProjectT/System/Core/Interfaces/Damageable.cpp new file mode 100644 index 0000000..0569a1e --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/Damageable.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Damageable.h" + + +// Add default functionality here for any ICharacterInteractionControl functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/Damageable.h b/Source/ProjectT/System/Core/Interfaces/Damageable.h new file mode 100644 index 0000000..c75eb56 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/Damageable.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h" +#include "ProjectT/Data/Gen/GenerateStructEffect.h" +#include "ProjectT/Data/Gen/GenerateStructSkill.h" +#include "UObject/Interface.h" +#include "Damageable.generated.h" + + +// This class does not need to be modified. +UINTERFACE() +class UDamageable : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API IDamageable +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Damageable")) + void ApplyDamageEvent(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Damageable")) + void ApplyRecoveryEvent(const TArray& InReleaseEffects); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Damageable")) + void GetCurrentEffectTypes(TArray& OutEffectSubTypes); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.cpp b/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.cpp new file mode 100644 index 0000000..aecc599 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "DebugHitCollision.h" + + +// Add default functionality here for any IDebugHitCollision functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.h b/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.h new file mode 100644 index 0000000..21e2b46 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/DebugHitCollision.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "DebugHitCollision.generated.h" + +UINTERFACE() +class UDebugHitCollision : public UInterface +{ + GENERATED_BODY() +}; + +/** + * NOTE: 인터페이스로 등록된 오브젝트는 CoreCheatManager에 의해서 Collision을 시각화 시킬수 있음 + */ +class PROJECTT_API IDebugHitCollision +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "DebugHitCollision") + void ShowVisual(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "DebugHitCollision") + void HideVisual(); + +}; diff --git a/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.cpp b/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.cpp new file mode 100644 index 0000000..ca424e3 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "GlobalObjectProvider.h" diff --git a/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.h b/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.h new file mode 100644 index 0000000..eb8975f --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/GlobalObjectProvider.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "GlobalObjectProvider.generated.h" + +UINTERFACE(MinimalAPI, Blueprintable) +class UGlobalObjectProvider : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IGlobalObjectProvider +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "DataDam")) + class UDataDam* GetDataDam(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "LevelManager")) + class UStageManager* GetStageManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "OptionManager")) + class UOptionManager* GetOptionManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "SoundManager")) + class USoundManager* GetSoundManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "UCheatManager")) + class UCoreCheatManager* GetCoreCheatManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "UNotificationCenter")) + class UNotificationCenter* GetNotificationCenter(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.cpp b/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.cpp new file mode 100644 index 0000000..3f9df51 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ItemObjectControl.h" + +// Add default functionality here for any IItemObjectControl functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.h b/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.h new file mode 100644 index 0000000..8125fe4 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ItemObjectControl.h @@ -0,0 +1,30 @@ + + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "ItemObjectControl.generated.h" + + +UINTERFACE(MinimalAPI, Blueprintable) +class UItemObjectControl : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API IItemObjectControl +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable,BlueprintNativeEvent) + FName GetItemRowName(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent) + void ObtainItem(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/LoadableObject.cpp b/Source/ProjectT/System/Core/Interfaces/LoadableObject.cpp new file mode 100644 index 0000000..d9df06e --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/LoadableObject.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LoadableObject.h" + + +// Add default functionality here for any ILoadable functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/LoadableObject.h b/Source/ProjectT/System/Core/Interfaces/LoadableObject.h new file mode 100644 index 0000000..94c853f --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/LoadableObject.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "LoadableObject.generated.h" + +UINTERFACE(MinimalAPI, Blueprintable) +class ULoadableObject : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API ILoadableObject +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "LoadableObject") + bool HasFinishedLoading(); + + virtual bool HasFinishedLoading() const + { + return false; + } +}; diff --git a/Source/ProjectT/System/Core/Interfaces/MouseInteraction.cpp b/Source/ProjectT/System/Core/Interfaces/MouseInteraction.cpp new file mode 100644 index 0000000..733acf7 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/MouseInteraction.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MouseInteraction.h" + + +// Add default functionality here for any IMouseInteraction functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/MouseInteraction.h b/Source/ProjectT/System/Core/Interfaces/MouseInteraction.h new file mode 100644 index 0000000..f4d8e5c --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/MouseInteraction.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "MouseInteraction.generated.h" + +UINTERFACE() +class UMouseInteraction : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IMouseInteraction +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Damageable")) + void RefreshCursorHitResult(FHitResult InHitResult); + +}; diff --git a/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.cpp b/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.cpp new file mode 100644 index 0000000..808604c --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ObjectInteractionControl.h" + + +// Add default functionality here for any IObjectInteractionControl functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.h b/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.h new file mode 100644 index 0000000..fb8f7e3 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ObjectInteractionControl.h @@ -0,0 +1,62 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "ObjectInteractionControl.generated.h" + +UENUM(BlueprintType) +enum class EInteractionObjectType: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Item UMETA(DisplayName = "Item"), + LevelObject UMETA(DisplayName = "LevelObject"), + ObjectiveCharacter UMETA(DIsplayeName = "ObjectiveCharacter") +}; + +UENUM(BlueprintType) +enum class EInteractionResultType: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Fail UMETA(DisplayName = "Fail"), + SuccessPre UMETA(DisplayName = "SuccessPre"), + SuccessUpdate UMETA(DisplayName = "SuccessUpdate"), + SuccessComplete UMETA(DisplayName = "SuccessComplete") +}; + +USTRUCT(Blueprintable) +struct FInteractionData +{ + GENERATED_BODY() + UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = "Interaction") + TArray RowNames; +}; + +UINTERFACE() +class UObjectInteractionControl : public UInterface +{ + GENERATED_BODY() +}; + +DECLARE_DELEGATE_OneParam(FOnInteractionSuccess, EInteractionResultType); +class PROJECTT_API IObjectInteractionControl +{ + GENERATED_BODY() + +public: + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback = nullptr) = 0; + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "CharacterInteraction")) + void SuccessPreAction(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "CharacterInteraction")) + void SuccessUpdateAction(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "CharacterInteraction")) + void SuccessCompleteAction(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "ObjectInteraction")) + EInteractionObjectType GetInteractionObjectType(); + +}; diff --git a/Source/ProjectT/System/Core/Interfaces/PoolableActor.cpp b/Source/ProjectT/System/Core/Interfaces/PoolableActor.cpp new file mode 100644 index 0000000..a674b88 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/PoolableActor.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PoolableActor.h" + + +// Add default functionality here for any IPooledActor functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/PoolableActor.h b/Source/ProjectT/System/Core/Interfaces/PoolableActor.h new file mode 100644 index 0000000..ff6f0c7 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/PoolableActor.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "PoolableActor.generated.h" + +UINTERFACE() +class UPoolableActor : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IPoolableActor +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "PoolableActor")) + void Enable(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "PoolableActor")) + void Disable(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "PoolableActor")) + void Pushed(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "PoolableActor")) + void Obtained(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.cpp b/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.cpp new file mode 100644 index 0000000..3a2b453 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ProcessStateControl.h" + + +// Add default functionality here for any IProcessStateControl functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.h b/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.h new file mode 100644 index 0000000..396751c --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/ProcessStateControl.h @@ -0,0 +1,44 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "ProcessStateControl.generated.h" + +UENUM(Blueprintable) +enum class EProcessState : uint8 +{ + None = 0 UMETA(Displayname = "None"), + Ready UMETA(Displayname = "Ready"), + Intro UMETA(Displayname = "Intro"), + PreGame UMETA(Displayname = "PreGame"), + GamePlaying UMETA(Displayname = "GamePlaying"), + Victory UMETA(Displayname = "Victory"), + Defeat UMETA(Displayname = "Defeat"), + Reward UMETA(Displyname = "Reward"), + Finish UMETA(Displyname = "Finish"), +}; + +// This class does not need to be modified. +UINTERFACE(MinimalAPI, Blueprintable) +class UProcessStateControl : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API IProcessStateControl +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "ProcessState")) + void ChangeProcessState(EProcessState NewState); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "ProcessState")) + EProcessState GetProcessState(); + +}; diff --git a/Source/ProjectT/System/Core/Interfaces/Visualizable.cpp b/Source/ProjectT/System/Core/Interfaces/Visualizable.cpp new file mode 100644 index 0000000..df5e1f3 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/Visualizable.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Visualizable.h" + + +// Add default functionality here for any IVisualizable functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/Visualizable.h b/Source/ProjectT/System/Core/Interfaces/Visualizable.h new file mode 100644 index 0000000..f9a76df --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/Visualizable.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "Visualizable.generated.h" + +UINTERFACE() +class UVisualizable : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API IVisualizable +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Visualizable") + void ShowVisual(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Visualizable") + void HideVisual(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.cpp b/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.cpp new file mode 100644 index 0000000..9804db9 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WidgetInputHandler.h" + +// Add default functionality here for any IWidgetInputHandler functions that are not pure virtual. diff --git a/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.h b/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.h new file mode 100644 index 0000000..6000c82 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/WidgetInputHandler.h @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "WidgetInputHandler.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI, Blueprintable) +class UWidgetInputHandler : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API IWidgetInputHandler +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnInit(int32 ContainerIndex); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnNavigate(const FVector2D& Direction); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnHovered(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnUnhovered(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnClicked(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnPressed(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnReleased(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "Widget Input")) + void OnBack(); +}; diff --git a/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.cpp b/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.cpp new file mode 100644 index 0000000..8a0f2c9 --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "WorldObjectProvider.h" + diff --git a/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.h b/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.h new file mode 100644 index 0000000..556ed3d --- /dev/null +++ b/Source/ProjectT/System/Core/Interfaces/WorldObjectProvider.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "WorldObjectProvider.generated.h" + +UINTERFACE(MinimalAPI, Blueprintable) +class UWorldObjectProvider : public UInterface +{ + GENERATED_BODY() +}; + +class PROJECTT_API IWorldObjectProvider +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "WorldObjectProvider")) + class USequenceManager* GetSequenceManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "WorldObjectProvider")) + class UPooledActorManager* GetPooledActorManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "WorldObjectProvider")) + class UQuestManager* GetQuestManager(); +}; diff --git a/Source/ProjectT/System/Core/Managers/CoreCheatManager.cpp b/Source/ProjectT/System/Core/Managers/CoreCheatManager.cpp new file mode 100644 index 0000000..7db915c --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/CoreCheatManager.cpp @@ -0,0 +1,441 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreCheatManager.h" + +#include "DrawDebugHelpers.h" +#include "QuestManager.h" +#include "Kismet/GameplayStatics.h" +#include "Blueprint/UserWidget.h" +#include "Blueprint/WidgetTree.h" +#include "Components/CapsuleComponent.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Components/CoreCameraComponent.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/GameModes/CoreGameState.h" +#include "ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h" +#include "GameFramework/SpectatorPawn.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h" +#include "ProjectT/System/Core/Objects/LevelObject/CeilObject.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + + +UCoreCheatManager::UCoreCheatManager() : + OuterObject(nullptr), + DebugWidgetVisibility(ESlateVisibility::Visible), + bDebugToggleCheat(0), + bInitialized(0) +{ +} + +void UCoreCheatManager::BroadCastDebugStatus() +{ + UScriptStruct* DebugStatusStruct = DebugStatus.StaticStruct(); + for(TFieldIterator It = DebugStatusStruct; It; ++It) + { + FProperty* Property = *It; + NMT_CHECKF(Property); + + const FName PropName = *Property->GetName(); + bool State = UGlobalUtilsLibrary::GetBoolFieldInStruct(&DebugStatus, PropName); + if(State) + { + uint16 ParamSize = CheatFunctionMap[PropName]->ParmsSize; + void* Params = FMemory_Alloca(ParamSize); + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(PropName, State); + } + } +} + +void UCoreCheatManager::DebugRestartGame() const +{ + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + AGameModeBase* GM = UGameplayStatics::GetGameMode(OuterObject); + NMT_CHECKF(GM); + + AWorldGameMode* CGM = Cast(GM); + NMT_CHECKF(CGM); + + CGM->UnPauseGame(); + + FString CLN = UGameplayStatics::GetCurrentLevelName(OuterObject); + UGameplayStatics::OpenLevel(OuterObject, FName(CLN)); +} + +void UCoreCheatManager::DebugDrawFrustum() const +{ + UWorld* World = OuterObject->GetWorld(); + float DeltaTime = UGameplayStatics::GetWorldDeltaSeconds(OuterObject); + ACorePlayerCharacter* Player = UGlobalUtilsLibrary::GetLocalPlayerUnChecked(OuterObject); + if(!NMT_ENSURE(Player)) return; + + FMinimalViewInfo ViewInfo; + TObjectPtr LocCoreCamera; + Player->GetCameraComponent(LocCoreCamera); + LocCoreCamera->GetCameraView(DeltaTime, ViewInfo); + + FColor Color = FColor::Magenta; + float LifeTime = 0.f; + float Thickness = 1.f; + float Near = 10.f; + float Far = 1000.f; + + const FVector Forward = ViewInfo.Rotation.Vector(); + const FVector Right = FRotationMatrix(ViewInfo.Rotation).GetScaledAxis(EAxis::Y); + const FVector Up = FRotationMatrix(ViewInfo.Rotation).GetScaledAxis(EAxis::Z); + + const float HalfFOV = FMath::DegreesToRadians(ViewInfo.FOV * 0.5f); + const float HNear = Near * FMath::Tan(HalfFOV); + const float WNear = HNear * ViewInfo.AspectRatio; + const float HFar = Far * FMath::Tan(HalfFOV); + const float WFar = HFar * ViewInfo.AspectRatio; + + const FVector CNear = ViewInfo.Location + Forward * Near; + const FVector CFar = ViewInfo.Location + Forward * Far; + + FVector NTL = CNear + Up * HNear - Right * WNear; + FVector NTR = CNear + Up * HNear + Right * WNear; + FVector NBL = CNear - Up * HNear - Right * WNear; + FVector NBR = CNear - Up * HNear + Right * WNear; + + FVector FTL = CFar + Up * HFar - Right * WFar; + FVector FTR = CFar + Up * HFar + Right * WFar; + FVector FBL = CFar - Up * HFar - Right * WFar; + FVector FBR = CFar - Up * HFar + Right * WFar; + + DrawDebugLine(World, NTL, NTR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NTR, NBR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NBR, NBL, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NBL, NTL, Color, false, LifeTime, 0, Thickness); + + DrawDebugLine(World, FTL, FTR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, FTR, FBR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, FBR, FBL, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, FBL, FTL, Color, false, LifeTime, 0, Thickness); + + DrawDebugLine(World, NTL, FTL, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NTR, FTR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NBR, FBR, Color, false, LifeTime, 0, Thickness); + DrawDebugLine(World, NBL, FBL, Color, false, LifeTime, 0, Thickness); +} + +void UCoreCheatManager::BindOnDebugSPGame(const FOnDebugSPGame& Callback) +{ + if(!OnDebugSPGame.IsBound()) OnDebugSPGame = Callback; +} + +void UCoreCheatManager::RefreshStatusEvent() +{ + UScriptStruct* DebugStatusStruct = DebugStatus.StaticStruct(); + for(TFieldIterator It = DebugStatusStruct; It; ++It) + { + FProperty* Property = *It; + NMT_CHECKF(Property); + + const FName PropName = *Property->GetName(); + bool FieldState = UGlobalUtilsLibrary::GetBoolFieldInStruct(&DebugStatus, PropName); + if(FieldState) + { + uint16 ParamSize = CheatFunctionMap[PropName]->ParmsSize; + void* Params = FMemory_Alloca(ParamSize); + ProcessEvent(CheatFunctionMap[PropName], Params); + ProcessEvent(CheatFunctionMap[PropName], Params); + } + } +} + +void UCoreCheatManager::DebugToggleCheat() +{ + if(!DebugWidget) + { + const UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(TEXT("/Script/UMGEditor.WidgetBlueprint'/Game/UI/Debug/WBP_DebugMainPanel.WBP_DebugMainPanel'")); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + UWorld* World = OuterObject->GetWorld(); + DebugWidget = CreateWidget(World, LoadedClass); + DebugWidget->AddToViewport(1); + DebugWidgetVisibility = DebugWidget->GetVisibility(); + } + else + { + if(!DebugWidget->IsInViewport()) DebugWidget->AddToViewport(1); + else if(DebugWidget->GetVisibility() != ESlateVisibility::Collapsed) DebugWidget->SetVisibility(ESlateVisibility::Collapsed); + else DebugWidget->SetVisibility(DebugWidgetVisibility); + } + bDebugToggleCheat = !bDebugToggleCheat; +} + +void UCoreCheatManager::PropagateStatusEvent(const bool State) +{ + UScriptStruct* DebugStatusStruct = DebugStatus.StaticStruct(); + for(TFieldIterator It = DebugStatusStruct; It; ++It) + { + FProperty* Property = *It; + NMT_CHECKF(Property); + + const FName PropName = *Property->GetName(); + bool FieldState = UGlobalUtilsLibrary::GetBoolFieldInStruct(&DebugStatus, PropName); + if(FieldState == State) + { + uint16 ParamSize = CheatFunctionMap[PropName]->ParmsSize; + void* Params = FMemory_Alloca(ParamSize); + ProcessEvent(CheatFunctionMap[PropName], Params); + } + } +} + +void UCoreCheatManager::DebugResetStatus() +{ + PropagateStatusEvent(true); + SaveDebugStatus = DebugStatus; +} + +void UCoreCheatManager::DebugTogglePlayerInvincibleHP() +{ + DebugStatus.bDebugPlayerInvincibleHP = !DebugStatus.bDebugPlayerInvincibleHP; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugPlayerInvincibleHP), DebugStatus.bDebugPlayerInvincibleHP); +} + +void UCoreCheatManager::DebugTogglePlayerDamage() +{ + DebugStatus.bDebugPlayerDamage = !DebugStatus.bDebugPlayerDamage; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugPlayerDamage), DebugStatus.bDebugPlayerDamage); +} + +void UCoreCheatManager::DebugTogglePlayerSpeed() +{ + DebugStatus.bDebugPlayerSpeed = !DebugStatus.bDebugPlayerSpeed; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugPlayerSpeed), DebugStatus.bDebugPlayerSpeed); +} + +void UCoreCheatManager::DebugTogglePlayerInvincibleStatusEffect() +{ + DebugStatus.bDebugPlayerInvincibleStatusEffect = !DebugStatus.bDebugPlayerInvincibleStatusEffect; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugPlayerInvincibleStatusEffect), DebugStatus.bDebugPlayerInvincibleStatusEffect); +} + +void UCoreCheatManager::DebugTogglePlayerInvincibleSkill() +{ + DebugStatus.bDebugPlayerInvincibleSkill = !DebugStatus.bDebugPlayerInvincibleSkill; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugPlayerInvincibleSkill), DebugStatus.bDebugPlayerInvincibleSkill); +} + +void UCoreCheatManager::DebugToggleEnemyInvincibleHP() +{ + DebugStatus.bDebugEnemyInvincibleHP = !DebugStatus.bDebugEnemyInvincibleHP; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugEnemyInvincibleHP), DebugStatus.bDebugEnemyInvincibleHP); +} + +void UCoreCheatManager::DebugToggleEnemyDamage() +{ + DebugStatus.bDebugEnemyDamage = !DebugStatus.bDebugEnemyDamage; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugEnemyDamage), DebugStatus.bDebugEnemyDamage); +} + +void UCoreCheatManager::DebugToggleEnemySpeed() +{ + DebugStatus.bDebugEnemySpeed = !DebugStatus.bDebugEnemySpeed; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugEnemySpeed), DebugStatus.bDebugEnemySpeed); +} + +void UCoreCheatManager::DebugToggleEnemyInvincibleStatusEffect() +{ + DebugStatus.bDebugEnemyInvincibleStatusEffect = !DebugStatus.bDebugEnemyInvincibleStatusEffect; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugEnemyInvincibleStatusEffect), DebugStatus.bDebugEnemyInvincibleStatusEffect); +} + +void UCoreCheatManager::DebugToggleEnemyInvincibleSkill() +{ + DebugStatus.bDebugEnemyInvincibleSkill = !DebugStatus.bDebugEnemyInvincibleSkill; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugEnemyInvincibleSkill), DebugStatus.bDebugEnemyInvincibleSkill); +} + +void UCoreCheatManager::DebugToggleVision() +{ + DebugStatus.bDebugVision = !DebugStatus.bDebugVision; + + UWorld* World = OuterObject->GetWorld(); + NMT_CHECKF(World); + + TArray Npcs; + UGameplayStatics::GetAllActorsOfClass(World, ACoreNpc::StaticClass(), Npcs); + for(AActor* Npc : Npcs) + { + if(ACoreNpc* CastToNpc = Cast(Npc)) CastToNpc->DebugToggleFrustum(); + } + + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugVision), DebugStatus.bDebugVision); +} + +void UCoreCheatManager::DebugToggleHitCollision() +{ + DebugStatus.bDebugHitCollision = !DebugStatus.bDebugHitCollision; + + UWorld* World = OuterObject->GetWorld(); + NMT_CHECKF(World); + + ACorePlayerCharacter* Player = UGlobalUtilsLibrary::GetLocalPlayerUnChecked(OuterObject); + NMT_CHECKF(Player); + + Player->GetCapsuleComponent()->SetHiddenInGame(!DebugStatus.bDebugHitCollision); + + TArray Npcs; + UGameplayStatics::GetAllActorsOfClass(World, ACoreNpc::StaticClass(), Npcs); + + for(AActor* Npc : Npcs) + { + if(ACoreNpc* CastToNpc = Cast(Npc)) + { + if(ASPNpcAgent* NpcAgent = Cast(CastToNpc)) + { + } + else CastToNpc->GetCapsuleComponent()->SetHiddenInGame(!DebugStatus.bDebugHitCollision); + } + } + + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugHitCollision), DebugStatus.bDebugHitCollision); +} + +void UCoreCheatManager::DebugToggleTimeStop() +{ + DebugStatus.bDebugTimeStop = !DebugStatus.bDebugTimeStop; + + UWorld* World = OuterObject->GetWorld(); + NMT_CHECKF(World); + + /** + * NOTE: 현재는 SinglePlay만 적용됨 + */ + AGameModeBase* GM = UGameplayStatics::GetGameMode(World); + if(ASPGameModeBase* SPGM = Cast(GM)) + { + SPGM->DebugGameTimePause(DebugStatus.bDebugTimeStop); + } + + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugTimeStop), DebugStatus.bDebugTimeStop); +} + +void UCoreCheatManager::DebugToggleSlomo() +{ + const FString SpeedCommand = !DebugStatus.bDebugSlomo ? TEXT("Slomo 10") : TEXT("Slomo 1"); + UKismetSystemLibrary::ExecuteConsoleCommand(OuterObject, SpeedCommand); + DebugStatus.bDebugSlomo = !DebugStatus.bDebugSlomo; + if(OnDebugSPGame.IsBound()) OnDebugSPGame.Execute(GET_MEMBER_NAME_CHECKED(FDebugStatus, bDebugSlomo), DebugStatus.bDebugSlomo); +} + +void UCoreCheatManager::DebugSpectatorPlay() +{ + UWorld* World = OuterObject->GetWorld(); + ACorePlayerCharacter* Player = UGlobalUtilsLibrary::GetLocalPlayerUnChecked(OuterObject); + if(!NMT_ENSURE(Player)) return; + TObjectPtr CoreCam; + Player->GetCameraComponent(CoreCam); + FTransform CamTransform = CoreCam->GetComponentTransform(); + TArray FindCeil; + UGameplayStatics::GetAllActorsOfClass(World, ACeilObject::StaticClass(), FindCeil); + + for(AActor* Ceil : FindCeil) + { + Ceil->SetActorHiddenInGame(true); + } + + DebugToggleTimeStop(); + if(AActor* FindSpectatorPawn = UGameplayStatics::GetActorOfClass(World, ASpectatorPawn::StaticClass())) + { + FindSpectatorPawn->SetActorTransform(CamTransform); + UGameplayStatics::GetPlayerController(World, 0)->SetViewTarget(FindSpectatorPawn); + UGameplayStatics::GetPlayerController(World, 0)->Possess(Cast(FindSpectatorPawn)); + return; + } + ASpectatorPawn* SpectatorPawn = World->SpawnActor(UCoreGameGeneralSettings::GetDebugSpectatorPawn(), CamTransform); + UGameplayStatics::GetPlayerController(World, 0)->SetViewTarget(SpectatorPawn); + UGameplayStatics::GetPlayerController(World, 0)->Possess(SpectatorPawn); +} + +void UCoreCheatManager::DebugAddMainQuest() +{ + UWorld* World = OuterObject->GetWorld(); + NMT_CHECKF(World); + + AGameModeBase* GM = UGameplayStatics::GetGameMode(World); + NMT_CHECKF(GM); + + UQuestManager* QM = IWorldObjectProvider::Execute_GetQuestManager(GM); + NMT_CHECKF(QM); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + QM->CheckObjectiveSatisfied(QM->MissionData.GetObjectiveSubType(), QM->MissionData.GetObjectiveIndex()); +} + +void UCoreCheatManager::DebugAddSubQuest(const int32 QuestIndex) +{ + UWorld* World = OuterObject->GetWorld(); + NMT_CHECKF(World); + + AGameModeBase* GM = UGameplayStatics::GetGameMode(World); + NMT_CHECKF(GM); + + UQuestManager* QM = IWorldObjectProvider::Execute_GetQuestManager(GM); + NMT_CHECKF(QM); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + if(QM->SubQuestList.IsValidIndex(QuestIndex)) + { + QM->CheckObjectiveSatisfied(QM->SubQuestList[QuestIndex].GetObjectiveSubType(), QM->SubQuestList[QuestIndex].GetObjectiveIndex()); + } +} + +FDebugStatus UCoreCheatManager::GetDebugStatus() +{ + return DebugStatus; +} + +void UCoreCheatManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); + + UScriptStruct* DebugStatusStruct = GetDebugStatus().StaticStruct(); + for(TFieldIterator It = DebugStatusStruct; It; ++It) + { + FProperty* Property = *It; + NMT_CHECKF(Property); + const FName PropName = *Property->GetName(); + CheatFunctionMap.FindOrAdd(PropName, nullptr); + } + + for(auto Iter = CheatFunctionMap.CreateIterator(); Iter; ++Iter) + { + for(TFieldIterator It = GetClass(); It; ++It) + { + UFunction* Func = *It; + const FString FuncName = Func->GetName(); + const FName KeyName = Iter->Key; + FString FormatKeyName = KeyName.ToString(); + + FString PrefixName = TEXT("bDebug"); + FormatKeyName.RemoveFromStart(PrefixName); + + if(FuncName.Contains(FormatKeyName)) CheatFunctionMap[KeyName] = Func; + } + } + + if(bInitialized) RefreshStatusEvent(); + else bInitialized = true; +} + +void UCoreCheatManager::ReleaseManager() +{ + OuterObject = nullptr; +} diff --git a/Source/ProjectT/System/Core/Managers/CoreCheatManager.h b/Source/ProjectT/System/Core/Managers/CoreCheatManager.h new file mode 100644 index 0000000..e6c2191 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/CoreCheatManager.h @@ -0,0 +1,197 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "CoreCheatManager.generated.h" + +/** + * NOTE: + * Member Field: Prefix("bDebug") + BodyName 의 규칙성으로 작성필요, 'bool' type의 변수로만 사용할 목적으로 정의됨 + * CheatManager::InitializeManager(): Member Field 네이밍 규칙에 영향이 있음 + * CheatManager::DebugResetStatus(): 'bool' type 규칙에 영향이 있음 + */ +USTRUCT(BlueprintType) +struct FDebugStatus +{ + GENERATED_BODY() + + FDebugStatus(): + bDebugPlayerInvincibleHP(0), + bDebugPlayerDamage(0), + bDebugPlayerSpeed(0), + bDebugPlayerInvincibleSkill(0), + bDebugPlayerInvincibleStatusEffect(0), + bDebugEnemyInvincibleHP(0), + bDebugEnemyDamage(0), + bDebugEnemySpeed(0), + bDebugEnemyInvincibleSkill(0), + bDebugEnemyInvincibleStatusEffect(0), + bDebugVision(0), + bDebugHitCollision(0), + bDebugTimeStop(0), + bDebugSlomo(0) + { + } + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugPlayerInvincibleHP : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugPlayerDamage : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugPlayerSpeed : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugPlayerInvincibleSkill : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugPlayerInvincibleStatusEffect : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugEnemyInvincibleHP : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugEnemyDamage : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugEnemySpeed : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugEnemyInvincibleSkill : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugEnemyInvincibleStatusEffect : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugVision : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugHitCollision : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugTimeStop : 1; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + uint8 bDebugSlomo : 1; +}; + +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnDebugSPGame, const FName&, StatusName, const bool, bState); + +UCLASS() +class PROJECTT_API UCoreCheatManager : public UObject +{ + GENERATED_BODY() + +public: + UCoreCheatManager(); + + UFUNCTION(BlueprintCallable) + void BroadCastDebugStatus(); + + UFUNCTION(BlueprintCallable) + void BindOnDebugSPGame(const FOnDebugSPGame& Callback); + void RefreshStatusEvent(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleCheat(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugResetStatus(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugRestartGame() const; + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugDrawFrustum() const; + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugTogglePlayerInvincibleHP(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugTogglePlayerDamage(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugTogglePlayerSpeed(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugTogglePlayerInvincibleStatusEffect(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugTogglePlayerInvincibleSkill(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleEnemyInvincibleHP(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleEnemyDamage(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleEnemySpeed(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleEnemyInvincibleStatusEffect(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleEnemyInvincibleSkill(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleVision(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleHitCollision(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleTimeStop(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugToggleSlomo(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugSpectatorPlay(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugAddMainQuest(); + + UFUNCTION(BlueprintCallable, Category = "Debug") + void DebugAddSubQuest(const int32 QuestIndex); + + UFUNCTION(BlueprintCallable, Category = "Debug") + FDebugStatus GetDebugStatus(); + + void InitializeManager(const UObject* WorldObjectContext); + void ReleaseManager(); + +private: + void PropagateStatusEvent(const bool State); + +private: + UPROPERTY() + TObjectPtr OuterObject; + + UPROPERTY() + FTimerHandle DebugTimerHandle; + + /** + * NOTE: FDebugStatus의 멤버 필드명에 따라 멤버함수를 적재함 + * DebugStatus의 따라 동작하는 함수 추가시 멤버함수명은 FDebugStatus의 BodyName을 따라가야함 + */ + UPROPERTY() + TMap CheatFunctionMap; + + UPROPERTY() + FOnDebugSPGame OnDebugSPGame; + + UPROPERTY() + TObjectPtr DebugWidget; + + ESlateVisibility DebugWidgetVisibility; + + uint8 bDebugToggleCheat : 1; + uint8 bInitialized : 1; + + FDebugStatus DebugStatus; + FDebugStatus SaveDebugStatus; +}; diff --git a/Source/ProjectT/System/Core/Managers/CoreWidgetManager.cpp b/Source/ProjectT/System/Core/Managers/CoreWidgetManager.cpp new file mode 100644 index 0000000..fdf549b --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/CoreWidgetManager.cpp @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreWidgetManager.h" + +UCoreWidgetManager::UCoreWidgetManager() : + OuterObject(nullptr) +{ +} + +void UCoreWidgetManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +void UCoreWidgetManager::ReleaseManager() +{ + OuterObject = nullptr; +} diff --git a/Source/ProjectT/System/Core/Managers/CoreWidgetManager.h b/Source/ProjectT/System/Core/Managers/CoreWidgetManager.h new file mode 100644 index 0000000..46a110f --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/CoreWidgetManager.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "CoreWidgetManager.generated.h" + + +UCLASS() +class PROJECTT_API UCoreWidgetManager : public UObject +{ + GENERATED_BODY() + +public: + UCoreWidgetManager(); + virtual void InitializeManager(const UObject* WorldObjectContext); + virtual void ReleaseManager(); + +protected: + UPROPERTY() + TObjectPtr OuterObject; +}; diff --git a/Source/ProjectT/System/Core/Managers/DataDam.cpp b/Source/ProjectT/System/Core/Managers/DataDam.cpp new file mode 100644 index 0000000..9225b09 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/DataDam.cpp @@ -0,0 +1,128 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "DataDam.h" + +#include "Engine/World.h" +#include "Engine/DataTable.h" + +#include "UObject/UObjectGlobals.h" +#include "Kismet/GameplayStatics.h" + +#include "Runtime/Core/Public/Misc/Paths.h" +#include "Runtime/Core/Public/Misc/FileHelper.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateStructStage.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h" + + +UDataDam::UDataDam() +{ + +} + +void UDataDam::Initialize() +{ + LoadDataTables(); +} + +void UDataDam::LoadDataTables() +{ + int8 Max = static_cast(*TEnumRange().end()); + NMT_CHECKF(Max >= 0); + + DataTableArray.Reserve(Max); + DataTableArray.SetNum(Max); + + for (EDataTableKey e : TEnumRange()) + { + FString DataTableName = JOIN_STRINGS(TEXT(""), TEXT("DT_"), EnumToString(e)); + UObject* LoadObject = UAssetUtilsLibrary::LoadDataTableByName(DataTableName); + UDataTable* LoadDataTable = CastChecked(LoadObject); + + uint8 Index = static_cast(e); + + if (DataTableArray.IsValidIndex(Index)) + DataTableArray[Index] = LoadDataTable; + } + UE_LOG(LogTemp, Display, TEXT("Data Table Loaded")); +} + +EDataTableKey UDataDam::GetDataTableKeyByName(const FName& InKeyName) +{ + UEnum* DataTableKeyEnum = StaticEnum(); + if (!NMT_ENSURE(DataTableKeyEnum)) return EDataTableKey(); + + for (EDataTableKey EnumValue : TEnumRange()) + { + const FString& ValueString = DataTableKeyEnum->GetNameStringByValue(StaticCast(EnumValue)); + + if (InKeyName == ValueString) + return EnumValue; + } + + return EDataTableKey(); +} + +const UDataTable* UDataDam::GetDataTableByEnum(EDataTableKey EArrayKey) +{ + uint8 Idx = static_cast(EArrayKey); + bool bValidArrayIdx = DataTableArray.IsValidIndex(Idx); + if (!NMT_ENSURE(bValidArrayIdx)) return nullptr; + return DataTableArray[Idx]; +} + +FName UDataDam::GetDataTableRowNameByIndex(EDataTableKey EArrayKey, const int32 Index) +{ + const UDataTable* FindTable = GetDataTableByEnum(EArrayKey); + if (!NMT_ENSURE(FindTable)) return FName(); + + TArray RowNames = FindTable->GetRowNames(); + bool bValidate = !RowNames.IsEmpty() && RowNames.IsValidIndex(Index); + if (!NMT_ENSURE(bValidate)) return FName(); + + return RowNames[Index]; +} + +int32 UDataDam::GetDataTableIndexByRowName(EDataTableKey EArrayKey, FName RowName) +{ + const UDataTable* FindTable = GetDataTableByEnum(EArrayKey); + if (!NMT_ENSURE(FindTable)) return 0; + + TArray RowNames = FindTable->GetRowNames(); + bool bValidate = !RowNames.IsEmpty() && RowNames.Find(RowName); + if(!NMT_ENSURE(bValidate)) return 0; + + return RowNames.Find(RowName); +} + +int32 UDataDam::GetDataTableNumberByRowName(EDataTableKey EArrayKey, FName RowName) +{ + const UDataTable* FindTable = GetDataTableByEnum(EArrayKey); + if (!NMT_ENSURE(FindTable)) return 0; + + TArray RowNames = FindTable->GetRowNames(); + bool bValidate = !RowNames.IsEmpty() && RowNames.Find(RowName); + if(!NMT_ENSURE(bValidate)) return 0; + + return RowNames.Find(RowName) + 1; +} + + +FStage UDataDam::GetLevelDataByCurrentLevelName(const UObject* InWorldContextObject) const +{ + FString CurrentLevelName = UGameplayStatics::GetCurrentLevelName(InWorldContextObject); + + TArray Stages = GetDataTableRowsChecked(); + + for (FStage* Stage : Stages) + { + if (Stage->sStageName == CurrentLevelName) + return *Stage; + } + return FStage(); +} diff --git a/Source/ProjectT/System/Core/Managers/DataDam.h b/Source/ProjectT/System/Core/Managers/DataDam.h new file mode 100644 index 0000000..c309a38 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/DataDam.h @@ -0,0 +1,103 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/ProjectT.h" +#include "DataDam.generated.h" + +enum class EDataTableKey : uint8; +enum class EGameLanguage : uint8; +struct FStage; + +UCLASS() +class PROJECTT_API UDataDam : public UObject +{ + GENERATED_BODY() + +public: + UDataDam(); + + void Initialize(); + void LoadDataTables(); + +public: + UFUNCTION(BlueprintPure, Category = "DataDam") + EDataTableKey GetDataTableKeyByName(const FName& InKeyName); + + UFUNCTION(BlueprintPure, Category = "DataDam") + const UDataTable* GetDataTableByEnum(EDataTableKey EArrayKey); + + UFUNCTION(BlueprintPure, Category = "DataDam") + FName GetDataTableRowNameByIndex(EDataTableKey EArrayKey, const int32 Index); + + UFUNCTION(BlueprintPure, Category = "DataDam") + int32 GetDataTableIndexByRowName(EDataTableKey EArrayKey, FName RowName); + + UFUNCTION(BlueprintPure, Category = "DataDam") + int32 GetDataTableNumberByRowName(EDataTableKey EArrayKey, FName RowName); + + UFUNCTION(BlueprintPure, meta = (Category = "DataDam")) + FStage GetLevelDataByCurrentLevelName(const UObject* InWorldContextObject) const; + + template + StructType* GetDataTableRowChecked(const FName& RowName) const + { + int32 Index = DataTableArray.IndexOfByPredicate([&](const UDataTable* Item) + { + return Item->RowStruct == StructType::StaticStruct(); + }); + bool IsValidIndex = Index >= 0 && Index < DataTableArray.Num(); + NMT_CHECKF(IsValidIndex); + StructType* FoundRow = DataTableArray[Index]->FindRow(RowName, TEXT("Not Found")); + + NMT_MSG_CHECKF(FoundRow, "%s have problem", *RowName.ToString()); + return FoundRow; + } + template + StructType* GetDataTableRowUnChecked(const FName& RowName) const + { + int32 Index = DataTableArray.IndexOfByPredicate([&](const UDataTable* Item) + { + return Item->RowStruct == StructType::StaticStruct(); + }); + if(!NMT_ENSURE(Index >= 0 && Index < DataTableArray.Num())) return nullptr; + + return DataTableArray[Index]->FindRow(RowName, TEXT("Not Found")); + } + template + TArray GetDataTableRowsChecked() const + { + TArray Ret; + int32 Index = DataTableArray.IndexOfByPredicate([&](const UDataTable* Item) + { + bool IsValidItem = IsValid(Item); + NMT_CHECKF(IsValidItem); + return Item->RowStruct == StructType::StaticStruct(); + }); + bool IsValidIndex = Index >= 0 && Index < DataTableArray.Num(); + NMT_CHECKF(IsValidIndex); + + if(DataTableArray.IsValidIndex(Index)) + DataTableArray[Index]->GetAllRows(StructType::StaticStruct()->GetName(), Ret); + + return Ret; + } + template + TArray GetDataTableRowNamesChecked() const + { + int32 Index = DataTableArray.IndexOfByPredicate([&](const UDataTable* Item) + { + return Item->RowStruct == StructType::StaticStruct(); + }); + bool IsValidIndex = Index >= 0 && Index < DataTableArray.Num(); + NMT_CHECKF(IsValidIndex); + + return DataTableArray[Index]->GetRowNames(); + } + +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "DataDam", meta = (AllowPrivateAccess = "true")) + TArray DataTableArray; + +}; diff --git a/Source/ProjectT/System/Core/Managers/LoadingManager.cpp b/Source/ProjectT/System/Core/Managers/LoadingManager.cpp new file mode 100644 index 0000000..b76ef89 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/LoadingManager.cpp @@ -0,0 +1,328 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LoadingManager.h" + +#include "AssetCompilingManager.h" +#include "ShaderCompiler.h" +#include "Widgets/SCompoundWidget.h" +#include "Blueprint/UserWidget.h" +#include "MoviePlayer.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/LoadableObject.h" +#include "ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.h" +#include "Widgets/Images/SThrobber.h" + +enum class ELoadingScenario : uint8 +{ + Ignore = 0, + Process +}; + +TMap LoadingScenarioMap = +{ + {EStage::None, ELoadingScenario::Ignore}, + {EStage::L_Entry, ELoadingScenario::Process}, + {EStage::L_Lobby, ELoadingScenario::Ignore}, + {EStage::L_Intro, ELoadingScenario::Ignore}, +}; + +class SLoadingScreenSimple : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SLoadingScreenSimple) {} + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs) + { + ChildSlot + [ + SNew(SVerticalBox) + +SVerticalBox::Slot() + .VAlign(VAlign_Center) + .HAlign(HAlign_Center) + [ + SNew(SThrobber) + .Visibility(EVisibility::SelfHitTestInvisible) + ] + +SVerticalBox::Slot() + .VAlign(VAlign_Center) + .HAlign(HAlign_Center) + [ + SNew(STextBlock) + .Visibility(EVisibility::SelfHitTestInvisible) + .Text(FText::FromString(TEXT("Loading..."))) + ] + ]; + } +}; + + +ULoadingManager::ULoadingManager(): + HoldLoadingScreenTime(0.f), + MaxHoldLoadingScreenTime(0.f), + LoadingWidgetClass(nullptr), + LoadingScreenWidget(nullptr), + bPreLoadingFlag(0), + bStartupLoading(0), + LoadingState(ELoadingState::None) +{ +} + +void ULoadingManager::Deinitialize() +{ + Super::Deinitialize(); + + FCoreUObjectDelegates::PreLoadMap.Remove(PreLoadMapHandle); + FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(PostLoadMapHandle); + + RemoveLoadingScreen(); + LoadingScreenWidget = nullptr; + LoadingWidgetClass = nullptr; + + OnLoadingStateDynamic.Clear(); + OnLoadingStateStatic = nullptr; + + if(TickerHandle.IsValid()) + { + FTSTicker::GetCoreTicker().RemoveTicker(TickerHandle); + } + + PreLoadObjects.Empty(); +} + +void ULoadingManager::Initialize(FSubsystemCollectionBase& Collection) +{ + Super::Initialize(Collection); + + PreLoadMapHandle = FCoreUObjectDelegates::PreLoadMapWithContext.AddUObject(this, &ULoadingManager::StartLoadMap); + PostLoadMapHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &ULoadingManager::EndLoadMap); +} + +bool ULoadingManager::ShouldCreateSubsystem(UObject* Outer) const +{ + return Super::ShouldCreateSubsystem(Outer); +} + +void ULoadingManager::RegisterPreLoadableObject(const TScriptInterface& LoadableObject) +{ + PreLoadObjects.Add(LoadableObject.GetObject()); +} + +void ULoadingManager::UnRegisterPreLoadableObject(const TScriptInterface& LoadableObject) +{ + PreLoadObjects.RemoveSwap(LoadableObject.GetObject()); +} + +void ULoadingManager::ReceiveLoadingState(const FOnLoadingStateStatic& Callback) +{ + if(!Callback.IsBound()) + NMT_MSG_CHECKF(0, "Callback Delegate Is Not Bound"); + + if(!bStartupLoading) + { + Callback.Execute(ELoadingState::End); + return; + } + + if(!OnLoadingStateStatic.IsBound()) + OnLoadingStateStatic = Callback; +} + +void ULoadingManager::StartLoadMap(const FWorldContext& WorldContext, const FString& MapName) +{ + if(WorldContext.OwningGameInstance == GetGameInstance()) + { + if(GEngine->IsInitialized()) + { + const FString BaseFilename = FPaths::GetBaseFilename(MapName); + const EStage CurrentStage = UGlobalUtilsLibrary::GetStringToEnum(BaseFilename); + BeginLoadingScreen(CurrentStage); + } + } +} + +void ULoadingManager::PreLoadingScreen(const EStage Stage) +{ + bPreLoadingFlag = true; + BeginLoadingScreen(Stage); +} + +void ULoadingManager::BeginLoadingScreen(const EStage Stage) +{ + ELoadingScenario* Found = LoadingScenarioMap.Find(Stage); + if(Found) + { + if(*Found == ELoadingScenario::Ignore) return; + } + + const UCoreLoadingScreenSettings* Settings = GetDefault(); + if(Stage == EStage::L_Entry) + { + if(Settings->bEnableStartUpMovie && !Settings->StartUpMoviePath.IsEmpty()) + { + bStartupLoading = true; + FLoadingScreenAttributes LoadingScreen; + LoadingScreen.bAutoCompleteWhenLoadingCompletes = false; + LoadingScreen.bMoviesAreSkippable = true; + LoadingScreen.MoviePaths.Add(Settings->StartUpMoviePath); + GetMoviePlayer()->SetupLoadingScreen(LoadingScreen); + GetMoviePlayer()->OnMoviePlaybackFinished().AddWeakLambda(this, [this]() + { + RemoveLoadingScreen(); + PropagateLoadingState(ELoadingState::End); + LoadingState = ELoadingState::None; + bPreLoadingFlag = false; + }); + return; + } + if(!Settings->bEnableStartUpMovie && Settings->PreLoadingScreenClassPath.IsValid()) + { + LoadingWidgetPath = Settings->PreLoadingScreenClassPath; + LoadingWidgetClass = LoadingWidgetPath.TryLoadClass(); + } + } + else + { + LoadingWidgetPath = Settings->PostLoadingScreenClassPath; + LoadingWidgetClass = LoadingWidgetPath.TryLoadClass(); + } + + if(LoadingState == ELoadingState::None) + { + UGameInstance* GI = GetGameInstance(); + NMT_CHECKF(GI); + + if(UGameViewportClient* GameViewportClient = GI->GetGameViewportClient()) + GameViewportClient->RemoveAllViewportWidgets(); + + MaxHoldLoadingScreenTime = Settings->MinimumLoadingScreenTime; + ShowLoadingScreen(); + } +} + +void ULoadingManager::ShowLoadingScreen() +{ + const UCoreLoadingScreenSettings* Settings = GetDefault(); + if(Settings->bForceLoadingComplete) + { + EndLoadingScreen(); + return; + } + + UGameInstance* GI = GetGameInstance(); + NMT_CHECKF(GI); + + if(!LoadingWidgetClass) + { + LoadingScreenWidget = SNew(SLoadingScreenSimple); + } + else + { + if(UUserWidget* UserWidget = UUserWidget::CreateWidgetInstance(*GI, LoadingWidgetClass, NAME_None)) + { + LoadingScreenWidget = UserWidget->TakeWidget(); + } + else + { + LoadingScreenWidget = SNew(SLoadingScreenSimple); + } + } + + NMT_CHECKF(LoadingScreenWidget); + if(UGameViewportClient* GameViewportClient = GI->GetGameViewportClient()) + { + GameViewportClient->AddViewportWidgetContent(LoadingScreenWidget.ToSharedRef(), Settings->ZOrder); + } + + PropagateLoadingState(ELoadingState::Start); + TickerHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULoadingManager::UpdateLoadingScreen)); +} + +bool ULoadingManager::UpdateLoadingScreen(float DeltaTime) +{ + HoldLoadingScreenTime += DeltaTime; + + const bool bHalfTimeDone = (HoldLoadingScreenTime < MaxHoldLoadingScreenTime * 0.5f); + if(bHalfTimeDone) return true; + + const bool bWithinMaxHold = (HoldLoadingScreenTime < MaxHoldLoadingScreenTime); + + /** + * NOTE: GShaderCompilingManager 글로벌 변수는 PIE(PlayInEditor), StandAlone 일때 유효함 + * 또한 빌드시 이미 World->Level 은 셰이더 컴파일을 기본적으로 프리 캐싱해서 배포하기 때문에 유도할 이유가 없음 + * 만약 메모리에 아직 올리지않은 에셋단위거나 직접적으로 로드를 해야한다면 FStreamableManager를 통해 비동기로드 설계를 유도해야할 것 같음 + */ +#if WITH_EDITOR + const bool bCompiling = GShaderCompilingManager->IsCompiling(); +#else + const bool bCompiling = false; +#endif + + if(!bCompiling && !bPreLoadingFlag) + { + if(!bWithinMaxHold && PreLoadObjects.IsEmpty()) + { + EndLoadingScreen(); + return false; + } + if(HoldLoadingScreenTime > 20.f && !PreLoadObjects.IsEmpty()) + { + auto FailedObjects = PreLoadObjects.FilterByPredicate([](const TWeakInterfacePtr& Object) + { + return Object->HasFinishedLoading(); + }); + for(TWeakInterfacePtr Obj : FailedObjects) + { + NMT_LOGF("Loading process timed out. Inspect the following object(s) still loading: %s", *Obj.GetWeakObjectPtr()->GetName()); + } + NMT_CHECKF(0); + } + + return true; + } + + PropagateLoadingState(ELoadingState::Update); + return true; +} + +void ULoadingManager::RemoveLoadingScreen() +{ + if(!LoadingScreenWidget.IsValid()) return; + if(TickerHandle.IsValid()) FTSTicker::GetCoreTicker().RemoveTicker(TickerHandle); + + if(UGameViewportClient* GameViewportClient = GetGameInstance()->GetGameViewportClient()) + { + GameViewportClient->RemoveViewportWidgetContent(LoadingScreenWidget.ToSharedRef()); + LoadingScreenWidget.Reset(); + } + + HoldLoadingScreenTime = 0.f; + MaxHoldLoadingScreenTime = 0.f; +} + +void ULoadingManager::EndLoadingScreen() +{ + RemoveLoadingScreen(); + PropagateLoadingState(ELoadingState::End); + LoadingState = ELoadingState::None; +} + +void ULoadingManager::EndLoadMap(UWorld* World) +{ + if(bPreLoadingFlag) + bPreLoadingFlag = false; +} + +void ULoadingManager::PropagateLoadingState(const ELoadingState NewState) +{ + LoadingState = NewState; + + if(OnLoadingStateDynamic.IsBound()) + OnLoadingStateDynamic.Broadcast(LoadingState); + + if(OnLoadingStateStatic.IsBound()) + OnLoadingStateStatic.Execute(LoadingState); +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Managers/LoadingManager.h b/Source/ProjectT/System/Core/Managers/LoadingManager.h new file mode 100644 index 0000000..38d634f --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/LoadingManager.h @@ -0,0 +1,83 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "LoadingManager.generated.h" + + +template class TScriptInterface; +class ILoadableObject; + +UENUM(BlueprintType) +enum class ELoadingState: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Start UMETA(DisplayName = "Start"), + Update UMETA(DisplayName = "Update"), + End UMETA(DisplayName = "End") +}; + +DECLARE_DELEGATE_OneParam(FOnLoadingStateStatic, const ELoadingState); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLoadingStateDynamic, const ELoadingState, LoadingState); + +UCLASS() +class PROJECTT_API ULoadingManager : public UGameInstanceSubsystem +{ + GENERATED_BODY() + +public: + ULoadingManager(); + virtual bool ShouldCreateSubsystem(UObject* Outer) const override; + void ReceiveLoadingState(const FOnLoadingStateStatic& Callback); + + UFUNCTION(BlueprintCallable) + void PreLoadingScreen(const EStage Stage = EStage::None); + + UFUNCTION(BlueprintCallable) + void RegisterPreLoadableObject(const TScriptInterface& LoadableObject); + + UFUNCTION(BlueprintCallable) + void UnRegisterPreLoadableObject(const TScriptInterface& LoadableObject); + +protected: + virtual void Deinitialize() override; + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + +private: + void StartLoadMap(const FWorldContext& WorldContext, const FString& MapName); + void BeginLoadingScreen(const EStage Stage); + void ShowLoadingScreen(); + bool UpdateLoadingScreen(float DeltaTime); + void EndLoadingScreen(); + void EndLoadMap(UWorld* World); + void RemoveLoadingScreen(); + void PropagateLoadingState(const ELoadingState NewState); + +public: + UPROPERTY(BlueprintAssignable) + FOnLoadingStateDynamic OnLoadingStateDynamic; + +private: + float HoldLoadingScreenTime; + float MaxHoldLoadingScreenTime; + + FOnLoadingStateStatic OnLoadingStateStatic; + + FDelegateHandle PreLoadMapHandle; + FDelegateHandle PostLoadMapHandle; + FDelegateHandle PostCompileHandle; + FTSTicker::FDelegateHandle TickerHandle; + + FSoftClassPath LoadingWidgetPath; + TSubclassOf LoadingWidgetClass; + TSharedPtr LoadingScreenWidget; + + uint8 bPreLoadingFlag : 1; + uint8 bStartupLoading : 1; + + ELoadingState LoadingState; + TArray> PreLoadObjects; +}; \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Managers/NotificationCenter.cpp b/Source/ProjectT/System/Core/Managers/NotificationCenter.cpp new file mode 100644 index 0000000..5d74839 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/NotificationCenter.cpp @@ -0,0 +1,110 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NotificationCenter.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +UNotificationCenter::UNotificationCenter() : + OuterObject(nullptr) +{ + +} + +void UNotificationCenter::Initialize(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +void UNotificationCenter::ReleaseNotificationCenter() +{ + for (TTuple>& It : Observers) + { + for(FNotificationCenterItem& Item : It.Value) + { + if(Item.Subscribe.IsBound()) + Item.Subscribe.Unbind(); + + if(Item.Object) + Item.Object = nullptr; + } + It.Value.Empty(); + } + Observers.Empty(); + OuterObject = nullptr; +} + +void UNotificationCenter::AddObserver(const ENotificationTypes NotificationTypes, + const FNotificationCenterItem& NotificationCenterItem) +{ + TArray& Items = Observers.FindOrAdd(NotificationTypes); + Items.Emplace(NotificationCenterItem); +} + +// FIXME: 현재는 동일한 오브젝트에서 동일한 알림 이름에 복수의 이벤트중 구분하여 삭제는 불가. +void UNotificationCenter::RemoveObserver(const UObject* Object, const ENotificationTypes NotificationTypes) +{ + if(NotificationTypes != ENotificationTypes::None) + { + const FString& NCName = UGlobalUtilsLibrary::GetEnumToString(NotificationTypes); + if(!NMT_MSG_ENSURE(Observers.Contains(NotificationTypes), "%s Not Found", *NCName)) return; + + TArray& Items = Observers[NotificationTypes]; + Items.RemoveAll([&](FNotificationCenterItem& Item) + { + if(Item.Object == Object) + { + if(Item.Subscribe.IsBound()) Item.Subscribe.Unbind(); + Item.Object = nullptr; + return true; + } + return false; + }); + } + else + { + for (TTuple>& It : Observers) + { + It.Value.RemoveAll([&](FNotificationCenterItem& Item) + { + if (Item.Object == Object) + { + if(Item.Subscribe.IsBound()) Item.Subscribe.Unbind(); + Item.Object = nullptr; + return true; + } + return false; + }); + } + } +} + +void UNotificationCenter::Post(const ENotificationTypes NotificationTypes) +{ + if(Observers.IsEmpty()) return; + + bool bPostFailed = NotificationTypes == ENotificationTypes::None || !Observers.Contains(NotificationTypes); + if(bPostFailed) return; + + TArray& Items = Observers[NotificationTypes]; + for(FNotificationCenterItem Item : Items) + { + if(Item.Subscribe.IsBound()) + Item.Subscribe.Execute(); + } +} + +void UNotificationCenter::AddObserverStatic(const UObject* Object, const ENotificationTypes NotificationTypes, const FNotificationCenterStatic& Subscribe) +{ + AddObserver(NotificationTypes, FNotificationCenterItem(Object, Subscribe)); +} + +void UNotificationCenter::AddObserverDynamic(const UObject* Object, const ENotificationTypes NotificationTypes, const FNotificationCenterDynamic& Subscribe) +{ + AddObserver(NotificationTypes, FNotificationCenterItem(Object, Subscribe)); +} + +void UNotificationCenter::RemoveObserverStatic(const UObject* Object, const ENotificationTypes NotificationTypes) +{ + RemoveObserver(Object, NotificationTypes); +} diff --git a/Source/ProjectT/System/Core/Managers/NotificationCenter.h b/Source/ProjectT/System/Core/Managers/NotificationCenter.h new file mode 100644 index 0000000..e76ce2e --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/NotificationCenter.h @@ -0,0 +1,114 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/ProjectT.h" +#include "UObject/Object.h" +#include "NotificationCenter.generated.h" + +UENUM(BlueprintType) +enum class ENotificationTypes : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Option_Language_Changed UMETA(DisplayName = "Option_Language_Changed"), + Level_Transition UMETA(DisplayName = "Level_Transition"), + GameState_Started UMETA(DisplayName = "GameState_Started"), + GameState_Changed UMETA(DisplayName = "GameState_Changed"), + GameState_Restarted UMETA(DisplayName = "GameState_Restarted"), + GameState_Defeat UMETA(DisplayName = "GameState_Defeat"), + GameState_Victory UMETA(DisplayName = "GameState_Victory"), + Player_Dead UMETA(DisplayName = "Player_Dead"), + UI_DefeatActionCleared UMETA(DisplayName = "UI_DefeatActionCleared"), + UI_VictoryActionCleared UMETA(DisplayName = "UI_VictoryActionCleared"), +}; + +DECLARE_DELEGATE(FNotificationCenterStatic) +DECLARE_DYNAMIC_DELEGATE(FNotificationCenterDynamic); + +struct FIntegratedSubscribeDelegate +{ + FNotificationCenterStatic FunctionStatic; + FNotificationCenterDynamic FunctionDynamic; + + FIntegratedSubscribeDelegate(){} + FIntegratedSubscribeDelegate(FNotificationCenterStatic const& Delegate) : FunctionStatic(Delegate){} + FIntegratedSubscribeDelegate(FNotificationCenterDynamic const& Delegate) : FunctionDynamic(Delegate){} + + void Execute() + { + if (FunctionStatic.IsBound()) FunctionStatic.Execute(); + else if (FunctionDynamic.IsBound()) FunctionDynamic.Execute(); + else NMT_MSG_CHECKF(0, "FIntegratedSubscribeDelegate Does Not Bound!"); + } + bool IsBound() const + { + return FunctionStatic.IsBound() || FunctionDynamic.IsBound(); + } + void Unbind() + { + FunctionStatic.Unbind(); + FunctionDynamic.Unbind(); + } +}; + +USTRUCT(BlueprintType) +struct FNotificationCenterItem +{ + GENERATED_BODY() + + FNotificationCenterItem() : Object(nullptr), Subscribe(nullptr){} + FNotificationCenterItem(const UObject* Object, FIntegratedSubscribeDelegate const& Subscribe) : Object(Object), Subscribe(Subscribe){} + + bool operator==(const FNotificationCenterItem& Other) const + { + return Object == Other.Object; + } + + bool operator!=(const FNotificationCenterItem& Other) const + { + return !(*this == Other); + } + + UPROPERTY() + const UObject* Object; + + FIntegratedSubscribeDelegate Subscribe; +}; + +enum class ENotificationTypes : uint8; + +UCLASS() +class PROJECTT_API UNotificationCenter : public UObject +{ + GENERATED_BODY() + + using TObservers = TMap>; + +public: + UNotificationCenter(); + + virtual void AddObserverStatic(const UObject* Object, const ENotificationTypes NotificationTypes, const FNotificationCenterStatic& Subscribe); + virtual void RemoveObserverStatic(const UObject* Object, const ENotificationTypes NotificationTypes); + + void Initialize(const UObject* WorldObjectContext); + void ReleaseNotificationCenter(); + + UFUNCTION(BlueprintCallable) + virtual void AddObserverDynamic(const UObject* Object, const ENotificationTypes NotificationTypes, const FNotificationCenterDynamic& Subscribe); + + UFUNCTION(BlueprintCallable) + virtual void RemoveObserver(const UObject* Object, const ENotificationTypes NotificationTypes); + + UFUNCTION(BlueprintCallable) + virtual void Post(const ENotificationTypes NotificationTypes); + +private: + void AddObserver(const ENotificationTypes NotificationTypes, const FNotificationCenterItem& NotificationCenterItem); + +private: + UPROPERTY() + TObjectPtr OuterObject; + + TObservers Observers; +}; diff --git a/Source/ProjectT/System/Core/Managers/OptionManager.cpp b/Source/ProjectT/System/Core/Managers/OptionManager.cpp new file mode 100644 index 0000000..32911a9 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/OptionManager.cpp @@ -0,0 +1,72 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "OptionManager.h" +#include "StageManager.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" + +UOptionManager::UOptionManager() +{ +} + +void UOptionManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +// void UOptionManager::InitializeOptionData() +// { +// GameOptionData = UPlayerGameSaveData::LoadOptionData(); +// } +// +// FGamePlayOption UOptionManager::GetGamePlayOption() const +// { +// return GameOptionData.GamePlayOption; +// } +// +// FAudioOption UOptionManager::GetAudioOption() const +// { +// return GameOptionData.AudioOption; +// } +// +// void UOptionManager::SetGamePlayOption(FGamePlayOption OptionData) +// { +// bool LanguageChanged = (GameOptionData.GamePlayOption.Language != OptionData.Language); +// +// GameOptionData.GamePlayOption = OptionData; +// UPlayerGameSaveData::SaveOptionData(GameOptionData); +// +// UNotificationCenter* NC = UGlobalUtilsLibrary::GetSharedNotificationCenter(this); +// if(LanguageChanged) +// { +// NC->Post(ENotificationTypes::Option_Language_Changed); +// } +// } +// +// void UOptionManager::SetAudioOption(FAudioOption OptionData) +// { +// GameOptionData.AudioOption = OptionData; +// UPlayerGameSaveData::SaveOptionData(GameOptionData); +// } +// +// void UOptionManager::ResetGameOptionData() +// { +// UWorld* World = UGlobalUtilsLibrary::GetValidWorld(OuterObject); +// ULevelManager* LM = IGlobalObjectProvider::Execute_GetLevelManager(World->GetGameInstance()); +// +// bool LanguageChanged = (GameOptionData.GamePlayOption.Language != UPlayerGameSaveData::GetGameLanguageFromDevice()); +// +// GameOptionData = UPlayerGameSaveData::LoadOptionData(); +// +// UNotificationCenter* NC = UGlobalUtilsLibrary::GetSharedNotificationCenter(this); +// if(LanguageChanged) +// { +// NC->Post(ENotificationTypes::Option_Language_Changed); +// } +// } + +void UOptionManager::ReleaseManager() +{ + OuterObject = nullptr; +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Managers/OptionManager.h b/Source/ProjectT/System/Core/Managers/OptionManager.h new file mode 100644 index 0000000..4331b05 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/OptionManager.h @@ -0,0 +1,109 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "OptionManager.generated.h" + +// UENUM(BlueprintType) +// enum class EGameLanguage : uint8 +// { +// Korea = 0 UMETA(DisplayName = "Korea"), +// English UMETA(DisplayName = "English"), +// Japanese UMETA(DisplayName = "Japanese"), +// ChineseCN UMETA(DisplayName = "ChineseCN"), +// ChineseTW UMETA(DisplayName = "ChineseTW"), +// Spanish UMETA(DisplayName = "Spanish"), +// French UMETA(DisplayName = "French"), +// German UMETA(DisplayName = "German"), +// Portugese UMETA(DisplayName = "Portugese"), +// Russian UMETA(DisplayName = "Russian"), +// }; +// +// +// USTRUCT(Blueprintable) +// struct FGamePlayOption +// { +// GENERATED_BODY() +// +// FGamePlayOption() : +// HardwareLanguage(EGameLanguage::English), +// Language(EGameLanguage::English) +// { +// } +// +// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GamePlayOption") +// EGameLanguage HardwareLanguage; +// +// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GamePlayOption") +// EGameLanguage Language; +// }; + +// USTRUCT(Blueprintable) +// struct FAudioOption +// { +// GENERATED_BODY() +// +// FAudioOption() : +// BGMVolume(5), +// SFXVolume(5) +// { +// } +// +// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AudioOption") +// int BGMVolume; +// +// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AudioOption") +// int SFXVolume; +// }; + +//USTRUCT(Blueprintable) +// struct FGameOptionData +// { +// GENERATED_BODY() +// +// UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="OptionData") +// FGamePlayOption GamePlayOption; +// +// UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="OptionData") +// FAudioOption AudioOption; +// }; + +UCLASS() +class PROJECTT_API UOptionManager : public UObject +{ + GENERATED_BODY() + +public: + UOptionManager(); + + void InitializeManager(const UObject* WorldObjectContext); + + // void InitializeOptionData(); + +// UFUNCTION(BlueprintPure) +// FGamePlayOption GetGamePlayOption() const; +// +// UFUNCTION(BlueprintPure) +// FAudioOption GetAudioOption() const; +// +// UFUNCTION(BlueprintCallable) +// void SetGamePlayOption(FGamePlayOption OptionData); +// +// UFUNCTION(BlueprintCallable) +// void SetAudioOption(FAudioOption OptionData); +// +// UFUNCTION(BlueprintCallable) +// void ResetGameOptionData(); +// + void ReleaseManager(); + +private: + UPROPERTY() + TObjectPtr OuterObject; +// +// UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "GameOptionData", meta = (AllowPrivateAccess = "true")) +// FGameOptionData GameOptionData; + +}; diff --git a/Source/ProjectT/System/Core/Managers/PooledActorManager.cpp b/Source/ProjectT/System/Core/Managers/PooledActorManager.cpp new file mode 100644 index 0000000..408f3b2 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/PooledActorManager.cpp @@ -0,0 +1,99 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PooledActorManager.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/PoolableActor.h" + +UPooledActorManager::UPooledActorManager() +{ +} + +void UPooledActorManager::CreatePool(const TSubclassOf& ActorClass, const int32 PoolSize, TArray* OutActors) +{ + NMT_CHECKF(ActorClass); + + bool bImplemented = ActorClass->ImplementsInterface(UPoolableActor::StaticClass()); + NMT_MSG_CHECKF(bImplemented, "ActorClass does not implement the required IPoolableActor interface."); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + TArray& Values = Pool.FindOrAdd(ActorClass); + + for(int32 i = 0; i < PoolSize; ++i) + { + AActor* NewActor = World->SpawnActor(ActorClass); + IPoolableActor::Execute_Disable(NewActor); + Values.Push(NewActor); + } + + if(OutActors != nullptr) + *OutActors = Values; +} + +void UPooledActorManager::Push(AActor* Object) +{ + NMT_CHECKF(Object); + + TSubclassOf ActorClass = Object->GetClass(); + bool bClassContains = Pool.Contains(ActorClass); + NMT_MSG_CHECKF(bClassContains, "Not found class type in pool"); + + TArray* FoundValues = Pool.Find(ActorClass); + NMT_CHECKF(FoundValues); + + IPoolableActor::Execute_Pushed(Object); + IPoolableActor::Execute_Disable(Object); + + if (!FoundValues->Contains(Object)) FoundValues->Push(Object); +} + +AActor* UPooledActorManager::Create(const TSubclassOf& ActorClass) +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + TArray* FoundValues = Pool.Find(ActorClass); + NMT_CHECKF(FoundValues); + + AActor* NewActor = World->SpawnActor(ActorClass); + return NewActor; +} + +AActor* UPooledActorManager::Obtain(const TSubclassOf& ActorClass) +{ + NMT_CHECKF(ActorClass); + + bool bImplemented = ActorClass->ImplementsInterface(UPoolableActor::StaticClass()); + NMT_MSG_CHECKF(bImplemented, "ActorClass does not implement the required IPoolableActor interface."); + + bool bClassContains = Pool.Contains(ActorClass); + NMT_MSG_CHECKF(bClassContains, "Not found class type in pool"); + + TArray* FoundValues = Pool.Find(ActorClass); + NMT_CHECKF(FoundValues); + + AActor* Ret = nullptr; + if(FoundValues->IsEmpty()) Ret = Create(ActorClass); + else + { + Ret = FoundValues->Pop(); + if(!NMT_MSG_ENSURE(Ret, "Actor is null please check")) + Ret = Create(ActorClass); + } + + IPoolableActor::Execute_Obtained(Ret); + IPoolableActor::Execute_Enable(Ret); + return Ret; +} + +void UPooledActorManager::ReleaseManager() +{ + for(TTuple, TArray>& It : Pool) + { + for(AActor*& Value : It.Value) + if(Value) Value = nullptr; + + It.Value.Empty(); + } + Pool.Empty(); +} diff --git a/Source/ProjectT/System/Core/Managers/PooledActorManager.h b/Source/ProjectT/System/Core/Managers/PooledActorManager.h new file mode 100644 index 0000000..45a029a --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/PooledActorManager.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "PooledActorManager.generated.h" + +UCLASS() +class PROJECTT_API UPooledActorManager : public UObject +{ + GENERATED_BODY() + +public: + UPooledActorManager(); + void ReleaseManager(); + void CreatePool(const TSubclassOf& ActorClass, int32 PoolSize, TArray* OutActors = nullptr); + void Push(AActor* Object); + AActor* Obtain(const TSubclassOf& ActorClass); + +private: + AActor* Create(const TSubclassOf& ActorClass); + +private: + TMap, TArray> Pool; +}; diff --git a/Source/ProjectT/System/Core/Managers/QuestManager.cpp b/Source/ProjectT/System/Core/Managers/QuestManager.cpp new file mode 100644 index 0000000..307b123 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/QuestManager.cpp @@ -0,0 +1,209 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "QuestManager.h" +#include "DataDam.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h" +#include "ProjectT/Data/Gen/GenerateStructObjective.h" +#include "ProjectT/Data/Gen/GenerateStructStage.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" + +void FQuestObjective::DecreaseObjectiveCount() +{ + if(ObjectiveCount > 0) ObjectiveCount -= 1; +} + +bool FQuestObjective::IsComplete() const +{ + return ObjectiveCount <= 0; +} + +UQuestManager::UQuestManager() : + OuterObject(nullptr) +{ +} + +void UQuestManager::InitializeMission(const int32 MissionIndex, const UDataTable* ObjectiveTable) +{ + FObjective* ObjectiveData = ObjectiveTable->FindRow(FROM_INT(MissionIndex), TEXT("Objective")); + NMT_MSG_CHECKF(ObjectiveData, "does not found Objective rowname[%s]", FROM_INT(MissionIndex)); + + OriginalQuestList.Push(*ObjectiveData); + + EObjectiveTypes ObjectiveTypes = UGlobalUtilsLibrary::GetStringToEnum(ObjectiveData->sObjectiveType); + EObjectiveSubTypes ObjectiveSubTypes = UGlobalUtilsLibrary::GetStringToEnum(ObjectiveData->sObjectiveSubType); + MissionData = FQuestObjective(ObjectiveTypes, ObjectiveSubTypes, ObjectiveData->iObjectiveItemId, ObjectiveData->iObjectiveCount, ObjectiveData->iObjectiveDescId); +} + +void UQuestManager::InitializeSubQuest(const FStage& StageRowData, const UDataTable* ObjectiveTable) +{ + UScriptStruct* ScriptStruct = StageRowData.StaticStruct(); + TFieldIterator It = ScriptStruct; + for(++It; It; ++It) + { + FProperty* Property = *It; + NMT_CHECKF(Property); + + const FName PropName = *Property->GetName(); + FName TargetLimitName = GET_MEMBER_NAME_CHECKED(FStage, iTimeLimit); + if(PropName.IsEqual(TargetLimitName)) break; + + FString ValueStr; + Property->ExportText_InContainer(0, ValueStr, &StageRowData, &StageRowData, nullptr, PPF_None); + int32 FieldIdx = FCString::Atoi(*ValueStr); + if(FieldIdx > 0) + { + FObjective* ObjectiveData = ObjectiveTable->FindRow(FROM_INT(FieldIdx), TEXT("Objective")); + NMT_MSG_CHECKF(ObjectiveData, "does not found Objective rowname[%s]", FROM_INT(FieldIdx)); + + /** NOTE: iObjectiveCount가 '0' 이라면 해당 타입의 퀘스트를 사용하지않음 */ + if(ObjectiveData->iObjectiveCount == 0) continue; + + OriginalQuestList.Push(*ObjectiveData); + EObjectiveTypes ObjectiveTypes = UGlobalUtilsLibrary::GetStringToEnum(ObjectiveData->sObjectiveType); + EObjectiveSubTypes ObjectiveSubTypes = UGlobalUtilsLibrary::GetStringToEnum(ObjectiveData->sObjectiveSubType); + FQuestObjective Data = FQuestObjective(ObjectiveTypes, ObjectiveSubTypes, ObjectiveData->iObjectiveItemId, ObjectiveData->iObjectiveCount, ObjectiveData->iObjectiveDescId); + SubQuestList.Push(Data); + } + } +} + +void UQuestManager::InitializeQuestList(const FStage& StageRowData, const FOnQuestInitializedStatic& Callback) +{ + if(StageRowData.IsDefault() || StageRowData.iMissionId == 0) + { + if(Callback.IsBound()) Callback.Execute(TArray{}); + return; + } + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(OuterObject); + UGameInstance* GI = UGameplayStatics::GetGameInstance(World); + NMT_CHECKF(GI); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GI); + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Objective); + + InitializeMission(StageRowData.iMissionId, FoundTable); + InitializeSubQuest(StageRowData, FoundTable); + + if(Callback.IsBound()) + Callback.Execute(OriginalQuestList); +} + +void UQuestManager::UpdateQuestManager(const UObject* Object, const FOnQuestChangedStatic& Callback) +{ + AddQuestChangedStatic(Object, Callback); +} + +bool UQuestManager::IsAllClearedSubQuests() +{ + bool bSubQuestEmpty = SubQuestList.IsEmpty(); + if(!NMT_MSG_ENSURE(!bSubQuestEmpty, "SubQuest list is empty")) return false; + + int32 SubQuestClearCount = 0; + for(const FQuestObjective& SubQuest : SubQuestList) + { + if(!SubQuest.IsComplete() && SubQuest.GetObjectiveSubType() == EObjectiveSubTypes::Avoid) + ++SubQuestClearCount; + + else if(SubQuest.IsComplete() && SubQuest.GetObjectiveSubType() != EObjectiveSubTypes::Avoid) + ++SubQuestClearCount; + } + + return SubQuestClearCount == SubQuestList.Num(); +} + +void UQuestManager::ReleaseManager() +{ + OuterObject = nullptr; + + for(auto Item : Subscribers) + { + if(Item.Subscribe.IsBound()) + Item.Subscribe.Unbind(); + + if(Item.Object) + Item.Object = nullptr; + } + + Subscribers.Empty(); + SubQuestList.Empty(); +} + +void UQuestManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +/** + * @param ObjectiveSubTypes SubQuest 유형별 타입입니다. + * @param ObjectiveTargetIndex TargetIndex는 'ObjectiveSubTypes' 유형에 따라 없을수도 있습니다 따라서 Index가 없다면 0을 보내면 조건에 만족합니다. + */ +void UQuestManager::CheckObjectiveSatisfied(const EObjectiveSubTypes ObjectiveSubTypes, const int32 ObjectiveTargetIndex) +{ + switch(ObjectiveSubTypes) + { + case EObjectiveSubTypes::Save: case EObjectiveSubTypes::Collect: case EObjectiveSubTypes::Avoid: case EObjectiveSubTypes::Kill: + { + if(MissionData.GetObjectiveSubType() == ObjectiveSubTypes) + { + MissionData.DecreaseObjectiveCount(); + + if(MissionData.IsComplete()) + BroadCastQuestChangedEvent(EObjectiveTypes::Mission, FObjectiveSubTypeContext(0, ObjectiveSubTypes), true); + else + BroadCastQuestChangedEvent(EObjectiveTypes::Mission, FObjectiveSubTypeContext(0, ObjectiveSubTypes), false); + + break; + } + + for(auto It = SubQuestList.CreateIterator(); It;) + { + if(It->DoesSubTypeMatch(ObjectiveSubTypes, ObjectiveTargetIndex)) + { + if(It->IsComplete()) break; + + It->DecreaseObjectiveCount(); + if(It->IsComplete()) + { + BroadCastQuestChangedEvent(EObjectiveTypes::Quest, FObjectiveSubTypeContext(It.GetIndex(), ObjectiveSubTypes), true); + break; + } + else BroadCastQuestChangedEvent(EObjectiveTypes::Quest, FObjectiveSubTypeContext(It.GetIndex(), ObjectiveSubTypes), false); + } + ++It; + } + break; + } + default: case EObjectiveSubTypes::None: NMT_CHECKF(0); + } +} + +void UQuestManager::AddQuestChangedStatic(const UObject* Object, const FOnQuestChangedStatic& Delegate) +{ + AddQuestChanged(FQuestChangedItem(Object, Delegate)); +} + +void UQuestManager::AddQuestChangedDynamic(const UObject* Object, const FOnQuestChangedDynamic& Delegate) +{ + AddQuestChanged(FQuestChangedItem(Object, Delegate)); +} + +void UQuestManager::BroadCastQuestChangedEvent(const EObjectiveTypes ObjectiveTypes, const FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted) +{ + for(FQuestChangedItem Item : Subscribers) + { + if(Item.Subscribe.IsBound()) + Item.Subscribe.Execute(ObjectiveTypes, ObjectiveSubTypeContext, IsQuestCompleted); + } +} + +void UQuestManager::AddQuestChanged(const FQuestChangedItem& QuestChangedItem) +{ + if(Subscribers.Contains(QuestChangedItem)) return; + Subscribers.Push(QuestChangedItem); +} diff --git a/Source/ProjectT/System/Core/Managers/QuestManager.h b/Source/ProjectT/System/Core/Managers/QuestManager.h new file mode 100644 index 0000000..057027a --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/QuestManager.h @@ -0,0 +1,204 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveSubTypes.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h" +#include "ProjectT/Data/Gen/GenerateStructStage.h" +#include "ProjectT/System/Core/Interfaces/ContentType.h" +#include "UObject/Object.h" +#include "QuestManager.generated.h" + +enum class EObjectiveSubTypes : uint8; +enum class EObjectiveTypes : uint8; +struct FStageData; +struct FObjective; + +USTRUCT(BlueprintType) +struct FObjectiveSubTypeContext +{ + GENERATED_BODY() + + FObjectiveSubTypeContext(): QuestNumber(0), ObjectiveSubType(){} + FObjectiveSubTypeContext(const int32 InQuestNumber, const EObjectiveSubTypes InObjectiveSubType) : QuestNumber(InQuestNumber), ObjectiveSubType(InObjectiveSubType) {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int32 QuestNumber; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + EObjectiveSubTypes ObjectiveSubType; +}; + +USTRUCT(BlueprintType) +struct FQuestObjective +{ + GENERATED_BODY() + + FQuestObjective(const EObjectiveTypes ObjectiveType, const EObjectiveSubTypes ObjectiveSubType, const int32 ItemIndex, + const int32 ObjectiveCount, const int32 ObjectiveDescIndex) : + ObjectiveType(ObjectiveType), + ObjectiveSubType(ObjectiveSubType), + ObjectiveIndex(ItemIndex), + ObjectiveCount(ObjectiveCount), + ObjectiveDescIndex(ObjectiveDescIndex){} + + FQuestObjective(): + ObjectiveType(), + ObjectiveSubType(), + ObjectiveIndex(0), + ObjectiveCount(0), + ObjectiveDescIndex(0){} + + void DecreaseObjectiveCount(); + bool IsComplete() const; + + EObjectiveTypes GetObjectiveType() const { NMT_CHECKF(ObjectiveType != EObjectiveTypes::None); return ObjectiveType; } + EObjectiveSubTypes GetObjectiveSubType() const { NMT_CHECKF(ObjectiveSubType != EObjectiveSubTypes::None); return ObjectiveSubType; } + int32 GetObjectiveIndex() const { return ObjectiveIndex; } + + bool DoesSubTypeMatch(const EObjectiveSubTypes TargetSubType, const int32 ObjectiveTargetIndex = 0) const + { + return TargetSubType == ObjectiveSubType && ObjectiveIndex == ObjectiveTargetIndex; + } + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + EObjectiveTypes ObjectiveType; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + EObjectiveSubTypes ObjectiveSubType; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + int32 ObjectiveIndex; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + int32 ObjectiveCount; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + int32 ObjectiveDescIndex; +}; + +DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnQuestChangedDynamic, const EObjectiveTypes, ObjectiveTypes, const FObjectiveSubTypeContext, ObjectiveSubTypeContext, const bool, IsQuestCompleted); +DECLARE_DELEGATE_ThreeParams(FOnQuestChangedStatic, const EObjectiveTypes, const FObjectiveSubTypeContext, const bool /* IsQuestCompleted */) + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnQuestInitializedDynamic, const TArray&, QuestList); +DECLARE_DELEGATE_OneParam(FOnQuestInitializedStatic, const TArray& /* QuestList */); + +template +struct FIntegrateDelegate +{ + StaticDelegateType StaticDelegate; + DynamicDelegateType DynamicDelegate; + + FIntegrateDelegate(){} + FIntegrateDelegate(StaticDelegateType const& Delegate) : StaticDelegate(Delegate){} + FIntegrateDelegate(DynamicDelegateType const& Delegate) : DynamicDelegate(Delegate){} + + void Execute(Params... Args) + { + if (StaticDelegate.IsBound()) StaticDelegate.Execute(Args...); + else if (DynamicDelegate.IsBound()) DynamicDelegate.Execute(Args...); + else NMT_MSG_CHECKF(0, "FIntegrateDelegate Does Not Bound!"); + } + bool IsBound() const + { + return StaticDelegate.IsBound() || DynamicDelegate.IsBound(); + } + void Unbind() + { + StaticDelegate.Unbind(); + DynamicDelegate.Unbind(); + } +}; + +using QuestChangedDelegate = FIntegrateDelegate; +USTRUCT(BlueprintType) +struct FQuestChangedItem +{ + GENERATED_BODY() + FQuestChangedItem() : Object(nullptr), Subscribe(nullptr){} + FQuestChangedItem(const UObject* Object, QuestChangedDelegate const& Subscribe) : Object(Object), Subscribe(Subscribe){} + + bool operator==(const FQuestChangedItem& Other) const + { + return Object == Other.Object; + } + + bool operator!=(const FQuestChangedItem& Other) const + { + return !(*this == Other); + } + + UPROPERTY() + const UObject* Object; + QuestChangedDelegate Subscribe; +}; + +using QuestInitialized = FIntegrateDelegate&>; +USTRUCT(BlueprintType) +struct FQuestInitializedItem +{ + GENERATED_BODY() + FQuestInitializedItem() : Object(nullptr), Subscribe(nullptr){} + FQuestInitializedItem(const UObject* Object, QuestInitialized const& Subscribe) : Object(Object), Subscribe(Subscribe){} + + bool operator==(const FQuestInitializedItem& Other) const + { + return Object == Other.Object; + } + + bool operator!=(const FQuestInitializedItem& Other) const + { + return !(*this == Other); + } + + UPROPERTY() + const UObject* Object; + QuestInitialized Subscribe; +}; + +UCLASS() +class PROJECTT_API UQuestManager : public UObject, public IContentType +{ + GENERATED_BODY() + CONTENT_TYPE_NUMBER(EContentType::Objective) + +public: + UQuestManager(); + + void ReleaseManager(); + void InitializeManager(const UObject* WorldObjectContext); + void InitializeQuestList(const FStage& StageRowData, const FOnQuestInitializedStatic& Callback); + void UpdateQuestManager(const UObject* Object, const FOnQuestChangedStatic& Callback); + bool IsAllClearedSubQuests(); + + void AddQuestChangedStatic(const UObject* Object, const FOnQuestChangedStatic& Delegate); + + UFUNCTION(BlueprintCallable) + void AddQuestChangedDynamic(const UObject* Object, const FOnQuestChangedDynamic& Delegate); + + UFUNCTION(BlueprintCallable) + void CheckObjectiveSatisfied(const EObjectiveSubTypes ObjectiveSubTypes, const int32 ObjectiveTargetIndex = 0); + +private: + void InitializeMission(const int32 MissionIndex, const UDataTable* ObjectiveTable); + void InitializeSubQuest(const FStage& StageRowData, const UDataTable* ObjectiveTable); + + void BroadCastQuestChangedEvent(const EObjectiveTypes ObjectiveTypes, const FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted); + void AddQuestChanged(const FQuestChangedItem& QuestChangedItem); + +private: + friend UCoreCheatManager; + + UPROPERTY() + TObjectPtr OuterObject; + FQuestObjective MissionData; + TArray SubQuestList; + TArray Subscribers; + + TArray OriginalQuestList; +}; diff --git a/Source/ProjectT/System/Core/Managers/ResourceManager.cpp b/Source/ProjectT/System/Core/Managers/ResourceManager.cpp new file mode 100644 index 0000000..0c13bcc --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/ResourceManager.cpp @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ResourceManager.h" + +UResourceManager::UResourceManager() : + OuterObject(nullptr) +{ + +} + +void UResourceManager::Initialize(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +void UResourceManager::ReleaseManager() +{ + if(OnPreLoadAssetComplete.IsBound()) OnPreLoadAssetComplete.Unbind(); + + for(TPair> Pair : Resources) + Pair.Value = nullptr; + + Resources.Empty(); + + OuterObject = nullptr; +} + +void UResourceManager::RequestPreLoad(const FOnPreLoadAssetComplete& Callback) +{ + if(OnPreLoadAssetComplete.IsBound()) return; + + OnPreLoadAssetComplete = Callback; + + + +} diff --git a/Source/ProjectT/System/Core/Managers/ResourceManager.h b/Source/ProjectT/System/Core/Managers/ResourceManager.h new file mode 100644 index 0000000..40500c3 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/ResourceManager.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "ResourceManager.generated.h" + + +DECLARE_DELEGATE(FOnPreLoadAssetComplete) + +UCLASS() +class PROJECTT_API UResourceManager : public UObject +{ + GENERATED_BODY() + +public: + UResourceManager(); + void Initialize(const UObject* WorldObjectContext); + void ReleaseManager(); + void RequestPreLoad(const FOnPreLoadAssetComplete& Callback); + +private: + UPROPERTY() + TObjectPtr OuterObject; + + UPROPERTY() + TMap> Resources; + + FOnPreLoadAssetComplete OnPreLoadAssetComplete; +}; diff --git a/Source/ProjectT/System/Core/Managers/SequenceManager.cpp b/Source/ProjectT/System/Core/Managers/SequenceManager.cpp new file mode 100644 index 0000000..bc7b6e3 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/SequenceManager.cpp @@ -0,0 +1,202 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SequenceManager.h" +#include "Kismet/GameplayStatics.h" +#include "Runtime/LevelSequence/Public/LevelSequenceActor.h" +#include "Runtime/LevelSequence/Public/LevelSequencePlayer.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" + + +USequenceManager::USequenceManager() : + bSkipable(true), + SequenceActor(nullptr), + SequencePlayer(nullptr), + CurrentSequence(nullptr), + SkipOffset(0.1f) +{ + +} + +void USequenceManager::InitializeSequenceManager(UWorld* World) +{ + +} + +void USequenceManager::UpdateSequence(UWorld* World, const FName& RowName, const FOnEndSequence& Callback) +{ + if(CHECK_FREE(RowName.ToString())) + { + Callback.Execute(); + return; + } + + // FIXME: 프로젝트 이주로 기존에 쓰던 데이터는 삭제됨 새로운 데이터 구조에 맞춰서 수정필요 + // UDataDam* DataDam = IGlobalObjectProvider::Execute_GetDataDam(UGameplayStatics::GetGameInstance(World)); + // FNSequenceListData* SequenceListData = DataDam->GetDataTableRowUnChecked(RowName); + // if(!NMT_ENSURE(SequenceListData)) + // { + // Callback.Execute(); + // return; + // } + // CurrentSequence = UGlobalUtilsLibrary::GetLevelSequenceFromPath(SequenceListData->sSequencePath); + + FMovieSceneSequencePlaybackSettings NewSettings; + + if(!SequencePlayer) + SequencePlayer = ULevelSequencePlayer::CreateLevelSequencePlayer(World, CurrentSequence.Get(), NewSettings, SequenceActor); + + if(!NMT_ENSURE(CurrentSequence && SequencePlayer)) return; + + if(SequencePlayer->OnFinished.IsBound()) + SequencePlayer->OnFinished.RemoveAll(this); + + SequencePlayer->OnFinished.AddDynamic(this, &USequenceManager::OnFinishedSequence); + + if(OnEndSequence.IsBound()) + OnEndSequence.Unbind(); + + OnEndSequence = Callback; + + SequencePlayer->Stop(); + SequenceActor->SetSequence(CurrentSequence); + SequencePlayer->Play(); + OnSceneEvent.Broadcast(SequencePlayer->GetSequenceName()); + if(!bSkipable || !OnSequenceStarted.IsBound()) return; + OnSequenceStarted.Execute(); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(World)); + //NC->Post(ENotificationTypes::Sequence_Begin); +} + +void USequenceManager::UpdateSequenceWithPlayRate(UWorld* World, const FName& RowName, float PlayRate, + FOnEndSequence Callback) +{ + if(CHECK_FREE(RowName.ToString())) + { + Callback.Execute(); + return; + } + + // FIXME: 프로젝트 이주로 기존에 쓰던 데이터는 삭제됨 새로운 데이터 구조에 맞춰서 수정필요 + // UDataDam* DataDam = IGlobalObjectProvider::Execute_GetDataDam(UGameplayStatics::GetGameInstance(World)); + // FNSequenceListData* SequenceListData = DataDam->GetDataTableRowUnChecked(RowName); + // if(!NMT_ENSURE(SequenceListData)) + // { + // Callback.Execute(); + // return; + // } + // CurrentSequence = UGlobalUtilsLibrary::GetLevelSequenceFromPath(SequenceListData->sSequencePath); + // + // FMovieSceneSequencePlaybackSettings NewSettings; + // + // if(!SequencePlayer) + // SequencePlayer = ULevelSequencePlayer::CreateLevelSequencePlayer(World, CurrentSequence.Get(), NewSettings, SequenceActor); + // + // if(!NMT_ENSURE(CurrentSequence && SequencePlayer)) return; + // + // if(SequencePlayer->OnFinished.IsBound()) + // SequencePlayer->OnFinished.RemoveAll(this); + // + // SequencePlayer->OnFinished.AddDynamic(this, &USequenceManager::OnFinishedSequence); + // + // if(OnEndSequence.IsBound()) + // OnEndSequence.Unbind(); + // + // OnEndSequence = Callback; + // + // SequencePlayer->Stop(); + // SequenceActor->SetSequence(CurrentSequence); + // SequencePlayer->Play(); + // SequencePlayer->SetPlayRate(PlayRate); + // OnSceneEvent.Broadcast(SequencePlayer->GetSequenceName()); + // if(!OnSequenceStarted.IsBound()) return; + // OnSequenceStarted.Execute(); + // + // UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(World)); + // NC->Post(ENotificationTypes::Sequence_Begin); + +} + +void USequenceManager::ReleaseManager() +{ + NOT_IMPLEMENTED(); +} + +void USequenceManager::OnFinishedSequence() +{ + if(SequencePlayer) SequencePlayer->SetPlayRate(1.0f); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(UGameplayStatics::GetGameInstance(this)); + // FIXME: 프로젝트 이주로 기존에 쓰던 데이터는 삭제됨 새로운 데이터 구조에 맞춰서 수정필요 + //NC->Post(ENotificationTypes::Sequence_End); + + if(!NMT_ENSURE(OnEndSequence.IsBound())) return; + OnEndSequence.Execute(); + if(!OnSequenceFinishedWithoutSkip.IsBound()) return; + OnSequenceFinishedWithoutSkip.Execute(); +} + +void USequenceManager::StopSequence() const +{ + if(SequencePlayer && SequencePlayer->IsPlaying()) + SequencePlayer->Stop(); +} + +void USequenceManager::AddSceneEventListener(TFunction Func) +{ + OnSceneEvent.AddLambda([Func](const FString& SequenceName) + { + Func(SequenceName); + }); +} + +void USequenceManager::SkipCurrentSequence() +{ + FQualifiedFrameTime FrameTime = SequencePlayer->GetEndTime(); + float PostSkipTime = FrameTime.AsSeconds() - SkipOffset; + + UMovieSceneSequence* Sequence = SequencePlayer->GetSequence(); + NMT_ENSURE(Sequence); + TArray MarkedFrames = Sequence->GetMovieScene()->GetMarkedFrames(); + if(MarkedFrames.Num() > 0) + { + int Idx = MarkedFrames.IndexOfByPredicate([&](FMovieSceneMarkedFrame MarkedFrame){ + return MarkedFrame.Label.Contains(TEXT("PostSkipTime")); + }); + if (Idx >= 0) + { + float TimeScaleFactor = 800.f; + PostSkipTime = MarkedFrames[Idx].FrameNumber / SequencePlayer->GetFrameRate(); + PostSkipTime /= TimeScaleFactor; + } + } + + FMovieSceneSequencePlaybackParams PlaybackParams; + PlaybackParams.Time = PostSkipTime; + PlaybackParams.PositionType = EMovieScenePositionType::Time; + + SequencePlayer->SetPlaybackPosition(PlaybackParams); + SequencePlayer->Play(); +} + +bool USequenceManager::IsCurrentSequenceSkipable() +{ + FQualifiedFrameTime FrameTime = SequencePlayer->GetEndTime(); + float Duration = FrameTime.AsSeconds(); + float CurrentTime = SequencePlayer->GetCurrentTime().AsSeconds(); + + return Duration - CurrentTime >= 1.0f; +} + +void USequenceManager::BeginDestroy() +{ + UObject::BeginDestroy(); + + OnEndSequence.Unbind(); + OnSceneEvent.Clear(); +} + + + diff --git a/Source/ProjectT/System/Core/Managers/SequenceManager.h b/Source/ProjectT/System/Core/Managers/SequenceManager.h new file mode 100644 index 0000000..a86a6a9 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/SequenceManager.h @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "SequenceManager.generated.h" + + +/** + * + */ +DECLARE_MULTICAST_DELEGATE_OneParam(FOnSceneEvent, const FString&) +DECLARE_DELEGATE(FOnSequenceStarted); +DECLARE_DELEGATE(FOnSequenceFinishedWithoutSkip); +DECLARE_DELEGATE(FOnEndSequence); + +class ALevelSequenceActor; +class ULevelSequencePlayer; +class ULevelSequence; + +UCLASS(BlueprintType) +class PROJECTT_API USequenceManager : public UObject +{ + GENERATED_BODY() + +public: + USequenceManager(); + + UFUNCTION() + void OnFinishedSequence(); + + void InitializeSequenceManager(UWorld* World); + void UpdateSequence(UWorld* World, const FName& RowName, const FOnEndSequence& Callback); + void UpdateSequenceWithPlayRate(UWorld* World, const FName& RowName, float PlayRate, FOnEndSequence Callback); + void ReleaseManager(); + + void StopSequence() const; + void AddSceneEventListener(TFunction Func); + + UFUNCTION(BlueprintCallable) + void SkipCurrentSequence(); + + bool IsCurrentSequenceSkipable(); + + FOnSequenceFinishedWithoutSkip OnSequenceFinishedWithoutSkip; + FOnSequenceStarted OnSequenceStarted; + uint8 bSkipable:1; + +protected: + virtual void BeginDestroy() override; + +private: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true")) + ALevelSequenceActor* SequenceActor; + + UPROPERTY() + TObjectPtr SequencePlayer; + + UPROPERTY() + TObjectPtr CurrentSequence; + + FOnEndSequence OnEndSequence; + FOnSceneEvent OnSceneEvent; + FName CurrentSequenceName; + float SkipOffset; + +}; + diff --git a/Source/ProjectT/System/Core/Managers/SoundManager.cpp b/Source/ProjectT/System/Core/Managers/SoundManager.cpp new file mode 100644 index 0000000..376287f --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/SoundManager.cpp @@ -0,0 +1,220 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SoundManager.h" + +#include "Components/AudioComponent.h" +#include "ProjectT/ProjectT.h" +#include "Kismet/GameplayStatics.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateStructSoundList.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" + +USoundManager::USoundManager() : + OuterObject(nullptr) +{ + +} + +void USoundManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +UAudioComponent* USoundManager::PlaySound2D(FName RowName) +{ + return PlaySound2D(RowName, nullptr); +} + +UAudioComponent* USoundManager::PlaySoundDynamic2D(FName RowName, const FOnSoundFinishedDynamic& Callback) +{ + UAudioComponent* Ret = PlaySound2D(RowName, FOnSoundFinishedStatic::CreateLambda([Callback](const ESoundState SoundState) + { + if(Callback.IsBound()) Callback.Execute(SoundState); + })); + + return Ret; +} + +UAudioComponent* USoundManager::PlaySound2D(FName RowName, const FOnSoundFinishedStatic& Callback) +{ + FSoundDescription SoundDesc = GetSoundByContentTypeUnChecked(RowName); + FString RowString = RowName.ToString(); + if(!CHECK_FREE(RowString)) + { + if(!NMT_MSG_ENSURE(!SoundDesc.IsDefault(), "%s : Sound FilePath Does Not Exist!", *RowString)) return nullptr; + } + else return nullptr; + + UAudioComponent* Ret = UGameplayStatics::SpawnSound2D(this, SoundDesc.SoundBase); + if(!Ret) + { + if(Callback.IsBound()) + Callback.Execute(ESoundState::NotSpawned); + + return nullptr; + } + + FSoundElements SE(ESoundSpace::Space2D, RowName, Ret); + SoundPool.Push(SE); + + if(Callback.IsBound()) + { + OnSoundFinished = Callback; + Ret->OnAudioFinished.AddDynamic(this, &USoundManager::OnSoundFinishedFunction); + } + UE_LOG(LogTemp, Log, TEXT("PlaySound[Space3D][%s] : %s"), *RowName.ToString(), *SoundDesc.SoundBase->GetPathName()); + + return Ret; +} + +void USoundManager::OnSoundFinishedFunction() +{ + if(OnSoundFinished.IsBound()) + { + OnSoundFinished.Execute(ESoundState::Spawned); + OnSoundFinished.Unbind(); + } +} + +FSoundDescription USoundManager::GetSoundByContentTypeUnChecked(const FName& RowName) +{ + FString RowString = RowName.ToString(); + if(CHECK_FREE(RowString) || !RowString.IsNumeric()) return FSoundDescription(); + + FSoundDescription Ret; + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GI); + NMT_CHECKF(DD); + + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::SoundList); + uint8* FoundData = FoundTable->FindRowUnchecked(RowName); + if(!NMT_MSG_ENSURE(FoundData, "Not Found Sound Data : %s", *RowName.ToString())) + return FSoundDescription(); + + FSoundList* SoundData = reinterpret_cast(FoundData); + if(SoundData->sSoundClass == TEXT("BGM")) + { + Ret.SoundBase = UAssetUtilsLibrary::GetSoundBaseFromPath(SoundData->sSoundPath); + Ret.Space = ESoundSpace::Space2D; + } + else if(SoundData->sSoundClass == TEXT("SFX")) + { + Ret.SoundBase = UAssetUtilsLibrary::GetSoundBaseFromPath(SoundData->sSoundPath); + Ret.Space = SoundData->sSoundType.Equals(TEXT("2D"))? ESoundSpace::Space2D : ESoundSpace::Space3D; + + if(!CHECK_FREE(SoundData->sAttenPath)) + Ret.SoundAttenuation = UAssetUtilsLibrary::GetSoundAttenuationFromPath(SoundData->sAttenPath); + } + else NMT_CHECKF(0); + + return Ret; +} + +UAudioComponent* USoundManager::PlaySound3D(FName RowName, FVector Location) +{ + return PlaySound3D(RowName, Location, nullptr); +} + +UAudioComponent* USoundManager::PlaySoundDynamic3D(FName RowName, FVector Location, const FOnSoundFinishedDynamic& Callback) +{ + UAudioComponent* Ret = PlaySound3D(RowName, Location, FOnSoundFinishedStatic::CreateLambda([Callback](const ESoundState SoundState) + { + if(Callback.IsBound()) Callback.Execute(SoundState); + })); + + return Ret; +} + +UAudioComponent* USoundManager::PlaySound3D(FName RowName, FVector Location, const FOnSoundFinishedStatic& CallBack) +{ + UAudioComponent* Ret = nullptr; + FSoundDescription SoundDesc = GetSoundByContentTypeUnChecked(RowName); + FString RowString = RowName.ToString(); + + if(!CHECK_FREE(RowString)) + { + if(!NMT_MSG_ENSURE(!SoundDesc.IsDefault(), "%s : Sound FilePath Does Not Exist!", *RowString)) return nullptr; + } + else return nullptr; + + APlayerController* PC = UGameplayStatics::GetPlayerController(OuterObject, 0); + Ret = UGameplayStatics::SpawnSoundAtLocation(OuterObject, SoundDesc.SoundBase, Location, FRotator(), 1.f, 1.f, 0.f, SoundDesc.SoundAttenuation); + if(!Ret) + { + if(CallBack.IsBound()) + CallBack.Execute(ESoundState::NotSpawned); + + return nullptr; + } + + FSoundElements SE(ESoundSpace::Space3D, RowName, Ret); + SoundPool.Push(SE); + + if(CallBack.IsBound()) + { + OnSoundFinished = CallBack; + Ret->OnAudioFinished.AddDynamic(this, &USoundManager::OnSoundFinishedFunction); + } + UE_LOG(LogTemp, Log, TEXT("PlaySound[Space3D][%s] : %s"), *RowName.ToString(), *SoundDesc.SoundBase->GetPathName()); + + return Ret; +} + +UAudioComponent* USoundManager::PlaySound3DAttached(FName RowName, USceneComponent* AttachComponent, + const EAttachLocation::Type AttachLocationRule, FString SocketID) +{ + UAudioComponent* Ret = nullptr; + FSoundDescription SoundDesc = GetSoundByContentTypeUnChecked(RowName); + FString RowString = RowName.ToString(); + + if(!CHECK_FREE(RowString)) + { + if(!NMT_MSG_ENSURE(!SoundDesc.IsDefault(), "%s : Sound FilePath Does Not Exist!", *RowString)) return nullptr; + if(!NMT_MSG_ENSURE(AttachComponent, "%s : AttachComponent Is Null!", *RowString)) return nullptr; + } + else return nullptr; + + APlayerController* PC = UGameplayStatics::GetPlayerController(OuterObject, 0); + Ret = UGameplayStatics::SpawnSoundAttached(SoundDesc.SoundBase, AttachComponent, *SocketID, FVector(), FRotator(), AttachLocationRule, false, 1.f, 1.f, 0.f, SoundDesc.SoundAttenuation); + if(!Ret) + { + return nullptr; + } + + + FSoundElements SE(ESoundSpace::Space3D, RowName, Ret); + SoundPool.Push(SE); + + UE_LOG(LogTemp, Log, TEXT("PlaySound[Space3D][%s] : %s"), *RowName.ToString(), *SoundDesc.SoundBase->GetPathName()); + + return Ret; +} + +void USoundManager::ResetAllPoolingSounds() +{ + for(const FSoundElements& SE : SoundPool) + { + if(IsValid(SE.AudioComponent) && IsValid(SE.AudioComponent->GetSound())) + { + if(SE.AudioComponent->IsPlaying()) + SE.AudioComponent->Stop(); + } + } + SoundPool.Empty(); +} + +void USoundManager::ReleaseManager() +{ + for(const FSoundElements& SE : SoundPool) + { + if(IsValid(SE.AudioComponent)) + SE.AudioComponent->DestroyComponent(); + } + SoundPool.Empty(); +} + diff --git a/Source/ProjectT/System/Core/Managers/SoundManager.h b/Source/ProjectT/System/Core/Managers/SoundManager.h new file mode 100644 index 0000000..65da5c8 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/SoundManager.h @@ -0,0 +1,124 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "SoundManager.generated.h" + +namespace EAttachLocation +{ + enum Type : int; +}; + +UENUM() +enum class ESoundSpace : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Space2D UMETA(DisplayName = "Space2D"), + Space3D UMETA(DisplayName = "Space3D"), +}; + +UENUM(BlueprintType) +enum class ESoundState : uint8 +{ + NotSpawned = 0 UMETA(DisplayName = "NotSpawned"), + Spawned UMETA(DisplayName = "Spawned"), +}; + +USTRUCT(Blueprintable) +struct FSoundElements +{ + GENERATED_BODY() + + FSoundElements(): Space(ESoundSpace::None), AudioComponent(nullptr) {} + FSoundElements(ESoundSpace InSpace, const FName& InSoundName, UAudioComponent* InAudioComponent) + : Space(InSpace), SoundName(InSoundName), AudioComponent(InAudioComponent) {} + + UPROPERTY() + ESoundSpace Space; + + UPROPERTY() + FName SoundName; + + UPROPERTY() + TObjectPtr AudioComponent; +}; + + +USTRUCT(Blueprintable) +struct FSoundDescription +{ + GENERATED_BODY() + + FSoundDescription() : SoundBase(nullptr), SoundAttenuation(nullptr), Space(ESoundSpace::None){} + FSoundDescription(USoundBase* const InSoundBase, USoundAttenuation* const InSoundAttenuation, const ESoundSpace InSpace) : + SoundBase(InSoundBase), + SoundAttenuation(InSoundAttenuation), + Space(InSpace){} + + bool IsDefault() const + { + return !SoundBase && !SoundAttenuation; + } + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SoundBase; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr SoundAttenuation; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + ESoundSpace Space; +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSoundFinishedDynamic, const ESoundState, SoundState); +DECLARE_DELEGATE_OneParam(FOnSoundFinishedStatic, const ESoundState); +UCLASS() +class PROJECTT_API USoundManager : public UObject +{ + GENERATED_BODY() + +public: + USoundManager(); + + void InitializeManager(const UObject* WorldObjectContext); + void ReleaseManager(); + + UFUNCTION() + void OnSoundFinishedFunction(); + + UAudioComponent* PlaySound2D(FName RowName, const FOnSoundFinishedStatic& Callback); + + UFUNCTION(BlueprintCallable) + UAudioComponent* PlaySound2D(FName RowName); + + UFUNCTION(BlueprintCallable) + UAudioComponent* PlaySoundDynamic2D(FName RowName, const FOnSoundFinishedDynamic& Callback); + + UAudioComponent* PlaySound3D(FName RowName, FVector Location, const FOnSoundFinishedStatic& CallBack); + + UFUNCTION(BlueprintCallable) + UAudioComponent* PlaySound3D(FName RowName, FVector Location); + + UFUNCTION(BlueprintCallable) + UAudioComponent* PlaySoundDynamic3D(FName RowName, FVector Location, const FOnSoundFinishedDynamic& Callback); + + UFUNCTION(BlueprintCallable) + UAudioComponent* PlaySound3DAttached(FName RowName, USceneComponent* AttachComponent, const EAttachLocation::Type AttachLocationRule, FString SocketID); + + UFUNCTION(BlueprintCallable) + void ResetAllPoolingSounds(); + +private: + FSoundDescription GetSoundByContentTypeUnChecked(const FName& RowName); + +private: + UPROPERTY() + TObjectPtr OuterObject; + + UPROPERTY() + TArray SoundPool; + + FOnSoundFinishedStatic OnSoundFinished; +}; diff --git a/Source/ProjectT/System/Core/Managers/StageManager.cpp b/Source/ProjectT/System/Core/Managers/StageManager.cpp new file mode 100644 index 0000000..4560723 --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/StageManager.cpp @@ -0,0 +1,212 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "StageManager.h" +#include "LoadingManager.h" +#include "NotificationCenter.h" +#include "Kismet/GameplayStatics.h" +#include "ProjectT/Data/Gen/GenerateEnumContentType.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" +#include "ProjectT/System/Core/Interfaces/CoreCameraControl.h" + +UStageManager::UStageManager(): + OuterObject(nullptr), + MaxStageNumber(0) +{ + LobbyPath = JOIN_STRINGS(TEXT(""), BaseDataPaths::LevelsDir, TEXT("L_Lobby.umap")); + SelectMapPath = JOIN_STRINGS(TEXT(""), BaseDataPaths::LevelsDir, TEXT("L_SelectMap.umap")); + IntroPath = JOIN_STRINGS(TEXT(""), BaseDataPaths::LevelsDir, TEXT("L_Intro.umap")); +} + +void UStageManager::GetStageData(const FString& LevelName, StageData& OutData) const +{ + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GI); + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Stage); + + TMap RowMap = FoundTable->GetRowMap(); + for(TPair Pair : RowMap) + { + FStage* StageData = reinterpret_cast(Pair.Value); + NMT_CHECKF(StageData); + + if(StageData->sStageName == LevelName) + { + OutData.Value.StageData = *StageData; + OutData.Key = Pair.Key; + FString KeyString = Pair.Key.ToString(); + UGlobalUtilsLibrary::DivideString(CONTENT_DIGIT, KeyString); + OutData.Value.StageProperties.StageNumber = FCString::Atoi(*KeyString); + return; + } + } + NMT_MSG_CHECKF(0, "StageData not found"); +} + +/** + * NOTE: Stage 테이블의 마지막 행 Index를 가공해서 스테이지 넘버로 변환 + * 챕터에 대한 고려가 없어서 챕터가 생긴다면 문제가 생길 가능성있음 + * @return MaxStageNumber + */ +int32 UStageManager::GetMaxStage() const +{ + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GI); + NMT_CHECKF(DD); + + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Stage); + TArray RowNames = FoundTable->GetRowNames(); + + FString KeyString = RowNames.Last().ToString(); + UGlobalUtilsLibrary::DivideString(CONTENT_DIGIT, KeyString); + int32 Ret = FCString::Atoi(*KeyString); + + return Ret; +} + +void UStageManager::InitializeManager(const UObject* WorldObjectContext, const FString& LevelName) +{ + OuterObject = const_cast(WorldObjectContext); + + StageData StageData; + GetStageData(LevelName, StageData); + CurrentStageInfo = StageData.Value; + CurrentStageInfo.RowName = StageData.Key; + MaxStageNumber = GetMaxStage(); +} + +void UStageManager::NextLevelLoad() +{ + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GI); + NMT_CHECKF(DD); + + FString NextLevelString = "FREE"; + FStageProperties StageProp = CurrentStageInfo.StageProperties; + do + { + if(StageProp.StageNumber >= MaxStageNumber) + { + UGameplayStatics::OpenLevel(OuterObject, *LobbyPath); + return; + } + StageProp.StageNumber += 1; + FName RowName = GetLevelDataRowName(StageProp); + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Stage); + FStage* FoundData = FoundTable->FindRow(RowName, TEXT("FStage")); + NMT_CHECKF(FoundData); + NextLevelString = FoundData->sStageName; + + } while (CHECK_FREE(NextLevelString)); + + const EStage NextLevel = UGlobalUtilsLibrary::GetStringToEnum(NextLevelString); + PrepareLevelLoad(NextLevel); +} + +void UStageManager::GetStagePath(const EStage StageType, FString& NextStagePath) +{ + FString NextLevelName = UGlobalUtilsLibrary::GetEnumToString(StageType); + + StageData StageData; + GetStageData(NextLevelName, StageData); + NextStagePath = UGlobalUtilsLibrary::ReferencePathToFilePath(StageData.Value.StageData.sStagePath); + + if (!FPackageName::DoesPackageExist(NextStagePath)) + NMT_MSG_CHECKF(0, "Stage package does not exist: %s", *NextStagePath); +} + +void UStageManager::PrepareLevelLoad(const EStage StageType, float FadeDuration , float FadeDelay) +{ + APawn* Player = UGameplayStatics::GetPlayerPawn(OuterObject, 0); + if(!NMT_ENSURE(Player)) return; + + FString NextStagePath; + GetStagePath(StageType, NextStagePath); + + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GI); + NMT_CHECKF(NC); + NC->Post(ENotificationTypes::Level_Transition); + + ICoreCameraControl* CameraControl = Player->FindComponentByInterface(); + CameraControl->StartFade(EFadeType::FadeOut, FOnStaticFinishCameraFade::CreateLambda([this, NextStagePath, StageType]() + { + UGameInstance* GI = UGameplayStatics::GetGameInstance(OuterObject); + NMT_CHECKF(GI); + + ULoadingManager* LoadingManager = GI->GetSubsystem(); + NMT_CHECKF(LoadingManager); + + LoadingManager->PreLoadingScreen(StageType); + LoadPackageAsync(NextStagePath, FLoadPackageAsyncDelegate::CreateUObject(this, &UStageManager::PackageLevelLoaded)); + }), FadeDuration, 1.f); + + FLoadPackageAsyncOptionalParams Params; + +} + +void UStageManager::ForceLoadLevel(EStage StageType) +{ + FString NextStagePath; + GetStagePath(StageType, NextStagePath); + + UGameplayStatics::OpenLevel(OuterObject, *NextStagePath); +} + +void UStageManager::PackageLevelLoaded(const FName& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result) +{ + switch(Result) + { + case EAsyncLoadingResult::Failed: + { + NMT_MSG_CHECKF(0, "Failed LoadLevel: %s", *PackageName.ToString()); + break; + } + case EAsyncLoadingResult::Succeeded: + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(OuterObject); + UGameplayStatics::OpenLevel(World, PackageName); + break; + } + case EAsyncLoadingResult::Canceled: + { + NMT_MSG_ENSURE(0, "Canceled LoadLevel: %s", *PackageName.ToString()); + break; + } + default: NMT_CHECKF(0); + } +} + +FName UStageManager::GetLevelDataRowName(const FStageProperties StageProperties) +{ + FString ContentType = FROM_INT(StaticCast(EContentType::Stage)); + + uint8 StageNumber = StaticCast(StageProperties.StageNumber); + FString Stage = StageNumber < 1000 ? StageNumber < 100 ? StageNumber < 10 ? + JOIN_STRINGS(TEXT(""), TEXT("000"), FROM_INT(StageNumber)) : + JOIN_STRINGS(TEXT(""), TEXT("00"), FROM_INT(StageNumber)) : + JOIN_STRINGS(TEXT(""), TEXT("0"), FROM_INT(StageNumber)) : + JOIN_STRINGS(TEXT(""), FROM_INT(StageNumber)); + + FName Ret = JOIN_STRINGS(TEXT(""), ContentType, Stage); + + return Ret; +} + +void UStageManager::ReleaseManager() +{ + OuterObject = nullptr; +} diff --git a/Source/ProjectT/System/Core/Managers/StageManager.h b/Source/ProjectT/System/Core/Managers/StageManager.h new file mode 100644 index 0000000..9ccf0bb --- /dev/null +++ b/Source/ProjectT/System/Core/Managers/StageManager.h @@ -0,0 +1,78 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateStructStage.h" +#include "UObject/Object.h" +#include "StageManager.generated.h" + +struct FStage; +enum class EStage : uint8; + +USTRUCT(Blueprintable) +struct FStageProperties +{ + GENERATED_BODY() + + FStageProperties() : + StageNumber(0){} + + int32 StageNumber; +}; + +USTRUCT(Blueprintable) +struct FStageInfo +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly) + FName RowName; + + UPROPERTY(BlueprintReadOnly) + FStageProperties StageProperties; + + UPROPERTY(BlueprintReadOnly) + FStage StageData; +}; + +DECLARE_DELEGATE_OneParam(FOnLevelLoadSuccess, const FString&); +UCLASS() +class PROJECTT_API UStageManager : public UObject +{ + GENERATED_BODY() + + using StageData = TPair; + +public: + UStageManager(); + void ReleaseManager(); + void InitializeManager(const UObject* WorldObjectContext, const FString& LevelName); + void NextLevelLoad(); + int32 GetMaxStage() const; + + UFUNCTION(BlueprintCallable) + void PrepareLevelLoad(EStage StageType, float FadeDuration = 1.0f, float FadeDelay = 1.0f); + + UFUNCTION(BlueprintCallable) + void ForceLoadLevel(EStage StageType); + + UFUNCTION(BlueprintCallable) + FORCEINLINE FStageInfo GetCurrentStageInfo() { return CurrentStageInfo; } + +private: + void PackageLevelLoaded(const FName& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result); + void GetStagePath(EStage StageType, FString& NextStagePath); + void GetStageData(const FString& LevelName, StageData& OutData) const; + FName GetLevelDataRowName(FStageProperties StageProperties); + +private: + UPROPERTY() + TObjectPtr OuterObject; + int32 MaxStageNumber; + FStageInfo CurrentStageInfo; + FString SaveLevelPath; + FString LobbyPath; + FString SelectMapPath; + FString IntroPath; +}; diff --git a/Source/ProjectT/System/Core/Mouse/LinearVisualObject.cpp b/Source/ProjectT/System/Core/Mouse/LinearVisualObject.cpp new file mode 100644 index 0000000..1ff98a1 --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/LinearVisualObject.cpp @@ -0,0 +1,74 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LinearVisualObject.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" + +ALinearVisualObject::ALinearVisualObject() +{ + PrimaryActorTick.bCanEverTick = true; + AimSceneRootComponent = CreateDefaultSubobject(TEXT("AimSceneRootComponent")); + AimSceneComponent = CreateDefaultSubobject(TEXT("AimSceneComponent")); + AimMeshComponent = CreateDefaultSubobject(TEXT("AimMeshComponent")); + AimTipSceneComponent = CreateDefaultSubobject(TEXT("AimTipSceneComponent")); + AimTipMeshComponent = CreateDefaultSubobject(TEXT("AimTipMeshComponent")); + + AimSceneComponent->SetupAttachment(AimSceneRootComponent); + AimSceneComponent->SetRelativeLocation(FVector(0.f, 0.f, -49.9f)); + + AimMeshComponent->SetupAttachment(AimSceneComponent); + AimMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + AimMeshComponent->CastShadow = false; + AimMeshComponent->SetHiddenInGame(true); + + AimTipSceneComponent->SetupAttachment(AimSceneComponent); + AimTipSceneComponent->SetRelativeLocation(FVector(100.f, 0.f, 0.f)); + AimTipMeshComponent->SetupAttachment(AimTipSceneComponent); + AimTipMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + AimTipMeshComponent->CastShadow = false; + AimTipMeshComponent->SetHiddenInGame(true); + AimTipMeshComponent->SetUsingAbsoluteScale(true); +} + +void ALinearVisualObject::BeginPlay() +{ + Super::BeginPlay(); + SetActorTickEnabled(false); +} + +void ALinearVisualObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ALinearVisualObject::RefreshCursorHitResult_Implementation(FHitResult InHitResult) +{ + IMouseInteraction::RefreshCursorHitResult_Implementation(InHitResult); + CursorHitResult = InHitResult; + FRotator LocCursorRotator(FRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), CursorHitResult.Location).Yaw, 0.f)); + AimSceneComponent->SetWorldRotation(LocCursorRotator); + float LocRatio = (CursorHitResult.Distance / 100.f) - 0.1f; + AimSceneComponent->SetRelativeScale3D(FVector(LocRatio, 1.f, 1.f)); + AimTipMeshComponent->SetRelativeLocation(FVector(-20.f / LocRatio, 0.f, 0.f)); +} + +void ALinearVisualObject::InitializeLinearObject() +{ + if(AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(this)) + { + if(ACorePlayerCharacter* LocPlayerCharacter = LocGameMode->GetPlayerCharacter()) + { + AttachToActor(LocPlayerCharacter, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + } + } +} + +void ALinearVisualObject::SetAimVisibility(const bool InbVisible) +{ + AimMeshComponent->SetHiddenInGame(!InbVisible); + AimTipMeshComponent->SetHiddenInGame(!InbVisible); +} + diff --git a/Source/ProjectT/System/Core/Mouse/LinearVisualObject.h b/Source/ProjectT/System/Core/Mouse/LinearVisualObject.h new file mode 100644 index 0000000..330d9e1 --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/LinearVisualObject.h @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectT/System/Core/Interfaces/MouseInteraction.h" +#include "LinearVisualObject.generated.h" + +UCLASS() +class PROJECTT_API ALinearVisualObject : public AActor, public IMouseInteraction +{ + GENERATED_BODY() + +public: + ALinearVisualObject(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void RefreshCursorHitResult_Implementation(FHitResult InHitResult) override; + void InitializeLinearObject(); + void SetAimVisibility(const bool InbVisible); + +protected: + FHitResult CursorHitResult; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimSceneRootComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimSceneComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimTipSceneComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimTipMeshComponent; +}; diff --git a/Source/ProjectT/System/Core/Mouse/Mouse.cpp b/Source/ProjectT/System/Core/Mouse/Mouse.cpp new file mode 100644 index 0000000..cc9c0fa --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/Mouse.cpp @@ -0,0 +1,261 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Mouse.h" + +#include "LinearVisualObject.h" +#include "ParabolaVisualObject.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/MouseInteraction.h" + +UMouse::UMouse() : + bTickEnabled(false), + bMouseTracing(false), + Range(0), + CurrentResultType(), + LinearTraceQuery(), + MouseTraceQuery(), + StandardActor(nullptr), + CurrentPlayerController(nullptr) +{ + OnConstruct(); +} + +void UMouse::Tick(float DeltaTime) +{ + if(bMouseTracing) + { + FHitResult LocHitResult; + switch(CurrentResultType) + { + case EMouseResultType::Linear : + { + LocHitResult = GetLinearCalibrateHitResult(); + IMouseInteraction::Execute_RefreshCursorHitResult(LinearVisualObject, LocHitResult); + break; + } + case EMouseResultType::Parabola : + { + LocHitResult = GetParabolaCalibrateHitResult(); + IMouseInteraction::Execute_RefreshCursorHitResult(ParabolaVisualObject, LocHitResult); + break; + } + default: NMT_LOG("ResultType None") break; + } + for(AActor* LocAffectActor : AffectActors) + { + IMouseInteraction::Execute_RefreshCursorHitResult(LocAffectActor, LocHitResult); + } + } +} + +TStatId UMouse::GetStatId() const +{ + return TStatId(); +} + +bool UMouse::IsTickable() const +{ + return bTickEnabled; +} + +void UMouse::SetTickEnabled(const bool InbEnabled) +{ + bTickEnabled = InbEnabled; +} + +void UMouse::InitializeMouse() +{ + if(UWorld* LocWorld = UGlobalUtilsLibrary::GetValidWorld(this)) + { + if(APlayerController* LocGetController = UGameplayStatics::GetPlayerController(LocWorld,0)) + { + CurrentPlayerController = LocGetController; + LinearTraceQuery = UEngineTypes::ConvertToTraceType(ECC_GameTraceChannel3); + MouseTraceQuery = UEngineTypes::ConvertToTraceType(ECC_GameTraceChannel1); + + LinearVisualObject = LocWorld->SpawnActor(LinearVisualObjectClass); + LinearVisualObject->InitializeLinearObject(); + + ParabolaVisualObject = LocWorld->SpawnActor(ParabolaVisualObjectClass); + ParabolaVisualObject->InitializeParabolaObject(); + } + } +} + +void UMouse::OnConstruct() +{ + //TODO : Edit Path Relative + FString LocTempPath = "/Script/Engine.Blueprint'/Game/System/Core/Mouse/Blueprints/BP_LinearVisualObject.BP_LinearVisualObject'"; + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(LocTempPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + LinearVisualObjectClass = LoadedClass; + LoadedClass = nullptr; + + LocTempPath = "/Script/Engine.Blueprint'/Game/System/Core/Mouse/Blueprints/BP_ParabolaVisualObject.BP_ParabolaVisualObject'"; + ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(LocTempPath); + LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass); + ParabolaVisualObjectClass = LoadedClass; +} + +void UMouse::OnEndPlay() +{ + SetTickEnabled(false); +} + +void UMouse::AimTracing(bool InbStart, AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const float InAffectRange, const EMouseResultType InResultType, bool InbPathVisible) +{ + if(InbStart) + { + StandardActor = InStandardActor; + AffectActors = InAffectActors; + Range = InRange; + CurrentResultType = InResultType; + bMouseTracing = true; + SetTickEnabled(true); + switch(InResultType) + { + case EMouseResultType::Parabola: + { + ParabolaVisualObject->SetAimVisibility(true, InbPathVisible, InAffectRange); + break; + } + case EMouseResultType::Linear: + { + LinearVisualObject->SetAimVisibility(true); + break; + } + default: NMT_LOG("MouseHitResult Type None"); + } + } + else + { + ParabolaVisualObject->SetAimVisibility(false); + LinearVisualObject->SetAimVisibility(false); + SetTickEnabled(false); + bMouseTracing = false; + StandardActor = nullptr; + AffectActors.Empty(); + Range = 0.f; + CurrentResultType = EMouseResultType::None; + } +} + +FHitResult UMouse::GetCursorHitResult(AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const EMouseResultType InResultType) +{ + StandardActor = InStandardActor; + AffectActors = InAffectActors; + Range = InRange; + FHitResult LocHitResult; + switch(InResultType) + { + case EMouseResultType::Linear : + { + LocHitResult = GetLinearCalibrateHitResult(); + break; + } + case EMouseResultType::Parabola : + { + LocHitResult = GetParabolaCalibrateHitResult(); + break; + } + default: NMT_LOG("ResultType None") break; + } + return LocHitResult; +} + +FHitResult UMouse::GetParabolaCalibrateHitResult() +{ + FHitResult LocCursorHitResult; + CurrentPlayerController->GetHitResultUnderCursorByChannel(MouseTraceQuery, true, MouseCursorHitResult); + if(MouseCursorHitResult.bBlockingHit) + { + float LocCursorDistance = FVector::Dist2D(StandardActor->GetActorLocation(), MouseCursorHitResult.Location); + float LocTraceLength = LocCursorDistance > Range ? LocTraceLength = Range : LocTraceLength = LocCursorDistance; + FVector LocHitForward(MouseCursorHitResult.Location.X, MouseCursorHitResult.Location.Y, StandardActor->GetActorLocation().Z); + LocHitForward = LocHitForward - StandardActor->GetActorLocation(); + LocHitForward.Normalize(); + TArray LocIgnoreActors; + LocIgnoreActors.Add(StandardActor); + + FHitResult LocTopDownHitResult; + UKismetSystemLibrary::LineTraceSingle(this, FVector(0.f, 0.f, 300.f) + StandardActor->GetActorLocation() + LocHitForward * LocTraceLength, + FVector(0.f, 0.f, -100.f) + StandardActor->GetActorLocation() + LocHitForward * LocTraceLength, LinearTraceQuery, false, LocIgnoreActors, + EDrawDebugTrace::None, LocTopDownHitResult, true); + if(LocTopDownHitResult.bBlockingHit) + { + FHitResult LocWallHitResult; + TArray> LocWallObjectType; + LocWallObjectType.Add(UEngineTypes::ConvertToObjectType(ECC_GameTraceChannel4)); + UKismetSystemLibrary::LineTraceSingleForObjects(this, StandardActor->GetActorLocation(), StandardActor->GetActorLocation() + LocHitForward * LocTraceLength, LocWallObjectType, false, LocIgnoreActors, + EDrawDebugTrace::None, LocWallHitResult, true); + if(LocWallHitResult.bBlockingHit) + { + LocTopDownHitResult.Component = LocWallHitResult.Component; + LocTopDownHitResult.Location = LocWallHitResult.Location; + LocTopDownHitResult.Location.Z = MouseCursorHitResult.Location.Z; + LocTraceLength = LocWallHitResult.Distance; + } + + } + TArray LocPropHitResults; + TArray> LocPropObjectType; + LocPropObjectType.Add(UEngineTypes::ConvertToObjectType(ECC_GameTraceChannel6)); + UKismetSystemLibrary::LineTraceMultiForObjects(this, StandardActor->GetActorLocation(), StandardActor->GetActorLocation() + LocHitForward * LocTraceLength, LocPropObjectType, false, LocIgnoreActors, + EDrawDebugTrace::None, LocPropHitResults, true); + if(LocPropHitResults.Num() > 0) + { + if(LocTopDownHitResult.Component->GetCollisionProfileName() == TEXT("Ground")||LocTopDownHitResult.Component->GetCollisionProfileName() == TEXT("Wall")) + { + LocCursorHitResult = LocTopDownHitResult; + } + else + { + LocPropHitResults.Last().Location.Z = MouseCursorHitResult.Location.Z; + LocCursorHitResult = LocPropHitResults.Last(); + } + } + else + { + LocTopDownHitResult.Location.Z = MouseCursorHitResult.Location.Z; + LocCursorHitResult = LocTopDownHitResult; + } + LastUpdatedHitResult = LocCursorHitResult; + } + else + { + LocCursorHitResult = LastUpdatedHitResult; + } + return LocCursorHitResult; +} + +FHitResult UMouse::GetLinearCalibrateHitResult() +{ + FHitResult LocCursorHitResult; + CurrentPlayerController->GetHitResultUnderCursorByChannel(MouseTraceQuery, true, MouseCursorHitResult); + if(MouseCursorHitResult.bBlockingHit) + { + FVector LocHitForward(MouseCursorHitResult.Location.X, MouseCursorHitResult.Location.Y, StandardActor->GetActorLocation().Z); + LocHitForward = LocHitForward - StandardActor->GetActorLocation(); + LocHitForward.Normalize(); + TArray LocIgnoreActors; + LocIgnoreActors.Add(StandardActor); + UKismetSystemLibrary::LineTraceSingle(this, StandardActor->GetActorLocation(), StandardActor->GetActorLocation() + LocHitForward * Range, + LinearTraceQuery, false, LocIgnoreActors, EDrawDebugTrace::None, LocCursorHitResult, true); + if(!LocCursorHitResult.bBlockingHit) + { + LocCursorHitResult.Location = MouseCursorHitResult.Location; + LocCursorHitResult.Distance = Range; + } + LastUpdatedHitResult = LocCursorHitResult; + } + else + { + LocCursorHitResult = LastUpdatedHitResult; + } + return LocCursorHitResult; +} \ No newline at end of file diff --git a/Source/ProjectT/System/Core/Mouse/Mouse.h b/Source/ProjectT/System/Core/Mouse/Mouse.h new file mode 100644 index 0000000..ff953e2 --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/Mouse.h @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "Mouse.generated.h" + +UENUM(BlueprintType) +enum class EMouseResultType: uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Linear UMETA(DisplayName = "Linear"), + Parabola UMETA(DisplayName = "Parabola") +}; + +UCLASS() +class PROJECTT_API UMouse : public UObject, public FTickableGameObject +{ + GENERATED_BODY() + +public: + UMouse(); + virtual void Tick(float DeltaTime) override; + virtual TStatId GetStatId() const override; + virtual bool IsTickable() const override; + void SetTickEnabled(bool InbEnabled); + void InitializeMouse(); + void OnConstruct(); + void OnEndPlay(); + + void AimTracing(bool InbStart, AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const float InAffectRange, const EMouseResultType InResultType, bool InbPathVisible = true); + FHitResult GetCursorHitResult(AActor* InStandardActor, const TArray& InAffectActors, const float InRange, const EMouseResultType InResultType); + +protected: + FHitResult GetParabolaCalibrateHitResult(); + FHitResult GetLinearCalibrateHitResult(); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr LinearVisualObject; + + UPROPERTY(VisibleAnywhere,BlueprintReadWrite) + TSubclassOf LinearVisualObjectClass; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr ParabolaVisualObject; + + UPROPERTY(VisibleAnywhere,BlueprintReadWrite) + TSubclassOf ParabolaVisualObjectClass; + +private: + bool bTickEnabled; + bool bMouseTracing; + float Range; + EMouseResultType CurrentResultType; + ETraceTypeQuery LinearTraceQuery; + ETraceTypeQuery MouseTraceQuery; + FHitResult MouseCursorHitResult; + FHitResult LastUpdatedHitResult; + + UPROPERTY() + AActor* StandardActor; + + UPROPERTY() + TArray AffectActors; + + UPROPERTY() + APlayerController* CurrentPlayerController; +}; diff --git a/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.cpp b/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.cpp new file mode 100644 index 0000000..b1a9d3f --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.cpp @@ -0,0 +1,66 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ParabolaVisualObject.h" + +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" + +AParabolaVisualObject::AParabolaVisualObject() +{ + PrimaryActorTick.bCanEverTick = true; + AimSceneComponent = CreateDefaultSubobject(TEXT("AimSceneComponent")); + ParabolaMeshComponent = CreateDefaultSubobject(TEXT("ParabolaMeshComponent")); + AffectAreaMeshComponent = CreateDefaultSubobject(TEXT("AffectAreaMeshComponent")); + + ParabolaMeshComponent->SetupAttachment(AimSceneComponent); + ParabolaMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + ParabolaMeshComponent->SetHiddenInGame(true); + AffectAreaMeshComponent->SetCollisionEnabled(ECollisionEnabled::Type::NoCollision); + AffectAreaMeshComponent->SetHiddenInGame(true); +} + +void AParabolaVisualObject::BeginPlay() +{ + Super::BeginPlay(); + SetActorTickEnabled(false); +} + +void AParabolaVisualObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AParabolaVisualObject::RefreshCursorHitResult_Implementation(FHitResult InHitResult) +{ + IMouseInteraction::RefreshCursorHitResult_Implementation(InHitResult); + CursorHitResult = InHitResult; + FRotator LocCursorRotator(FRotator(0.f, UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), CursorHitResult.Location).Yaw, 0.f)); + AimSceneComponent->SetWorldRotation(LocCursorRotator); + FVector LocEndPoint = CursorHitResult.Location; + AffectAreaMeshComponent->SetWorldLocation(LocEndPoint + FVector(0, 0, 0.1)); + FVector LocCalibLocation(GetActorLocation().X, GetActorLocation().Y, LocEndPoint.Z); + float LocFinalDistance = FVector::Distance(LocCalibLocation, LocEndPoint); + ParabolaMeshComponent->SetWorldScale3D(FVector(LocFinalDistance / 100.f, 1.f, 1.1f)); +} + +void AParabolaVisualObject::InitializeParabolaObject() +{ + if(AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(this)) + { + if(ACorePlayerCharacter* LocPlayerCharacter = LocGameMode->GetPlayerCharacter()) + { + AttachToActor(LocPlayerCharacter, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + } + } +} + +void AParabolaVisualObject::SetAimVisibility(bool InbVisible, bool InbPathVisible, float InAffectRange) +{ + if(InbVisible) AffectAreaMeshComponent->SetWorldScale3D(FVector(InAffectRange / 50.f)); + AffectAreaMeshComponent->SetHiddenInGame(!InbVisible); + if(InbPathVisible) ParabolaMeshComponent->SetHiddenInGame(!InbVisible); +} + diff --git a/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.h b/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.h new file mode 100644 index 0000000..7e7f56c --- /dev/null +++ b/Source/ProjectT/System/Core/Mouse/ParabolaVisualObject.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectT/System/Core/Interfaces/MouseInteraction.h" +#include "ParabolaVisualObject.generated.h" + +UCLASS() +class PROJECTT_API AParabolaVisualObject : public AActor, public IMouseInteraction +{ + GENERATED_BODY() + +public: + AParabolaVisualObject(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void RefreshCursorHitResult_Implementation(FHitResult InHitResult) override; + void InitializeParabolaObject(); + void SetAimVisibility(bool InbVisible, bool InbPathVisible = true, float InAffectRange = 0.f); + +protected: + FHitResult CursorHitResult; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AimSceneComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr ParabolaMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TObjectPtr AffectAreaMeshComponent; +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.cpp new file mode 100644 index 0000000..bd415d9 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.cpp @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CeilObject.h" + +void ACeilObject::ActivateCeil(bool bActivate) +{ + bActivate ? IVisualizable::Execute_ShowVisual(this) : IVisualizable::HideVisual_Implementation(); +} + +void ACeilObject::ShowVisual_Implementation() +{ + Super::ShowVisual_Implementation(); +} + +void ACeilObject::HideVisual_Implementation() +{ + Super::HideVisual_Implementation(); +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.h new file mode 100644 index 0000000..e829a23 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CeilObject.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreObject.h" +#include "CeilObject.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ACeilObject : public ACoreObject +{ + GENERATED_BODY() + +public: + void ActivateCeil(bool bActivate); + +protected: + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + +public: + +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.cpp new file mode 100644 index 0000000..bb6a40b --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.cpp @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreInteractionObject.h" + +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" + +ACoreInteractionObject::ACoreInteractionObject() : + CurrentOwner(nullptr), + SuccessProgressTime(0.f), + CurrentProgressRatio(0.f), + CurrentProgressTime(0.f) +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ACoreInteractionObject::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreInteractionObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ACoreInteractionObject::TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) +{ +} + +void ACoreInteractionObject::ShowVisual_Implementation() +{ + SetVisibility(true); +} + +void ACoreInteractionObject::HideVisual_Implementation() +{ + ResetToDefault(); +} + +void ACoreInteractionObject::SetVisibility(bool InbVisible) +{ +} + +void ACoreInteractionObject::ResetToDefault() +{ + SetVisibility(false); + StartProgressTime(false); + ProgressTimerHandle.Invalidate(); + CurrentProgressTime = 0.f; + CurrentProgressRatio = 0.f; + CurrentOwner = nullptr; +} + +void ACoreInteractionObject::StartProgressTime(bool InbStart) +{ + if (InbStart) + { + if (!GetWorld()->GetTimerManager().IsTimerActive(ProgressTimerHandle)) + GetWorld()->GetTimerManager().SetTimer(ProgressTimerHandle, this, &ACoreInteractionObject::SetProgressPercent, 1 / 60.f, true); + } + else + { + GetWorld()->GetTimerManager().ClearTimer(ProgressTimerHandle); + ProgressTimerHandle.Invalidate(); + } +} + +EInteractionObjectType ACoreInteractionObject::GetInteractionObjectType_Implementation() +{ + return InteractionObjectType; +} + +void ACoreInteractionObject::SetProgressPercent() +{ + CurrentProgressTime = CurrentProgressTime + 1.f / 60.f; + CurrentProgressRatio = CurrentProgressTime / SuccessProgressTime; + if (CurrentProgressRatio > 1.f) + { + GetWorld()->GetTimerManager().ClearTimer(ProgressTimerHandle); + ProgressTimerHandle.Invalidate(); + //CurrentOwner->AcceptObjectInteraction_Implementation(true, true); + ResetToDefault(); + } +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h new file mode 100644 index 0000000..cb60051 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h @@ -0,0 +1,49 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreObject.h" +#include "GameFramework/Actor.h" +#include "ProjectT/System/Core/Interfaces/ObjectInteractionControl.h" +#include "ProjectT/System/Core/Interfaces/Visualizable.h" +#include "CoreInteractionObject.generated.h" + + +UCLASS() +class PROJECTT_API ACoreInteractionObject : public ACoreObject, public IObjectInteractionControl +{ + GENERATED_BODY() + +public: + ACoreInteractionObject(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) override; + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + virtual void SetVisibility(bool InbVisible); + void ResetToDefault(); + void StartProgressTime(bool InbStart); + virtual EInteractionObjectType GetInteractionObjectType_Implementation() override; + +protected: + void SetProgressPercent(); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction, meta = (AllowPrivateAccess = "true")) + class ACombatCharacter* CurrentOwner; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction, meta = (AllowPrivateAccess = "true")) + EInteractionObjectType InteractionObjectType; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + float SuccessProgressTime; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) + float CurrentProgressRatio; + +private: + float CurrentProgressTime; + FTimerHandle ProgressTimerHandle; +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.cpp new file mode 100644 index 0000000..cd419b0 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreObject.h" + + +ACoreObject::ACoreObject() +{ + PrimaryActorTick.bCanEverTick = true; + + MeshSceneComponent = CreateDefaultSubobject(TEXT("MeshSceneComponent")); + MeshSceneComponent->SetupAttachment(RootComponent); +} + +void ACoreObject::ShowVisual_Implementation() +{ + IVisualizable::ShowVisual_Implementation(); +} + +void ACoreObject::HideVisual_Implementation() +{ + IVisualizable::HideVisual_Implementation(); +} + +void ACoreObject::BeginPlay() +{ + Super::BeginPlay(); +} + +void ACoreObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.h new file mode 100644 index 0000000..5375827 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/CoreObject.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectT/System/Core/Interfaces/Visualizable.h" +#include "CoreObject.generated.h" + +UCLASS() +class PROJECTT_API ACoreObject : public AActor, public IVisualizable +{ + GENERATED_BODY() + +public: + ACoreObject(); + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + virtual void Tick(float DeltaTime) override; + + FName GetObjectRowName() const { return ObjectRowName; } + +protected: + virtual void BeginPlay() override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TObjectPtr MeshSceneComponent; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + FName ObjectRowName; +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.cpp new file mode 100644 index 0000000..f241425 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.cpp @@ -0,0 +1,49 @@ + +#include "ExitPoint.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" + +AExitPoint::AExitPoint() : + OnCompleteExitPoint(nullptr) +{ + +} + +void AExitPoint::TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) +{ + Super::TryInteraction(InSendData, Callback); +} + +void AExitPoint::ActivateExitPoint_Implementation() +{ + StartAction(); +} + +void AExitPoint::StartAction_Implementation() +{ + +} + +void AExitPoint::EndAction_Implementation() +{ + if(OnCompleteExitPoint.IsBound()) + OnCompleteExitPoint.Execute(); +} + +void AExitPoint::ShowVisual_Implementation() +{ +} + +void AExitPoint::HideVisual_Implementation() +{ +} + +void AExitPoint::CompleteExitPoint(const FOnCompleteExitPoint& Callback) +{ + if(!Callback.IsBound()) return; + OnCompleteExitPoint = Callback; +} + +void AExitPoint::BeginPlay() +{ + Super::BeginPlay(); +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.h b/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.h new file mode 100644 index 0000000..f47e396 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/ExitPoint.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CoreMinimal.h" +#include "CoreInteractionObject.h" +#include "ExitPoint.generated.h" + +DECLARE_DELEGATE(FOnCompleteExitPoint) +UCLASS() +class PROJECTT_API AExitPoint : public ACoreInteractionObject +{ + GENERATED_BODY() + +public: + AExitPoint(); + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) override; + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + + UFUNCTION(BlueprintNativeEvent) + void ActivateExitPoint(); + + void CompleteExitPoint(const FOnCompleteExitPoint& Callback); + +protected: + virtual void BeginPlay() override; + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + void StartAction(); + + UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + void EndAction(); + +private: + FOnCompleteExitPoint OnCompleteExitPoint; +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.cpp new file mode 100644 index 0000000..4711cb0 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.cpp @@ -0,0 +1,400 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "ItemObject.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/Data/Gen/GenerateStructItemSet.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateStructMeshList.h" + +#if WITH_EDITOR +#include "Components/TextRenderComponent.h" +#include "ProjectT/Data/Gen/GenerateStructLocalization.h" +#endif + + + +AItemObject::AItemObject() +{ + PrimaryActorTick.bCanEverTick = true; + InteractionObjectType = EInteractionObjectType::Item; + + DefaultStaticMeshComponent = CreateDefaultSubobject(TEXT("DefaultStaticMeshComponent")); + DefaultStaticMeshComponent->SetupAttachment(MeshSceneComponent); + DefaultDynamicMeshComponent = CreateDefaultSubobject(TEXT("DefaultDynamicMeshComponent")); + DefaultDynamicMeshComponent->SetupAttachment(MeshSceneComponent); + +#if WITH_EDITOR + if(!GEditor) return; + ItemDebugTEXT = CreateEditorOnlyDefaultSubobject(TEXT("DEBUG")); + ItemDebugTEXT->SetupAttachment(MeshSceneComponent); + ItemSetDT = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::ItemSet); + ItemSetDT->OnDataTableChanged().AddUObject(this, &AItemObject::ItemSetOnlyEditor); +#endif +} + +void AItemObject::BeginPlay() +{ + Super::BeginPlay(); + + if(NMT_ENSURE(SavedItemLabel > 0)) + SetItemByWeightFromTable(SavedItemLabel); + +#if WITH_EDITOR + if(!GEditor) return; + ItemDebugTEXT->DestroyComponent(); + ItemDataForEditor.Empty(); +#endif +} + +void AItemObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AItemObject::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); + +#if WITH_EDITOR + if(!GEditor) return; + const FString LabelRowName = *GetActorLabel(); + if(LabelRowName.IsNumeric()) + { + SavedItemLabel = FCString::Atoi(*LabelRowName); + ItemSetOnlyEditor(); + } +#endif +} + +void AItemObject::TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) +{ + Super::TryInteraction(InSendData, Callback); + Callback.Execute(EInteractionResultType::SuccessComplete); +} + +void AItemObject::SuccessCompleteAction_Implementation() +{ + Super::SuccessCompleteAction_Implementation(); +} + +void AItemObject::SetVisibility(bool InbVisible) +{ + Super::SetVisibility(InbVisible); + DefaultStaticMeshComponent->SetRenderCustomDepth(InbVisible); + DefaultDynamicMeshComponent->SetRenderCustomDepth(InbVisible); +} + +void AItemObject::ShowVisual_Implementation() +{ + Super::ShowVisual_Implementation(); +} + +void AItemObject::HideVisual_Implementation() +{ + Super::HideVisual_Implementation(); +} + +void AItemObject::ItemIdle_Implementation(EItemTypes TargetItem) +{ +} + +void AItemObject::ItemFlyUP_Implementation() +{ +} + +void AItemObject::ItemFlyToUI_Implementation() +{ +} + +FItem AItemObject::GetItemData() +{ + return ItemData; +} + +void AItemObject::BeginStateItem() +{ + ItemInitLocation = GetActorLocation(); + switch(ItemType) + { + case EItemTypes::None: + { + break; + } + case EItemTypes::Gimick: + { + ItemIdle(EItemTypes::Gimick); + break; + } + case EItemTypes::Usable: + { + ItemIdle(EItemTypes::Usable); + break; + } + case EItemTypes::Collection: + { + ItemIdle(EItemTypes::Collection); + break; + } + default: + break; + } +} + +EItemTypes AItemObject::GetItemType() +{ + return ItemType; +} + +void AItemObject::SetItem(const FName& ItemRowName) +{ + if(!ObjectRowName.IsNone()) return; + + UDataTable* ItemDT = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Item); + FItem* FindItem = ItemDT->FindRow(ItemRowName, FString()); + + if(!FindItem) NMT_MSG_CHECKF(0, "Can't find Item ID %s from DT_ItemSet!", *ItemRowName.ToString()); + + ItemData = *FindItem; + ObjectRowName = ItemRowName; + + UDataTable* MLSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::MeshList); + FMeshList* ItemMeshData = MLSTable->FindRow(FROM_INT(ItemData.iItemMeshId), TEXT("FMeshList")); + if(!ItemMeshData) return; + + if(ItemMeshData->sMeshPath.Contains(FString("StaticMesh"))) + { + UStaticMesh* ItemStaticMesh = UAssetUtilsLibrary::GetStaticMeshFromPath(ItemMeshData->sMeshPath); + if(!ItemStaticMesh) return; + DefaultDynamicMeshComponent->SetSkeletalMesh(nullptr); + DefaultStaticMeshComponent->SetStaticMesh(ItemStaticMesh); + } + + else if(ItemMeshData->sMeshPath.Contains(FString("SkeletalMesh"))) + { + USkeletalMesh* ItemDynamicMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(ItemMeshData->sMeshPath); + if(!ItemDynamicMesh) return; + DefaultStaticMeshComponent->SetStaticMesh(nullptr); + DefaultDynamicMeshComponent->SetSkeletalMesh(ItemDynamicMesh); + } + + UEnum* EnumItemType = StaticEnum(); + if(!EnumItemType) return; + int32 EnumIDX = EnumItemType->GetValueByName(*ItemData.sItemType); + if(EnumIDX == INDEX_NONE) return; + ItemType = static_cast(EnumIDX); + + BeginStateItem(); +} + +void AItemObject::SetItemByWeightFromTable(int32 GroupID) +{ + TArray ItemSetList; + TArray FindItemIDs; + ItemSetDT = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::ItemSet); + ItemSetDT->GetAllRows(TEXT(""), ItemSetList); + + for(auto FindSet : ItemSetList) + { + if(FindSet->iItemGroupId == GroupID) + { + for(int i = 1; i <= FindSet->iProbWeight; i++) + { + FindItemIDs.Add(FindSet->iItemId); + } + } + } + + if(FindItemIDs.Num() == 0) return; + + UGlobalUtilsLibrary::ShuffleArray(FindItemIDs); + const FName DecidedRowName = FName(FString::FromInt(FindItemIDs[0])); + SetItem(DecidedRowName); +} + +void AItemObject::ObtainItem_Implementation() +{ + if(!bObtain) + { + bObtain = true; + SetActorEnableCollision(false); + switch(ItemType) + { + case EItemTypes::None: + { + break; + } + case EItemTypes::Gimick: + { + ItemFlyUP(); + break; + } + case EItemTypes::Usable: + { + ItemFlyUP(); + break; + } + case EItemTypes::Collection: + { + ItemFlyToUI(); + break; + } + default: + break; + } + } +} + +FName AItemObject::GetItemRowName_Implementation() +{ + return GetObjectRowName(); +} + +void AItemObject::UseItem() +{ + NOT_IMPLEMENTED() +} + +#if WITH_EDITOR +void AItemObject::ItemSetOnlyEditor() +{ + ItemDataForEditor.Empty(); + DrawItemDebugText(); + SetItemMeshEditor(); +} +void AItemObject::DrawItemDebugText() +{ + ItemDebugTEXT->SetTextRenderColor(FColor(0, 255, 0)); + + if(SavedItemLabel != 0) + { + ItemDebugTEXT->SetHorizontalAlignment(EHorizTextAligment::EHTA_Center); + + TArray ItemSetList; + TSet FindItemIDs; + TMap LocItemData; + int32 SumWeight = 0; + + ItemSetDT->GetAllRows(TEXT(""), ItemSetList); + LocItemData.Empty(); + for(FItemSet* FindSet : ItemSetList) + { + if(FindSet->iItemGroupId == SavedItemLabel) + { + LocItemData.Add(FindSet->iItemId, FindSet->iProbWeight); + SumWeight += FindSet->iProbWeight; + FindItemIDs.Add(FindSet->iItemId); + } + } + + if(FindItemIDs.Num() == 0) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 0, 0)); + ItemDebugTEXT->SetText(FText::FromString("NONE Data")); + return; + } + + if(SumWeight <= 0) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 0, 0)); + ItemDebugTEXT->SetText(FText::FromString("Weight Is Zero : NeverSetItem")); + return; + } + + FString ItemDebugString = FString(); + UDataTable* ItemDT = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Item); + + for(int32 Item : FindItemIDs) + { + FLocalization LocString = {}; + FItem LocItem = {}; + float Probability = 0.f; + FName DecidedItem = FName(FString::FromInt(Item)); + int32 LocItemRowName = FCString::Atoi(*DecidedItem.ToString()); + FItem* FindItem = ItemDT->FindRow(DecidedItem, FString("Can't Find Item ID !!!!")); + + if(!FindItem) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 0, 0)); + ItemDebugTEXT->SetText(FText::FromString("Can't Find ItemID")); + return; + } + LocItem = *FindItem; + ItemDataForEditor.AddUnique(LocItem); + FName FindString = FName(FString::FromInt(LocItem.iItemNameId)); + UDataTable* StringDT = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Localization); + LocString = *(StringDT->FindRow(FindString, FString())); + + Probability = static_cast(*(LocItemData.Find(LocItemRowName))) / static_cast(SumWeight); + Probability *= 100; + + FString Result = FString::Printf(TEXT("%.2f"), Probability); + + ItemDebugString.Append(LocString.sEnglish); + ItemDebugString.Append(":"); + ItemDebugString.Append(Result); + ItemDebugString.Append("%"); + ItemDebugString.Append("\n"); + } + ItemDebugTEXT->SetText(FText::FromString(ItemDebugString)); + ItemDebugTEXT->SetWorldLocation(GetActorLocation() + FVector(0, 0, 60)); + } +} +void AItemObject::SetItemMeshEditor() +{ + DefaultStaticMeshComponent->SetStaticMesh(nullptr); + DefaultDynamicMeshComponent->SetSkeletalMesh(nullptr); + + if(ItemDataForEditor.Num() == 1) + { + FItem LocItem = ItemDataForEditor[0]; + + UDataTable* MLSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::MeshList); + FMeshList* ItemMeshData = MLSTable->FindRow(FROM_INT(LocItem.iItemMeshId), TEXT("FMeshList")); + if(!ItemMeshData) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 255, 0)); + return; + } + + + if(ItemMeshData->sMeshPath.Contains(FString("StaticMesh"))) + { + UStaticMesh* ItemStaticMesh = UAssetUtilsLibrary::GetStaticMeshFromPath(ItemMeshData->sMeshPath); + if(!ItemStaticMesh) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 255, 0)); + return; + } + DefaultStaticMeshComponent->SetStaticMesh(ItemStaticMesh); + } + + else if(ItemMeshData->sMeshPath.Contains(FString("SkeletalMesh"))) + { + USkeletalMesh* ItemDynamicMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(ItemMeshData->sMeshPath); + if(!ItemDynamicMesh) + { + ItemDebugTEXT->SetTextRenderColor(FColor(255, 255, 0)); + return; + } + DefaultDynamicMeshComponent->SetSkeletalMesh(ItemDynamicMesh); + } + } + else if(ItemDataForEditor.Num() == 0) + { + DefaultStaticMeshComponent->SetStaticMesh(nullptr); + DefaultDynamicMeshComponent->SetSkeletalMesh(nullptr); + } + else + { + UStaticMesh* EditorMesh = Cast(StaticLoadObject(UStaticMesh::StaticClass(), nullptr, TEXT("/Engine/EditorMeshes/EditorHelp.EditorHelp"))); + if(EditorMesh) + { + DefaultStaticMeshComponent->SetStaticMesh(EditorMesh); + } + } +} +#endif + diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.h new file mode 100644 index 0000000..bd466d7 --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/ItemObject.h @@ -0,0 +1,102 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreInteractionObject.h" +#include "ProjectT/Data/Gen/GenerateEnumItemTypes.h" +#include "ProjectT/Data/Gen/GenerateStructItem.h" +#include "ProjectT/System/Core/Interfaces/ItemObjectControl.h" +#include "ItemObject.generated.h" + +UCLASS() +class PROJECTT_API AItemObject : public ACoreInteractionObject, public IItemObjectControl +{ + GENERATED_BODY() + +public: + AItemObject(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) override; + virtual void SuccessCompleteAction_Implementation() override; + + virtual void SetVisibility(bool InbVisible) override; + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + virtual void ObtainItem_Implementation()override; + virtual FName GetItemRowName_Implementation()override; + + UFUNCTION(BlueprintCallable) + void SetItem(const FName& ItemRowName); + + UFUNCTION(BlueprintNativeEvent) + void ItemIdle(EItemTypes TargetItem); + + UFUNCTION(BlueprintNativeEvent) + void ItemFlyUP(); + + UFUNCTION(BlueprintNativeEvent) + void ItemFlyToUI(); + + UFUNCTION(BlueprintPure, Category = "ItemObject") + EItemTypes GetItemType(); + + FItem GetItemData(); + void BeginStateItem(); + void SetItemByWeightFromTable(int32 GroupID); + +protected: + UFUNCTION(BlueprintCallable) + virtual void UseItem(); + +private: +#if WITH_EDITOR + + UFUNCTION() + void ItemSetOnlyEditor(); + + UFUNCTION() + void DrawItemDebugText(); + + UFUNCTION() + void SetItemMeshEditor(); +#endif + +public: + UPROPERTY(BlueprintReadWrite) + FVector ItemInitLocation; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Interaction, meta = (AllowPrivateAccess = "true")) + FItem ItemData; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Interaction, meta = (AllowPrivateAccess = "true")) + EItemTypes ItemType; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TObjectPtr DefaultStaticMeshComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TObjectPtr DefaultDynamicMeshComponent; + +private: + UPROPERTY() + int32 SavedItemLabel; + + UPROPERTY() + UDataTable* ItemSetDT; + + UPROPERTY() + uint8 bObtain : 1; + +#if WITH_EDITORONLY_DATA + UPROPERTY() + TObjectPtr ItemDebugTEXT; + + UPROPERTY() + TArray ItemDataForEditor; +#endif + +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.cpp new file mode 100644 index 0000000..b03f7ff --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.cpp @@ -0,0 +1,91 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LevelCastObject.h" + +void ALevelCastObject::TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) +{ + if (LevelObjectData.iCastItemId != 0) + { + if(InSendData.RowNames.Num()>0) + { + if(InSendData.RowNames.Contains(FString::FromInt(LevelObjectData.iCastItemId))) + { + if(Callback.IsBound()) Callback.Execute(EInteractionResultType::SuccessPre); + SuccessInteraction(true); + ExecuteBindNPCEvent(); + ExecuteBindCeilEvent(); + } + else + { + if(Callback.IsBound()) Callback.Execute(EInteractionResultType::Fail); + SuccessInteraction(false); + } + } + else + { + if(Callback.IsBound()) Callback.Execute(EInteractionResultType::Fail); + SuccessInteraction(false); + } + } + else + { + if(Callback.IsBound()) Callback.Execute(EInteractionResultType::SuccessPre); + SuccessInteraction(true); + ExecuteBindNPCEvent(); + ExecuteBindCeilEvent(); + } +} + +void ALevelCastObject::SuccessPreAction_Implementation() +{ + Super::SuccessPreAction_Implementation(); +} + +void ALevelCastObject::SuccessUpdateAction_Implementation() +{ + Super::SuccessUpdateAction_Implementation(); +} + +void ALevelCastObject::SuccessCompleteAction_Implementation() +{ + Super::SuccessCompleteAction_Implementation(); +} + +void ALevelCastObject::SetVisibility(bool InbVisible) +{ + Super::SetVisibility(InbVisible); +} + +void ALevelCastObject::ShowVisual_Implementation() +{ + Super::ShowVisual_Implementation(); + + TArray ChildComponents; + for (auto Child : ChildComponents) + { + if (UPrimitiveComponent* PrimitiveComp = Cast(Child)) + { + PrimitiveComp->SetCustomDepthStencilValue(0); + } + } +} + +void ALevelCastObject::HideVisual_Implementation() +{ + Super::HideVisual_Implementation(); + + TArray ChildComponents; + for (auto Child : ChildComponents) + { + if (UPrimitiveComponent* PrimitiveComp = Cast(Child)) + { + PrimitiveComp->SetCustomDepthStencilValue(1); + } + } +} + +void ALevelCastObject::SuccessInteraction_Implementation(bool Result) +{ + +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.h new file mode 100644 index 0000000..3731abe --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelCastObject.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LevelInteractionObject.h" +#include "LevelCastObject.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ALevelCastObject : public ALevelInteractionObject +{ + GENERATED_BODY() + +public: + virtual void TryInteraction(const FInteractionData InSendData, FOnInteractionSuccess Callback) override; + virtual void SuccessPreAction_Implementation() override; + virtual void SuccessUpdateAction_Implementation() override; + virtual void SuccessCompleteAction_Implementation() override; + virtual void SetVisibility(bool InbVisible) override; + +protected: + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + + UFUNCTION(BlueprintNativeEvent) + void SuccessInteraction(bool Result); + +public: + +protected: + +private: + uint8 bCompleteInteraction : 1; + +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.cpp new file mode 100644 index 0000000..559994b --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.cpp @@ -0,0 +1,141 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LevelInteractionObject.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "Components/BoxComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "CeilObject.h" + + +ALevelInteractionObject::ALevelInteractionObject() +{ + PrimaryActorTick.bCanEverTick = true; + InteractionObjectType = EInteractionObjectType::LevelObject; + + BoxCollision = CreateDefaultSubobject(TEXT("BoxCollisionComponent")); + BoxCollision->SetupAttachment(MeshSceneComponent); +} + +void ALevelInteractionObject::BeginPlay() +{ + Super::BeginPlay(); +} + +void ALevelInteractionObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ALevelInteractionObject::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); + +#if WITH_EDITOR + const FString LabelRowName = *GetActorLabel(); + if (LabelRowName.IsNumeric()) ApplyObjectConfiguration(*LabelRowName); + + for(ACoreNpc* Npc : BindNPCs) + { + if(Npc) Npc->SetActivatedOnStart(false); + } +#endif +} + +void ALevelInteractionObject::SetVisibility(bool InbVisible) +{ + Super::SetVisibility(InbVisible); + TArray ChildComponents; + GetRootComponent()->GetChildrenComponents(true, ChildComponents); + + for (USceneComponent* Child : ChildComponents) + { + if (UPrimitiveComponent* PrimitiveComp = Cast(Child)) + { + PrimitiveComp->SetRenderCustomDepth(InbVisible); + } + } +} + +void ALevelInteractionObject::ShowVisual_Implementation() +{ + Super::ShowVisual_Implementation(); +} + +void ALevelInteractionObject::HideVisual_Implementation() +{ + Super::HideVisual_Implementation(); +} + +void ALevelInteractionObject::Destroyed() +{ + Super::Destroyed(); + +#if WITH_EDITOR + if(!BindNPCs.IsEmpty()) + { + for(ACoreNpc* Npc : BindNPCs) + { + if(Npc) Npc->SetActivatedOnStart(true); + } + } +#endif +} + +#if WITH_EDITOR +void ALevelInteractionObject::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); + + if(PropertyChangedEvent.Property && PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(ALevelInteractionObject, BindNPCs)) + { + if(!PrevSelectedNPCs.IsEmpty()) + { + for(ACoreNpc* Npc : PrevSelectedNPCs) + { + if(Npc) Npc->SetActivatedOnStart(true); + } + } + + for(ACoreNpc* Npc : BindNPCs) + { + if(Npc) Npc->SetActivatedOnStart(false); + } + PrevSelectedNPCs = BindNPCs; + } +} + +void ALevelInteractionObject::ApplyObjectConfiguration(const FName& RowName) +{ + UDataTable* LevelObjTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::LevelObject); + FLevelObject* ObjData = LevelObjTable->FindRow(RowName, TEXT("FLevelObjectList")); + if (!ObjData)return; + LevelObjectData = *ObjData; +} +#endif + +void ALevelInteractionObject::ExecuteBindNPCEvent() +{ + for(ACoreNpc* Npc : BindNPCs) + { + if(Npc) + { + Npc->ActivateCharacter(true); + } + } +} + +void ALevelInteractionObject::ExecuteBindCeilEvent() +{ + if(CeilObjects.Num() != 0) + { + for(ACeilObject* CeilObject : CeilObjects) + { + if(CeilObject) + { + CeilObject->ActivateCeil(true); + } + } + } +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.h new file mode 100644 index 0000000..270af0b --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelInteractionObject.h @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CoreInteractionObject.h" +#include "ProjectT/Data/Gen/GenerateStructLevelObject.h" +#include "ProjectT/Data/Gen/GenerateEnumLevelObjectTypes.h" +#include "LevelInteractionObject.generated.h" + +UCLASS() +class PROJECTT_API ALevelInteractionObject : public ACoreInteractionObject +{ + GENERATED_BODY() + +public: + ALevelInteractionObject(); + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetVisibility(bool InbVisible) override; + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + virtual void Destroyed() override; + + //FIXME + int32 GetCastItemID() { return LevelObjectData.iCastItemId; } +protected: + +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; + virtual void ApplyObjectConfiguration(const FName& RowName); +#endif + + void ExecuteBindNPCEvent(); + void ExecuteBindCeilEvent(); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TObjectPtr BoxCollision; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Interaction, meta = (AllowPrivateAccess = "true")) + FLevelObject LevelObjectData; + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TArray> BindNPCs; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true")) + TArray> CeilObjects; + +#if WITH_EDITORONLY_DATA + UPROPERTY() + TArray> PrevSelectedNPCs; +#endif +}; diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.cpp b/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.cpp new file mode 100644 index 0000000..235192a --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LevelTrapObject.h" + +void ALevelTrapObject::SetVisibility(bool InbVisible) +{ +} diff --git a/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.h b/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.h new file mode 100644 index 0000000..98d2a9a --- /dev/null +++ b/Source/ProjectT/System/Core/Objects/LevelObject/LevelTrapObject.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LevelInteractionObject.h" +#include "LevelTrapObject.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ALevelTrapObject : public ALevelInteractionObject +{ + GENERATED_BODY() + +public: + virtual void SetVisibility(bool InbVisible) override; + +}; diff --git a/Source/ProjectT/System/Core/SaveGame/UserSaveGame.cpp b/Source/ProjectT/System/Core/SaveGame/UserSaveGame.cpp new file mode 100644 index 0000000..764843d --- /dev/null +++ b/Source/ProjectT/System/Core/SaveGame/UserSaveGame.cpp @@ -0,0 +1,91 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "UserSaveGame.h" + +#include "Kismet/GameplayStatics.h" +#include "ProjectT/ProjectT.h" + + +const FString UUserSaveGame::SaveSlotName = TEXT("UserSaveData"); +UUserSaveGame::UUserSaveGame() +{ +} + +void UUserSaveGame::LoadUserSaveGame(UUserSaveGame*& OutSaveInstance) +{ + USaveGame* SaveGame = UGameplayStatics::LoadGameFromSlot(SaveSlotName, 0); + if(!SaveGame) + { + SaveGame = UGameplayStatics::CreateSaveGameObject(UUserSaveGame::StaticClass()); + UGameplayStatics::SaveGameToSlot(SaveGame, SaveSlotName, 0); + } + OutSaveInstance = CastChecked(SaveGame); +} + +void UUserSaveGame::SetCurrentSelectedCharacterData(const FString& InData) +{ + UUserSaveGame* SaveInstance = GetSaveInstance(); + SaveInstance->UserSaveData.SelectedCharacterData = InData; + + GameSave(SaveInstance); +} + +void UUserSaveGame::EmplaceUnlockCharacterData(const FString& RowName, const bool bCleared) +{ + UUserSaveGame* SaveInstance = GetSaveInstance(); + int32 FoundIndex = SaveInstance->UserSaveData.UnlockCharacterData.IndexOfByPredicate([RowName](const FUnlockCharacterData& CharacterData) + { + return CharacterData.UnlockCharacterRowName == RowName; + }); + FUnlockCharacterData Data; + if(FoundIndex == INDEX_NONE) Data = FUnlockCharacterData(RowName, bCleared); + else SaveInstance->UserSaveData.UnlockCharacterData[FoundIndex].bCleared = bCleared; + + SaveInstance->UserSaveData.UnlockCharacterData.Push(Data); + GameSave(SaveInstance); +} + +void UUserSaveGame::GetUnlockStageData(TArray& OutData) +{ + OutData = GetSaveInstance()->UserSaveData.UnlockStageData; +} + +void UUserSaveGame::EmplaceUnlockStageData(const FString& RowName, const bool bCleared) +{ + UUserSaveGame* SaveInstance = GetSaveInstance(); + int32 FoundIndex = SaveInstance->UserSaveData.UnlockStageData.IndexOfByPredicate([RowName](const FStageData& StageData) + { + return StageData.StageRowName == RowName; + }); + FStageData Data; + if(FoundIndex == INDEX_NONE) Data = FStageData(RowName, bCleared); + else SaveInstance->UserSaveData.UnlockCharacterData[FoundIndex].bCleared = bCleared; + + SaveInstance->UserSaveData.UnlockStageData.Push(Data); + GameSave(SaveInstance); +} + +void UUserSaveGame::GameSave(UUserSaveGame* InSaveInstance) +{ + NMT_CHECKF(InSaveInstance); + UGameplayStatics::SaveGameToSlot(InSaveInstance, SaveSlotName, 0); +} + +UUserSaveGame* UUserSaveGame::GetSaveInstance() +{ + UUserSaveGame* Ret = nullptr; + LoadUserSaveGame(Ret); + + return Ret; +} + +void UUserSaveGame::GetUnlockCharacterData(TArray& OutData) +{ + OutData = GetSaveInstance()->UserSaveData.UnlockCharacterData; +} + +void UUserSaveGame::GetSelectedCharacterData(FString& OutData) +{ + OutData = GetSaveInstance()->UserSaveData.SelectedCharacterData; +} diff --git a/Source/ProjectT/System/Core/SaveGame/UserSaveGame.h b/Source/ProjectT/System/Core/SaveGame/UserSaveGame.h new file mode 100644 index 0000000..fcadcb3 --- /dev/null +++ b/Source/ProjectT/System/Core/SaveGame/UserSaveGame.h @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/SaveGame.h" +#include "ProjectT/Data/User/UserDataModel.h" +#include "UserSaveGame.generated.h" + +UCLASS() +class PROJECTT_API UUserSaveGame : public USaveGame +{ + GENERATED_BODY() + +public: + UUserSaveGame(); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void GetUnlockCharacterData(TArray& OutData); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void GetSelectedCharacterData(FString& OutData); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void LoadUserSaveGame(UUserSaveGame*& OutSaveInstance); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void SetCurrentSelectedCharacterData(const FString& InData); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void EmplaceUnlockCharacterData(const FString& RowName, const bool bCleared); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void GetUnlockStageData(TArray& OutData); + + UFUNCTION(BlueprintCallable, Category = "UserSaveGame") + static void EmplaceUnlockStageData(const FString& RowName, const bool bCleared); + +private: + static void GameSave(UUserSaveGame* InSaveInstance); + + UFUNCTION() + static UUserSaveGame* GetSaveInstance(); + +private: + UPROPERTY() + FUserSaveData UserSaveData; + + static const FString SaveSlotName; +}; diff --git a/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.cpp b/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.cpp new file mode 100644 index 0000000..b5718cf --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.cpp @@ -0,0 +1,210 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreGameUserSettings.h" +#include "Sound/SoundClass.h" +#include "Sound/SoundMix.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" + +UCoreGameUserSettings::UCoreGameUserSettings() +{ + Initialize(); +} + +UCoreGameUserSettings* UCoreGameUserSettings::GetCoreGameUserSettings() +{ + return Cast(GetGameUserSettings()); +} + +void UCoreGameUserSettings::Initialize() +{ + UserGameOptionData = FGameOptionData(); + SetSystemLanguage(); +} + +void UCoreGameUserSettings::InitializeToDefault() +{ + Initialize(); + InitializeUserSettings(true); +} + +void UCoreGameUserSettings::InitializeUserSettings(const bool bReset/* = false*/) +{ + if (NMT_ENSURE(!UCoreGameGeneralSettings::GetMasterSoundClass().IsNull() && !UCoreGameGeneralSettings::GetBGMSoundClass().IsNull() && !UCoreGameGeneralSettings::GetSFXSoundClass().IsNull() && !UCoreGameGeneralSettings::GetSoundMixClass().IsNull())) + { + MasterSoundClass = UCoreGameGeneralSettings::GetMasterSoundClass().Get(); + BGMSoundClass = UCoreGameGeneralSettings::GetBGMSoundClass().Get(); + SFXSoundClass = UCoreGameGeneralSettings::GetSFXSoundClass().Get(); + SoundMix = UCoreGameGeneralSettings::GetSoundMixClass().Get(); + } + + bReset ? SetUserLanguage(UserGameOptionData.GamePlayOption.System_Language) : SetUserLanguage(UserGameOptionData.GamePlayOption.Setting_Language); + SetUserScreenResolution(UserGameOptionData.GamePlayOption.Setting_Resolution); + SetUserWindowMode(UserGameOptionData.GamePlayOption.Setting_WindowMode); + SetUserGamma(UserGameOptionData.GamePlayOption.Setting_Gamma); + + SetUserAntialiasingQuality(UserGameOptionData.GraphicOption.Setting_AntialiasingQuality); + SetUserShadowQuality(UserGameOptionData.GraphicOption.Setting_ShadowQuality); + SetUserScalability(UserGameOptionData.GraphicOption.Setting_ScalabilityQuality); + + SetUserMasterVolume(UserGameOptionData.AudioOption.Setting_MasterVolume); + SetUserBGMVolume(UserGameOptionData.AudioOption.Setting_BGMVolume); + SetUserSFXVolume(UserGameOptionData.AudioOption.Setting_SFXVolume); + + UGameplayStatics::SetBaseSoundMix(GEngine->GameViewport->GetWorld(), SoundMix); +} + +void UCoreGameUserSettings::ChangeSettingByEnum(const EGameOptionType InOptionType, const int32 InOptionLevel, const float InOptionValue) +{ + switch (InOptionType) + { + case EGameOptionType::Language: + SetUserLanguage(static_cast(InOptionLevel)); + break; + case EGameOptionType::Resolution: + SetUserScreenResolution(static_cast(InOptionLevel)); + break; + case EGameOptionType::WindowMode: + SetUserWindowMode(static_cast(InOptionLevel)); + break; + case EGameOptionType::Gamma: + SetUserGamma(InOptionValue); + break; + case EGameOptionType::Scalability: + SetUserShadowQuality(InOptionLevel); + break; + case EGameOptionType::AntiAliasingQuality: + SetUserAntialiasingQuality(InOptionLevel); + break; + case EGameOptionType::ShadowQuality: + SetUserShadowQuality(InOptionLevel); + break; + case EGameOptionType::MasterVolume: + SetUserMasterVolume(InOptionValue); + break; + case EGameOptionType::BGMVolume: + SetUserBGMVolume(InOptionValue); + break; + case EGameOptionType::SFXVolume: + SetUserSFXVolume(InOptionValue); + break; + default: break; + } +} + +void UCoreGameUserSettings::SetSystemLanguage() +{ + const FString ISOCode = UKismetSystemLibrary::GetDefaultLanguage(); + EGameLanguage Language = EGameLanguage::English; + + // FIXME: 데이터테이블 생성 후 구조에 맞춰 수정 필요 + if (ISOCode.StartsWith(TEXT("ko"))) + { + Language = EGameLanguage::Korea; + } + else if (ISOCode.StartsWith(TEXT("en"))) + { + Language = EGameLanguage::English; + } + else if (ISOCode.StartsWith(TEXT("zh-CN"))) + { + Language = EGameLanguage::ChineseCN; + } + else if (ISOCode.StartsWith(TEXT("zh-TW"))) + { + Language = EGameLanguage::ChineseTW; + } + else if (ISOCode.StartsWith(TEXT("es"))) + { + Language = EGameLanguage::Spanish; + } + + UserGameOptionData.GamePlayOption.System_Language = Language; +} + +void UCoreGameUserSettings::SetUserLanguage(const EGameLanguage InLanguage) +{ + bool bLanguageChanged = UserGameOptionData.GamePlayOption.Setting_Language != InLanguage; + + UserGameOptionData.GamePlayOption.Setting_Language = InLanguage; + + SaveSettings(); + if (bLanguageChanged) + { + UNotificationCenter* NC = UGlobalUtilsLibrary::GetSharedNotificationCenter(this); + NC->Post(ENotificationTypes::Option_Language_Changed); + } +} + +void UCoreGameUserSettings::SetUserScreenResolution(const EResolution InResolution) +{ + const FString ResolutionStr = UGlobalUtilsLibrary::GetEnumToString(InResolution); + NMT_ENSURE(!ResolutionStr.IsEmpty()); + + const TArray ParsedResult = UGlobalUtilsLibrary::ParseStringIndices(ResolutionStr, "_"); + NMT_ENSURE(ParsedResult.Num() >= 3); + if(ParsedResult[1].IsEmpty() || ParsedResult[2].IsEmpty()) + { + NMT_MSG_ENSURE(0, "ParsedResult Array is Empty"); + return; + } + + const int32 Width = FCString::Atoi(*ParsedResult[1]); + const int32 Height = FCString::Atoi(*ParsedResult[2]); + + UserGameOptionData.GamePlayOption.Setting_Resolution = InResolution; + + SetScreenResolution(FIntPoint(Width, Height)); + ApplySettings(true); +} + +void UCoreGameUserSettings::SetUserWindowMode(const EWindowMode::Type InWindowMode) +{ + if (InWindowMode >= EWindowMode::Type::NumWindowModes) + { + NMT_LOG("WindowMode can only be one of three types"); + return; + } + + UserGameOptionData.GamePlayOption.Setting_WindowMode = InWindowMode; + + SetFullscreenMode(InWindowMode); + ApplySettings(true); +} + +void UCoreGameUserSettings::SetUserGamma(const float InValue) +{ + UserGameOptionData.GamePlayOption.Setting_Gamma = InValue; + + // FIXME: 밝기 조절 방식이 정해지고난 뒤 구현 필요 + + ApplySettings(false); +} + +void UCoreGameUserSettings::SetUserScalability(const int32 InLevel) +{ + UserGameOptionData.GraphicOption.Setting_ScalabilityQuality = InLevel; + + SetUserAntialiasingQuality(InLevel); + SetUserShadowQuality(InLevel); +} + +void UCoreGameUserSettings::SetUserAntialiasingQuality(const int32 InLevel) +{ + UserGameOptionData.GraphicOption.Setting_AntialiasingQuality = InLevel; + + SetAntiAliasingQuality(InLevel); + ApplySettings(false); +} + +void UCoreGameUserSettings::SetUserShadowQuality(const int32 InLevel) +{ + UserGameOptionData.GraphicOption.Setting_ShadowQuality = InLevel; + + SetShadowQuality(InLevel); + ApplySettings(false); +} + + diff --git a/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h b/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h new file mode 100644 index 0000000..1c247fe --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GameSettings/CoreGameUserSettings.h @@ -0,0 +1,237 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameUserSettings.h" +#include "Kismet/GameplayStatics.h" +#include "ProjectT/ProjectT.h" +#include "CoreGameUserSettings.generated.h" + +/** + * + */ +UENUM(BlueprintType) +enum class EGameLanguage : uint8 +{ + Korea = 0 UMETA(DisplayName = "Korea"), + English UMETA(DisplayName = "English"), + ChineseCN UMETA(DisplayName = "ChineseCN"), + ChineseTW UMETA(DisplayName = "ChineseTW"), + Spanish UMETA(DisplayName = "Spanish"), +}; + +UENUM(BlueprintType) +enum class EGameOptionType : uint8 +{ + Language = 0 UMETA(DisplayName = "Language"), + Resolution UMETA(DisplayName = "Resolution"), + WindowMode UMETA(DisplayName = "WindowMode"), + Gamma UMETA(DisplayName = "Gamma"), + Scalability UMETA(DisplayName = "Scalability"), + AntiAliasingQuality UMETA(DisplayName = "AntiAliasing Quality"), + ShadowQuality UMETA(DisplayName = "Shadow Quality"), + MasterVolume UMETA(DisplayName = "MasterVolume"), + BGMVolume UMETA(DisplayName = "BGM Volume"), + SFXVolume UMETA(DisplayName = "SFX Volume"), + // Display, + // VSync, + // TextureQuality, + // EffectQuality, +}; + +UENUM(BlueprintType) +enum class EResolution : uint8 +{ + None = 0 UMETA(DisplayName = "None"), + Res_3840_2160 UMETA(DisplayName = "Res_3840_2160"), + Res_2560_1600 UMETA(DisplayName = "Res_2560_1600"), + Res_2560_1440 UMETA(DisplayName = "Res_2560_1440"), + Res_1920_1440 UMETA(DisplayName = "Res_1920_1440"), + Res_1920_1200 UMETA(DisplayName = "Res_1920_1200"), + Res_1920_1080 UMETA(DisplayName = "Res_1920_1080"), + Res_1600_1200 UMETA(DisplayName = "Res_1600_1200"), + Res_1600_1024 UMETA(DisplayName = "Res_1600_1024"), + Res_1600_900 UMETA(DisplayName = "Res_1600_900"), + Res_1280_960 UMETA(DisplayName = "Res_1280_960"), + Res_1280_800 UMETA(DisplayName = "Res_1280_800"), + Res_1280_720 UMETA(DisplayName = "Res_1280_720"), +}; + +USTRUCT(Blueprintable) +struct FGamePlayOption +{ + GENERATED_BODY() + + FGamePlayOption() : + System_Language(EGameLanguage::Korea), + Setting_Language(EGameLanguage::Korea), + Setting_Resolution(EResolution::Res_1920_1080), + Setting_WindowMode(EWindowMode::Type::Fullscreen), + Setting_Gamma(1.f) + {} + + /*Language*/ + UPROPERTY(BlueprintReadOnly, Category = "GamePlayOption") + EGameLanguage System_Language; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GamePlayOption") + EGameLanguage Setting_Language; + + /*Display*/ + UPROPERTY(Config, BlueprintReadOnly, Category = "GamePlayOption") + EResolution Setting_Resolution; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GamePlayOption") + TEnumAsByte Setting_WindowMode; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GamePlayOption") + float Setting_Gamma; +}; + +USTRUCT(Blueprintable) +struct FGraphicOption +{ + GENERATED_BODY() + + FGraphicOption() : + Setting_ScalabilityQuality(Scalability::DefaultQualityLevel), + Setting_AntialiasingQuality(Scalability::DefaultQualityLevel), + Setting_ShadowQuality(Scalability::DefaultQualityLevel) + {} + + UPROPERTY(Config, BlueprintReadOnly, Category = "GraphicOption") + int32 Setting_ScalabilityQuality; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GraphicOption") + int32 Setting_AntialiasingQuality; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GraphicOption") + int32 Setting_ShadowQuality; +}; + +USTRUCT(Blueprintable) +struct FAudioOption +{ + GENERATED_BODY() + + FAudioOption() : + Setting_MasterVolume(1.f), + Setting_BGMVolume(1.f), + Setting_SFXVolume(1.f) + {} + + UPROPERTY(Config, BlueprintReadOnly, Category = "AudioOption") + float Setting_MasterVolume; + + UPROPERTY(Config, BlueprintReadOnly, Category = "AudioOption") + float Setting_BGMVolume; + + UPROPERTY(Config, BlueprintReadOnly, Category = "AudioOption") + float Setting_SFXVolume; +}; + +USTRUCT(Blueprintable) +struct FGameOptionData +{ + GENERATED_BODY() + + FGameOptionData() : + GamePlayOption(FGamePlayOption()), + GraphicOption(FGraphicOption()), + AudioOption(FAudioOption()) + {} + + UPROPERTY(Config, BlueprintReadOnly, Category = "GamePlayOption") + FGamePlayOption GamePlayOption; + + UPROPERTY(Config, BlueprintReadOnly, Category = "GraphicOption") + FGraphicOption GraphicOption; + + UPROPERTY(Config, BlueprintReadOnly, Category = "AudioOption") + FAudioOption AudioOption; +}; + +UCLASS(config=GameUserSettings) +class PROJECTT_API UCoreGameUserSettings : public UGameUserSettings +{ + GENERATED_BODY() + +public: + UCoreGameUserSettings(); + + UFUNCTION(BlueprintPure, Category = "GameUserSetting") + static UCoreGameUserSettings* GetCoreGameUserSettings(); + +public: + void InitializeUserSettings(const bool bReset = false); + + UFUNCTION(BlueprintPure, Category = "GameOptionData") + FGameOptionData GetGameOptionData() const { return UserGameOptionData; } + + UFUNCTION(BlueprintPure, Category = "GamePlayOption") + FGamePlayOption GetGamePlayOption() const { return UserGameOptionData.GamePlayOption; } + + UFUNCTION(BlueprintPure, Category = "GraphicOption") + FGraphicOption GetGraphicOption() const { return UserGameOptionData.GraphicOption; } + + UFUNCTION(BlueprintPure, Category = "AudioOption") + FAudioOption GetAudioOption() const { return UserGameOptionData.AudioOption; } + + UFUNCTION(BlueprintCallable, Category = "GameUserSetting") + void InitializeToDefault(); + + UFUNCTION(BlueprintCallable, Category = "GameUserSetting") + void ChangeSettingByEnum(const EGameOptionType InOptionType, const int32 InOptionLevel, const float InOptionValue); + +private: + void Initialize(); + + void SetSystemLanguage(); + void SetUserLanguage(const EGameLanguage InLanguage); + void SetUserScreenResolution(const EResolution InResolution); + void SetUserWindowMode(const EWindowMode::Type InWindowMode); + void SetUserGamma(const float InValue); + void SetUserScalability(const int32 InLevel); + void SetUserAntialiasingQuality(const int32 InLevel); + void SetUserShadowQuality(const int32 InLevel); + + FORCEINLINE void SetSoundMixClassOverride(USoundClass* InSoundClass, const float InVolume) const + { + UWorld* World = GEngine->GameViewport->GetWorld(); + NMT_ENSURE(World); + + UGameplayStatics::SetSoundMixClassOverride(World, SoundMix, InSoundClass, InVolume, 1.0f, 0.f, false); + } + + FORCEINLINE void SetUserMasterVolume(const float InVolume) const + { + SetSoundMixClassOverride(MasterSoundClass, InVolume); + } + + FORCEINLINE void SetUserBGMVolume(const float InVolume) const + { + SetSoundMixClassOverride(BGMSoundClass, InVolume); + } + + FORCEINLINE void SetUserSFXVolume(const float InVolume) const + { + SetSoundMixClassOverride(SFXSoundClass, InVolume); + } + +private: + UPROPERTY(Config) + FGameOptionData UserGameOptionData; + + UPROPERTY() + USoundClass* MasterSoundClass; + + UPROPERTY() + USoundClass* BGMSoundClass; + + UPROPERTY() + USoundClass* SFXSoundClass; + + UPROPERTY() + USoundMix* SoundMix; +}; diff --git a/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.cpp b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.cpp new file mode 100644 index 0000000..d052065 --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreGameGeneralSettings.h" + +UCoreGameGeneralSettings* UCoreGameGeneralSettings::Get() +{ + static UCoreGameGeneralSettings* Instance; + + if (Instance != nullptr) + { + return Instance; + } + + TObjectIterator SettingsIt(RF_NoFlags); + if (SettingsIt) + { + Instance = *SettingsIt; + } + + return Instance; +} diff --git a/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h new file mode 100644 index 0000000..17c2086 --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreGameGeneralSettings.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DeveloperSettings.h" +#include "Sound/SoundMix.h" +#include "CoreGameGeneralSettings.generated.h" + +/** + * NOTE: ProjectT에 사용되는 보편적인 시스템 및 에셋 클래스를 정의합니다. + */ + +class USoundClass; +class USoundMix; +class ASpectatorPawn; + +UCLASS(Config=Game, DefaultConfig, meta = (DisplayName = "General Class Settings")) +class PROJECTT_API UCoreGameGeneralSettings : public UDeveloperSettings +{ + GENERATED_BODY() + +public: + static UCoreGameGeneralSettings* Get(); + + UFUNCTION(BlueprintCallable,Category="GeneralSound") + static TSoftObjectPtr GetMasterSoundClass() + { + return UCoreGameGeneralSettings::Get()->Sound_Master; + } + + UFUNCTION(BlueprintCallable,Category="GeneralSound") + static TSoftObjectPtr GetSFXSoundClass() + { + return UCoreGameGeneralSettings::Get()->Sound_BGM; + } + + UFUNCTION(BlueprintCallable,Category="GeneralSound") + static TSoftObjectPtr GetBGMSoundClass() + { + return UCoreGameGeneralSettings::Get()->Sound_SFX; + } + + UFUNCTION(BlueprintCallable,Category="GeneralSound") + static TSoftObjectPtr GetSoundMixClass() + { + return UCoreGameGeneralSettings::Get()->SoundMixClass_Master; + } + + UFUNCTION(BlueprintCallable, Category = "DebugSpectator") + static TSubclassOf GetDebugSpectatorPawn() + { + return UCoreGameGeneralSettings::Get()->DebugSpectatorPawn; + } + +private: + UPROPERTY(Config,EditAnywhere,BlueprintReadOnly,Category="GeneralSound", meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr Sound_Master; + + UPROPERTY(Config,EditAnywhere,BlueprintReadOnly,Category="GeneralSound", meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr Sound_BGM; + + UPROPERTY(Config,EditAnywhere,BlueprintReadOnly,Category="GeneralSound", meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr Sound_SFX; + + UPROPERTY(Config,EditAnywhere,BlueprintReadOnly,Category="GeneralSound", meta = (AllowPrivateAccess = "true")) + TSoftObjectPtr SoundMixClass_Master; + + UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "SinglePlay", meta = (AllowPrivateAccess = "true")) + TSubclassOf DebugSpectatorPawn; +}; diff --git a/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.cpp b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.cpp new file mode 100644 index 0000000..abeed3f --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CoreLoadingScreenSettings.h" + +UCoreLoadingScreenSettings::UCoreLoadingScreenSettings(): + bEnableStartUpMovie(false), + ZOrder(10000.f), + MinimumLoadingScreenTime(2.f), + bForceLoadingComplete(0) +{ + CategoryName = TEXT("Game"); +} diff --git a/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.h b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.h new file mode 100644 index 0000000..fa1589e --- /dev/null +++ b/Source/ProjectT/System/Core/Settings/GeneralSettings/CoreLoadingScreenSettings.h @@ -0,0 +1,43 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DeveloperSettings.h" +#include "CoreLoadingScreenSettings.generated.h" + +/** + * + */ +UCLASS(config=Game, defaultconfig, meta=(DisplayName="LoadingScreenSettings")) +class PROJECTT_API UCoreLoadingScreenSettings : public UDeveloperSettings +{ + GENERATED_BODY() + +public: + UCoreLoadingScreenSettings(); + + /** + * The movie paths local to the game's Content/Movies/ directory we will play. + */ + UPROPERTY(config, EditAnywhere, Category = Display) + bool bEnableStartUpMovie; + + UPROPERTY(config, EditAnywhere, Category = Display, meta = (EditCondition = "bEnableStartUpMovie")) + FString StartUpMoviePath; + + UPROPERTY(config, EditAnywhere, Category = Display, meta = (MetaClass = "/Script/UMG.UserWidget", EditCondition = "!bEnableStartUpMovie")) + FSoftClassPath PreLoadingScreenClassPath; + + UPROPERTY(config, EditAnywhere, Category = Display, meta = (MetaClass = "/Script/UMG.UserWidget")) + FSoftClassPath PostLoadingScreenClassPath; + + UPROPERTY(config, EditAnywhere, Category = Display) + float ZOrder; + + UPROPERTY(config, EditAnywhere, Category = Display, meta= (ClampMin = "2.0", UIMin = "2.0")) + float MinimumLoadingScreenTime; + + UPROPERTY(config, EditAnywhere, Category = Display) + uint8 bForceLoadingComplete : 1; +}; diff --git a/Source/ProjectT/System/Core/Widget/CommonHUD.cpp b/Source/ProjectT/System/Core/Widget/CommonHUD.cpp new file mode 100644 index 0000000..d604620 --- /dev/null +++ b/Source/ProjectT/System/Core/Widget/CommonHUD.cpp @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CommonHUD.h" +#include "ProjectT/ProjectT.h" + +void UCommonHUD::ToggleGameMenuEvent_Implementation() +{ +} + +void UCommonHUD::NativeConstruct() +{ + Super::NativeConstruct(); + InitializeBindEvent(); +} + +void UCommonHUD::InitializeBindEvent() +{ + NOT_IMPLEMENTED(); +} diff --git a/Source/ProjectT/System/Core/Widget/CommonHUD.h b/Source/ProjectT/System/Core/Widget/CommonHUD.h new file mode 100644 index 0000000..d54e0e3 --- /dev/null +++ b/Source/ProjectT/System/Core/Widget/CommonHUD.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "CommonHUD.generated.h" + +UCLASS() +class PROJECTT_API UCommonHUD : public UUserWidget +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintNativeEvent) + void ToggleGameMenuEvent(); + +protected: + virtual void NativeConstruct() override; + virtual void InitializeBindEvent(); +}; diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.cpp b/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.cpp new file mode 100644 index 0000000..6b5e9fa --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.cpp @@ -0,0 +1,182 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LobbyGameMode.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Lobby/Managers/LobbyWidgetManager.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.h" + + +ALobbyGameMode::ALobbyGameMode() + :CurrentStreamLevel(nullptr), + StageIDX(0) +{ + +} + +void ALobbyGameMode::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); +} + +ULobbyWidgetManager* ALobbyGameMode::GetLobbyWidgetManager_Implementation() +{ + NMT_MSG_CHECKF(CoreWidgetManager, "Widget Manager is Null"); + ULobbyWidgetManager* LWM = Cast(CoreWidgetManager); + NMT_MSG_CHECKF(LWM, "LobbyWidgetManager Cast Failed"); + return LWM; +} + +ALobbyPreviewCharacter* ALobbyGameMode::GetLobbyPreviewCharacter_Implementation() +{ + AActor* FindActor; + FindActor = UGameplayStatics::GetActorOfClass(GetWorld(), ALobbyPreviewCharacter::StaticClass()); + NMT_MSG_CHECKF(FindActor, "LobbyPreviewCharacter not found"); + ALobbyPreviewCharacter* LPC = Cast(FindActor); + NMT_MSG_CHECKF(LPC, "Cast fail to LobbyPreviewCharacter"); + + return LPC; +} + + +void ALobbyGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) +{ + Super::InitGame(MapName, Options, ErrorMessage); + InitializeManagers(); + InitializeUI(); + CurrentStreamLevel = LobbyLevels[0]; +} + +void ALobbyGameMode::BeginPlay() +{ + Super::BeginPlay(); +} + +void ALobbyGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); +} + +void ALobbyGameMode::InitializeManagers() +{ + Super::InitializeManagers(); + UWorld* World = GetWorld(); + NMT_CHECKF(World); + + if(!CoreWidgetManager) + { + CoreWidgetManager = NewObject(this); + CoreWidgetManager->InitializeManager(this); + NMT_CHECKF(CoreWidgetManager); + } +} + +void ALobbyGameMode::InitializeUI() +{ + Super::InitializeUI(); + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + + NMT_CHECKF(CoreWidgetManager); + ULobbyWidgetManager* LWM = CastChecked(CoreWidgetManager); + LWM->OnRequestLevelChange.BindUFunction(this, FName("LevelChange")); + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GetGameInstance()); + NMT_CHECKF(DD); + + const UDataTable* StageTable = DD->GetDataTableByEnum(EDataTableKey::Stage); + NMT_CHECKF(StageTable); + for(FName StageRow : StageTable->GetRowNames()) + { + FStage* StageData = StageTable->FindRow(StageRow, TEXT("Not Found StageDataRow")); + if(StageData) + { + LWM->StageDatas.Add(StageRow, *StageData); + } + } + + const UDataTable* PlayerCharacterTable = DD->GetDataTableByEnum(EDataTableKey::PlayerCharacter); + NMT_CHECKF(PlayerCharacterTable); + for(FName PlayerCharacterRow : PlayerCharacterTable->GetRowNames()) + { + FPlayerCharacter* PlayerCharacterData = PlayerCharacterTable->FindRow(PlayerCharacterRow, TEXT("Not Found PlayerCharacterDataRow")); + if(PlayerCharacterData) + { + LWM->PlayerCharacterDatas.Add(PlayerCharacterRow, *PlayerCharacterData); + } + } + + const UDataTable* SkillTable = DD->GetDataTableByEnum(EDataTableKey::Skill); + NMT_CHECKF(SkillTable); + for(FName SkillRow : SkillTable->GetRowNames()) + { + FSkill* SkillData = SkillTable->FindRow(SkillRow, TEXT("Not Found SkillDataRow")); + if(SkillData) + { + LWM->SkillDatas.Add(SkillRow, *SkillData); + } + } + + const UDataTable* ObjectiveTable = DD->GetDataTableByEnum(EDataTableKey::Objective); + NMT_CHECKF(ObjectiveTable); + for(FName ObjectiveRow : ObjectiveTable->GetRowNames()) + { + FObjective* ObjectiveData = ObjectiveTable->FindRow(ObjectiveRow, TEXT("Not Found ObjectiveDataRow")); + if(ObjectiveData) + { + LWM->ObjectiveDatas.Add(ObjectiveRow, *ObjectiveData); + } + } +} + +void ALobbyGameMode::LevelChange(int32 LobbyLevelIDX) +{ + StageIDX = LobbyLevelIDX; + if(LobbyLevels.IsValidIndex(StageIDX)) + { + FLatentActionInfo LatentInfo; + LatentInfo.CallbackTarget = this; + LatentInfo.ExecutionFunction = FName("CompleteLevelUnLoad"); + LatentInfo.UUID = 1; + LatentInfo.Linkage = 0; + + UGameplayStatics::UnloadStreamLevelBySoftObjectPtr( + this, + CurrentStreamLevel, + LatentInfo, + true + ); + } + +} + +void ALobbyGameMode::CompleteLevelLoad() +{ + ULobbyWidgetManager* LWM = CastChecked(CoreWidgetManager); + CurrentStreamLevel = LobbyLevels[StageIDX]; + LWM->OnCompleteLevelChange.ExecuteIfBound(StageIDX); +} + +void ALobbyGameMode::CompleteLevelUnLoad() +{ + if(LobbyLevels.IsValidIndex(StageIDX)) + { + FLatentActionInfo LatentInfo; + LatentInfo.CallbackTarget = this; + LatentInfo.ExecutionFunction = FName("CompleteLevelLoad"); + LatentInfo.UUID = 2; + LatentInfo.Linkage = 0; + const TSoftObjectPtr& LevelToLoad = LobbyLevels[StageIDX]; + + UGameplayStatics::LoadStreamLevelBySoftObjectPtr( + this, + LevelToLoad, + true, + true, + LatentInfo + ); + } +} + diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.h b/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.h new file mode 100644 index 0000000..6851544 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyGameMode.h @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/GameModes/CoreGameMode.h" +#include "ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.h" +#include "LobbyGameMode.generated.h" + +/** + * + */ + +class ULobbyWidgetManager; + +UCLASS() +class PROJECTT_API ALobbyGameMode : public ACoreGameMode, public ILobbyObjectProvider +{ + GENERATED_BODY() + +public: + ALobbyGameMode(); + virtual void Tick(float DeltaSeconds) override; + virtual ULobbyWidgetManager* GetLobbyWidgetManager_Implementation() override; + virtual ALobbyPreviewCharacter* GetLobbyPreviewCharacter_Implementation() override; + + + +protected: + virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override; + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void InitializeManagers() override; + virtual void InitializeUI() override; + +private: + UFUNCTION() + void LevelChange(int32 LobbyLevelIDX); + + UFUNCTION() + void CompleteLevelLoad(); + + UFUNCTION() + void CompleteLevelUnLoad(); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LobbyLevels") + TArray> LobbyLevels; + +private: + UPROPERTY() + TSoftObjectPtr CurrentStreamLevel; + + UPROPERTY() + int32 StageIDX; + +}; diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.cpp b/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.cpp new file mode 100644 index 0000000..5ae2b02 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.cpp @@ -0,0 +1,19 @@ + +#include "LobbyGameState.h" + + +ALobbyGameState::ALobbyGameState() +{ + PrimaryActorTick.bCanEverTick = true; +} + + +void ALobbyGameState::BeginPlay() +{ + Super::BeginPlay(); +} + +void ALobbyGameState::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); +} diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.h b/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.h new file mode 100644 index 0000000..6602a5d --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyGameState.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/GameModes/CoreGameState.h" +#include "LobbyGameState.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ALobbyGameState : public ACoreGameState +{ + GENERATED_BODY() + +public: + ALobbyGameState(); + + +protected: + virtual void BeginPlay() override; + virtual void Tick(float DeltaSeconds) override; + +protected: + + +}; diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.cpp b/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.cpp new file mode 100644 index 0000000..92897a1 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.cpp @@ -0,0 +1,30 @@ + +#include "LobbyPawn.h" +#include "ProjectT/System/Core/Components/CoreCameraComponent.h" + + +ALobbyPawn::ALobbyPawn() +{ + PrimaryActorTick.bCanEverTick = true; + LobbyPawnCamera = CreateDefaultSubobject(TEXT("LobbyPawnCamera")); + LobbyPawnCamera->SetupAttachment(RootComponent); +} + +void ALobbyPawn::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ALobbyPawn::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +void ALobbyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); + +} + diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.h b/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.h new file mode 100644 index 0000000..e04cdc2 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyPawn.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Pawn.h" +#include "LobbyPawn.generated.h" + +UCLASS() +class PROJECTT_API ALobbyPawn : public APawn +{ + GENERATED_BODY() + +public: + // Sets default values for this pawn's properties + ALobbyPawn(); + +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; + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera") + TObjectPtr LobbyPawnCamera; + +}; diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.cpp b/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.cpp new file mode 100644 index 0000000..9f0db96 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LobbyPlayerController.h" + +ALobbyPlayerController::ALobbyPlayerController() +{ + bShowMouseCursor = true; +} + +void ALobbyPlayerController::OnPossess(APawn* InPawn) +{ + Super::OnPossess(InPawn); + InitializePlayerScreen(); +} diff --git a/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.h b/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.h new file mode 100644 index 0000000..acb6600 --- /dev/null +++ b/Source/ProjectT/System/Lobby/GameModes/LobbyPlayerController.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/GameModes/CorePlayerController.h" +#include "LobbyPlayerController.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ALobbyPlayerController : public ACorePlayerController +{ + GENERATED_BODY() + +public: + ALobbyPlayerController(); + + virtual void OnPossess(APawn* InPawn) override; + + +}; diff --git a/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.cpp b/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.cpp new file mode 100644 index 0000000..4dda8dd --- /dev/null +++ b/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LobbyObjectProvider.h" + +// Add default functionality here for any ILobbyObjectProvider functions that are not pure virtual. diff --git a/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.h b/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.h new file mode 100644 index 0000000..6d445ae --- /dev/null +++ b/Source/ProjectT/System/Lobby/Interfaces/LobbyObjectProvider.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "LobbyObjectProvider.generated.h" + + +UINTERFACE(MinimalAPI, Blueprintable) +class ULobbyObjectProvider : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API ILobbyObjectProvider +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "LobbyObjectProvider")) + class ULobbyWidgetManager* GetLobbyWidgetManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "LobbyObjectProvider")) + class ALobbyPreviewCharacter* GetLobbyPreviewCharacter(); + +}; diff --git a/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.cpp b/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.cpp new file mode 100644 index 0000000..38b40cf --- /dev/null +++ b/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.cpp @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LobbyWidgetManager.h" +#include "ProjectT/System/Lobby/GameModes/LobbyGameMode.h" + +void ULobbyWidgetManager::InitializeManager(const UObject* WorldObjectContext) +{ + Super::InitializeManager(WorldObjectContext); +} + +void ULobbyWidgetManager::ReleaseManager() +{ + OnRequestLevelChange.Unbind(); + + Super::ReleaseManager(); +} + +void ULobbyWidgetManager::RequestLevelChange(int32 StageIDX, const FOnCompleteLevelChange& Subscribe) +{ + OnRequestLevelChange.ExecuteIfBound(StageIDX); + OnCompleteLevelChange = Subscribe; +} + +void ULobbyWidgetManager::RequestStageData(const FOnRequestStageData& OnRequestStageData) +{ + FStageWrap Data; + Data.StageDatas = StageDatas; + OnRequestStageData.ExecuteIfBound(Data); +} + +void ULobbyWidgetManager::RequestPlayerCharacterData(const FOnRequestPlayerCharacterData& OnRequestPlayerCharacterData) +{ + FCharacterWrap Data; + Data.PlayerCharacterDatas = PlayerCharacterDatas; + OnRequestPlayerCharacterData.ExecuteIfBound(Data); +} + +void ULobbyWidgetManager::RequestSkillData(const FOnRequestSkillData& OnRequestSkillData) +{ + FSkillWrap Data; + Data.SkillDatas = SkillDatas; + OnRequestSkillData.ExecuteIfBound(Data); +} + +void ULobbyWidgetManager::RequestObjectiveData(const FOnRequestObjectiveData& OnRequestObjectiveData) +{ + FObjectiveWrap Data; + Data.ObjectiveDatas = ObjectiveDatas; + OnRequestObjectiveData.ExecuteIfBound(Data); +} + diff --git a/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.h b/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.h new file mode 100644 index 0000000..6a4520e --- /dev/null +++ b/Source/ProjectT/System/Lobby/Managers/LobbyWidgetManager.h @@ -0,0 +1,115 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Managers/CoreWidgetManager.h" +#include "ProjectT/Data/Gen/GenerateStructStage.h" +#include "ProjectT/Data/Gen/GenerateStructPlayerCharacter.h" +#include "ProjectT/Data/Gen/GenerateStructSkill.h" +#include "ProjectT/Data/Gen/GenerateStructObjective.h" + +#include "LobbyWidgetManager.generated.h" + +USTRUCT(BlueprintType) +struct FStageWrap +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + TMap StageDatas; +}; + +USTRUCT(BlueprintType) +struct FCharacterWrap +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + TMap PlayerCharacterDatas; +}; + +USTRUCT(BlueprintType) +struct FSkillWrap +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + TMap SkillDatas; +}; + +USTRUCT(BlueprintType) +struct FObjectiveWrap +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly) + TMap ObjectiveDatas; +}; + + +DECLARE_DELEGATE_OneParam(FOnRequestLevelChange,int32); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnCompleteLevelChange, int32, StageIDX); + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnRequestStageData, FStageWrap, OutDatas); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnRequestPlayerCharacterData, FCharacterWrap, OutDatas); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnRequestSkillData, FSkillWrap, OutDatas); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnRequestObjectiveData, FObjectiveWrap, OutDatas); + + +/** + * + */ +UCLASS() +class PROJECTT_API ULobbyWidgetManager : public UCoreWidgetManager +{ + GENERATED_BODY() + +public: + virtual void InitializeManager(const UObject* WorldObjectContext) override; + virtual void ReleaseManager() override; + + UFUNCTION(BlueprintCallable, Category = "Level") + void RequestLevelChange(int32 StageIDX, const FOnCompleteLevelChange& Subscribe); + + UFUNCTION(BlueprintCallable, Category = "Data") + void RequestStageData(const FOnRequestStageData& OnRequestStageData); + + UFUNCTION(BlueprintCallable, Category = "Data") + void RequestPlayerCharacterData(const FOnRequestPlayerCharacterData& OnRequestPlayerCharacterData); + + UFUNCTION(BlueprintCallable, Category = "Data") + void RequestSkillData(const FOnRequestSkillData& OnRequestSkillData); + + UFUNCTION(BlueprintCallable, Category = "Data") + void RequestObjectiveData(const FOnRequestObjectiveData& OnRequestObjectiveData); + + +public: + UPROPERTY() + TMap StageDatas; + + UPROPERTY() + TMap PlayerCharacterDatas; + + UPROPERTY() + TMap SkillDatas; + + UPROPERTY() + TMap ObjectiveDatas; + + + UPROPERTY() + FOnCompleteLevelChange OnCompleteLevelChange; + + + FOnRequestLevelChange OnRequestLevelChange; + + +private: + +}; diff --git a/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.cpp b/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.cpp new file mode 100644 index 0000000..53e8442 --- /dev/null +++ b/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.cpp @@ -0,0 +1,126 @@ + +#include "LobbyPreviewCharacter.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateStructMeshList.h" +#include "ProjectT/Data/Gen/GenerateStructSocketList.h" +#include "ProjectT/Data/Gen/GenerateStructCharacterMeshSet.h" +#include "ProjectT/Data/Gen/GenerateStructAnimationSet.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/SaveGame/UserSaveGame.h" + + +// Sets default values +ALobbyPreviewCharacter::ALobbyPreviewCharacter() +{ + PrimaryActorTick.bCanEverTick = true; + + BodyMesh = CreateDefaultSubobject(TEXT("CharacterBody")); + BodyMesh->SetupAttachment(RootComponent); + + WeaponMesh = CreateDefaultSubobject(TEXT("Weapon")); + WeaponMesh->SetupAttachment(BodyMesh); + + WeaponDynamicMesh = CreateDefaultSubobject(TEXT("WeaponDynamic")); + WeaponDynamicMesh->SetupAttachment(BodyMesh); +} + +// Called when the game starts or when spawned +void ALobbyPreviewCharacter::BeginPlay() +{ + Super::BeginPlay(); + + UUserSaveGame* SG; + UUserSaveGame::LoadUserSaveGame(SG); + if(!SG) return; + + FString SelectData; + SG->GetSelectedCharacterData(SelectData); + + UDataTable* ChrTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::PlayerCharacter); + FPlayerCharacter* ChrData = ChrTable->FindRow(*SelectData, TEXT("FPlayerCharacter")); + if(!ChrData) return; + + SetCharacterByData(*ChrData); +} + +// Called every frame +void ALobbyPreviewCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +bool ALobbyPreviewCharacter::SetCharacterByData(const FPlayerCharacter& Data) +{ + UDataTable* CMSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::CharacterMeshSet); + FCharacterMeshSet* CMSData = CMSTable->FindRow(FROM_INT(Data.iCharMeshSetId), TEXT("FCharacterMeshSet")); + if(!CMSData) return false; + + UDataTable* MLSTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::MeshList); + FMeshList* BodyData = MLSTable->FindRow(FROM_INT(CMSData->iBodyMeshId), TEXT("FMeshList")); + if(!BodyData) return false; + + USkeletalMesh* FindBodyMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(BodyData->sMeshPath); + if(!FindBodyMesh) return false; + BodyMesh->SetSkeletalMesh(FindBodyMesh); + + UDataTable* ASTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::AnimationSet); + FAnimationSet* AnimData = ASTable->FindRow(FROM_INT(Data.iCharAniSetId), TEXT("FAnimationSetList")); + if(!AnimData) return false; + + UAnimSequence* FindAnim = UAssetUtilsLibrary::GetAnimSequenceFromPath(AnimData->sIdleAniPath); + if(!FindAnim) return false; + BodyMesh->PlayAnimation(FindAnim, true); + + FMeshList* WeaponData = nullptr; + if(CMSData->iWeaponMeshId != 0) WeaponData = MLSTable->FindRow(FROM_INT(CMSData->iWeaponMeshId), TEXT("FMeshList")); + + if(!WeaponData) return true; + if(!CHECK_FREE(WeaponData->sMeshPath)) + { + UMeshComponent* WeaponComponent = nullptr; + FString ScriptType = UGlobalUtilsLibrary::GetScriptTypeByRefPath(WeaponData->sMeshPath); + if(ScriptType.Equals(TEXT("StaticMesh"))) + { + UStaticMesh* FindWeaponMesh = UAssetUtilsLibrary::GetStaticMeshFromPath(WeaponData->sMeshPath); + WeaponMesh->SetStaticMesh(FindWeaponMesh); + UGlobalUtilsLibrary::EnableComponent(WeaponMesh, true); + WeaponComponent = WeaponMesh; + } + else if(ScriptType.Equals(TEXT("SkeletalMesh"))) + { + USkeletalMesh* FindWeaponMesh = UAssetUtilsLibrary::GetSkeletalMeshFromPath(WeaponData->sMeshPath); + WeaponDynamicMesh->SetSkeletalMesh(FindWeaponMesh); + UGlobalUtilsLibrary::EnableComponent(WeaponDynamicMesh, true); + WeaponComponent = WeaponDynamicMesh; + } + else + { + + } + + CMSData->iWeaponSocketId; + UDataTable* SocketTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::SocketList); + FSocketList* SocketData = SocketTable->FindRow(FROM_INT(CMSData->iWeaponSocketId), TEXT("FSocketList")); + if(CHECK_FREE(SocketData->sSocketName)) + { + NMT_MSG_ENSURE(0, "Socket Name Is FREE [%s][%s]", FROM_INT(CMSData->iWeaponSocketId), *SocketData->sSocketName); + return true; + } + + WeaponComponent->AttachToComponent(BodyMesh, FAttachmentTransformRules::SnapToTargetIncludingScale, *SocketData->sSocketName); + } + + else + { + WeaponMesh->SetStaticMesh(nullptr); + WeaponDynamicMesh->SetSkeletalMesh(nullptr); + } + + return true; + +} + diff --git a/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.h b/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.h new file mode 100644 index 0000000..9b2b1b3 --- /dev/null +++ b/Source/ProjectT/System/Lobby/Objects/LobbyPreviewCharacter.h @@ -0,0 +1,35 @@ + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectT/Data/Gen/GenerateStructPlayerCharacter.h" +#include "LobbyPreviewCharacter.generated.h" + +UCLASS() +class PROJECTT_API ALobbyPreviewCharacter : public AActor +{ + GENERATED_BODY() + +public: + ALobbyPreviewCharacter(); + + virtual void Tick(float DeltaTime) override; + + UFUNCTION(BlueprintCallable) + bool SetCharacterByData(const FPlayerCharacter& Data); + +protected: + virtual void BeginPlay() override; + +public: + UPROPERTY(EditAnywhere,BlueprintReadWrite) + TObjectPtr BodyMesh; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr WeaponMesh; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr WeaponDynamicMesh; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.cpp new file mode 100644 index 0000000..edc71dd --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.cpp @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_CheckAtArriveLocation.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Vector.h" +#include "Components/CapsuleComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" + +UBTDecorator_CheckAtArriveLocation::UBTDecorator_CheckAtArriveLocation() : + AcceptRadius(1.f), + bIncludeCapsuleRadius(false) +{ + NodeName = "Check At ArriveLocation"; +} + +bool UBTDecorator_CheckAtArriveLocation::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + const UBlackboardComponent* Blackboard = OwnerComp.GetBlackboardComponent(); + AAIController* AIC = OwnerComp.GetAIOwner(); + if(!AIC) + return false; + + ACoreNpc* Npc = AIC->GetPawn(); + if(!Npc) + return false; + + if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) + { + const FVector TargetLocation = Blackboard->GetValue(BlackboardKey.GetSelectedKeyID()); + FVector2D StartLocation2D = FVector2D(Npc->GetActorLocation().X, Npc->GetActorLocation().Y); + FVector2D TargetLocation2D = FVector2D(TargetLocation.X, TargetLocation.Y); + float Distance2D = FVector2D::Distance(StartLocation2D, TargetLocation2D); + + if(bIncludeCapsuleRadius) + { + UCapsuleComponent* CapsuleComponent = Npc->GetCapsuleComponent(); + if(!CapsuleComponent) + return Distance2D > AcceptRadius; + + return Distance2D > AcceptRadius + CapsuleComponent->GetScaledCapsuleRadius(); + } + + return Distance2D > AcceptRadius; + } + + return false; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.h new file mode 100644 index 0000000..79838e3 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocation.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDecorator_CheckAtArriveLocation.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_CheckAtArriveLocation : public UBTDecorator +{ + GENERATED_BODY() + +public: + UBTDecorator_CheckAtArriveLocation(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; + +public: + UPROPERTY(EditAnywhere, Category = Blackboard) + FBlackboardKeySelector BlackboardKey; + + UPROPERTY(EditAnywhere) + float AcceptRadius; + + UPROPERTY(EditAnywhere) + uint8 bIncludeCapsuleRadius : 1; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.cpp new file mode 100644 index 0000000..1380d45 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.cpp @@ -0,0 +1,51 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_CheckAtArriveLocationLoop.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Vector.h" +#include "Components/CapsuleComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" + +UBTDecorator_CheckAtArriveLocationLoop::UBTDecorator_CheckAtArriveLocationLoop() : + AcceptRadius(1.f), + bIncludeCapsuleRadius(false) +{ + NodeName = "Check At ArriveLocation Loop"; +} + +bool UBTDecorator_CheckAtArriveLocationLoop::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + const UBlackboardComponent* Blackboard = OwnerComp.GetBlackboardComponent(); + AAIController* AIC = OwnerComp.GetAIOwner(); + if(!AIC) + return false; + + ACoreNpc* Npc = AIC->GetPawn(); + if(!Npc) + return false; + + if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) + { + const FVector TargetLocation = Blackboard->GetValue(BlackboardKey.GetSelectedKeyID()); + FVector2D StartLocation2D = FVector2D(Npc->GetActorLocation().X, Npc->GetActorLocation().Y); + FVector2D TargetLocation2D = FVector2D(TargetLocation.X, TargetLocation.Y); + float Distance2D = FVector2D::Distance(StartLocation2D, TargetLocation2D); + NMT_LOGF("Check At ArriveLocation Loop. Dist %f", Distance2D) + + if(bIncludeCapsuleRadius) + { + UCapsuleComponent* CapsuleComponent = Npc->GetCapsuleComponent(); + if(!CapsuleComponent) + return Distance2D > AcceptRadius; + + return Distance2D > AcceptRadius + CapsuleComponent->GetScaledCapsuleRadius(); + } + + return Distance2D > AcceptRadius; + } + + return false; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.h new file mode 100644 index 0000000..989a480 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckAtArriveLocationLoop.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/Decorators/BTDecorator_ConditionalLoop.h" +#include "BTDecorator_CheckAtArriveLocationLoop.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_CheckAtArriveLocationLoop : public UBTDecorator_ConditionalLoop +{ + GENERATED_BODY() + +public: + UBTDecorator_CheckAtArriveLocationLoop(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; + +public: + UPROPERTY(EditAnywhere) + float AcceptRadius; + + UPROPERTY(EditAnywhere) + uint8 bIncludeCapsuleRadius : 1; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.cpp new file mode 100644 index 0000000..c6b3625 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_CheckEffect.h" + +#include "AIController.h" +#include "ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" + +UBTDecorator_CheckEffect::UBTDecorator_CheckEffect() : + EffectSubType(EEffectSubTypes::None) +{ + NodeName = "CheckEffect"; +} + +bool UBTDecorator_CheckEffect::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + ACoreNpc* Npc = OwnerComp.GetAIOwner()->GetPawn(); + if(!Npc) + return false; + + TArray Effects = Npc->GetCurrentEffects(); + return Effects.Contains(EffectSubType); + +} \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.h new file mode 100644 index 0000000..16029f7 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckEffect.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDecorator_CheckEffect.generated.h" + +enum class EEffectSubTypes : uint8; +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_CheckEffect : public UBTDecorator +{ + GENERATED_BODY() + +public: + UBTDecorator_CheckEffect(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; + + UPROPERTY(EditAnywhere, Category = "BlackBoard") + EEffectSubTypes EffectSubType; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.cpp new file mode 100644 index 0000000..8377b03 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.cpp @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_CheckHp.h" + +#include "AIController.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + +UBTDecorator_CheckHp::UBTDecorator_CheckHp() +{ + NodeName = "CheckHp"; +} + +bool UBTDecorator_CheckHp::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + ACoreNpc* Npc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Npc) + return false; + + USPNpcStatusComponent* NpcStatusComponent = Npc->GetNpcStatusComponent(); + if(!NpcStatusComponent) + return false; + + return NpcStatusComponent->GetCurrentHP() > 0.f; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.h new file mode 100644 index 0000000..a76b914 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_CheckHp.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDecorator_CheckHp.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_CheckHp : public UBTDecorator +{ + GENERATED_BODY() + +public: + UBTDecorator_CheckHp(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.cpp new file mode 100644 index 0000000..ad74655 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.cpp @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_InAtkDistance.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTDecorator_InAtkDistance::UBTDecorator_InAtkDistance() +{ + NodeName = "In Atk Distance"; +} + +bool UBTDecorator_InAtkDistance::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + UBlackboardComponent* BBC = OwnerComp.GetAIOwner()->GetBlackboardComponent(); + if(!BBC) + return false; + + AActor* Target = Cast(BBC->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey())); + if(!Target) + return false; + + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return false; + + return AgentNpc->IsTargetInAttackRange(Target); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.h new file mode 100644 index 0000000..b8e1256 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_InAtkDistance.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDecorator_InAtkDistance.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_InAtkDistance : public UBTDecorator +{ + GENERATED_BODY() + +public: + UBTDecorator_InAtkDistance(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.cpp new file mode 100644 index 0000000..b5affec --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.cpp @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTDecorator_OnNavMesh.h" + +#include "AIController.h" +#include "NavigationSystem.h" +#include "Components/CapsuleComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" + +UBTDecorator_OnNavMesh::UBTDecorator_OnNavMesh() +{ + NodeName = "On NavMesh"; +} + +bool UBTDecorator_OnNavMesh::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + AAIControllerBase* AIC = Cast(OwnerComp.GetAIOwner()); + if(!AIC) + return false; + + ACoreNpc* Npc = AIC->GetPawn(); + if(!Npc) + return false; + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(Npc); + if(!World) + return false; + + UNavigationSystemV1* NavSystem = UNavigationSystemV1::GetCurrent(World); + if(!NavSystem) + return false; + + float CapsuleRadius, CapsuleHalfHeight; + UCapsuleComponent* CapsuleComponent = Npc->GetCapsuleComponent(); + if(!CapsuleComponent) + return false; + + CapsuleComponent->GetScaledCapsuleSize(CapsuleRadius, CapsuleHalfHeight); + FVector Extent(CapsuleRadius, CapsuleRadius, CapsuleHalfHeight); + FNavLocation OutLocation; + + bool bOnNavMesh = NavSystem->ProjectPointToNavigation(Npc->GetActorLocation(), OutLocation, Extent); + if(bOnNavMesh) + { + return true; + } + + NMT_LOG("NOT On Nav Mesh") + return false; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.h new file mode 100644 index 0000000..c7f83d4 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Decorators/BTDecorator_OnNavMesh.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDecorator_OnNavMesh.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTDecorator_OnNavMesh : public UBTDecorator +{ + GENERATED_BODY() + +public: + UBTDecorator_OnNavMesh(); + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.cpp new file mode 100644 index 0000000..05ae8d0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.cpp @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTService_CheckAtkDistance.h" + +#include "AIController.h" +#include "RHIShaderFormatDefinitions.inl" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTService_CheckAtkDistance::UBTService_CheckAtkDistance() +{ + NodeName = TEXT("CheckAtkDistance"); + Interval = 1.f; +} + +void UBTService_CheckAtkDistance::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); + + UBlackboardComponent* BBC = OwnerComp.GetAIOwner()->GetBlackboardComponent(); + if(!BBC) + return; + + AActor* Target = Cast(BBC->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey())); + if(!Target) + return; + + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return; + + if(AgentNpc->IsTargetInAttackRange(Target) && AgentNpc->IsFinishSkillCoolDown() && BBC->GetValueAsBool(UBlackboardKeyLibrary::GetCanAttack())) + { + AgentNpc->ChangeNpcState(ENpcState::Attack); + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.h new file mode 100644 index 0000000..73ecf55 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_CheckAtkDistance.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTService.h" +#include "BTService_CheckAtkDistance.generated.h" + + +UCLASS() +class PROJECTT_API UBTService_CheckAtkDistance : public UBTService +{ + GENERATED_BODY() + +public: + UBTService_CheckAtkDistance(); + +protected: + virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.cpp new file mode 100644 index 0000000..ea81550 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.cpp @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTService_UpdateTargetInfo.h" + +#include "AIController.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" + +UBTService_UpdateTargetInfo::UBTService_UpdateTargetInfo() +{ + NodeName = TEXT("UpdateTargetInfo"); + Interval = 0.5f; +} + +void UBTService_UpdateTargetInfo::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); + + AAIControllerBase* AIC = Cast(OwnerComp.GetAIOwner()); + if(!AIC) + return; + + AActor* Target = AIC->GetTargetActor(); + if(!Target) + return; + + if(Target) + { + AIC->UpdateTargetLocation(Target->GetActorLocation()); + AIC->UpdateTargetDirection(Target); + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.h new file mode 100644 index 0000000..e804e3e --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Services/BTService_UpdateTargetInfo.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTService.h" +#include "BTService_UpdateTargetInfo.generated.h" + + +UCLASS() +class PROJECTT_API UBTService_UpdateTargetInfo : public UBTService +{ + GENERATED_BODY() + +public: + UBTService_UpdateTargetInfo(); + +protected: + virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.cpp new file mode 100644 index 0000000..f866cfd --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.cpp @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_Alert.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" + +UBTTask_Alert::UBTTask_Alert() +{ + NodeName = TEXT("Alert"); + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_Alert::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ACoreNpc* Npc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Npc) + return EBTNodeResult::Failed; + + UBlackboardComponent* BBC = OwnerComp.GetBlackboardComponent(); + if(!BBC) + return EBTNodeResult::Failed; + + FVector TargetLocation = BBC->GetValueAsVector(UBlackboardKeyLibrary::GetTargetLocationKey()); + Npc->Alert(TargetLocation); + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.h new file mode 100644 index 0000000..f531652 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Alert.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_Alert.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_Alert : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_Alert(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.cpp new file mode 100644 index 0000000..30aabe0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.cpp @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_Attack.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTTask_Attack::UBTTask_Attack() +{ + NodeName = TEXT("Attack"); +} + +EBTNodeResult::Type UBTTask_Attack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return EBTNodeResult::Failed; + + AAIControllerBase* AIC = Cast(OwnerComp.GetAIOwner()); + if(!AIC) + return EBTNodeResult::Failed; + + AgentNpc->TryAttack(); + + return EBTNodeResult::Succeeded; +} + diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.h new file mode 100644 index 0000000..49a6a1b --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Attack.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_Attack.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_Attack : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_Attack(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.cpp new file mode 100644 index 0000000..25fcc4d --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.cpp @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_ChangeAgentAnim.h" + +#include "AIController.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.h" + +UBTTask_ChangeAgentAnim::UBTTask_ChangeAgentAnim() : + bNormal(true), + NpcNormalAnimState(ENpcNormalAnimState::Idle), + NpcAbnormalAnimState(ENpcAbnormalAnimState::HitBack) +{ + NodeName = TEXT("Change AgentAnim"); + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_ChangeAgentAnim::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return EBTNodeResult::Failed; + + USPNpcAgentAnimInstance* AnimInst = AgentNpc->GetAgentAnimInstance(); + if(!AnimInst) + return EBTNodeResult::Failed; + + if(bNormal) + { + AnimInst->SetNormalState(true); + AnimInst->ChangeNpcNormalAnimState(NpcNormalAnimState); + } + else + { + AnimInst->ChangeNpcAbnormalAnimState(NpcAbnormalAnimState); + } + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.h new file mode 100644 index 0000000..a002e57 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeAgentAnim.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "BTTask_ChangeAgentAnim.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_ChangeAgentAnim : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_ChangeAgentAnim(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +public: + UPROPERTY(EditAnywhere) + uint8 bNormal : 1; + + UPROPERTY(EditAnywhere, meta = (EditCondition="bNormal", EditConditionHides = true)) + ENpcNormalAnimState NpcNormalAnimState; + + UPROPERTY(EditAnywhere, meta = (EditCondition="!bNormal", EditConditionHides = true)) + ENpcAbnormalAnimState NpcAbnormalAnimState; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.cpp new file mode 100644 index 0000000..62fce00 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.cpp @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_ChangeBlackboardKey.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Bool.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Enum.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Vector.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" + +UBTTask_ChangeBlackboardKey::UBTTask_ChangeBlackboardKey() : + BoolValue(false), + VectorValue(FVector::ZeroVector), + NpcStateEnumValue(ENpcState::Default), + bIsBool(false), + bIsVector(false), + bIsNpcStateEnum(false) +{ + NodeName = TEXT("Change BlackboardKey"); +} + +#if WITH_EDITOR +void UBTTask_ChangeBlackboardKey::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); + + if(KeySelector.SelectedKeyType) + { + bIsBool = KeySelector.SelectedKeyType->IsChildOf(UBlackboardKeyType_Bool::StaticClass()); + bIsVector = KeySelector.SelectedKeyType->IsChildOf(UBlackboardKeyType_Vector::StaticClass()); + // FIXME + bIsNpcStateEnum = KeySelector.SelectedKeyType->IsChildOf(UBlackboardKeyType_Enum::StaticClass()); + } +} +#endif + +EBTNodeResult::Type UBTTask_ChangeBlackboardKey::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + UBlackboardComponent* BBC = OwnerComp.GetBlackboardComponent(); + if(!BBC) return EBTNodeResult::Failed; + + const FName KeyName = KeySelector.SelectedKeyName; + + if(bIsBool) + { + BBC->SetValueAsBool(KeyName, BoolValue); + } + else if(bIsVector) + { + BBC->SetValueAsVector(KeyName, VectorValue); + } + else if(bIsNpcStateEnum) + { + ACoreNpc* Npc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Npc) + return EBTNodeResult::Failed; + + Npc->ChangeNpcState(NpcStateEnumValue); + } + else + { + return EBTNodeResult::Failed; + } + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.h new file mode 100644 index 0000000..87025ce --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeBlackboardKey.h @@ -0,0 +1,51 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_ChangeBlackboardKey.generated.h" + + +enum class ENpcState : uint8; +enum class EPatrolType : uint8; + +UCLASS() +class PROJECTT_API UBTTask_ChangeBlackboardKey : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_ChangeBlackboardKey(); + +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +public: + UPROPERTY(EditAnywhere, Category = "BlackBoard") + FBlackboardKeySelector KeySelector; + + UPROPERTY(EditAnywhere, Category = "Value", meta = (EditCondition = "bIsBool", EditConditionHides)) + uint8 BoolValue : 1; + + UPROPERTY(EditAnywhere, Category = "Value", meta = (EditCondition = "bIsVector", EditConditionHides)) + FVector VectorValue; + + UPROPERTY(EditAnywhere, Category = "Value", meta = (EditCondition = "bIsNpcStateEnum", EditConditionHides)) + ENpcState NpcStateEnumValue; + +private: + UPROPERTY() + uint8 bIsBool : 1; + + UPROPERTY() + uint8 bIsVector : 1; + + UPROPERTY() + uint8 bIsNpcStateEnum : 1; + +}; + \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.cpp new file mode 100644 index 0000000..688b3e9 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_ChangeSpeed.h" + +#include "AIController.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTTask_ChangeSpeed::UBTTask_ChangeSpeed() : + SpeedType(ENpcSpeedType::Walk) +{ + NodeName = TEXT("ChangeSpeed"); + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_ChangeSpeed::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return EBTNodeResult::Failed; + + AgentNpc->ChangeSpeed(SpeedType); + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.h new file mode 100644 index 0000000..7f7fed7 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_ChangeSpeed.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_ChangeSpeed.generated.h" + + +enum class ENpcSpeedType : uint8; + +UCLASS() +class PROJECTT_API UBTTask_ChangeSpeed : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_ChangeSpeed(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +public: + UPROPERTY(EditAnywhere) + ENpcSpeedType SpeedType; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.cpp new file mode 100644 index 0000000..c834a45 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.cpp @@ -0,0 +1,68 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_MoveToLocation.h" + +#include "AIController.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType_Object.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTTask_MoveToLocation::UBTTask_MoveToLocation() : + AgentNpc(nullptr) +{ + NodeName = TEXT("Move To Location"); +} + +EBTNodeResult::Type UBTTask_MoveToLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + AgentNpc = OwnerComp.GetAIOwner()->GetPawn(); + if(!AgentNpc) + return EBTNodeResult::Failed; + + AAIController* AIController = OwnerComp.GetAIOwner(); + AIController->ClearFocus(EAIFocusPriority::Default); + AgentNpc->SetHeadRotationEnable(false); + + return PerformMoveTask(OwnerComp, NodeMemory); +} + +void UBTTask_MoveToLocation::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult) +{ + Super::OnTaskFinished(OwnerComp, NodeMemory, TaskResult); + + if(TaskResult == EBTNodeResult::Succeeded) + { + ArriveToTargetLocation(OwnerComp); + } + else if(TaskResult == EBTNodeResult::Failed) + { + NMT_LOG("Move Fail") + ArriveToTargetLocation(OwnerComp); + } + else if(TaskResult == EBTNodeResult::Aborted) + { + NMT_LOG("Move Aborted") + ArriveToTargetLocation(OwnerComp); + } +} + +void UBTTask_MoveToLocation::ArriveToTargetLocation(UBehaviorTreeComponent& OwnerComp) const +{ + UBlackboardComponent* BBC = OwnerComp.GetBlackboardComponent(); + if(!BBC) + return; + + if(!AgentNpc) + return; + + if(BBC->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey()) == nullptr) + { + if(AgentNpc->GetNpcState() == ENpcState::Chase) + { + AgentNpc->ChangeNpcState(ENpcState::Guard); + NMT_LOG("Arrive Target Location. To Guard"); + } + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.h new file mode 100644 index 0000000..cedc488 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToLocation.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/Tasks/BTTask_MoveTo.h" +#include "Navigation/PathFollowingComponent.h" + +#include "BTTask_MoveToLocation.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_MoveToLocation : public UBTTask_MoveTo +{ + GENERATED_BODY() + +public: + UBTTask_MoveToLocation(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult) override; + +private: + void ArriveToTargetLocation(UBehaviorTreeComponent& OwnerComp) const; + +private: + TObjectPtr AgentNpc; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.cpp new file mode 100644 index 0000000..123d9f3 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.cpp @@ -0,0 +1,83 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_MoveToNearestNavPoint.h" + +#include "AIController.h" +#include "NavigationSystem.h" +#include "Navigation/PathFollowingComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + +UBTTask_MoveToNearestNavPoint::UBTTask_MoveToNearestNavPoint() : + NavSearchExtent2D(300.f) +{ + NodeName = "Move To Nearest NavPoint"; + bCreateNodeInstance = true; +} + +EBTNodeResult::Type UBTTask_MoveToNearestNavPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ACoreNpc* Npc = OwnerComp.GetAIOwner()->GetPawn(); + if(!Npc) + return EBTNodeResult::Failed; + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(Npc); + if(!World) + return EBTNodeResult::Failed; + + UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent(World); + if(!NavSys) + return EBTNodeResult::Failed; + + CachedOwnerBTComp = &OwnerComp; + FNavLocation ProjectedLocation = FNavLocation(); + FVector StartPoint = Npc->GetActorLocation(); + NavSys->ProjectPointToNavigation(StartPoint,ProjectedLocation, FVector(NavSearchExtent2D, NavSearchExtent2D, StartPoint.Z)); + + if(ProjectedLocation.Location == FVector::ZeroVector) + return EBTNodeResult::Failed; + + USPNpcStatusComponent* NpcStatus = Npc->GetNpcStatusComponent(); + if(!NpcStatus) + return EBTNodeResult::Failed; + + FVector TargetLocation = FVector(ProjectedLocation.Location.X, ProjectedLocation.Location.Y, StartPoint.Z); + float Distance = FVector::Dist(StartPoint, TargetLocation); + float Speed = NpcStatus->GetStatusNpcRun(); + float Duration = FMath::Max(Distance / Speed, 1.f); + + LatentInfo.CallbackTarget = this; + LatentInfo.ExecutionFunction = FName("OnMoveFinished"); + LatentInfo.Linkage = 0; + LatentInfo.UUID = 0; + + UKismetSystemLibrary::MoveComponentTo(Npc->GetRootComponent(), + TargetLocation, + Npc->GetRootComponent()->GetComponentRotation(), + true, + true, + Duration, + false, + EMoveComponentAction::Type::Move, + LatentInfo); + + return EBTNodeResult::InProgress; +} + +void UBTTask_MoveToNearestNavPoint::OnMoveFinished() +{ + if(CachedOwnerBTComp) + { + if(AAIController* AIC = CachedOwnerBTComp->GetAIOwner()) + { + if(UPathFollowingComponent* PathFollowingComp = AIC->GetPathFollowingComponent()) + { + PathFollowingComp->Cleanup(); + } + } + + FinishLatentTask(*CachedOwnerBTComp, EBTNodeResult::Succeeded); + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.h new file mode 100644 index 0000000..e35c188 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_MoveToNearestNavPoint.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_MoveToNearestNavPoint.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_MoveToNearestNavPoint : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_MoveToNearestNavPoint(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + + UFUNCTION() + void OnMoveFinished(); + +public: + UPROPERTY(EditAnywhere) + float NavSearchExtent2D; + +protected: + UPROPERTY() + TObjectPtr CachedOwnerBTComp; + + FLatentActionInfo LatentInfo; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.cpp new file mode 100644 index 0000000..7b8e38e --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.cpp @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_Patrol.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/Core/Components/PathFollowComponent.h" + +UBTTask_Patrol::UBTTask_Patrol() +{ + NodeName = TEXT("Patrol"); + bNotifyTick = true; +} + +EBTNodeResult::Type UBTTask_Patrol::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + Super::ExecuteTask(OwnerComp, NodeMemory); + + APawn* OwnerPawn = OwnerComp.GetAIOwner()->GetPawn(); + if(!NMT_ENSURE(OwnerPawn)) + return EBTNodeResult::Failed; + + UPathFollowComponent* PathFollowComponent = OwnerPawn->FindComponentByClass(); + if(!NMT_ENSURE(PathFollowComponent)) + return EBTNodeResult::Failed; + + UBlackboardComponent* BBC = OwnerComp.GetBlackboardComponent(); + if(!BBC) + return EBTNodeResult::Failed; + + if(bool bMoveReverse = BBC->GetValueAsBool(UBlackboardKeyLibrary::GetMoveReverseKey())) + { + PathFollowComponent->MoveToNextWayPoint(bMoveReverse); + BBC->SetValueAsBool(UBlackboardKeyLibrary::GetMoveReverseKey(), false); + } + else + PathFollowComponent->MoveToNextWayPoint(); + + return EBTNodeResult::InProgress; +} + +void UBTTask_Patrol::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds); +} + +void UBTTask_Patrol::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult) +{ + Super::OnTaskFinished(OwnerComp, NodeMemory, TaskResult); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.h new file mode 100644 index 0000000..b7da7d8 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_Patrol.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_Patrol.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_Patrol : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_Patrol(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + virtual void OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.cpp new file mode 100644 index 0000000..99c8e88 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.cpp @@ -0,0 +1,82 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_RotateHead.h" + +#include "AIController.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTTask_RotateHead::UBTTask_RotateHead() : + HeadRotationType(EHeadRotationType::None) +{ + NodeName = TEXT("RotateHead"); + bNotifyTick = true; + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_RotateHead::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + AAIControllerBase* AIC = Cast(OwnerComp.GetAIOwner()); + if (!AIC) + return EBTNodeResult::Failed; + + FBTRotateHeadMemory* Memory = CastInstanceNodeMemory(NodeMemory); + Memory->Npc = Cast(AIC->GetPawn()); + if(!Memory->Npc.IsValid()) + return EBTNodeResult::Failed; + + switch(HeadRotationType) + { + case EHeadRotationType::None: + { + Memory->Npc->SetHeadRotationEnable(false); + return EBTNodeResult::Succeeded; + } + case EHeadRotationType::Pause: + { + Memory->Npc->ChangeHeadRotationState(HeadRotationType); + return EBTNodeResult::Succeeded; + } + case EHeadRotationType::TurnToTarget: + { + if(Memory->Npc->bCanRotateHeadToTarget) + return EBTNodeResult::Succeeded; + + Memory->Npc->bCanRotateHeadToTarget = true; + AActor* Target = AIC->GetTargetActor(); + if(Target) + Memory->Npc->SetHeadTargetRotation(Target->GetActorLocation()); + break; + } + case EHeadRotationType::Search: + case EHeadRotationType::Guard: + case EHeadRotationType::LoopSearch: + break; + } + + Memory->Npc->SetHeadRotationEnable(true); + Memory->Npc->ChangeHeadRotationState(HeadRotationType); + + return EBTNodeResult::InProgress; +} + +void UBTTask_RotateHead::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds); + + FBTRotateHeadMemory* Memory = CastInstanceNodeMemory(NodeMemory); + if(!Memory->Npc.IsValid()) + return; + + if(Memory->Npc->bReachedHeadRotation && HeadRotationType != EHeadRotationType::LoopSearch) + { + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + } +} + +uint16 UBTTask_RotateHead::GetInstanceMemorySize() const +{ + return sizeof(FBTRotateHeadMemory); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.h new file mode 100644 index 0000000..709625c --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateHead.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "BTTask_RotateHead.generated.h" + +struct FBTRotateHeadMemory +{ + TWeakObjectPtr Npc; +}; + +UCLASS() +class PROJECTT_API UBTTask_RotateHead : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_RotateHead(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + +protected: + virtual uint16 GetInstanceMemorySize() const override; + +public: + UPROPERTY(EditAnywhere) + EHeadRotationType HeadRotationType; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.cpp new file mode 100644 index 0000000..0dd1d09 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.cpp @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_RotateToDefault.h" + +#include "AIController.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.h" + +UBTTask_RotateToDefault::UBTTask_RotateToDefault() +{ + NodeName = "Rotate To Default"; + bNotifyTick = true; + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_RotateToDefault::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + if(!OwnerComp.GetAIOwner()) + return EBTNodeResult::Failed; + + FBTRotateToDefaultMemory* Memory = CastInstanceNodeMemory(NodeMemory); + Memory->NpcStationary = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Memory->NpcStationary.IsValid()) + return EBTNodeResult::Failed; + + return EBTNodeResult::InProgress; +} + +void UBTTask_RotateToDefault::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds); + + FBTRotateToDefaultMemory* Memory = CastInstanceNodeMemory(NodeMemory); + if(!Memory->NpcStationary.IsValid()) + return; + + Memory->CurrentRotation = Memory->NpcStationary->GetActorRotation(); + + float YawDelta = FMath::FindDeltaAngleDegrees(Memory->CurrentRotation.Yaw, Memory->NpcStationary->DefaultRotation.Yaw); + if (FMath::Abs(YawDelta) < 1.f) + { + Memory->NpcStationary->SetActorRotation(FRotator(Memory->CurrentRotation.Pitch, Memory->NpcStationary->DefaultRotation.Yaw, Memory->CurrentRotation.Roll)); + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + } + + Memory->NpcStationary->SetActorRotation(FMath::RInterpTo(Memory->CurrentRotation, FRotator(Memory->CurrentRotation.Pitch, Memory->NpcStationary->DefaultRotation.Yaw, Memory->CurrentRotation.Roll), DeltaSeconds, 5.f)); +} + +uint16 UBTTask_RotateToDefault::GetInstanceMemorySize() const +{ + return sizeof(FBTRotateToDefaultMemory); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.h new file mode 100644 index 0000000..b00907a --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToDefault.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_RotateToDefault.generated.h" + + +struct FBTRotateToDefaultMemory +{ + TWeakObjectPtr NpcStationary; + FRotator CurrentRotation; +}; + +UCLASS() +class PROJECTT_API UBTTask_RotateToDefault : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_RotateToDefault(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + +protected: + virtual uint16 GetInstanceMemorySize() const override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.cpp new file mode 100644 index 0000000..d2419f6 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.cpp @@ -0,0 +1,100 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_RotateToTargetDirection.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/Blackboard/BlackboardKeyType.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + +UBTTask_RotateToTargetDirection::UBTTask_RotateToTargetDirection() +{ + NodeName = "Rotate To Target Direction"; + bNotifyTick = true; +} + +EBTNodeResult::Type UBTTask_RotateToTargetDirection::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + if(!OwnerComp.GetAIOwner()) + return EBTNodeResult::Failed; + + FBTRotateToTargetDirMemory* Memory = CastInstanceNodeMemory(NodeMemory); + Memory->AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Memory->AgentNpc.IsValid()) + return EBTNodeResult::Failed; + + UpdateTargetRotation(OwnerComp, NodeMemory); + + Memory->bIsAtTargetRotation = FMath::IsNearlyEqual(Memory->AgentNpc->GetActorRotation().Yaw, Memory->TargetRotation.Yaw, 5.f); + + return EBTNodeResult::InProgress; +} + +void UBTTask_RotateToTargetDirection::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds); + + FBTRotateToTargetDirMemory* Memory = CastInstanceNodeMemory(NodeMemory); + if(!Memory->AgentNpc.IsValid()) + FinishLatentTask(OwnerComp, EBTNodeResult::Failed); + + USPNpcStatusComponent* NpcStatusComp = Memory->AgentNpc->GetNpcStatusComponent(); + if(!NpcStatusComp) + FinishLatentTask(OwnerComp, EBTNodeResult::Failed); + + if(NpcStatusComp->IsDead()) + FinishLatentTask(OwnerComp, EBTNodeResult::Failed); + + if(FMath::IsNearlyEqual(Memory->AgentNpc->GetActorRotation().Yaw, Memory->TargetRotation.Yaw, 5.f)) + { + Memory->AgentNpc->SetActorRotation(Memory->TargetRotation); + + if(Memory->AgentNpc->CanRotateWhileAttack()) + { + if(!Memory->bIsAtTargetRotation) + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + } + else + { + UpdateTargetRotation(OwnerComp, NodeMemory); + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + } + } + + if(Memory->AgentNpc->CanRotateWhileAttack()) + UpdateTargetRotation(OwnerComp, NodeMemory); + + Memory->AgentNpc->SetActorRotation(FMath::RInterpTo(Memory->AgentNpc->GetActorRotation(), Memory->TargetRotation, DeltaSeconds, 5.f)); +} + +uint16 UBTTask_RotateToTargetDirection::GetInstanceMemorySize() const +{ + return sizeof(FBTRotateToTargetDirMemory); +} + +void UBTTask_RotateToTargetDirection::UpdateTargetRotation(UBehaviorTreeComponent& InOwnerComp, uint8* InNodeMemory) const +{ + UBlackboardComponent* BBC = InOwnerComp.GetBlackboardComponent(); + if(!BBC) + return; + + FBTRotateToTargetDirMemory* Memory = CastInstanceNodeMemory(InNodeMemory); + if(!Memory->AgentNpc.IsValid()) + return; + + if(AActor* TargetActor = Cast(BBC->GetValueAsObject(UBlackboardKeyLibrary::GetTargetActorKey()))) + { + Memory->TargetRotation = UKismetMathLibrary::FindLookAtRotation(Memory->AgentNpc->GetActorLocation(), TargetActor->GetActorLocation()); + FVector TargetDir = (TargetActor->GetActorLocation() - Memory->AgentNpc->GetActorLocation()).GetSafeNormal(); + BBC->SetValueAsVector(UBlackboardKeyLibrary::GetTargetDirKey(), TargetDir); + } + else + { + FVector TargetDir = BBC->GetValueAsVector(UBlackboardKeyLibrary::GetTargetDirKey()); + Memory->TargetRotation = FRotationMatrix::MakeFromX(TargetDir).Rotator(); + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.h new file mode 100644 index 0000000..048bbd8 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_RotateToTargetDirection.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_RotateToTargetDirection.generated.h" + +/** + * + */ + +struct FBTRotateToTargetDirMemory +{ + TWeakObjectPtr AgentNpc; + FRotator TargetRotation; + uint8 bIsAtTargetRotation : 1; +}; + +UCLASS() +class PROJECTT_API UBTTask_RotateToTargetDirection : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_RotateToTargetDirection(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + +protected: + virtual uint16 GetInstanceMemorySize() const override; + +private: + void UpdateTargetRotation(UBehaviorTreeComponent& InOwnerComp, uint8* InNodeMemory) const; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.cpp new file mode 100644 index 0000000..cbd28c3 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_SelectNextPatrolType.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.h" + +UBTTask_SelectNextPatrolType::UBTTask_SelectNextPatrolType() +{ + NodeName = "Select NextPatrolType"; +} + +EBTNodeResult::Type UBTTask_SelectNextPatrolType::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ASPNpcPatrol* PatrolNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!PatrolNpc) + return EBTNodeResult::Failed; + + PatrolNpc->ChangePatrolType(); + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.h new file mode 100644 index 0000000..f2e1ca0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectNextPatrolType.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_SelectNextPatrolType.generated.h" + + +UCLASS() +class PROJECTT_API UBTTask_SelectNextPatrolType : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_SelectNextPatrolType(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.cpp new file mode 100644 index 0000000..5b6a9a4 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.cpp @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_SelectRandomPatrolDir.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Blackboard/BlackboardKeyLibrary.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +UBTTask_SelectRandomPatrolDir::UBTTask_SelectRandomPatrolDir() +{ + NodeName = "Random Patrol Dir"; +} + +EBTNodeResult::Type UBTTask_SelectRandomPatrolDir::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + ASPNpcAgent* AgentNpc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!AgentNpc) + return EBTNodeResult::Failed; + + UBlackboardComponent* BBC = OwnerComp.GetBlackboardComponent(); + if(!BBC) + return EBTNodeResult::Failed; + + bool RandomDir = FMath::RandBool(); + BBC->SetValueAsBool(UBlackboardKeyLibrary::GetMoveReverseKey(), RandomDir); + UE_LOG(LogTemp, Warning, TEXT("RandomDir %d"), RandomDir); + + return EBTNodeResult::Succeeded; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.h new file mode 100644 index 0000000..0b3f246 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_SelectRandomPatrolDir.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTask_SelectRandomPatrolDir.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API UBTTask_SelectRandomPatrolDir : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_SelectRandomPatrolDir(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.cpp new file mode 100644 index 0000000..b0dca23 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.cpp @@ -0,0 +1,80 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_UpdateDoubtGauge.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + +UBTTask_UpdateDoubtGauge::UBTTask_UpdateDoubtGauge() +{ + NodeName = TEXT("UpdateDoubtGauge"); + bNotifyTick = true; + bIgnoreRestartSelf = true; +} + +EBTNodeResult::Type UBTTask_UpdateDoubtGauge::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + if(!OwnerComp.GetAIOwner()) + return EBTNodeResult::Failed; + + ACoreNpc* Npc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + if(!Npc) + return EBTNodeResult::Failed; + + USPNpcStatusComponent* NpcStatusComp = Npc->GetNpcStatusComponent(); + if(!NpcStatusComp) + return EBTNodeResult::Failed; + + FBTUpdateDoubtGaugeMemory* Memory = CastInstanceNodeMemory(NodeMemory); + + Memory->CurrentDoubtTime = NpcStatusComp->GetStatusNpcDoubtTime(); + Memory->MaxDoubtTime = NpcStatusComp->GetStatusPreviousNpcDoubtTime(); + Memory->DoubtState = Npc->GetCurrentDoubtState(); + + return EBTNodeResult::InProgress; +} + +void UBTTask_UpdateDoubtGauge::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds); + + ACoreNpc* Npc = Cast(OwnerComp.GetAIOwner()->GetPawn()); + NMT_CHECKF(Npc); + + FBTUpdateDoubtGaugeMemory* Memory = CastInstanceNodeMemory(NodeMemory); + switch(Memory->DoubtState) + { + case EDoubtState::None: + { + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + break; + } + case EDoubtState::Increasing: + { + Memory->CurrentDoubtTime = FMath::Clamp(Memory->CurrentDoubtTime + DeltaSeconds, 0.f, Memory->MaxDoubtTime); + Npc->UpdateDoubtTime(Memory->CurrentDoubtTime); + break; + } + case EDoubtState::Decreasing: + { + if(Memory->CurrentDoubtTime <= 0.f) + { + Npc->ChangeDoubtState(EDoubtState::None); + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + } + + Memory->CurrentDoubtTime = FMath::Clamp(Memory->CurrentDoubtTime - (DeltaSeconds / 6.f), 0.f, Memory->MaxDoubtTime); + Npc->UpdateDoubtTime(Memory->CurrentDoubtTime); + break; + } + default: NOT_IMPLEMENTED() + } +} + +uint16 UBTTask_UpdateDoubtGauge::GetInstanceMemorySize() const +{ + return sizeof(FBTUpdateDoubtGaugeMemory); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.h new file mode 100644 index 0000000..8be4008 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/AI/BehaviorTree/Tasks/BTTask_UpdateDoubtGauge.h @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "BTTask_UpdateDoubtGauge.generated.h" + +/** + * + */ + +struct FBTUpdateDoubtGaugeMemory +{ + EDoubtState DoubtState; + float MaxDoubtTime; + float CurrentDoubtTime; +}; + +UCLASS() +class PROJECTT_API UBTTask_UpdateDoubtGauge : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UBTTask_UpdateDoubtGauge(); + + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; + +protected: + virtual uint16 GetInstanceMemorySize() const override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.cpp new file mode 100644 index 0000000..be89889 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.cpp @@ -0,0 +1,141 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNpcAgentAnimInstance.h" + +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" + +USPNpcAgentAnimInstance::USPNpcAgentAnimInstance() : + NpcActionMontage(nullptr), + CurrentNormalState(ENpcNormalAnimState::None), + PrevNormalState(ENpcNormalAnimState::None), + CurrentAbnormalState(ENpcAbnormalAnimState::None), + bWalk(false), + bRun(false), + bNormal(true), + bAction(false) +{ +} + +void USPNpcAgentAnimInstance::NativeInitializeAnimation() +{ + Super::NativeInitializeAnimation(); + + OwnerNpcCharacter = Cast(TryGetPawnOwner()); +} + +void USPNpcAgentAnimInstance::NativeUpdateAnimation(float DeltaSeconds) +{ + Super::NativeUpdateAnimation(DeltaSeconds); +} + +void USPNpcAgentAnimInstance::ChangeNpcAbnormalAnimState(const ENpcAbnormalAnimState InAbnormalState) +{ + bNormal = false; + + if(Montage_IsPlaying(NpcActionMontage)) + { + if(Montage_GetEndedDelegate(NpcActionMontage)->IsBound()) + Montage_GetEndedDelegate(NpcActionMontage)->Unbind(); + + Montage_Stop(0.f); + } + + switch(InAbnormalState) + { + case ENpcAbnormalAnimState::HitBack: + { + NMT_LOG("HitBack"); + break; + } + case ENpcAbnormalAnimState::JumpBack: + { + NMT_LOG("JumpBack"); + break; + } + case ENpcAbnormalAnimState::FallDown: + { + NMT_LOG("FallDown"); + break; + } + case ENpcAbnormalAnimState::Stun: + { + NMT_LOG("Stun"); + break; + } + case ENpcAbnormalAnimState::DeadStart: + { + NMT_LOG("DeadStart"); + break; + } + case ENpcAbnormalAnimState::DeadLoop: + { + OwnerNpcCharacter->StartDisableNpc(); + NMT_LOG("DeadLoop"); + break; + } + case ENpcAbnormalAnimState::GetUp: + { + NMT_LOG("GetUp"); + break; + } + case ENpcAbnormalAnimState::None: default: NMT_LOG("Not Valid"); + } + + CurrentAbnormalState = InAbnormalState; +} + +void USPNpcAgentAnimInstance::ChangeNpcNormalAnimState(const ENpcNormalAnimState InNormalState) +{ + if(!bNormal) + return; + + switch(InNormalState) + { + case ENpcNormalAnimState::Idle: + { + bWalk = false; + bRun = false; + break; + } + case ENpcNormalAnimState::Walk: + { + bWalk = true; + bRun = false; + break; + } + case ENpcNormalAnimState::Run: + { + bWalk = false; + bRun = true; + break; + } + default: NMT_LOG("Not Valid"); + } + + bNormal = true; + CurrentNormalState = InNormalState; +} + +void USPNpcAgentAnimInstance::ResetAnimState() +{ + SetNormalState(true); + CurrentNormalState = ENpcNormalAnimState::None; + PrevNormalState = ENpcNormalAnimState::None; + CurrentAbnormalState = ENpcAbnormalAnimState::None; +} + +void USPNpcAgentAnimInstance::SetActionMontage(class UAnimMontage* InActionMontage) +{ + NpcActionMontage = InActionMontage; +} + +void USPNpcAgentAnimInstance::SetNormalState(bool InNormal) +{ + bNormal = InNormal; +} + +void USPNpcAgentAnimInstance::SetActionState(bool InAction) +{ + bAction = InAction; +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.h new file mode 100644 index 0000000..7eae0b0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/Animations/SPNpcAgentAnimInstance.h @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Characters/NPC/Animations/NpcAnimInstance.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "SPNpcAgentAnimInstance.generated.h" + + +UCLASS() +class PROJECTT_API USPNpcAgentAnimInstance : public UNpcAnimInstance +{ + GENERATED_BODY() + +public: + USPNpcAgentAnimInstance(); + + virtual void NativeInitializeAnimation() override; + virtual void NativeUpdateAnimation(float DeltaSeconds) override; + + UFUNCTION(BlueprintCallable) + void ChangeNpcAbnormalAnimState(const ENpcAbnormalAnimState InAbnormalState); + + UFUNCTION(BlueprintCallable) + void ChangeNpcNormalAnimState(const ENpcNormalAnimState InNormalState); + + FORCEINLINE ENpcAbnormalAnimState GetNpcAbnormalAnimState() const { return CurrentAbnormalState; }; + void ResetAnimState(); + void SetActionMontage(UAnimMontage* InActionMontage); + void SetNormalState(bool InNormal); + void SetActionState(bool InAction); + +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + TObjectPtr OwnerNpcCharacter; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NpcAnimationState) + TObjectPtr NpcActionMontage; + + UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = NpcAnimationState) + ENpcNormalAnimState CurrentNormalState; + + UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = NpcAnimationState); + ENpcNormalAnimState PrevNormalState; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = NpcAnimationState) + ENpcAbnormalAnimState CurrentAbnormalState; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = NpcoAnimationState); + uint8 bWalk : 1; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = NpcAnimationState); + uint8 bRun : 1; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = NpcAnimationState); + uint8 bNormal : 1; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = NpcAnimationState); + uint8 bAction : 1; + +}; + diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.cpp new file mode 100644 index 0000000..8996088 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.cpp @@ -0,0 +1,1290 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNpcAgent.h" + +#include "NavigationSystem.h" +#include "NiagaraComponent.h" +#include "Animations/SPNpcAgentAnimInstance.h" +#include "Components/CapsuleComponent.h" +#include "Components/WidgetComponent.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateEnumEffectSubTypes.h" +#include "ProjectT/Data/Gen/GenerateEnumSkillTypes.h" +#include "ProjectT/Data/Gen/GenerateStructEffect.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIPerceptionController.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AISightController.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/Core/Common/AssetUtilsLibrary.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Components/ObstacleFilterComponent.h" +#include "ProjectT/System/Core/Components/PathFollowComponent.h" +#include "ProjectT/System/Core/Components/VisionConeComponent.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" +#include "ProjectT/System/Core/Managers/PooledActorManager.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" +#include "ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h" +#include "ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h" +#include "ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h" + + +ASPNpcAgent::ASPNpcAgent() : + CurrentSpeed(ENpcSpeedType::Walk), + SkillType(ESkillTypes::None), + ChaseRangeProfileName(TEXT("ChaseRange")), + DissolveParameterName(TEXT("Dissolve")), + SkillCoolTime(0.f), + DissolveElapsedTime(0.f), + DissolveDuration(1.5f), + bRotateWhileAttack(false), + bSkillCooldownActive(false), + bDissolving(false), + CurrentUsingSkill(nullptr), + AgentAnimInstance(nullptr), + NpcActionMontage(nullptr) +{ + PrimaryActorTick.bCanEverTick = true; + + AIControllerClass = AAISightController::StaticClass(); + GetCapsuleComponent()->SetCollisionProfileName(TEXT("Enemy")); + GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint); + GetMesh()->SetAnimInstanceClass(USPNpcAgentAnimInstance::StaticClass()); + GetMesh()->SetCustomDepthStencilValue(1); + WeaponStaticComponent->SetCustomDepthStencilValue(1); + WeaponStaticComponent->SetCustomDepthStencilValue(1); + + HpBarWidgetComponent = CreateDefaultSubobject(TEXT("HpBarWidgetComponent")); + DetectIndicatorWidget = CreateDefaultSubobject(TEXT("DetectIndicatorWidget")); + SphereChaseRangeComponent = CreateDefaultSubobject(TEXT("SphereChaseRangeComponent")); + DissolveFXComponent = CreateDefaultSubobject(TEXT("DissolveFXComponent")); + VisionLineMeshComponent = CreateDefaultSubobject(TEXT("VisionLineMeshComponent")); + NMT_CHECKF(HpBarWidgetComponent && DetectIndicatorWidget && SphereChaseRangeComponent && DissolveFXComponent && VisionLineMeshComponent) + + HpBarWidgetComponent->SetupAttachment(WidgetRootComponent); + HpBarWidgetComponent->SetWidgetSpace(EWidgetSpace::Screen); + + DetectIndicatorWidget->SetupAttachment(WidgetRootComponent); + DetectIndicatorWidget->SetWidgetSpace(EWidgetSpace::Screen); + + SphereChaseRangeComponent->SetupAttachment(SubRootComponent); + SphereChaseRangeComponent->SetCollisionProfileName(ChaseRangeProfileName); + SphereChaseRangeComponent->SetLineThickness(1.f); + + DissolveFXComponent->SetupAttachment(SubRootComponent); + DissolveFXComponent->bAutoActivate = false; + + VisionLineMeshComponent->SetupAttachment(SubRootComponent); + VisionLineMeshComponent->SetRelativeLocation(FVector(0, 0, -GetCapsuleComponent()->GetScaledCapsuleHalfHeight() - 1.f)); + VisionLineMeshComponent->SetHiddenInGame(true); + VisionLineMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + VisionLineMeshComponent->SetComponentTickEnabled(false); +} + +void ASPNpcAgent::PostInitializeComponents() +{ + Super::PostInitializeComponents(); +} + +void ASPNpcAgent::BeginPlay() +{ + Super::BeginPlay(); + + InitializeMaterials(); +} + +void ASPNpcAgent::InitializeStatus(const FEnemyNpc InNpcStatus) +{ + Super::InitializeStatus(InNpcStatus); + + GetCharacterMovement()->MaxWalkSpeed = InNpcStatus.fNpcMove; + + NMT_CHECKF(VisionConeComponent && NpcStatusComponent);; + VisionConeComponent->SetupSightSettings(NpcStatusComponent->GetStatusNpcSightLength(), NpcStatusComponent->GetStatusNpcSightAngle()); +} + +void ASPNpcAgent::Respawn() +{ + Super::Respawn(); + + GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Walking); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); +} + +void ASPNpcAgent::ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed) +{ + if(InButtonPressed == EKeys::RightMouseButton) + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + NMT_CHECKF(World) + ASPGameModeBase* SPGM = UGlobalUtilsLibrary::GetGameModeChecked(World); + NMT_CHECKF(SPGM) + USPEnemyVisionManager* EM = ISPObjectProvider::Execute_GetEnemyVisionManager(SPGM); + NMT_CHECKF(EM) + EM->RegisterFocused(this); + } +} + +void ASPNpcAgent::ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + GetMesh()->SetRenderCustomDepth(true); + WeaponStaticComponent->SetRenderCustomDepth(true); + WeaponDynamicComponent->SetRenderCustomDepth(true); +} + +void ASPNpcAgent::ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent) +{ + GetMesh()->SetRenderCustomDepth(false); + WeaponStaticComponent->SetRenderCustomDepth(false); + WeaponDynamicComponent->SetRenderCustomDepth(false); +} + +void ASPNpcAgent::ResetStateAfterGameEnd() +{ + Super::ResetStateAfterGameEnd(); + + StopSkillActionMontage(); + FinishCurrentSkill(); + FinishCheckInChaseRange(); +} + +#if WITH_EDITOR +void ASPNpcAgent::ApplyCharacterData(const FTableRowBase* RowData) +{ + Super::ApplyCharacterData(RowData); +} +#endif + +void ASPNpcAgent::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + if(bSkillCooldownActive) + { + UpdateSkillCooldown(DeltaTime); + } + + if(bDissolving) + { + UpdateDissolve(DeltaTime); + } + + if(CurrentVisionMode == EVisionMode::Line) + { + UpdateVisionLineLength(); + } +} + +void ASPNpcAgent::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + StopSkillActionMontage(); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + World->GetTimerManager().ClearTimer(CheckChaseRangeTimerHandle); + World->GetTimerManager().ClearTimer(JumpBackTimerHandle); + World->GetTimerManager().ClearTimer(EffectTimerHandle); +} + +bool ASPNpcAgent::GetUseSight_Implementation() +{ + return true; +} + +bool ASPNpcAgent::GetUseHearing_Implementation() +{ + return true; +} + +FSightInfo ASPNpcAgent::GetSightInfo_Implementation() +{ + NMT_CHECKF(NpcStatusComponent) + bool bNpcDataValid = !NpcStatusComponent->GetCurrentNpcStatus().IsDefault(); + if(!NMT_ENSURE(bNpcDataValid)) + return FSightInfo(); + + FSightInfo Info; + + Info.SightRange = NpcStatusComponent->GetStatusNpcSightLength(); + Info.SightAngle = NpcStatusComponent->GetStatusNpcSightAngle(); + Info.LoseSightRange = Info.SightRange + LoseSightOffset; + Info.SightMaxAge = PerceptionMaxAge; + + return Info; +} + +class UBlackboardData* ASPNpcAgent::GetBlackboardData_Implementation() +{ + return Blackboard; +} + +class UBehaviorTree* ASPNpcAgent::GetBehaviorTree_Implementation() +{ + return BehaviorTree; +} + +void ASPNpcAgent::DetectTargetBySight_Implementation(AActor* InTarget, FAIStimulus InStimulus) +{ + switch(CurrentState) + { + case ENpcState::Default: + { + ChangeDoubtState(EDoubtState::Increasing); + ChangeNpcState(ENpcState::Doubt); + break; + } + case ENpcState::Guard: case ENpcState::Returning: + { + ChangeNpcState(ENpcState::Chase); + ApplyStateToQuest(ENpcState::Chase); + break; + } + case ENpcState::Doubt: break; + case ENpcState::Chase: break; + case ENpcState::Attack: break; + case ENpcState::Hit: break; + case ENpcState::Dead: break; + default : NMT_LOG("Not Valid Type") + } +} + +void ASPNpcAgent::ForgetTarget_Implementation(AActor* InTarget) +{ + switch(CurrentState) + { + case ENpcState::Doubt: + { + GetAIControllerBase()->UpdateTargetInfo(nullptr); + ChangeNpcState(ENpcState::Default); + break; + } + case ENpcState::Default: break; + case ENpcState::Guard: break; + case ENpcState::Returning: break; + case ENpcState::Chase: break; + case ENpcState::Attack: break; + case ENpcState::Hit: break; + case ENpcState::Dead : break; + default : NMT_LOG("Not Valid Type") + } +} + +FTransform ASPNpcAgent::GetViewTransform_Implementation() +{ + FTransform Transform; + Transform.SetLocation(SubRootComponent->GetComponentLocation()); + Transform.SetRotation(SubRootComponent->GetComponentRotation().Quaternion()); + Transform.SetScale3D(FVector(1, 1, 1)); + + return Transform; +} + +void ASPNpcAgent::InitializeProperty() +{ + Super::InitializeProperty(); + + AgentAnimInstance = Cast(GetMesh()->GetAnimInstance()); + NMT_CHECKF(AgentAnimInstance); + AgentAnimInstance->SetActionMontage(NpcActionMontage); + + NMT_CHECKF(SphereChaseRangeComponent && NpcStatusComponent); + FObstacleFilterInfo FilterInfo; + FilterInfo.TraceCollisionChannels.Add(ECC_GameTraceChannel4); // NOTE : Wall + FilterInfo.TraceCollisionChannels.Add(ECC_GameTraceChannel6); // NOTE : Prop + FilterInfo.SphereRadius = NpcStatusComponent->GetStatusNpcChaseLength(); + FilterInfo.CheckOutOfRange = true; + SphereChaseRangeComponent->InitializeProperty(FilterInfo); + SphereChaseRangeComponent->DeactivateFiltering(); + + SetSkillClass(); +} + +void ASPNpcAgent::ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + float LocFinalDamage = CCM->GetDebugStatus().bDebugPlayerDamage? InDamage + 1000.f : InDamage; + + if(NpcStatusComponent->ApplyDamage(LocFinalDamage)) + { + ChangeNpcState(ENpcState::Dead); + } + else + { + if(CCM->GetDebugStatus().bDebugEnemyInvincibleStatusEffect) return; + if(InDamage > 0.f) + { + HpBarWidgetComponent->GetUserWidgetObject()->SetVisibility(ESlateVisibility::SelfHitTestInvisible); + GetAIControllerBase()->UpdateTargetInfo(InOccurActor); + } + + for(FEffect EffectType : InSkillEffects) + { + const EEffectSubTypes EffectSubType = UGlobalUtilsLibrary::GetStringToEnum(EffectType.sEffect); + if(CheckEffectTime(EffectType)) + { + switch(EffectSubType) + { + case EEffectSubTypes::None: + { + ChangeNpcState(ENpcState::Chase); + break; + } + case EEffectSubTypes::Hitback: + { + ChangeNpcState(ENpcState::Hit); + if(!NpcStatusComponent->IsDead()) + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::HitBack); + break; + } + case EEffectSubTypes::Jumpback: + { + ChangeNpcState(ENpcState::Hit); + JumpBack(InOriginLocation); + break; + } + case EEffectSubTypes::Slow: + { + if(InDamage > 0.f && CurrentState != ENpcState::Attack) + { + SetReturnLocationFromDefault(); + ChangeNpcState(ENpcState::Chase); + } + + StatusSlow(EffectType.fEffectValue); + break; + } + case EEffectSubTypes::Fast: + { + if(InDamage > 0.f && CurrentState != ENpcState::Attack) + { + SetReturnLocationFromDefault(); + ChangeNpcState(ENpcState::Chase); + } + + StatusFast(EffectType.fEffectValue); + break; + } + case EEffectSubTypes::Bind: + { + if(InDamage > 0.f && CurrentState != ENpcState::Attack) + { + SetReturnLocationFromDefault(); + ChangeNpcState(ENpcState::Chase); + } + + ChangeSpeed(ENpcSpeedType::Stop, true); + break; + } + case EEffectSubTypes::Unrecog: + { + SetUnDetectTarget(true); + break; + } + case EEffectSubTypes::CogImmune: NOT_IMPLEMENTED_MSG("EEffectSubTypes::CogImmune"); break; + case EEffectSubTypes::Stun: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Stun"); break; + case EEffectSubTypes::Surge: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Surge"); break; + case EEffectSubTypes::HitbackImmune: NOT_IMPLEMENTED_MSG("EEffectSubTypes::HitbackImmune"); break; + case EEffectSubTypes::Heal: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Heal"); break; + default: NMT_LOG("Not Valid"); + } + AddEffectTimeMap(EffectType); + } + } + } +} + +void ASPNpcAgent::ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) +{ + for(FEffect LocCurEffect : InReleaseEffects) + { + EEffectSubTypes LoCurReleaseEffect = UGlobalUtilsLibrary::GetStringToEnum(LocCurEffect.sEffect); + EffectTimeMap.Remove(LoCurReleaseEffect); + if(EffectTimeMap.IsEmpty()) + { + GetWorld()->GetTimerManager().ClearTimer(EffectTimerHandle); + } + switch(LoCurReleaseEffect) + { + case EEffectSubTypes::Unrecog: + { + SetUnDetectTarget(false); + break; + } + case EEffectSubTypes::Surge: + { + if(CurrentState == ENpcState::Default) + { + ChangeNpcState(ENpcState::Returning); + } + break; + } + case EEffectSubTypes::Bind: + { + if(CurrentState == ENpcState::Returning || CurrentState == ENpcState::Chase || CurrentState == ENpcState::Attack) + { + ChangeSpeed(ENpcSpeedType::Run); + } + else + { + ChangeSpeed(ENpcSpeedType::Walk); + } + break; + } + case EEffectSubTypes::Fast: + { + StatusFast(LocCurEffect.fEffectValue, true); + break; + } + case EEffectSubTypes::Slow: + { + StatusSlow(LocCurEffect.fEffectValue, true); + break; + } + case EEffectSubTypes::Hitback: NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::Hitback"); break; + case EEffectSubTypes::Jumpback: NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::Jumpback"); break; + case EEffectSubTypes::CogImmune: NOT_IMPLEMENTED_MSG("Release EEffectSubTypes::CogImmune"); break; + case EEffectSubTypes::None: break; + case EEffectSubTypes::Stun: break; + case EEffectSubTypes::HitbackImmune: break; + case EEffectSubTypes::Heal: break; + default: NMT_LOG("No Release Effect Type") + } + } +} + +void ASPNpcAgent::StartDisableNpc() +{ + Super::StartDisableNpc(); + + DissolveFXComponent->Activate(true); + bDissolving = true; + NotifyVisionDetection(false); + ChangeSpeed(ENpcSpeedType::Stop, true); + ClearSkillCoolTime(); + FinishCurrentSkill(); + FinishCheckInChaseRange(); +} + +void ASPNpcAgent::CompleteDisableNpc() +{ + Super::CompleteDisableNpc(); + + AgentAnimInstance->ResetAnimState(); + for(UMeshComponent* MeshComponent : AllMeshComponents) + { + if(MeshComponent == nullptr) + continue; + + MeshComponent->SetScalarParameterValueOnMaterials(DissolveParameterName, 1.f); + } +} + +class USPNpcAgentAnimInstance* ASPNpcAgent::GetAgentAnimInstance() const +{ + NMT_CHECKF(AgentAnimInstance); + return AgentAnimInstance; +} + +void ASPNpcAgent::ChangeNpcState(const ENpcState InState) +{ + PrevState = CurrentState; + + if(CurrentState != InState) + { + switch(InState) + { + case ENpcState::Default: + { + bCanRotateHeadToTarget = true; + if(CurrentDoubtState == EDoubtState::Increasing) + ChangeDoubtState(EDoubtState::Decreasing); + break; + } + case ENpcState::Doubt: + { + NotifyVisionDetection(true); + AgentAnimInstance->SetNormalState(true); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); + break; + } + case ENpcState::Chase: + { + if(GetAIControllerBase()->GetTargetActor()) + StartCheckInChaseRange(); + + ChangeDoubtState(EDoubtState::None); + NotifyVisionDetection(false); + break; + } + case ENpcState::Attack: + { + if(GetAIControllerBase()->GetTargetActor()) + StartCheckInChaseRange(); + + NotifyVisionDetection(false); + break; + } + case ENpcState::Guard: + { + bCanTriggerAlert = true; + ChangeSpeed(ENpcSpeedType::Stop); + AgentAnimInstance->SetNormalState(true); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); + break; + } + case ENpcState::Hit: + { + SetReturnLocationFromDefault(); + StopSkillActionMontage(); + ClearSkillCoolTime(); + GetAIControllerBase()->SetEnableAttack(true); + FinishCurrentSkill(); + ChangeSpeed(ENpcSpeedType::Stop, true); + SetVisionMode(EVisionMode::None); + break; + } + case ENpcState::Dead: + { + ChangeSpeed(ENpcSpeedType::Stop, true); + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::DeadStart); + ApplyStateToQuest(ENpcState::Dead); + HpBarWidgetComponent->GetUserWidgetObject()->SetVisibility(ESlateVisibility::Collapsed); + break; + } + case ENpcState::Returning: + { + break; + } + default: NMT_LOG("Not Valid ENpcState") + } + } +} + +void ASPNpcAgent::ActivateCharacter(const bool InbEnable) +{ + Super::ActivateCharacter(InbEnable); + + DetectIndicatorWidget->SetVisibility(InbEnable); + + if(InbEnable) + GetAIControllerBase()->SetCanRotateWhileAttack(bRotateWhileAttack); +} + +void ASPNpcAgent::SetDetectTargetFromNoise(AActor* InTarget) +{ + Super::SetDetectTargetFromNoise(InTarget); +} + +void ASPNpcAgent::SetDetectLocationFromNoise(const FVector& InTargetLocation) +{ + Super::SetDetectLocationFromNoise(InTargetLocation); +} + +void ASPNpcAgent::ChangeSpeed(const ENpcSpeedType InSpeed, const bool InbStopImmediately) +{ + float Speed = 0.f; + switch(InSpeed) + { + case ENpcSpeedType::Walk: + { + Speed = NpcStatusComponent->GetStatusNpcMove(); + break; + } + case ENpcSpeedType::Run: + { + Speed = NpcStatusComponent->GetStatusNpcRun(); + break; + } + case ENpcSpeedType::Stop: + { + if(InbStopImmediately) + GetCharacterMovement()->StopMovementImmediately(); + + if(UPathFollowComponent* PathFollowComponent = FindComponentByClass()) + PathFollowComponent->StopMove(); + break; + } + default: NMT_LOG("Not Valid Type") + } + + CurrentSpeed = InSpeed; + EffectTimeMap.Find(EEffectSubTypes::Bind) ? GetCharacterMovement()->MaxWalkSpeed = 0.f : GetCharacterMovement()->MaxWalkSpeed = Speed; +} + +class ACoreSkill* ASPNpcAgent::GetCurrentSkill() const +{ + return CurrentUsingSkill; +} + +void ASPNpcAgent::GetSkillClass(TSubclassOf& OutSkillClass) const +{ + OutSkillClass = NpcSkillClass; +} + +void ASPNpcAgent::UpdateDissolve(const float InDeltaSeconds) +{ + DissolveElapsedTime += InDeltaSeconds; + float Alpha = FMath::Clamp(1.f - (DissolveElapsedTime / DissolveDuration), 0.f, 1.f); + + if(FMath::IsNearlyZero(Alpha)) + { + bDissolving = false; + DissolveElapsedTime = 0.f; + CompleteDisableNpc(); + } + else + { + for(UMeshComponent* MeshComponent : AllMeshComponents) + { + if(MeshComponent == nullptr) + continue; + + MeshComponent->SetScalarParameterValueOnMaterials(DissolveParameterName, Alpha); + } + } +} + +void ASPNpcAgent::NotifyVisionDetection(const bool InbDetect) +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + NMT_CHECKF(World) + ASPGameModeBase* SPGM = UGlobalUtilsLibrary::GetGameModeChecked(World); + NMT_CHECKF(SPGM) + USPEnemyVisionManager* EM = ISPObjectProvider::Execute_GetEnemyVisionManager(SPGM); + if(EM) + { + InbDetect ? EM->RegisterDetection(this) : EM->UnregisterDetection(this); + } +} + +void ASPNpcAgent::ShowVisual_Implementation() +{ + +} + +void ASPNpcAgent::HideVisual_Implementation() +{ +} + +void ASPNpcAgent::UpdateVisionLineLength() +{ + AActor* Target = GetAIControllerBase()->GetTargetActor(); + if(!Target) + return; + + NMT_CHECKF(VisionLineMeshComponent) + FVector Start = VisionLineMeshComponent->GetComponentLocation(); + FVector End = Target->GetActorLocation(); + float Distance = FVector::Dist2D(Start, End); + float ScaleX = Distance / 100.f; + FRotator LookRotator = UKismetMathLibrary::FindLookAtRotation(Start, End); + + VisionLineMeshComponent->SetRelativeScale3D(FVector(ScaleX, 1.f, 1.f)); + VisionLineMeshComponent->SetWorldRotation(LookRotator); +} + +void ASPNpcAgent::PlayActionMontage(FName InSectionName, FOnMontageBlendingOutStarted InEndedFunction) +{ + NMT_CHECKF(AgentAnimInstance) + if(!NMT_ENSURE(NpcActionMontage)) + return; + + AgentAnimInstance->SetActionState(true); + + AgentAnimInstance->Montage_Play(NpcActionMontage, 1, EMontagePlayReturnType::MontageLength, 0, true); + if(AgentAnimInstance->GetInstanceForMontage(NpcActionMontage)) + { + FAnimMontageInstance* MontageInstance = AgentAnimInstance->GetInstanceForMontage(NpcActionMontage); + if(MontageInstance && MontageInstance->OnMontageBlendingOutStarted.IsBound()) + { + MontageInstance->OnMontageBlendingOutStarted.Unbind(); + } + } + AgentAnimInstance->Montage_SetBlendingOutDelegate(InEndedFunction); + AgentAnimInstance->Montage_JumpToSection(InSectionName); +} + +void ASPNpcAgent::TryAttack() +{ + if(!IsFinishSkillCoolDown()) + { + NMT_LOGF("Skill CoolDown.. : %f", SkillCoolTime) + return; + } + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(World); + UPooledActorManager* LocPoolManager = IWorldObjectProvider::Execute_GetPooledActorManager(LocGameMode); + if(!LocPoolManager) + return; + + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); + ChangeSpeed(ENpcSpeedType::Stop, true); + CurrentUsingSkill = Cast(LocPoolManager->Obtain(NpcSkillClass)); + if(CurrentUsingSkill) + { + CurrentUsingSkill->SetSkillOwner(this); + StartAttack(); + GetAIControllerBase()->SetEnableAttack(false); + SetHeadRotationEnable(false); + return; + } + + NMT_MSG_ENSURE(0, "Fail to obtain Npc Skill"); +} + +void ASPNpcAgent::StartAttack() +{ + FSkill SkillData = CurrentUsingSkill->GetSkillData(); + ActionMontageSectionName = SkillData.sSkillName; + + switch(SkillType) + { + case ESkillTypes::Melee: + { + CurrentUsingSkill->StartSkill(); + SetSkillCoolTime(SkillData.fCooldown); + PlayActionMontage(FName(*ActionMontageSectionName), FOnMontageBlendingOutStarted::CreateWeakLambda(this, [this](UAnimMontage* Montage, bool Interrupted) + { + TryFinishAttack(); + })); + } + break; + case ESkillTypes::Direct: + { + if(PrevState == ENpcState::Attack) + { + ContinueAttack(); + return; + } + + CurrentUsingSkill->StartSkill(); + ActionMontageSectionName.Append("Draw"); + PlayActionMontage(FName(*ActionMontageSectionName), FOnMontageBlendingOutStarted::CreateWeakLambda(this, [this](UAnimMontage* Montage, bool Interrupted) + { + ContinueAttack(); + })); + } + break; + case ESkillTypes::None: NOT_IMPLEMENTED_MSG("StartAttack::None") + break; + case ESkillTypes::Buff: NOT_IMPLEMENTED_MSG("StartAttack::None") + break; + case ESkillTypes::Indirect: NOT_IMPLEMENTED_MSG("StartAttack::None") + break; + default : NMT_LOG("Not Valid Type") + } +} + +void ASPNpcAgent::ContinueAttack() +{ + if(CurrentUsingSkill == nullptr) return; + FSkill SkillData = CurrentUsingSkill->GetSkillData(); + ActionMontageSectionName = SkillData.sSkillName; + + switch(SkillType) + { + case ESkillTypes::Direct: + { + CurrentUsingSkill->ActivateSkill(); + SetSkillCoolTime(SkillData.fCooldown); + ActionMontageSectionName.Append("Shoot"); + PlayActionMontage(FName(*ActionMontageSectionName)); + } + break; + case ESkillTypes::Melee: NOT_IMPLEMENTED_MSG("ContinueAttack::Melee") + break; + case ESkillTypes::None: NOT_IMPLEMENTED_MSG("ContinueAttack::None") + break; + case ESkillTypes::Buff: NOT_IMPLEMENTED_MSG("ContinueAttack::None") + break; + case ESkillTypes::Indirect: NOT_IMPLEMENTED_MSG("ContinueAttack::None") + break; + default : NMT_LOG("Not Valid Type") + } +} + +void ASPNpcAgent::TryFinishAttack() +{ + NMT_LOG("TryFinishAttack") + switch(SkillType) + { + case ESkillTypes::Melee: + { + GetAIControllerBase()->SetEnableAttack(true); + FinishCurrentSkill(); + ShouldContinueAttack() ? ChangeNpcState(ENpcState::Attack) : ChangeNpcState(ENpcState::Chase); + } + break; + case ESkillTypes::Direct: + { + if(CurrentUsingSkill == nullptr) + { + GetAIControllerBase()->SetEnableAttack(true); + return; + } + + FSkill SkillData = CurrentUsingSkill->GetSkillData(); + ActionMontageSectionName = SkillData.sSkillName; + + if(ShouldContinueAttack()) + { + NMT_LOG("Attack Again") + GetAIControllerBase()->SetEnableAttack(true); + FinishCurrentSkill(); + ChangeNpcState(ENpcState::Attack); + } + else + { + ActionMontageSectionName.Append("Undraw"); + PlayActionMontage(FName(*ActionMontageSectionName), FOnMontageBlendingOutStarted::CreateWeakLambda(this, [this](UAnimMontage* Montage, bool Interrupted) + { + FinishAttack(); + })); + } + } + break; + case ESkillTypes::None: NOT_IMPLEMENTED_MSG("ESkillTypes::None") + break; + case ESkillTypes::Buff: NOT_IMPLEMENTED_MSG("ESkillTypes::None") + break; + case ESkillTypes::Indirect: NOT_IMPLEMENTED_MSG("ESkillTypes::None") + break; + default : NMT_LOG("Not Valid Type") + } +} + +void ASPNpcAgent::FinishAttack() +{ + FinishCurrentSkill(); + + if(!GetController()) + return; + + GetAIControllerBase()->SetEnableAttack(true); + if(!ShouldContinueAttack()) + ChangeNpcState(ENpcState::Chase); +} + +void ASPNpcAgent::SetUnDetectTarget(const bool InbUnDetect) +{ + Super::SetUnDetectTarget(InbUnDetect); + + GetAIPerceptionController()->SetUnDetect(bUnDetect); + if(bUnDetect) + { + if(CurrentVisionMode == EVisionMode::Cone) + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + NMT_CHECKF(World) + ASPGameModeBase* SPGM = UGlobalUtilsLibrary::GetGameModeChecked(World); + NMT_CHECKF(SPGM) + USPEnemyVisionManager* EM = ISPObjectProvider::Execute_GetEnemyVisionManager(SPGM); + NMT_CHECKF(EM) + EM->IsFocusedNpc(this) ? EM->UnregisterFocused() : EM->UnregisterDetection(this); + } + } + else + { + GetAIPerceptionController()->ForceUpdatePerception(); + } +} + +void ASPNpcAgent::SetVisionMode(EVisionMode InVisionMode) +{ + CurrentVisionMode = InVisionMode; + NMT_CHECKF(VisionConeComponent && VisionLineMeshComponent) + + switch(InVisionMode) + { + case EVisionMode::None: + { + VisionConeComponent->ToggleDraw(false); + VisionLineMeshComponent->SetHiddenInGame(true); + VisionLineMeshComponent->SetComponentTickEnabled(false); + break; + } + case EVisionMode::Cone: + { + VisionConeComponent->ToggleDraw(true); + VisionLineMeshComponent->SetHiddenInGame(true); + VisionLineMeshComponent->SetComponentTickEnabled(false); + break; + } + case EVisionMode::Line: + { + VisionConeComponent->ToggleDraw(false); + VisionLineMeshComponent->SetComponentTickEnabled(true); + VisionLineMeshComponent->SetHiddenInGame(false); + break; + } + } +} + +void ASPNpcAgent::ChangeDoubtState(const EDoubtState InDoubtState) +{ + Super::ChangeDoubtState(InDoubtState); + + switch(InDoubtState) + { + case EDoubtState::None: + { + NotifyVisionDetection(false); + break; + } + case EDoubtState::Increasing: case EDoubtState::Decreasing: break; + default: NOT_IMPLEMENTED(); + } +} + +void ASPNpcAgent::InitializeMaterials() +{ + TArray MeshComponents; + GetComponents(MeshComponents); + + for(UMeshComponent* MeshComp : MeshComponents) + { + AllMeshComponents.Add(MeshComp); + } +} + +void ASPNpcAgent::StatusSlow(float InSlowValue, bool InbRecovery) +{ + float LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Slow)? LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Slow)->EffectValue : LocBeforeValue = 0.f; + if(LocBeforeValue == InSlowValue) return; + if(!InbRecovery) InSlowValue = InSlowValue * -1.f; + float LocSlowValue = InSlowValue - LocBeforeValue; + NpcStatusComponent->AddStatusNpcMove(LocSlowValue); + NpcStatusComponent->AddStatusNpcRun(LocSlowValue); + + if(CurrentSpeed == ENpcSpeedType::Walk) + GetCharacterMovement()->MaxWalkSpeed = GetNpcStatusComponent()->GetCurrentNpcStatus().fNpcMove; + else if(CurrentSpeed == ENpcSpeedType::Run) + GetCharacterMovement()->MaxWalkSpeed = GetNpcStatusComponent()->GetCurrentNpcStatus().fNpcRun; +} + +void ASPNpcAgent::StatusFast(float InFastValue, bool InbRecovery) +{ + float LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Fast)? LocBeforeValue = EffectTimeMap.Find(EEffectSubTypes::Fast)->EffectValue : LocBeforeValue = 0.f; + if(LocBeforeValue == InFastValue) return; + if(InbRecovery) InFastValue = InFastValue * -1.f; + float LocFastValue = InFastValue - LocBeforeValue; + NpcStatusComponent->AddStatusNpcMove(LocFastValue); + NpcStatusComponent->AddStatusNpcRun(LocFastValue); + + if(CurrentSpeed == ENpcSpeedType::Walk) + GetCharacterMovement()->MaxWalkSpeed = GetNpcStatusComponent()->GetCurrentNpcStatus().fNpcMove; + else if(CurrentSpeed == ENpcSpeedType::Run) + GetCharacterMovement()->MaxWalkSpeed = GetNpcStatusComponent()->GetCurrentNpcStatus().fNpcRun; +} + +void ASPNpcAgent::JumpBack(const FVector& InTargetLocation) +{ + FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), InTargetLocation); + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::JumpBack); + float JumpPower = 100.f; + FVector JumpDir = (GetActorLocation() - InTargetLocation).GetSafeNormal(); + FVector JumpBackVector = JumpPower * JumpDir; + FVector LaunchVelocity; + + SetActorRotation(LookAtRotation); + UGlobalUtilsLibrary::SuggestProjectileVelocityAtLocation(GetWorld(), LaunchVelocity, GetActorLocation(), + GetActorLocation() + JumpBackVector, 40.f, 0.f, 1.f); + LaunchCharacter(LaunchVelocity, true, true); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(!World->GetTimerManager().IsTimerActive(JumpBackTimerHandle)) + { + World->GetTimerManager().SetTimer(JumpBackTimerHandle, this, &ASPNpcAgent::CheckFallingFromJumpBack, World->GetDeltaSeconds(), true, 0.2f); + } +} + +void ASPNpcAgent::CheckFallingFromJumpBack() +{ + if(!GetMovementComponent()->IsFalling() && GetWorld()->GetTimerManager().IsTimerActive(JumpBackTimerHandle)) + { + GetWorld()->GetTimerManager().ClearTimer(JumpBackTimerHandle); + JumpBackTimerHandle.Invalidate(); + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::FallDown); + // RelocateOnNavMesh(); + } +} + +bool ASPNpcAgent::ShouldContinueAttack() const +{ + AActor* Target = GetAIControllerBase()->GetTargetActor(); + if(Target && IsTargetInAttackRange(Target)) + { + if(SkillType == ESkillTypes::Direct) + { + NMT_CHECKF(NpcStatusComponent) + FCollisionObjectQueryParams ObjectQueryParams; + ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel4); // NOTE : Wall + ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel6); // NOTE : Prop + FHitResult HitResult; + FVector EndTraceLocation = GetActorLocation() + GetActorForwardVector() * NpcStatusComponent->GetStatusNpcAttackLength(); + GetWorld()->LineTraceSingleByObjectType(HitResult, GetActorLocation(), EndTraceLocation, ObjectQueryParams, FCollisionQueryParams()); + return !HitResult.bBlockingHit; + } + + return true; + } + + return false; +} + +void ASPNpcAgent::DetermineNextStateAfterAbnormal() +{ + ENpcAbnormalAnimState AbnormalAnimState = AgentAnimInstance->GetNpcAbnormalAnimState(); + + switch(AbnormalAnimState) + { + case ENpcAbnormalAnimState::HitBack: + { + if(!NpcStatusComponent->IsDead()) + { + AgentAnimInstance->SetNormalState(true); + ChangeNpcState(ENpcState::Chase); + } + break; + } + case ENpcAbnormalAnimState::FallDown: + { + if(!NpcStatusComponent->IsDead()) + { + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::GetUp); + } + else + { + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::DeadLoop); + ChangeNpcState(ENpcState::Dead); + } + break; + } + case ENpcAbnormalAnimState::GetUp: + { + AgentAnimInstance->SetNormalState(true); + AActor* Target = GetAIControllerBase()->GetTargetActor(); + if(Target) + { + IsTargetInAttackRange(Target) ? ChangeNpcState(ENpcState::Attack) : ChangeNpcState(ENpcState::Chase); + } + else + { + ChangeNpcState(ENpcState::Chase); + } + + break; + } + case ENpcAbnormalAnimState::DeadStart: + { + AgentAnimInstance->ChangeNpcAbnormalAnimState(ENpcAbnormalAnimState::DeadLoop); + GetMesh()->bPauseAnims = true; + break; + } + case ENpcAbnormalAnimState::DeadLoop: case ENpcAbnormalAnimState::JumpBack: case ENpcAbnormalAnimState::Stun: NOT_IMPLEMENTED() + break; + default: NMT_LOG("Not Valid") + } +} + +void ASPNpcAgent::SetCurrentUsingSkill(class ACoreSkill* InSkill) +{ + CurrentUsingSkill = InSkill; +} + +void ASPNpcAgent:: FinishCurrentSkill() +{ + if(CurrentUsingSkill) + { + NMT_LOG("FinishCurrentSkill") + CurrentUsingSkill->FinishSkill(); + CurrentUsingSkill = nullptr; + } +} + +void ASPNpcAgent::SetSkillCoolTime(const float InCoolTime) +{ + SkillCoolTime = InCoolTime; + bSkillCooldownActive = true; +} + +class AAIPerceptionController* ASPNpcAgent::GetAIPerceptionController() const +{ + AAIPerceptionController* AIC = Cast(GetController()); + NMT_CHECKF(AIC) + + return AIC; +} + +bool ASPNpcAgent::IsFinishSkillCoolDown() const +{ + return SkillCoolTime <= 0.f; +} + +bool ASPNpcAgent::IsTargetInAttackRange(const AActor* InTarget) const +{ + NMT_CHECKF(NpcStatusComponent) + return GetHorizontalDistanceTo(InTarget) <= NpcStatusComponent->GetStatusNpcAttackLength(); +} + +void ASPNpcAgent::StartCheckInChaseRange() +{ + NMT_CHECKF(SphereChaseRangeComponent) + if(!SphereChaseRangeComponent->OnExitedSphereRange.IsBound()) + { + SphereChaseRangeComponent->ActivateFiltering(); + SphereChaseRangeComponent->OnEnterSphereRange.AddWeakLambda(this, [this](AActor* Target) + { + GetAIControllerBase()->UpdateTargetInfo(Target); + }); + SphereChaseRangeComponent->OnExitedSphereRange.AddWeakLambda(this, [this]() + { + GetAIControllerBase()->UpdateTargetInfo(nullptr); + }); + } + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(!World->GetTimerManager().IsTimerActive(CheckChaseRangeTimerHandle)) + World->GetTimerManager().SetTimer(CheckChaseRangeTimerHandle, this, &ASPNpcAgent::CheckTargetInChaseRange, World->GetDeltaSeconds(), true); +} + +void ASPNpcAgent::StopSkillActionMontage() +{ + NMT_CHECKF(AgentAnimInstance) + if(!NMT_ENSURE(NpcActionMontage)) + return; + + AgentAnimInstance->SetActionState(false); + if(AgentAnimInstance->GetInstanceForMontage(NpcActionMontage)) + { + FAnimMontageInstance* MontageInstance = AgentAnimInstance->GetInstanceForMontage(NpcActionMontage); + if(MontageInstance && MontageInstance->OnMontageBlendingOutStarted.IsBound()) + { + MontageInstance->OnMontageBlendingOutStarted.Unbind(); + } + } + AgentAnimInstance->Montage_Stop(0.f, NpcActionMontage); +} + +void ASPNpcAgent::SetSkillClass() +{ + UDataTable* SkillDataTable = UAssetUtilsLibrary::LoadDataTableByEnumKey(EDataTableKey::Skill); + if(!NMT_ENSURE(SkillDataTable)) + return; + + NMT_CHECKF(NpcStatusComponent) + FString SkillRowName = FString::FromInt(NpcStatusComponent->GetStatusNpcAttackId()); + FSkill* SkillDataRow = SkillDataTable->FindRow(*SkillRowName, TEXT("Not Found FSkill")); + + if(!NMT_ENSURE(SkillDataRow)) + return; + + FString TempPath = SkillDataRow->sSkillBpPath; + if(!CHECK_FREE(TempPath)) + { + FString ClassPath = UAssetUtilsLibrary::AssetReferencePathToClassPath(TempPath); + UClass* LoadedClass = StaticLoadClass(UObject::StaticClass(), nullptr, *ClassPath); + NMT_CHECKF(LoadedClass) + NpcSkillClass = TSubclassOf(LoadedClass); + SkillType = UGlobalUtilsLibrary::GetStringToEnum(*SkillDataRow->sSkillType); + bRotateWhileAttack = SkillType == ESkillTypes::Melee; + } +} + +void ASPNpcAgent::ClearSkillCoolTime() +{ + bSkillCooldownActive = false; + SkillCoolTime = 0.f; +} + +void ASPNpcAgent::UpdateSkillCooldown(const float InDeltaSeconds) +{ + if(SkillCoolTime < 0.f) + { + ClearSkillCoolTime(); + if(SkillType == ESkillTypes::Direct) + TryFinishAttack(); + } + + SkillCoolTime -= InDeltaSeconds; +} + +void ASPNpcAgent::CheckTargetInChaseRange() +{ + if(SphereChaseRangeComponent) + { + AActor* TargetActor = GetAIControllerBase()->GetTargetActor(); + if(TargetActor == nullptr) + return; + + TArray DetectedActor = SphereChaseRangeComponent->GetNonBlockedActors(TargetActor->GetActorLocation(), GetActorLocation()); + ACorePlayerCharacter* DetectedPlayer = nullptr; + + for (AActor* Actor : DetectedActor) + { + if(ACorePlayerCharacter* Player = Cast(Actor)) + DetectedPlayer = Player; + } + + if(DetectedPlayer == nullptr) + { + NMT_LOG("DetectedPlayer is empty. Player is behind wall") + FinishCheckInChaseRange(); + } + } +} + +void ASPNpcAgent::FinishCheckInChaseRange() +{ + if(GetWorld()->GetTimerManager().IsTimerActive(CheckChaseRangeTimerHandle) && SphereChaseRangeComponent) + { + NMT_LOG("FinishCheckInChaseRange") + GetWorld()->GetTimerManager().ClearTimer(CheckChaseRangeTimerHandle); + CheckChaseRangeTimerHandle.Invalidate(); + GetAIControllerBase()->UpdateTargetInfo(nullptr); + SphereChaseRangeComponent->DeactivateFiltering(); + SphereChaseRangeComponent->OnExitedSphereRange.Clear(); + + if(CurrentState != ENpcState::Attack && CurrentState != ENpcState::Hit) + { + ChangeNpcState(ENpcState::Chase); + } + } +} + +void ASPNpcAgent::RelocateOnNavMesh() +{ + // FIXME : 현재 미사용. 테스트 필요 + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + NMT_CHECKF(World); + + UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(World); + NMT_CHECKF(NavSys); + + float CapsuleRadius, CapsuleHalfHeight; + GetCapsuleComponent()->GetScaledCapsuleSize(CapsuleRadius, CapsuleHalfHeight); + FVector Extent(CapsuleRadius, CapsuleRadius, CapsuleHalfHeight); + FNavLocation OutLocation; + + bool bOnNavMesh = NavSys->ProjectPointToNavigation(GetActorLocation(), OutLocation, Extent); + if(bOnNavMesh) + { + NMT_LOG("On Nav Mesh") + } + else + { + NMT_LOG("NOT On Nav Mesh") + Extent += FVector(50.0, 50.0, 0.0); + if(NavSys->ProjectPointToNavigation(GetActorLocation(), OutLocation, Extent)) + { + SetActorLocation(OutLocation); + } + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h new file mode 100644 index 0000000..c424841 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h @@ -0,0 +1,169 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/Data/Gen/GenerateEnumSkillTypes.h" +#include "ProjectT/Data/Npc/NpcDataModel.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" +#include "ProjectT/System/Core/Interfaces/DebugHitCollision.h" +#include "SPNpcAgent.generated.h" + +enum class ENpcNormalAnimState : uint8; +enum class ENpcAgentAnimType : uint8; + +UCLASS() +class PROJECTT_API ASPNpcAgent : public ACoreNpc, public IAISettings, public IDebugHitCollision +{ + GENERATED_BODY() + +public: + ASPNpcAgent(); + + virtual void PostInitializeComponents() override; + virtual void Tick(float DeltaTime) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + virtual bool GetUseSight_Implementation() override; + virtual bool GetUseHearing_Implementation() override; + virtual FSightInfo GetSightInfo_Implementation() override; + virtual UBlackboardData* GetBlackboardData_Implementation() override; + virtual UBehaviorTree* GetBehaviorTree_Implementation() override; + virtual void DetectTargetBySight_Implementation(AActor* InTarget, FAIStimulus InStimulus) override; + virtual void ForgetTarget_Implementation(AActor* InTarget) override; + virtual FTransform GetViewTransform_Implementation() override; + virtual void ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) override; + virtual void ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) override; + virtual void StartDisableNpc() override; + virtual void CompleteDisableNpc() override; + virtual void ChangeNpcState(const ENpcState InState) override; + virtual void ActivateCharacter(const bool InbEnable) override; + virtual void SetDetectTargetFromNoise(AActor* InTarget) override; + virtual void SetDetectLocationFromNoise(const FVector& InTargetLocation) override; + virtual void SetVisionMode(EVisionMode InVisionMode) override; + virtual void ChangeDoubtState(const EDoubtState InDoubtState) override; + + UFUNCTION(BlueprintPure) + class USPNpcAgentAnimInstance* GetAgentAnimInstance() const; + + UFUNCTION(BlueprintCallable) + void ChangeSpeed(const ENpcSpeedType InSpeed, const bool InbStopImmediately = false); + + UFUNCTION() + void FinishCheckInChaseRange(); + + FORCEINLINE bool CanRotateWhileAttack() const { return bRotateWhileAttack; } + class ACoreSkill* GetCurrentSkill() const; + class AAIPerceptionController* GetAIPerceptionController() const; + bool IsFinishSkillCoolDown() const; + bool IsTargetInAttackRange(const AActor* InTarget) const; + void GetSkillClass(TSubclassOf& OutSkillClass) const; + void PlayActionMontage(FName InSectionName, FOnMontageBlendingOutStarted InEndedFunction = nullptr); + void StopSkillActionMontage(); + void TryAttack(); + bool ShouldContinueAttack() const; + void DetermineNextStateAfterAbnormal(); + void SetCurrentUsingSkill(class ACoreSkill* InSkill); + void FinishCurrentSkill(); + void SetSkillCoolTime(const float InCoolTime); + +protected: + virtual void BeginPlay() override; + virtual void InitializeStatus(const FEnemyNpc InNpcStatus) override; + virtual void InitializeProperty() override; + virtual void Respawn() override; + virtual void ExecuteClickedEvent(UPrimitiveComponent* InTouchedComponent, FKey InButtonPressed) override; + virtual void ExecuteBeginCursorOverEvent(UPrimitiveComponent* InTouchedComponent) override; + virtual void ExecuteEndCursorOverEvent(UPrimitiveComponent* InTouchedComponent) override; + virtual void ResetStateAfterGameEnd() override; + virtual void SetUnDetectTarget(const bool InbUnDetect) override; + void InitializeMaterials(); + void StatusSlow(float InSlowValue, bool InbRecovery = false); + void StatusFast(float InFastValue, bool InbRecovery = false); + +#if WITH_EDITOR + virtual void ApplyCharacterData(const FTableRowBase* RowData) override; +#endif + + UFUNCTION() + void ContinueAttack(); + + UFUNCTION() + void TryFinishAttack(); + + UFUNCTION() + void FinishAttack(); + + void RelocateOnNavMesh(); + void CheckTargetInChaseRange(); + void UpdateSkillCooldown(const float InDeltaSeconds); + void JumpBack(const FVector& InTargetLocation); + void CheckFallingFromJumpBack(); + void StartCheckInChaseRange(); + void SetSkillClass(); + void ClearSkillCoolTime(); + void StartAttack(); + void UpdateDissolve(const float InDeltaSeconds); + void UpdateVisionLineLength(); + void NotifyVisionDetection(const bool InbDetect); + +public: + virtual void ShowVisual_Implementation() override; + virtual void HideVisual_Implementation() override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AISetting") + FCrowdSettingsInfo CrowdSettingsInfo; + + uint8 bAttack : 1; + +protected: + ENpcSpeedType CurrentSpeed; + ESkillTypes SkillType; + FString ActionMontageSectionName; + FName ChaseRangeProfileName; + FName DissolveParameterName; + float SkillCoolTime; + float DissolveElapsedTime; + float DissolveDuration; + uint8 bRotateWhileAttack : 1; + uint8 bSkillCooldownActive : 1; + uint8 bDissolving : 1; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr HpBarWidgetComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component") + TObjectPtr DetectIndicatorWidget; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Component") + TObjectPtr SphereChaseRangeComponent; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Component") + TObjectPtr DissolveFXComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr VisionLineMeshComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skill") + TSubclassOf NpcSkillClass; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Skill") + TObjectPtr CurrentUsingSkill; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Animation") + TObjectPtr AgentAnimInstance; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation") + TObjectPtr NpcActionMontage; + + UPROPERTY() + FTimerHandle CheckChaseRangeTimerHandle; + + UPROPERTY() + FTimerHandle JumpBackTimerHandle; + + UPROPERTY() + TArray> AllMeshComponents; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.cpp new file mode 100644 index 0000000..f284e4b --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.cpp @@ -0,0 +1,303 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNpcFixed.h" + +#include "Components/BoxComponent.h" +#include "Components/CapsuleComponent.h" +#include "Components/SphereComponent.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "GameFramework/SpringArmComponent.h" +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/Animations/NpcFixedAnimInstance.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + + +ASPNpcFixed::ASPNpcFixed() : + HeadPitchAngle(-37.f), + DetectParameterName(TEXT("Detect")) +{ + PrimaryActorTick.bCanEverTick = true; + + GetCapsuleComponent()->SetCollisionProfileName(TEXT("Fixed")); + GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint); + GetMesh()->SetAnimInstanceClass(UNpcFixedAnimInstance::StaticClass()); + + DetectCollisionComponent = CreateDefaultSubobject(TEXT("DetectCollisionComponent")); + DetectSpotMeshComponent = CreateDefaultSubobject(TEXT("DetectSpotMeshComponent")); + DetectConeMeshComponent = CreateDefaultSubobject(TEXT("DetectConeMeshComponent")); + BoundingBoxComponent = CreateDefaultSubobject(TEXT("BoundingBoxComponent")); + NMT_CHECKF(DetectCollisionComponent && DetectSpotMeshComponent && DetectConeMeshComponent && BoundingBoxComponent) + + DetectCollisionComponent->SetupAttachment(RootComponent); + DetectCollisionComponent->SetCollisionProfileName(TEXT("InteractionRange")); + DetectCollisionComponent->SetSphereRadius(76.f); + DetectCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ASPNpcFixed::DetectBeginOverlap); + DetectCollisionComponent->OnComponentEndOverlap.AddDynamic(this, &ASPNpcFixed::DetectEndOverlap); + + DetectSpotMeshComponent->SetupAttachment(DetectCollisionComponent); + DetectSpotMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + + DetectConeMeshComponent->SetupAttachment(SpringArmComponent); + DetectConeMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + DetectConeMeshComponent->SetRelativeLocation(FVector(140.0, 0, 8.0)); + DetectConeMeshComponent->SetRelativeRotation(FRotator(90.0, 0, 0)); + DetectConeMeshComponent->SetRelativeScale3D(FVector(1.25, 2.0, 2.5)); + + BoundingBoxComponent->SetupAttachment(RootComponent); + BoundingBoxComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + BoundingBoxComponent->SetBoxExtent(FVector(200.f, 150.f, 120.f)); + GetMesh()->SetupAttachment(BoundingBoxComponent); + GetMesh()->bUseAttachParentBound = true; + + GetCharacterMovement()->GravityScale = 0.f; + GetCharacterMovement()->SetComponentTickEnabled(false); + WeaponDynamicComponent->SetComponentTickEnabled(false); + WeaponStaticComponent->SetComponentTickEnabled(false); + AccessoryMeshComponent->SetComponentTickEnabled(false); +} + +void ASPNpcFixed::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPNpcFixed::SetSpringArmRotation() +{ + FRotator ArmRotator = SpringArmComponent->GetComponentRotation(); + SpringArmComponent->SetWorldRotation(UKismetMathLibrary::MakeRotator(ArmRotator.Roll, ArmRotator.Pitch, GetMesh()->GetSocketRotation(EyeSocketName).Yaw)); +} + +void ASPNpcFixed::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPNpcFixed::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPNpcFixed::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); +} + +UBlackboardData* ASPNpcFixed::GetBlackboardData_Implementation() +{ + return Blackboard; +} + +UBehaviorTree* ASPNpcFixed::GetBehaviorTree_Implementation() +{ + return BehaviorTree; +} + +void ASPNpcFixed::StartDisableNpc() +{ + Super::StartDisableNpc(); + + SetVisionMode(EVisionMode::None); + SetActorTickEnabled(false); + SetActorEnableCollision(false); + + if(bEnableRespawn) + GetWorldTimerManager().SetTimer(RespawnTimerHandle, this, &ASPNpcFixed::Respawn, RespawnTime, false); +} + +void ASPNpcFixed::CompleteDisableNpc() +{ + Super::CompleteDisableNpc(); +} + +void ASPNpcFixed::ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) +{ + if(NpcStatusComponent->ApplyDamage(InDamage)) + { + ChangeNpcState(ENpcState::Dead); + } + else + { + for(FEffect EffectType : InSkillEffects) + { + EEffectSubTypes EffectSubType = UGlobalUtilsLibrary::GetStringToEnum(EffectType.sEffect); + switch(EffectSubType) + { + case EEffectSubTypes::None: + { + ChangeNpcState(ENpcState::Chase); + break; + } + case EEffectSubTypes::Hitback: + { + ChangeNpcState(ENpcState::Hit); + break; + } + case EEffectSubTypes::Jumpback: + { + ChangeNpcState(ENpcState::Hit); + break; + } + case EEffectSubTypes::Unrecog: + { + SetUnDetectTarget(true); + break; + } + case EEffectSubTypes::Slow: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Slow") + break; + case EEffectSubTypes::Bind: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Bind") + break; + case EEffectSubTypes::Fast: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Fast") + break; + case EEffectSubTypes::CogImmune: NOT_IMPLEMENTED_MSG("EEffectSubTypes::CogImmune") + break; + case EEffectSubTypes::Stun: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Stun") + break; + case EEffectSubTypes::Surge: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Surge") + break; + case EEffectSubTypes::HitbackImmune: NOT_IMPLEMENTED_MSG("EEffectSubTypes::HitbackImmune") + break; + case EEffectSubTypes::Heal: NOT_IMPLEMENTED_MSG("EEffectSubTypes::Heal") + break; + default: NMT_LOG("Not Valid") + } + } + } +} + +void ASPNpcFixed::ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) +{ + for(FEffect LocCurEffect : InReleaseEffects) + { + EEffectSubTypes LoCurReleaseEffect = UGlobalUtilsLibrary::GetStringToEnum(LocCurEffect.sEffect); + switch(LoCurReleaseEffect) + { + case EEffectSubTypes::Unrecog: + { + SetUnDetectTarget(false); + + TArray OverlappedActors; + DetectCollisionComponent->GetOverlappingActors(OverlappedActors); + if(!OverlappedActors.IsEmpty()) + { + for(AActor* OverlappedActor : OverlappedActors) + { + if(ACorePlayerCharacter* Player = Cast(OverlappedActor)) + { + UpdateDetectState(true, Player); + break; + } + } + } + break; + } + case EEffectSubTypes::CogImmune: break; + case EEffectSubTypes::Surge: break; + case EEffectSubTypes::Bind: break; + case EEffectSubTypes::Fast: break; + case EEffectSubTypes::Slow: break; + case EEffectSubTypes::Hitback: break; + case EEffectSubTypes::Jumpback: break; + case EEffectSubTypes::None: break; + case EEffectSubTypes::Stun: break; + case EEffectSubTypes::HitbackImmune: break; + case EEffectSubTypes::Heal: break; + default: NMT_LOG("No Release Effect Type"); + } + } +} + +void ASPNpcFixed::InitializeProperty() +{ + Super::InitializeProperty(); + + FixedAnimInstance = Cast(GetMesh()->GetAnimInstance()); + NMT_CHECKF(FixedAnimInstance); + NpcAnimInstance->ForwardHeadRotation.Pitch = NpcAnimInstance->HeadRotation.Pitch = HeadPitchAngle; + + SetDetectSpotLocation(); + DetectConeMeshComponent->AttachToComponent(GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepWorld, EAttachmentRule::KeepRelative, EAttachmentRule::KeepWorld, true), EyeSocketName); + DetectSpotDynamicMaterial = DetectSpotMeshComponent->CreateAndSetMaterialInstanceDynamic(0); + DetectConeDynamicMaterial = DetectConeMeshComponent->CreateAndSetMaterialInstanceDynamic(0); +} + +void ASPNpcFixed::ActivateCharacter(const bool InbEnable) +{ + Super::ActivateCharacter(InbEnable); +} + +#if WITH_EDITOR +void ASPNpcFixed::ApplyCharacterData(const FTableRowBase* RowData) +{ + Super::ApplyCharacterData(RowData); +} +#endif + +void ASPNpcFixed::DetectBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) +{ + if(ACorePlayerCharacter* Player = Cast(OtherActor)) + { + if(OtherComp->ComponentHasTag("PlayerCapsule")) + UpdateDetectState(true, Player); + } +} + +void ASPNpcFixed::DetectEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + if(Cast(OtherActor) && OtherComp->ComponentHasTag("PlayerCapsule")) + { + UpdateDetectState(false, nullptr); + } +} + +void ASPNpcFixed::SetDetectSpotLocation() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + NMT_CHECKF(World) + + FHitResult HitResult; + FVector EyeLocation = GetMesh()->GetSocketLocation(EyeSocketName); + FRotator EyeRotation = GetActorRotation() + FRotator(HeadPitchAngle, 0.0, 0.0); + FVector Dir = EyeRotation.Vector().GetSafeNormal(); + FVector EndLocation = EyeLocation + Dir * 1500.f; + bool bHitGround = World->LineTraceSingleByObjectType(HitResult, EyeLocation, EndLocation, ECC_GameTraceChannel5, FCollisionQueryParams()); + if(bHitGround) + { + DetectCollisionComponent->SetWorldLocation(FVector(HitResult.Location.X, HitResult.Location.Y, HitResult.Location.Z + 1.f)); + } + + DetectCollisionComponent->AttachToComponent(SpringArmComponent, FAttachmentTransformRules(EAttachmentRule::KeepRelative, EAttachmentRule::KeepWorld, EAttachmentRule::KeepWorld, true)); +} + +void ASPNpcFixed::SetDetectMaterial(const bool InbDetect) const +{ + DetectSpotDynamicMaterial->SetScalarParameterValue(DetectParameterName, InbDetect); + DetectConeDynamicMaterial->SetScalarParameterValue(DetectParameterName, InbDetect); +} + +void ASPNpcFixed::UpdateDetectState(const bool InbDetect, const class ACorePlayerCharacter* InTarget) +{ + if(InbDetect) + { + if(!InTarget) + return; + + bool PlayerUnDetect; + InTarget->GetUnDetectState(PlayerUnDetect); + if(PlayerUnDetect || bUnDetect) + return; + + SetDetectMaterial(true); + Alert(InTarget->GetActorLocation()); + } + else + { + SetDetectMaterial(false); + bCanTriggerAlert = true; + } +} + + + diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h new file mode 100644 index 0000000..bb2700d --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcFixed.h @@ -0,0 +1,78 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Interfaces/AISettings.h" +#include "SPNpcFixed.generated.h" + +UCLASS() +class PROJECTT_API ASPNpcFixed : public ACoreNpc, public IAISettings +{ + GENERATED_BODY() + +public: + ASPNpcFixed(); + + virtual void OnConstruction(const FTransform& Transform) override; + virtual void Tick(float DeltaTime) override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + virtual UBlackboardData* GetBlackboardData_Implementation() override; + virtual UBehaviorTree* GetBehaviorTree_Implementation() override; + virtual void StartDisableNpc() override; + virtual void CompleteDisableNpc() override; + virtual void ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) override;; + virtual void ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) override; + virtual void ActivateCharacter(const bool InbEnable) override; + virtual void SetDetectTargetFromNoise(AActor* InTarget) override {}; + virtual void SetDetectLocationFromNoise(const FVector& InTargetLocation) override {}; + virtual void SetSpringArmRotation() override; + +protected: + virtual void BeginPlay() override; + virtual void InitializeProperty() override; + +#if WITH_EDITOR + virtual void ApplyCharacterData(const FTableRowBase* RowData) override; +#endif + + UFUNCTION() + void DetectBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); + + UFUNCTION() + void DetectEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); + + void SetDetectSpotLocation(); + void SetDetectMaterial(const bool InbDetect) const; + void UpdateDetectState(const bool InbDetect, const class ACorePlayerCharacter* InTarget); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + float HeadPitchAngle; + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr DetectCollisionComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr DetectSpotMeshComponent; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr DetectConeMeshComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Animation") + TObjectPtr FixedAnimInstance; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr BoundingBoxComponent; + + UPROPERTY() + TObjectPtr DetectSpotDynamicMaterial; + + UPROPERTY() + TObjectPtr DetectConeDynamicMaterial; + + FName DetectParameterName; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.cpp new file mode 100644 index 0000000..3d8c51f --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.cpp @@ -0,0 +1,233 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNpcPatrol.h" + +#include "Animations/SPNpcAgentAnimInstance.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Components/PathFollowComponent.h" +#include "ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h" + + +ASPNpcPatrol::ASPNpcPatrol() : + PathFollowComponent(nullptr), + CurrentPatrolType(EPatrolType::Patrol) +{ + PrimaryActorTick.bCanEverTick = true; + + PathFollowComponent = CreateDefaultSubobject(TEXT("PathFollowComponent")); + NMT_CHECKF(PathFollowComponent) +} + +void ASPNpcPatrol::PostInitializeComponents() +{ + Super::PostInitializeComponents(); + + InitializePatrolInfo(); +} + +void ASPNpcPatrol::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPNpcPatrol::Respawn() +{ + Super::Respawn(); +} + +void ASPNpcPatrol::ActivateCharacter(const bool InbEnable) +{ + Super::ActivateCharacter(InbEnable); + + if(InbEnable) + { + ChangePatrolType(); + } +} + +void ASPNpcPatrol::ForgetTarget_Implementation(AActor* InTarget) +{ + switch(CurrentState) + { + case ENpcState::Doubt: + { + NMT_CHECKF(PathFollowComponent) + GetAIControllerBase()->UpdateTargetInfo(nullptr); + ChangePatrolType(true, CurrentPatrolType); + ChangeNpcState(ENpcState::Default); + break; + } + case ENpcState::Default: break; + case ENpcState::Guard: break; + case ENpcState::Returning: break; + case ENpcState::Chase: break; + case ENpcState::Attack: break; + case ENpcState::Hit: break; + case ENpcState::Dead : break; + default : NMT_LOG("Not Valid Type") + } +} + +void ASPNpcPatrol::ChangeNpcState(const ENpcState InState) +{ + Super::ChangeNpcState(InState); + + if(CurrentState != InState) + { + switch(InState) + { + case ENpcState::Doubt: + { + NMT_CHECKF(PathFollowComponent) + PathFollowComponent->StopMove(); + break; + } + case ENpcState::Returning: break; + case ENpcState::Default: break; + case ENpcState::Chase: break; + case ENpcState::Attack: break; + case ENpcState::Guard: break; + case ENpcState::Dead: break; + case ENpcState::Hit: break; + default: NMT_LOG("Not Valid ENpcState") + } + + CurrentState = InState; + GetAIControllerBase()->ChangeNpcStateKey(InState); + ChangeIndicatorState(InState); + } +} + +void ASPNpcPatrol::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPNpcPatrol::ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) +{ + Super::ApplyDamageEvent_Implementation(InOccurActor, InOriginLocation, InDamage, InSkillEffects); + + for(FEffect EffectType : InSkillEffects) + { + EEffectSubTypes EffectSubType = UGlobalUtilsLibrary::GetStringToEnum(EffectType.sEffect); + switch(EffectSubType) + { + case EEffectSubTypes::Surge: + { + SetReturnLocationFromDefault(); + break; + } + case EEffectSubTypes::Bind: + { + GetAIControllerBase()->UpdateNextPatrolType(EPatrolType::None); + break; + } + case EEffectSubTypes::Hitback: break; + case EEffectSubTypes::Jumpback: break; + case EEffectSubTypes::Slow: break; + case EEffectSubTypes::Unrecog: break; + case EEffectSubTypes::None: break; + case EEffectSubTypes::Fast: break; + case EEffectSubTypes::CogImmune: break; + case EEffectSubTypes::Stun: break; + case EEffectSubTypes::HitbackImmune: break; + case EEffectSubTypes::Heal: break; + default: NMT_LOG("Not Valid"); + } + } +} + +void ASPNpcPatrol::ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) +{ + Super::ApplyRecoveryEvent_Implementation(InReleaseEffects); + + for(FEffect LocCurEffect : InReleaseEffects) + { + EEffectSubTypes LoCurReleaseEffect = UGlobalUtilsLibrary::GetStringToEnum(LocCurEffect.sEffect); + switch(LoCurReleaseEffect) + { + case EEffectSubTypes::Bind: + { + if(CurrentState == ENpcState::Default) + ChangePatrolType(true, CurrentPatrolType); + break; + } + case EEffectSubTypes::Unrecog: break; + case EEffectSubTypes::Surge: break; + case EEffectSubTypes::Fast: break; + case EEffectSubTypes::Slow: break; + case EEffectSubTypes::Hitback: break; + case EEffectSubTypes::Jumpback: break; + case EEffectSubTypes::CogImmune: break; + case EEffectSubTypes::None: break; + case EEffectSubTypes::Stun: break; + case EEffectSubTypes::HitbackImmune: break; + case EEffectSubTypes::Heal: break; + default: NMT_LOG("No Release Effect Type") + } + } +} + +void ASPNpcPatrol::InitializePatrolInfo() +{ + PathFollowComponent->OnSuccessMove.AddUObject(this, &ASPNpcPatrol::ChangePatrolType); + + NMT_CHECKF(NpcStatusComponent) + int32 MoveProb = static_cast(NpcStatusComponent->GetStatusNpcMoveProb()); + int32 SearchProb = MoveProb + static_cast(NpcStatusComponent->GetStatusNpcSearchProb()); + int32 ScoutProb = SearchProb + static_cast(NpcStatusComponent->GetStatusNpcScoutProb()); + + PatrolTypeWeights.Add({EPatrolType::Patrol, MoveProb}); + PatrolTypeWeights.Add({EPatrolType::Search, SearchProb}); + PatrolTypeWeights.Add({EPatrolType::SearchPatrol, ScoutProb}); +} + +EPatrolType ASPNpcPatrol::SelectNextPatrolType() +{ + EPatrolType ReturnType = EPatrolType::Patrol; + int32 RandomValue = FMath::RandRange(1, 100); + + for(TPair& Weight : PatrolTypeWeights) + { + if(RandomValue <= Weight.Value) + { + ReturnType = Weight.Key; + break; + } + } + + return ReturnType; +} + +void ASPNpcPatrol::ChangePatrolType(bool InbForcedAction, EPatrolType InActionType) +{ + if(InbForcedAction) + CurrentPatrolType = InActionType; + else + CurrentPatrolType = SelectNextPatrolType(); + + switch(CurrentPatrolType) + { + case EPatrolType::Patrol: case EPatrolType::SearchPatrol: + { + ChangeSpeed(ENpcSpeedType::Walk); + AgentAnimInstance->SetNormalState(true); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Walk); + break; + } + case EPatrolType::Search: + { + ChangeSpeed(ENpcSpeedType::Stop); + AgentAnimInstance->SetNormalState(true); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); + break; + } + case EPatrolType::None: + break; + default: NOT_IMPLEMENTED() + } + + GetAIControllerBase()->UpdateNextPatrolType(CurrentPatrolType); +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.h new file mode 100644 index 0000000..e8f5452 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcPatrol.h @@ -0,0 +1,46 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPNpcAgent.h" +#include "SPNpcPatrol.generated.h" + +UCLASS() +class PROJECTT_API ASPNpcPatrol : public ASPNpcAgent +{ + GENERATED_BODY() + +public: + ASPNpcPatrol(); + virtual void PostInitializeComponents() override; + virtual void Tick(float DeltaTime) override; + virtual void ApplyDamageEvent_Implementation(AActor* InOccurActor, const FVector& InOriginLocation, const float InDamage, const TArray& InSkillEffects) override; + virtual void ApplyRecoveryEvent_Implementation(const TArray& InReleaseEffects) override; + virtual void ActivateCharacter(const bool InbEnable) override; + virtual void ForgetTarget_Implementation(AActor* InTarget) override; + virtual void ChangeNpcState(const ENpcState InState) override; + + UFUNCTION() + EPatrolType SelectNextPatrolType(); + + UFUNCTION() + void ChangePatrolType(bool InbForcedAction = false, EPatrolType InActionType = EPatrolType::None); + +protected: + virtual void BeginPlay() override; + virtual void Respawn() override; + +private: + void InitializePatrolInfo(); + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component") + TObjectPtr PathFollowComponent; + +private: + UPROPERTY() + EPatrolType CurrentPatrolType; + + TArray> PatrolTypeWeights; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.cpp b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.cpp new file mode 100644 index 0000000..5360e2b --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.cpp @@ -0,0 +1,72 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNpcStationary.h" + +#include "Animations/SPNpcAgentAnimInstance.h" +#include "ProjectT/System/Core/Characters/NPC/AI/Controllers/AIControllerBase.h" + + +ASPNpcStationary::ASPNpcStationary() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPNpcStationary::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPNpcStationary::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPNpcStationary::Respawn() +{ + Super::Respawn(); +} + +void ASPNpcStationary::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPNpcStationary::ActivateCharacter(const bool InbEnable) +{ + Super::ActivateCharacter(InbEnable); + + if(InbEnable) + SetReturnLocationFromDefault(); +} + +void ASPNpcStationary::ChangeNpcState(const ENpcState InState) +{ + Super::ChangeNpcState(InState); + + if(CurrentState != InState) + { + switch(InState) + { + case ENpcState::Default: + { + ChangeSpeed(ENpcSpeedType::Stop, true); + AgentAnimInstance->SetNormalState(true); + AgentAnimInstance->ChangeNpcNormalAnimState(ENpcNormalAnimState::Idle); + break; + } + case ENpcState::Doubt: break; + case ENpcState::Chase: break; + case ENpcState::Attack: break; + case ENpcState::Guard: break; + case ENpcState::Hit: break; + case ENpcState::Dead: break; + case ENpcState::Returning: break; + default: NMT_LOG("Not Valid ENpcState") + } + + CurrentState = InState; + GetAIControllerBase()->ChangeNpcStateKey(InState); + ChangeIndicatorState(InState); + } +} diff --git a/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.h b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.h new file mode 100644 index 0000000..4b0cb5c --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/NPC/SPNpcStationary.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/SinglePlay/Characters/NPC/SPNpcAgent.h" +#include "SPNpcStationary.generated.h" + +UCLASS() +class PROJECTT_API ASPNpcStationary : public ASPNpcAgent +{ + GENERATED_BODY() + +public: + ASPNpcStationary(); + virtual void OnConstruction(const FTransform& Transform) override; + virtual void Tick(float DeltaTime) override; + virtual void ActivateCharacter(const bool InbEnable) override; + virtual void ChangeNpcState(const ENpcState InState) override; + +protected: + virtual void BeginPlay() override; + virtual void Respawn() override; + +}; \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.cpp new file mode 100644 index 0000000..5ea8ed4 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.cpp @@ -0,0 +1,42 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPHolister.h" + +ASPHolister::ASPHolister() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPHolister::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ASPHolister::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPHolister::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + //Super::SetSkillState(InSkillState, InSkillData); + Super::SetMeleeAtkSkillState(InSkillState, InSkillData); +} + +void ASPHolister::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + Super::SetMeleeAtkSkillState(InSkillState, InSkillData); +} + +void ASPHolister::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPHolister::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.h new file mode 100644 index 0000000..f981029 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPHolister.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPPlayerCharacter.h" +#include "SPHolister.generated.h" + +UCLASS() +class PROJECTT_API ASPHolister : public ASPPlayerCharacter +{ + GENERATED_BODY() + +public: + ASPHolister(); + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.cpp new file mode 100644 index 0000000..45b03af --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.cpp @@ -0,0 +1,167 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPIcien.h" + +#include "ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/Core/Components/PlayerStatusComponent.h" +// Temp Only KeyBoard State +#define ONLY_KEYBOARD 1 + +ASPIcien::ASPIcien() : + SkillMoveAnimation(nullptr) +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPIcien::BeginPlay() +{ + Super::BeginPlay(); + PlayerAnimInstance->SetModifyAnimation(nullptr, SkillMoveAnimation); +} + +void ASPIcien::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPIcien::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + CurrentUsingSkill->StartSkill(); + SetInputable(false); + PlayActionMontage(*InSkillData.sSkillName, FOnMontageEnded::CreateLambda([InSkillData, this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) + { + SetSkillState(EPlayerSkillState::Activate, InSkillData); + } + })); + PlayerAnimInstance->SetModifyState(true); + CurrentUsingSkill->SkillTimeEnd.BindLambda([InSkillData , this]() + { + SetSkillState(EPlayerSkillState::Finish, InSkillData); + }); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + CurrentUsingSkill->CancelSkill(); + FSkill LocIcienSkillData; + CurrentUsingSkill->GetSkillData(LocIcienSkillData); + if(!CurrentUsingSkill->GetActivated()) SetSkillState(EPlayerSkillState::Finish, LocIcienSkillData); + break; + } + case EPlayerSkillState::Release: + { + //If Want Release decode underline + //CurrentUsingSkill->ReleaseSkill(); + //SetSkillState(EPlayerSkillState::Finish, InSkillData); + break; + } + case EPlayerSkillState::Activate: + { + PlayerAnimInstance->SetActionState(false); + CurrentUsingSkill->ActivateSkill(); + SetInputable(true); + break; + } + case EPlayerSkillState::Finish: + { + CurrentUsingSkill->FinishSkill(); + SetSkillCoolTime(CurrentUsingSkill.GetClass(),InSkillData); + SetCurrentSkill(false); + PlayerAnimInstance->SetModifyState(false); + break; + } + default: NMT_LOG("Icien State None"); break; + } +} + +void ASPIcien::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(bCalibrateSkill) + { + AActor* LocNearActor = nullptr; + if(CheckSkillCalibrateRange(InSkillData,LocNearActor)) + { + CalibrateMeshNearActor(LocNearActor); + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + + if(bMovingAction) + { + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->CurrentPlayerStatus.fCharMove * MeleeAtkDecreaseSpeedRatio; + } + else + { + SetInputable(false); + } + StartMouseCursorParabola(true, false, false); + CurrentUsingSkill->StartSkill(); + PlayActionMontage(*InSkillData.sSkillName, FOnMontageEnded::CreateLambda([InSkillData, this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) SetMeleeAtkSkillState(EPlayerSkillState::Finish, InSkillData); + })); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + CurrentUsingSkill->CancelSkill(); + FSkill LocIcienSkillData; + CurrentUsingSkill->GetSkillData(LocIcienSkillData); + SetMeleeAtkSkillState(EPlayerSkillState::Finish, LocIcienSkillData); + break; + } + case EPlayerSkillState::Release: break; + case EPlayerSkillState::Finish: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + if(bMovingAction) + { + SetActorRotation(GetMesh()->GetComponentRotation()); + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->PreviousPlayerStatus.fCharMove; + } + else + { + SetInputable(true); + } + break; + } + default: NMT_LOG("IcienAtk State None"); break; + } +} +void ASPIcien::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPIcien::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.h new file mode 100644 index 0000000..c3ec10c --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPIcien.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPPlayerCharacter.h" +#include "SPIcien.generated.h" + +UCLASS() +class PROJECTT_API ASPIcien : public ASPPlayerCharacter +{ + GENERATED_BODY() + +public: + ASPIcien(); + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + +protected: + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr SkillMoveAnimation; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.cpp new file mode 100644 index 0000000..73d41e0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.cpp @@ -0,0 +1,184 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPNox.h" + +#include "ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/Core/Components/PlayerStatusComponent.h" + +// Temp Only KeyBoard State +#define ONLY_KEYBOARD 1 + +ASPNox::ASPNox() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPNox::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ASPNox::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPNox::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + Super::SetSkillState(InSkillState, InSkillData); + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(!bMovingAction) PlayActionMontage(*InSkillData.sSkillName,nullptr); + SetSkillState(EPlayerSkillState::Aim); + break; + } + case EPlayerSkillState::Aim: + { + StartMouseCursorParabola(true, true, false); + CurrentUsingSkill->AimSkill(); + if(bMovingAction) + { + PlayerAnimInstance->SetActionState(false); + } + else + { + SetInputable(false); + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + GetWorld()->GetTimerManager().SetTimer(MouseCursorTimerHandle, this, &ASPNox::RotateMeshToMouseCursor, GetWorld()->DeltaTimeSeconds, true); + } + break; + } + case EPlayerSkillState::Cancel: + { + StartMouseCursorParabola(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + break; + } + case EPlayerSkillState::Release: + { + StartMouseCursorParabola(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + break; + } + case EPlayerSkillState::Activate: + { + StartMouseCursorParabola(false); + CurrentUsingSkill->ActivateSkill(); + PlayerAnimInstance->SetActionState(true); + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + SetActorRotationToMouseCursor(); + CalibrateMeshMouseCursor(); + SetInputable(false); + PlayActionMontage(*InSkillData.sSkillName.Append("Active"),FOnMontageEnded::CreateLambda([this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) + { + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->PreviousPlayerStatus.fCharMove; + PlayerAnimInstance->SetActionState(false); + SetInputable(true); + } + })); + break; + } + case EPlayerSkillState::Finish: break; + default: NMT_LOG("NoxSkill State None"); break; + } +} + +void ASPNox::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(bCalibrateSkill) + { + AActor* LocNearActor = nullptr; + if(CheckSkillCalibrateRange(InSkillData,LocNearActor)) + { + CalibrateMeshNearActor(LocNearActor); + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + } + else + { + #if ONLY_KEYBOARD + CalibrateMeshMouseCursor(); + #endif + } + + if(bMovingAction) + { + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->CurrentPlayerStatus.fCharMove * MeleeAtkDecreaseSpeedRatio; + } + else + { + SetInputable(false); + } + CurrentUsingSkill->StartSkill(); + PlayActionMontage(*InSkillData.sSkillName,FOnMontageEnded::CreateLambda([InSkillData, this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) SetMeleeAtkSkillState(EPlayerSkillState::Finish,InSkillData); + })); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + CurrentUsingSkill->CancelSkill(); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + if(bMovingAction) + { + SetActorRotation(GetMesh()->GetComponentRotation()); + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->PreviousPlayerStatus.fCharMove; + } + else + { + SetInputable(true); + } + break; + } + case EPlayerSkillState::Release: break; + case EPlayerSkillState::Finish: + { + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + SetCurrentSkill(false); + PlayerAnimInstance->SetActionState(false); + if(bMovingAction) + { + SetActorRotation(GetMesh()->GetComponentRotation()); + PlayerStatusComponent->CurrentPlayerStatus.fCharMove = PlayerStatusComponent->PreviousPlayerStatus.fCharMove; + } + else + { + SetInputable(true); + } + break; + } + default: NMT_LOG("NoxAtk State None"); break; + } +} + +void ASPNox::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPNox::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.h new file mode 100644 index 0000000..59862ec --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPNox.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPPlayerCharacter.h" +#include "SPNox.generated.h" + +UCLASS() +class PROJECTT_API ASPNox : public ASPPlayerCharacter +{ + GENERATED_BODY() + +public: + ASPNox(); + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.cpp new file mode 100644 index 0000000..2c406bc --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPPlayerCharacter.h" + +ASPPlayerCharacter::ASPPlayerCharacter() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPPlayerCharacter::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPPlayerCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.h new file mode 100644 index 0000000..14d5e75 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPlayerCharacter.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "SPPlayerCharacter.generated.h" + +UCLASS() +class PROJECTT_API ASPPlayerCharacter : public ACorePlayerCharacter +{ + GENERATED_BODY() + CONTENT_TYPE_NUMBER(EContentType::PlayerCharacter) + +public: + ASPPlayerCharacter(); + +protected: + virtual void BeginPlay() override; + +public: + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.cpp new file mode 100644 index 0000000..4d99e3a --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.cpp @@ -0,0 +1,102 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPPyroMania.h" +#include "ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h" +#include "ProjectT/System/Core/Characters/Skill/PyroAtk.h" +#include "ProjectT/System/Core/Components/PlayerStatusComponent.h" + +ASPPyroMania::ASPPyroMania() +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPPyroMania::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPPyroMania::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPPyroMania::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + Super::SetSkillState(InSkillState, InSkillData); + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + if(!bMovingAction) PlayActionMontage(*InSkillData.sSkillName,nullptr); + SetSkillState(EPlayerSkillState::Aim); + break; + } + case EPlayerSkillState::Aim: + { + StartMouseCursorLinear(true); + CurrentUsingSkill->AimSkill(); + if(bMovingAction) + { + PlayerAnimInstance->SetActionState(false); + } + else + { + SetInputable(false); + GetWorld()->GetTimerManager().ClearTimer(MeshRotateCalibrateTimerHandle); + GetWorld()->GetTimerManager().SetTimer(MouseCursorTimerHandle, this, &ASPPyroMania::RotateMeshToMouseCursor, GetWorld()->DeltaTimeSeconds, true); + } + break; + } + case EPlayerSkillState::Cancel: + { + StartMouseCursorLinear(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + break; + } + case EPlayerSkillState::Release: + { + StartMouseCursorLinear(false); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + break; + } + case EPlayerSkillState::Activate: + { + CurrentUsingSkill->ActivateSkill(); + StartMouseCursorLinear(false); + PlayerAnimInstance->SetActionState(true); + SetSkillCoolTime(CurrentUsingSkill.GetClass(), InSkillData); + GetWorld()->GetTimerManager().ClearTimer(MouseCursorTimerHandle); + SetActorRotationToMouseCursor(); + CalibrateMeshMouseCursor(); + SetInputable(false); + PlayActionMontage(*InSkillData.sSkillName.Append("Active"),FOnMontageEnded::CreateLambda([this](UAnimMontage* Montage, bool Interrupted) + { + if(!Interrupted) + { + PlayerStatusComponent->SetStatusCharMove(PlayerStatusComponent->GetStatusPreviousCharMove()); + PlayerAnimInstance->SetActionState(false); + SetInputable(true); + } + })); + break; + } + case EPlayerSkillState::Finish: break; + default: NMT_LOG("PyroSkill State None"); break; + } +} + +void ASPPyroMania::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + Super::SetMeleeAtkSkillState(InSkillState, InSkillData); +} + +void ASPPyroMania::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPPyroMania::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.h new file mode 100644 index 0000000..6eac4d0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPPlayerCharacter.h" +#include "SPPyroMania.generated.h" + +UCLASS() +class PROJECTT_API ASPPyroMania : public ASPPlayerCharacter +{ + GENERATED_BODY() + +public: + ASPPyroMania(); + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.cpp b/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.cpp new file mode 100644 index 0000000..58a5fdf --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.cpp @@ -0,0 +1,108 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPSneako.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Characters/Player/Animations/AnimInstance/PlayerCharacterAnimInstance.h" +#include "ProjectT/System/Core/Characters/Skill/CoreSkill.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" + +ASPSneako::ASPSneako() : + HeadHideMaterialInstance(nullptr), + HeadMaterialInstance(nullptr), + SkillIdleAnimation(nullptr), + SkillMoveAnimation(nullptr) +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPSneako::BeginPlay() +{ + Super::BeginPlay(); + PlayerAnimInstance->SetModifyAnimation(SkillIdleAnimation, SkillMoveAnimation); +} + +void ASPSneako::OnConstruction(const FTransform& Transform) +{ + Super::OnConstruction(Transform); +} + +void ASPSneako::SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + switch(InSkillState) + { + case EPlayerSkillState::Start: + { + GetMesh()->SetMaterial(0, HeadHideMaterialInstance); + WeaponStaticComponent->SetHiddenInGame(true); + CurrentUsingSkill->StartSkill(); + PlayerAnimInstance->SetModifyState(true); + CurrentUsingSkill->SkillTimeEnd.BindLambda([InSkillData , this]() + { + SetSkillState(EPlayerSkillState::Finish, InSkillData); + }); + break; + } + case EPlayerSkillState::Aim: break; + case EPlayerSkillState::Cancel: + { + CurrentUsingSkill->CancelSkill(); + FSkill LocSneakoSkillData; + CurrentUsingSkill->GetSkillData(LocSneakoSkillData); + SetSkillState(EPlayerSkillState::Finish, LocSneakoSkillData); + break; + } + case EPlayerSkillState::Release: + { + CurrentUsingSkill->ReleaseSkill(); + SetSkillState(EPlayerSkillState::Finish, InSkillData); + break; + } + case EPlayerSkillState::Activate: break; + case EPlayerSkillState::Finish: + { + CurrentUsingSkill->FinishSkill(); + AWorldGameMode* LocGameMode = UGlobalUtilsLibrary::GetGameModeChecked(this); + TArray LocNpcCharacters; + LocGameMode->GetNpcCharacters(LocNpcCharacters); + for(AActor* LocNpc : LocNpcCharacters) + { + TArray LocNpcEffectTypes; + Execute_GetCurrentEffectTypes(LocNpc, LocNpcEffectTypes); + if(!LocNpcEffectTypes.Contains(EEffectSubTypes::Unrecog)) + { + TArray LocEffects; + FEffect LocEffect; + const FString LocUnrecogString = UGlobalUtilsLibrary::GetEnumToString(EEffectSubTypes::Unrecog); + LocEffect.sEffect = LocUnrecogString; + LocEffects.Add(LocEffect); + Execute_ApplyRecoveryEvent(LocNpc, LocEffects); + } + } + SetSkillCoolTime(CurrentUsingSkill.GetClass(),InSkillData); + SetCurrentSkill(false); + GetMesh()->SetMaterial(0, HeadMaterialInstance); + WeaponStaticComponent->SetHiddenInGame(false); + PlayerAnimInstance->SetModifyState(false); + break; + } + default: NMT_LOG("SneakoSkill State None"); break; + } +} + +void ASPSneako::SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData) +{ + Super::SetMeleeAtkSkillState(InSkillState, InSkillData); +} + +void ASPSneako::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ASPSneako::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + diff --git a/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.h b/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.h new file mode 100644 index 0000000..5027a12 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Characters/Player/SPSneako.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SPPlayerCharacter.h" +#include "SPSneako.generated.h" + +UCLASS() +class PROJECTT_API ASPSneako : public ASPPlayerCharacter +{ + GENERATED_BODY() + +public: + ASPSneako(); + virtual void Tick(float DeltaTime) override; + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + +protected: + virtual void BeginPlay() override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void SetSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + virtual void SetMeleeAtkSkillState(EPlayerSkillState InSkillState, FSkill InSkillData = FSkill()) override; + +protected: + UPROPERTY(EditDefaultsOnly) + UMaterialInstance* HeadHideMaterialInstance; + + UPROPERTY(EditDefaultsOnly) + UMaterialInstance* HeadMaterialInstance; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr SkillIdleAnimation; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = PlayerAnimation, meta = (AllowPrivateAccess = "true")) + TObjectPtr SkillMoveAnimation; +}; diff --git a/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.cpp b/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.cpp new file mode 100644 index 0000000..aaf73b6 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.cpp @@ -0,0 +1,202 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SPNpcStatusComponent.h" + +#include "ProjectT/ProjectT.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/CoreCheatManager.h" + +USPNpcStatusComponent::USPNpcStatusComponent() : + bOverrideStatusInEditor(false), + HalfRotationAngle(0.f) +{ + PrimaryComponentTick.bCanEverTick = true; +} + +/** + * NOTE: ApplyDamage Description + * @param InDamageAmount: Damage Hit Value + * @return 'True': Npc Is Dead + */ +bool USPNpcStatusComponent::ApplyDamage(const float InDamageAmount) +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + if(CCM->GetDebugStatus().bDebugEnemyInvincibleHP) return false; + + if(CurrentNpcStatus.fNpcHp <= 0.f) + return true; + + CurrentNpcStatus.fNpcHp = CurrentNpcStatus.fNpcHp - InDamageAmount; + if(OnNpcHit.IsBound()) + CurrentNpcStatus.fNpcHp < 0.f ? OnNpcHit.Broadcast(0.f) : OnNpcHit.Broadcast(CurrentNpcStatus.fNpcHp / PreviousNpcStatus.fNpcHp); + + NMT_LOGF("Damage : %f", InDamageAmount) + return CurrentNpcStatus.fNpcHp <= 0.f; +} + +void USPNpcStatusComponent::UpdateCurrentDoubtTime(const float InDoubtTime) +{ + CurrentNpcStatus.fDoubtTime = InDoubtTime; +} + +FEnemyNpc USPNpcStatusComponent::GetPreviousNpcStatus() +{ + return PreviousNpcStatus; +} + +FEnemyNpc USPNpcStatusComponent::GetCurrentNpcStatus() +{ + return CurrentNpcStatus; +} + +float USPNpcStatusComponent::GetStatusPreviousNpcHp() +{ + return PreviousNpcStatus.fNpcHp; +} + +float USPNpcStatusComponent::GetStatusNpcHp() +{ + return CurrentNpcStatus.fNpcHp; +} + +float USPNpcStatusComponent::GetStatusPreviousNpcMove() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return PreviousNpcStatus.fNpcMove * (CCM->GetDebugStatus().bDebugEnemySpeed ? 2.f : 1.f); +} + +float USPNpcStatusComponent::GetStatusNpcMove() +{ + UCoreCheatManager* CCM = UGlobalUtilsLibrary::GetSharedCoreCheatManager(this); + return CurrentNpcStatus.fNpcMove * (CCM->GetDebugStatus().bDebugEnemySpeed ? 2.f : 1.f); +} + +void USPNpcStatusComponent::SetStatusNpcMove(float InValue) +{ + CurrentNpcStatus.fNpcMove = InValue; +} + +void USPNpcStatusComponent::AddStatusNpcMove(const float InValue) +{ + CurrentNpcStatus.fNpcMove = GetStatusNpcMove() + InValue; +} + +float USPNpcStatusComponent::GetStatusPreviousNpcRun() +{ + return PreviousNpcStatus.fNpcRun; +} + +float USPNpcStatusComponent::GetStatusNpcRun() +{ + return CurrentNpcStatus.fNpcRun; +} + +void USPNpcStatusComponent::SetStatusNpcRun(float InValue) +{ + CurrentNpcStatus.fNpcRun = InValue; +} + +void USPNpcStatusComponent::AddStatusNpcRun(const float InValue) +{ + CurrentNpcStatus.fNpcRun = GetStatusNpcRun() + InValue; +} + +float USPNpcStatusComponent::GetStatusNpcSightLength() +{ + return CurrentNpcStatus.fSightLength; +} + +float USPNpcStatusComponent::GetStatusNpcSightAngle() +{ + return CurrentNpcStatus.fSightAngle; +} + +float USPNpcStatusComponent::GetStatusNpcAttackLength() +{ + return CurrentNpcStatus.fAttackLength; +} + +float USPNpcStatusComponent::GetStatusNpcChaseLength() +{ + return CurrentNpcStatus.fChaseLength; +} + +float USPNpcStatusComponent::GetStatusNpcRotationAngle() +{ + return CurrentNpcStatus.fRotationAngle; +} + +float USPNpcStatusComponent::GetStatusNpcHalfRotationAngle() +{ + return HalfRotationAngle; +} + +float USPNpcStatusComponent::GetStatusNpcRotationSpeed() +{ + return CurrentNpcStatus.fRotationSpeed; +} + +void USPNpcStatusComponent::SetStatusNpcRotationSpeed(float InValue) +{ + CurrentNpcStatus.fRotationSpeed = InValue; +} + +float USPNpcStatusComponent::GetStatusNpcDoubtTime() +{ + return CurrentNpcStatus.fDoubtTime; +} + +float USPNpcStatusComponent::GetStatusPreviousNpcDoubtTime() +{ + return PreviousNpcStatus.fDoubtTime; +} + +float USPNpcStatusComponent::GetStatusNpcNoise() +{ + return CurrentNpcStatus.fNpcNoise; +} + +float USPNpcStatusComponent::GetStatusNpcMoveProb() +{ + return CurrentNpcStatus.fMoveProb; +} + +float USPNpcStatusComponent::GetStatusNpcSearchProb() +{ + return CurrentNpcStatus.fSearchProb; +} + +float USPNpcStatusComponent::GetStatusNpcScoutProb() +{ + return CurrentNpcStatus.fScoutProb; +} + +int32 USPNpcStatusComponent::GetStatusNpcAttackId() +{ + return CurrentNpcStatus.iNpcAttackId; +} + +void USPNpcStatusComponent::BeginPlay() +{ + Super::BeginPlay(); +} + +void USPNpcStatusComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); +} + +void USPNpcStatusComponent::InitializeStatus(const FEnemyNpc& InStatus) +{ + PreviousNpcStatus = InStatus; + CurrentNpcStatus = InStatus; + HalfRotationAngle = InStatus.fRotationAngle / 2.f; + CurrentNpcStatus.fDoubtTime = 0.f; +} + +void USPNpcStatusComponent::ReInitializeStatus() +{ + CurrentNpcStatus = PreviousNpcStatus; + CurrentNpcStatus.fDoubtTime = 0.f; + HalfRotationAngle = CurrentNpcStatus.fRotationAngle / 2.f; +} diff --git a/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h b/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h new file mode 100644 index 0000000..79179fc --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Components/SPNpcStatusComponent.h @@ -0,0 +1,129 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "ProjectT/Data/Gen/GenerateStructEnemyNPC.h" +#include "SPNpcStatusComponent.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNpcHit, float, HpRatio); +UCLASS(ClassGroup = (Component), meta = (BlueprintSpawnableComponent)) +class PROJECTT_API USPNpcStatusComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + USPNpcStatusComponent(); + + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + void InitializeStatus(const FEnemyNpc& InStatus); + void ReInitializeStatus(); + + FORCEINLINE float GetCurrentHP() const { return CurrentNpcStatus.fNpcHp; } + FORCEINLINE bool IsDead() const { return CurrentNpcStatus.fNpcHp <= 0.f; } + bool ApplyDamage(const float InDamageAmount); + void UpdateCurrentDoubtTime(const float InDoubtTime); + + UFUNCTION(BlueprintCallable, BlueprintPure) + FEnemyNpc GetPreviousNpcStatus(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + FEnemyNpc GetCurrentNpcStatus(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousNpcHp(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusNpcHp(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousNpcMove(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusNpcMove(); + + UFUNCTION(BlueprintCallable) + void SetStatusNpcMove(const float InValue); + + UFUNCTION(BlueprintCallable) + void AddStatusNpcMove(const float InValue); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusPreviousNpcRun(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusNpcRun(); + + UFUNCTION(BlueprintCallable) + void SetStatusNpcRun(const float InValue); + + UFUNCTION(BlueprintCallable) + void AddStatusNpcRun(const float InValue); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcSightLength(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcSightAngle(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcAttackLength(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcChaseLength(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcRotationAngle(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcHalfRotationAngle(); + + UFUNCTION(BlueprintCallable, BlueprintPure) + float GetStatusNpcRotationSpeed(); + + UFUNCTION(BlueprintCallable) + void SetStatusNpcRotationSpeed(const float InValue); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcDoubtTime(); + + UFUNCTION(BlueprintCallable) + float GetStatusPreviousNpcDoubtTime(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcNoise(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcMoveProb(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcSearchProb(); + + UFUNCTION(BlueprintCallable) + float GetStatusNpcScoutProb(); + + UFUNCTION(BlueprintCallable) + int32 GetStatusNpcAttackId(); + +protected: + virtual void BeginPlay() override; + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NpcStatus, meta = (AllowPrivateAccess = "true")) + FEnemyNpc PreviousNpcStatus; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NpcStatus, meta = (AllowPrivateAccess = "true")) + FEnemyNpc CurrentNpcStatus; + +protected: + UPROPERTY(BlueprintAssignable) + FOnNpcHit OnNpcHit; + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NpcStatus, meta = (AllowPrivateAccess = "true")) + uint8 bOverrideStatusInEditor : 1; + + float HalfRotationAngle; +}; diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.cpp b/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.cpp new file mode 100644 index 0000000..6cef42e --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.cpp @@ -0,0 +1,409 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPGameModeBase.h" + +#include "Kismet/KismetMathLibrary.h" +#include "ProjectT/ProjectT.h" +#include "ProjectT/Data/Gen/GenerateEnumDataTableKey.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h" +#include "ProjectT/Data/Gen/GenerateEnumStage.h" +#include "ProjectT/Data/Gen/GenerateStructCharacterUnlock.h" +#include "ProjectT/Data/Paths/BaseDataPathLibrary.h" +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Components/PlayerStatusComponent.h" +#include "ProjectT/System/Core/GameModes/CoreGameState.h" +#include "ProjectT/System/Core/GameModes/CorePlayerController.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Interfaces/ProcessStateControl.h" +#include "ProjectT/System/Core/Managers/DataDam.h" +#include "ProjectT/System/Core/Managers/LoadingManager.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/Core/Managers/StageManager.h" +#include "ProjectT/System/Core/Objects/LevelObject/ExitPoint.h" +#include "ProjectT/System/Core/SaveGame/UserSaveGame.h" +#include "ProjectT/System/SinglePlay/Characters/Player/SPPyroMania.h" +#include "ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h" +#include "ProjectT/System/SinglePlay/Managers/SPWidgetManager.h" + + +ASPGameModeBase::ASPGameModeBase() : + SPEnemyVisionManager(nullptr), + RemainingSeconds(0), + ExitPoint(nullptr) +{ +} + +void ASPGameModeBase::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); +} + + +void ASPGameModeBase::InitializeEnemyCharacters() +{ + Super::InitializeEnemyCharacters(); +} + +void ASPGameModeBase::InitializePlayer() +{ + Super::InitializePlayer(); +} + +void ASPGameModeBase::InitializeUI() +{ + Super::InitializeUI(); + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + ACorePlayerCharacter* CPC = GetPlayerCharacter(); + NMT_CHECKF(CoreWidgetManager); + + USPWidgetManager* SPWM = CastChecked(CoreWidgetManager); + + OnUpdateRemainingTime.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdateTime); + + CPC->PlayerDeadDone.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnPlayerDead); + CPC->OnRequestInteractIcon.BindDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdateIndicator); + CPC->RefreshInteractionVisibility.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnInteractionIndicator); + CPC->ItemSlotActivate.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdateSlotFocus); + CPC->RefreshSkillCoolTime.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnSkillUpdate); + + UPlayerInventoryComponent* PIC = CPC->GetPlayerInventory(); + NMT_CHECKF(PIC); + + PIC->UpdateSpendInventoryData.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdateConsumableSlot); + PIC->UpdateGimmickInventoryData.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdateGimmickSlot); + + UPlayerStatusComponent* PSC = CPC->GetPlayerStatus(); + NMT_CHECKF(PSC); + + PSC->UpdatePlayerHpPercent.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdatePlayerHP); + PSC->UpdatePlayerStaminaPercent.AddDynamic(SPWM, &USPWidgetManager::ExecuteOnUpdatePlayerStamina); +} + +void ASPGameModeBase::InitializeExitPoint() +{ + AActor* Actor = nullptr; + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + Actor = UGameplayStatics::GetActorOfClass(World, AExitPoint::StaticClass()); + if(!Actor) + { + FRotator Rotator = FRotator(); + FVector SpawnPoint = FVector::ZeroVector; + TArray SpawnPoints; + GetPlayerSpawnPoints(SpawnPoints); + if(!SpawnPoints.IsEmpty()) + { + UGlobalUtilsLibrary::ShuffleArray(PlayerSpawnPoints); + SpawnPoint = SpawnPoints[0]->GetActorLocation(); + } + else + { + FVector Center = FVector(0.f, 0.f, 0.f); + FVector Extent = FVector(1000.f, 1000.f, 0.f); + SpawnPoint = UKismetMathLibrary::RandomPointInBoundingBox(Center, Extent); + } + Actor = World->SpawnActor(AExitPoint::StaticClass(), &SpawnPoint, &Rotator); + } + + ExitPoint = Cast(Actor); + NMT_CHECKF(ExitPoint); +} + +void ASPGameModeBase::SetStageTimeLimit() +{ + UStageManager* StageMgr = IGlobalObjectProvider::Execute_GetStageManager(GetGameInstance()); + NMT_CHECKF(StageMgr); + FStageInfo CurrentStageInfo = StageMgr->GetCurrentStageInfo(); + RemainingSeconds = CurrentStageInfo.StageData.iTimeLimit; +} + +void ASPGameModeBase::InitializeEnemyByFlag() +{ + for(AActor* Npc : NpcCharacters) + { + ACoreNpc* FindNpc = CastChecked(Npc); + FindNpc->ActivateCharacter(FindNpc->GetActivatedOnStart()); + } +} + +bool ASPGameModeBase::ChangedProcessEvent(const EProcessState ProcessState) +{ + bool bInitialized = Super::ChangedProcessEvent(ProcessState); + if(!NMT_ENSURE(bInitialized)) return false; + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + + UStageManager* SM = IGlobalObjectProvider::Execute_GetStageManager(GetGameInstance()); + NMT_CHECKF(SM); + + FStageInfo StageInfo = SM->GetCurrentStageInfo(); + ACoreGameState* CGS = UGlobalUtilsLibrary::GetGameStateChecked(World); + + switch(ProcessState) + { + case EProcessState::Ready: + { + InitializePlayer(); + InitializeEnemyCharacters(); + InitializeEnemyByFlag(); + InitializeItemObject(); + InitializeExitPoint(); + InitializeUI(); + + ULoadingManager* LoadingManager = GetGameInstance()->GetSubsystem(); + NMT_CHECKF(LoadingManager); + + LoadingManager->ReceiveLoadingState(FOnLoadingStateStatic::CreateWeakLambda(this, [CGS](const ELoadingState LoadingState) + { + if(LoadingState == ELoadingState::End) + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Intro); + } + })); + LoadingManager->UnRegisterPreLoadableObject(this); + + break; + } + case EProcessState::Intro: + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::PreGame); + break; + } + case EProcessState::PreGame: + { + ACorePlayerController* Controller = UGlobalUtilsLibrary::GetLocalPlayerControllerChecked(GetPlayerCharacter()); + Controller->InitializePlayerScreen(); + + QuestManager->InitializeQuestList(StageInfo.StageData, FOnQuestInitializedStatic::CreateLambda([this](const TArray& QuestList) + { + Execute_GetSPWidgetManager(this)->ExecuteOnQuestInitialized(QuestList); + })); + Execute_GetSPWidgetManager(this)->ExecuteStartGame(); + + TSubclassOf PlayerSkillClass; + TSubclassOf PlayerAtkClass; + GetPlayerCharacter()->GetSkillClass(PlayerAtkClass, PlayerSkillClass); + + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GetGameInstance()); + NMT_CHECKF(DD); + + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::Skill); + FSkill* PlayerCurSkill = FoundTable->FindRow(FName(*FString::FromInt(GetPlayerCharacter()->GetPlayerStatus()->GetPreviousPlayerStatus().iCharSkillId)), TEXT("")); + NMT_CHECKF(PlayerCurSkill); + + Execute_GetSPWidgetManager(this)->ExecuteOnSkillInitialized(*PlayerSkillClass, PlayerCurSkill->sSkillIconPath); + InitializeMapData(); + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::GamePlaying); + break; + } + case EProcessState::GamePlaying: + { + QuestManager->UpdateQuestManager(this, FOnQuestChangedStatic::CreateLambda([this, SM](const EObjectiveTypes ObjectiveType, const FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestComplete) + { + Execute_GetSPWidgetManager(this)->ExecuteOnQuestUpdate(ObjectiveType, ObjectiveSubTypeContext, IsQuestComplete); + if(ObjectiveType == EObjectiveTypes::Mission && IsQuestComplete) ExitPoint->ActivateExitPoint(); + })); + + ExitPoint->CompleteExitPoint(FOnCompleteExitPoint::CreateLambda([CGS]() + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Victory); + })); + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GetGameInstance()); + + NC->AddObserverStatic(this, ENotificationTypes::Player_Dead, FNotificationCenterStatic::CreateLambda([this, CGS]() + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Defeat); + })); + + NC->AddObserverStatic(this, ENotificationTypes::GameState_Started, FNotificationCenterStatic::CreateLambda([this, World, CGS]() + { + ACorePlayerCharacter* CPC = GetPlayerCharacter(); + CPC->SetInputable(true); + SetStageTimeLimit(); + World->GetTimerManager().SetTimer(StageRemainTimeHandle, [this, CGS]() + { + RemainingSeconds -= 1; + OnUpdateRemainingTime.Broadcast(RemainingSeconds); + + if (RemainingSeconds == 0) + { + GetWorld()->GetTimerManager().ClearTimer(StageRemainTimeHandle); + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Defeat); + } + },1.0f, true); + })); + break; + } + case EProcessState::Victory: + { + if(QuestManager->IsAllClearedSubQuests()) + { + UDataDam* DD = IGlobalObjectProvider::Execute_GetDataDam(GetGameInstance()); + NMT_CHECKF(DD); + + const UDataTable* FoundTable = DD->GetDataTableByEnum(EDataTableKey::CharacterUnlock); + + FCharacterUnlock* UnlockData = nullptr; + for(TTuple Data : FoundTable->GetRowMap()) + { + UnlockData = reinterpret_cast(Data.Value); + NMT_CHECKF(UnlockData); + + if(FROM_INT(UnlockData->iClearStage) == StageInfo.RowName) break; + UnlockData = nullptr; + } + NMT_MSG_CHECKF(UnlockData, "Failed to retrieve data from the \"CharacterUnlock.csv\" iClearStage column using the index from another \"Stage.csv\" primary key[%s].", *StageInfo.RowName.ToString()); + UUserSaveGame::EmplaceUnlockCharacterData(FROM_INT(UnlockData->iPlayerCharId), true); + } + + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GetGameInstance()); + NC->Post(ENotificationTypes::GameState_Victory); + NC->AddObserverStatic(this, ENotificationTypes::UI_VictoryActionCleared, FNotificationCenterStatic::CreateLambda([this, CGS]() + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Reward); + })); + Execute_GetSPWidgetManager(this)->ExecuteOnGameVictory(); + + break; + } + case EProcessState::Defeat: + { + UNotificationCenter* NC = IGlobalObjectProvider::Execute_GetNotificationCenter(GetGameInstance()); + NC->Post(ENotificationTypes::GameState_Defeat); + NC->AddObserverStatic(this, ENotificationTypes::UI_DefeatActionCleared, FNotificationCenterStatic::CreateLambda([this, World, SM]() + { + FString CurrentLevelName = UGameplayStatics::GetCurrentLevelName(World); + + UGameplayStatics::OpenLevel(World, *CurrentLevelName); + + //FIXME 데이터 테이블 레벨 패스정보가 달라서 크래시 발생 + // SM->PrepareLevelLoad(UGlobalUtilsLibrary::GetStringToEnum(CurrentLevelName)); + })); + Execute_GetSPWidgetManager(this)->ExecuteOnGameDefeat(); + break; + } + case EProcessState::Reward: + { + IProcessStateControl::Execute_ChangeProcessState(CGS, EProcessState::Finish); + break; + } + case EProcessState::Finish: + { + SM->ForceLoadLevel(EStage::L_Lobby); + break; + } + default: case EProcessState::None: NMT_CHECKF(0); + } + return true; +} + +USPWidgetManager* ASPGameModeBase::GetSPWidgetManager_Implementation() +{ + NMT_MSG_CHECKF(CoreWidgetManager, "Widget Manager is Null"); + + USPWidgetManager* SPWM = Cast(CoreWidgetManager); + NMT_MSG_CHECKF(SPWM, "SPWidgetManager Cast Failed"); + + return SPWM; +} + +void ASPGameModeBase::DebugGameTimePause(bool bPause) +{ + if(!StageRemainTimeHandle.IsValid()) return; + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + if(bPause) World->GetTimerManager().PauseTimer(StageRemainTimeHandle); + else World->GetTimerManager().UnPauseTimer(StageRemainTimeHandle); +} + +USPEnemyVisionManager* ASPGameModeBase::GetEnemyVisionManager_Implementation() +{ + return SPEnemyVisionManager; +} + +UQuestManager* ASPGameModeBase::GetQuestManager_Implementation() +{ + return Super::GetQuestManager_Implementation(); +} + +bool ASPGameModeBase::HasFinishedLoading_Implementation() +{ + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + ACoreGameState* CGS = UGlobalUtilsLibrary::GetGameStateChecked(World); + + switch(EProcessState State = IProcessStateControl::Execute_GetProcessState(CGS)) + { + case EProcessState::None: case EProcessState::Ready: + { + return false; + } + case EProcessState::Intro: case EProcessState::PreGame: case EProcessState::GamePlaying: + case EProcessState::Victory: case EProcessState::Defeat: case EProcessState::Reward: case EProcessState::Finish: + { + return true; + } + } + return false; +} + +void ASPGameModeBase::InitializeMapData_Implementation() +{ +} + +void ASPGameModeBase::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) +{ + Super::InitGame(MapName, Options, ErrorMessage); + + ULoadingManager* LoadingManager = GetGameInstance()->GetSubsystem(); + NMT_CHECKF(LoadingManager); + + LoadingManager->RegisterPreLoadableObject(this); +} + +void ASPGameModeBase::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + GetWorld()->GetTimerManager().ClearTimer(StageRemainTimeHandle); + + CoreWidgetManager->ReleaseManager(); + CoreWidgetManager = nullptr; + + SPEnemyVisionManager->ReleaseManager(); + SPEnemyVisionManager = nullptr; +} + +void ASPGameModeBase::InitializeManagers() +{ + Super::InitializeManagers(); + + UWorld* World = GetWorld(); + NMT_CHECKF(World); + + if (!CoreWidgetManager) + { + CoreWidgetManager = NewObject(this); + CoreWidgetManager->InitializeManager(this); + NMT_CHECKF(CoreWidgetManager); + } + + if(!SPEnemyVisionManager) + { + SPEnemyVisionManager = NewObject(this); + SPEnemyVisionManager->InitializeManager(World); + NMT_CHECKF(SPEnemyVisionManager); + } +} + +void ASPGameModeBase::InitializeNotification() +{ + Super::InitializeNotification(); +} \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h b/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h new file mode 100644 index 0000000..9e844ce --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Characters/Player/CorePlayerCharacter.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Interfaces/LoadableObject.h" +#include "ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h" +#include "SPGameModeBase.generated.h" + +/** + * + */ + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnUpdateRemainingTime, int32, RemainSeconds); + +UCLASS() +class PROJECTT_API ASPGameModeBase : public AWorldGameMode, public ISPObjectProvider, public ILoadableObject +{ + GENERATED_BODY() + +public: + ASPGameModeBase(); + virtual void Tick(float DeltaSeconds) override; + virtual bool ChangedProcessEvent(const EProcessState ProcessState) override; + virtual USPWidgetManager* GetSPWidgetManager_Implementation() override; + virtual USPEnemyVisionManager* GetEnemyVisionManager_Implementation() override; + virtual UQuestManager* GetQuestManager_Implementation() override; + virtual bool HasFinishedLoading_Implementation() override; + + //FIXME : 임시. 미니맵 렌더타겟 텍스처를 그리기 위한 함수 + UFUNCTION(BlueprintNativeEvent) + void InitializeMapData(); + + void DebugGameTimePause(bool bPause); + +protected: + virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override; + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void InitializeManagers() override; + virtual void InitializeNotification() override; + virtual void InitializeEnemyCharacters() override; + virtual void InitializePlayer() override; + virtual void InitializeUI() override; + +private: + void InitializeExitPoint(); + void SetStageTimeLimit(); + void InitializeEnemyByFlag(); + +public: + UPROPERTY(BlueprintAssignable) + FOnUpdateRemainingTime OnUpdateRemainingTime; + +private: + UPROPERTY() + TObjectPtr SPEnemyVisionManager; + + UPROPERTY() + FTimerHandle StageRemainTimeHandle; + + UPROPERTY() + int32 RemainingSeconds; + + UPROPERTY() + TObjectPtr ExitPoint; +}; diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.cpp b/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.cpp new file mode 100644 index 0000000..3ccb7a0 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.cpp @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPGameStateBase.h" + +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/GameModes/WorldGameMode.h" +#include "ProjectT/System/Core/Interfaces/GlobalObjectProvider.h" +#include "ProjectT/System/Core/Managers/NotificationCenter.h" + +ASPGameStateBase::ASPGameStateBase(): + ProcessState(EProcessState::None), + bOnce(0) +{ + PrimaryActorTick.bCanEverTick = true; +} + +void ASPGameStateBase::ChangeProcessState_Implementation(EProcessState NewState) +{ + if(ProcessState == NewState) return; + + ProcessState = NewState; + + if(ChangedProcessEvent.IsBound()) + { + if(!HasAuthority()) return; + + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* GM = World->GetAuthGameMode(); + NMT_CHECKF(GM); + + if(ChangedProcessEvent.IsBound()) + { + bool bSucceeded = ChangedProcessEvent.Execute(ProcessState); + IGlobalObjectProvider::Execute_GetNotificationCenter(GetGameInstance())->Post(ENotificationTypes::GameState_Changed); + } + } +} + +EProcessState ASPGameStateBase::GetProcessState_Implementation() +{ + return ProcessState; +} + +void ASPGameStateBase::BeginPlay() +{ + Super::BeginPlay(); +} + +void ASPGameStateBase::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); + + if(!bOnce) + { + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + AWorldGameMode* GM = UGlobalUtilsLibrary::GetGameModeChecked(World); + ChangedProcessEvent.BindUObject(GM, &AWorldGameMode::ChangedProcessEvent); + Execute_ChangeProcessState(this, EProcessState::Ready); + bOnce = true; + return; + } +} diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.h b/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.h new file mode 100644 index 0000000..1bfee14 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPGameStateBase.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/GameModes/CoreGameState.h" +#include "SPGameStateBase.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ASPGameStateBase : public ACoreGameState +{ + GENERATED_BODY() + +public: + ASPGameStateBase(); + virtual void ChangeProcessState_Implementation(EProcessState NewState) override; + virtual EProcessState GetProcessState_Implementation() override; + +protected: + virtual void BeginPlay() override; + virtual void Tick(float DeltaSeconds) override; + +protected: + FOnChangedProcessEvent ChangedProcessEvent; + EProcessState ProcessState; + uint8 bOnce:1; +}; diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.cpp b/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.cpp new file mode 100644 index 0000000..a3c7659 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPPlayerController.h" diff --git a/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.h b/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.h new file mode 100644 index 0000000..417df98 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/GameModes/SPPlayerController.h @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/GameModes/CorePlayerController.h" +#include "SPPlayerController.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API ASPPlayerController : public ACorePlayerController +{ + GENERATED_BODY() +}; diff --git a/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.cpp b/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.cpp new file mode 100644 index 0000000..aa9caf8 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPObjectProvider.h" + + +// Add default functionality here for any ISPObjectProvider functions that are not pure virtual. diff --git a/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h b/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h new file mode 100644 index 0000000..653fdf5 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "SPObjectProvider.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI, Blueprintable) +class USPObjectProvider : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class PROJECTT_API ISPObjectProvider +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "SPObjectProvider")) + class USPWidgetManager* GetSPWidgetManager(); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, meta = (Category = "SPObjectProvider")) + class USPEnemyVisionManager* GetEnemyVisionManager(); +}; diff --git a/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.cpp b/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.cpp new file mode 100644 index 0000000..a090a62 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.cpp @@ -0,0 +1,127 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPEnemyVisionManager.h" + +#include "ProjectT/System/Core/Characters/NPC/CoreNpc.h" + +USPEnemyVisionManager::USPEnemyVisionManager() : + OuterObject(nullptr) +{ +} + +void USPEnemyVisionManager::InitializeManager(const UObject* WorldObjectContext) +{ + OuterObject = const_cast(WorldObjectContext); +} + +void USPEnemyVisionManager::ReleaseManager() +{ + OuterObject = nullptr; + FocusedNpc = nullptr; + DetectNpcList.Empty(); +} + +void USPEnemyVisionManager::RegisterFocused(class ACoreNpc* InDetectNpc) +{ + if(FocusedNpc != nullptr) + { + if(FocusedNpc == InDetectNpc) + { + if(DetectNpcList.Contains(InDetectNpc)) + { + UnregisterDetection(InDetectNpc); + } + else + { + FocusedNpc->SetVisionMode(EVisionMode::None); + } + + FocusedNpc = nullptr; + } + else + { + FocusedNpc->SetVisionMode(EVisionMode::None); + FocusedNpc = InDetectNpc; + FocusedNpc->SetVisionMode(EVisionMode::Cone); + } + } + else + { + if(DetectNpcList.Contains(InDetectNpc)) + { + UnregisterDetection(InDetectNpc); + } + else + { + UnregisterAllDetection(); + FocusedNpc = InDetectNpc; + FocusedNpc->SetVisionMode(EVisionMode::Cone); + } + } +} + +void USPEnemyVisionManager::RegisterDetection(class ACoreNpc* InDetectNpc) +{ + if(DetectNpcList.Contains(InDetectNpc)) + return; + + if(FocusedNpc != nullptr) + { + FocusedNpc->SetVisionMode(EVisionMode::None); + FocusedNpc = nullptr; + } + + DetectNpcList.Add(InDetectNpc); + InDetectNpc->SetVisionMode(EVisionMode::Cone); + // UpdateSightState(); +} + +void USPEnemyVisionManager::UnregisterDetection(class ACoreNpc* InDetectNpc) +{ + if(!DetectNpcList.Contains(InDetectNpc)) + return; + + DetectNpcList.Remove(InDetectNpc); + InDetectNpc->SetVisionMode(EVisionMode::None); + // UpdateSightState(); +} + +void USPEnemyVisionManager::UnregisterFocused() +{ + if(FocusedNpc != nullptr) + { + FocusedNpc->SetVisionMode(EVisionMode::None); + FocusedNpc = nullptr; + } +} + +void USPEnemyVisionManager::UnregisterAllDetection() +{ + for(ACoreNpc* Npc : DetectNpcList) + { + Npc->SetVisionMode(EVisionMode::None); + } + + DetectNpcList.Empty(); +} + +bool USPEnemyVisionManager::IsFocusedNpc(class ACoreNpc* InNpc) const +{ + return FocusedNpc && FocusedNpc == InNpc; +} + +void USPEnemyVisionManager::UpdateSightState() +{ + for(int i = 0; i < DetectNpcList.Num(); i++) + { + if(i == 0) + { + DetectNpcList[i]->SetVisionMode(EVisionMode::Cone); + } + else + { + DetectNpcList[i]->SetVisionMode(EVisionMode::Line); + } + } +} diff --git a/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h b/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h new file mode 100644 index 0000000..8839790 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Managers/SPEnemyVisionManager.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "SPEnemyVisionManager.generated.h" + +/** + * + */ +UCLASS() +class PROJECTT_API USPEnemyVisionManager : public UObject +{ + GENERATED_BODY() + +public: + USPEnemyVisionManager(); + + void InitializeManager(const UObject* WorldObjectContext); + void ReleaseManager(); + void RegisterFocused(class ACoreNpc* InDetectNpc); + void RegisterDetection(class ACoreNpc* InDetectNpc); + void UnregisterDetection(class ACoreNpc* InDetectNpc); + void UnregisterFocused(); + void UnregisterAllDetection(); + bool IsFocusedNpc(class ACoreNpc* InNpc) const; + +protected: + void UpdateSightState(); + +private: + UPROPERTY() + TObjectPtr OuterObject; + + UPROPERTY() + TObjectPtr FocusedNpc; + + UPROPERTY() + TArray> DetectNpcList; +}; diff --git a/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.cpp b/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.cpp new file mode 100644 index 0000000..1358b57 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.cpp @@ -0,0 +1,132 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPWidgetManager.h" +#include "ProjectT/System/Core/Components/PlayerInventoryComponent.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" + + +USPWidgetManager::USPWidgetManager() +{ +} + +void USPWidgetManager::InitializeManager(const UObject* WorldObjectContext) +{ + Super::InitializeManager(WorldObjectContext); +} + +void USPWidgetManager::ReleaseManager() +{ + OnPlayerDead.Unbind(); + OnGameDefeat.Unbind(); + OnGameVictory.Unbind(); + OnInteractionIndicator.Unbind(); + OnUpdatePlayerHP.Unbind(); + OnUpdatePlayerStamina.Unbind(); + OnUpdateTime.Unbind(); + OnUpdateIndicator.Unbind(); + OnUpdateSlotFocus.Unbind(); + OnQuestUpdate.Unbind(); + OnUpdateConsumableSlot.Unbind(); + OnUpdateGimmickSlot.Unbind(); + OnSkillUpdate.Unbind(); + OnQuestInitialized.Unbind(); + + Super::ReleaseManager(); +} + +void USPWidgetManager::ExecuteOnGameDefeat() +{ + if(OnGameDefeat.IsBound()) + OnGameDefeat.Execute(); +} + +void USPWidgetManager::ExecuteOnGameVictory() +{ + if(OnGameVictory.IsBound()) + OnGameVictory.Execute(); +} + +void USPWidgetManager::ExecuteStartGame() +{ + if(OnStartGame.IsBound()) + OnStartGame.Execute(); +} + +void USPWidgetManager::ExecuteOnPlayerDead() +{ + if(!OnPlayerDead.IsBound()) return; + OnPlayerDead.Execute(); +} + +void USPWidgetManager::ExecuteOnInteractionIndicator(const bool bEnabled) +{ + if(!OnInteractionIndicator.IsBound()) return; + OnInteractionIndicator.Execute(bEnabled); +} + +void USPWidgetManager::ExecuteOnUpdatePlayerHP(const float HPRatio) +{ + if(!OnUpdatePlayerHP.IsBound()) return; + OnUpdatePlayerHP.Execute(HPRatio); +} + +void USPWidgetManager::ExecuteOnUpdatePlayerStamina(const float StaminaRatio) +{ + if(!OnUpdatePlayerStamina.IsBound()) return; + OnUpdatePlayerStamina.Execute(StaminaRatio); +} + +void USPWidgetManager::ExecuteOnUpdateTime(const int32 RemainTime) +{ + if(!OnUpdateTime.IsBound()) return; + OnUpdateTime.Execute(RemainTime); +} + +void USPWidgetManager::ExecuteOnUpdateIndicator(const FString& InteractionText, const bool bVisibility) +{ + if(!OnUpdateIndicator.IsBound()) return; + OnUpdateIndicator.Execute(InteractionText, bVisibility); +} + +void USPWidgetManager::ExecuteOnUpdateSlotFocus(const int& SlotIndex, const bool bFocused) +{ + if(!OnUpdateSlotFocus.IsBound()) return; + OnUpdateSlotFocus.Execute(SlotIndex, bFocused); +} + +void USPWidgetManager::ExecuteOnSkillInitialized(TSubclassOf SkillClass, const FString& IconPath) +{ + if(!OnSkillInitialized.IsBound()) return; + OnSkillInitialized.Execute(SkillClass, IconPath); +} + +void USPWidgetManager::ExecuteOnQuestUpdate(const EObjectiveTypes ObjectiveTypes, const FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted) +{ + if(!OnQuestUpdate.IsBound()) return; + OnQuestUpdate.Execute(ObjectiveTypes, ObjectiveSubTypeContext, IsQuestCompleted); +} + +void USPWidgetManager::ExecuteOnSkillUpdate(TSubclassOf SkillClass, const float RemainTimeRatio, const bool bCoolDownComplete) +{ + if(!OnSkillUpdate.IsBound()) return; + OnSkillUpdate.Execute(SkillClass, RemainTimeRatio, bCoolDownComplete); +} + +void USPWidgetManager::ExecuteOnUpdateConsumableSlot(const FName& RowName, const FItem& ItemData, const int32 SlotIndex, const int32 ResultCount) +{ + if(!OnUpdateConsumableSlot.IsBound()) return; + OnUpdateConsumableSlot.Execute(RowName, ItemData, SlotIndex, ResultCount); +} + +void USPWidgetManager::ExecuteOnUpdateGimmickSlot(const FName& RowName, const FPlayerGimmickSlotData& ItemData, const int32 SlotIndex, const int32 ResultCount) +{ + if(!OnUpdateGimmickSlot.IsBound()) return; + OnUpdateGimmickSlot.Execute(RowName, ItemData, SlotIndex, ResultCount); +} + +void USPWidgetManager::ExecuteOnQuestInitialized(const TArray& QuestList) +{ + if(!OnQuestInitialized.IsBound()) return; + OnQuestInitialized.Execute(QuestList); +} diff --git a/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.h b/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.h new file mode 100644 index 0000000..ec79b07 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Managers/SPWidgetManager.h @@ -0,0 +1,142 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "ProjectT/Data/Gen/GenerateStructItem.h" +#include "ProjectT/Data/Gen/GenerateEnumObjectiveTypes.h" +#include "ProjectT/System/Core/Components/PlayerInventoryComponent.h" +#include "ProjectT/System/Core/Managers/CoreWidgetManager.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/SinglePlay/Widget/SPCommonHUD.h" +#include "SPWidgetManager.generated.h" + +DECLARE_DYNAMIC_DELEGATE(FOnStartGame); +DECLARE_DYNAMIC_DELEGATE(FOnPlayerDead); +DECLARE_DYNAMIC_DELEGATE(FOnGameDefeat); +DECLARE_DYNAMIC_DELEGATE(FOnGameVictory); + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnInteractionIndicator, const bool, bEnabled); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnUpdatePlayerHP, const float, HPRatio); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnUpdatePlayerStamina, const float, StaminaRatio); +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnUpdateTime, const int32, RemainTime); + +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnUpdateIndicator, const FString&, InteractionText, const bool, bVisibility); +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnUpdateSlotFocus, const int&, SlotIndex, const bool, bFocused); + +DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnQuestUpdate, const EObjectiveTypes, ObjectiveTypes, const FObjectiveSubTypeContext, ObjectiveSubTypeContext, const bool, IsQuestCompleted); +DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnSkillUpdate, TSubclassOf, SkillClass, const float, RemainTimeRatio, const bool, bCoolDownComplete); + +DECLARE_DYNAMIC_DELEGATE_FourParams(FOnUpdateConsumableSlot, const FName&, RowName, const FItem&, ItemData, const int32, SlotIndex, const int32, ResultCount); +DECLARE_DYNAMIC_DELEGATE_FourParams(FOnUpdateGimmickSlot, const FName&, RowName, const FPlayerGimmickSlotData&, ItemData, const int32, SlotIndex, const int32, ResultCount); + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnQuestInitialized, const TArray&, QuestList); +DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnSkillInitialized, TSubclassOf, SkillClass, const FString&, IconPath); + +UCLASS() +class PROJECTT_API USPWidgetManager : public UCoreWidgetManager +{ + GENERATED_BODY() + +public: + USPWidgetManager(); + + virtual void InitializeManager(const UObject* WorldObjectContext) override; + virtual void ReleaseManager() override; + void ExecuteOnGameDefeat(); + void ExecuteOnGameVictory(); + + UFUNCTION() + void ExecuteStartGame(); + + UFUNCTION() + void ExecuteOnQuestInitialized(const TArray& QuestList); + + UFUNCTION() + void ExecuteOnQuestUpdate(const EObjectiveTypes ObjectiveTypes, const FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted); + + UFUNCTION() + void ExecuteOnPlayerDead(); + + UFUNCTION() + void ExecuteOnInteractionIndicator(const bool bEnabled); + + UFUNCTION() + void ExecuteOnUpdatePlayerHP(const float HPRatio); + + UFUNCTION() + void ExecuteOnUpdatePlayerStamina(const float StaminaRatio); + + UFUNCTION() + void ExecuteOnUpdateTime(const int32 RemainTime); + + UFUNCTION() + void ExecuteOnUpdateIndicator(const FString& InteractionText, const bool bVisibility); + + UFUNCTION() + void ExecuteOnUpdateSlotFocus(const int& SlotIndex, const bool bFocused); + + UFUNCTION() + void ExecuteOnSkillInitialized(TSubclassOf SkillClass, const FString& IconPath); + + UFUNCTION() + void ExecuteOnSkillUpdate(TSubclassOf SkillClass, const float RemainTimeRatio, const bool bCoolDownComplete); + + UFUNCTION() + void ExecuteOnUpdateConsumableSlot(const FName& RowName, const FItem& ItemData, const int32 SlotIndex, const int32 ResultCount); + + UFUNCTION() + void ExecuteOnUpdateGimmickSlot(const FName& RowName, const FPlayerGimmickSlotData& ItemData, const int32 SlotIndex, const int32 ResultCount); + +private: + friend USPCommonHUD; + + UPROPERTY() + FOnPlayerDead OnPlayerDead; + + UPROPERTY() + FOnGameDefeat OnGameDefeat; + + UPROPERTY() + FOnGameVictory OnGameVictory; + + UPROPERTY() + FOnInteractionIndicator OnInteractionIndicator; + + UPROPERTY() + FOnUpdatePlayerHP OnUpdatePlayerHP; + + UPROPERTY() + FOnUpdatePlayerStamina OnUpdatePlayerStamina; + + UPROPERTY() + FOnUpdateTime OnUpdateTime; + + UPROPERTY() + FOnUpdateIndicator OnUpdateIndicator; + + UPROPERTY() + FOnUpdateSlotFocus OnUpdateSlotFocus; + + UPROPERTY() + FOnQuestUpdate OnQuestUpdate; + + UPROPERTY() + FOnUpdateConsumableSlot OnUpdateConsumableSlot; + + UPROPERTY() + FOnUpdateGimmickSlot OnUpdateGimmickSlot; + + UPROPERTY() + FOnSkillUpdate OnSkillUpdate; + + UPROPERTY() + FOnQuestInitialized OnQuestInitialized; + + UPROPERTY() + FOnStartGame OnStartGame; + + UPROPERTY() + FOnSkillInitialized OnSkillInitialized; +}; diff --git a/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.cpp b/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.cpp new file mode 100644 index 0000000..3c972f2 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.cpp @@ -0,0 +1,78 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NPCSpawner.h" + +#include "Kismet/GameplayStatics.h" +#include "ProjectT/ProjectT.h" + +ANPCSpawner::ANPCSpawner() +{ + PrimaryActorTick.bCanEverTick = false; + + RootSceneComponent = CreateDefaultSubobject(FName("RootSceneComponent")); + NMT_CHECKF(RootSceneComponent); + + SetRootComponent(RootSceneComponent); +} + +void ANPCSpawner::Destroyed() +{ +#if WITH_EDITOR + if(IsValid(SpawnedNPCActor)) + { + SpawnedNPCActor->Destroy(); + SpawnedNPCActor = nullptr; + } +#endif + + Super::Destroyed(); +} + +#if WITH_EDITOR +void ANPCSpawner::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); + + if(!GEditor) return; + SpawnNPCByTable(); +} + +void ANPCSpawner::SpawnNPCByTable() +{ + const FString LabelRowName = *GetActorLabel(); + if(LabelRowName.IsNumeric()) + { + + UWorld* World = GetWorld(); + if(IsValid(World)) + { + // @FIXME : 테이블에 따른 정보 필요 + + if(IsValid(SpawnedNPCActor)) + { + SpawnedNPCActor->Destroy(); + SpawnedNPCActor = nullptr; + } + + // @FIXME : 임시 클래스 + FString Path = TEXT("/Game/Characters/NPC/Agent/Blueprints/BP_SPNpcPatrol.BP_SPNpcPatrol_C"); + if (UClass* TargetClass = LoadObject(nullptr, *Path)) + { + SpawnedNPCActor = World->SpawnActorDeferred(TargetClass, FTransform::Identity,nullptr, nullptr, ESpawnActorCollisionHandlingMethod::AlwaysSpawn, ESpawnActorScaleMethod::MultiplyWithRoot); + if(SpawnedNPCActor) + { + SpawnedNPCActor->SetActorLabel(LabelRowName); + UGameplayStatics::FinishSpawningActor(SpawnedNPCActor, FTransform::Identity); + SpawnedNPCActor->AttachToActor(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + NMT_LOG("NPC spawn successed"); + } + } + } + else + { + NMT_LOG("NPC spawn failed. World is not valid"); + } + } +} +#endif \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.h b/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.h new file mode 100644 index 0000000..6eea6e3 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Objects/NPCSpawner.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "NPCSpawner.generated.h" + +UCLASS() +class PROJECTT_API ANPCSpawner : public AActor +{ + GENERATED_BODY() + +public: + ANPCSpawner(); + virtual void Destroyed() override; + +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; + +private: + void SpawnNPCByTable(); +#endif + +protected: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TObjectPtr RootSceneComponent; + +private: + UPROPERTY(VisibleAnywhere) + TObjectPtr SpawnedNPCActor; +}; \ No newline at end of file diff --git a/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.cpp b/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.cpp new file mode 100644 index 0000000..978ab72 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.cpp @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPLevelObject.h" + + +// Sets default values +ASPLevelObject::ASPLevelObject() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; +} + +// Called when the game starts or when spawned +void ASPLevelObject::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASPLevelObject::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + diff --git a/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.h b/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.h new file mode 100644 index 0000000..de50d67 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Objects/SPLevelObject.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Objects/LevelObject/CoreInteractionObject.h" +#include "SPLevelObject.generated.h" + +UCLASS() +class PROJECTT_API ASPLevelObject : public ACoreInteractionObject +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASPLevelObject(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; +}; diff --git a/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.cpp b/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.cpp new file mode 100644 index 0000000..bddcc98 --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.cpp @@ -0,0 +1,103 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "SPCommonHUD.h" + +#include "ProjectT/System/Core/Common/GlobalUtilsLibrary.h" +#include "ProjectT/System/Core/Managers/QuestManager.h" +#include "ProjectT/System/SinglePlay/GameModes/SPGameModeBase.h" +#include "ProjectT/System/SinglePlay/Managers/SPWidgetManager.h" +#include "ProjectT/System/SinglePlay/Interfaces/SPObjectProvider.h" + +void USPCommonHUD::NativeConstruct() +{ + Super::NativeConstruct(); +} + +void USPCommonHUD::InitializeBindEvent() +{ + Super::InitializeBindEvent(); + UWorld* World = UGlobalUtilsLibrary::GetValidWorld(this); + ASPGameModeBase* SPGM = UGlobalUtilsLibrary::GetGameModeChecked(World); + USPWidgetManager* SPWM = ISPObjectProvider::Execute_GetSPWidgetManager(SPGM); + SPWM->OnGameDefeat.BindDynamic(this, &USPCommonHUD::ReceiveGameDefeat); + SPWM->OnGameVictory.BindDynamic(this, &USPCommonHUD::ReceiveGameVictory); + SPWM->OnInteractionIndicator.BindDynamic(this, &USPCommonHUD::ReceiveInteractionIndicator); + SPWM->OnPlayerDead.BindDynamic(this, &USPCommonHUD::ReceivePlayerDead); + SPWM->OnQuestInitialized.BindDynamic(this, &USPCommonHUD::ReceiveQuestInitialized); + SPWM->OnQuestUpdate.BindDynamic(this, &USPCommonHUD::ReceiveQuestUpdate); + SPWM->OnSkillInitialized.BindDynamic(this, &USPCommonHUD::ReceiveSkillInitialized); + SPWM->OnSkillUpdate.BindDynamic(this, &USPCommonHUD::ReceiveSkillUpdate); + SPWM->OnUpdateIndicator.BindDynamic(this, &USPCommonHUD::ReceiveUpdateIndicator); + SPWM->OnUpdateTime.BindDynamic(this, &USPCommonHUD::ReceiveUpdateTime); + SPWM->OnUpdateConsumableSlot.BindDynamic(this, &USPCommonHUD::ReceiveUpdateConsumableSlot); + SPWM->OnUpdateGimmickSlot.BindDynamic(this, &USPCommonHUD::ReceiveUpdateGimmickSlot); + SPWM->OnUpdatePlayerStamina.BindDynamic(this, &USPCommonHUD::ReceiveUpdatePlayerStamina); + SPWM->OnUpdateSlotFocus.BindDynamic(this, &USPCommonHUD::ReceiveUpdateSlotFocus); + SPWM->OnUpdatePlayerHP.BindDynamic(this, &USPCommonHUD::ReceiveUpdatePlayerHP); + SPWM->OnStartGame.BindDynamic(this, &USPCommonHUD::ReceiveStartGame); +} + +void USPCommonHUD::ReceiveStartGame_Implementation() +{ +} + +void USPCommonHUD::ReceivePlayerDead_Implementation() +{ +} + +void USPCommonHUD::ReceiveGameDefeat_Implementation() +{ +} + +void USPCommonHUD::ReceiveGameVictory_Implementation() +{ +} + +void USPCommonHUD::ReceiveInteractionIndicator_Implementation(const bool bEnabled) +{ +} + +void USPCommonHUD::ReceiveUpdatePlayerHP_Implementation(const float HPRatio) +{ +} + +void USPCommonHUD::ReceiveUpdatePlayerStamina_Implementation(const float StaminaRatio) +{ +} + +void USPCommonHUD::ReceiveUpdateTime_Implementation(const int32 RemainTime) +{ +} + +void USPCommonHUD::ReceiveUpdateIndicator_Implementation(const FString& InteractionText, const bool bVisibility) +{ +} + +void USPCommonHUD::ReceiveUpdateSlotFocus_Implementation(const int& SlotIndex, const bool bFocused) +{ +} + +void USPCommonHUD::ReceiveQuestUpdate_Implementation(const EObjectiveTypes ObjectiveTypes, const struct FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted) +{ +} + +void USPCommonHUD::ReceiveSkillUpdate_Implementation(TSubclassOf SkillClass, const float RemainTimeRatio, const bool bCoolDownComplete) +{ +} + +void USPCommonHUD::ReceiveUpdateConsumableSlot_Implementation(const FName& RowName, const FItem& ItemData, const int32 SlotIndex, const int32 ResultCount) +{ +} + +void USPCommonHUD::ReceiveUpdateGimmickSlot_Implementation(const FName& RowName, const FPlayerGimmickSlotData& ItemData, const int32 SlotIndex, const int32 ResultCount) +{ +} + +void USPCommonHUD::ReceiveQuestInitialized_Implementation(const TArray& QuestList) +{ +} + +void USPCommonHUD::ReceiveSkillInitialized_Implementation(TSubclassOf SkillClass, const FString& IconPath) +{ +} diff --git a/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.h b/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.h new file mode 100644 index 0000000..4e0375a --- /dev/null +++ b/Source/ProjectT/System/SinglePlay/Widget/SPCommonHUD.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectT/System/Core/Widget/CommonHUD.h" +#include "SPCommonHUD.generated.h" + +enum class EObjectiveTypes: uint8; + +UCLASS() +class PROJECTT_API USPCommonHUD : public UCommonHUD +{ + GENERATED_BODY() + +protected: + virtual void NativeConstruct() override; + virtual void InitializeBindEvent() override; + + UFUNCTION(BlueprintNativeEvent) + void ReceiveStartGame(); + + UFUNCTION(BlueprintNativeEvent) + void ReceivePlayerDead(); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveGameDefeat(); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveGameVictory(); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveInteractionIndicator(const bool bEnabled); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdatePlayerHP(const float HPRatio); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdatePlayerStamina(const float StaminaRatio); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdateTime(const int32 RemainTime); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdateIndicator(const FString& InteractionText, const bool bVisibility); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdateSlotFocus(const int& SlotIndex, const bool bFocused); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveQuestUpdate(const EObjectiveTypes ObjectiveTypes, const struct FObjectiveSubTypeContext ObjectiveSubTypeContext, const bool IsQuestCompleted); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveSkillUpdate(TSubclassOf SkillClass, const float RemainTimeRatio, const bool bCoolDownComplete); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdateConsumableSlot(const FName& RowName, const FItem& ItemData, const int32 SlotIndex, const int32 ResultCount); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveUpdateGimmickSlot(const FName& RowName, const FPlayerGimmickSlotData& ItemData, const int32 SlotIndex, const int32 ResultCount); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveQuestInitialized(const TArray& QuestList); + + UFUNCTION(BlueprintNativeEvent) + void ReceiveSkillInitialized(TSubclassOf SkillClass, const FString& IconPath); +}; diff --git a/Source/ProjectTEditor.Target.cs b/Source/ProjectTEditor.Target.cs new file mode 100644 index 0000000..6e3bf8a --- /dev/null +++ b/Source/ProjectTEditor.Target.cs @@ -0,0 +1,15 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class ProjectTEditorTarget : TargetRules +{ + public ProjectTEditorTarget( TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V5; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_5; + ExtraModuleNames.AddRange(new string[] { "ProjectT" , "EditorUtilityModule"}); + } +}