Initial VocationLife commit: C++ gameplay module and project foundation.
Source, config, and docs only — UE template assets stay local to save storage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
eae24f1c34
8
.gitattributes
vendored
Normal file
8
.gitattributes
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Unreal Engine binary assets
|
||||||
|
*.uasset filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.umap filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ubulk filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.uexp filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ufont filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.upipelinecache filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ushaderbytecode filter=lfs diff=lfs merge=lfs -text
|
||||||
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Unreal Engine
|
||||||
|
Binaries/
|
||||||
|
DerivedDataCache/
|
||||||
|
Intermediate/
|
||||||
|
Saved/
|
||||||
|
Build/
|
||||||
|
*.sln
|
||||||
|
*.xcodeproj
|
||||||
|
*.xcworkspace
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
*.VC.db
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
|
||||||
|
# Epic template content (keep local, do not push — saves LFS/bandwidth)
|
||||||
|
Content/*
|
||||||
|
!Content/VocationLife/
|
||||||
|
Content/VocationLife/**/*.uasset
|
||||||
|
Content/VocationLife/**/*.umap
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Crash reports
|
||||||
|
*.log
|
||||||
32
Config/DefaultEditor.ini
Normal file
32
Config/DefaultEditor.ini
Normal file
File diff suppressed because one or more lines are too long
5
Config/DefaultEditorPerProjectUserSettings.ini
Normal file
5
Config/DefaultEditorPerProjectUserSettings.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[ContentBrowser]
|
||||||
|
ContentBrowserTab1.SelectedPaths=/Game/VocationLife
|
||||||
|
|
||||||
|
[/Script/InEditorDocumentation.InEditorDocumentationSettings]
|
||||||
|
TutorialUrl="https://dev.epicgames.com/documentation/unreal-engine/introduction-to-unreal-engine"
|
||||||
271
Config/DefaultEngine.ini
Normal file
271
Config/DefaultEngine.ini
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
[/Script/Engine.CollisionProfile]
|
||||||
|
+Profiles=(Name="Projectile",CollisionEnabled=QueryOnly,ObjectTypeName="Projectile",CustomResponses=,HelpMessage="Preset for projectiles",bCanModify=True)
|
||||||
|
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,Name="Projectile",DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False)
|
||||||
|
+EditProfiles=(Name="Trigger",CustomResponses=((Channel=Projectile, Response=ECR_Ignore)))
|
||||||
|
|
||||||
|
[/Script/EngineSettings.GameMapsSettings]
|
||||||
|
EditorStartupMap=/Engine/Maps/Entry.Entry
|
||||||
|
LocalMapOptions=
|
||||||
|
TransitionMap=
|
||||||
|
bUseSplitscreen=True
|
||||||
|
TwoPlayerSplitscreenLayout=Horizontal
|
||||||
|
ThreePlayerSplitscreenLayout=FavorTop
|
||||||
|
GameInstanceClass=/Script/VocationLife.VocationGameInstance
|
||||||
|
GameDefaultMap=/Engine/Maps/Entry.Entry
|
||||||
|
ServerDefaultMap=/Engine/Maps/Entry.Entry
|
||||||
|
GlobalDefaultGameMode=/Script/VocationLife.VocationGameMode
|
||||||
|
GlobalDefaultServerGameMode=/Script/VocationLife.VocationGameMode
|
||||||
|
|
||||||
|
[/Script/Engine.RendererSettings]
|
||||||
|
r.Mobile.ShadingPath=1
|
||||||
|
r.Mobile.ExtendedGBuffer=False
|
||||||
|
r.Mobile.AntiAliasing=2
|
||||||
|
r.Mobile.FloatPrecisionMode=0
|
||||||
|
r.Mobile.AllowDitheredLODTransition=False
|
||||||
|
r.DiscardUnusedQuality=False
|
||||||
|
r.AllowOcclusionQueries=True
|
||||||
|
r.MinScreenRadiusForLights=0.030000
|
||||||
|
r.MinScreenRadiusForDepthPrepass=0.030000
|
||||||
|
r.PrecomputedVisibilityWarning=False
|
||||||
|
r.TextureStreaming=True
|
||||||
|
Compat.UseDXT5NormalMaps=False
|
||||||
|
r.VirtualTextures=True
|
||||||
|
r.VirtualTexturedLightmaps=False
|
||||||
|
r.VT.TileSize=128
|
||||||
|
r.VT.TileBorderSize=4
|
||||||
|
r.VT.AnisotropicFiltering=False
|
||||||
|
r.VT.EnableAutoImport=False
|
||||||
|
bEnableVirtualTextureOpacityMask=False
|
||||||
|
r.MeshPaintVirtualTexture.Support=True
|
||||||
|
r.MeshPaintVirtualTexture.TileSize=32
|
||||||
|
r.MeshPaintVirtualTexture.TileBorderSize=2
|
||||||
|
r.MeshPaintVirtualTexture.UseCompression=True
|
||||||
|
r.StaticMesh.DefaultMeshPaintTextureSupport=True
|
||||||
|
r.MeshPaintVirtualTexture.DefaultTexelsPerVertex=4
|
||||||
|
r.MeshPaintVirtualTexture.MaxTextureSize=4096
|
||||||
|
r.vt.rvt.EnableBaseColor=True
|
||||||
|
r.vt.rvt.EnableBaseColorRoughness=True
|
||||||
|
r.vt.rvt.EnableBaseColorSpecular=True
|
||||||
|
r.vt.rvt.EnableMask4=True
|
||||||
|
r.vt.rvt.EnableWorldHeight=True
|
||||||
|
r.vt.rvt.EnableDisplacement=True
|
||||||
|
r.vt.rvt.HighQualityPerPixelHeight=True
|
||||||
|
WorkingColorSpaceChoice=sRGB
|
||||||
|
RedChromaticityCoordinate=(X=0.640000,Y=0.330000)
|
||||||
|
GreenChromaticityCoordinate=(X=0.300000,Y=0.600000)
|
||||||
|
BlueChromaticityCoordinate=(X=0.150000,Y=0.060000)
|
||||||
|
WhiteChromaticityCoordinate=(X=0.312700,Y=0.329000)
|
||||||
|
r.LegacyLuminanceFactors=False
|
||||||
|
r.ClearCoatNormal=False
|
||||||
|
r.DynamicGlobalIlluminationMethod=1
|
||||||
|
r.ReflectionMethod=1
|
||||||
|
r.ReflectionCaptureResolution=512
|
||||||
|
r.ReflectionEnvironmentLightmapMixBasedOnRoughness=True
|
||||||
|
r.Lumen.HardwareRayTracing=True
|
||||||
|
r.Lumen.HardwareRayTracing.LightingMode=0
|
||||||
|
r.Lumen.TranslucencyReflections.FrontLayer.EnableForProject=False
|
||||||
|
r.Lumen.TraceMeshSDFs=0
|
||||||
|
r.Lumen.ScreenTracingSource=0
|
||||||
|
r.Lumen.Reflections.HardwareRayTracing.Translucent.Refraction.EnableForProject=False
|
||||||
|
r.MegaLights.EnableForProject=False
|
||||||
|
r.MegaLights.FrontLayerTranslucency.EnableForProject=False
|
||||||
|
r.RayTracing.Shadows=False
|
||||||
|
r.Shadow.Virtual.Enable=1
|
||||||
|
r.RayTracing=True
|
||||||
|
r.RayTracing.RayTracingProxies.ProjectEnabled=True
|
||||||
|
r.RayTracing.UseTextureLod=False
|
||||||
|
r.PathTracing=True
|
||||||
|
r.GenerateMeshDistanceFields=True
|
||||||
|
r.DistanceFields.DefaultVoxelDensity=0.200000
|
||||||
|
r.Nanite.ProjectEnabled=True
|
||||||
|
r.AllowStaticLighting=False
|
||||||
|
r.NormalMapsForStaticLighting=False
|
||||||
|
r.ForwardShading=False
|
||||||
|
r.VertexFoggingForOpaque=True
|
||||||
|
r.SeparateTranslucency=True
|
||||||
|
r.TranslucentSortPolicy=0
|
||||||
|
TranslucentSortAxis=(X=0.000000,Y=-1.000000,Z=0.000000)
|
||||||
|
r.LocalFogVolume.ApplyOnTranslucent=False
|
||||||
|
xr.VRS.FoveationLevel=0
|
||||||
|
xr.VRS.DynamicFoveation=False
|
||||||
|
r.CustomDepth=1
|
||||||
|
r.CustomDepthTemporalAAJitter=True
|
||||||
|
r.PostProcessing.PropagateAlpha=False
|
||||||
|
r.Deferred.SupportPrimitiveAlphaHoldout=False
|
||||||
|
r.DefaultFeature.Bloom=True
|
||||||
|
r.DefaultFeature.AmbientOcclusion=True
|
||||||
|
r.DefaultFeature.AmbientOcclusionStaticFraction=True
|
||||||
|
r.DefaultFeature.AutoExposure=False
|
||||||
|
r.DefaultFeature.AutoExposure.Method=0
|
||||||
|
r.DefaultFeature.AutoExposure.Bias=1.000000
|
||||||
|
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
|
||||||
|
r.DefaultFeature.LocalExposure.HighlightContrastScale=0.800000
|
||||||
|
r.DefaultFeature.LocalExposure.ShadowContrastScale=0.800000
|
||||||
|
r.DefaultFeature.MotionBlur=False
|
||||||
|
r.DefaultFeature.LensFlare=False
|
||||||
|
r.TemporalAA.Upsampling=True
|
||||||
|
r.AntiAliasingMethod=0
|
||||||
|
r.MSAACount=4
|
||||||
|
r.DefaultFeature.LightUnits=2
|
||||||
|
r.DefaultBackBufferPixelFormat=4
|
||||||
|
r.ScreenPercentage.Default=100.000000
|
||||||
|
r.ScreenPercentage.Default.Desktop.Mode=1
|
||||||
|
r.ScreenPercentage.Default.Mobile.Mode=0
|
||||||
|
r.ScreenPercentage.Default.VR.Mode=0
|
||||||
|
r.ScreenPercentage.Default.PathTracer.Mode=0
|
||||||
|
r.Shadow.UnbuiltPreviewInGame=True
|
||||||
|
r.StencilForLODDither=False
|
||||||
|
r.EarlyZPass=3
|
||||||
|
r.EarlyZPassOnlyMaterialMasking=True
|
||||||
|
r.Shadow.CSMCaching=False
|
||||||
|
r.DBuffer=True
|
||||||
|
r.ClearSceneMethod=1
|
||||||
|
r.VelocityOutputPass=0
|
||||||
|
r.Velocity.EnableVertexDeformation=2
|
||||||
|
r.SelectiveBasePassOutputs=False
|
||||||
|
bDefaultParticleCutouts=False
|
||||||
|
fx.GPUSimulationTextureSizeX=1024
|
||||||
|
fx.GPUSimulationTextureSizeY=1024
|
||||||
|
r.AllowGlobalClipPlane=False
|
||||||
|
r.GBufferFormat=1
|
||||||
|
r.MorphTarget.Mode=True
|
||||||
|
r.MorphTarget.MaxBlendWeight=5.000000
|
||||||
|
r.SupportSkyAtmosphere=True
|
||||||
|
r.SupportSkyAtmosphereAffectsHeightFog=True
|
||||||
|
r.SupportExpFogMatchesVolumetricFog=False
|
||||||
|
r.SupportLocalFogVolumes=True
|
||||||
|
r.SupportCloudShadowOnForwardLitTranslucent=False
|
||||||
|
r.ClusteredDeferredShading.EnableForProject=True
|
||||||
|
r.LightFunctionAtlas.Format=0
|
||||||
|
r.VolumetricFog.LightFunction=True
|
||||||
|
r.Deferred.UsesLightFunctionAtlas=True
|
||||||
|
r.SingleLayerWater.UsesLightFunctionAtlas=False
|
||||||
|
r.Translucent.UsesLightFunctionAtlas=False
|
||||||
|
r.Translucent.UsesIESProfiles=False
|
||||||
|
r.Translucent.UsesRectLights=False
|
||||||
|
r.Translucent.UsesShadowedLocalLights=False
|
||||||
|
r.GPUCrashDebugging=False
|
||||||
|
vr.InstancedStereo=False
|
||||||
|
r.MobileHDR=True
|
||||||
|
vr.MobileMultiView=False
|
||||||
|
r.Mobile.UseHWsRGBEncoding=False
|
||||||
|
vr.RoundRobinOcclusion=False
|
||||||
|
r.MeshStreaming=False
|
||||||
|
r.HeterogeneousVolumes=True
|
||||||
|
r.HeterogeneousVolumes.Shadows=False
|
||||||
|
r.Translucency.HeterogeneousVolumes=False
|
||||||
|
r.WireframeCullThreshold=5.000000
|
||||||
|
r.SupportStationarySkylight=True
|
||||||
|
r.SupportLowQualityLightmaps=True
|
||||||
|
r.SupportPointLightWholeSceneShadows=True
|
||||||
|
r.Shadow.TranslucentPerObject.ProjectEnabled=False
|
||||||
|
r.Water.SingleLayerWater.SupportCloudShadow=False
|
||||||
|
r.Substrate=False
|
||||||
|
r.Substrate.ProjectGBufferFormat=0
|
||||||
|
r.Substrate.ProjectClosuresPerPixel=4
|
||||||
|
r.Substrate.ProjectClosuresPerPixelOverride=0
|
||||||
|
r.Substrate.BytesPerPixel=80
|
||||||
|
r.Substrate.OpaqueMaterialRoughRefraction=False
|
||||||
|
r.Refraction.Blur=False
|
||||||
|
r.Substrate.Debug.AdvancedVisualizationShaders=False
|
||||||
|
r.Substrate.EnableLayerSupport=False
|
||||||
|
r.Material.RoughDiffuse=False
|
||||||
|
r.Material.EnergyConservation=False
|
||||||
|
r.Material.DefaultAutoMaterialUsage=True
|
||||||
|
r.OIT.SortedPixels=False
|
||||||
|
r.HairStrands.LODMode=True
|
||||||
|
r.VRS.Support=True
|
||||||
|
r.Mobile.EnableStaticAndCSMShadowReceivers=True
|
||||||
|
r.Mobile.EnableMovableLightCSMShaderCulling=True
|
||||||
|
r.Mobile.Forward.EnableLocalLights=1
|
||||||
|
r.Mobile.Forward.EnableClusteredReflections=False
|
||||||
|
r.Mobile.AllowDistanceFieldShadows=True
|
||||||
|
r.Mobile.EnableMovableSpotlightsShadow=False
|
||||||
|
r.GPUSkin.Limit2BoneInfluences=False
|
||||||
|
r.SupportDepthOnlyIndexBuffers=False
|
||||||
|
r.SupportReversedIndexBuffers=False
|
||||||
|
slate.MaterialShaderMode=0
|
||||||
|
r.Mobile.AmbientOcclusion=False
|
||||||
|
r.Mobile.ScreenSpaceReflections=False
|
||||||
|
r.Mobile.DBuffer=False
|
||||||
|
r.Mobile.PropagateAlpha=False
|
||||||
|
r.GPUSkin.UnlimitedBoneInfluences=False
|
||||||
|
r.GPUSkin.AlwaysUseDeformerForUnlimitedBoneInfluences=False
|
||||||
|
r.GPUSkin.UnlimitedBoneInfluencesThreshold=8
|
||||||
|
DefaultBoneInfluenceLimit=(Default=0,PerPlatform=())
|
||||||
|
r.SkinCache.CompileShaders=1
|
||||||
|
r.SkinCache.DefaultBehavior=1
|
||||||
|
r.Nanite.Foliage=False
|
||||||
|
bNaniteStreamableBulkDataOptional=(Default=False,PerPlatform=())
|
||||||
|
bStreamSkeletalMeshLODs=(Default=False,PerPlatform=())
|
||||||
|
bDiscardSkeletalMeshOptionalLODs=(Default=False,PerPlatform=())
|
||||||
|
VisualizeCalibrationColorMaterialPath=/Engine/EngineMaterials/PPM_DefaultCalibrationColor.PPM_DefaultCalibrationColor
|
||||||
|
VisualizeCalibrationCustomMaterialPath=None
|
||||||
|
VisualizeCalibrationGrayscaleMaterialPath=/Engine/EngineMaterials/PPM_DefaultCalibrationGrayscale.PPM_DefaultCalibrationGrayscale
|
||||||
|
r.PSOPrecache.ProxyCreationStrategy=1
|
||||||
|
PSOPrecacheFallbackMaterial=None
|
||||||
|
|
||||||
|
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
|
||||||
|
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
|
||||||
|
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
|
||||||
|
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
|
||||||
|
-D3D12TargetedShaderFormats=PCD3D_SM5
|
||||||
|
+D3D12TargetedShaderFormats=PCD3D_SM6
|
||||||
|
-D3D11TargetedShaderFormats=PCD3D_SM5
|
||||||
|
+D3D11TargetedShaderFormats=PCD3D_SM5
|
||||||
|
|
||||||
|
[/Script/HardwareTargeting.HardwareTargetingSettings]
|
||||||
|
TargetedHardwareClass=Desktop
|
||||||
|
AppliedTargetedHardwareClass=Desktop
|
||||||
|
DefaultGraphicsPerformance=Scalable
|
||||||
|
AppliedDefaultGraphicsPerformance=Scalable
|
||||||
|
|
||||||
|
[/Script/Engine.Engine]
|
||||||
|
NearClipPlane=5.000000
|
||||||
|
|
||||||
|
+ActiveGameNameRedirects=(OldGameName="VocationLife",NewGameName="/Script/VocationLife")
|
||||||
|
+ActiveGameNameRedirects=(OldGameName="/Script/VocationLife",NewGameName="/Script/VocationLife")
|
||||||
|
|
||||||
|
[/Script/OnlineSubsystemUtils.IpNetDriver]
|
||||||
|
NetServerMaxTickRate=60
|
||||||
|
|
||||||
|
[/Script/OnlineSubsystemSteam.SteamNetDriver]
|
||||||
|
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
|
||||||
|
|
||||||
|
[OnlineSubsystem]
|
||||||
|
DefaultPlatformService=Null
|
||||||
|
|
||||||
|
[OnlineSubsystemNull]
|
||||||
|
bEnabled=true
|
||||||
|
|
||||||
|
[OnlineSubsystemSteam]
|
||||||
|
bEnabled=true
|
||||||
|
SteamDevAppId=480
|
||||||
|
bInitServerOnClient=true
|
||||||
|
|
||||||
|
[/Script/Engine.GameEngine]
|
||||||
|
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
|
||||||
|
|
||||||
|
[/Script/OnlineSubsystemUtils.OnlineSession]
|
||||||
|
bUseBuildIdOverride=false
|
||||||
|
|
||||||
|
[/Script/AIModule.AISystem]
|
||||||
|
bForgetStaleActors=True
|
||||||
|
|
||||||
|
[/Script/Engine.UserInterfaceSettings]
|
||||||
|
UIScaleRule=ShortestSide
|
||||||
|
|
||||||
|
[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings]
|
||||||
|
bEnablePlugin=True
|
||||||
|
bAllowNetworkConnection=True
|
||||||
|
SecurityToken=55490E894C07D04A1ACF51BB99492878
|
||||||
|
bIncludeInShipping=False
|
||||||
|
bAllowExternalStartInShipping=False
|
||||||
|
bCompileAFSProject=False
|
||||||
|
bUseCompression=False
|
||||||
|
bLogFiles=False
|
||||||
|
bReportStats=False
|
||||||
|
ConnectionType=USBOnly
|
||||||
|
bUseManualIPAddress=False
|
||||||
|
ManualIPAddress=
|
||||||
|
|
||||||
22
Config/DefaultGame.ini
Normal file
22
Config/DefaultGame.ini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[/Script/EngineSettings.GeneralProjectSettings]
|
||||||
|
ProjectID=019F047E36E8731BAF0FDD0409BFCFA0
|
||||||
|
ProjectName=VocationLife
|
||||||
|
CompanyName=VocationLife Project
|
||||||
|
ProjectVersion=0.1.0
|
||||||
|
Description=Life-sim remake inspired by Fantasy Life with first-person and top-down cameras, co-op multiplayer, and dedicated server support.
|
||||||
|
SupportContact=
|
||||||
|
Homepage=
|
||||||
|
LicensingTerms=
|
||||||
|
PrivacyPolicy=
|
||||||
|
bStartInVR=False
|
||||||
|
|
||||||
|
[ConsoleVariables]
|
||||||
|
CommonUI.CheckKeyboardFocusAndParentage=1
|
||||||
|
CommonUI.DisallowUserFocusedWidgetForPendingFocusRecipient=1
|
||||||
|
CommonUI.FallbackToDesiredOnAutoRestoreFailure=1
|
||||||
|
|
||||||
|
[/Script/VocationLife.VocationEOS]
|
||||||
|
bEOSEnabled=false
|
||||||
|
ProductId=
|
||||||
|
SandboxId=
|
||||||
|
DeploymentId=
|
||||||
120
Config/DefaultInput.ini
Normal file
120
Config/DefaultInput.ini
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
[/Script/Engine.InputSettings]
|
||||||
|
-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
|
||||||
|
-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
|
||||||
|
-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
|
||||||
|
-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
|
||||||
|
-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
|
||||||
|
-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
|
||||||
|
-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
|
||||||
|
+AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Touch",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_FaceButton1",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_FaceButton2",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_IndexPointing",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_ThumbUp",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Left_ThumbRest",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_FaceButton1",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_FaceButton2",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_IndexPointing",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_ThumbUp",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusTouch_Right_ThumbRest",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Left_ThumbPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Left_IndexPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Left_MiddlePinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Left_RingPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Left_PinkPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Right_ThumbPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Right_IndexPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Right_MiddlePinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Right_RingPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="OculusHand_Right_PinkPinchStrength",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
+AxisConfig=(AxisKeyName="Cosmos_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
|
||||||
|
bAltEnterTogglesFullscreen=True
|
||||||
|
bF11TogglesFullscreen=True
|
||||||
|
bUseMouseForTouch=False
|
||||||
|
bEnableMouseSmoothing=True
|
||||||
|
bEnableFOVScaling=True
|
||||||
|
bCaptureMouseOnLaunch=True
|
||||||
|
bEnableLegacyInputScales=True
|
||||||
|
bEnableMotionControls=True
|
||||||
|
bFilterInputByPlatformUser=False
|
||||||
|
bShouldFlushPressedKeysOnViewportFocusLost=True
|
||||||
|
bAlwaysShowTouchInterface=False
|
||||||
|
bShowConsoleOnFourFingerTap=True
|
||||||
|
bEnableGestureRecognizer=False
|
||||||
|
bUseAutocorrect=False
|
||||||
|
DefaultViewportMouseCaptureMode=CapturePermanently
|
||||||
|
DefaultViewportMouseLockMode=LockAlways
|
||||||
|
FOVScale=0.011110
|
||||||
|
DoubleClickTime=0.200000
|
||||||
|
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
|
||||||
|
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
|
||||||
|
DefaultTouchInterface=None
|
||||||
|
-ConsoleKeys=Tilde
|
||||||
|
+ConsoleKeys=Tilde
|
||||||
|
|
||||||
|
[EnhancedInputPlatformSettings_Windows EnhancedInputPlatformSettings]
|
||||||
|
bShouldLogMappingContextRedirects=False
|
||||||
|
|
||||||
31
Config/Localization/Game_Compile.ini
Normal file
31
Config/Localization/Game_Compile.ini
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
ResourceName=Game.locres
|
||||||
|
bSkipSourceCheck=false
|
||||||
|
bValidateFormatPatterns=true
|
||||||
|
bValidateSafeWhitespace=false
|
||||||
|
bValidateRichTextTags=false
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=GenerateTextLocalizationResource
|
||||||
|
|
||||||
32
Config/Localization/Game_Export.ini
Normal file
32
Config/Localization/Game_Export.ini
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
PortableObjectName=Game.po
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=InternationalizationExport
|
||||||
|
bExportLoc=true
|
||||||
|
LocalizedTextCollapseMode=ELocalizedTextCollapseMode::IdenticalTextIdAndSource
|
||||||
|
POFormat=EPortableObjectFormat::Unreal
|
||||||
|
ShouldPersistCommentsOnExport=false
|
||||||
|
ShouldAddSourceLocationsAsComments=true
|
||||||
|
|
||||||
27
Config/Localization/Game_ExportDialogueScript.ini
Normal file
27
Config/Localization/Game_ExportDialogueScript.ini
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
DialogueScriptName=GameDialogue.csv
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=ExportDialogueScript
|
||||||
|
|
||||||
48
Config/Localization/Game_Gather.ini
Normal file
48
Config/Localization/Game_Gather.ini
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
ManifestDependencies=../../Engine/Content/Localization/Engine/Engine.manifest
|
||||||
|
ManifestDependencies=../../Engine/Content/Localization/Editor/Editor.manifest
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=GatherTextFromAssets
|
||||||
|
IncludePathFilters=Content/DemoTemplate/*
|
||||||
|
ExcludePathFilters=Content/Localization/*
|
||||||
|
PackageFileNameFilters=*.umap
|
||||||
|
PackageFileNameFilters=*.uasset
|
||||||
|
ShouldExcludeDerivedClasses=false
|
||||||
|
ShouldGatherFromEditorOnlyData=false
|
||||||
|
SkipGatherCache=false
|
||||||
|
|
||||||
|
[GatherTextStep1]
|
||||||
|
CommandletClass=GenerateGatherManifest
|
||||||
|
|
||||||
|
[GatherTextStep2]
|
||||||
|
CommandletClass=GenerateGatherArchive
|
||||||
|
|
||||||
|
[GatherTextStep3]
|
||||||
|
CommandletClass=GenerateTextLocalizationReport
|
||||||
|
bWordCountReport=true
|
||||||
|
WordCountReportName=Game.csv
|
||||||
|
bConflictReport=true
|
||||||
|
ConflictReportName=Game_Conflicts.txt
|
||||||
|
|
||||||
27
Config/Localization/Game_GenerateReports.ini
Normal file
27
Config/Localization/Game_GenerateReports.ini
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=GenerateTextLocalizationReport
|
||||||
|
bWordCountReport=true
|
||||||
|
WordCountReportName=Game.csv
|
||||||
|
|
||||||
30
Config/Localization/Game_Import.ini
Normal file
30
Config/Localization/Game_Import.ini
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
PortableObjectName=Game.po
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=InternationalizationExport
|
||||||
|
bImportLoc=true
|
||||||
|
LocalizedTextCollapseMode=ELocalizedTextCollapseMode::IdenticalTextIdAndSource
|
||||||
|
POFormat=EPortableObjectFormat::Unreal
|
||||||
|
|
||||||
28
Config/Localization/Game_ImportDialogue.ini
Normal file
28
Config/Localization/Game_ImportDialogue.ini
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=ImportLocalizedDialogue
|
||||||
|
RawAudioPath=
|
||||||
|
ImportedDialogueFolder=ImportedDialogue
|
||||||
|
bImportNativeAsSource=false
|
||||||
|
|
||||||
27
Config/Localization/Game_ImportDialogueScript.ini
Normal file
27
Config/Localization/Game_ImportDialogueScript.ini
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; THESE ARE GENERATED FILES, DO NOT EDIT DIRECTLY!
|
||||||
|
; USE THE LOCALIZATION DASHBOARD IN THE UNREAL EDITOR TO EDIT THE CONFIGURATION
|
||||||
|
[CommonSettings]
|
||||||
|
SourcePath=Content/Localization/Game
|
||||||
|
DestinationPath=Content/Localization/Game
|
||||||
|
NativeCulture=en
|
||||||
|
CulturesToGenerate=en
|
||||||
|
CulturesToGenerate=ar
|
||||||
|
CulturesToGenerate=ko
|
||||||
|
CulturesToGenerate=ja
|
||||||
|
CulturesToGenerate=zh-Hans
|
||||||
|
CulturesToGenerate=fr
|
||||||
|
CulturesToGenerate=de
|
||||||
|
CulturesToGenerate=it
|
||||||
|
CulturesToGenerate=es
|
||||||
|
CulturesToGenerate=es-419
|
||||||
|
CulturesToGenerate=pl
|
||||||
|
CulturesToGenerate=pt-BR
|
||||||
|
CulturesToGenerate=ru
|
||||||
|
CulturesToGenerate=tr
|
||||||
|
ManifestName=Game.manifest
|
||||||
|
ArchiveName=Game.archive
|
||||||
|
DialogueScriptName=GameDialogue.csv
|
||||||
|
|
||||||
|
[GatherTextStep0]
|
||||||
|
CommandletClass=ImportDialogueScript
|
||||||
|
|
||||||
5
Config/ServerConfig.ini
Normal file
5
Config/ServerConfig.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[/Script/VocationLife.VocationServerSettings]
|
||||||
|
ServerName=VocationLife Dedicated Server
|
||||||
|
MaxPlayers=4
|
||||||
|
Port=7777
|
||||||
|
bLANOnly=true
|
||||||
0
Content/VocationLife/Camera/.gitkeep
Normal file
0
Content/VocationLife/Camera/.gitkeep
Normal file
0
Content/VocationLife/Characters/.gitkeep
Normal file
0
Content/VocationLife/Characters/.gitkeep
Normal file
0
Content/VocationLife/Core/.gitkeep
Normal file
0
Content/VocationLife/Core/.gitkeep
Normal file
0
Content/VocationLife/Input/.gitkeep
Normal file
0
Content/VocationLife/Input/.gitkeep
Normal file
0
Content/VocationLife/Network/.gitkeep
Normal file
0
Content/VocationLife/Network/.gitkeep
Normal file
0
Content/VocationLife/Systems/.gitkeep
Normal file
0
Content/VocationLife/Systems/.gitkeep
Normal file
0
Content/VocationLife/UI/.gitkeep
Normal file
0
Content/VocationLife/UI/.gitkeep
Normal file
0
Content/VocationLife/World/.gitkeep
Normal file
0
Content/VocationLife/World/.gitkeep
Normal file
30
Docs/CrossplayEOS.md
Normal file
30
Docs/CrossplayEOS.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Crossplay (Epic Online Services)
|
||||||
|
|
||||||
|
VocationLife ships with an EOS integration layer that is **disabled by default**.
|
||||||
|
|
||||||
|
## Enable EOS
|
||||||
|
|
||||||
|
1. Open `VocationLife.uproject` and enable the **OnlineSubsystemEOS** plugin.
|
||||||
|
2. Set credentials in [`Config/DefaultGame.ini`](../Config/DefaultGame.ini):
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[/Script/VocationLife.VocationEOS]
|
||||||
|
bEOSEnabled=true
|
||||||
|
ProductId=YOUR_PRODUCT_ID
|
||||||
|
SandboxId=YOUR_SANDBOX_ID
|
||||||
|
DeploymentId=YOUR_DEPLOYMENT_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Configure the EOS plugin settings in `Config/DefaultEngine.ini` per Epic documentation.
|
||||||
|
4. Call `InitializeEOS()` on `UVocationEOSSubsystem` from your menu flow once UI is ready.
|
||||||
|
|
||||||
|
## Console ports
|
||||||
|
|
||||||
|
Console builds require platform SDKs and certification. Recommended order:
|
||||||
|
|
||||||
|
1. Stabilize PC multiplayer (listen + dedicated)
|
||||||
|
2. Enable EOS for PC crossplay
|
||||||
|
3. Add PlayStation / Xbox targets with platform-specific Online Subsystem modules
|
||||||
|
4. Use separate scalability profiles (no hardware RT on consoles)
|
||||||
|
|
||||||
|
The `UVocationSessionSubsystem` can be extended to route session creation through EOS when `UVocationEOSSubsystem::IsEOSEnabled()` returns true.
|
||||||
42
Docs/DedicatedServer.md
Normal file
42
Docs/DedicatedServer.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Dedicated Server Hosting
|
||||||
|
|
||||||
|
VocationLife includes a `VocationLifeServer` build target for headless dedicated hosting.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Engine/Build/BatchFiles/RunUBT.sh VocationLifeServer Linux Development \
|
||||||
|
-project="/path/to/VocationLife/VocationLife.uproject"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Some UE Linux preview distributions do not ship server targets. Use a full engine build or Windows `VocationLifeServer` target if Linux server compilation is unavailable.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit [`Config/ServerConfig.ini`](../Config/ServerConfig.ini):
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[/Script/VocationLife.VocationServerSettings]
|
||||||
|
ServerName=VocationLife Dedicated Server
|
||||||
|
MaxPlayers=4
|
||||||
|
Port=7777
|
||||||
|
bLANOnly=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./VocationLife/Binaries/Linux/VocationLifeServer \
|
||||||
|
/Game/Engine/Maps/Entry \
|
||||||
|
-log -port=7777 -MaxPlayers=4
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connect
|
||||||
|
|
||||||
|
From a client console (`~`):
|
||||||
|
|
||||||
|
```
|
||||||
|
open 127.0.0.1:7777
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use **H** to host and **J** to join from the in-game pause overlay (LAN).
|
||||||
99
README.md
Normal file
99
README.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# VocationLife
|
||||||
|
|
||||||
|
A life-simulation action RPG remake inspired by Fantasy Life, built in **Unreal Engine 5.8**.
|
||||||
|
|
||||||
|
## Vision
|
||||||
|
|
||||||
|
- First-person gameplay (primary) with classic top-down camera toggle
|
||||||
|
- Mouse, keyboard, and gamepad support via Enhanced Input
|
||||||
|
- Co-op multiplayer (listen server first, dedicated server hosting)
|
||||||
|
- Optional hardware ray tracing and scalability presets
|
||||||
|
- Future crossplay via Epic Online Services (EOS)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Unreal Engine 5.8
|
||||||
|
- Windows (DX12), Linux (Vulkan), or macOS
|
||||||
|
- GPU with ray tracing support for the RT preset (optional)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Open `VocationLife.uproject` in Unreal Engine 5.8.
|
||||||
|
2. Allow the editor to compile the `VocationLife` C++ module on first launch.
|
||||||
|
3. Press **Play** — a test world (floor, mining nodes, enemy) is spawned automatically.
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
| Action | Keyboard | Gamepad |
|
||||||
|
|--------|----------|---------|
|
||||||
|
| Move | WASD | Left stick |
|
||||||
|
| Look | Mouse | Right stick |
|
||||||
|
| Jump | Space | A / Cross |
|
||||||
|
| Interact / Craft | E | X / Square |
|
||||||
|
| Attack | LMB | RT |
|
||||||
|
| Toggle camera (FP / Top-Down) | V | Menu |
|
||||||
|
| Quick save | I | Y / Triangle |
|
||||||
|
| Pause | Esc | Start |
|
||||||
|
|
||||||
|
### Pause menu shortcuts
|
||||||
|
|
||||||
|
While paused:
|
||||||
|
|
||||||
|
- **F1–F5** — Graphics presets (Low → Ray Tracing)
|
||||||
|
- **H** — Host co-op session
|
||||||
|
- **J** — Find and join LAN session
|
||||||
|
- **S** — Save game
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
Content/VocationLife/ Blueprint extensions and art (create in editor)
|
||||||
|
Source/VocationLife/ Core gameplay C++ (camera, input, inventory, crafting, multiplayer)
|
||||||
|
Config/ Engine and server configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dedicated Server Hosting
|
||||||
|
|
||||||
|
Build the server target:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/path/to/UnrealEngine/Engine/Build/BatchFiles/Linux/Build.sh \
|
||||||
|
VocationLifeServer Linux Development \
|
||||||
|
-project="/path/to/VocationLife/VocationLife.uproject"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run headless:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./VocationLife/Binaries/Linux/VocationLifeServer \
|
||||||
|
-log -port=7777 -MaxPlayers=4
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `Config/ServerConfig.ini` for server name, port, and player limit.
|
||||||
|
|
||||||
|
Clients connect with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
open 127.0.0.1:7777
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiplayer
|
||||||
|
|
||||||
|
- **LAN / Null subsystem** — works out of the box for local testing.
|
||||||
|
- **Steam** — set `SteamDevAppId` in `Config/DefaultEngine.ini` (default: 480 for Spacewar test app).
|
||||||
|
- **EOS Crossplay** — enable `OnlineSubsystemEOS` plugin and fill credentials in `Config/DefaultGame.ini` under `[/Script/VocationLife.VocationEOS]`.
|
||||||
|
|
||||||
|
## Graphics Presets
|
||||||
|
|
||||||
|
Presets are applied at runtime via `UVocationGraphicsLibrary`:
|
||||||
|
|
||||||
|
- Low / Medium / High / Ultra — scalability levels
|
||||||
|
- Ray Tracing — enables `r.RayTracing`, Lumen HW-RT, and path tracing
|
||||||
|
|
||||||
|
## Legal
|
||||||
|
|
||||||
|
This is a fan project. It is not affiliated with Level-5 or Nintendo. Use original art and naming for any public release.
|
||||||
|
|
||||||
|
## Development Roadmap
|
||||||
|
|
||||||
|
See the project plan for phased delivery: foundation → vertical slice → multiplayer → dedicated servers → crossplay.
|
||||||
15
Source/VocationLife.Target.cs
Normal file
15
Source/VocationLife.Target.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class VocationLifeTarget : TargetRules
|
||||||
|
{
|
||||||
|
public VocationLifeTarget(TargetInfo Target) : base(Target)
|
||||||
|
{
|
||||||
|
Type = TargetType.Game;
|
||||||
|
DefaultBuildSettings = BuildSettingsVersion.V7;
|
||||||
|
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_8;
|
||||||
|
ExtraModuleNames.Add("VocationLife");
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Source/VocationLife/Private/CombatComponent.cpp
Normal file
46
Source/VocationLife/Private/CombatComponent.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "CombatComponent.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
|
||||||
|
UCombatComponent::UCombatComponent()
|
||||||
|
{
|
||||||
|
SetIsReplicatedByDefault(true);
|
||||||
|
PrimaryComponentTick.bCanEverTick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCombatComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
DOREPLIFETIME(UCombatComponent, Health);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCombatComponent::ApplyDamage(float DamageAmount, AActor* DamageCauser)
|
||||||
|
{
|
||||||
|
if (!GetOwner() || !GetOwner()->HasAuthority() || DamageAmount <= 0.f || !IsAlive())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Health = FMath::Clamp(Health - DamageAmount, 0.f, MaxHealth);
|
||||||
|
OnHealthChanged.Broadcast(Health, MaxHealth);
|
||||||
|
|
||||||
|
if (!IsAlive())
|
||||||
|
{
|
||||||
|
OnDeath.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCombatComponent::ServerApplyDamage_Implementation(float DamageAmount, AActor* DamageCauser)
|
||||||
|
{
|
||||||
|
ApplyDamage(DamageAmount, DamageCauser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCombatComponent::OnRep_Health()
|
||||||
|
{
|
||||||
|
OnHealthChanged.Broadcast(Health, MaxHealth);
|
||||||
|
if (!IsAlive())
|
||||||
|
{
|
||||||
|
OnDeath.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
124
Source/VocationLife/Private/CraftingComponent.cpp
Normal file
124
Source/VocationLife/Private/CraftingComponent.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "CraftingComponent.h"
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "VocationGameInstance.h"
|
||||||
|
#include "VocationPlayerState.h"
|
||||||
|
#include "GameFramework/Pawn.h"
|
||||||
|
#include "GameFramework/PlayerState.h"
|
||||||
|
|
||||||
|
UCraftingComponent::UCraftingComponent()
|
||||||
|
{
|
||||||
|
PrimaryComponentTick.bCanEverTick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UCraftingComponent::CanCraftRecipe(const FRecipeDefinition& Recipe) const
|
||||||
|
{
|
||||||
|
const UInventoryComponent* Inventory = GetInventory();
|
||||||
|
if (!Inventory)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const APawn* OwnerPawn = Cast<APawn>(GetOwner()))
|
||||||
|
{
|
||||||
|
if (const AVocationPlayerState* PS = OwnerPawn->GetPlayerState<AVocationPlayerState>())
|
||||||
|
{
|
||||||
|
if (Recipe.RequiredVocation != EVocationLifeClass::None &&
|
||||||
|
PS->GetActiveVocation() != Recipe.RequiredVocation)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const FRecipeIngredient& Ingredient : Recipe.Ingredients)
|
||||||
|
{
|
||||||
|
if (!Inventory->HasItem(Ingredient.ItemId, Ingredient.Quantity))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UCraftingComponent::CraftRecipe(const FRecipeDefinition& Recipe)
|
||||||
|
{
|
||||||
|
if (!GetOwner() || !GetOwner()->HasAuthority())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CanCraftRecipe(Recipe))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInventoryComponent* Inventory = GetInventory();
|
||||||
|
if (!Inventory)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const FRecipeIngredient& Ingredient : Recipe.Ingredients)
|
||||||
|
{
|
||||||
|
Inventory->RemoveItem(Ingredient.ItemId, Ingredient.Quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory->AddItem(Recipe.OutputItemId, Recipe.OutputQuantity);
|
||||||
|
OnCraftCompleted.Broadcast(Recipe.RecipeId, Recipe.OutputItemId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UCraftingComponent::ServerCraftRecipe_Implementation(FName RecipeId)
|
||||||
|
{
|
||||||
|
FRecipeDefinition Recipe;
|
||||||
|
if (FindRecipe(RecipeId, Recipe))
|
||||||
|
{
|
||||||
|
CraftRecipe(Recipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FRecipeDefinition> UCraftingComponent::GetAvailableRecipes(EVocationLifeClass Vocation) const
|
||||||
|
{
|
||||||
|
TArray<FRecipeDefinition> Result;
|
||||||
|
if (const UWorld* World = GetWorld())
|
||||||
|
{
|
||||||
|
if (const UVocationGameInstance* GI = World->GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
for (const FRecipeDefinition& Recipe : GI->GetRecipeDefinitions())
|
||||||
|
{
|
||||||
|
if (Recipe.RequiredVocation == EVocationLifeClass::None || Recipe.RequiredVocation == Vocation)
|
||||||
|
{
|
||||||
|
Result.Add(Recipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInventoryComponent* UCraftingComponent::GetInventory() const
|
||||||
|
{
|
||||||
|
return GetOwner() ? GetOwner()->FindComponentByClass<UInventoryComponent>() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UCraftingComponent::FindRecipe(FName RecipeId, FRecipeDefinition& OutRecipe) const
|
||||||
|
{
|
||||||
|
if (const UWorld* World = GetWorld())
|
||||||
|
{
|
||||||
|
if (const UVocationGameInstance* GI = World->GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
for (const FRecipeDefinition& Recipe : GI->GetRecipeDefinitions())
|
||||||
|
{
|
||||||
|
if (Recipe.RecipeId == RecipeId)
|
||||||
|
{
|
||||||
|
OutRecipe = Recipe;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
158
Source/VocationLife/Private/InventoryComponent.cpp
Normal file
158
Source/VocationLife/Private/InventoryComponent.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "VocationGameInstance.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
#include "Engine/World.h"
|
||||||
|
|
||||||
|
UInventoryComponent::UInventoryComponent()
|
||||||
|
{
|
||||||
|
SetIsReplicatedByDefault(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UInventoryComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
DOREPLIFETIME(UInventoryComponent, Slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UInventoryComponent::AddItem(FName ItemId, int32 Quantity)
|
||||||
|
{
|
||||||
|
if (!GetOwner() || !GetOwner()->HasAuthority() || ItemId.IsNone() || Quantity <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32 MaxStack = GetMaxStack(ItemId);
|
||||||
|
int32 Remaining = Quantity;
|
||||||
|
|
||||||
|
while (Remaining > 0)
|
||||||
|
{
|
||||||
|
const int32 SlotIndex = FindSlotIndex(ItemId);
|
||||||
|
if (SlotIndex != INDEX_NONE)
|
||||||
|
{
|
||||||
|
FInventorySlot& Slot = Slots[SlotIndex];
|
||||||
|
const int32 Space = MaxStack - Slot.Quantity;
|
||||||
|
const int32 ToAdd = FMath::Min(Space, Remaining);
|
||||||
|
Slot.Quantity += ToAdd;
|
||||||
|
Remaining -= ToAdd;
|
||||||
|
if (Remaining <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FInventorySlot NewSlot;
|
||||||
|
NewSlot.ItemId = ItemId;
|
||||||
|
NewSlot.Quantity = FMath::Min(Remaining, MaxStack);
|
||||||
|
Slots.Add(NewSlot);
|
||||||
|
Remaining -= NewSlot.Quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnInventoryChanged.Broadcast();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UInventoryComponent::RemoveItem(FName ItemId, int32 Quantity)
|
||||||
|
{
|
||||||
|
if (!GetOwner() || !GetOwner()->HasAuthority() || ItemId.IsNone() || Quantity <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasItem(ItemId, Quantity))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Remaining = Quantity;
|
||||||
|
for (int32 Index = Slots.Num() - 1; Index >= 0 && Remaining > 0; --Index)
|
||||||
|
{
|
||||||
|
if (Slots[Index].ItemId != ItemId)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32 ToRemove = FMath::Min(Slots[Index].Quantity, Remaining);
|
||||||
|
Slots[Index].Quantity -= ToRemove;
|
||||||
|
Remaining -= ToRemove;
|
||||||
|
|
||||||
|
if (Slots[Index].Quantity <= 0)
|
||||||
|
{
|
||||||
|
Slots.RemoveAt(Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnInventoryChanged.Broadcast();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UInventoryComponent::HasItem(FName ItemId, int32 Quantity) const
|
||||||
|
{
|
||||||
|
return GetItemCount(ItemId) >= Quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UInventoryComponent::GetItemCount(FName ItemId) const
|
||||||
|
{
|
||||||
|
int32 Total = 0;
|
||||||
|
for (const FInventorySlot& Slot : Slots)
|
||||||
|
{
|
||||||
|
if (Slot.ItemId == ItemId)
|
||||||
|
{
|
||||||
|
Total += Slot.Quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UInventoryComponent::SetSlots(const TArray<FInventorySlot>& NewSlots)
|
||||||
|
{
|
||||||
|
if (GetOwner() && GetOwner()->HasAuthority())
|
||||||
|
{
|
||||||
|
Slots = NewSlots;
|
||||||
|
OnRep_Slots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UInventoryComponent::ServerAddItem_Implementation(FName ItemId, int32 Quantity)
|
||||||
|
{
|
||||||
|
AddItem(ItemId, Quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UInventoryComponent::ServerRemoveItem_Implementation(FName ItemId, int32 Quantity)
|
||||||
|
{
|
||||||
|
RemoveItem(ItemId, Quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UInventoryComponent::OnRep_Slots()
|
||||||
|
{
|
||||||
|
OnInventoryChanged.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UInventoryComponent::FindSlotIndex(FName ItemId) const
|
||||||
|
{
|
||||||
|
for (int32 Index = 0; Index < Slots.Num(); ++Index)
|
||||||
|
{
|
||||||
|
if (Slots[Index].ItemId == ItemId && Slots[Index].Quantity < GetMaxStack(ItemId))
|
||||||
|
{
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INDEX_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UInventoryComponent::GetMaxStack(FName ItemId) const
|
||||||
|
{
|
||||||
|
if (const UWorld* World = GetWorld())
|
||||||
|
{
|
||||||
|
if (const UVocationGameInstance* GI = World->GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
FVocationItemDefinition Def;
|
||||||
|
if (GI->FindItemDefinition(ItemId, Def))
|
||||||
|
{
|
||||||
|
return Def.MaxStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 99;
|
||||||
|
}
|
||||||
78
Source/VocationLife/Private/MiningNode.cpp
Normal file
78
Source/VocationLife/Private/MiningNode.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "MiningNode.h"
|
||||||
|
#include "VocationCharacter.h"
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "Components/StaticMeshComponent.h"
|
||||||
|
#include "Engine/StaticMesh.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
#include "TimerManager.h"
|
||||||
|
#include "UObject/ConstructorHelpers.h"
|
||||||
|
|
||||||
|
AMiningNode::AMiningNode()
|
||||||
|
{
|
||||||
|
bReplicates = true;
|
||||||
|
|
||||||
|
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
|
||||||
|
RootComponent = MeshComponent;
|
||||||
|
|
||||||
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Engine/BasicShapes/Cube.Cube"));
|
||||||
|
if (CubeMesh.Succeeded())
|
||||||
|
{
|
||||||
|
MeshComponent->SetStaticMesh(CubeMesh.Object);
|
||||||
|
MeshComponent->SetWorldScale3D(FVector(1.5f, 1.5f, 1.5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AMiningNode::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
DOREPLIFETIME(AMiningNode, bIsDepleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
FText AMiningNode::GetInteractionPrompt_Implementation() const
|
||||||
|
{
|
||||||
|
return bIsDepleted
|
||||||
|
? FText::FromString(TEXT("Ore depleted"))
|
||||||
|
: FText::FromString(TEXT("Mine [E]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AMiningNode::CanInteract_Implementation(APawn* InteractingPawn) const
|
||||||
|
{
|
||||||
|
return !bIsDepleted && InteractingPawn != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AMiningNode::Interact_Implementation(APawn* InteractingPawn)
|
||||||
|
{
|
||||||
|
if (!HasAuthority() || bIsDepleted || !InteractingPawn)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AVocationCharacter* Character = Cast<AVocationCharacter>(InteractingPawn))
|
||||||
|
{
|
||||||
|
if (UInventoryComponent* Inventory = Character->GetInventoryComponent())
|
||||||
|
{
|
||||||
|
Inventory->AddItem(OreItemId, OreYield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bIsDepleted = true;
|
||||||
|
OnRep_Depleted();
|
||||||
|
GetWorldTimerManager().SetTimer(RespawnTimerHandle, this, &AMiningNode::HandleRespawn, RespawnTimeSeconds, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AMiningNode::OnRep_Depleted()
|
||||||
|
{
|
||||||
|
if (MeshComponent)
|
||||||
|
{
|
||||||
|
MeshComponent->SetVisibility(!bIsDepleted);
|
||||||
|
MeshComponent->SetCollisionEnabled(bIsDepleted ? ECollisionEnabled::NoCollision : ECollisionEnabled::QueryAndPhysics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AMiningNode::HandleRespawn()
|
||||||
|
{
|
||||||
|
bIsDepleted = false;
|
||||||
|
OnRep_Depleted();
|
||||||
|
}
|
||||||
339
Source/VocationLife/Private/VocationCharacter.cpp
Normal file
339
Source/VocationLife/Private/VocationCharacter.cpp
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationCharacter.h"
|
||||||
|
#include "VocationPlayerController.h"
|
||||||
|
#include "VocationPlayerState.h"
|
||||||
|
#include "VocationGameInstance.h"
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "CraftingComponent.h"
|
||||||
|
#include "CombatComponent.h"
|
||||||
|
#include "Interactable.h"
|
||||||
|
#include "VocationEnemy.h"
|
||||||
|
#include "Camera/CameraComponent.h"
|
||||||
|
#include "Components/CapsuleComponent.h"
|
||||||
|
#include "Components/SkeletalMeshComponent.h"
|
||||||
|
#include "GameFramework/CharacterMovementComponent.h"
|
||||||
|
#include "GameFramework/SpringArmComponent.h"
|
||||||
|
#include "EnhancedInputComponent.h"
|
||||||
|
#include "InputActionValue.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
#include "Engine/World.h"
|
||||||
|
#include "DrawDebugHelpers.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
|
||||||
|
AVocationCharacter::AVocationCharacter()
|
||||||
|
{
|
||||||
|
PrimaryActorTick.bCanEverTick = true;
|
||||||
|
bReplicates = true;
|
||||||
|
|
||||||
|
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.f);
|
||||||
|
|
||||||
|
FirstPersonCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
|
||||||
|
FirstPersonCamera->SetupAttachment(GetCapsuleComponent());
|
||||||
|
FirstPersonCamera->SetRelativeLocation(FVector(0.f, 0.f, 64.f));
|
||||||
|
FirstPersonCamera->bUsePawnControlRotation = true;
|
||||||
|
|
||||||
|
TopDownSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("TopDownSpringArm"));
|
||||||
|
TopDownSpringArm->SetupAttachment(RootComponent);
|
||||||
|
TopDownSpringArm->TargetArmLength = TopDownArmLength;
|
||||||
|
TopDownSpringArm->SetRelativeRotation(FRotator(TopDownPitch, 0.f, 0.f));
|
||||||
|
TopDownSpringArm->bDoCollisionTest = true;
|
||||||
|
TopDownSpringArm->bUsePawnControlRotation = false;
|
||||||
|
TopDownSpringArm->bInheritPitch = false;
|
||||||
|
TopDownSpringArm->bInheritRoll = false;
|
||||||
|
TopDownSpringArm->bInheritYaw = false;
|
||||||
|
TopDownSpringArm->SetActive(false);
|
||||||
|
|
||||||
|
TopDownCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
|
||||||
|
TopDownCamera->SetupAttachment(TopDownSpringArm, USpringArmComponent::SocketName);
|
||||||
|
TopDownCamera->bUsePawnControlRotation = false;
|
||||||
|
|
||||||
|
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(TEXT("InventoryComponent"));
|
||||||
|
CraftingComponent = CreateDefaultSubobject<UCraftingComponent>(TEXT("CraftingComponent"));
|
||||||
|
CombatComponent = CreateDefaultSubobject<UCombatComponent>(TEXT("CombatComponent"));
|
||||||
|
|
||||||
|
if (USkeletalMeshComponent* MeshComp = GetMesh())
|
||||||
|
{
|
||||||
|
MeshComp->SetOnlyOwnerSee(true);
|
||||||
|
MeshComp->SetupAttachment(FirstPersonCamera);
|
||||||
|
MeshComp->SetRelativeLocation(FVector(25.f, 0.f, -90.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UCharacterMovementComponent* Movement = GetCharacterMovement())
|
||||||
|
{
|
||||||
|
Movement->bOrientRotationToMovement = false;
|
||||||
|
Movement->RotationRate = FRotator(0.f, 540.f, 0.f);
|
||||||
|
Movement->JumpZVelocity = 500.f;
|
||||||
|
Movement->AirControl = 0.35f;
|
||||||
|
Movement->MaxWalkSpeed = 500.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bUseControllerRotationPitch = true;
|
||||||
|
bUseControllerRotationYaw = true;
|
||||||
|
bUseControllerRotationRoll = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
ApplyCameraModeVisuals();
|
||||||
|
|
||||||
|
if (HasAuthority())
|
||||||
|
{
|
||||||
|
if (UInventoryComponent* Inventory = GetInventoryComponent())
|
||||||
|
{
|
||||||
|
Inventory->AddItem(TEXT("Coal"), 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::Tick(float DeltaSeconds)
|
||||||
|
{
|
||||||
|
Super::Tick(DeltaSeconds);
|
||||||
|
UpdateCameraMode(DeltaSeconds);
|
||||||
|
UpdateInteractionPrompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||||
|
{
|
||||||
|
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
DOREPLIFETIME(AVocationCharacter, CurrentCameraMode);
|
||||||
|
DOREPLIFETIME(AVocationCharacter, TargetCameraMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::ToggleCameraMode()
|
||||||
|
{
|
||||||
|
const EVocationCameraMode NewMode = CurrentCameraMode == EVocationCameraMode::FirstPerson
|
||||||
|
? EVocationCameraMode::TopDown
|
||||||
|
: EVocationCameraMode::FirstPerson;
|
||||||
|
SetCameraMode(NewMode, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::SetCameraMode(EVocationCameraMode NewMode, bool bInstant)
|
||||||
|
{
|
||||||
|
if (NewMode == TargetCameraMode && !bInstant)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasAuthority())
|
||||||
|
{
|
||||||
|
ServerSetCameraMode(NewMode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetCameraMode = NewMode;
|
||||||
|
if (bInstant)
|
||||||
|
{
|
||||||
|
CurrentCameraMode = NewMode;
|
||||||
|
CameraBlendAlpha = 1.f;
|
||||||
|
bIsBlendingCamera = false;
|
||||||
|
ApplyCameraModeVisuals();
|
||||||
|
OnCameraModeChanged.Broadcast(CurrentCameraMode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bIsBlendingCamera = true;
|
||||||
|
CameraBlendAlpha = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AVocationPlayerController* PC = Cast<AVocationPlayerController>(GetController()))
|
||||||
|
{
|
||||||
|
PC->ApplyInputMappingForCameraMode(NewMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleMove(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
const FVector2D MovementVector = Value.Get<FVector2D>();
|
||||||
|
if (MovementVector.IsNearlyZero())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentCameraMode == EVocationCameraMode::TopDown)
|
||||||
|
{
|
||||||
|
const FRotator YawRotation(0.f, GetControlRotation().Yaw, 0.f);
|
||||||
|
const FVector Forward = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
|
||||||
|
const FVector Right = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
|
||||||
|
AddMovementInput(Forward, MovementVector.Y);
|
||||||
|
AddMovementInput(Right, MovementVector.X);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddMovementInput(GetActorForwardVector(), MovementVector.Y);
|
||||||
|
AddMovementInput(GetActorRightVector(), MovementVector.X);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleLook(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
if (CurrentCameraMode != EVocationCameraMode::FirstPerson)
|
||||||
|
{
|
||||||
|
const FVector2D LookVector = Value.Get<FVector2D>();
|
||||||
|
AddControllerYawInput(LookVector.X);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FVector2D LookVector = Value.Get<FVector2D>();
|
||||||
|
AddControllerYawInput(LookVector.X);
|
||||||
|
AddControllerPitchInput(LookVector.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleJumpStarted()
|
||||||
|
{
|
||||||
|
Jump();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleInteract()
|
||||||
|
{
|
||||||
|
if (AActor* Target = FindInteractableTarget())
|
||||||
|
{
|
||||||
|
if (Target->GetClass()->ImplementsInterface(UInteractable::StaticClass()))
|
||||||
|
{
|
||||||
|
IInteractable::Execute_Interact(Target, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (UCraftingComponent* Crafting = GetCraftingComponent())
|
||||||
|
{
|
||||||
|
if (const AVocationPlayerState* PS = GetPlayerState<AVocationPlayerState>())
|
||||||
|
{
|
||||||
|
const TArray<FRecipeDefinition> Recipes = Crafting->GetAvailableRecipes(PS->GetActiveVocation());
|
||||||
|
for (const FRecipeDefinition& Recipe : Recipes)
|
||||||
|
{
|
||||||
|
if (Crafting->CanCraftRecipe(Recipe))
|
||||||
|
{
|
||||||
|
Crafting->CraftRecipe(Recipe);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleAttack()
|
||||||
|
{
|
||||||
|
if (!CombatComponent)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FVector Start = GetActorLocation() + FVector(0.f, 0.f, 50.f);
|
||||||
|
const FVector End = Start + GetActorForwardVector() * CombatComponent->AttackRange;
|
||||||
|
|
||||||
|
FCollisionQueryParams Params(SCENE_QUERY_STAT(VocationAttack), false, this);
|
||||||
|
FHitResult Hit;
|
||||||
|
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Pawn, Params))
|
||||||
|
{
|
||||||
|
if (AVocationEnemy* Enemy = Cast<AVocationEnemy>(Hit.GetActor()))
|
||||||
|
{
|
||||||
|
if (UCombatComponent* EnemyCombat = Enemy->GetCombatComponent())
|
||||||
|
{
|
||||||
|
EnemyCombat->ServerApplyDamage(CombatComponent->AttackDamage, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleToggleCamera()
|
||||||
|
{
|
||||||
|
ToggleCameraMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::HandleInventory()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetWorld()->GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SaveGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AActor* AVocationCharacter::FindInteractableTarget() const
|
||||||
|
{
|
||||||
|
const FVector Start = FirstPersonCamera ? FirstPersonCamera->GetComponentLocation() : GetActorLocation();
|
||||||
|
const FVector Forward = GetControlRotation().Vector();
|
||||||
|
const FVector End = Start + Forward * InteractionRange;
|
||||||
|
|
||||||
|
FCollisionQueryParams Params(SCENE_QUERY_STAT(VocationInteract), false, this);
|
||||||
|
FHitResult Hit;
|
||||||
|
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params))
|
||||||
|
{
|
||||||
|
if (Hit.GetActor() && Hit.GetActor()->GetClass()->ImplementsInterface(UInteractable::StaticClass()))
|
||||||
|
{
|
||||||
|
if (IInteractable::Execute_CanInteract(Hit.GetActor(), const_cast<AVocationCharacter*>(this)))
|
||||||
|
{
|
||||||
|
return Hit.GetActor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::UpdateCameraMode(float DeltaSeconds)
|
||||||
|
{
|
||||||
|
if (!bIsBlendingCamera)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraBlendAlpha = FMath::Clamp(CameraBlendAlpha + (DeltaSeconds / FMath::Max(CameraBlendTime, 0.01f)), 0.f, 1.f);
|
||||||
|
if (CameraBlendAlpha >= 1.f)
|
||||||
|
{
|
||||||
|
CurrentCameraMode = TargetCameraMode;
|
||||||
|
bIsBlendingCamera = false;
|
||||||
|
ApplyCameraModeVisuals();
|
||||||
|
OnCameraModeChanged.Broadcast(CurrentCameraMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::ApplyCameraModeVisuals()
|
||||||
|
{
|
||||||
|
const bool bFirstPerson = CurrentCameraMode == EVocationCameraMode::FirstPerson;
|
||||||
|
|
||||||
|
if (APlayerController* PC = Cast<APlayerController>(GetController()))
|
||||||
|
{
|
||||||
|
PC->SetViewTargetWithBlend(this, bIsBlendingCamera ? CameraBlendTime : 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
FirstPersonCamera->SetActive(bFirstPerson);
|
||||||
|
TopDownSpringArm->SetActive(!bFirstPerson);
|
||||||
|
TopDownCamera->SetActive(!bFirstPerson);
|
||||||
|
|
||||||
|
bUseControllerRotationPitch = bFirstPerson;
|
||||||
|
if (UCharacterMovementComponent* Movement = GetCharacterMovement())
|
||||||
|
{
|
||||||
|
Movement->bOrientRotationToMovement = !bFirstPerson;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::UpdateInteractionPrompt()
|
||||||
|
{
|
||||||
|
if (AVocationPlayerController* PC = Cast<AVocationPlayerController>(GetController()))
|
||||||
|
{
|
||||||
|
if (AActor* Target = FindInteractableTarget())
|
||||||
|
{
|
||||||
|
const FText Prompt = IInteractable::Execute_GetInteractionPrompt(Target);
|
||||||
|
PC->ShowInteractionPrompt(Prompt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PC->ClearInteractionPrompt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::OnRep_CameraMode()
|
||||||
|
{
|
||||||
|
ApplyCameraModeVisuals();
|
||||||
|
OnCameraModeChanged.Broadcast(CurrentCameraMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationCharacter::ServerSetCameraMode_Implementation(EVocationCameraMode NewMode)
|
||||||
|
{
|
||||||
|
SetCameraMode(NewMode, false);
|
||||||
|
}
|
||||||
36
Source/VocationLife/Private/VocationEOSSubsystem.cpp
Normal file
36
Source/VocationLife/Private/VocationEOSSubsystem.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationEOSSubsystem.h"
|
||||||
|
#include "Misc/ConfigCacheIni.h"
|
||||||
|
|
||||||
|
void UVocationEOSSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
|
{
|
||||||
|
Super::Initialize(Collection);
|
||||||
|
|
||||||
|
GConfig->GetBool(TEXT("/Script/VocationLife.VocationEOS"), TEXT("bEOSEnabled"), bEOSEnabled, GGameIni);
|
||||||
|
GConfig->GetString(TEXT("/Script/VocationLife.VocationEOS"), TEXT("ProductId"), ProductId, GGameIni);
|
||||||
|
GConfig->GetString(TEXT("/Script/VocationLife.VocationEOS"), TEXT("SandboxId"), SandboxId, GGameIni);
|
||||||
|
GConfig->GetString(TEXT("/Script/VocationLife.VocationEOS"), TEXT("DeploymentId"), DeploymentId, GGameIni);
|
||||||
|
|
||||||
|
if (!bEOSEnabled)
|
||||||
|
{
|
||||||
|
SubsystemState = EEOSSubsystemState::Disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationEOSSubsystem::InitializeEOS()
|
||||||
|
{
|
||||||
|
if (!bEOSEnabled)
|
||||||
|
{
|
||||||
|
SubsystemState = EEOSSubsystemState::Disabled;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProductId.IsEmpty() || SandboxId.IsEmpty() || DeploymentId.IsEmpty())
|
||||||
|
{
|
||||||
|
SubsystemState = EEOSSubsystemState::Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubsystemState = EEOSSubsystemState::Ready;
|
||||||
|
}
|
||||||
24
Source/VocationLife/Private/VocationEnemy.cpp
Normal file
24
Source/VocationLife/Private/VocationEnemy.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationEnemy.h"
|
||||||
|
#include "CombatComponent.h"
|
||||||
|
|
||||||
|
AVocationEnemy::AVocationEnemy()
|
||||||
|
{
|
||||||
|
CombatComponent = CreateDefaultSubobject<UCombatComponent>(TEXT("CombatComponent"));
|
||||||
|
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationEnemy::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
if (CombatComponent)
|
||||||
|
{
|
||||||
|
CombatComponent->OnDeath.AddDynamic(this, &AVocationEnemy::HandleDeath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationEnemy::HandleDeath()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
177
Source/VocationLife/Private/VocationGameInstance.cpp
Normal file
177
Source/VocationLife/Private/VocationGameInstance.cpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationGameInstance.h"
|
||||||
|
#include "VocationSaveGame.h"
|
||||||
|
#include "VocationGraphicsLibrary.h"
|
||||||
|
#include "VocationCharacter.h"
|
||||||
|
#include "VocationPlayerState.h"
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "CombatComponent.h"
|
||||||
|
#include "GameFramework/PlayerState.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
|
||||||
|
UVocationGameInstance::UVocationGameInstance()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationGameInstance::Init()
|
||||||
|
{
|
||||||
|
Super::Init();
|
||||||
|
InitializeDefaultData();
|
||||||
|
OnDataReady.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationGameInstance::InitializeDefaultData()
|
||||||
|
{
|
||||||
|
ItemDefinitions.Empty();
|
||||||
|
RecipeDefinitions.Empty();
|
||||||
|
|
||||||
|
auto AddItem = [this](FName Id, const FString& Name, int32 MaxStack, bool bMaterial = true)
|
||||||
|
{
|
||||||
|
FVocationItemDefinition Def;
|
||||||
|
Def.ItemId = Id;
|
||||||
|
Def.DisplayName = FText::FromString(Name);
|
||||||
|
Def.MaxStack = MaxStack;
|
||||||
|
Def.bIsCraftingMaterial = bMaterial;
|
||||||
|
ItemDefinitions.Add(Id, Def);
|
||||||
|
};
|
||||||
|
|
||||||
|
AddItem(TEXT("IronOre"), TEXT("Iron Ore"), 99);
|
||||||
|
AddItem(TEXT("Coal"), TEXT("Coal"), 99);
|
||||||
|
AddItem(TEXT("IronIngot"), TEXT("Iron Ingot"), 50, false);
|
||||||
|
AddItem(TEXT("IronSword"), TEXT("Iron Sword"), 1, false);
|
||||||
|
|
||||||
|
FRecipeDefinition SmeltIron;
|
||||||
|
SmeltIron.RecipeId = TEXT("SmeltIron");
|
||||||
|
SmeltIron.DisplayName = FText::FromString(TEXT("Smelt Iron Ingot"));
|
||||||
|
SmeltIron.RequiredVocation = EVocationLifeClass::Blacksmith;
|
||||||
|
SmeltIron.Ingredients = {
|
||||||
|
{TEXT("IronOre"), 2},
|
||||||
|
{TEXT("Coal"), 1}
|
||||||
|
};
|
||||||
|
SmeltIron.OutputItemId = TEXT("IronIngot");
|
||||||
|
SmeltIron.OutputQuantity = 1;
|
||||||
|
RecipeDefinitions.Add(SmeltIron);
|
||||||
|
|
||||||
|
FRecipeDefinition ForgeSword;
|
||||||
|
ForgeSword.RecipeId = TEXT("ForgeIronSword");
|
||||||
|
ForgeSword.DisplayName = FText::FromString(TEXT("Forge Iron Sword"));
|
||||||
|
ForgeSword.RequiredVocation = EVocationLifeClass::Blacksmith;
|
||||||
|
ForgeSword.Ingredients = {
|
||||||
|
{TEXT("IronIngot"), 2},
|
||||||
|
{TEXT("Coal"), 1}
|
||||||
|
};
|
||||||
|
ForgeSword.OutputItemId = TEXT("IronSword");
|
||||||
|
ForgeSword.OutputQuantity = 1;
|
||||||
|
RecipeDefinitions.Add(ForgeSword);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UVocationGameInstance::FindItemDefinition(FName ItemId, FVocationItemDefinition& OutDefinition) const
|
||||||
|
{
|
||||||
|
if (const FVocationItemDefinition* Found = ItemDefinitions.Find(ItemId))
|
||||||
|
{
|
||||||
|
OutDefinition = *Found;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UVocationGameInstance::SaveGame(const FString& SlotName)
|
||||||
|
{
|
||||||
|
UVocationSaveGame* SaveObject = Cast<UVocationSaveGame>(
|
||||||
|
UGameplayStatics::CreateSaveGameObject(UVocationSaveGame::StaticClass()));
|
||||||
|
if (!SaveObject)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0))
|
||||||
|
{
|
||||||
|
SaveObject->PlayerLocation = Pawn->GetActorLocation();
|
||||||
|
SaveObject->PlayerRotation = Pawn->GetActorRotation();
|
||||||
|
|
||||||
|
if (const AVocationCharacter* Character = Cast<AVocationCharacter>(Pawn))
|
||||||
|
{
|
||||||
|
if (UCombatComponent* Combat = Character->GetCombatComponent())
|
||||||
|
{
|
||||||
|
SaveObject->PlayerHealth = Combat->GetHealth();
|
||||||
|
}
|
||||||
|
if (UInventoryComponent* Inventory = Character->GetInventoryComponent())
|
||||||
|
{
|
||||||
|
SaveObject->Inventory = Inventory->GetSlots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (APlayerState* PlayerState = UGameplayStatics::GetPlayerState(this, 0))
|
||||||
|
{
|
||||||
|
if (const AVocationPlayerState* PS = Cast<AVocationPlayerState>(PlayerState))
|
||||||
|
{
|
||||||
|
SaveObject->ActiveVocation = PS->GetActiveVocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveObject->GraphicsPreset = CurrentGraphicsPreset;
|
||||||
|
SaveObject->bRayTracingEnabled = bRayTracingEnabled;
|
||||||
|
|
||||||
|
const bool bSuccess = UGameplayStatics::SaveGameToSlot(SaveObject, SlotName, 0);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
CurrentSave = SaveObject;
|
||||||
|
}
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UVocationGameInstance::LoadGame(const FString& SlotName)
|
||||||
|
{
|
||||||
|
if (!UGameplayStatics::DoesSaveGameExist(SlotName, 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USaveGame* Loaded = UGameplayStatics::LoadGameFromSlot(SlotName, 0);
|
||||||
|
UVocationSaveGame* SaveObject = Cast<UVocationSaveGame>(Loaded);
|
||||||
|
if (!SaveObject)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentSave = SaveObject;
|
||||||
|
SetGraphicsPreset(SaveObject->GraphicsPreset, SaveObject->bRayTracingEnabled);
|
||||||
|
|
||||||
|
if (APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0))
|
||||||
|
{
|
||||||
|
Pawn->SetActorLocation(SaveObject->PlayerLocation);
|
||||||
|
Pawn->SetActorRotation(SaveObject->PlayerRotation);
|
||||||
|
|
||||||
|
if (AVocationCharacter* Character = Cast<AVocationCharacter>(Pawn))
|
||||||
|
{
|
||||||
|
if (UInventoryComponent* Inventory = Character->GetInventoryComponent())
|
||||||
|
{
|
||||||
|
Inventory->SetSlots(SaveObject->Inventory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (APlayerState* PlayerState = UGameplayStatics::GetPlayerState(this, 0))
|
||||||
|
{
|
||||||
|
if (AVocationPlayerState* PS = Cast<AVocationPlayerState>(PlayerState))
|
||||||
|
{
|
||||||
|
PS->SetActiveVocation(SaveObject->ActiveVocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UVocationGameInstance::HasSaveGame(const FString& SlotName) const
|
||||||
|
{
|
||||||
|
return UGameplayStatics::DoesSaveGameExist(SlotName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationGameInstance::SetGraphicsPreset(EVocationGraphicsPreset Preset, bool bEnableRayTracing)
|
||||||
|
{
|
||||||
|
CurrentGraphicsPreset = Preset;
|
||||||
|
bRayTracingEnabled = bEnableRayTracing;
|
||||||
|
UVocationGraphicsLibrary::ApplyGraphicsPreset(Preset, bEnableRayTracing);
|
||||||
|
}
|
||||||
64
Source/VocationLife/Private/VocationGameMode.cpp
Normal file
64
Source/VocationLife/Private/VocationGameMode.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationGameMode.h"
|
||||||
|
#include "VocationCharacter.h"
|
||||||
|
#include "VocationPlayerController.h"
|
||||||
|
#include "VocationPlayerState.h"
|
||||||
|
#include "VocationHUD.h"
|
||||||
|
#include "VocationTestWorldBuilder.h"
|
||||||
|
#include "Engine/World.h"
|
||||||
|
#include "GameFramework/PlayerController.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
#include "Misc/ConfigCacheIni.h"
|
||||||
|
#include "Misc/Paths.h"
|
||||||
|
|
||||||
|
AVocationGameMode::AVocationGameMode()
|
||||||
|
{
|
||||||
|
DefaultPawnClass = AVocationCharacter::StaticClass();
|
||||||
|
PlayerControllerClass = AVocationPlayerController::StaticClass();
|
||||||
|
PlayerStateClass = AVocationPlayerState::StaticClass();
|
||||||
|
HUDClass = AVocationHUD::StaticClass();
|
||||||
|
bUseSeamlessTravel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
|
||||||
|
{
|
||||||
|
Super::InitGame(MapName, Options, ErrorMessage);
|
||||||
|
|
||||||
|
int32 ConfigMaxPlayers = MaxCoopPlayers;
|
||||||
|
const FString ServerConfigPath = FPaths::ProjectConfigDir() / TEXT("ServerConfig.ini");
|
||||||
|
GConfig->GetInt(TEXT("/Script/VocationLife.VocationServerSettings"), TEXT("MaxPlayers"), ConfigMaxPlayers, ServerConfigPath);
|
||||||
|
MaxCoopPlayers = ConfigMaxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationGameMode::PostLogin(APlayerController* NewPlayer)
|
||||||
|
{
|
||||||
|
Super::PostLogin(NewPlayer);
|
||||||
|
|
||||||
|
if (HasAuthority() && GetWorld())
|
||||||
|
{
|
||||||
|
TArray<AActor*> ExistingBuilders;
|
||||||
|
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AVocationTestWorldBuilder::StaticClass(), ExistingBuilders);
|
||||||
|
if (ExistingBuilders.Num() == 0)
|
||||||
|
{
|
||||||
|
GetWorld()->SpawnActor<AVocationTestWorldBuilder>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FString AVocationGameMode::InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId,
|
||||||
|
const FString& Options, const FString& Portal)
|
||||||
|
{
|
||||||
|
FString ErrorMessage = Super::InitNewPlayer(NewPlayerController, UniqueId, Options, Portal);
|
||||||
|
if (!ErrorMessage.IsEmpty())
|
||||||
|
{
|
||||||
|
return ErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetNumPlayers() >= MaxCoopPlayers)
|
||||||
|
{
|
||||||
|
return FString::Printf(TEXT("Server is full (%d/%d players)."), MaxCoopPlayers, MaxCoopPlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorMessage;
|
||||||
|
}
|
||||||
70
Source/VocationLife/Private/VocationGraphicsLibrary.cpp
Normal file
70
Source/VocationLife/Private/VocationGraphicsLibrary.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationGraphicsLibrary.h"
|
||||||
|
#include "Scalability.h"
|
||||||
|
#include "Engine/Engine.h"
|
||||||
|
#include "GameFramework/GameUserSettings.h"
|
||||||
|
|
||||||
|
void UVocationGraphicsLibrary::ApplyGraphicsPreset(EVocationGraphicsPreset Preset, bool bEnableRayTracing)
|
||||||
|
{
|
||||||
|
UGameUserSettings* Settings = GEngine ? GEngine->GetGameUserSettings() : nullptr;
|
||||||
|
if (!Settings)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 QualityLevel = 2;
|
||||||
|
switch (Preset)
|
||||||
|
{
|
||||||
|
case EVocationGraphicsPreset::Low:
|
||||||
|
QualityLevel = 0;
|
||||||
|
break;
|
||||||
|
case EVocationGraphicsPreset::Medium:
|
||||||
|
QualityLevel = 1;
|
||||||
|
break;
|
||||||
|
case EVocationGraphicsPreset::High:
|
||||||
|
QualityLevel = 2;
|
||||||
|
break;
|
||||||
|
case EVocationGraphicsPreset::Ultra:
|
||||||
|
case EVocationGraphicsPreset::RayTracing:
|
||||||
|
QualityLevel = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalability::FQualityLevels QualityLevels;
|
||||||
|
QualityLevels.SetFromSingleQualityLevel(QualityLevel);
|
||||||
|
Scalability::SetQualityLevels(QualityLevels);
|
||||||
|
Settings->SetOverallScalabilityLevel(QualityLevel);
|
||||||
|
|
||||||
|
const bool bUseRayTracing = bEnableRayTracing || Preset == EVocationGraphicsPreset::RayTracing;
|
||||||
|
if (GEngine)
|
||||||
|
{
|
||||||
|
GEngine->Exec(nullptr, *FString::Printf(TEXT("r.RayTracing %d"), bUseRayTracing ? 1 : 0));
|
||||||
|
GEngine->Exec(nullptr, *FString::Printf(TEXT("r.Lumen.HardwareRayTracing %d"), bUseRayTracing ? 1 : 0));
|
||||||
|
GEngine->Exec(nullptr, *FString::Printf(TEXT("r.PathTracing %d"), bUseRayTracing ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings->ApplySettings(false);
|
||||||
|
Settings->SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
FText UVocationGraphicsLibrary::GetGraphicsPresetDisplayName(EVocationGraphicsPreset Preset)
|
||||||
|
{
|
||||||
|
switch (Preset)
|
||||||
|
{
|
||||||
|
case EVocationGraphicsPreset::Low:
|
||||||
|
return FText::FromString(TEXT("Low"));
|
||||||
|
case EVocationGraphicsPreset::Medium:
|
||||||
|
return FText::FromString(TEXT("Medium"));
|
||||||
|
case EVocationGraphicsPreset::High:
|
||||||
|
return FText::FromString(TEXT("High"));
|
||||||
|
case EVocationGraphicsPreset::Ultra:
|
||||||
|
return FText::FromString(TEXT("Ultra"));
|
||||||
|
case EVocationGraphicsPreset::RayTracing:
|
||||||
|
return FText::FromString(TEXT("Ray Tracing"));
|
||||||
|
default:
|
||||||
|
return FText::FromString(TEXT("Custom"));
|
||||||
|
}
|
||||||
|
}
|
||||||
83
Source/VocationLife/Private/VocationHUD.cpp
Normal file
83
Source/VocationLife/Private/VocationHUD.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationHUD.h"
|
||||||
|
#include "VocationGraphicsLibrary.h"
|
||||||
|
#include "Engine/Canvas.h"
|
||||||
|
#include "Engine/Engine.h"
|
||||||
|
|
||||||
|
void AVocationHUD::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::SetInteractionPrompt(const FText& Prompt)
|
||||||
|
{
|
||||||
|
CurrentInteractionPrompt = Prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::ClearInteractionPrompt()
|
||||||
|
{
|
||||||
|
CurrentInteractionPrompt = FText::GetEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::SetPauseVisible(bool bVisible)
|
||||||
|
{
|
||||||
|
bShowPauseMenu = bVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::ShowDebugStatus(const FString& Status)
|
||||||
|
{
|
||||||
|
DebugStatusLine = Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::ApplyGraphicsPresetFromHUD(EVocationGraphicsPreset Preset, bool bRayTracing)
|
||||||
|
{
|
||||||
|
UVocationGraphicsLibrary::ApplyGraphicsPreset(Preset, bRayTracing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::DrawHUD()
|
||||||
|
{
|
||||||
|
Super::DrawHUD();
|
||||||
|
DrawMainHUD();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationHUD::DrawMainHUD()
|
||||||
|
{
|
||||||
|
if (!Canvas)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float Scale = Canvas->ClipX / 1920.f;
|
||||||
|
const FLinearColor TextColor(1.f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
|
if (!CurrentInteractionPrompt.IsEmpty())
|
||||||
|
{
|
||||||
|
const FString PromptString = CurrentInteractionPrompt.ToString();
|
||||||
|
float TextWidth = 0.f;
|
||||||
|
float TextHeight = 0.f;
|
||||||
|
Canvas->StrLen(GEngine->GetMediumFont(), PromptString, TextWidth, TextHeight);
|
||||||
|
Canvas->DrawColor = FColor::White;
|
||||||
|
Canvas->DrawText(GEngine->GetMediumFont(), PromptString,
|
||||||
|
(Canvas->ClipX - TextWidth) * 0.5f, Canvas->ClipY * 0.85f, 1.2f * Scale, 1.2f * Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DebugStatusLine.IsEmpty())
|
||||||
|
{
|
||||||
|
Canvas->DrawColor = FColor::Cyan;
|
||||||
|
Canvas->DrawText(GEngine->GetSmallFont(), DebugStatusLine, 40.f * Scale, 40.f * Scale, Scale, Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bShowPauseMenu)
|
||||||
|
{
|
||||||
|
const FString PauseText = TEXT("PAUSED\nF1 Low | F2 Medium | F3 High | F4 Ultra | F5 Ray Tracing\nH Host | J Join | S Save");
|
||||||
|
Canvas->DrawColor = FColor::Yellow;
|
||||||
|
Canvas->DrawText(GEngine->GetMediumFont(), PauseText, Canvas->ClipX * 0.35f, Canvas->ClipY * 0.35f, Scale, Scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const FString Controls = TEXT("WASD Move | Mouse Look | V Camera | E Interact/Craft | LMB Attack | I Save | Esc Pause");
|
||||||
|
Canvas->DrawColor = FColor(200, 200, 200);
|
||||||
|
Canvas->DrawText(GEngine->GetSmallFont(), Controls, 40.f * Scale, Canvas->ClipY - 60.f * Scale, Scale, Scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
281
Source/VocationLife/Private/VocationPlayerController.cpp
Normal file
281
Source/VocationLife/Private/VocationPlayerController.cpp
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationPlayerController.h"
|
||||||
|
#include "VocationCharacter.h"
|
||||||
|
#include "VocationHUD.h"
|
||||||
|
#include "VocationSessionSubsystem.h"
|
||||||
|
#include "VocationGameInstance.h"
|
||||||
|
#include "EnhancedInputComponent.h"
|
||||||
|
#include "EnhancedInputSubsystems.h"
|
||||||
|
#include "InputAction.h"
|
||||||
|
#include "InputMappingContext.h"
|
||||||
|
#include "InputCoreTypes.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
|
||||||
|
AVocationPlayerController::AVocationPlayerController()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
CreateRuntimeInputAssets();
|
||||||
|
|
||||||
|
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||||
|
{
|
||||||
|
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||||
|
LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
|
||||||
|
{
|
||||||
|
Subsystem->AddMappingContext(SharedMappingContext, SharedMappingPriority);
|
||||||
|
Subsystem->AddMappingContext(FirstPersonMappingContext, ModeMappingPriority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AVocationHUD* HUD = Cast<AVocationHUD>(GetHUD()))
|
||||||
|
{
|
||||||
|
VocationHUD = HUD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(GI->GetGraphicsPreset(), GI->IsRayTracingEnabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::SetupInputComponent()
|
||||||
|
{
|
||||||
|
Super::SetupInputComponent();
|
||||||
|
|
||||||
|
if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(InputComponent))
|
||||||
|
{
|
||||||
|
if (AVocationCharacter* Character = Cast<AVocationCharacter>(GetPawn()))
|
||||||
|
{
|
||||||
|
EnhancedInput->BindAction(MoveAction, ETriggerEvent::Triggered, Character, &AVocationCharacter::HandleMove);
|
||||||
|
EnhancedInput->BindAction(LookAction, ETriggerEvent::Triggered, Character, &AVocationCharacter::HandleLook);
|
||||||
|
EnhancedInput->BindAction(JumpAction, ETriggerEvent::Started, Character, &AVocationCharacter::HandleJumpStarted);
|
||||||
|
EnhancedInput->BindAction(InteractAction, ETriggerEvent::Started, Character, &AVocationCharacter::HandleInteract);
|
||||||
|
EnhancedInput->BindAction(AttackAction, ETriggerEvent::Started, Character, &AVocationCharacter::HandleAttack);
|
||||||
|
EnhancedInput->BindAction(ToggleCameraAction, ETriggerEvent::Started, Character, &AVocationCharacter::HandleToggleCamera);
|
||||||
|
EnhancedInput->BindAction(InventoryAction, ETriggerEvent::Started, Character, &AVocationCharacter::HandleInventory);
|
||||||
|
EnhancedInput->BindAction(PauseAction, ETriggerEvent::Started, this, &AVocationPlayerController::TogglePauseMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputComponent->BindKey(EKeys::F1, IE_Pressed, this, &AVocationPlayerController::ApplyLowGraphics).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::F2, IE_Pressed, this, &AVocationPlayerController::ApplyMediumGraphics).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::F3, IE_Pressed, this, &AVocationPlayerController::ApplyHighGraphics).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::F4, IE_Pressed, this, &AVocationPlayerController::ApplyUltraGraphics).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::F5, IE_Pressed, this, &AVocationPlayerController::ApplyRayTracingGraphics).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::H, IE_Pressed, this, &AVocationPlayerController::HostCoopGame).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::J, IE_Pressed, this, &AVocationPlayerController::JoinFirstFoundSession).bConsumeInput = false;
|
||||||
|
InputComponent->BindKey(EKeys::S, IE_Pressed, this, &AVocationPlayerController::QuickSave).bConsumeInput = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::OnPossess(APawn* InPawn)
|
||||||
|
{
|
||||||
|
Super::OnPossess(InPawn);
|
||||||
|
SetupInputComponent();
|
||||||
|
|
||||||
|
if (AVocationCharacter* Character = Cast<AVocationCharacter>(InPawn))
|
||||||
|
{
|
||||||
|
ApplyInputMappingForCameraMode(Character->GetCameraMode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::TogglePauseMenu()
|
||||||
|
{
|
||||||
|
bPauseMenuOpen = !bPauseMenuOpen;
|
||||||
|
SetPause(bPauseMenuOpen);
|
||||||
|
if (VocationHUD)
|
||||||
|
{
|
||||||
|
VocationHUD->SetPauseVisible(bPauseMenuOpen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ShowInteractionPrompt(const FText& Prompt)
|
||||||
|
{
|
||||||
|
if (VocationHUD)
|
||||||
|
{
|
||||||
|
VocationHUD->SetInteractionPrompt(Prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ClearInteractionPrompt()
|
||||||
|
{
|
||||||
|
if (VocationHUD)
|
||||||
|
{
|
||||||
|
VocationHUD->ClearInteractionPrompt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::HostCoopGame()
|
||||||
|
{
|
||||||
|
if (UVocationSessionSubsystem* Sessions = GetGameInstance()->GetSubsystem<UVocationSessionSubsystem>())
|
||||||
|
{
|
||||||
|
Sessions->HostSession(4, TEXT("VocationLife"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::FindCoopGames()
|
||||||
|
{
|
||||||
|
if (UVocationSessionSubsystem* Sessions = GetGameInstance()->GetSubsystem<UVocationSessionSubsystem>())
|
||||||
|
{
|
||||||
|
Sessions->FindSessions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::JoinCoopGame(int32 SessionIndex)
|
||||||
|
{
|
||||||
|
if (UVocationSessionSubsystem* Sessions = GetGameInstance()->GetSubsystem<UVocationSessionSubsystem>())
|
||||||
|
{
|
||||||
|
Sessions->JoinSessionByIndex(SessionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyInputMappingForCameraMode(EVocationCameraMode CameraMode)
|
||||||
|
{
|
||||||
|
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||||
|
{
|
||||||
|
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||||
|
LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
|
||||||
|
{
|
||||||
|
Subsystem->RemoveMappingContext(FirstPersonMappingContext);
|
||||||
|
Subsystem->RemoveMappingContext(TopDownMappingContext);
|
||||||
|
|
||||||
|
if (CameraMode == EVocationCameraMode::FirstPerson)
|
||||||
|
{
|
||||||
|
Subsystem->AddMappingContext(FirstPersonMappingContext, ModeMappingPriority);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Subsystem->AddMappingContext(TopDownMappingContext, ModeMappingPriority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::CreateRuntimeInputAssets()
|
||||||
|
{
|
||||||
|
MoveAction = NewObject<UInputAction>(this, TEXT("IA_Move"));
|
||||||
|
MoveAction->ValueType = EInputActionValueType::Axis2D;
|
||||||
|
|
||||||
|
LookAction = NewObject<UInputAction>(this, TEXT("IA_Look"));
|
||||||
|
LookAction->ValueType = EInputActionValueType::Axis2D;
|
||||||
|
|
||||||
|
JumpAction = NewObject<UInputAction>(this, TEXT("IA_Jump"));
|
||||||
|
InteractAction = NewObject<UInputAction>(this, TEXT("IA_Interact"));
|
||||||
|
AttackAction = NewObject<UInputAction>(this, TEXT("IA_Attack"));
|
||||||
|
ToggleCameraAction = NewObject<UInputAction>(this, TEXT("IA_ToggleCamera"));
|
||||||
|
InventoryAction = NewObject<UInputAction>(this, TEXT("IA_Inventory"));
|
||||||
|
PauseAction = NewObject<UInputAction>(this, TEXT("IA_Pause"));
|
||||||
|
|
||||||
|
SharedMappingContext = NewObject<UInputMappingContext>(this, TEXT("IMC_Vocation_Shared"));
|
||||||
|
SharedMappingContext->MapKey(JumpAction, EKeys::SpaceBar);
|
||||||
|
SharedMappingContext->MapKey(InteractAction, EKeys::E);
|
||||||
|
SharedMappingContext->MapKey(AttackAction, EKeys::LeftMouseButton);
|
||||||
|
SharedMappingContext->MapKey(ToggleCameraAction, EKeys::V);
|
||||||
|
SharedMappingContext->MapKey(InventoryAction, EKeys::I);
|
||||||
|
SharedMappingContext->MapKey(PauseAction, EKeys::Escape);
|
||||||
|
SharedMappingContext->MapKey(JumpAction, EKeys::Gamepad_FaceButton_Bottom);
|
||||||
|
SharedMappingContext->MapKey(InteractAction, EKeys::Gamepad_FaceButton_Left);
|
||||||
|
SharedMappingContext->MapKey(AttackAction, EKeys::Gamepad_RightTrigger);
|
||||||
|
SharedMappingContext->MapKey(ToggleCameraAction, EKeys::Gamepad_Special_Right);
|
||||||
|
SharedMappingContext->MapKey(InventoryAction, EKeys::Gamepad_FaceButton_Top);
|
||||||
|
SharedMappingContext->MapKey(PauseAction, EKeys::Gamepad_Special_Left);
|
||||||
|
|
||||||
|
FirstPersonMappingContext = NewObject<UInputMappingContext>(this, TEXT("IMC_Vocation_FP"));
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::W);
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::S);
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::A);
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::D);
|
||||||
|
FirstPersonMappingContext->MapKey(LookAction, EKeys::Mouse2D);
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::Gamepad_LeftX);
|
||||||
|
FirstPersonMappingContext->MapKey(MoveAction, EKeys::Gamepad_LeftY);
|
||||||
|
FirstPersonMappingContext->MapKey(LookAction, EKeys::Gamepad_RightX);
|
||||||
|
FirstPersonMappingContext->MapKey(LookAction, EKeys::Gamepad_RightY);
|
||||||
|
|
||||||
|
TopDownMappingContext = NewObject<UInputMappingContext>(this, TEXT("IMC_Vocation_TP"));
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::W);
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::S);
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::A);
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::D);
|
||||||
|
TopDownMappingContext->MapKey(LookAction, EKeys::Mouse2D);
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::Gamepad_LeftX);
|
||||||
|
TopDownMappingContext->MapKey(MoveAction, EKeys::Gamepad_LeftY);
|
||||||
|
TopDownMappingContext->MapKey(LookAction, EKeys::Gamepad_RightX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyLowGraphics()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(EVocationGraphicsPreset::Low, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyMediumGraphics()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(EVocationGraphicsPreset::Medium, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyHighGraphics()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(EVocationGraphicsPreset::High, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyUltraGraphics()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(EVocationGraphicsPreset::Ultra, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::ApplyRayTracingGraphics()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SetGraphicsPreset(EVocationGraphicsPreset::RayTracing, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::JoinFirstFoundSession()
|
||||||
|
{
|
||||||
|
if (UVocationSessionSubsystem* Sessions = GetGameInstance()->GetSubsystem<UVocationSessionSubsystem>())
|
||||||
|
{
|
||||||
|
Sessions->OnSessionSearchComplete.AddDynamic(this, &AVocationPlayerController::HandleSessionSearchForJoin);
|
||||||
|
Sessions->FindSessions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::HandleSessionSearchForJoin(const TArray<FString>& SessionNames)
|
||||||
|
{
|
||||||
|
if (UVocationSessionSubsystem* Sessions = GetGameInstance()->GetSubsystem<UVocationSessionSubsystem>())
|
||||||
|
{
|
||||||
|
Sessions->OnSessionSearchComplete.RemoveDynamic(this, &AVocationPlayerController::HandleSessionSearchForJoin);
|
||||||
|
if (SessionNames.Num() > 0)
|
||||||
|
{
|
||||||
|
Sessions->JoinSessionByIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerController::QuickSave()
|
||||||
|
{
|
||||||
|
if (UVocationGameInstance* GI = GetGameInstance<UVocationGameInstance>())
|
||||||
|
{
|
||||||
|
GI->SaveGame();
|
||||||
|
if (VocationHUD)
|
||||||
|
{
|
||||||
|
VocationHUD->ShowDebugStatus(TEXT("Game saved."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Source/VocationLife/Private/VocationPlayerState.cpp
Normal file
30
Source/VocationLife/Private/VocationPlayerState.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationPlayerState.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
|
||||||
|
AVocationPlayerState::AVocationPlayerState()
|
||||||
|
{
|
||||||
|
bReplicates = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
DOREPLIFETIME(AVocationPlayerState, ActiveVocation);
|
||||||
|
DOREPLIFETIME(AVocationPlayerState, Health);
|
||||||
|
DOREPLIFETIME(AVocationPlayerState, MaxHealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerState::SetActiveVocation(EVocationLifeClass NewVocation)
|
||||||
|
{
|
||||||
|
if (HasAuthority())
|
||||||
|
{
|
||||||
|
ActiveVocation = NewVocation;
|
||||||
|
OnRep_ActiveVocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationPlayerState::OnRep_ActiveVocation()
|
||||||
|
{
|
||||||
|
}
|
||||||
166
Source/VocationLife/Private/VocationSessionSubsystem.cpp
Normal file
166
Source/VocationLife/Private/VocationSessionSubsystem.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationSessionSubsystem.h"
|
||||||
|
#include "OnlineSubsystem.h"
|
||||||
|
#include "OnlineSessionSettings.h"
|
||||||
|
#include "Interfaces/OnlineSessionInterface.h"
|
||||||
|
|
||||||
|
static const FName VOCATION_SESSION_NAME = TEXT("VocationLifeSession");
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::HostSession(int32 MaxPlayers, const FString& SessionName)
|
||||||
|
{
|
||||||
|
IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
|
||||||
|
if (!OnlineSubsystem)
|
||||||
|
{
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface();
|
||||||
|
if (!Sessions.IsValid())
|
||||||
|
{
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateSessionDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(
|
||||||
|
FOnCreateSessionCompleteDelegate::CreateUObject(this, &UVocationSessionSubsystem::OnCreateSessionComplete));
|
||||||
|
|
||||||
|
TSharedRef<FOnlineSessionSettings> SessionSettings = MakeShared<FOnlineSessionSettings>();
|
||||||
|
SessionSettings->bIsLANMatch = true;
|
||||||
|
SessionSettings->NumPublicConnections = MaxPlayers;
|
||||||
|
SessionSettings->bShouldAdvertise = true;
|
||||||
|
SessionSettings->bUsesPresence = true;
|
||||||
|
SessionSettings->Set(FName(TEXT("SESSION_NAME")), SessionName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
|
||||||
|
|
||||||
|
const ULocalPlayer* LocalPlayer = GetWorld() && GetWorld()->GetFirstLocalPlayerFromController()
|
||||||
|
? GetWorld()->GetFirstLocalPlayerFromController()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (!Sessions->CreateSession(0, VOCATION_SESSION_NAME, *SessionSettings))
|
||||||
|
{
|
||||||
|
Sessions->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionDelegateHandle);
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::FindSessions()
|
||||||
|
{
|
||||||
|
IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
|
||||||
|
if (!OnlineSubsystem)
|
||||||
|
{
|
||||||
|
OnSessionSearchComplete.Broadcast({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface();
|
||||||
|
if (!Sessions.IsValid())
|
||||||
|
{
|
||||||
|
OnSessionSearchComplete.Broadcast({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FindSessionsDelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(
|
||||||
|
FOnFindSessionsCompleteDelegate::CreateUObject(this, &UVocationSessionSubsystem::OnFindSessionsComplete));
|
||||||
|
|
||||||
|
SessionSearch = MakeShared<FOnlineSessionSearch>();
|
||||||
|
SessionSearch->bIsLanQuery = true;
|
||||||
|
SessionSearch->MaxSearchResults = 20;
|
||||||
|
SessionSearch->QuerySettings.Set(FName(TEXT("PRESENCESEARCH")), true, EOnlineComparisonOp::Equals);
|
||||||
|
|
||||||
|
if (!Sessions->FindSessions(0, SessionSearch.ToSharedRef()))
|
||||||
|
{
|
||||||
|
Sessions->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsDelegateHandle);
|
||||||
|
OnSessionSearchComplete.Broadcast({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::JoinSessionByIndex(int32 SessionIndex)
|
||||||
|
{
|
||||||
|
IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
|
||||||
|
if (!OnlineSubsystem || !SessionSearch.IsValid())
|
||||||
|
{
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface();
|
||||||
|
if (!Sessions.IsValid() || !SessionSearch->SearchResults.IsValidIndex(SessionIndex))
|
||||||
|
{
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinSessionDelegateHandle = Sessions->AddOnJoinSessionCompleteDelegate_Handle(
|
||||||
|
FOnJoinSessionCompleteDelegate::CreateUObject(this, &UVocationSessionSubsystem::OnJoinSessionComplete));
|
||||||
|
|
||||||
|
if (!Sessions->JoinSession(0, VOCATION_SESSION_NAME, SessionSearch->SearchResults[SessionIndex]))
|
||||||
|
{
|
||||||
|
Sessions->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionDelegateHandle);
|
||||||
|
OnSessionJoined.Broadcast(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::DestroySession()
|
||||||
|
{
|
||||||
|
if (IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
|
||||||
|
{
|
||||||
|
if (IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface())
|
||||||
|
{
|
||||||
|
Sessions->DestroySession(VOCATION_SESSION_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bIsHosting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
|
||||||
|
{
|
||||||
|
if (IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
|
||||||
|
{
|
||||||
|
if (IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface())
|
||||||
|
{
|
||||||
|
Sessions->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionDelegateHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bIsHosting = bWasSuccessful;
|
||||||
|
OnSessionJoined.Broadcast(bWasSuccessful);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::OnFindSessionsComplete(bool bWasSuccessful)
|
||||||
|
{
|
||||||
|
TArray<FString> SessionNames;
|
||||||
|
if (bWasSuccessful && SessionSearch.IsValid())
|
||||||
|
{
|
||||||
|
for (const FOnlineSessionSearchResult& Result : SessionSearch->SearchResults)
|
||||||
|
{
|
||||||
|
FString Name;
|
||||||
|
Result.Session.SessionSettings.Get(FName(TEXT("SESSION_NAME")), Name);
|
||||||
|
SessionNames.Add(Name.IsEmpty() ? TEXT("VocationLife Server") : Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
|
||||||
|
{
|
||||||
|
if (IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface())
|
||||||
|
{
|
||||||
|
Sessions->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsDelegateHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSessionSearchComplete.Broadcast(SessionNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UVocationSessionSubsystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
|
||||||
|
{
|
||||||
|
if (IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
|
||||||
|
{
|
||||||
|
if (IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface())
|
||||||
|
{
|
||||||
|
Sessions->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionDelegateHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool bSuccess = Result == EOnJoinSessionCompleteResult::Success;
|
||||||
|
OnSessionJoined.Broadcast(bSuccess);
|
||||||
|
}
|
||||||
84
Source/VocationLife/Private/VocationTestWorldBuilder.cpp
Normal file
84
Source/VocationLife/Private/VocationTestWorldBuilder.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationTestWorldBuilder.h"
|
||||||
|
#include "MiningNode.h"
|
||||||
|
#include "VocationEnemy.h"
|
||||||
|
#include "Engine/StaticMeshActor.h"
|
||||||
|
#include "Components/StaticMeshComponent.h"
|
||||||
|
#include "Engine/StaticMesh.h"
|
||||||
|
#include "Engine/DirectionalLight.h"
|
||||||
|
#include "Engine/SkyLight.h"
|
||||||
|
#include "Components/DirectionalLightComponent.h"
|
||||||
|
#include "Components/SkyLightComponent.h"
|
||||||
|
#include "EngineUtils.h"
|
||||||
|
#include "Kismet/GameplayStatics.h"
|
||||||
|
#include "UObject/ConstructorHelpers.h"
|
||||||
|
|
||||||
|
AVocationTestWorldBuilder::AVocationTestWorldBuilder()
|
||||||
|
{
|
||||||
|
PrimaryActorTick.bCanEverTick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationTestWorldBuilder::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
if (bAutoBuildOnBeginPlay && GetWorld() && HasAuthority())
|
||||||
|
{
|
||||||
|
BuildTestWorld();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVocationTestWorldBuilder::BuildTestWorld()
|
||||||
|
{
|
||||||
|
UWorld* World = GetWorld();
|
||||||
|
if (!World)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> PlaneMesh(TEXT("/Engine/BasicShapes/Plane.Plane"));
|
||||||
|
if (PlaneMesh.Succeeded())
|
||||||
|
{
|
||||||
|
FActorSpawnParameters SpawnParams;
|
||||||
|
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||||
|
|
||||||
|
if (AStaticMeshActor* Floor = World->SpawnActor<AStaticMeshActor>(FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams))
|
||||||
|
{
|
||||||
|
Floor->GetStaticMeshComponent()->SetStaticMesh(PlaneMesh.Object);
|
||||||
|
Floor->SetActorScale3D(FVector(20.f, 20.f, 1.f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FActorSpawnParameters SpawnParams;
|
||||||
|
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||||
|
|
||||||
|
World->SpawnActor<AMiningNode>(FVector(400.f, 0.f, 50.f), FRotator::ZeroRotator, SpawnParams);
|
||||||
|
World->SpawnActor<AMiningNode>(FVector(-350.f, 250.f, 50.f), FRotator::ZeroRotator, SpawnParams);
|
||||||
|
World->SpawnActor<AVocationEnemy>(FVector(800.f, 0.f, 100.f), FRotator(180.f, 0.f, 0.f), SpawnParams);
|
||||||
|
|
||||||
|
TArray<AActor*> FoundLights;
|
||||||
|
UGameplayStatics::GetAllActorsOfClass(World, ADirectionalLight::StaticClass(), FoundLights);
|
||||||
|
if (FoundLights.Num() == 0)
|
||||||
|
{
|
||||||
|
ADirectionalLight* Sun = World->SpawnActor<ADirectionalLight>();
|
||||||
|
if (Sun)
|
||||||
|
{
|
||||||
|
Sun->SetActorRotation(FRotator(-45.f, 45.f, 0.f));
|
||||||
|
if (UDirectionalLightComponent* Light = Sun->GetComponent())
|
||||||
|
{
|
||||||
|
Light->SetIntensity(6.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<AActor*> FoundSkies;
|
||||||
|
UGameplayStatics::GetAllActorsOfClass(World, ASkyLight::StaticClass(), FoundSkies);
|
||||||
|
if (FoundSkies.Num() == 0)
|
||||||
|
{
|
||||||
|
ASkyLight* Sky = World->SpawnActor<ASkyLight>();
|
||||||
|
if (Sky && Sky->GetLightComponent())
|
||||||
|
{
|
||||||
|
Sky->GetLightComponent()->SetIntensity(1.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Source/VocationLife/Public/CombatComponent.h
Normal file
58
Source/VocationLife/Public/CombatComponent.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "CombatComponent.generated.h"
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChanged, float, NewHealth, float, MaxHealth);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);
|
||||||
|
|
||||||
|
UCLASS(ClassGroup = (VocationLife), meta = (BlueprintSpawnableComponent))
|
||||||
|
class VOCATIONLIFE_API UCombatComponent : public UActorComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UCombatComponent();
|
||||||
|
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Combat")
|
||||||
|
void ApplyDamage(float DamageAmount, AActor* DamageCauser);
|
||||||
|
|
||||||
|
UFUNCTION(Server, Reliable, BlueprintCallable, Category = "VocationLife|Combat")
|
||||||
|
void ServerApplyDamage(float DamageAmount, AActor* DamageCauser);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Combat")
|
||||||
|
bool IsAlive() const { return Health > 0.f; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Combat")
|
||||||
|
float GetHealth() const { return Health; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Combat")
|
||||||
|
float GetMaxHealth() const { return MaxHealth; }
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VocationLife|Combat")
|
||||||
|
float AttackDamage = 15.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VocationLife|Combat")
|
||||||
|
float AttackRange = 200.f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Combat")
|
||||||
|
FOnHealthChanged OnHealthChanged;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Combat")
|
||||||
|
FOnDeath OnDeath;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "VocationLife|Combat")
|
||||||
|
float Health = 100.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VocationLife|Combat")
|
||||||
|
float MaxHealth = 100.f;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_Health();
|
||||||
|
};
|
||||||
40
Source/VocationLife/Public/CraftingComponent.h
Normal file
40
Source/VocationLife/Public/CraftingComponent.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "CraftingComponent.generated.h"
|
||||||
|
|
||||||
|
class UInventoryComponent;
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnCraftCompleted, FName, RecipeId, FName, OutputItemId);
|
||||||
|
|
||||||
|
UCLASS(ClassGroup = (VocationLife), meta = (BlueprintSpawnableComponent))
|
||||||
|
class VOCATIONLIFE_API UCraftingComponent : public UActorComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UCraftingComponent();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Crafting")
|
||||||
|
bool CanCraftRecipe(const FRecipeDefinition& Recipe) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Crafting")
|
||||||
|
bool CraftRecipe(const FRecipeDefinition& Recipe);
|
||||||
|
|
||||||
|
UFUNCTION(Server, Reliable, BlueprintCallable, Category = "VocationLife|Crafting")
|
||||||
|
void ServerCraftRecipe(FName RecipeId);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Crafting")
|
||||||
|
TArray<FRecipeDefinition> GetAvailableRecipes(EVocationLifeClass Vocation) const;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Crafting")
|
||||||
|
FOnCraftCompleted OnCraftCompleted;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UInventoryComponent* GetInventory() const;
|
||||||
|
bool FindRecipe(FName RecipeId, FRecipeDefinition& OutRecipe) const;
|
||||||
|
};
|
||||||
28
Source/VocationLife/Public/Interactable.h
Normal file
28
Source/VocationLife/Public/Interactable.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "UObject/Interface.h"
|
||||||
|
#include "Interactable.generated.h"
|
||||||
|
|
||||||
|
UINTERFACE(MinimalAPI, BlueprintType)
|
||||||
|
class UInteractable : public UInterface
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
};
|
||||||
|
|
||||||
|
class VOCATIONLIFE_API IInteractable
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
|
||||||
|
FText GetInteractionPrompt() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
|
||||||
|
bool CanInteract(APawn* InteractingPawn) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
|
||||||
|
void Interact(APawn* InteractingPawn);
|
||||||
|
};
|
||||||
58
Source/VocationLife/Public/InventoryComponent.h
Normal file
58
Source/VocationLife/Public/InventoryComponent.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "InventoryComponent.generated.h"
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnInventoryChanged);
|
||||||
|
|
||||||
|
UCLASS(ClassGroup = (VocationLife), meta = (BlueprintSpawnableComponent))
|
||||||
|
class VOCATIONLIFE_API UInventoryComponent : public UActorComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UInventoryComponent();
|
||||||
|
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
bool AddItem(FName ItemId, int32 Quantity);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
bool RemoveItem(FName ItemId, int32 Quantity);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
bool HasItem(FName ItemId, int32 Quantity = 1) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
int32 GetItemCount(FName ItemId) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
const TArray<FInventorySlot>& GetSlots() const { return Slots; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
void SetSlots(const TArray<FInventorySlot>& NewSlots);
|
||||||
|
|
||||||
|
UFUNCTION(Server, Reliable, BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
void ServerAddItem(FName ItemId, int32 Quantity);
|
||||||
|
|
||||||
|
UFUNCTION(Server, Reliable, BlueprintCallable, Category = "VocationLife|Inventory")
|
||||||
|
void ServerRemoveItem(FName ItemId, int32 Quantity);
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Inventory")
|
||||||
|
FOnInventoryChanged OnInventoryChanged;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_Slots, BlueprintReadOnly, Category = "VocationLife|Inventory")
|
||||||
|
TArray<FInventorySlot> Slots;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_Slots();
|
||||||
|
|
||||||
|
int32 FindSlotIndex(FName ItemId) const;
|
||||||
|
int32 GetMaxStack(FName ItemId) const;
|
||||||
|
};
|
||||||
52
Source/VocationLife/Public/MiningNode.h
Normal file
52
Source/VocationLife/Public/MiningNode.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "Interactable.h"
|
||||||
|
#include "MiningNode.generated.h"
|
||||||
|
|
||||||
|
class UStaticMeshComponent;
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AMiningNode : public AActor, public IInteractable
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AMiningNode();
|
||||||
|
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
|
virtual FText GetInteractionPrompt_Implementation() const override;
|
||||||
|
virtual bool CanInteract_Implementation(APawn* InteractingPawn) const override;
|
||||||
|
virtual void Interact_Implementation(APawn* InteractingPawn) override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Mining")
|
||||||
|
bool IsDepleted() const { return bIsDepleted; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife|Mining")
|
||||||
|
TObjectPtr<UStaticMeshComponent> MeshComponent;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Mining")
|
||||||
|
FName OreItemId = TEXT("IronOre");
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Mining")
|
||||||
|
int32 OreYield = 3;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Mining")
|
||||||
|
float RespawnTimeSeconds = 30.f;
|
||||||
|
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_Depleted, BlueprintReadOnly, Category = "VocationLife|Mining")
|
||||||
|
bool bIsDepleted = false;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_Depleted();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleRespawn();
|
||||||
|
|
||||||
|
FTimerHandle RespawnTimerHandle;
|
||||||
|
};
|
||||||
129
Source/VocationLife/Public/VocationCharacter.h
Normal file
129
Source/VocationLife/Public/VocationCharacter.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Character.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationCharacter.generated.h"
|
||||||
|
|
||||||
|
class UCameraComponent;
|
||||||
|
class USpringArmComponent;
|
||||||
|
class UInventoryComponent;
|
||||||
|
class UCraftingComponent;
|
||||||
|
class UCombatComponent;
|
||||||
|
class UInputAction;
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCameraModeChanged, EVocationCameraMode, NewMode);
|
||||||
|
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class VOCATIONLIFE_API AVocationCharacter : public ACharacter
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationCharacter();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
virtual void Tick(float DeltaSeconds) override;
|
||||||
|
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Camera")
|
||||||
|
void ToggleCameraMode();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Camera")
|
||||||
|
void SetCameraMode(EVocationCameraMode NewMode, bool bInstant = false);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Camera")
|
||||||
|
EVocationCameraMode GetCameraMode() const { return CurrentCameraMode; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleMove(const struct FInputActionValue& Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleLook(const struct FInputActionValue& Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleJumpStarted();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleInteract();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleAttack();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleToggleCamera();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void HandleInventory();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Interaction")
|
||||||
|
AActor* FindInteractableTarget() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife")
|
||||||
|
UInventoryComponent* GetInventoryComponent() const { return InventoryComponent; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife")
|
||||||
|
UCraftingComponent* GetCraftingComponent() const { return CraftingComponent; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife")
|
||||||
|
UCombatComponent* GetCombatComponent() const { return CombatComponent; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Camera")
|
||||||
|
FOnCameraModeChanged OnCameraModeChanged;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
TObjectPtr<UCameraComponent> FirstPersonCamera;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
TObjectPtr<USpringArmComponent> TopDownSpringArm;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
TObjectPtr<UCameraComponent> TopDownCamera;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
TObjectPtr<UInventoryComponent> InventoryComponent;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
TObjectPtr<UCraftingComponent> CraftingComponent;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
TObjectPtr<UCombatComponent> CombatComponent;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
float CameraBlendTime = 0.35f;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
float TopDownArmLength = 900.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
float TopDownPitch = -45.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Interaction")
|
||||||
|
float InteractionRange = 300.f;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void UpdateCameraMode(float DeltaSeconds);
|
||||||
|
void ApplyCameraModeVisuals();
|
||||||
|
void UpdateInteractionPrompt();
|
||||||
|
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_CameraMode, BlueprintReadOnly, Category = "VocationLife|Camera")
|
||||||
|
EVocationCameraMode CurrentCameraMode = EVocationCameraMode::FirstPerson;
|
||||||
|
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_CameraMode)
|
||||||
|
EVocationCameraMode TargetCameraMode = EVocationCameraMode::FirstPerson;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
float CameraBlendAlpha = 1.f;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
bool bIsBlendingCamera = false;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_CameraMode();
|
||||||
|
|
||||||
|
UFUNCTION(Server, Reliable)
|
||||||
|
void ServerSetCameraMode(EVocationCameraMode NewMode);
|
||||||
|
};
|
||||||
57
Source/VocationLife/Public/VocationEOSSubsystem.h
Normal file
57
Source/VocationLife/Public/VocationEOSSubsystem.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Subsystems/GameInstanceSubsystem.h"
|
||||||
|
#include "VocationEOSSubsystem.generated.h"
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EEOSSubsystemState : uint8
|
||||||
|
{
|
||||||
|
Disabled,
|
||||||
|
Initializing,
|
||||||
|
Ready,
|
||||||
|
Error
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Epic Online Services integration layer for future crossplay.
|
||||||
|
* Configured via Config/DefaultVocationLife.ini — disabled until EOS credentials are set.
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API UVocationEOSSubsystem : public UGameInstanceSubsystem
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|EOS")
|
||||||
|
bool IsEOSEnabled() const { return bEOSEnabled; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|EOS")
|
||||||
|
EEOSSubsystemState GetState() const { return SubsystemState; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|EOS")
|
||||||
|
void InitializeEOS();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|EOS")
|
||||||
|
FString GetProductId() const { return ProductId; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY()
|
||||||
|
bool bEOSEnabled = false;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
EEOSSubsystemState SubsystemState = EEOSSubsystemState::Disabled;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FString ProductId;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FString SandboxId;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FString DeploymentId;
|
||||||
|
};
|
||||||
30
Source/VocationLife/Public/VocationEnemy.h
Normal file
30
Source/VocationLife/Public/VocationEnemy.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Character.h"
|
||||||
|
#include "VocationEnemy.generated.h"
|
||||||
|
|
||||||
|
class UCombatComponent;
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AVocationEnemy : public ACharacter
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationEnemy();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Enemy")
|
||||||
|
UCombatComponent* GetCombatComponent() const { return CombatComponent; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "VocationLife|Enemy")
|
||||||
|
TObjectPtr<UCombatComponent> CombatComponent;
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleDeath();
|
||||||
|
};
|
||||||
71
Source/VocationLife/Public/VocationGameInstance.h
Normal file
71
Source/VocationLife/Public/VocationGameInstance.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Engine/GameInstance.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationGameInstance.generated.h"
|
||||||
|
|
||||||
|
class UVocationSaveGame;
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnVocationDataReady);
|
||||||
|
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class VOCATIONLIFE_API UVocationGameInstance : public UGameInstance
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UVocationGameInstance();
|
||||||
|
|
||||||
|
virtual void Init() override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Save")
|
||||||
|
bool SaveGame(const FString& SlotName = TEXT("VocationSave"));
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Save")
|
||||||
|
bool LoadGame(const FString& SlotName = TEXT("VocationSave"));
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Save")
|
||||||
|
bool HasSaveGame(const FString& SlotName = TEXT("VocationSave")) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Data")
|
||||||
|
const TMap<FName, FVocationItemDefinition>& GetItemDefinitions() const { return ItemDefinitions; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Data")
|
||||||
|
const TArray<FRecipeDefinition>& GetRecipeDefinitions() const { return RecipeDefinitions; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Data")
|
||||||
|
bool FindItemDefinition(FName ItemId, FVocationItemDefinition& OutDefinition) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Graphics")
|
||||||
|
void SetGraphicsPreset(EVocationGraphicsPreset Preset, bool bEnableRayTracing);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Graphics")
|
||||||
|
EVocationGraphicsPreset GetGraphicsPreset() const { return CurrentGraphicsPreset; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Graphics")
|
||||||
|
bool IsRayTracingEnabled() const { return bRayTracingEnabled; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife")
|
||||||
|
FOnVocationDataReady OnDataReady;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "VocationLife|Save")
|
||||||
|
TObjectPtr<UVocationSaveGame> CurrentSave;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void InitializeDefaultData();
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TMap<FName, FVocationItemDefinition> ItemDefinitions;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TArray<FRecipeDefinition> RecipeDefinitions;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
EVocationGraphicsPreset CurrentGraphicsPreset = EVocationGraphicsPreset::High;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
bool bRayTracingEnabled = false;
|
||||||
|
};
|
||||||
29
Source/VocationLife/Public/VocationGameMode.h
Normal file
29
Source/VocationLife/Public/VocationGameMode.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/GameModeBase.h"
|
||||||
|
#include "VocationGameMode.generated.h"
|
||||||
|
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class VOCATIONLIFE_API AVocationGameMode : public AGameModeBase
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationGameMode();
|
||||||
|
|
||||||
|
virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;
|
||||||
|
virtual void PostLogin(APlayerController* NewPlayer) override;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Multiplayer")
|
||||||
|
int32 MaxCoopPlayers = 4;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VocationLife|Server")
|
||||||
|
FString ServerWelcomeMessage = TEXT("Welcome to VocationLife");
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual FString InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId,
|
||||||
|
const FString& Options, const FString& Portal) override;
|
||||||
|
};
|
||||||
21
Source/VocationLife/Public/VocationGraphicsLibrary.h
Normal file
21
Source/VocationLife/Public/VocationGraphicsLibrary.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationGraphicsLibrary.generated.h"
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API UVocationGraphicsLibrary : public UBlueprintFunctionLibrary
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Graphics")
|
||||||
|
static void ApplyGraphicsPreset(EVocationGraphicsPreset Preset, bool bEnableRayTracing);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Graphics")
|
||||||
|
static FText GetGraphicsPresetDisplayName(EVocationGraphicsPreset Preset);
|
||||||
|
};
|
||||||
48
Source/VocationLife/Public/VocationHUD.h
Normal file
48
Source/VocationLife/Public/VocationHUD.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/HUD.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationHUD.generated.h"
|
||||||
|
|
||||||
|
class UUserWidget;
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AVocationHUD : public AHUD
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void SetInteractionPrompt(const FText& Prompt);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void ClearInteractionPrompt();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void SetPauseVisible(bool bVisible);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void ShowDebugStatus(const FString& Status);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void ApplyGraphicsPresetFromHUD(EVocationGraphicsPreset Preset, bool bRayTracing);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DrawMainHUD();
|
||||||
|
virtual void DrawHUD() override;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|UI")
|
||||||
|
TSubclassOf<UUserWidget> PauseMenuWidgetClass;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UUserWidget> PauseMenuWidget;
|
||||||
|
|
||||||
|
FText CurrentInteractionPrompt;
|
||||||
|
FString DebugStatusLine;
|
||||||
|
bool bShowPauseMenu = false;
|
||||||
|
};
|
||||||
123
Source/VocationLife/Public/VocationPlayerController.h
Normal file
123
Source/VocationLife/Public/VocationPlayerController.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/PlayerController.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationPlayerController.generated.h"
|
||||||
|
|
||||||
|
class UInputMappingContext;
|
||||||
|
class UInputAction;
|
||||||
|
class AVocationHUD;
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AVocationPlayerController : public APlayerController
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationPlayerController();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
virtual void SetupInputComponent() override;
|
||||||
|
virtual void OnPossess(APawn* InPawn) override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void TogglePauseMenu();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void ShowInteractionPrompt(const FText& Prompt);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|UI")
|
||||||
|
void ClearInteractionPrompt();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void HostCoopGame();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void FindCoopGames();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void JoinCoopGame(int32 SessionIndex);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Input")
|
||||||
|
void ApplyInputMappingForCameraMode(EVocationCameraMode CameraMode);
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void ApplyLowGraphics();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void ApplyMediumGraphics();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void ApplyHighGraphics();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void ApplyUltraGraphics();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void ApplyRayTracingGraphics();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void JoinFirstFoundSession();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void QuickSave();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleSessionSearchForJoin(const TArray<FString>& SessionNames);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void CreateRuntimeInputAssets();
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputMappingContext> SharedMappingContext;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputMappingContext> FirstPersonMappingContext;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputMappingContext> TopDownMappingContext;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> MoveAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> LookAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> JumpAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> InteractAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> AttackAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> ToggleCameraAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> InventoryAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<UInputAction> PauseAction;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TObjectPtr<AVocationHUD> VocationHUD;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|Input")
|
||||||
|
int32 SharedMappingPriority = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|Input")
|
||||||
|
int32 ModeMappingPriority = 1;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|Input")
|
||||||
|
float MouseSensitivity = 1.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|Input")
|
||||||
|
float GamepadLookSensitivity = 1.f;
|
||||||
|
|
||||||
|
bool bPauseMenuOpen = false;
|
||||||
|
};
|
||||||
38
Source/VocationLife/Public/VocationPlayerState.h
Normal file
38
Source/VocationLife/Public/VocationPlayerState.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/PlayerState.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationPlayerState.generated.h"
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AVocationPlayerState : public APlayerState
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationPlayerState();
|
||||||
|
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife")
|
||||||
|
EVocationLifeClass GetActiveVocation() const { return ActiveVocation; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife")
|
||||||
|
void SetActiveVocation(EVocationLifeClass NewVocation);
|
||||||
|
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_ActiveVocation, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
EVocationLifeClass ActiveVocation = EVocationLifeClass::Miner;
|
||||||
|
|
||||||
|
UPROPERTY(Replicated, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
float Health = 100.f;
|
||||||
|
|
||||||
|
UPROPERTY(Replicated, BlueprintReadOnly, Category = "VocationLife")
|
||||||
|
float MaxHealth = 100.f;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_ActiveVocation();
|
||||||
|
};
|
||||||
36
Source/VocationLife/Public/VocationSaveGame.h
Normal file
36
Source/VocationLife/Public/VocationSaveGame.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/SaveGame.h"
|
||||||
|
#include "VocationTypes.h"
|
||||||
|
#include "VocationSaveGame.generated.h"
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API UVocationSaveGame : public USaveGame
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
FVector PlayerLocation = FVector::ZeroVector;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
FRotator PlayerRotation = FRotator::ZeroRotator;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
TArray<FInventorySlot> Inventory;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
EVocationLifeClass ActiveVocation = EVocationLifeClass::Miner;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
float PlayerHealth = 100.f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
EVocationGraphicsPreset GraphicsPreset = EVocationGraphicsPreset::High;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, Category = "Save")
|
||||||
|
bool bRayTracingEnabled = false;
|
||||||
|
};
|
||||||
51
Source/VocationLife/Public/VocationSessionSubsystem.h
Normal file
51
Source/VocationLife/Public/VocationSessionSubsystem.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Subsystems/GameInstanceSubsystem.h"
|
||||||
|
#include "Interfaces/OnlineSessionInterface.h"
|
||||||
|
#include "VocationSessionSubsystem.generated.h"
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSessionSearchComplete, const TArray<FString>&, SessionNames);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSessionJoined, bool, bSuccess);
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API UVocationSessionSubsystem : public UGameInstanceSubsystem
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void HostSession(int32 MaxPlayers = 4, const FString& SessionName = TEXT("VocationLife"));
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void FindSessions();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void JoinSessionByIndex(int32 SessionIndex);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
void DestroySession();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "VocationLife|Session")
|
||||||
|
bool IsHosting() const { return bIsHosting; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Session")
|
||||||
|
FOnSessionSearchComplete OnSessionSearchComplete;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "VocationLife|Session")
|
||||||
|
FOnSessionJoined OnSessionJoined;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
|
||||||
|
void OnFindSessionsComplete(bool bWasSuccessful);
|
||||||
|
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
|
||||||
|
|
||||||
|
FDelegateHandle CreateSessionDelegateHandle;
|
||||||
|
FDelegateHandle FindSessionsDelegateHandle;
|
||||||
|
FDelegateHandle JoinSessionDelegateHandle;
|
||||||
|
|
||||||
|
TSharedPtr<class FOnlineSessionSearch> SessionSearch;
|
||||||
|
bool bIsHosting = false;
|
||||||
|
};
|
||||||
28
Source/VocationLife/Public/VocationTestWorldBuilder.h
Normal file
28
Source/VocationLife/Public/VocationTestWorldBuilder.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "VocationTestWorldBuilder.generated.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a minimal playable test layout when Lvl_VocationTest has no placed actors.
|
||||||
|
* Place one instance in the test map or let GameMode spawn it automatically.
|
||||||
|
*/
|
||||||
|
UCLASS()
|
||||||
|
class VOCATIONLIFE_API AVocationTestWorldBuilder : public AActor
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
AVocationTestWorldBuilder();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void BuildTestWorld();
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category = "VocationLife|World")
|
||||||
|
bool bAutoBuildOnBeginPlay = true;
|
||||||
|
};
|
||||||
107
Source/VocationLife/Public/VocationTypes.h
Normal file
107
Source/VocationLife/Public/VocationTypes.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "VocationTypes.generated.h"
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EVocationCameraMode : uint8
|
||||||
|
{
|
||||||
|
FirstPerson UMETA(DisplayName = "First Person"),
|
||||||
|
TopDown UMETA(DisplayName = "Top Down")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EVocationGraphicsPreset : uint8
|
||||||
|
{
|
||||||
|
Low UMETA(DisplayName = "Low"),
|
||||||
|
Medium UMETA(DisplayName = "Medium"),
|
||||||
|
High UMETA(DisplayName = "High"),
|
||||||
|
Ultra UMETA(DisplayName = "Ultra"),
|
||||||
|
RayTracing UMETA(DisplayName = "Ray Tracing")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EVocationLifeClass : uint8
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Miner,
|
||||||
|
Blacksmith,
|
||||||
|
Paladin,
|
||||||
|
Mercenary,
|
||||||
|
Hunter,
|
||||||
|
Wizard,
|
||||||
|
Woodcutter,
|
||||||
|
Angler,
|
||||||
|
Cook,
|
||||||
|
Carpenter,
|
||||||
|
Tailor,
|
||||||
|
Alchemist
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FVocationItemDefinition
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
|
||||||
|
FName ItemId = NAME_None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
|
||||||
|
FText DisplayName;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
|
||||||
|
int32 MaxStack = 99;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
|
||||||
|
bool bIsCraftingMaterial = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FInventorySlot
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inventory")
|
||||||
|
FName ItemId = NAME_None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Inventory")
|
||||||
|
int32 Quantity = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRecipeIngredient
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
FName ItemId = NAME_None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
int32 Quantity = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRecipeDefinition
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
FName RecipeId = NAME_None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
FText DisplayName;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
EVocationLifeClass RequiredVocation = EVocationLifeClass::None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
TArray<FRecipeIngredient> Ingredients;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
FName OutputItemId = NAME_None;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Recipe")
|
||||||
|
int32 OutputQuantity = 1;
|
||||||
|
};
|
||||||
34
Source/VocationLife/VocationLife.Build.cs
Normal file
34
Source/VocationLife/VocationLife.Build.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
|
||||||
|
public class VocationLife : ModuleRules
|
||||||
|
{
|
||||||
|
public VocationLife(ReadOnlyTargetRules Target) : base(Target)
|
||||||
|
{
|
||||||
|
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||||
|
|
||||||
|
PublicDependencyModuleNames.AddRange(new string[]
|
||||||
|
{
|
||||||
|
"Core",
|
||||||
|
"CoreUObject",
|
||||||
|
"Engine",
|
||||||
|
"InputCore",
|
||||||
|
"EnhancedInput",
|
||||||
|
"UMG",
|
||||||
|
"Slate",
|
||||||
|
"SlateCore",
|
||||||
|
"OnlineSubsystem",
|
||||||
|
"OnlineSubsystemUtils",
|
||||||
|
"Json",
|
||||||
|
"JsonUtilities"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Target.Platform == UnrealTargetPlatform.Win64 ||
|
||||||
|
Target.Platform == UnrealTargetPlatform.Linux ||
|
||||||
|
Target.Platform == UnrealTargetPlatform.Mac)
|
||||||
|
{
|
||||||
|
PrivateDependencyModuleNames.Add("OnlineSubsystemSteam");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Source/VocationLife/VocationLife.cpp
Normal file
6
Source/VocationLife/VocationLife.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "VocationLife.h"
|
||||||
|
#include "Modules/ModuleManager.h"
|
||||||
|
|
||||||
|
IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, VocationLife, "VocationLife");
|
||||||
5
Source/VocationLife/VocationLife.h
Normal file
5
Source/VocationLife/VocationLife.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
15
Source/VocationLifeEditor.Target.cs
Normal file
15
Source/VocationLifeEditor.Target.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class VocationLifeEditorTarget : TargetRules
|
||||||
|
{
|
||||||
|
public VocationLifeEditorTarget(TargetInfo Target) : base(Target)
|
||||||
|
{
|
||||||
|
Type = TargetType.Editor;
|
||||||
|
DefaultBuildSettings = BuildSettingsVersion.V7;
|
||||||
|
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_8;
|
||||||
|
ExtraModuleNames.Add("VocationLife");
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Source/VocationLifeServer.Target.cs
Normal file
16
Source/VocationLifeServer.Target.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright VocationLife Project. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class VocationLifeServerTarget : TargetRules
|
||||||
|
{
|
||||||
|
public VocationLifeServerTarget(TargetInfo Target) : base(Target)
|
||||||
|
{
|
||||||
|
Type = TargetType.Server;
|
||||||
|
DefaultBuildSettings = BuildSettingsVersion.V7;
|
||||||
|
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_8;
|
||||||
|
ExtraModuleNames.Add("VocationLife");
|
||||||
|
bUseChecksInShipping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
VocationLife.uproject
Normal file
50
VocationLife.uproject
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"FileVersion": 3,
|
||||||
|
"EngineAssociation": "5.8",
|
||||||
|
"Category": "",
|
||||||
|
"Description": "Fantasy Life inspired life-sim remake with dual camera, co-op multiplayer, and optional ray tracing.",
|
||||||
|
"Modules": [
|
||||||
|
{
|
||||||
|
"Name": "VocationLife",
|
||||||
|
"Type": "Runtime",
|
||||||
|
"LoadingPhase": "Default"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Plugins": [
|
||||||
|
{
|
||||||
|
"Name": "ModelingToolsEditorMode",
|
||||||
|
"Enabled": true,
|
||||||
|
"TargetAllowList": [
|
||||||
|
"Editor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Landmass",
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "InEditorDocumentation",
|
||||||
|
"Enabled": true,
|
||||||
|
"TargetAllowList": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"PlatformAllowList": [
|
||||||
|
"Win64",
|
||||||
|
"Mac",
|
||||||
|
"Linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "AIAssistant",
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "OnlineSubsystemSteam",
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "OnlineSubsystemEOS",
|
||||||
|
"Enabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user