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