diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini index 71e3c755b..ed1ddd8f7 100644 --- a/Config/DefaultEditor.ini +++ b/Config/DefaultEditor.ini @@ -7,7 +7,7 @@ +mTargetContentFolderPaths=/Game/SVN/MainLevel/ [/Script/AdvancedPreviewScene.SharedProfiles] -+Profiles=(ProfileName="Epic Headquarters",bSharedProfile=True,bIsEngineDefaultProfile=True,bUseSkyLighting=True,DirectionalLightIntensity=1.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=1.000000,bRotateLightingRig=False,bShowEnvironment=False,bShowFloor=False,bShowGrid=False,EnvironmentColor=(R=0.200000,G=0.200000,B=0.200000,A=1.000000),EnvironmentIntensity=1.000000,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",bPostProcessingEnabled=True,PostProcessingSettings=(bOverride_TemperatureType=False,bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_ColorCorrectionHighlightsMax=False,bOverride_BlueCorrection=False,bOverride_ExpandGamut=False,bOverride_ToneCurveAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_ChromaticAberrationStartOffset=False,bOverride_bMegaLights=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomMethod=False,bOverride_BloomIntensity=False,bOverride_BloomGaussianIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomConvolutionIntensity=False,bOverride_BloomConvolutionTexture=False,bOverride_BloomConvolutionScatterDispersion=False,bOverride_BloomConvolutionSize=False,bOverride_BloomConvolutionCenterUV=False,bOverride_BloomConvolutionPreFilterMin=False,bOverride_BloomConvolutionPreFilterMax=False,bOverride_BloomConvolutionPreFilterMult=False,bOverride_BloomConvolutionBufferScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_CameraShutterSpeed=False,bOverride_CameraISO=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_AutoExposureBiasCurve=False,bOverride_AutoExposureMeterMask=False,bOverride_AutoExposureApplyPhysicalCameraExposure=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LocalExposureMethod=False,bOverride_LocalExposureHighlightContrastScale=False,bOverride_LocalExposureShadowContrastScale=False,bOverride_LocalExposureHighlightContrastCurve=False,bOverride_LocalExposureShadowContrastCurve=False,bOverride_LocalExposureHighlightThreshold=False,bOverride_LocalExposureShadowThreshold=False,bOverride_LocalExposureDetailStrength=False,bOverride_LocalExposureBlurredLuminanceBlend=False,bOverride_LocalExposureBlurredLuminanceKernelSizePercent=False,bOverride_LocalExposureHighlightThresholdStrength=False,bOverride_LocalExposureShadowThresholdStrength=False,bOverride_LocalExposureMiddleGreyBias=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_Sharpen=False,bOverride_FilmGrainIntensity=False,bOverride_FilmGrainIntensityShadows=False,bOverride_FilmGrainIntensityMidtones=False,bOverride_FilmGrainIntensityHighlights=False,bOverride_FilmGrainShadowsMax=False,bOverride_FilmGrainHighlightsMin=False,bOverride_FilmGrainHighlightsMax=False,bOverride_FilmGrainTexelSize=False,bOverride_FilmGrainTexture=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_AmbientOcclusionTemporalBlendWeight=False,bOverride_RayTracingAO=False,bOverride_RayTracingAOSamplesPerPixel=False,bOverride_RayTracingAOIntensity=False,bOverride_RayTracingAORadius=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldMinFstop=False,bOverride_DepthOfFieldBladeCount=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldSqueezeFactor=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldUseHairDepth=False,bOverride_DepthOfFieldPetzvalBokeh=False,bOverride_DepthOfFieldPetzvalBokehFalloff=False,bOverride_DepthOfFieldPetzvalExclusionBoxExtents=False,bOverride_DepthOfFieldPetzvalExclusionBoxRadius=False,bOverride_DepthOfFieldAspectRatioScalar=False,bOverride_DepthOfFieldMatteBoxFlags=False,bOverride_DepthOfFieldBarrelRadius=False,bOverride_DepthOfFieldBarrelLength=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurTargetFPS=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ReflectionMethod=False,bOverride_LumenReflectionQuality=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,bOverride_UserFlags=False,bOverride_RayTracingReflectionsMaxRoughness=False,bOverride_RayTracingReflectionsMaxBounces=False,bOverride_RayTracingReflectionsSamplesPerPixel=False,bOverride_RayTracingReflectionsShadows=False,bOverride_RayTracingReflectionsTranslucency=False,bOverride_TranslucencyType=False,bOverride_RayTracingTranslucencyMaxRoughness=False,bOverride_RayTracingTranslucencyRefractionRays=False,bOverride_RayTracingTranslucencySamplesPerPixel=False,bOverride_RayTracingTranslucencyShadows=False,bOverride_RayTracingTranslucencyRefraction=False,bOverride_RayTracingTranslucencyMaxPrimaryHitEvents=False,bOverride_RayTracingTranslucencyMaxSecondaryHitEvents=False,bOverride_RayTracingTranslucencyUseRayTracedRefraction=False,bOverride_DynamicGlobalIlluminationMethod=False,bOverride_LumenSceneLightingQuality=False,bOverride_LumenSceneDetail=False,bOverride_LumenSceneViewDistance=False,bOverride_LumenSceneLightingUpdateSpeed=False,bOverride_LumenFinalGatherQuality=False,bOverride_LumenFinalGatherLightingUpdateSpeed=False,bOverride_LumenFinalGatherScreenTraces=False,bOverride_LumenMaxTraceDistance=False,bOverride_LumenDiffuseColorBoost=False,bOverride_LumenSkylightLeaking=False,bOverride_LumenSkylightLeakingTint=False,bOverride_LumenFullSkylightLeakingDistance=False,bOverride_LumenRayLightingMode=False,bOverride_LumenReflectionsScreenTraces=False,bOverride_LumenFrontLayerTranslucencyReflections=False,bOverride_LumenMaxRoughnessToTraceReflections=False,bOverride_LumenMaxReflectionBounces=False,bOverride_LumenMaxRefractionBounces=False,bOverride_LumenSurfaceCacheResolution=False,bOverride_RayTracingGI=False,bOverride_RayTracingGIMaxBounces=False,bOverride_RayTracingGISamplesPerPixel=False,bOverride_PathTracingMaxBounces=False,bOverride_PathTracingSamplesPerPixel=False,bOverride_PathTracingMaxPathIntensity=False,bOverride_PathTracingEnableEmissiveMaterials=False,bOverride_PathTracingEnableReferenceDOF=False,bOverride_PathTracingEnableReferenceAtmosphere=False,bOverride_PathTracingEnableDenoiser=False,bOverride_PathTracingIncludeEmissive=False,bOverride_PathTracingIncludeDiffuse=False,bOverride_PathTracingIncludeIndirectDiffuse=False,bOverride_PathTracingIncludeSpecular=False,bOverride_PathTracingIncludeIndirectSpecular=False,bOverride_PathTracingIncludeVolume=False,bOverride_PathTracingIncludeIndirectVolume=False,bMobileHQGaussian=False,BloomMethod=BM_SOG,AutoExposureMethod=AEM_Histogram,TemperatureType=TEMP_WhiteBalance,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,ColorCorrectionHighlightsMax=1.000000,ColorCorrectionShadowsMax=0.090000,BlueCorrection=0.600000,ExpandGamut=1.000000,ToneCurveAmount=1.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,ChromaticAberrationStartOffset=0.000000,BloomIntensity=0.675000,BloomGaussianIntensity=1.000000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomConvolutionIntensity=1.000000,BloomConvolutionScatterDispersion=1.000000,BloomConvolutionSize=1.000000,BloomConvolutionTexture=None,BloomConvolutionCenterUV=(X=0.500000,Y=0.500000),BloomConvolutionPreFilterMin=7.000000,BloomConvolutionPreFilterMax=15000.000000,BloomConvolutionPreFilterMult=15.000000,BloomConvolutionBufferScale=0.133000,BloomDirtMask=None,BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),DynamicGlobalIlluminationMethod=Lumen,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,LumenRayLightingMode=Default,LumenSceneLightingQuality=1.000000,LumenSceneDetail=1.000000,LumenSceneViewDistance=20000.000000,LumenSceneLightingUpdateSpeed=1.000000,LumenFinalGatherQuality=1.000000,LumenFinalGatherLightingUpdateSpeed=1.000000,LumenFinalGatherScreenTraces=True,LumenMaxTraceDistance=20000.000000,LumenDiffuseColorBoost=1.000000,LumenSkylightLeaking=0.000000,LumenSkylightLeakingTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LumenFullSkylightLeakingDistance=1000.000000,LumenSurfaceCacheResolution=1.000000,ReflectionMethod=Lumen,LumenReflectionQuality=1.000000,LumenReflectionsScreenTraces=True,LumenFrontLayerTranslucencyReflections=False,LumenMaxRoughnessToTraceReflections=0.400000,LumenMaxReflectionBounces=1,LumenMaxRefractionBounces=0,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,bMegaLights=True,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,CameraShutterSpeed=60.000000,CameraISO=100.000000,DepthOfFieldFstop=4.000000,DepthOfFieldMinFstop=1.200000,DepthOfFieldBladeCount=5,AutoExposureBias=1.000000,AutoExposureBiasBackup=0.000000,bOverride_AutoExposureBiasBackup=False,AutoExposureApplyPhysicalCameraExposure=True,AutoExposureBiasCurve=None,AutoExposureMeterMask=None,AutoExposureLowPercent=10.000000,AutoExposureHighPercent=90.000000,AutoExposureMinBrightness=-10.000000,AutoExposureMaxBrightness=20.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,HistogramLogMin=-10.000000,HistogramLogMax=20.000000,LocalExposureMethod=Bilateral,LocalExposureHighlightContrastScale=1.000000,LocalExposureShadowContrastScale=1.000000,LocalExposureHighlightContrastCurve=None,LocalExposureShadowContrastCurve=None,LocalExposureHighlightThreshold=0.000000,LocalExposureShadowThreshold=0.000000,LocalExposureDetailStrength=1.000000,LocalExposureBlurredLuminanceBlend=0.600000,LocalExposureBlurredLuminanceKernelSizePercent=50.000000,LocalExposureHighlightThresholdStrength=1.000000,LocalExposureShadowThresholdStrength=1.000000,LocalExposureMiddleGreyBias=0.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,Sharpen=0.000000,FilmGrainIntensity=0.000000,FilmGrainIntensityShadows=1.000000,FilmGrainIntensityMidtones=1.000000,FilmGrainIntensityHighlights=1.000000,FilmGrainShadowsMax=0.090000,FilmGrainHighlightsMin=0.500000,FilmGrainHighlightsMax=1.000000,FilmGrainTexelSize=1.000000,FilmGrainTexture=None,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,AmbientOcclusionTemporalBlendWeight=0.100000,RayTracingAO=False,RayTracingAOSamplesPerPixel=1,RayTracingAOIntensity=1.000000,RayTracingAORadius=200.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldSensorWidth=24.576000,DepthOfFieldSqueezeFactor=1.000000,DepthOfFieldFocalDistance=0.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldUseHairDepth=False,DepthOfFieldPetzvalBokeh=0.000000,DepthOfFieldPetzvalBokehFalloff=1.000000,DepthOfFieldPetzvalExclusionBoxExtents=(X=0.000000,Y=0.000000),DepthOfFieldPetzvalExclusionBoxRadius=0.000000,DepthOfFieldAspectRatioScalar=1.000000,DepthOfFieldBarrelRadius=5.000000,DepthOfFieldBarrelLength=0.000000,DepthOfFieldMatteBoxFlags[0]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[1]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[2]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldOcclusion=0.400000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurTargetFPS=30,MotionBlurPerObjectSize=0.000000,TranslucencyType=Raster,RayTracingTranslucencyMaxRoughness=0.600000,RayTracingTranslucencyRefractionRays=3,RayTracingTranslucencySamplesPerPixel=1,RayTracingTranslucencyMaxPrimaryHitEvents=4,RayTracingTranslucencyMaxSecondaryHitEvents=2,RayTracingTranslucencyShadows=Hard_shadows,RayTracingTranslucencyRefraction=True,RayTracingTranslucencyUseRayTracedRefraction=False,PathTracingMaxBounces=32,PathTracingSamplesPerPixel=2048,PathTracingMaxPathIntensity=24.000000,PathTracingEnableEmissiveMaterials=True,PathTracingEnableReferenceDOF=False,PathTracingEnableReferenceAtmosphere=False,PathTracingEnableDenoiser=True,PathTracingIncludeEmissive=True,PathTracingIncludeDiffuse=True,PathTracingIncludeIndirectDiffuse=True,PathTracingIncludeSpecular=True,PathTracingIncludeIndirectSpecular=True,PathTracingIncludeVolume=True,PathTracingIncludeIndirectVolume=True,UserFlags=0,WeightedBlendables=(Array=)),LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000),bEnableToneMapping=True,bShowMeshEdges=False) ++Profiles=(ProfileName="Epic Headquarters",bSharedProfile=True,bIsEngineDefaultProfile=True,bUseSkyLighting=True,DirectionalLightIntensity=1.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=1.000000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=False,bShowGrid=False,EnvironmentColor=(R=0.200000,G=0.200000,B=0.200000,A=1.000000),EnvironmentIntensity=1.000000,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",bPostProcessingEnabled=True,PostProcessingSettings=(bOverride_TemperatureType=False,bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_ColorCorrectionHighlightsMax=False,bOverride_BlueCorrection=False,bOverride_ExpandGamut=False,bOverride_ToneCurveAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_ChromaticAberrationStartOffset=False,bOverride_bMegaLights=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomMethod=False,bOverride_BloomIntensity=False,bOverride_BloomGaussianIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomConvolutionIntensity=False,bOverride_BloomConvolutionTexture=False,bOverride_BloomConvolutionScatterDispersion=False,bOverride_BloomConvolutionSize=False,bOverride_BloomConvolutionCenterUV=False,bOverride_BloomConvolutionPreFilterMin=False,bOverride_BloomConvolutionPreFilterMax=False,bOverride_BloomConvolutionPreFilterMult=False,bOverride_BloomConvolutionBufferScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_CameraShutterSpeed=False,bOverride_CameraISO=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_AutoExposureBiasCurve=False,bOverride_AutoExposureMeterMask=False,bOverride_AutoExposureApplyPhysicalCameraExposure=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LocalExposureMethod=False,bOverride_LocalExposureHighlightContrastScale=False,bOverride_LocalExposureShadowContrastScale=False,bOverride_LocalExposureHighlightContrastCurve=False,bOverride_LocalExposureShadowContrastCurve=False,bOverride_LocalExposureHighlightThreshold=False,bOverride_LocalExposureShadowThreshold=False,bOverride_LocalExposureDetailStrength=False,bOverride_LocalExposureBlurredLuminanceBlend=False,bOverride_LocalExposureBlurredLuminanceKernelSizePercent=False,bOverride_LocalExposureHighlightThresholdStrength=False,bOverride_LocalExposureShadowThresholdStrength=False,bOverride_LocalExposureMiddleGreyBias=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_Sharpen=False,bOverride_FilmGrainIntensity=False,bOverride_FilmGrainIntensityShadows=False,bOverride_FilmGrainIntensityMidtones=False,bOverride_FilmGrainIntensityHighlights=False,bOverride_FilmGrainShadowsMax=False,bOverride_FilmGrainHighlightsMin=False,bOverride_FilmGrainHighlightsMax=False,bOverride_FilmGrainTexelSize=False,bOverride_FilmGrainTexture=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_AmbientOcclusionTemporalBlendWeight=False,bOverride_RayTracingAO=False,bOverride_RayTracingAOSamplesPerPixel=False,bOverride_RayTracingAOIntensity=False,bOverride_RayTracingAORadius=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldMinFstop=False,bOverride_DepthOfFieldBladeCount=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldSqueezeFactor=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldUseHairDepth=False,bOverride_DepthOfFieldPetzvalBokeh=False,bOverride_DepthOfFieldPetzvalBokehFalloff=False,bOverride_DepthOfFieldPetzvalExclusionBoxExtents=False,bOverride_DepthOfFieldPetzvalExclusionBoxRadius=False,bOverride_DepthOfFieldAspectRatioScalar=False,bOverride_DepthOfFieldMatteBoxFlags=False,bOverride_DepthOfFieldBarrelRadius=False,bOverride_DepthOfFieldBarrelLength=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurTargetFPS=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ReflectionMethod=False,bOverride_LumenReflectionQuality=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,bOverride_UserFlags=False,bOverride_RayTracingReflectionsMaxRoughness=False,bOverride_RayTracingReflectionsMaxBounces=False,bOverride_RayTracingReflectionsSamplesPerPixel=False,bOverride_RayTracingReflectionsShadows=False,bOverride_RayTracingReflectionsTranslucency=False,bOverride_TranslucencyType=False,bOverride_RayTracingTranslucencyMaxRoughness=False,bOverride_RayTracingTranslucencyRefractionRays=False,bOverride_RayTracingTranslucencySamplesPerPixel=False,bOverride_RayTracingTranslucencyShadows=False,bOverride_RayTracingTranslucencyRefraction=False,bOverride_RayTracingTranslucencyMaxPrimaryHitEvents=False,bOverride_RayTracingTranslucencyMaxSecondaryHitEvents=False,bOverride_RayTracingTranslucencyUseRayTracedRefraction=False,bOverride_DynamicGlobalIlluminationMethod=False,bOverride_LumenSceneLightingQuality=False,bOverride_LumenSceneDetail=False,bOverride_LumenSceneViewDistance=False,bOverride_LumenSceneLightingUpdateSpeed=False,bOverride_LumenFinalGatherQuality=False,bOverride_LumenFinalGatherLightingUpdateSpeed=False,bOverride_LumenFinalGatherScreenTraces=False,bOverride_LumenMaxTraceDistance=False,bOverride_LumenDiffuseColorBoost=False,bOverride_LumenSkylightLeaking=False,bOverride_LumenSkylightLeakingTint=False,bOverride_LumenFullSkylightLeakingDistance=False,bOverride_LumenRayLightingMode=False,bOverride_LumenReflectionsScreenTraces=False,bOverride_LumenFrontLayerTranslucencyReflections=False,bOverride_LumenMaxRoughnessToTraceReflections=False,bOverride_LumenMaxReflectionBounces=False,bOverride_LumenMaxRefractionBounces=False,bOverride_LumenSurfaceCacheResolution=False,bOverride_RayTracingGI=False,bOverride_RayTracingGIMaxBounces=False,bOverride_RayTracingGISamplesPerPixel=False,bOverride_PathTracingMaxBounces=False,bOverride_PathTracingSamplesPerPixel=False,bOverride_PathTracingMaxPathIntensity=False,bOverride_PathTracingEnableEmissiveMaterials=False,bOverride_PathTracingEnableReferenceDOF=False,bOverride_PathTracingEnableReferenceAtmosphere=False,bOverride_PathTracingEnableDenoiser=False,bOverride_PathTracingIncludeEmissive=False,bOverride_PathTracingIncludeDiffuse=False,bOverride_PathTracingIncludeIndirectDiffuse=False,bOverride_PathTracingIncludeSpecular=False,bOverride_PathTracingIncludeIndirectSpecular=False,bOverride_PathTracingIncludeVolume=False,bOverride_PathTracingIncludeIndirectVolume=False,bMobileHQGaussian=False,BloomMethod=BM_SOG,AutoExposureMethod=AEM_Histogram,TemperatureType=TEMP_WhiteBalance,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,ColorCorrectionHighlightsMax=1.000000,ColorCorrectionShadowsMax=0.090000,BlueCorrection=0.600000,ExpandGamut=1.000000,ToneCurveAmount=1.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,ChromaticAberrationStartOffset=0.000000,BloomIntensity=0.675000,BloomGaussianIntensity=1.000000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomConvolutionIntensity=1.000000,BloomConvolutionScatterDispersion=1.000000,BloomConvolutionSize=1.000000,BloomConvolutionTexture=None,BloomConvolutionCenterUV=(X=0.500000,Y=0.500000),BloomConvolutionPreFilterMin=7.000000,BloomConvolutionPreFilterMax=15000.000000,BloomConvolutionPreFilterMult=15.000000,BloomConvolutionBufferScale=0.133000,BloomDirtMask=None,BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),DynamicGlobalIlluminationMethod=Lumen,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,LumenRayLightingMode=Default,LumenSceneLightingQuality=1.000000,LumenSceneDetail=1.000000,LumenSceneViewDistance=20000.000000,LumenSceneLightingUpdateSpeed=1.000000,LumenFinalGatherQuality=1.000000,LumenFinalGatherLightingUpdateSpeed=1.000000,LumenFinalGatherScreenTraces=True,LumenMaxTraceDistance=20000.000000,LumenDiffuseColorBoost=1.000000,LumenSkylightLeaking=0.000000,LumenSkylightLeakingTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LumenFullSkylightLeakingDistance=1000.000000,LumenSurfaceCacheResolution=1.000000,ReflectionMethod=Lumen,LumenReflectionQuality=1.000000,LumenReflectionsScreenTraces=True,LumenFrontLayerTranslucencyReflections=False,LumenMaxRoughnessToTraceReflections=0.400000,LumenMaxReflectionBounces=1,LumenMaxRefractionBounces=0,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,bMegaLights=True,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,CameraShutterSpeed=60.000000,CameraISO=100.000000,DepthOfFieldFstop=4.000000,DepthOfFieldMinFstop=1.200000,DepthOfFieldBladeCount=5,AutoExposureBias=1.000000,AutoExposureBiasBackup=0.000000,bOverride_AutoExposureBiasBackup=False,AutoExposureApplyPhysicalCameraExposure=True,AutoExposureBiasCurve=None,AutoExposureMeterMask=None,AutoExposureLowPercent=10.000000,AutoExposureHighPercent=90.000000,AutoExposureMinBrightness=-10.000000,AutoExposureMaxBrightness=20.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,HistogramLogMin=-10.000000,HistogramLogMax=20.000000,LocalExposureMethod=Bilateral,LocalExposureHighlightContrastScale=1.000000,LocalExposureShadowContrastScale=1.000000,LocalExposureHighlightContrastCurve=None,LocalExposureShadowContrastCurve=None,LocalExposureHighlightThreshold=0.000000,LocalExposureShadowThreshold=0.000000,LocalExposureDetailStrength=1.000000,LocalExposureBlurredLuminanceBlend=0.600000,LocalExposureBlurredLuminanceKernelSizePercent=50.000000,LocalExposureHighlightThresholdStrength=1.000000,LocalExposureShadowThresholdStrength=1.000000,LocalExposureMiddleGreyBias=0.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,Sharpen=0.000000,FilmGrainIntensity=0.000000,FilmGrainIntensityShadows=1.000000,FilmGrainIntensityMidtones=1.000000,FilmGrainIntensityHighlights=1.000000,FilmGrainShadowsMax=0.090000,FilmGrainHighlightsMin=0.500000,FilmGrainHighlightsMax=1.000000,FilmGrainTexelSize=1.000000,FilmGrainTexture=None,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,AmbientOcclusionTemporalBlendWeight=0.100000,RayTracingAO=False,RayTracingAOSamplesPerPixel=1,RayTracingAOIntensity=1.000000,RayTracingAORadius=200.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldSensorWidth=24.576000,DepthOfFieldSqueezeFactor=1.000000,DepthOfFieldFocalDistance=0.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldUseHairDepth=False,DepthOfFieldPetzvalBokeh=0.000000,DepthOfFieldPetzvalBokehFalloff=1.000000,DepthOfFieldPetzvalExclusionBoxExtents=(X=0.000000,Y=0.000000),DepthOfFieldPetzvalExclusionBoxRadius=0.000000,DepthOfFieldAspectRatioScalar=1.000000,DepthOfFieldBarrelRadius=5.000000,DepthOfFieldBarrelLength=0.000000,DepthOfFieldMatteBoxFlags[0]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[1]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[2]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldOcclusion=0.400000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurTargetFPS=30,MotionBlurPerObjectSize=0.000000,TranslucencyType=Raster,RayTracingTranslucencyMaxRoughness=0.600000,RayTracingTranslucencyRefractionRays=3,RayTracingTranslucencySamplesPerPixel=1,RayTracingTranslucencyMaxPrimaryHitEvents=4,RayTracingTranslucencyMaxSecondaryHitEvents=2,RayTracingTranslucencyShadows=Hard_shadows,RayTracingTranslucencyRefraction=True,RayTracingTranslucencyUseRayTracedRefraction=False,PathTracingMaxBounces=32,PathTracingSamplesPerPixel=2048,PathTracingMaxPathIntensity=24.000000,PathTracingEnableEmissiveMaterials=True,PathTracingEnableReferenceDOF=False,PathTracingEnableReferenceAtmosphere=False,PathTracingEnableDenoiser=True,PathTracingIncludeEmissive=True,PathTracingIncludeDiffuse=True,PathTracingIncludeIndirectDiffuse=True,PathTracingIncludeSpecular=True,PathTracingIncludeIndirectSpecular=True,PathTracingIncludeVolume=True,PathTracingIncludeIndirectVolume=True,UserFlags=0,WeightedBlendables=(Array=)),LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000),bEnableToneMapping=True,bShowMeshEdges=False) +Profiles=(ProfileName="Grey Wireframe",bSharedProfile=True,bIsEngineDefaultProfile=True,bUseSkyLighting=True,DirectionalLightIntensity=1.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=1.000000,bRotateLightingRig=False,bShowEnvironment=False,bShowFloor=False,bShowGrid=True,EnvironmentColor=(R=0.039216,G=0.039216,B=0.039216,A=1.000000),EnvironmentIntensity=1.000000,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",bPostProcessingEnabled=False,PostProcessingSettings=(bOverride_TemperatureType=False,bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_ColorCorrectionHighlightsMax=False,bOverride_BlueCorrection=False,bOverride_ExpandGamut=False,bOverride_ToneCurveAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_ChromaticAberrationStartOffset=False,bOverride_bMegaLights=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomMethod=False,bOverride_BloomIntensity=False,bOverride_BloomGaussianIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomConvolutionIntensity=False,bOverride_BloomConvolutionTexture=False,bOverride_BloomConvolutionScatterDispersion=False,bOverride_BloomConvolutionSize=False,bOverride_BloomConvolutionCenterUV=False,bOverride_BloomConvolutionPreFilterMin=False,bOverride_BloomConvolutionPreFilterMax=False,bOverride_BloomConvolutionPreFilterMult=False,bOverride_BloomConvolutionBufferScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_CameraShutterSpeed=False,bOverride_CameraISO=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_AutoExposureBiasCurve=False,bOverride_AutoExposureMeterMask=False,bOverride_AutoExposureApplyPhysicalCameraExposure=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LocalExposureMethod=False,bOverride_LocalExposureHighlightContrastScale=False,bOverride_LocalExposureShadowContrastScale=False,bOverride_LocalExposureHighlightContrastCurve=False,bOverride_LocalExposureShadowContrastCurve=False,bOverride_LocalExposureHighlightThreshold=False,bOverride_LocalExposureShadowThreshold=False,bOverride_LocalExposureDetailStrength=False,bOverride_LocalExposureBlurredLuminanceBlend=False,bOverride_LocalExposureBlurredLuminanceKernelSizePercent=False,bOverride_LocalExposureHighlightThresholdStrength=False,bOverride_LocalExposureShadowThresholdStrength=False,bOverride_LocalExposureMiddleGreyBias=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_Sharpen=False,bOverride_FilmGrainIntensity=False,bOverride_FilmGrainIntensityShadows=False,bOverride_FilmGrainIntensityMidtones=False,bOverride_FilmGrainIntensityHighlights=False,bOverride_FilmGrainShadowsMax=False,bOverride_FilmGrainHighlightsMin=False,bOverride_FilmGrainHighlightsMax=False,bOverride_FilmGrainTexelSize=False,bOverride_FilmGrainTexture=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_AmbientOcclusionTemporalBlendWeight=False,bOverride_RayTracingAO=False,bOverride_RayTracingAOSamplesPerPixel=False,bOverride_RayTracingAOIntensity=False,bOverride_RayTracingAORadius=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldMinFstop=False,bOverride_DepthOfFieldBladeCount=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldSqueezeFactor=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldUseHairDepth=False,bOverride_DepthOfFieldPetzvalBokeh=False,bOverride_DepthOfFieldPetzvalBokehFalloff=False,bOverride_DepthOfFieldPetzvalExclusionBoxExtents=False,bOverride_DepthOfFieldPetzvalExclusionBoxRadius=False,bOverride_DepthOfFieldAspectRatioScalar=False,bOverride_DepthOfFieldMatteBoxFlags=False,bOverride_DepthOfFieldBarrelRadius=False,bOverride_DepthOfFieldBarrelLength=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurTargetFPS=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ReflectionMethod=False,bOverride_LumenReflectionQuality=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,bOverride_UserFlags=False,bOverride_RayTracingReflectionsMaxRoughness=False,bOverride_RayTracingReflectionsMaxBounces=False,bOverride_RayTracingReflectionsSamplesPerPixel=False,bOverride_RayTracingReflectionsShadows=False,bOverride_RayTracingReflectionsTranslucency=False,bOverride_TranslucencyType=False,bOverride_RayTracingTranslucencyMaxRoughness=False,bOverride_RayTracingTranslucencyRefractionRays=False,bOverride_RayTracingTranslucencySamplesPerPixel=False,bOverride_RayTracingTranslucencyShadows=False,bOverride_RayTracingTranslucencyRefraction=False,bOverride_RayTracingTranslucencyMaxPrimaryHitEvents=False,bOverride_RayTracingTranslucencyMaxSecondaryHitEvents=False,bOverride_RayTracingTranslucencyUseRayTracedRefraction=False,bOverride_DynamicGlobalIlluminationMethod=False,bOverride_LumenSceneLightingQuality=False,bOverride_LumenSceneDetail=False,bOverride_LumenSceneViewDistance=False,bOverride_LumenSceneLightingUpdateSpeed=False,bOverride_LumenFinalGatherQuality=False,bOverride_LumenFinalGatherLightingUpdateSpeed=False,bOverride_LumenFinalGatherScreenTraces=False,bOverride_LumenMaxTraceDistance=False,bOverride_LumenDiffuseColorBoost=False,bOverride_LumenSkylightLeaking=False,bOverride_LumenSkylightLeakingTint=False,bOverride_LumenFullSkylightLeakingDistance=False,bOverride_LumenRayLightingMode=False,bOverride_LumenReflectionsScreenTraces=False,bOverride_LumenFrontLayerTranslucencyReflections=False,bOverride_LumenMaxRoughnessToTraceReflections=False,bOverride_LumenMaxReflectionBounces=False,bOverride_LumenMaxRefractionBounces=False,bOverride_LumenSurfaceCacheResolution=False,bOverride_RayTracingGI=False,bOverride_RayTracingGIMaxBounces=False,bOverride_RayTracingGISamplesPerPixel=False,bOverride_PathTracingMaxBounces=False,bOverride_PathTracingSamplesPerPixel=False,bOverride_PathTracingMaxPathIntensity=False,bOverride_PathTracingEnableEmissiveMaterials=False,bOverride_PathTracingEnableReferenceDOF=False,bOverride_PathTracingEnableReferenceAtmosphere=False,bOverride_PathTracingEnableDenoiser=False,bOverride_PathTracingIncludeEmissive=False,bOverride_PathTracingIncludeDiffuse=False,bOverride_PathTracingIncludeIndirectDiffuse=False,bOverride_PathTracingIncludeSpecular=False,bOverride_PathTracingIncludeIndirectSpecular=False,bOverride_PathTracingIncludeVolume=False,bOverride_PathTracingIncludeIndirectVolume=False,bMobileHQGaussian=False,BloomMethod=BM_SOG,AutoExposureMethod=AEM_Histogram,TemperatureType=TEMP_WhiteBalance,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,ColorCorrectionHighlightsMax=1.000000,ColorCorrectionShadowsMax=0.090000,BlueCorrection=0.600000,ExpandGamut=1.000000,ToneCurveAmount=1.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,ChromaticAberrationStartOffset=0.000000,BloomIntensity=0.675000,BloomGaussianIntensity=1.000000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomConvolutionIntensity=1.000000,BloomConvolutionScatterDispersion=1.000000,BloomConvolutionSize=1.000000,BloomConvolutionTexture=None,BloomConvolutionCenterUV=(X=0.500000,Y=0.500000),BloomConvolutionPreFilterMin=7.000000,BloomConvolutionPreFilterMax=15000.000000,BloomConvolutionPreFilterMult=15.000000,BloomConvolutionBufferScale=0.133000,BloomDirtMask=None,BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),DynamicGlobalIlluminationMethod=Lumen,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,LumenRayLightingMode=Default,LumenSceneLightingQuality=1.000000,LumenSceneDetail=1.000000,LumenSceneViewDistance=20000.000000,LumenSceneLightingUpdateSpeed=1.000000,LumenFinalGatherQuality=1.000000,LumenFinalGatherLightingUpdateSpeed=1.000000,LumenFinalGatherScreenTraces=True,LumenMaxTraceDistance=20000.000000,LumenDiffuseColorBoost=1.000000,LumenSkylightLeaking=0.000000,LumenSkylightLeakingTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LumenFullSkylightLeakingDistance=1000.000000,LumenSurfaceCacheResolution=1.000000,ReflectionMethod=Lumen,LumenReflectionQuality=1.000000,LumenReflectionsScreenTraces=True,LumenFrontLayerTranslucencyReflections=False,LumenMaxRoughnessToTraceReflections=0.400000,LumenMaxReflectionBounces=1,LumenMaxRefractionBounces=0,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,bMegaLights=True,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,CameraShutterSpeed=60.000000,CameraISO=100.000000,DepthOfFieldFstop=4.000000,DepthOfFieldMinFstop=1.200000,DepthOfFieldBladeCount=5,AutoExposureBias=1.000000,AutoExposureBiasBackup=0.000000,bOverride_AutoExposureBiasBackup=False,AutoExposureApplyPhysicalCameraExposure=True,AutoExposureBiasCurve=None,AutoExposureMeterMask=None,AutoExposureLowPercent=10.000000,AutoExposureHighPercent=90.000000,AutoExposureMinBrightness=-10.000000,AutoExposureMaxBrightness=20.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,HistogramLogMin=-10.000000,HistogramLogMax=20.000000,LocalExposureMethod=Bilateral,LocalExposureHighlightContrastScale=1.000000,LocalExposureShadowContrastScale=1.000000,LocalExposureHighlightContrastCurve=None,LocalExposureShadowContrastCurve=None,LocalExposureHighlightThreshold=0.000000,LocalExposureShadowThreshold=0.000000,LocalExposureDetailStrength=1.000000,LocalExposureBlurredLuminanceBlend=0.600000,LocalExposureBlurredLuminanceKernelSizePercent=50.000000,LocalExposureHighlightThresholdStrength=1.000000,LocalExposureShadowThresholdStrength=1.000000,LocalExposureMiddleGreyBias=0.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,Sharpen=0.000000,FilmGrainIntensity=0.000000,FilmGrainIntensityShadows=1.000000,FilmGrainIntensityMidtones=1.000000,FilmGrainIntensityHighlights=1.000000,FilmGrainShadowsMax=0.090000,FilmGrainHighlightsMin=0.500000,FilmGrainHighlightsMax=1.000000,FilmGrainTexelSize=1.000000,FilmGrainTexture=None,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,AmbientOcclusionTemporalBlendWeight=0.100000,RayTracingAO=False,RayTracingAOSamplesPerPixel=1,RayTracingAOIntensity=1.000000,RayTracingAORadius=200.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldSensorWidth=24.576000,DepthOfFieldSqueezeFactor=1.000000,DepthOfFieldFocalDistance=0.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldUseHairDepth=False,DepthOfFieldPetzvalBokeh=0.000000,DepthOfFieldPetzvalBokehFalloff=1.000000,DepthOfFieldPetzvalExclusionBoxExtents=(X=0.000000,Y=0.000000),DepthOfFieldPetzvalExclusionBoxRadius=0.000000,DepthOfFieldAspectRatioScalar=1.000000,DepthOfFieldBarrelRadius=5.000000,DepthOfFieldBarrelLength=0.000000,DepthOfFieldMatteBoxFlags[0]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[1]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[2]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldOcclusion=0.400000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurTargetFPS=30,MotionBlurPerObjectSize=0.000000,TranslucencyType=Raster,RayTracingTranslucencyMaxRoughness=0.600000,RayTracingTranslucencyRefractionRays=3,RayTracingTranslucencySamplesPerPixel=1,RayTracingTranslucencyMaxPrimaryHitEvents=4,RayTracingTranslucencyMaxSecondaryHitEvents=2,RayTracingTranslucencyShadows=Hard_shadows,RayTracingTranslucencyRefraction=True,RayTracingTranslucencyUseRayTracedRefraction=False,PathTracingMaxBounces=32,PathTracingSamplesPerPixel=2048,PathTracingMaxPathIntensity=24.000000,PathTracingEnableEmissiveMaterials=True,PathTracingEnableReferenceDOF=False,PathTracingEnableReferenceAtmosphere=False,PathTracingEnableDenoiser=True,PathTracingIncludeEmissive=True,PathTracingIncludeDiffuse=True,PathTracingIncludeIndirectDiffuse=True,PathTracingIncludeSpecular=True,PathTracingIncludeIndirectSpecular=True,PathTracingIncludeVolume=True,PathTracingIncludeIndirectVolume=True,UserFlags=0,WeightedBlendables=(Array=)),LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000),bEnableToneMapping=False,bShowMeshEdges=True) +Profiles=(ProfileName="Grey Ambient",bSharedProfile=True,bIsEngineDefaultProfile=True,bUseSkyLighting=True,DirectionalLightIntensity=4.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=2.000000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,bShowGrid=True,EnvironmentColor=(R=0.200000,G=0.200000,B=0.200000,A=1.000000),EnvironmentIntensity=1.000000,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/T_GreyAmbient",bPostProcessingEnabled=False,PostProcessingSettings=(bOverride_TemperatureType=False,bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_ColorCorrectionHighlightsMax=False,bOverride_BlueCorrection=False,bOverride_ExpandGamut=False,bOverride_ToneCurveAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_ChromaticAberrationStartOffset=False,bOverride_bMegaLights=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomMethod=False,bOverride_BloomIntensity=False,bOverride_BloomGaussianIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomConvolutionIntensity=False,bOverride_BloomConvolutionTexture=False,bOverride_BloomConvolutionScatterDispersion=False,bOverride_BloomConvolutionSize=False,bOverride_BloomConvolutionCenterUV=False,bOverride_BloomConvolutionPreFilterMin=False,bOverride_BloomConvolutionPreFilterMax=False,bOverride_BloomConvolutionPreFilterMult=False,bOverride_BloomConvolutionBufferScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_CameraShutterSpeed=False,bOverride_CameraISO=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_AutoExposureBiasCurve=False,bOverride_AutoExposureMeterMask=False,bOverride_AutoExposureApplyPhysicalCameraExposure=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LocalExposureMethod=False,bOverride_LocalExposureHighlightContrastScale=False,bOverride_LocalExposureShadowContrastScale=False,bOverride_LocalExposureHighlightContrastCurve=False,bOverride_LocalExposureShadowContrastCurve=False,bOverride_LocalExposureHighlightThreshold=False,bOverride_LocalExposureShadowThreshold=False,bOverride_LocalExposureDetailStrength=False,bOverride_LocalExposureBlurredLuminanceBlend=False,bOverride_LocalExposureBlurredLuminanceKernelSizePercent=False,bOverride_LocalExposureHighlightThresholdStrength=False,bOverride_LocalExposureShadowThresholdStrength=False,bOverride_LocalExposureMiddleGreyBias=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_Sharpen=False,bOverride_FilmGrainIntensity=False,bOverride_FilmGrainIntensityShadows=False,bOverride_FilmGrainIntensityMidtones=False,bOverride_FilmGrainIntensityHighlights=False,bOverride_FilmGrainShadowsMax=False,bOverride_FilmGrainHighlightsMin=False,bOverride_FilmGrainHighlightsMax=False,bOverride_FilmGrainTexelSize=False,bOverride_FilmGrainTexture=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_AmbientOcclusionTemporalBlendWeight=False,bOverride_RayTracingAO=False,bOverride_RayTracingAOSamplesPerPixel=False,bOverride_RayTracingAOIntensity=False,bOverride_RayTracingAORadius=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldMinFstop=False,bOverride_DepthOfFieldBladeCount=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldSqueezeFactor=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldUseHairDepth=False,bOverride_DepthOfFieldPetzvalBokeh=False,bOverride_DepthOfFieldPetzvalBokehFalloff=False,bOverride_DepthOfFieldPetzvalExclusionBoxExtents=False,bOverride_DepthOfFieldPetzvalExclusionBoxRadius=False,bOverride_DepthOfFieldAspectRatioScalar=False,bOverride_DepthOfFieldMatteBoxFlags=False,bOverride_DepthOfFieldBarrelRadius=False,bOverride_DepthOfFieldBarrelLength=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurTargetFPS=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ReflectionMethod=False,bOverride_LumenReflectionQuality=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,bOverride_UserFlags=False,bOverride_RayTracingReflectionsMaxRoughness=False,bOverride_RayTracingReflectionsMaxBounces=False,bOverride_RayTracingReflectionsSamplesPerPixel=False,bOverride_RayTracingReflectionsShadows=False,bOverride_RayTracingReflectionsTranslucency=False,bOverride_TranslucencyType=False,bOverride_RayTracingTranslucencyMaxRoughness=False,bOverride_RayTracingTranslucencyRefractionRays=False,bOverride_RayTracingTranslucencySamplesPerPixel=False,bOverride_RayTracingTranslucencyShadows=False,bOverride_RayTracingTranslucencyRefraction=False,bOverride_RayTracingTranslucencyMaxPrimaryHitEvents=False,bOverride_RayTracingTranslucencyMaxSecondaryHitEvents=False,bOverride_RayTracingTranslucencyUseRayTracedRefraction=False,bOverride_DynamicGlobalIlluminationMethod=False,bOverride_LumenSceneLightingQuality=False,bOverride_LumenSceneDetail=False,bOverride_LumenSceneViewDistance=False,bOverride_LumenSceneLightingUpdateSpeed=False,bOverride_LumenFinalGatherQuality=False,bOverride_LumenFinalGatherLightingUpdateSpeed=False,bOverride_LumenFinalGatherScreenTraces=False,bOverride_LumenMaxTraceDistance=False,bOverride_LumenDiffuseColorBoost=False,bOverride_LumenSkylightLeaking=False,bOverride_LumenSkylightLeakingTint=False,bOverride_LumenFullSkylightLeakingDistance=False,bOverride_LumenRayLightingMode=False,bOverride_LumenReflectionsScreenTraces=False,bOverride_LumenFrontLayerTranslucencyReflections=False,bOverride_LumenMaxRoughnessToTraceReflections=False,bOverride_LumenMaxReflectionBounces=False,bOverride_LumenMaxRefractionBounces=False,bOverride_LumenSurfaceCacheResolution=False,bOverride_RayTracingGI=False,bOverride_RayTracingGIMaxBounces=False,bOverride_RayTracingGISamplesPerPixel=False,bOverride_PathTracingMaxBounces=False,bOverride_PathTracingSamplesPerPixel=False,bOverride_PathTracingMaxPathIntensity=False,bOverride_PathTracingEnableEmissiveMaterials=False,bOverride_PathTracingEnableReferenceDOF=False,bOverride_PathTracingEnableReferenceAtmosphere=False,bOverride_PathTracingEnableDenoiser=False,bOverride_PathTracingIncludeEmissive=False,bOverride_PathTracingIncludeDiffuse=False,bOverride_PathTracingIncludeIndirectDiffuse=False,bOverride_PathTracingIncludeSpecular=False,bOverride_PathTracingIncludeIndirectSpecular=False,bOverride_PathTracingIncludeVolume=False,bOverride_PathTracingIncludeIndirectVolume=False,bMobileHQGaussian=False,BloomMethod=BM_SOG,AutoExposureMethod=AEM_Histogram,TemperatureType=TEMP_WhiteBalance,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,ColorCorrectionHighlightsMax=1.000000,ColorCorrectionShadowsMax=0.090000,BlueCorrection=0.600000,ExpandGamut=1.000000,ToneCurveAmount=1.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,ChromaticAberrationStartOffset=0.000000,BloomIntensity=0.675000,BloomGaussianIntensity=1.000000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomConvolutionIntensity=1.000000,BloomConvolutionScatterDispersion=1.000000,BloomConvolutionSize=1.000000,BloomConvolutionTexture=None,BloomConvolutionCenterUV=(X=0.500000,Y=0.500000),BloomConvolutionPreFilterMin=7.000000,BloomConvolutionPreFilterMax=15000.000000,BloomConvolutionPreFilterMult=15.000000,BloomConvolutionBufferScale=0.133000,BloomDirtMask=None,BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),DynamicGlobalIlluminationMethod=Lumen,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,LumenRayLightingMode=Default,LumenSceneLightingQuality=1.000000,LumenSceneDetail=1.000000,LumenSceneViewDistance=20000.000000,LumenSceneLightingUpdateSpeed=1.000000,LumenFinalGatherQuality=1.000000,LumenFinalGatherLightingUpdateSpeed=1.000000,LumenFinalGatherScreenTraces=True,LumenMaxTraceDistance=20000.000000,LumenDiffuseColorBoost=1.000000,LumenSkylightLeaking=0.000000,LumenSkylightLeakingTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LumenFullSkylightLeakingDistance=1000.000000,LumenSurfaceCacheResolution=1.000000,ReflectionMethod=Lumen,LumenReflectionQuality=1.000000,LumenReflectionsScreenTraces=True,LumenFrontLayerTranslucencyReflections=False,LumenMaxRoughnessToTraceReflections=0.400000,LumenMaxReflectionBounces=1,LumenMaxRefractionBounces=0,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,bMegaLights=True,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,CameraShutterSpeed=60.000000,CameraISO=100.000000,DepthOfFieldFstop=4.000000,DepthOfFieldMinFstop=1.200000,DepthOfFieldBladeCount=5,AutoExposureBias=1.000000,AutoExposureBiasBackup=0.000000,bOverride_AutoExposureBiasBackup=False,AutoExposureApplyPhysicalCameraExposure=True,AutoExposureBiasCurve=None,AutoExposureMeterMask=None,AutoExposureLowPercent=10.000000,AutoExposureHighPercent=90.000000,AutoExposureMinBrightness=-10.000000,AutoExposureMaxBrightness=20.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,HistogramLogMin=-10.000000,HistogramLogMax=20.000000,LocalExposureMethod=Bilateral,LocalExposureHighlightContrastScale=1.000000,LocalExposureShadowContrastScale=1.000000,LocalExposureHighlightContrastCurve=None,LocalExposureShadowContrastCurve=None,LocalExposureHighlightThreshold=0.000000,LocalExposureShadowThreshold=0.000000,LocalExposureDetailStrength=1.000000,LocalExposureBlurredLuminanceBlend=0.600000,LocalExposureBlurredLuminanceKernelSizePercent=50.000000,LocalExposureHighlightThresholdStrength=1.000000,LocalExposureShadowThresholdStrength=1.000000,LocalExposureMiddleGreyBias=0.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,Sharpen=0.000000,FilmGrainIntensity=0.000000,FilmGrainIntensityShadows=1.000000,FilmGrainIntensityMidtones=1.000000,FilmGrainIntensityHighlights=1.000000,FilmGrainShadowsMax=0.090000,FilmGrainHighlightsMin=0.500000,FilmGrainHighlightsMax=1.000000,FilmGrainTexelSize=1.000000,FilmGrainTexture=None,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,AmbientOcclusionTemporalBlendWeight=0.100000,RayTracingAO=False,RayTracingAOSamplesPerPixel=1,RayTracingAOIntensity=1.000000,RayTracingAORadius=200.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldSensorWidth=24.576000,DepthOfFieldSqueezeFactor=1.000000,DepthOfFieldFocalDistance=0.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldUseHairDepth=False,DepthOfFieldPetzvalBokeh=0.000000,DepthOfFieldPetzvalBokehFalloff=1.000000,DepthOfFieldPetzvalExclusionBoxExtents=(X=0.000000,Y=0.000000),DepthOfFieldPetzvalExclusionBoxRadius=0.000000,DepthOfFieldAspectRatioScalar=1.000000,DepthOfFieldBarrelRadius=5.000000,DepthOfFieldBarrelLength=0.000000,DepthOfFieldMatteBoxFlags[0]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[1]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldMatteBoxFlags[2]=(Pitch=0.000000,Roll=0.000000,Length=0.000000),DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldOcclusion=0.400000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurTargetFPS=30,MotionBlurPerObjectSize=0.000000,TranslucencyType=Raster,RayTracingTranslucencyMaxRoughness=0.600000,RayTracingTranslucencyRefractionRays=3,RayTracingTranslucencySamplesPerPixel=1,RayTracingTranslucencyMaxPrimaryHitEvents=4,RayTracingTranslucencyMaxSecondaryHitEvents=2,RayTracingTranslucencyShadows=Hard_shadows,RayTracingTranslucencyRefraction=True,RayTracingTranslucencyUseRayTracedRefraction=False,PathTracingMaxBounces=32,PathTracingSamplesPerPixel=2048,PathTracingMaxPathIntensity=24.000000,PathTracingEnableEmissiveMaterials=True,PathTracingEnableReferenceDOF=False,PathTracingEnableReferenceAtmosphere=False,PathTracingEnableDenoiser=True,PathTracingIncludeEmissive=True,PathTracingIncludeDiffuse=True,PathTracingIncludeIndirectDiffuse=True,PathTracingIncludeSpecular=True,PathTracingIncludeIndirectSpecular=True,PathTracingIncludeVolume=True,PathTracingIncludeIndirectVolume=True,UserFlags=0,WeightedBlendables=(Array=)),LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000),bEnableToneMapping=False,bShowMeshEdges=False) diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index c9320c3b5..8ec14ac72 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -84,7 +84,7 @@ mWorldWidgetClasses[11]=None +mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/BP_PoisonPuddleGimmickModel.BP_PoisonPuddleGimmickModel_C",mViewClass="/Game/BP/Obstacle/BP_PoisonPuddleGimmick.BP_PoisonPuddleGimmick_C") +mWorldModelViewMappings=(mModelClass="/Game/BP/Pawn/Enemy/Stage2/BP_Slime_ExplosionUnitModel.BP_Slime_ExplosionUnitModel_C",mViewClass="/Game/BP/Pawn/Enemy/Stage2/BP_Slime_ExplosionUnit.BP_Slime_ExplosionUnit_C") +mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/BP_BlackHoleTotemGimmickModel.BP_BlackHoleTotemGimmickModel_C",mViewClass="/Game/BP/Obstacle/BP_BlackHoleTotemGimmick.BP_BlackHoleTotemGimmick_C") -+mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/BP_Barrel_ExplosionGimmickModel1.BP_Barrel_ExplosionGimmickModel1_C",mViewClass="/Game/BP/Obstacle/BP_Barrel_ExplosionGimmick.BP_Barrel_ExplosionGimmick_C") ++mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/BP_Barrel_ExplosionGimmickModel.BP_Barrel_ExplosionGimmickModel_C",mViewClass="/Game/BP/Obstacle/BP_Barrel_ExplosionGimmick.BP_Barrel_ExplosionGimmick_C") +mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/Stage1/BP_FemObstacleModel.BP_FemObstacleModel_C",mViewClass="/Game/BP/Obstacle/Stage1/BP_FemObstacle.BP_FemObstacle_C") +mWorldModelViewMappings=(mModelClass="/Game/BP/Obstacle/Stage1/BP_CrystalObstacleModel.BP_CrystalObstacleModel_C",mViewClass="/Game/BP/Obstacle/Stage1/BP_CrystalObstacle.BP_CrystalObstacle_C") +mWorldModelViewMappings=(mModelClass="/Game/BP/Pawn/Enemy/Stage2/BP_SkeletonBirdUnitModel.BP_SkeletonBirdUnitModel_C",mViewClass="/Game/BP/Pawn/Enemy/Stage2/BP_SkeletonBirdUnit.BP_SkeletonBirdUnit_C") @@ -184,7 +184,7 @@ mSoundClasses[1]=/Game/BP/Sound/SC_BGM.SC_BGM mSoundClasses[2]=/Game/BP/Sound/SC_SFX.SC_SFX mSoundClasses[3]=/Game/BP/Sound/SC_Voice.SC_Voice mSoundClasses[4]=/Game/BP/Sound/SC_UI.SC_UI -mGlobalStatusEffectVFXSetting=(mEffectVFXs=(("/Script/P_RD.TacticalEffect_GetVulnerability", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetWeakness", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetVigor", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Vigor.FXS_Buff_Vigor",mSocketName="Socket_Ground")))),("/Script/P_RD.TacticalEffect_GetFortification", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Fortification.FXS_Buff_Fortification",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetDefense", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Defense.FXS_Buff_Defense",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_Heal", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Get_Heal.FXS_Get_Heal",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetExhaustion", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetSlow", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetHaste", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Haste.FXS_Buff_Haste",mSocketName="Socket_Ground")))),("/Script/P_RD.TacticalEffect_GetFrail", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_Attack", (mTimelineExecutionDatas=((mKeyName="HitFlash")))),("/Script/P_RD.TacticalEffect_GetBuff_Strength", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Strength.FXS_Buff_Strength",mSocketName="Socket_Ground")))),("/Script/P_RD.TacticalEffect_GetDebuff_Strength", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetBuff_Acumeny", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Acumeny.FXS_Buff_Acumeny",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetDebuff_Acumeny", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetActionPoint", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Get_ActionPoint.FXS_Get_ActionPoint",mSocketName="Socket_Ground")))),("/Script/P_RD.TacticalEffect_GetPoison", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Poison.FXS_Debuff_Poison",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetControlImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_ControlImmunity.FXS_Buff_ControlImmunity",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetWeakeningImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_WeakeningImmunity.FXS_Buff_WeakeningImmunity",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetForcedMovementImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_ForcedMovementImmunity.FXS_Buff_ForcedMovementImmunity",mSocketName="Socket_Chest"))))),mInfiniteEffectVFXs=(("/Script/P_RD.TacticalEffect_Stun", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Stun_Infinite.FXS_Debuff_Stun_Infinite",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_Root", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Root_Infinite.FXS_Debuff_Root_Infinite",mSocketName="Socket_Ground")))))) +mGlobalStatusEffectVFXSetting=(mEffectVFXs=(("/Script/P_RD.TacticalEffect_GetVulnerability", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetWeakness", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetVigor", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Vigor.FXS_Buff_Vigor")))),("/Script/P_RD.TacticalEffect_GetFortification", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Fortification.FXS_Buff_Fortification",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetDefense", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Defense.FXS_Buff_Defense",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_Heal", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Get_Heal.FXS_Get_Heal",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetExhaustion", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetSlow", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetHaste", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Haste.FXS_Buff_Haste")))),("/Script/P_RD.TacticalEffect_GetFrail", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_Attack", (mTimelineExecutionDatas=((mKeyName="HitFlash")))),("/Script/P_RD.TacticalEffect_GetBuff_Strength", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Strength.FXS_Buff_Strength")))),("/Script/P_RD.TacticalEffect_GetDebuff_Strength", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetBuff_Acumeny", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_Acumeny.FXS_Buff_Acumeny",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetDebuff_Acumeny", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_DeBuff.FXS_DeBuff",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetActionPoint", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Get_ActionPoint.FXS_Get_ActionPoint")))),("/Script/P_RD.TacticalEffect_GetPoison", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Poison.FXS_Debuff_Poison",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetControlImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_ControlImmunity.FXS_Buff_ControlImmunity",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetWeakeningImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_WeakeningImmunity.FXS_Buff_WeakeningImmunity",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_GetForcedMovementImmunity", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Buff_ForcedMovementImmunity.FXS_Buff_ForcedMovementImmunity",mSocketName="Socket_Chest")))),("/Script/P_RD.TacticalEffect_ReduceCooldown", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Get_ReduceCoolDown.FXS_Get_ReduceCoolDown",mSocketName="Socket_Chest"))))),mInfiniteEffectVFXs=(("/Script/P_RD.TacticalEffect_Stun", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Stun_Infinite.FXS_Debuff_Stun_Infinite",mSocketName="Socket_Head")))),("/Script/P_RD.TacticalEffect_Root", (mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Effect/FXS_Debuff_Root_Infinite.FXS_Debuff_Root_Infinite")))))) mCombatTargetRemoveVFX=(mNiagaraSpawnDatas=((mNiagaraSystem="/Game/SVN/InSideAsset/VFX/Leave/FXS_DissolveParticle_ZAxis.FXS_DissolveParticle_ZAxis",mSocketName="Socket_Chest")),mTimelineExecutionDatas=((mKeyName="Dissolve")),mIncludeSpawnedNiagaraInTimeline=True) +mCombatTargetVFXTimelineSettings=(mTimelineKeyName="Dissolve",mTimelineCurve="/Game/BP/Curve/C_Dissolve.C_Dissolve",mTimelineEvent=(mSyncTarget=7,mParameterName="User.Dissolve",mCPDIndex=0)) +mCombatTargetVFXTimelineSettings=(mTimelineKeyName="HitFlash",mTimelineCurve="/Game/BP/Curve/C_HitFlash.C_HitFlash",mTimelineEvent=(mSyncTarget=1,mParameterName="",mCPDIndex=1)) diff --git a/Content/BP/Animation/Unit/Common/Skill/AM_Common_HourglassTurn.uasset b/Content/BP/Animation/Unit/Common/Skill/AM_Common_HourglassTurn.uasset new file mode 100644 index 000000000..bbe5ae34f Binary files /dev/null and b/Content/BP/Animation/Unit/Common/Skill/AM_Common_HourglassTurn.uasset differ diff --git a/Content/BP/Animation/Unit/Common/Skill/AM_Common_Leap.uasset b/Content/BP/Animation/Unit/Common/Skill/AM_Common_Leap.uasset new file mode 100644 index 000000000..292f38c1f Binary files /dev/null and b/Content/BP/Animation/Unit/Common/Skill/AM_Common_Leap.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage1/Eagle/Skill/AM_Eagle_Fly.uasset b/Content/BP/Animation/Unit/Enemy/Stage1/Eagle/Skill/AM_Eagle_Fly.uasset index 939de80c8..4e5963971 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage1/Eagle/Skill/AM_Eagle_Fly.uasset and b/Content/BP/Animation/Unit/Enemy/Stage1/Eagle/Skill/AM_Eagle_Fly.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/ABP_HatchetBird.uasset b/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/ABP_HatchetBird.uasset index dc49d4f30..745f01327 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/ABP_HatchetBird.uasset and b/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/ABP_HatchetBird.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/Skill/AM_Hatchet_Fly.uasset b/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/Skill/AM_Hatchet_Fly.uasset index 5efd9bab3..269d80e08 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/Skill/AM_Hatchet_Fly.uasset and b/Content/BP/Animation/Unit/Enemy/Stage2/HatchetBird/Skill/AM_Hatchet_Fly.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/ABP_Skeleton_Golem.uasset b/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/ABP_Skeleton_Golem.uasset index d7086ad98..b82d7fb79 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/ABP_Skeleton_Golem.uasset and b/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/ABP_Skeleton_Golem.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/Skill/AM_Skeleton_Golem_Impact_Leap.uasset b/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/Skill/AM_Skeleton_Golem_Impact_Leap.uasset new file mode 100644 index 000000000..ad91b5165 Binary files /dev/null and b/Content/BP/Animation/Unit/Enemy/Stage2/Skeleton_Golem/Skill/AM_Skeleton_Golem_Impact_Leap.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage3/Ghost/Skill/AM_Ghost_Teleport.uasset b/Content/BP/Animation/Unit/Enemy/Stage3/Ghost/Skill/AM_Ghost_Teleport.uasset index 3c595f11b..5bc75fcda 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage3/Ghost/Skill/AM_Ghost_Teleport.uasset and b/Content/BP/Animation/Unit/Enemy/Stage3/Ghost/Skill/AM_Ghost_Teleport.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/ABP_Skeleton_Rogue.uasset b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/ABP_Skeleton_Rogue.uasset index f39a59f48..5f62d6fa0 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/ABP_Skeleton_Rogue.uasset and b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/ABP_Skeleton_Rogue.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/Skill/AM_Skeleton_Rogue_FlashStep.uasset b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/Skill/AM_Skeleton_Rogue_FlashStep.uasset new file mode 100644 index 000000000..5256efdd3 Binary files /dev/null and b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Rogue/Skill/AM_Skeleton_Rogue_FlashStep.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/ABP_Skeleton_Warrior.uasset b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/ABP_Skeleton_Warrior.uasset index e9db874f3..c26b05acf 100644 Binary files a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/ABP_Skeleton_Warrior.uasset and b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/ABP_Skeleton_Warrior.uasset differ diff --git a/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/Skill/AM_Skeleton_Warrior_ImpactLeap.uasset b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/Skill/AM_Skeleton_Warrior_ImpactLeap.uasset new file mode 100644 index 000000000..b695a22db Binary files /dev/null and b/Content/BP/Animation/Unit/Enemy/Stage3/Skeleton_Warrior/Skill/AM_Skeleton_Warrior_ImpactLeap.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Barbarian/ABP_Barbarian.uasset b/Content/BP/Animation/Unit/Mercenary/Barbarian/ABP_Barbarian.uasset index a7efb8e0d..b8b507f1d 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Barbarian/ABP_Barbarian.uasset and b/Content/BP/Animation/Unit/Mercenary/Barbarian/ABP_Barbarian.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Barbarian/Skill/AM_Barbarian_ImpactLeap.uasset b/Content/BP/Animation/Unit/Mercenary/Barbarian/Skill/AM_Barbarian_ImpactLeap.uasset new file mode 100644 index 000000000..6745754c5 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Barbarian/Skill/AM_Barbarian_ImpactLeap.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Druid/ABP_Druid.uasset b/Content/BP/Animation/Unit/Mercenary/Druid/ABP_Druid.uasset index 861a2019a..fa8e16866 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Druid/ABP_Druid.uasset and b/Content/BP/Animation/Unit/Mercenary/Druid/ABP_Druid.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Druid/Skill/AM_Druid_BlessingOfTime.uasset b/Content/BP/Animation/Unit/Mercenary/Druid/Skill/AM_Druid_BlessingOfTime.uasset new file mode 100644 index 000000000..53403673d Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Druid/Skill/AM_Druid_BlessingOfTime.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Knight/ABP_Knight.uasset b/Content/BP/Animation/Unit/Mercenary/Knight/ABP_Knight.uasset index 59f32b086..20ea4bc6f 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Knight/ABP_Knight.uasset and b/Content/BP/Animation/Unit/Mercenary/Knight/ABP_Knight.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Knight/Skill/AM_Knight_GuardianCharge.uasset b/Content/BP/Animation/Unit/Mercenary/Knight/Skill/AM_Knight_GuardianCharge.uasset new file mode 100644 index 000000000..ddcdf5ff6 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Knight/Skill/AM_Knight_GuardianCharge.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Mage/ABP_Mage.uasset b/Content/BP/Animation/Unit/Mercenary/Mage/ABP_Mage.uasset index 7343e4612..b57898ef3 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Mage/ABP_Mage.uasset and b/Content/BP/Animation/Unit/Mercenary/Mage/ABP_Mage.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_Teleport.uasset b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_Teleport.uasset new file mode 100644 index 000000000..cd4f580d1 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_Teleport.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TickTock.uasset b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TickTock.uasset new file mode 100644 index 000000000..1928cdbb8 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TickTock.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TimeAcceleration.uasset b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TimeAcceleration.uasset new file mode 100644 index 000000000..a0130ca43 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Mage/Skill/AM_Mage_TimeAcceleration.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Ranger/ABP_Ranger.uasset b/Content/BP/Animation/Unit/Mercenary/Ranger/ABP_Ranger.uasset index 5f829ad5a..88308979b 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Ranger/ABP_Ranger.uasset and b/Content/BP/Animation/Unit/Mercenary/Ranger/ABP_Ranger.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Ranger/Skill/AM_Ranger_Smoke.uasset b/Content/BP/Animation/Unit/Mercenary/Ranger/Skill/AM_Ranger_Smoke.uasset new file mode 100644 index 000000000..b651c8fd1 Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Ranger/Skill/AM_Ranger_Smoke.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Rogue/ABP_Rogue.uasset b/Content/BP/Animation/Unit/Mercenary/Rogue/ABP_Rogue.uasset index b90010a31..284b16edf 100644 Binary files a/Content/BP/Animation/Unit/Mercenary/Rogue/ABP_Rogue.uasset and b/Content/BP/Animation/Unit/Mercenary/Rogue/ABP_Rogue.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_Cheat.uasset b/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_Cheat.uasset new file mode 100644 index 000000000..4ab5b6ebf Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_Cheat.uasset differ diff --git a/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_FlashStep.uasset b/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_FlashStep.uasset new file mode 100644 index 000000000..c42bc19bb Binary files /dev/null and b/Content/BP/Animation/Unit/Mercenary/Rogue/Skill/AM_Rogue_FlashStep.uasset differ diff --git a/Content/BP/Curve/CCT_Attribute.uasset b/Content/BP/Curve/CCT_Attribute.uasset index ec5840df0..673d7daf0 100644 Binary files a/Content/BP/Curve/CCT_Attribute.uasset and b/Content/BP/Curve/CCT_Attribute.uasset differ diff --git a/Content/BP/Curve/CombatTarget/CT_ExplosionGimmickAttribute.uasset b/Content/BP/Curve/CombatTarget/CT_ExplosionGimmickAttribute.uasset new file mode 100644 index 000000000..63e1684c7 Binary files /dev/null and b/Content/BP/Curve/CombatTarget/CT_ExplosionGimmickAttribute.uasset differ diff --git a/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_RogueUnitAttribute.uasset b/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_RogueUnitAttribute.uasset index 5a9fdcade..e4f3bdb18 100644 Binary files a/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_RogueUnitAttribute.uasset and b/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_RogueUnitAttribute.uasset differ diff --git a/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_WarriorUnitAttribute.uasset b/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_WarriorUnitAttribute.uasset index 0fe86606b..0e6b69245 100644 Binary files a/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_WarriorUnitAttribute.uasset and b/Content/BP/Curve/Enemy/Stage3/CT_Skeleton_WarriorUnitAttribute.uasset differ diff --git a/Content/BP/Curve/Player/CT_RoguePlayerUnitAttribute.uasset b/Content/BP/Curve/Player/CT_RoguePlayerUnitAttribute.uasset index d0d0ba902..22fad0c25 100644 Binary files a/Content/BP/Curve/Player/CT_RoguePlayerUnitAttribute.uasset and b/Content/BP/Curve/Player/CT_RoguePlayerUnitAttribute.uasset differ diff --git a/Content/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.uasset b/Content/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.uasset index e01247e60..f2e96e9ab 100644 Binary files a/Content/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.uasset and b/Content/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.uasset differ diff --git a/Content/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.uasset b/Content/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.uasset new file mode 100644 index 000000000..c6caf3270 Binary files /dev/null and b/Content/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.uasset differ diff --git a/Content/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.uasset b/Content/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.uasset new file mode 100644 index 000000000..9de7d2180 Binary files /dev/null and b/Content/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.uasset differ diff --git a/Content/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.uasset b/Content/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.uasset new file mode 100644 index 000000000..65844de97 Binary files /dev/null and b/Content/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.uasset differ diff --git a/Content/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.uasset b/Content/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.uasset index 8eb56c78b..0e0e32f07 100644 Binary files a/Content/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.uasset and b/Content/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.uasset differ diff --git a/Content/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.uasset b/Content/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.uasset new file mode 100644 index 000000000..3bf7f4b77 Binary files /dev/null and b/Content/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.uasset differ diff --git a/Content/BP/DataAsset/Passive/DA_Passive_P046.uasset b/Content/BP/DataAsset/Passive/DA_Passive_P046.uasset new file mode 100644 index 000000000..1b23be96f Binary files /dev/null and b/Content/BP/DataAsset/Passive/DA_Passive_P046.uasset differ diff --git a/Content/BP/DataAsset/Passive/DA_Passive_P047.uasset b/Content/BP/DataAsset/Passive/DA_Passive_P047.uasset new file mode 100644 index 000000000..11bebaf30 Binary files /dev/null and b/Content/BP/DataAsset/Passive/DA_Passive_P047.uasset differ diff --git a/Content/BP/DataAsset/Passive/DA_Passive_P048.uasset b/Content/BP/DataAsset/Passive/DA_Passive_P048.uasset new file mode 100644 index 000000000..b20b1799e Binary files /dev/null and b/Content/BP/DataAsset/Passive/DA_Passive_P048.uasset differ diff --git a/Content/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.uasset b/Content/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.uasset new file mode 100644 index 000000000..ea268133d Binary files /dev/null and b/Content/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.uasset differ diff --git a/Content/BP/DataAsset/Room/EliteMonster/Stage2/DA_Elite_Stage2_00.uasset b/Content/BP/DataAsset/Room/EliteMonster/Stage2/DA_Elite_Stage2_00.uasset index 6cad3257f..36ffc9b9d 100644 Binary files a/Content/BP/DataAsset/Room/EliteMonster/Stage2/DA_Elite_Stage2_00.uasset and b/Content/BP/DataAsset/Room/EliteMonster/Stage2/DA_Elite_Stage2_00.uasset differ diff --git a/Content/BP/DataAsset/Room/Monster/DA_GimmickTest_Step.uasset b/Content/BP/DataAsset/Room/Monster/DA_GimmickTest_Step.uasset index 4c20158bd..abbe133c8 100644 Binary files a/Content/BP/DataAsset/Room/Monster/DA_GimmickTest_Step.uasset and b/Content/BP/DataAsset/Room/Monster/DA_GimmickTest_Step.uasset differ diff --git a/Content/BP/DataAsset/Room/Monster/Stage1/DA_Monster_Stage1_00.uasset b/Content/BP/DataAsset/Room/Monster/Stage1/DA_Monster_Stage1_00.uasset index 0d543ea7d..921b299c1 100644 Binary files a/Content/BP/DataAsset/Room/Monster/Stage1/DA_Monster_Stage1_00.uasset and b/Content/BP/DataAsset/Room/Monster/Stage1/DA_Monster_Stage1_00.uasset differ diff --git a/Content/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.uasset b/Content/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.uasset new file mode 100644 index 000000000..d6d853211 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.uasset differ diff --git a/Content/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.uasset b/Content/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.uasset new file mode 100644 index 000000000..fde5efbfa Binary files /dev/null and b/Content/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage1/Golem/DA_Golem_Swing.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage1/Golem/DA_Golem_Swing.uasset index 782e50670..6674cc3a7 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage1/Golem/DA_Golem_Swing.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage1/Golem/DA_Golem_Swing.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage1/Leshy/DA_Leshy_Vine_Pull.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage1/Leshy/DA_Leshy_Vine_Pull.uasset index 58b6a4293..a3358636d 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage1/Leshy/DA_Leshy_Vine_Pull.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage1/Leshy/DA_Leshy_Vine_Pull.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.uasset index 04490526a..006589759 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_ExplosionShot.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_ExplosionShot.uasset index 186b288b9..79ff4730d 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_ExplosionShot.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_ExplosionShot.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_Shot.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_Shot.uasset index 5df6edd4b..2b56c9791 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_Shot.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage2/Rat/DA_Rat_Shot.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.uasset new file mode 100644 index 000000000..bc135b13f Binary files /dev/null and b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Melee/DA_Skeleton_Melee_Attack_Punch.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Melee/DA_Skeleton_Melee_Attack_Punch.uasset index 4958b741f..0a03ee670 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Melee/DA_Skeleton_Melee_Attack_Punch.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Melee/DA_Skeleton_Melee_Attack_Punch.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Ranged/DA_Skeleton_Ranged_Shot.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Ranged/DA_Skeleton_Ranged_Shot.uasset index ec39091f1..049dd6077 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Ranged/DA_Skeleton_Ranged_Shot.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Ranged/DA_Skeleton_Ranged_Shot.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.uasset index 0353ac8da..f5337e2df 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Mage/DA_Skeleton_Mage_Attack_FireBall.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Mage/DA_Skeleton_Mage_Attack_FireBall.uasset index 7f020aa76..c4769e365 100644 Binary files a/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Mage/DA_Skeleton_Mage_Attack_FireBall.uasset and b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Mage/DA_Skeleton_Mage_Attack_FireBall.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.uasset new file mode 100644 index 000000000..47d61dd17 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.uasset differ diff --git a/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.uasset b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.uasset new file mode 100644 index 000000000..01f434119 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.uasset b/Content/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.uasset new file mode 100644 index 000000000..cedc46156 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.uasset b/Content/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.uasset new file mode 100644 index 000000000..6de886e30 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.uasset b/Content/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.uasset new file mode 100644 index 000000000..e804d4267 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Attack_Common_FireBall.uasset b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Attack_Common_FireBall.uasset index 53609c146..a66eaac7b 100644 Binary files a/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Attack_Common_FireBall.uasset and b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Attack_Common_FireBall.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.uasset b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.uasset new file mode 100644 index 000000000..7922c7d83 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.uasset b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.uasset new file mode 100644 index 000000000..64e1f9805 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.uasset b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.uasset new file mode 100644 index 000000000..2ccdc08bb Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Attack_Rare_SharpenBlade.uasset b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Attack_Rare_SharpenBlade.uasset index 0a3f4ba40..5f7bc8e82 100644 Binary files a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Attack_Rare_SharpenBlade.uasset and b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Attack_Rare_SharpenBlade.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.uasset b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.uasset new file mode 100644 index 000000000..f40939e85 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.uasset b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.uasset new file mode 100644 index 000000000..396617234 Binary files /dev/null and b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.uasset differ diff --git a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.uasset b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.uasset similarity index 84% rename from Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.uasset rename to Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.uasset index b3ca9912c..cc410e195 100644 Binary files a/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.uasset and b/Content/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.uasset differ diff --git a/Content/BP/DataAsset/Unit/EnemyUnit/Stage2/DA_SkeletonGolem.uasset b/Content/BP/DataAsset/Unit/EnemyUnit/Stage2/DA_SkeletonGolem.uasset index 14cfd1c6f..c472e0fab 100644 Binary files a/Content/BP/DataAsset/Unit/EnemyUnit/Stage2/DA_SkeletonGolem.uasset and b/Content/BP/DataAsset/Unit/EnemyUnit/Stage2/DA_SkeletonGolem.uasset differ diff --git a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_GhostUnit.uasset b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_GhostUnit.uasset index 5a2c42595..2fb17caf6 100644 Binary files a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_GhostUnit.uasset and b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_GhostUnit.uasset differ diff --git a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_RogueUnit.uasset b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_RogueUnit.uasset index 9f79272df..8680d5f41 100644 Binary files a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_RogueUnit.uasset and b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_RogueUnit.uasset differ diff --git a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_WarriorUnit.uasset b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_WarriorUnit.uasset index 1de2615f9..0e694f436 100644 Binary files a/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_WarriorUnit.uasset and b/Content/BP/DataAsset/Unit/EnemyUnit/Stage3/DA_Skeleton_WarriorUnit.uasset differ diff --git a/Content/BP/DataAsset/Unit/PlayerUnit/DA_TestKnightPlayerUnit.uasset b/Content/BP/DataAsset/Unit/PlayerUnit/DA_TestKnightPlayerUnit.uasset index 8c2bdc732..169afefc1 100644 Binary files a/Content/BP/DataAsset/Unit/PlayerUnit/DA_TestKnightPlayerUnit.uasset and b/Content/BP/DataAsset/Unit/PlayerUnit/DA_TestKnightPlayerUnit.uasset differ diff --git a/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel.uasset b/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel.uasset new file mode 100644 index 000000000..dc446591b Binary files /dev/null and b/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel.uasset differ diff --git a/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel1.uasset b/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel1.uasset deleted file mode 100644 index 8f6c99283..000000000 Binary files a/Content/BP/Obstacle/BP_Barrel_ExplosionGimmickModel1.uasset and /dev/null differ diff --git a/Content/BP/Pawn/Player/BP_MagePlayerUnit.uasset b/Content/BP/Pawn/Player/BP_MagePlayerUnit.uasset index f1b490f87..02fc64962 100644 Binary files a/Content/BP/Pawn/Player/BP_MagePlayerUnit.uasset and b/Content/BP/Pawn/Player/BP_MagePlayerUnit.uasset differ diff --git a/Content/BP/Pawn/Player/BP_RoguePlayerUnit.uasset b/Content/BP/Pawn/Player/BP_RoguePlayerUnit.uasset index 576986bd7..6fe56173d 100644 Binary files a/Content/BP/Pawn/Player/BP_RoguePlayerUnit.uasset and b/Content/BP/Pawn/Player/BP_RoguePlayerUnit.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_BlessingOfTime.uasset b/Content/BP/ReleaseIcons/T_Beta15_BlessingOfTime.uasset new file mode 100644 index 000000000..6fc37796e Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_BlessingOfTime.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_BrokenClock.uasset b/Content/BP/ReleaseIcons/T_Beta15_BrokenClock.uasset new file mode 100644 index 000000000..36cf741c9 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_BrokenClock.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_Cheat.uasset b/Content/BP/ReleaseIcons/T_Beta15_Cheat.uasset new file mode 100644 index 000000000..4ff491616 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_Cheat.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_HourglassTurn.uasset b/Content/BP/ReleaseIcons/T_Beta15_HourglassTurn.uasset new file mode 100644 index 000000000..301c3ed63 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_HourglassTurn.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_Inkpot.uasset b/Content/BP/ReleaseIcons/T_Beta15_Inkpot.uasset new file mode 100644 index 000000000..738c84037 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_Inkpot.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_MagicHat.uasset b/Content/BP/ReleaseIcons/T_Beta15_MagicHat.uasset new file mode 100644 index 000000000..402969c16 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_MagicHat.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_TickTock.uasset b/Content/BP/ReleaseIcons/T_Beta15_TickTock.uasset new file mode 100644 index 000000000..b00b9096c Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_TickTock.uasset differ diff --git a/Content/BP/ReleaseIcons/T_Beta15_TimeAcceleration.uasset b/Content/BP/ReleaseIcons/T_Beta15_TimeAcceleration.uasset new file mode 100644 index 000000000..7a2c90705 Binary files /dev/null and b/Content/BP/ReleaseIcons/T_Beta15_TimeAcceleration.uasset differ diff --git a/Content/Localization/Game/Game.manifest b/Content/Localization/Game/Game.manifest index 7c451321c..fb43208c7 100644 Binary files a/Content/Localization/Game/Game.manifest and b/Content/Localization/Game/Game.manifest differ diff --git a/Content/Localization/Game/en/Game.archive b/Content/Localization/Game/en/Game.archive index 5876e7c13..f043505ae 100644 Binary files a/Content/Localization/Game/en/Game.archive and b/Content/Localization/Game/en/Game.archive differ diff --git a/Content/Localization/Game/en/Game.locres b/Content/Localization/Game/en/Game.locres index 8c7127e5c..2a34bb299 100644 Binary files a/Content/Localization/Game/en/Game.locres and b/Content/Localization/Game/en/Game.locres differ diff --git a/Content/Localization/Game/en/Game.po b/Content/Localization/Game/en/Game.po index 90348da52..f1cc569be 100644 --- a/Content/Localization/Game/en/Game.po +++ b/Content/Localization/Game/en/Game.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: Game\n" -"POT-Creation-Date: 2026-09-20 19:15\n" -"PO-Revision-Date: 2026-09-20 19:15\n" +"POT-Creation-Date: 2026-09-24 07:56\n" +"PO-Revision-Date: 2026-09-24 07:56\n" "Language-Team: \n" "Language: en\n" "MIME-Version: 1.0\n" @@ -578,49 +578,91 @@ msgstr "Lesser Mana Stone" #: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mDescription msgctxt ",A49118234BDFD14414CA899AC9101F44" msgid "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the start of combat, grants yourself 3 stacks of Control Immunity." #. Key: 9D84487840C81B5E8E421AB52FDCB802 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mName msgctxt ",9D84487840C81B5E8E421AB52FDCB802" msgid "๊ฐ์„ฑ ์†Œ๊ธˆ" -msgstr "๊ฐ์„ฑ ์†Œ๊ธˆ" +msgstr "Smelling Salts" #. Key: 23527D6E4FBB2651103240BFABAB46B2 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mDescription #: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mDescription msgctxt ",23527D6E4FBB2651103240BFABAB46B2" msgid "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the end of your turn, if you did not move during that turn, grants yourself 2 stacks of Forced Movement Immunity." #. Key: 3CD32F654A03B4250F12C3AE59417F4F #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mName msgctxt ",3CD32F654A03B4250F12C3AE59417F4F" msgid "๋„์ฟจ ๋ฟŒ๋ฆฌ" -msgstr "๋„์ฟจ ๋ฟŒ๋ฆฌ" +msgstr "Vine Root" #. Key: 864CA6C7435AD98CC59B6DA260478C49 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mDescription #: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mDescription msgctxt ",864CA6C7435AD98CC59B6DA260478C49" -msgid "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the end of your turn, if your HP is at or below 50%, grants yourself 2 stacks of Weakening Immunity." #. Key: 0930ED7244258EE0992F9A9E38282B80 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mName msgctxt ",0930ED7244258EE0992F9A9E38282B80" msgid "์ง„ํ†ต์ œ" -msgstr "์ง„ํ†ต์ œ" +msgstr "Painkiller" + +#. Key: 73821AC74148829F555B3C819627C769 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mDescription +msgctxt ",73821AC74148829F555B3C819627C769" +msgid "ํ„ด ์‹œ์ž‘ ์‹œ, 3ํšŒ ์งธ๋ผ๋ฉด ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 1 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the start of every third turn, reduces skill cooldowns by 1." + +#. Key: DE557EE74760245C2CFE54BBC57D95A1 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mName +msgctxt ",DE557EE74760245C2CFE54BBC57D95A1" +msgid "๊ณ ์žฅ๋‚œ ์‹œ๊ณ„" +msgstr "Broken Clock" + +#. Key: 4A3030494AD8D63422112FB8F6E9C5CC +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mDescription +msgctxt ",4A3030494AD8D63422112FB8F6E9C5CC" +msgid "ํšจ๊ณผ ์ ์šฉ ์ข…๋ฃŒ ์‹œ, ๋Œ€์ƒ์˜ ์ฒด๋ ฅ์ด 0์ดํ•˜๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด, ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 3 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "After an effect is applied, if the target has 0 HP or less, reduces skill cooldowns by 3." + +#. Key: A62C7D644B3A487D97CB0EBFBFE6A0EF +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mName +msgctxt ",A62C7D644B3A487D97CB0EBFBFE6A0EF" +msgid "๋งˆ๋ฒ• ๋ชจ์ž" +msgstr "Magic Hat" + +#. Key: F68A888542FCB383C28DE182180747B5 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mDescription +msgctxt ",F68A888542FCB383C28DE182180747B5" +msgid "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, 5ํšŒ ์งธ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 1 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "On every fifth skill use, reduces skill cooldowns by 1." + +#. Key: 8DE9EEFB442237936C8C2D865CC0CC1C +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mName +msgctxt ",8DE9EEFB442237936C8C2D865CC0CC1C" +msgid "์ž‰ํฌ๋ณ‘" +msgstr "Inkpot" #. Key: 79458D0F4B162D84BC01A59F3BA287F6 #. SourceLocation: /Game/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.DA_Barrel_ExplosionGimmick.mDisplayName #: /Game/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.DA_Barrel_ExplosionGimmick.mDisplayName msgctxt ",79458D0F4B162D84BC01A59F3BA287F6" -msgid "ํ™”์•ฝํ†ต" -msgstr "Explosive Barrel" +msgid "Explosion Barrel" +msgstr "Explosion Barrel" #. Key: 54613FF7435635437189C0ACB78087F7 #. SourceLocation: /Game/BP/DataAsset/CombatTargetObstacle/DA_BlackHoleTotemGimmick.DA_BlackHoleTotemGimmick.mDisplayName @@ -704,7 +746,7 @@ msgstr "Ghoul's Fury" #: /Game/BP/DataAsset/Equipment/DA_Equipment_A002_RottenRegeneration.DA_Equipment_A002_RottenRegeneration.mDescription msgctxt ",7F3E1DDD40324EABB4ED4FB8637EEC5D" msgid "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, ์ฒด๋ ฅ์„ 10 ํšŒ๋ณตํ•ฉ๋‹ˆ๋‹ค.\r\n๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." -msgstr "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, ์ฒด๋ ฅ์„ 10 ํšŒ๋ณตํ•ฉ๋‹ˆ๋‹ค.\r\n๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgstr "Restores 10 HP when using a skill.\r\nImmune to Stun and Root." #. Key: 7D8B51E24AF8D178D285F588B53429E1 #. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A002_RottenRegeneration.DA_Equipment_A002_RottenRegeneration.mName @@ -760,14 +802,28 @@ msgstr "Jack's Scythe" #: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mDescription msgctxt ",340563DF4DE492C006C25F90B9747773" msgid "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." -msgstr "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." +msgstr "Cannot be forcibly moved." #. Key: CC4CBD8B43E0D4117D16FD89293B1F0C #. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mName #: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mName msgctxt ",CC4CBD8B43E0D4117D16FD89293B1F0C" msgid "๋ฌด๊ฑฐ์›€" -msgstr "๋ฌด๊ฑฐ์›€" +msgstr "Heavy" + +#. Key: 52AC6B4E426F409940C0F3AE4F1A802E +#. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mDescription +#: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mDescription +msgctxt ",52AC6B4E426F409940C0F3AE4F1A802E" +msgid "์ƒํƒœ์ด์ƒ์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgstr "Immune to status ailments." + +#. Key: BEEEFCF9486186C7F17380981CFFA37C +#. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mName +#: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mName +msgctxt ",BEEEFCF9486186C7F17380981CFFA37C" +msgid "์œ ๋ น" +msgstr "Ghost" #. Key: 65D880F245C83280B41946BD97A388DF #. SourceLocation: /Game/BP/DataAsset/Obstacle/Common/DA_EmptyObstacle.DA_EmptyObstacle.mDisplayName @@ -1446,21 +1502,42 @@ msgstr "Gain 2 Exhaustion at the start of combat." #: /Game/BP/DataAsset/Passive/DA_Passive_P043.DA_Passive_P043.mDescription msgctxt ",E232C1A94E258B745579FBBB4A2098D3" msgid "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the start of combat, grants yourself 3 stacks of Control Immunity." #. Key: DF6CCA7B40EA815885DA61943F9EDE6C #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P044.DA_Passive_P044.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_P044.DA_Passive_P044.mDescription msgctxt ",DF6CCA7B40EA815885DA61943F9EDE6C" msgid "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the end of your turn, if you did not move during that turn, grants yourself 2 stacks of Forced Movement Immunity." #. Key: 12CE6CE647BC9466B93D21A554AE7A15 #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P045.DA_Passive_P045.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_P045.DA_Passive_P045.mDescription msgctxt ",12CE6CE647BC9466B93D21A554AE7A15" msgid "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the end of your turn, if your HP is at or below 50%, grants yourself 2 stacks of Weakening Immunity." + +#. Key: B3F1361A43E557DA273C07A0801BCE1D +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P046.DA_Passive_P046.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P046.DA_Passive_P046.mDescription +msgctxt ",B3F1361A43E557DA273C07A0801BCE1D" +msgid "ํ„ด ์‹œ์ž‘ ์‹œ, 3ํšŒ ์งธ๋ผ๋ฉด ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 1 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "At the start of every third turn, reduces skill cooldowns by 1." + +#. Key: CC8B771B450D75FB207E569AD04BD5A8 +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P047.DA_Passive_P047.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P047.DA_Passive_P047.mDescription +msgctxt ",CC8B771B450D75FB207E569AD04BD5A8" +msgid "ํšจ๊ณผ ์ ์šฉ ์ข…๋ฃŒ ์‹œ, ๋Œ€์ƒ์˜ ์ฒด๋ ฅ์ด 0์ดํ•˜๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด, ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 3 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "After an effect is applied, if the target has 0 HP or less, reduces skill cooldowns by 3." + +#. Key: 7CB1C2D44F426340E0640CA290DA9F9D +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P048.DA_Passive_P048.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P048.DA_Passive_P048.mDescription +msgctxt ",7CB1C2D44F426340E0640CA290DA9F9D" +msgid "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, 5ํšŒ ์งธ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์Šคํ‚ฌ ์žฌ์‚ฌ์šฉ ๋Œ€๊ธฐ์‹œ๊ฐ„์ด 1 ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค." +msgstr "On every fifth skill use, reduces skill cooldowns by 1." #. Key: 2DC3489240D5807EBE56018D55C41684 #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_ReceivingEffect_Defense_3.DA_Passive_ReceivingEffect_Defense_3.mDescription @@ -1572,14 +1649,21 @@ msgstr "When hit, gain 5 Armor." #: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P005_Heavy.DA_MonsterPassive_P005_Heavy.mDescription msgctxt ",A8C71BE242679B3126E09CBCA88CDBBB" msgid "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." -msgstr "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." +msgstr "Cannot be forcibly moved." #. Key: 65A95708457ABC11C2B96E981982B092 #. SourceLocation: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P006_NoBrain.DA_MonsterPassive_P006_NoBrain.mDescription #: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P006_NoBrain.DA_MonsterPassive_P006_NoBrain.mDescription msgctxt ",65A95708457ABC11C2B96E981982B092" msgid "๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." -msgstr "๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgstr "Immune to Stun and Root." + +#. Key: E777B96E4C7ABDE94B11C9A6EC22A628 +#. SourceLocation: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.DA_MonsterPassive_P007_Ghost.mDescription +#: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.DA_MonsterPassive_P007_Ghost.mDescription +msgctxt ",E777B96E4C7ABDE94B11C9A6EC22A628" +msgid "์ƒํƒœ์ด์ƒ์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgstr "Immune to status ailments." #. Key: DAF8C7E3429395E9A134439F0A52ADA9 #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Attack_Common_CoveringFire.DA_Common_Attack_Common_CoveringFire.mName @@ -1644,6 +1728,13 @@ msgctxt ",4A6D37CC418F089541EBF19E45A336C8" msgid "ํ™”์ดํŠธํ™€" msgstr "White Hole" +#. Key: 8B8C71E047C12CB42A991DA6C6570E46 +#. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.DA_Common_Move_Rare_Leap.mName +#: /Game/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.DA_Common_Move_Rare_Leap.mName +msgctxt ",8B8C71E047C12CB42A991DA6C6570E46" +msgid "๋„์•ฝ" +msgstr "Leap" + #. Key: F742548B49BE186CCE49D18FA518B68E #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Common_FancyFootwork.DA_Common_Spell_Common_FancyFootwork.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Common_FancyFootwork.DA_Common_Spell_Common_FancyFootwork.mName @@ -1679,6 +1770,13 @@ msgctxt ",61086B4E48A408A8A7A9D481D487FF9E" msgid "๊ฐ•ํ™”" msgstr "Fortification" +#. Key: 9F7762A64BEC537C13801EB53598C455 +#. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.DA_Common_Spell_Epic_HourglassTurn.mName +#: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.DA_Common_Spell_Epic_HourglassTurn.mName +msgctxt ",9F7762A64BEC537C13801EB53598C455" +msgid "๋ชจ๋ž˜ ์‹œ๊ณ„ ๋Œ๋ฆฌ๊ธฐ" +msgstr "Turn the Hourglass" + #. Key: 0D0C22BF4AF123F5F79971825460A31E #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_Move.DA_Common_Spell_Epic_Move.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_Move.DA_Common_Spell_Epic_Move.mName @@ -1691,7 +1789,7 @@ msgstr "Move" #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Rare_Passion.DA_Common_Spell_Rare_Passion.mName msgctxt ",60A454584E4B3F31292ADBA2C8D730C5" msgid "์—ด์ •" -msgstr "์—ด์ •" +msgstr "Passion" #. Key: BB9E52CD456ECEDC18C1D895C1230BA7 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage1/Eagle/DA_Eagle_Attack.DA_Eagle_Attack.mName @@ -1712,7 +1810,7 @@ msgstr "Eye Peck" #: /Game/BP/DataAsset/Skill/Enemy/Stage1/Eagle/DA_Eagle_Fly.DA_Eagle_Fly.mName msgctxt ",942E244C4432DDB5B182CC8D21CCA9B1" msgid "๋‚ ๊ธฐ" -msgstr "๋‚ ๊ธฐ" +msgstr "Fly" #. Key: 8429CE8B42B9BDED4B645B89BF083AE3 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage1/Eagle/DA_Eagle_WindyWing.DA_Eagle_WindyWing.mName @@ -1915,7 +2013,7 @@ msgstr "Blade Wind" #: /Game/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.DA_HatchetBird_Move_Fly.mName msgctxt ",F2D2DBB74B5C38278EE7C784C2EB8B6B" msgid "๋‚ ๊ธฐ" -msgstr "๋‚ ๊ธฐ" +msgstr "Fly" #. Key: 78242B044347011D203F1AAC7A9A411E #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Spell_Haste.DA_HatchetBird_Spell_Haste.mName @@ -2001,6 +2099,13 @@ msgctxt ",B40FAB4B4B345D7656487E93BF60A75B" msgid "ํฌํšจ" msgstr "Howl" +#. Key: 17ED0AA54BFC96200BC847942A70A1A3 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.DA_Skeleton_Golem_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.DA_Skeleton_Golem_ImpactLeap.mName +msgctxt ",17ED0AA54BFC96200BC847942A70A1A3" +msgid "์ถฉ๊ฒฉ ๋„์•ฝ" +msgstr "Impact Leap" + #. Key: 0936ABD04F5E80223644A0834B9E8244 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_Kick.DA_Skeleton_Golem_Kick.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_Kick.DA_Skeleton_Golem_Kick.mName @@ -2104,21 +2209,21 @@ msgstr "Offering" #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Boo.DA_Ghost_Boo.mName msgctxt ",965DED1D41B83DA585D40382393D29C5" msgid "์šฐ์šฐ" -msgstr "์šฐ์šฐ" +msgstr "Boo" #. Key: 75BDB9DD45EE48005EE6719FF551D909 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Sob.DA_Ghost_Sob.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Sob.DA_Ghost_Sob.mName msgctxt ",75BDB9DD45EE48005EE6719FF551D909" msgid "ํ๋А๋‚Œ" -msgstr "ํ๋А๋‚Œ" +msgstr "Sob" #. Key: D5DBCB8A481C46576E6D2EA44244CA22 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.DA_Ghost_Teleport.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.DA_Ghost_Teleport.mName msgctxt ",D5DBCB8A481C46576E6D2EA44244CA22" msgid "ํ…”๋ ˆํฌํŠธ" -msgstr "ํ…”๋ ˆํฌํŠธ" +msgstr "Teleport" #. Key: 58B9886F4D5F9300A1EAD1B45B59F4E8 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghoul/DA_Ghoul_Attack_Bite.DA_Ghoul_Attack_Bite.mName @@ -2253,6 +2358,13 @@ msgctxt ",976B1CA94EF59B2D0BC609B088490B5A" msgid "๋ชจ๋ž˜ ๋ฟŒ๋ฆฌ๊ธฐ" msgstr "Sand Toss" +#. Key: 1E6BDAB44BCFA585540C538EFD1837C5 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.DA_Skeleton_Rogue_Move_FlashStep.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.DA_Skeleton_Rogue_Move_FlashStep.mName +msgctxt ",1E6BDAB44BCFA585540C538EFD1837C5" +msgid "์ˆœ๋ณด" +msgstr "Flash Step" + #. Key: 3272345B4A1DDFAB9999618F1B40E8E4 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Attack_PushAttack.DA_Skeleton_Warrior_Attack_PushAttack.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Attack_PushAttack.DA_Skeleton_Warrior_Attack_PushAttack.mName @@ -2274,6 +2386,13 @@ msgctxt ",230DAABE477BCCFB6C59D78908AF7734" msgid "๊ฐ•ํƒ€" msgstr "Heavy Strike" +#. Key: 54E9E2A64A3EF00F2D73DFBD3789F9B0 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.DA_Skeleton_Warrior_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.DA_Skeleton_Warrior_ImpactLeap.mName +msgctxt ",54E9E2A64A3EF00F2D73DFBD3789F9B0" +msgid "์ถฉ๊ฒฉ ๋„์•ฝ" +msgstr "Impact Leap" + #. Key: 109D3ECD4076880A38CFE69DF880E876 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Spell_Rage.DA_Skeleton_Warrior_Spell_Rage.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Spell_Rage.DA_Skeleton_Warrior_Spell_Rage.mName @@ -2435,6 +2554,13 @@ msgctxt ",3FC2019A4ACE262F9429DABA566D1FBB" msgid "ํ›จ์œˆ๋“œ" msgstr "Whirlwind" +#. Key: BD8EF739457917EED9FBD0A3BDAAAFAC +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.DA_Barbarian_Move_Epic_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.DA_Barbarian_Move_Epic_ImpactLeap.mName +msgctxt ",BD8EF739457917EED9FBD0A3BDAAAFAC" +msgid "์ถฉ๊ฒฉ ๋„์•ฝ" +msgstr "Impact Leap" + #. Key: 0FB44FE6446A80EE3357BDB38EA9BE89 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Common_Fear.DA_Barbarian_Spell_Common_Fear.mName #: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Common_Fear.DA_Barbarian_Spell_Common_Fear.mName @@ -2468,7 +2594,7 @@ msgstr "Meditation" #: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Epic_Unstoppable.DA_Barbarian_Spell_Epic_Unstoppable.mName msgctxt ",6AB5F90A406AE9BC57E861ADEA2BE9BB" msgid "์ €์ง€ ๋ถˆ๊ฐ€" -msgstr "์ €์ง€ ๋ถˆ๊ฐ€" +msgstr "Unstoppable" #. Key: 38B4E17042D9CA31297F11B6B6515059 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Rare_BloodWall.DA_Barbarian_Spell_Rare_BloodWall.mName @@ -2582,6 +2708,13 @@ msgctxt ",930AA6CD482E22148F40F7A82D524A46" msgid "๋…๊ตฌ๋ฆ„" msgstr "Poison Cloud" +#. Key: 4571C9B445366B946B1C8A859D10B206 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.DA_Druid_Spell_Epic_BlessingOfTime.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.DA_Druid_Spell_Epic_BlessingOfTime.mName +msgctxt ",4571C9B445366B946B1C8A859D10B206" +msgid "์‹œ๊ฐ„์˜ ์ถ•๋ณต" +msgstr "Blessing of Time" + #. Key: 79F9D5E448B105C5182AAEB5B231991B #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_FlashFruit.DA_Druid_Spell_Epic_FlashFruit.mName #: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_FlashFruit.DA_Druid_Spell_Epic_FlashFruit.mName @@ -2629,7 +2762,7 @@ msgstr "Faith" #: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Rare_ImmunityBoost.DA_Druid_Spell_Rare_ImmunityBoost.mName msgctxt ",4216869C40F1CBC51B3607BECD01C719" msgid "๋ฉด์—ญ๋ ฅ ์ฆ์ง„" -msgstr "๋ฉด์—ญ๋ ฅ ์ฆ์ง„" +msgstr "Immunity Boost" #. Key: 1CBF9AB042E43F5FF8B6678C37D00A07 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Rare_Prayer.DA_Druid_Spell_Rare_Prayer.mName @@ -2743,6 +2876,13 @@ msgctxt ",8CD748794A959830CC1BC28924CD3B40" msgid "ํšŒ์ „ ๋ฒ ๊ธฐ" msgstr "Spinning Slash" +#. Key: FC30220B45CA3F19A4DAA1AED3661E8C +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.DA_Knight_Move_Common_GuardianCharge.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.DA_Knight_Move_Common_GuardianCharge.mName +msgctxt ",FC30220B45CA3F19A4DAA1AED3661E8C" +msgid "์ˆ˜ํ˜ธ ๋Œ๊ฒฉ" +msgstr "Guardian Charge" + #. Key: 0EE1C53A48F082065A5CD49A20F292F5 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Spell_Common_Block.DA_Knight_Spell_Common_Block.mName #: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Spell_Common_Block.DA_Knight_Spell_Common_Block.mName @@ -2925,6 +3065,13 @@ msgctxt "SkillNames,Mage.ThunderStorm" msgid "๋ฒผ๋ฝ ํญํ’" msgstr "Thunderstorm" +#. Key: 1DDE84294BBC3B614AF52291C0A37F44 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.DA_Mage_Move_Epic_Teleport.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.DA_Mage_Move_Epic_Teleport.mName +msgctxt ",1DDE84294BBC3B614AF52291C0A37F44" +msgid "์ˆœ๊ฐ„์ด๋™" +msgstr "Teleport" + #. Key: F82A1B16498215B98D0F2597C10FC203 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Common_Gust.DA_Mage_Spell_Common_Gust.mName #: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Common_Gust.DA_Mage_Spell_Common_Gust.mName @@ -2960,6 +3107,20 @@ msgctxt ",1B782957494A25B0656C77846DD49EDF" msgid "๋งˆ๋ฒ• ์žฅ๋ฒฝ" msgstr "Magic Barrier" +#. Key: CA4A0FAD49B332EA55F6B1B0FA1B155E +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.DA_Mage_Spell_Epic_TickTock.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.DA_Mage_Spell_Epic_TickTock.mName +msgctxt ",CA4A0FAD49B332EA55F6B1B0FA1B155E" +msgid "๋˜‘๋”ฑ" +msgstr "Tick-Tock" + +#. Key: 0E9A769446391E0EF05A6688B0F63502 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.DA_Mage_Spell_Rare_TimeAcceleration.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.DA_Mage_Spell_Rare_TimeAcceleration.mName +msgctxt ",0E9A769446391E0EF05A6688B0F63502" +msgid "์‹œ๊ฐ„ ๊ฐ€์†" +msgstr "Time Acceleration" + #. Key: A482DF92454637EF78C6CD8BD1922F3E #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Ranger/DA_Ranger_Attack_Common_Disarm.DA_Ranger_Attack_Common_Disarm.mName #: /Game/BP/DataAsset/Skill/Mercenary/Ranger/DA_Ranger_Attack_Common_Disarm.DA_Ranger_Attack_Common_Disarm.mName @@ -3219,6 +3380,20 @@ msgctxt ",E56043D14CD1CA4EA669629BB0BF3634" msgid "์นผ๊ฐˆ๊ธฐ" msgstr "Sharpen Blade" +#. Key: A931024340831279EA06E288356EBEB4 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.DA_Rogue_Move_FlashStep.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.DA_Rogue_Move_FlashStep.mName +msgctxt ",A931024340831279EA06E288356EBEB4" +msgid "์ˆœ๋ณด" +msgstr "Flash Step" + +#. Key: 5213A4FF4FAF6C3E09821791D50F596C +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.DA_Rogue_Spell_Epic_Cheat.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.DA_Rogue_Spell_Epic_Cheat.mName +msgctxt ",5213A4FF4FAF6C3E09821791D50F596C" +msgid "์‚ฌ๊ธฐ" +msgstr "Cheat" + #. Key: D34E45444D8889195424DFADFE72BEDE #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Doping.DA_Rogue_Spell_Epic_Doping.mName #: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Doping.DA_Rogue_Spell_Epic_Doping.mName @@ -3233,13 +3408,6 @@ msgctxt ",4E54F0E849151674F8D78D8820C2A244" msgid "ํšŒํ”ผ" msgstr "Evasion" -#. Key: 60314B094FDC9F7EDB24FEB950738DB9 -#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.DA_Rogue_Spell_Epic_SleightOfHand.mName -#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.DA_Rogue_Spell_Epic_SleightOfHand.mName -msgctxt ",60314B094FDC9F7EDB24FEB950738DB9" -msgid "์†๊ธฐ์ˆ " -msgstr "Sleight of Hand" - #. Key: Rogue.LegSweep #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_LegSweep.DA_Rogue_Spell_Rare_LegSweep.mName #: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_LegSweep.DA_Rogue_Spell_Rare_LegSweep.mName @@ -3254,6 +3422,13 @@ msgctxt ",BD3F00D5461E9872A817BC92E6547246" msgid "๋ชจ๋ž˜ ๋ฟŒ๋ฆฌ๊ธฐ" msgstr "Sand Toss" +#. Key: 60314B094FDC9F7EDB24FEB950738DB9 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.DA_Rogue_Spell_Rare_SleightOfHand.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.DA_Rogue_Spell_Rare_SleightOfHand.mName +msgctxt ",60314B094FDC9F7EDB24FEB950738DB9" +msgid "์†๊ธฐ์ˆ " +msgstr "Sleight of Hand" + #. Key: AE209B3847CEC8895AC92884CFC83A76 #. SourceLocation: /Game/BP/DataAsset/Unit/EnemyUnit/Stage1/DA_EagleUnit.DA_EagleUnit.mDisplayName #: /Game/BP/DataAsset/Unit/EnemyUnit/Stage1/DA_EagleUnit.DA_EagleUnit.mDisplayName @@ -6433,8 +6608,8 @@ msgid "{0}\n{1}" msgstr "{0}\n{1}" #. Key: CurrentCombatArea -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(1393) -#: Source/P_RD/GameMode/CombatGameMode.cpp(1393) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(1405) +#: Source/P_RD/GameMode/CombatGameMode.cpp(1405) msgctxt "CombatGameMode,CurrentCombatArea" msgid "ํ˜„์žฌ ์ „ํˆฌ ์ง€์—ญ" msgstr "Current Combat Area" @@ -6468,43 +6643,43 @@ msgid "EMPTY" msgstr "EMPTY" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2294) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2294) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2306) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2306) msgctxt "CombatGameMode,ArtifactFallbackName" msgid "Artifact {0}" msgstr "Artifact {0}" #. Key: MovedTiles -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2496) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2496) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2508) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2508) msgctxt "CombatFloatingLog,MovedTiles" msgid "์ด๋™ {0}์นธ" msgstr "Move {0} tiles" #. Key: EnteredBoard -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2503) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2503) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2515) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2515) msgctxt "CombatFloatingLog,EnteredBoard" msgid "๋“ฑ์žฅ" msgstr "Entrance" #. Key: ExitedBoard -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2510) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2510) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2522) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2522) msgctxt "CombatFloatingLog,ExitedBoard" msgid "์ „ํˆฌ๋ถˆ๋Šฅ" msgstr "Defeated" #. Key: VictoryRewardTitle -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2777) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2777) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2789) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2789) msgctxt "CombatGameMode,VictoryRewardTitle" msgid "์ „ํˆฌ ๋ณด์ƒ" msgstr "Battle Rewards" #. Key: UnknownRewardMercenary -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2820) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2820) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2832) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2832) msgctxt "CombatGameMode,UnknownRewardMercenary" msgid "Mercenary" msgstr "Mercenary" @@ -6649,125 +6824,146 @@ msgctxt "FrontendGameMode,RangerDesc" msgid "๋จผ ๊ฑฐ๋ฆฌ์—์„œ ํ™œ๋กœ ์ ์„ ์†Ž์•„๋‚ด๋Š” ๋ช…์‚ฌ์ˆ˜.\n๊ฐ€๊นŒ์ด ๋ถ™๊ธฐ ์ „์— ์Šน๋ถ€๋ฅผ ๋‚ธ๋‹ค." msgstr "A sharpshooter who picks off enemies from afar with a bow.\nSettles the fight before they can close in." +#. Key: PartyArtifact +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(1001) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(1001) +msgctxt "RoomGameModeBase,PartyArtifact" +msgid "Party-wide effect" +msgstr "Party-wide effect" + #. Key: MonsterRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(142) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(142) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) msgctxt "RoomGameModeBase,MonsterRoomTitle" msgid "Monster" msgstr "Monster" #. Key: EliteRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) msgctxt "RoomGameModeBase,EliteRoomTitle" msgid "Elite" msgstr "Elite" #. Key: BossRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) msgctxt "RoomGameModeBase,BossRoomTitle" msgid "Boss" msgstr "Boss" #. Key: ShopRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) msgctxt "RoomGameModeBase,ShopRoomTitle" msgid "Shop" msgstr "Shop" #. Key: TreasureRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) msgctxt "RoomGameModeBase,TreasureRoomTitle" msgid "Treasure" msgstr "Treasure" #. Key: UnknownRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(154) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(154) msgctxt "RoomGameModeBase,UnknownRoomTitle" msgid "Unknown" msgstr "Unknown" #. Key: MapRoomDescription -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(163) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(163) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(165) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(165) msgctxt "RoomGameModeBase,MapRoomDescription" msgid "Row {0}, Column {1}. Next routes: {2}" msgstr "Row {0}, Column {1}. Next routes: {2}" #. Key: StartPointDescription -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(176) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(176) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(178) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(178) msgctxt "RoomGameModeBase,StartPointDescription" msgid "Routes: {0}" msgstr "Routes: {0}" #. Key: RosterJobKnight -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(207) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(207) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) msgctxt "RoomGameModeBase,RosterJobKnight" msgid "๊ธฐ์‚ฌ" msgstr "Knight" #. Key: RosterJobMage -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(208) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(208) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) msgctxt "RoomGameModeBase,RosterJobMage" msgid "๋งˆ๋ฒ•์‚ฌ" msgstr "Mage" #. Key: RosterJobRanger -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) msgctxt "RoomGameModeBase,RosterJobRanger" msgid "๊ถ์ˆ˜" msgstr "Ranger" #. Key: RosterJobRogue -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) msgctxt "RoomGameModeBase,RosterJobRogue" msgid "๋„์ " msgstr "Rogue" #. Key: RosterJobBarbarian -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(213) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(213) msgctxt "RoomGameModeBase,RosterJobBarbarian" msgid "์•ผ๋งŒ์ „์‚ฌ" msgstr "Barbarian" #. Key: RosterJobDruid -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(214) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(214) msgctxt "RoomGameModeBase,RosterJobDruid" msgid "๋“œ๋ฃจ์ด๋“œ" msgstr "Druid" +#. Key: SaveAndExitFailed +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(399) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(399) +msgctxt "RoomGameModeBase,SaveAndExitFailed" +msgid "์ €์žฅ ํ›„ ์ข…๋ฃŒ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." +msgstr "Failed to save and exit." + +#. Key: AbandonRunFailed +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(400) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(400) +msgctxt "RoomGameModeBase,AbandonRunFailed" +msgid "๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." +msgstr "Failed to abandon the run." + +#. Key: SavingRun +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(411) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(411) +msgctxt "RoomGameModeBase,SavingRun" +msgid "์ €์žฅ ์ค‘..." +msgstr "Saving..." + #. Key: StartPointTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(554) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(554) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(626) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(626) msgctxt "RoomGameModeBase,StartPointTitle" msgid "Start" msgstr "Start" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(925) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(925) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(997) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(997) msgctxt "RoomGameModeBase,ArtifactFallbackName" msgid "Artifact {0}" msgstr "Artifact {0}" -#. Key: PartyArtifact -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(929) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(929) -msgctxt "RoomGameModeBase,PartyArtifact" -msgid "Party-wide effect" -msgstr "Party-wide effect" - #. Key: MercenaryLevel #. SourceLocation: Source/P_RD/GameMode/ShopGameMode.cpp(325) #: Source/P_RD/GameMode/ShopGameMode.cpp(325) @@ -7070,281 +7266,274 @@ msgid "์žŠํžŒ ์„ฑ์ฑ„" msgstr "Forgotten Citadel" #. Key: MercenaryMoveSummary -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2051) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2051) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2044) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2044) msgctxt "CombatLayoutHUD,MercenaryMoveSummary" msgid "์ด๋™" msgstr "Move" #. Key: PartySlotEmpty -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2120) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2120) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2113) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2113) msgctxt "CombatLayoutHUD,PartySlotEmpty" msgid "๋นˆ ์ž๋ฆฌ" msgstr "Empty Slot" #. Key: PreviousTurns -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2567) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2567) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2560) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2560) msgctxt "CombatLayoutHUD,PreviousTurns" msgid "์ด์ „ ์ฐจ๋ก€ ๋ณด๊ธฐ" msgstr "View previous turns" #. Key: NextTurns -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2569) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2569) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2562) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2562) msgctxt "CombatLayoutHUD,NextTurns" msgid "๋‹ค์Œ ์ฐจ๋ก€ ๋ณด๊ธฐ" msgstr "View upcoming turns" #. Key: Move -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2682) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2682) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2675) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2675) msgctxt "CombatLayoutHUD,Move" msgid "์ด๋™" msgstr "Move" #. Key: MoveCostPerTileShort -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2683) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2683) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2676) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2676) msgctxt "CombatLayoutHUD,MoveCostPerTileShort" msgid "1/์นธ" msgstr "1/tile" #. Key: MoveCost -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2684) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2684) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2677) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2677) msgctxt "CombatLayoutHUD,MoveCost" msgid "AP 1/์นธ" msgstr "AP 1/tile" #. Key: SkillCost -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2728) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2728) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2721) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2721) msgctxt "CombatLayoutHUD,SkillCost" msgid "AP {0}" msgstr "AP {0}" #. Key: SkillCardDamage -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2780) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2780) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2773) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2773) msgctxt "CombatLayoutHUD,SkillCardDamage" msgid "ํ”ผํ•ด {0}~{1}" msgstr "DMG {0}~{1}" #. Key: CombatObjectiveRemaining -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2946) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2946) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2939) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2939) msgctxt "CombatLayoutHUD,CombatObjectiveRemaining" msgid "๋ชจ๋“  ์  ์ฒ˜์น˜ โ€” ๋‚จ์€ ์  {0}" msgstr "Defeat all enemies โ€” {0} remaining" #. Key: MercenaryInventoryPageTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2972) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2972) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2965) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2965) msgctxt "CombatHUD,MercenaryInventoryPageTitle" msgid "์ธ๋ฒคํ† ๋ฆฌ" msgstr "Inventory" #. Key: MercenaryPageTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2973) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2973) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2966) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2966) msgctxt "CombatHUD,MercenaryPageTitle" msgid "์šฉ๋ณ‘" msgstr "Mercenaries" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3004) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3004) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2997) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2997) msgctxt "CombatHUD,ArtifactFallbackName" msgid "Artifact" msgstr "Artifact" #. Key: BattleStart -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3445) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3445) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3438) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3438) msgctxt "CombatAnnouncement,BattleStart" msgid "BATTLE START" msgstr "BATTLE START" #. Key: Round -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3512) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3512) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3505) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3505) msgctxt "CombatAnnouncement,Round" msgid "ROUND {0}" msgstr "ROUND {0}" #. Key: EndTurn -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3844) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3844) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3837) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3837) msgctxt "CombatLayoutHUD,EndTurn" msgid "ํ„ด ์ข…๋ฃŒ" msgstr "End Turn" #. Key: CancelAim -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3847) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3847) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3840) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3840) msgctxt "CombatLayoutHUD,CancelAim" msgid "์ทจ์†Œ" msgstr "Cancel" -#. Key: SavingRun -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4890) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4890) -msgctxt "CombatLayoutHUD,SavingRun" -msgid "์ €์žฅ ์ค‘..." -msgstr "Saving..." - #. Key: SaveAndExitFailed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4949) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4949) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4874) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4874) msgctxt "CombatLayoutHUD,SaveAndExitFailed" msgid "์ €์žฅ ํ›„ ์ข…๋ฃŒ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." msgstr "Failed to save and exit." #. Key: AbandonRunFailed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4973) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4973) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4898) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4898) msgctxt "CombatLayoutHUD,AbandonRunFailed" msgid "๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." msgstr "Failed to abandon the run." #. Key: MonsterTabSkills -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5657) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5657) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5571) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5571) msgctxt "CombatLayoutHUD,MonsterTabSkills" msgid "์Šคํ‚ฌ" msgstr "Skills" #. Key: MonsterTabNoSkills -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5658) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5658) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5572) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5572) msgctxt "CombatLayoutHUD,MonsterTabNoSkills" msgid "์Šคํ‚ฌ ยท ์—†์Œ" msgstr "Skills ยท None" #. Key: MonsterEquipmentHeading -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5736) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5736) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5650) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5650) msgctxt "CombatLayoutHUD,MonsterEquipmentHeading" msgid "์žฅ๋น„ ยท ๋ˆŒ๋Ÿฌ์„œ ์ž์„ธํžˆ" msgstr "Equipment ยท Tap for details" #. Key: MonsterEquipmentEmpty -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5737) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5737) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5651) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5651) msgctxt "CombatLayoutHUD,MonsterEquipmentEmpty" msgid "์žฅ๋น„ ยท ์—†์Œ" msgstr "Equipment ยท None" #. Key: UnitDetailLevel -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6302) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6302) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6216) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6216) msgctxt "CombatLayoutHUD,UnitDetailLevel" msgid "Lv.{0}" msgstr "Lv.{0}" #. Key: UnitDetailAlly -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6307) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6307) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6221) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6221) msgctxt "CombatLayoutHUD,UnitDetailAlly" msgid "์•„๊ตฐ" msgstr "Ally" #. Key: UnitDetailEnemy -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6308) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6308) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6222) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6222) msgctxt "CombatLayoutHUD,UnitDetailEnemy" msgid "์ " msgstr "Enemy" #. Key: UnitDetailIdentityAndHp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6310) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6310) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6224) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6224) msgctxt "CombatLayoutHUD,UnitDetailIdentityAndHp" msgid "{0} ยท {1} ยท HP {2}/{3}" msgstr "{0} ยท {1} ยท HP {2}/{3}" #. Key: UnitDetailWithDefense -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6316) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6316) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6230) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6230) msgctxt "CombatLayoutHUD,UnitDetailWithDefense" msgid "{0} ยท ๋ฐฉ์–ด {1}" msgstr "{0} ยท Defense {1}" #. Key: DetailChipLevel -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6338) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6338) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6252) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6252) msgctxt "CombatLayoutHUD,DetailChipLevel" msgid "๋ ˆ๋ฒจ" msgstr "Level" #. Key: DetailChipHp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6341) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6341) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6255) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6255) msgctxt "CombatLayoutHUD,DetailChipHp" msgid "HP" msgstr "HP" #. Key: DetailChipDefense -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6343) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6343) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6257) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6257) msgctxt "CombatLayoutHUD,DetailChipDefense" msgid "๋ฐฉ์–ด" msgstr "Defense" #. Key: DetailChipSpeed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6345) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6345) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6259) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6259) msgctxt "CombatLayoutHUD,DetailChipSpeed" msgid "์†๋„" msgstr "Speed" #. Key: DetailChipAp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6347) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6347) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6261) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6261) msgctxt "CombatLayoutHUD,DetailChipAp" msgid "AP" msgstr "AP" #. Key: UnitDetailChipCritical -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6348) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6348) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6262) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6262) msgctxt "CombatLayoutHUD,UnitDetailChipCritical" msgid "์น˜๋ช…ํƒ€" msgstr "Crit" #. Key: UnitDetailPassiveLine -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6355) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6355) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6269) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6269) msgctxt "CombatLayoutHUD,UnitDetailPassiveLine" msgid "ยท {0}" msgstr "ยท {0}" #. Key: UnitDetailNoPassives -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6358) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6358) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6272) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6272) msgctxt "CombatLayoutHUD,UnitDetailNoPassives" msgid "ํŒจ์‹œ๋ธŒ ์—†์Œ" msgstr "No passives" #. Key: UnitDetailEnemyThreatLegend -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6364) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6364) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6278) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6278) msgctxt "CombatLayoutHUD,UnitDetailEnemyThreatLegend" msgid "{0}\n\nํŒ์˜ ํ‘œ์‹œ๋Š” ์ด ์ ์ด ํ•œ ํ„ด์— ๋‹ฟ๋Š” ๊ณณ์ด๋‹ค.\nํ…Œ๋‘๋ฆฌ ๋ฐด๋“œ = ์ด๋™ ๋ฒ”์œ„, ์ฑ„์›€ = ๊ณต๊ฒฉ ๋ฒ”์œ„." msgstr "{0}\n\nThe board shows every tile this enemy can reach in one turn.\nBorder band = movement range, fill = attack range." #. Key: MoveDetailTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6692) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6692) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6604) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6604) msgctxt "CombatLayoutHUD,MoveDetailTitle" msgid "์ด๋™" msgstr "Move" #. Key: MoveDetailDescription -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6693) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6693) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6605) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6605) msgctxt "CombatLayoutHUD,MoveDetailDescription" msgid "ํ•œ ์นธ ์˜ฎ๊ธธ ๋•Œ๋งˆ๋‹ค ํ–‰๋™๋ ฅ์„ 1 ์”๋‹ˆ๋‹ค. (์ตœ๋Œ€ {0}์นธ ์ด๋™ ๊ฐ€๋Šฅ)\n\n์ด๋™ํ•  ์นธ์„ ํ„ฐ์น˜ํ•˜์—ฌ ๊ณ ๋ฅธ ํ›„, ๋งˆ์ง€๋ง‰ ์นธ์„ ๋‹ค์‹œ ํ„ฐ์น˜ํ•˜์—ฌ ์ด๋™์„ ํ™•์ •ํ•ฉ๋‹ˆ๋‹ค." msgstr "Moving one tile costs 1 AP. (Up to {0} tiles)\n\nTap a tile to choose a destination, then tap the final tile again to confirm movement." @@ -8505,36 +8694,36 @@ msgid "(mock reward)" msgstr "(mock reward)" #. Key: ChestOpen -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1860) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1860) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1861) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1861) msgctxt "RewardConcept03Widget,ChestOpen" msgid "์ƒ์ž ์—ด๊ธฐ" msgstr "Open Chest" #. Key: ChestOpenHint -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1864) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1864) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1865) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1865) msgctxt "RewardConcept03Widget,ChestOpenHint" msgid "์ƒ์ž๋ฅผ ๋ˆŒ๋Ÿฌ ์—ฌ์„ธ์š”" msgstr "Tap the chest to open it" #. Key: ClaimSelectedOne -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) msgctxt "RewardConcept03Widget,ClaimSelectedOne" msgid "์„ ํƒํ•œ 1๊ฐœ ๋ฐ›๊ธฐ" msgstr "Claim Selected Item" #. Key: Confirm -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) msgctxt "RewardConcept03Widget,Confirm" msgid "ํ™•์ •" msgstr "Confirm" #. Key: SelectedArtifact -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1920) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1920) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1921) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1921) msgctxt "RewardConcept03Widget,SelectedArtifact" msgid "์„ ํƒ๋จ" msgstr "Selected" @@ -9289,197 +9478,197 @@ msgid "Cancel" msgstr "Cancel" #. Key: SkillNoteOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1285) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1285) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1277) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1277) msgctxt "ShopUIWidgetBase,SkillNoteOwned" msgid "{0} ์ „์šฉ ยท ์ด๋ฏธ ๋ณด์œ " msgstr "{0} only ยท Owned" #. Key: SkillNoteOtherJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1288) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1288) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1280) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1280) msgctxt "ShopUIWidgetBase,SkillNoteOtherJob" msgid "{0} ์ „์šฉ ยท ์žฅ์ฐฉ ๋ถˆ๊ฐ€" msgstr "{0} only ยท Cannot equip" #. Key: SkillNoteUnowned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1291) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1291) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1283) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1283) msgctxt "ShopUIWidgetBase,SkillNoteUnowned" msgid "{0} ์ „์šฉ ยท ๋ฏธ๋ณด์œ  ์šฉ๋ณ‘" msgstr "{0} only ยท No mercenary owned" #. Key: SkillNoteCommon -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1297) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1297) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1289) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1289) msgctxt "ShopUIWidgetBase,SkillNoteCommon" msgid "๊ณต์šฉ ์Šคํ‚ฌ" msgstr "Common skill" #. Key: SkillNoteJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1298) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1298) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1290) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1290) msgctxt "ShopUIWidgetBase,SkillNoteJob" msgid "{0} ์ „์šฉ" msgstr "{0} only" #. Key: SoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1573) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1573) msgctxt "ShopUIWidgetBase,SoldOut" msgid "ํ’ˆ์ ˆ" msgstr "Sold Out" #. Key: RailOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1585) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1585) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1577) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1577) msgctxt "ShopUIWidgetBase,RailOwned" msgid "๋ณด์œ " msgstr "Owned" #. Key: RailPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1589) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1589) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) msgctxt "ShopUIWidgetBase,RailPrice" msgid "{0} G" msgstr "{0} G" #. Key: SelectedJobUnitCount -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1683) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1683) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1675) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1675) msgctxt "ShopUIWidgetBase,SelectedJobUnitCount" msgid "{0}/{1}" msgstr "{0}/{1}" #. Key: RestPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1792) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1792) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1784) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1784) msgctxt "ShopUIWidgetBase,RestPrice" msgid "{0} G" msgstr "{0} G" #. Key: RestUsed -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1869) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1869) msgctxt "ShopUIWidgetBase,RestUsed" msgid "ํœด์‹ ์™„๋ฃŒ" msgstr "Rest Complete" #. Key: RestNotAffordable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1881) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1881) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1873) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1873) msgctxt "ShopUIWidgetBase,RestNotAffordable" msgid "๊ณจ๋“œ ๋ถ€์กฑ" msgstr "Not enough Gold" #. Key: RestNow -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1885) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1885) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) msgctxt "ShopUIWidgetBase,RestNow" msgid "ํœด์‹ํ•˜๊ธฐ" msgstr "Rest" #. Key: NoShopItems -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1890) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1890) msgctxt "ShopUIWidgetBase,NoShopItems" msgid "ํŒ๋งค ์ƒํ’ˆ์ด ์—†์Šต๋‹ˆ๋‹ค" msgstr "No items for sale" #. Key: NoSelectedPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) msgctxt "ShopUIWidgetBase,NoSelectedPrice" msgid "-" msgstr "-" #. Key: Unavailable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1914) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1914) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) msgctxt "ShopUIWidgetBase,Unavailable" msgid "๊ตฌ๋งค ๋ถˆ๊ฐ€" msgstr "Unavailable" #. Key: SelectedSoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1951) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1951) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1943) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1943) msgctxt "ShopUIWidgetBase,SelectedSoldOut" msgid "ํ’ˆ์ ˆ" msgstr "Sold Out" #. Key: SelectedPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1952) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1952) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1944) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1944) msgctxt "ShopUIWidgetBase,SelectedPrice" msgid "{0} G" msgstr "{0} G" #. Key: BuySoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1969) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1969) msgctxt "ShopUIWidgetBase,BuySoldOut" msgid "ํ’ˆ์ ˆ" msgstr "Sold Out" #. Key: BuyNotAffordable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1973) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1973) msgctxt "ShopUIWidgetBase,BuyNotAffordable" msgid "๊ณจ๋“œ ๋ถ€์กฑ" msgstr "Not enough Gold" #. Key: BuySelectTarget -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) msgctxt "ShopUIWidgetBase,BuySelectTarget" msgid "๋Œ€์ƒ ์„ ํƒ" msgstr "Select Target" #. Key: BuyAlreadyOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) msgctxt "ShopUIWidgetBase,BuyAlreadyOwned" msgid "์ด๋ฏธ ๋ณด์œ " msgstr "Owned" #. Key: BuyOtherJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1993) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1993) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) msgctxt "ShopUIWidgetBase,BuyOtherJob" msgid "์ง์—… ๋ถˆ์ผ์น˜" msgstr "Wrong job" #. Key: BuyUnownedTarget -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1997) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1997) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) msgctxt "ShopUIWidgetBase,BuyUnownedTarget" msgid "๋ฏธ๋ณด์œ  ์šฉ๋ณ‘" msgstr "No Mercenary Owned" #. Key: EquipSelectedSkill -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2007) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2007) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1999) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1999) msgctxt "ShopUIWidgetBase,EquipSelectedSkill" msgid "์žฅ์ฐฉ" msgstr "Equip" #. Key: ReplaceSelectedSkill -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2008) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2008) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2000) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2000) msgctxt "ShopUIWidgetBase,ReplaceSelectedSkill" msgid "๊ต์ฒด" msgstr "Replace" #. Key: BuySelected -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2012) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2012) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2004) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2004) msgctxt "ShopUIWidgetBase,BuySelected" msgid "๊ตฌ๋งค" msgstr "Buy" #. Key: GoldAmount -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2049) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2049) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2041) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2041) msgctxt "ShopUIWidgetBase,GoldAmount" msgid "{0} G" msgstr "{0} G" @@ -9491,6 +9680,13 @@ msgctxt "ShopUIWidgetBase,Leave" msgid "๋‚˜๊ฐ€๊ธฐ" msgstr "Leave" +#. Key: [{0}] +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2109) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2109) +msgctxt "ShopUIWidgetBase,[{0}]" +msgid "[{0}]" +msgstr "[{0}]" + #. Key: Shop #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(211) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(211) @@ -9498,34 +9694,27 @@ msgctxt "ShopUIWidgetBase,Shop" msgid "์ƒ์ " msgstr "Shop" -#. Key: [{0}] -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2117) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2117) -msgctxt "ShopUIWidgetBase,[{0}]" -msgid "[{0}]" -msgstr "[{0}]" - -#. Key: ArtifactTab -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) -msgctxt "ShopUIWidgetBase,ArtifactTab" -msgid "์•„ํ‹ฐํŒฉํŠธ" -msgstr "Artifacts" - #. Key: Sold Out -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2154) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2154) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2146) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2146) msgctxt "ShopUIWidgetBase,Sold Out" msgid "Sold Out" msgstr "Sold Out" #. Key: {0} G -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2155) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2155) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2147) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2147) msgctxt "ShopUIWidgetBase,{0} G" msgid "{0} G" msgstr "{0} G" +#. Key: ArtifactTab +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) +msgctxt "ShopUIWidgetBase,ArtifactTab" +msgid "์•„ํ‹ฐํŒฉํŠธ" +msgstr "Artifacts" + #. Key: SkillTab #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(219) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(219) @@ -9548,22 +9737,22 @@ msgid "์šฉ๋ณ‘ ๊ณ ์šฉ" msgstr "Hire Mercenaries" #. Key: [{0}] {1} Lv.{2} -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2290) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2290) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2282) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2282) msgctxt "ShopUIWidgetBase,[{0}] {1} Lv.{2}" msgid "[{0}] {1} Lv.{2}" msgstr "[{0}] {1} Lv.{2}" #. Key: S{0}: {1} -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2304) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2304) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2296) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2296) msgctxt "ShopUIWidgetBase,S{0}: {1}" msgid "S{0}: {1}" msgstr "S{0}: {1}" #. Key: - -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2306) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2306) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2298) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2298) msgctxt "ShopUIWidgetBase,-" msgid "-" msgstr "-" @@ -9590,82 +9779,89 @@ msgid "์ธ๋ฒคํ† ๋ฆฌ" msgstr "Inventory" #. Key: ArtifactFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2468) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2468) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2460) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2460) msgctxt "ShopUIWidgetBase,ArtifactFallbackDescription" msgid "ํŒŒํ‹ฐ ์ „์ฒด์— ์ ์šฉ๋˜๋Š” ์•„ํ‹ฐํŒฉํŠธ์ž…๋‹ˆ๋‹ค." msgstr "This Artifact applies to the entire party." #. Key: SkillFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2469) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2469) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2461) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2461) msgctxt "ShopUIWidgetBase,SkillFallbackDescription" msgid "์„ ํƒํ•œ ์šฉ๋ณ‘์˜ ์Šคํ‚ฌ ์Šฌ๋กฏ์— ์žฅ์ฐฉํ•ฉ๋‹ˆ๋‹ค." msgstr "Equips to the selected mercenary's skill slot." #. Key: ArtifactDetailType -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2522) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2522) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2514) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2514) msgctxt "ShopUIWidgetBase,ArtifactDetailType" msgid "์•„ํ‹ฐํŒฉํŠธ ยท ํŒŒํ‹ฐ ๊ณต์šฉ" msgstr "Artifact ยท Party-wide" #. Key: SkillDetailType -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2523) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2523) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2515) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2515) msgctxt "ShopUIWidgetBase,SkillDetailType" msgid "์Šคํ‚ฌ ยท {0}" msgstr "Skill ยท {0}" #. Key: ArtifactEffectHeading -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2526) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2526) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2518) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2518) msgctxt "ShopUIWidgetBase,ArtifactEffectHeading" msgid "ํšจ๊ณผ" msgstr "Effect" #. Key: SkillEffectHeading -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2527) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2527) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2519) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2519) msgctxt "ShopUIWidgetBase,SkillEffectHeading" msgid "์Šคํ‚ฌ ํšจ๊ณผ" msgstr "Skill Effects" #. Key: LevelUpTitle -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2691) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2691) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2680) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2680) msgctxt "ShopUIWidgetBase,LevelUpTitle" msgid "๋ ˆ๋ฒจ์—…" msgstr "Level Up" #. Key: LevelUpNoCandidates -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2710) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2710) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2699) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2699) msgctxt "ShopUIWidgetBase,LevelUpNoCandidates" msgid "๋ฐฐ์šธ ์ˆ˜ ์žˆ๋Š” ์ƒˆ ์Šคํ‚ฌ์ด ์—†์Šต๋‹ˆ๋‹ค" msgstr "There are no new skills available to learn" #. Key: LevelUpChooseOne -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2711) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2711) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2700) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2700) msgctxt "ShopUIWidgetBase,LevelUpChooseOne" msgid "1๊ฐœ ์„ ํƒ" msgstr "Choose 1" #. Key: LevelUpSkip -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2716) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2716) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2705) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2705) msgctxt "ShopUIWidgetBase,LevelUpSkip" msgid "๋ฐ›์ง€ ์•Š๊ธฐ" msgstr "Skip Reward" #. Key: LevelUpEquip -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2718) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2718) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2707) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2707) msgctxt "ShopUIWidgetBase,LevelUpEquip" msgid "์„ ํƒํ•˜์—ฌ ์žฅ์ฐฉ" msgstr "Select and Equip" +#. Key: OwnedSkillFallbackDescription +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(848) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(848) +msgctxt "ShopUIWidgetBase,OwnedSkillFallbackDescription" +msgid "ํ˜„์žฌ ์žฅ์ฐฉ ์ค‘์ธ ์Šคํ‚ฌ์ž…๋‹ˆ๋‹ค." +msgstr "This skill is currently equipped." + #. Key: ShopJobKnight #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(85) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(85) @@ -9673,13 +9869,6 @@ msgctxt "ShopUIWidgetBase,ShopJobKnight" msgid "๊ธฐ์‚ฌ" msgstr "Knight" -#. Key: OwnedSkillFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(852) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(852) -msgctxt "ShopUIWidgetBase,OwnedSkillFallbackDescription" -msgid "ํ˜„์žฌ ์žฅ์ฐฉ ์ค‘์ธ ์Šคํ‚ฌ์ž…๋‹ˆ๋‹ค." -msgstr "This skill is currently equipped." - #. Key: ShopJobRanger #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(86) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(86) diff --git a/Content/Localization/Game/ko/Game.archive b/Content/Localization/Game/ko/Game.archive index 6124608c9..a6a5eb4c7 100644 Binary files a/Content/Localization/Game/ko/Game.archive and b/Content/Localization/Game/ko/Game.archive differ diff --git a/Content/Localization/Game/ko/Game.locres b/Content/Localization/Game/ko/Game.locres index 8fdc07c10..83071ab0b 100644 Binary files a/Content/Localization/Game/ko/Game.locres and b/Content/Localization/Game/ko/Game.locres differ diff --git a/Content/Localization/Game/ko/Game.po b/Content/Localization/Game/ko/Game.po index 0af0c2c6c..efd349447 100644 --- a/Content/Localization/Game/ko/Game.po +++ b/Content/Localization/Game/ko/Game.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: Game\n" -"POT-Creation-Date: 2026-09-20 19:15\n" -"PO-Revision-Date: 2026-09-20 19:15\n" +"POT-Creation-Date: 2026-09-24 07:56\n" +"PO-Revision-Date: 2026-09-24 07:56\n" "Language-Team: \n" "Language: ko\n" "MIME-Version: 1.0\n" @@ -577,50 +577,92 @@ msgstr "์ž‘์€ ๋งˆ๋ฒ•์„" #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mDescription #: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mDescription msgctxt ",A49118234BDFD14414CA899AC9101F44" -msgid "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the start of combat, grants yourself 3 stacks of Control Immunity." msgstr "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. Key: 9D84487840C81B5E8E421AB52FDCB802 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A043_SmelingSalts.DA_Artifact_A043_SmelingSalts.mName msgctxt ",9D84487840C81B5E8E421AB52FDCB802" -msgid "๊ฐ์„ฑ ์†Œ๊ธˆ" +msgid "Smelling Salts" msgstr "๊ฐ์„ฑ ์†Œ๊ธˆ" #. Key: 23527D6E4FBB2651103240BFABAB46B2 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mDescription #: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mDescription msgctxt ",23527D6E4FBB2651103240BFABAB46B2" -msgid "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the end of your turn, if you did not move during that turn, grants yourself 2 stacks of Forced Movement Immunity." msgstr "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. Key: 3CD32F654A03B4250F12C3AE59417F4F #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A044_VineRoot.DA_Artifact_A044_VineRoot.mName msgctxt ",3CD32F654A03B4250F12C3AE59417F4F" -msgid "๋„์ฟจ ๋ฟŒ๋ฆฌ" +msgid "Vine Root" msgstr "๋„์ฟจ ๋ฟŒ๋ฆฌ" #. Key: 864CA6C7435AD98CC59B6DA260478C49 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mDescription #: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mDescription msgctxt ",864CA6C7435AD98CC59B6DA260478C49" -msgid "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." -msgstr "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the end of your turn, if your HP is at or below 50%, grants yourself 2 stacks of Weakening Immunity." +msgstr "At the end of your turn, if your HP is at or below 50%, grants yourself 2 stacks of Weakening Immunity." #. Key: 0930ED7244258EE0992F9A9E38282B80 #. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mName #: /Game/BP/DataAsset/Artifact/DA_Artifact_A045_PainKiller.DA_Artifact_A045_PainKiller.mName msgctxt ",0930ED7244258EE0992F9A9E38282B80" -msgid "์ง„ํ†ต์ œ" +msgid "Painkiller" msgstr "์ง„ํ†ต์ œ" +#. Key: 73821AC74148829F555B3C819627C769 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mDescription +msgctxt ",73821AC74148829F555B3C819627C769" +msgid "At the start of every third turn, reduces skill cooldowns by 1." +msgstr "" + +#. Key: DE557EE74760245C2CFE54BBC57D95A1 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock.DA_Artifact_A046_BrokenClock.mName +msgctxt ",DE557EE74760245C2CFE54BBC57D95A1" +msgid "Broken Clock" +msgstr "" + +#. Key: 4A3030494AD8D63422112FB8F6E9C5CC +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mDescription +msgctxt ",4A3030494AD8D63422112FB8F6E9C5CC" +msgid "After an effect is applied, if the target has 0 HP or less, reduces skill cooldowns by 3." +msgstr "" + +#. Key: A62C7D644B3A487D97CB0EBFBFE6A0EF +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat.DA_Artifact_A047_MagicHat.mName +msgctxt ",A62C7D644B3A487D97CB0EBFBFE6A0EF" +msgid "Magic Hat" +msgstr "" + +#. Key: F68A888542FCB383C28DE182180747B5 +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mDescription +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mDescription +msgctxt ",F68A888542FCB383C28DE182180747B5" +msgid "On every fifth skill use, reduces skill cooldowns by 1." +msgstr "" + +#. Key: 8DE9EEFB442237936C8C2D865CC0CC1C +#. SourceLocation: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mName +#: /Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot.DA_Artifact_A048_Inkpot.mName +msgctxt ",8DE9EEFB442237936C8C2D865CC0CC1C" +msgid "Inkpot" +msgstr "" + #. Key: 79458D0F4B162D84BC01A59F3BA287F6 #. SourceLocation: /Game/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.DA_Barrel_ExplosionGimmick.mDisplayName #: /Game/BP/DataAsset/CombatTargetObstacle/DA_Barrel_ExplosionGimmick.DA_Barrel_ExplosionGimmick.mDisplayName msgctxt ",79458D0F4B162D84BC01A59F3BA287F6" -msgid "Explosive Barrel" -msgstr "ํ™”์•ฝํ†ต" +msgid "Explosion Barrel" +msgstr "ํญ๋ฐœํ†ต" #. Key: 54613FF7435635437189C0ACB78087F7 #. SourceLocation: /Game/BP/DataAsset/CombatTargetObstacle/DA_BlackHoleTotemGimmick.DA_BlackHoleTotemGimmick.mDisplayName @@ -703,7 +745,7 @@ msgstr "๊ตฌ์šธ์˜ ๋ถ„๋…ธ" #. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A002_RottenRegeneration.DA_Equipment_A002_RottenRegeneration.mDescription #: /Game/BP/DataAsset/Equipment/DA_Equipment_A002_RottenRegeneration.DA_Equipment_A002_RottenRegeneration.mDescription msgctxt ",7F3E1DDD40324EABB4ED4FB8637EEC5D" -msgid "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, ์ฒด๋ ฅ์„ 10 ํšŒ๋ณตํ•ฉ๋‹ˆ๋‹ค.\r\n๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgid "Restores 10 HP when using a skill.\r\nImmune to Stun and Root." msgstr "์Šคํ‚ฌ ์‚ฌ์šฉ ์‹œ, ์ฒด๋ ฅ์„ 10 ํšŒ๋ณตํ•ฉ๋‹ˆ๋‹ค.\r\n๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." #. Key: 7D8B51E24AF8D178D285F588B53429E1 @@ -759,16 +801,30 @@ msgstr "์žญ์˜ ๋‚ซ" #. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mDescription #: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mDescription msgctxt ",340563DF4DE492C006C25F90B9747773" -msgid "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." +msgid "Cannot be forcibly moved." msgstr "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." #. Key: CC4CBD8B43E0D4117D16FD89293B1F0C #. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mName #: /Game/BP/DataAsset/Equipment/DA_Equipment_A006_Chunk.DA_Equipment_A006_Chunk.mName msgctxt ",CC4CBD8B43E0D4117D16FD89293B1F0C" -msgid "๋ฌด๊ฑฐ์›€" +msgid "Heavy" msgstr "๋ฌด๊ฑฐ์›€" +#. Key: 52AC6B4E426F409940C0F3AE4F1A802E +#. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mDescription +#: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mDescription +msgctxt ",52AC6B4E426F409940C0F3AE4F1A802E" +msgid "Immune to status ailments." +msgstr "์ƒํƒœ์ด์ƒ์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + +#. Key: BEEEFCF9486186C7F17380981CFFA37C +#. SourceLocation: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mName +#: /Game/BP/DataAsset/Equipment/DA_Equipment_A007_Ghost.DA_Equipment_A007_Ghost.mName +msgctxt ",BEEEFCF9486186C7F17380981CFFA37C" +msgid "Ghost" +msgstr "์œ ๋ น" + #. Key: 65D880F245C83280B41946BD97A388DF #. SourceLocation: /Game/BP/DataAsset/Obstacle/Common/DA_EmptyObstacle.DA_EmptyObstacle.mDisplayName #: /Game/BP/DataAsset/Obstacle/Common/DA_EmptyObstacle.DA_EmptyObstacle.mDisplayName @@ -1445,23 +1501,44 @@ msgstr "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ํƒˆ์ง„ 2๋ฅผ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P043.DA_Passive_P043.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_P043.DA_Passive_P043.mDescription msgctxt ",E232C1A94E258B745579FBBB4A2098D3" -msgid "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the start of combat, grants yourself 3 stacks of Control Immunity." msgstr "์ „ํˆฌ ์‹œ์ž‘ ์‹œ, ์ž์‹ ์—๊ฒŒ ์ œ์–ด ๋ฉด์—ญ์„ 3 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. Key: DF6CCA7B40EA815885DA61943F9EDE6C #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P044.DA_Passive_P044.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_P044.DA_Passive_P044.mDescription msgctxt ",DF6CCA7B40EA815885DA61943F9EDE6C" -msgid "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the end of your turn, if you did not move during that turn, grants yourself 2 stacks of Forced Movement Immunity." msgstr "ํ„ด ์ข…๋ฃŒ ์‹œ, ์ž์‹ ์˜ ํ„ด ๋™์•ˆ ์ด๋™ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ž์‹ ์—๊ฒŒ ๊ฐ•์ œ ์ด๋™ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. Key: 12CE6CE647BC9466B93D21A554AE7A15 #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P045.DA_Passive_P045.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_P045.DA_Passive_P045.mDescription msgctxt ",12CE6CE647BC9466B93D21A554AE7A15" -msgid "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +msgid "At the end of your turn, if your HP is at or below 50%, grants yourself 2 stacks of Weakening Immunity." msgstr "ํ„ด ์ค‘๋ฃŒ ์‹œ, ์ฒด๋ ฅ์ด 50% ์ดํ•˜๋ผ๋ฉด ์ž์‹ ์—๊ฒŒ ์‡ ์•ฝ ๋ฉด์—ญ์„ 2 ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." +#. Key: B3F1361A43E557DA273C07A0801BCE1D +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P046.DA_Passive_P046.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P046.DA_Passive_P046.mDescription +msgctxt ",B3F1361A43E557DA273C07A0801BCE1D" +msgid "At the start of every third turn, reduces skill cooldowns by 1." +msgstr "" + +#. Key: CC8B771B450D75FB207E569AD04BD5A8 +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P047.DA_Passive_P047.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P047.DA_Passive_P047.mDescription +msgctxt ",CC8B771B450D75FB207E569AD04BD5A8" +msgid "After an effect is applied, if the target has 0 HP or less, reduces skill cooldowns by 3." +msgstr "" + +#. Key: 7CB1C2D44F426340E0640CA290DA9F9D +#. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_P048.DA_Passive_P048.mDescription +#: /Game/BP/DataAsset/Passive/DA_Passive_P048.DA_Passive_P048.mDescription +msgctxt ",7CB1C2D44F426340E0640CA290DA9F9D" +msgid "On every fifth skill use, reduces skill cooldowns by 1." +msgstr "" + #. Key: 2DC3489240D5807EBE56018D55C41684 #. SourceLocation: /Game/BP/DataAsset/Passive/DA_Passive_ReceivingEffect_Defense_3.DA_Passive_ReceivingEffect_Defense_3.mDescription #: /Game/BP/DataAsset/Passive/DA_Passive_ReceivingEffect_Defense_3.DA_Passive_ReceivingEffect_Defense_3.mDescription @@ -1571,16 +1648,23 @@ msgstr "ํ”ผ๊ฒฉ ์‹œ, ์ž์‹ ์—๊ฒŒ ๋ฐฉ์–ด๋„ 5์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค." #. SourceLocation: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P005_Heavy.DA_MonsterPassive_P005_Heavy.mDescription #: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P005_Heavy.DA_MonsterPassive_P005_Heavy.mDescription msgctxt ",A8C71BE242679B3126E09CBCA88CDBBB" -msgid "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." +msgid "Cannot be forcibly moved." msgstr "๊ฐ•์ œ๋กœ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." #. Key: 65A95708457ABC11C2B96E981982B092 #. SourceLocation: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P006_NoBrain.DA_MonsterPassive_P006_NoBrain.mDescription #: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P006_NoBrain.DA_MonsterPassive_P006_NoBrain.mDescription msgctxt ",65A95708457ABC11C2B96E981982B092" -msgid "๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +msgid "Immune to Stun and Root." msgstr "๊ธฐ์ ˆ, ์†๋ฐ•์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." +#. Key: E777B96E4C7ABDE94B11C9A6EC22A628 +#. SourceLocation: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.DA_MonsterPassive_P007_Ghost.mDescription +#: /Game/BP/DataAsset/Passive/Monster/DA_MonsterPassive_P007_Ghost.DA_MonsterPassive_P007_Ghost.mDescription +msgctxt ",E777B96E4C7ABDE94B11C9A6EC22A628" +msgid "Immune to status ailments." +msgstr "์ƒํƒœ์ด์ƒ์— ๊ฑธ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + #. Key: DAF8C7E3429395E9A134439F0A52ADA9 #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Attack_Common_CoveringFire.DA_Common_Attack_Common_CoveringFire.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Attack_Common_CoveringFire.DA_Common_Attack_Common_CoveringFire.mName @@ -1644,6 +1728,13 @@ msgctxt ",4A6D37CC418F089541EBF19E45A336C8" msgid "White Hole" msgstr "ํ™”์ดํŠธํ™€" +#. Key: 8B8C71E047C12CB42A991DA6C6570E46 +#. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.DA_Common_Move_Rare_Leap.mName +#: /Game/BP/DataAsset/Skill/Common/DA_Common_Move_Rare_Leap.DA_Common_Move_Rare_Leap.mName +msgctxt ",8B8C71E047C12CB42A991DA6C6570E46" +msgid "Leap" +msgstr "๋„์•ฝ" + #. Key: F742548B49BE186CCE49D18FA518B68E #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Common_FancyFootwork.DA_Common_Spell_Common_FancyFootwork.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Common_FancyFootwork.DA_Common_Spell_Common_FancyFootwork.mName @@ -1679,6 +1770,13 @@ msgctxt ",61086B4E48A408A8A7A9D481D487FF9E" msgid "Fortification" msgstr "๊ฐ•ํ™”" +#. Key: 9F7762A64BEC537C13801EB53598C455 +#. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.DA_Common_Spell_Epic_HourglassTurn.mName +#: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn.DA_Common_Spell_Epic_HourglassTurn.mName +msgctxt ",9F7762A64BEC537C13801EB53598C455" +msgid "Turn the Hourglass" +msgstr "" + #. Key: 0D0C22BF4AF123F5F79971825460A31E #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_Move.DA_Common_Spell_Epic_Move.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_Move.DA_Common_Spell_Epic_Move.mName @@ -1690,7 +1788,7 @@ msgstr "์ด๋™" #. SourceLocation: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Rare_Passion.DA_Common_Spell_Rare_Passion.mName #: /Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Rare_Passion.DA_Common_Spell_Rare_Passion.mName msgctxt ",60A454584E4B3F31292ADBA2C8D730C5" -msgid "์—ด์ •" +msgid "Passion" msgstr "์—ด์ •" #. Key: BB9E52CD456ECEDC18C1D895C1230BA7 @@ -1711,7 +1809,7 @@ msgstr "๋ˆˆ ์ชผ๊ธฐ" #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage1/Eagle/DA_Eagle_Fly.DA_Eagle_Fly.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage1/Eagle/DA_Eagle_Fly.DA_Eagle_Fly.mName msgctxt ",942E244C4432DDB5B182CC8D21CCA9B1" -msgid "๋‚ ๊ธฐ" +msgid "Fly" msgstr "๋‚ ๊ธฐ" #. Key: 8429CE8B42B9BDED4B645B89BF083AE3 @@ -1914,7 +2012,7 @@ msgstr "์นผ๋‚  ๋ฐ”๋žŒ" #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.DA_HatchetBird_Move_Fly.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage2/HatchetBird/DA_HatchetBird_Move_Fly.DA_HatchetBird_Move_Fly.mName msgctxt ",F2D2DBB74B5C38278EE7C784C2EB8B6B" -msgid "๋‚ ๊ธฐ" +msgid "Fly" msgstr "๋‚ ๊ธฐ" #. Key: 78242B044347011D203F1AAC7A9A411E @@ -2001,6 +2099,13 @@ msgctxt ",B40FAB4B4B345D7656487E93BF60A75B" msgid "Howl" msgstr "ํฌํšจ" +#. Key: 17ED0AA54BFC96200BC847942A70A1A3 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.DA_Skeleton_Golem_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_ImpactLeap.DA_Skeleton_Golem_ImpactLeap.mName +msgctxt ",17ED0AA54BFC96200BC847942A70A1A3" +msgid "Impact Leap" +msgstr "์ถฉ๊ฒฉ ๋„์•ฝ" + #. Key: 0936ABD04F5E80223644A0834B9E8244 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_Kick.DA_Skeleton_Golem_Kick.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage2/Skeleton_Golem/DA_Skeleton_Golem_Kick.DA_Skeleton_Golem_Kick.mName @@ -2103,21 +2208,21 @@ msgstr "์ œ๋ฌผ" #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Boo.DA_Ghost_Boo.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Boo.DA_Ghost_Boo.mName msgctxt ",965DED1D41B83DA585D40382393D29C5" -msgid "์šฐ์šฐ" +msgid "Boo" msgstr "์šฐ์šฐ" #. Key: 75BDB9DD45EE48005EE6719FF551D909 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Sob.DA_Ghost_Sob.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Sob.DA_Ghost_Sob.mName msgctxt ",75BDB9DD45EE48005EE6719FF551D909" -msgid "ํ๋А๋‚Œ" +msgid "Sob" msgstr "ํ๋А๋‚Œ" #. Key: D5DBCB8A481C46576E6D2EA44244CA22 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.DA_Ghost_Teleport.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Ghost/DA_Ghost_Teleport.DA_Ghost_Teleport.mName msgctxt ",D5DBCB8A481C46576E6D2EA44244CA22" -msgid "ํ…”๋ ˆํฌํŠธ" +msgid "Teleport" msgstr "ํ…”๋ ˆํฌํŠธ" #. Key: 58B9886F4D5F9300A1EAD1B45B59F4E8 @@ -2253,6 +2358,13 @@ msgctxt ",976B1CA94EF59B2D0BC609B088490B5A" msgid "Sand Toss" msgstr "๋ชจ๋ž˜ ๋ฟŒ๋ฆฌ๊ธฐ" +#. Key: 1E6BDAB44BCFA585540C538EFD1837C5 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.DA_Skeleton_Rogue_Move_FlashStep.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Rogue/DA_Skeleton_Rogue_Move_FlashStep.DA_Skeleton_Rogue_Move_FlashStep.mName +msgctxt ",1E6BDAB44BCFA585540C538EFD1837C5" +msgid "Flash Step" +msgstr "์ˆœ๋ณด" + #. Key: 3272345B4A1DDFAB9999618F1B40E8E4 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Attack_PushAttack.DA_Skeleton_Warrior_Attack_PushAttack.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Attack_PushAttack.DA_Skeleton_Warrior_Attack_PushAttack.mName @@ -2274,6 +2386,13 @@ msgctxt ",230DAABE477BCCFB6C59D78908AF7734" msgid "Heavy Strike" msgstr "๊ฐ•ํƒ€" +#. Key: 54E9E2A64A3EF00F2D73DFBD3789F9B0 +#. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.DA_Skeleton_Warrior_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_ImpactLeap.DA_Skeleton_Warrior_ImpactLeap.mName +msgctxt ",54E9E2A64A3EF00F2D73DFBD3789F9B0" +msgid "Impact Leap" +msgstr "์ถฉ๊ฒฉ ๋„์•ฝ" + #. Key: 109D3ECD4076880A38CFE69DF880E876 #. SourceLocation: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Spell_Rage.DA_Skeleton_Warrior_Spell_Rage.mName #: /Game/BP/DataAsset/Skill/Enemy/Stage3/Skeleton_Warrior/DA_Skeleton_Warrior_Spell_Rage.DA_Skeleton_Warrior_Spell_Rage.mName @@ -2435,6 +2554,13 @@ msgctxt ",3FC2019A4ACE262F9429DABA566D1FBB" msgid "Whirlwind" msgstr "ํ›จ์œˆ๋“œ" +#. Key: BD8EF739457917EED9FBD0A3BDAAAFAC +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.DA_Barbarian_Move_Epic_ImpactLeap.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Move_Epic_ImpactLeap.DA_Barbarian_Move_Epic_ImpactLeap.mName +msgctxt ",BD8EF739457917EED9FBD0A3BDAAAFAC" +msgid "Impact Leap" +msgstr "์ถฉ๊ฒฉ ๋„์•ฝ" + #. Key: 0FB44FE6446A80EE3357BDB38EA9BE89 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Common_Fear.DA_Barbarian_Spell_Common_Fear.mName #: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Common_Fear.DA_Barbarian_Spell_Common_Fear.mName @@ -2467,7 +2593,7 @@ msgstr "๋ช…์ƒ" #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Epic_Unstoppable.DA_Barbarian_Spell_Epic_Unstoppable.mName #: /Game/BP/DataAsset/Skill/Mercenary/Barbarian/DA_Barbarian_Spell_Epic_Unstoppable.DA_Barbarian_Spell_Epic_Unstoppable.mName msgctxt ",6AB5F90A406AE9BC57E861ADEA2BE9BB" -msgid "์ €์ง€ ๋ถˆ๊ฐ€" +msgid "Unstoppable" msgstr "์ €์ง€ ๋ถˆ๊ฐ€" #. Key: 38B4E17042D9CA31297F11B6B6515059 @@ -2582,6 +2708,13 @@ msgctxt ",930AA6CD482E22148F40F7A82D524A46" msgid "Poison Cloud" msgstr "๋…๊ตฌ๋ฆ„" +#. Key: 4571C9B445366B946B1C8A859D10B206 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.DA_Druid_Spell_Epic_BlessingOfTime.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime.DA_Druid_Spell_Epic_BlessingOfTime.mName +msgctxt ",4571C9B445366B946B1C8A859D10B206" +msgid "Blessing of Time" +msgstr "" + #. Key: 79F9D5E448B105C5182AAEB5B231991B #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_FlashFruit.DA_Druid_Spell_Epic_FlashFruit.mName #: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_FlashFruit.DA_Druid_Spell_Epic_FlashFruit.mName @@ -2628,7 +2761,7 @@ msgstr "๋ฏฟ์Œ" #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Rare_ImmunityBoost.DA_Druid_Spell_Rare_ImmunityBoost.mName #: /Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Rare_ImmunityBoost.DA_Druid_Spell_Rare_ImmunityBoost.mName msgctxt ",4216869C40F1CBC51B3607BECD01C719" -msgid "๋ฉด์—ญ๋ ฅ ์ฆ์ง„" +msgid "Immunity Boost" msgstr "๋ฉด์—ญ๋ ฅ ์ฆ์ง„" #. Key: 1CBF9AB042E43F5FF8B6678C37D00A07 @@ -2743,6 +2876,13 @@ msgctxt ",8CD748794A959830CC1BC28924CD3B40" msgid "Spinning Slash" msgstr "ํšŒ์ „ ๋ฒ ๊ธฐ" +#. Key: FC30220B45CA3F19A4DAA1AED3661E8C +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.DA_Knight_Move_Common_GuardianCharge.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Move_Common_GuardianCharge.DA_Knight_Move_Common_GuardianCharge.mName +msgctxt ",FC30220B45CA3F19A4DAA1AED3661E8C" +msgid "Guardian Charge" +msgstr "์ˆ˜ํ˜ธ ๋Œ๊ฒฉ" + #. Key: 0EE1C53A48F082065A5CD49A20F292F5 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Spell_Common_Block.DA_Knight_Spell_Common_Block.mName #: /Game/BP/DataAsset/Skill/Mercenary/Knight/DA_Knight_Spell_Common_Block.DA_Knight_Spell_Common_Block.mName @@ -2925,6 +3065,13 @@ msgctxt "SkillNames,Mage.ThunderStorm" msgid "Thunderstorm" msgstr "๋ฒผ๋ฝ ํญํ’" +#. Key: 1DDE84294BBC3B614AF52291C0A37F44 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.DA_Mage_Move_Epic_Teleport.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Move_Epic_Teleport.DA_Mage_Move_Epic_Teleport.mName +msgctxt ",1DDE84294BBC3B614AF52291C0A37F44" +msgid "Teleport" +msgstr "์ˆœ๊ฐ„์ด๋™" + #. Key: F82A1B16498215B98D0F2597C10FC203 #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Common_Gust.DA_Mage_Spell_Common_Gust.mName #: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Common_Gust.DA_Mage_Spell_Common_Gust.mName @@ -2960,6 +3107,20 @@ msgctxt ",1B782957494A25B0656C77846DD49EDF" msgid "Magic Barrier" msgstr "๋งˆ๋ฒ• ์žฅ๋ฒฝ" +#. Key: CA4A0FAD49B332EA55F6B1B0FA1B155E +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.DA_Mage_Spell_Epic_TickTock.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock.DA_Mage_Spell_Epic_TickTock.mName +msgctxt ",CA4A0FAD49B332EA55F6B1B0FA1B155E" +msgid "Tick-Tock" +msgstr "" + +#. Key: 0E9A769446391E0EF05A6688B0F63502 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.DA_Mage_Spell_Rare_TimeAcceleration.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration.DA_Mage_Spell_Rare_TimeAcceleration.mName +msgctxt ",0E9A769446391E0EF05A6688B0F63502" +msgid "Time Acceleration" +msgstr "" + #. Key: A482DF92454637EF78C6CD8BD1922F3E #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Ranger/DA_Ranger_Attack_Common_Disarm.DA_Ranger_Attack_Common_Disarm.mName #: /Game/BP/DataAsset/Skill/Mercenary/Ranger/DA_Ranger_Attack_Common_Disarm.DA_Ranger_Attack_Common_Disarm.mName @@ -3219,6 +3380,20 @@ msgctxt ",E56043D14CD1CA4EA669629BB0BF3634" msgid "Sharpen Blade" msgstr "์นผ๊ฐˆ๊ธฐ" +#. Key: A931024340831279EA06E288356EBEB4 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.DA_Rogue_Move_FlashStep.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Move_FlashStep.DA_Rogue_Move_FlashStep.mName +msgctxt ",A931024340831279EA06E288356EBEB4" +msgid "Flash Step" +msgstr "์ˆœ๋ณด" + +#. Key: 5213A4FF4FAF6C3E09821791D50F596C +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.DA_Rogue_Spell_Epic_Cheat.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat.DA_Rogue_Spell_Epic_Cheat.mName +msgctxt ",5213A4FF4FAF6C3E09821791D50F596C" +msgid "Cheat" +msgstr "" + #. Key: D34E45444D8889195424DFADFE72BEDE #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Doping.DA_Rogue_Spell_Epic_Doping.mName #: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Doping.DA_Rogue_Spell_Epic_Doping.mName @@ -3233,13 +3408,6 @@ msgctxt ",4E54F0E849151674F8D78D8820C2A244" msgid "Evasion" msgstr "ํšŒํ”ผ" -#. Key: 60314B094FDC9F7EDB24FEB950738DB9 -#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.DA_Rogue_Spell_Epic_SleightOfHand.mName -#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_SleightOfHand.DA_Rogue_Spell_Epic_SleightOfHand.mName -msgctxt ",60314B094FDC9F7EDB24FEB950738DB9" -msgid "Sleight of Hand" -msgstr "์†๊ธฐ์ˆ " - #. Key: Rogue.LegSweep #. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_LegSweep.DA_Rogue_Spell_Rare_LegSweep.mName #: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_LegSweep.DA_Rogue_Spell_Rare_LegSweep.mName @@ -3254,6 +3422,13 @@ msgctxt ",BD3F00D5461E9872A817BC92E6547246" msgid "Sand Toss" msgstr "๋ชจ๋ž˜ ๋ฟŒ๋ฆฌ๊ธฐ" +#. Key: 60314B094FDC9F7EDB24FEB950738DB9 +#. SourceLocation: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.DA_Rogue_Spell_Rare_SleightOfHand.mName +#: /Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Rare_SleightOfHand.DA_Rogue_Spell_Rare_SleightOfHand.mName +msgctxt ",60314B094FDC9F7EDB24FEB950738DB9" +msgid "Sleight of Hand" +msgstr "์†๊ธฐ์ˆ " + #. Key: AE209B3847CEC8895AC92884CFC83A76 #. SourceLocation: /Game/BP/DataAsset/Unit/EnemyUnit/Stage1/DA_EagleUnit.DA_EagleUnit.mDisplayName #: /Game/BP/DataAsset/Unit/EnemyUnit/Stage1/DA_EagleUnit.DA_EagleUnit.mDisplayName @@ -6276,7 +6451,7 @@ msgstr "์‹œ์ „์ž๊ฐ€ ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ์œผ๋กœ {0}์นธ ๋ฐ€์–ด๋ƒ…๋‹ˆ๋‹ค." #: Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_ReduceCooldown.cpp(36) msgctxt "SkillEffectLayer_ReduceCooldown,ReduceCooldownDesc" msgid "Reduces cooldown by {0}." -msgstr "" +msgstr "์ฟจ๋‹ค์šด์„ {0} ๊ฐ์†Œ์‹œํ‚ต๋‹ˆ๋‹ค." #. Key: RootName #. SourceLocation: Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Root.cpp(20) @@ -6433,8 +6608,8 @@ msgid "{0}\n{1}" msgstr "{0}\n{1}" #. Key: CurrentCombatArea -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(1393) -#: Source/P_RD/GameMode/CombatGameMode.cpp(1393) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(1405) +#: Source/P_RD/GameMode/CombatGameMode.cpp(1405) msgctxt "CombatGameMode,CurrentCombatArea" msgid "Current Combat Area" msgstr "ํ˜„์žฌ ์ „ํˆฌ ์ง€์—ญ" @@ -6468,43 +6643,43 @@ msgid "EMPTY" msgstr "EMPTY" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2294) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2294) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2306) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2306) msgctxt "CombatGameMode,ArtifactFallbackName" msgid "Artifact {0}" msgstr "์•„ํ‹ฐํŒฉํŠธ {0}" #. Key: MovedTiles -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2496) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2496) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2508) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2508) msgctxt "CombatFloatingLog,MovedTiles" msgid "Move {0} tiles" msgstr "์ด๋™ {0}์นธ" #. Key: EnteredBoard -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2503) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2503) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2515) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2515) msgctxt "CombatFloatingLog,EnteredBoard" msgid "Entrance" msgstr "๋“ฑ์žฅ" #. Key: ExitedBoard -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2510) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2510) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2522) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2522) msgctxt "CombatFloatingLog,ExitedBoard" msgid "Defeated" msgstr "์ „ํˆฌ๋ถˆ๋Šฅ" #. Key: VictoryRewardTitle -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2777) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2777) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2789) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2789) msgctxt "CombatGameMode,VictoryRewardTitle" msgid "Battle Rewards" msgstr "์ „ํˆฌ ๋ณด์ƒ" #. Key: UnknownRewardMercenary -#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2820) -#: Source/P_RD/GameMode/CombatGameMode.cpp(2820) +#. SourceLocation: Source/P_RD/GameMode/CombatGameMode.cpp(2832) +#: Source/P_RD/GameMode/CombatGameMode.cpp(2832) msgctxt "CombatGameMode,UnknownRewardMercenary" msgid "Mercenary" msgstr "์šฉ๋ณ‘" @@ -6649,125 +6824,146 @@ msgctxt "FrontendGameMode,RangerDesc" msgid "A sharpshooter who picks off enemies from afar with a bow.\nSettles the fight before they can close in." msgstr "๋จผ ๊ฑฐ๋ฆฌ์—์„œ ํ™œ๋กœ ์ ์„ ์†Ž์•„๋‚ด๋Š” ๋ช…์‚ฌ์ˆ˜.\n๊ฐ€๊นŒ์ด ๋ถ™๊ธฐ ์ „์— ์Šน๋ถ€๋ฅผ ๋‚ธ๋‹ค." +#. Key: PartyArtifact +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(1001) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(1001) +msgctxt "RoomGameModeBase,PartyArtifact" +msgid "Party-wide effect" +msgstr "ํŒŒํ‹ฐ ์ „์ฒด ํšจ๊ณผ" + #. Key: MonsterRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(142) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(142) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) msgctxt "RoomGameModeBase,MonsterRoomTitle" msgid "Monster" msgstr "๋ชฌ์Šคํ„ฐ" #. Key: EliteRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(144) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) msgctxt "RoomGameModeBase,EliteRoomTitle" msgid "Elite" msgstr "์—˜๋ฆฌํŠธ" #. Key: BossRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(146) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) msgctxt "RoomGameModeBase,BossRoomTitle" msgid "Boss" msgstr "๋ณด์Šค" #. Key: ShopRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(148) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) msgctxt "RoomGameModeBase,ShopRoomTitle" msgid "Shop" msgstr "์ƒ์ " #. Key: TreasureRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(150) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) msgctxt "RoomGameModeBase,TreasureRoomTitle" msgid "Treasure" msgstr "๋ณด๋ฌผ" #. Key: UnknownRoomTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(152) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(154) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(154) msgctxt "RoomGameModeBase,UnknownRoomTitle" msgid "Unknown" msgstr "์•Œ ์ˆ˜ ์—†์Œ" #. Key: MapRoomDescription -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(163) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(163) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(165) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(165) msgctxt "RoomGameModeBase,MapRoomDescription" msgid "Row {0}, Column {1}. Next routes: {2}" msgstr "{0}ํ–‰ {1}์—ด. ๋‹ค์Œ ๊ฒฝ๋กœ: {2}" #. Key: StartPointDescription -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(176) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(176) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(178) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(178) msgctxt "RoomGameModeBase,StartPointDescription" msgid "Routes: {0}" msgstr "๊ฒฝ๋กœ: {0}" #. Key: RosterJobKnight -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(207) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(207) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) msgctxt "RoomGameModeBase,RosterJobKnight" msgid "Knight" msgstr "๊ธฐ์‚ฌ" #. Key: RosterJobMage -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(208) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(208) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) msgctxt "RoomGameModeBase,RosterJobMage" msgid "Mage" msgstr "๋งˆ๋ฒ•์‚ฌ" #. Key: RosterJobRanger -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(209) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) msgctxt "RoomGameModeBase,RosterJobRanger" msgid "Ranger" msgstr "๊ถ์ˆ˜" #. Key: RosterJobRogue -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(210) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) msgctxt "RoomGameModeBase,RosterJobRogue" msgid "Rogue" msgstr "๋„์ " #. Key: RosterJobBarbarian -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(211) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(213) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(213) msgctxt "RoomGameModeBase,RosterJobBarbarian" msgid "Barbarian" msgstr "์•ผ๋งŒ์ „์‚ฌ" #. Key: RosterJobDruid -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(212) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(214) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(214) msgctxt "RoomGameModeBase,RosterJobDruid" msgid "Druid" msgstr "๋“œ๋ฃจ์ด๋“œ" +#. Key: SaveAndExitFailed +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(399) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(399) +msgctxt "RoomGameModeBase,SaveAndExitFailed" +msgid "Failed to save and exit." +msgstr "" + +#. Key: AbandonRunFailed +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(400) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(400) +msgctxt "RoomGameModeBase,AbandonRunFailed" +msgid "Failed to abandon the run." +msgstr "" + +#. Key: SavingRun +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(411) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(411) +msgctxt "RoomGameModeBase,SavingRun" +msgid "Saving..." +msgstr "" + #. Key: StartPointTitle -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(554) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(554) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(626) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(626) msgctxt "RoomGameModeBase,StartPointTitle" msgid "Start" msgstr "์‹œ์ž‘" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(925) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(925) +#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(997) +#: Source/P_RD/GameMode/RoomGameModeBase.cpp(997) msgctxt "RoomGameModeBase,ArtifactFallbackName" msgid "Artifact {0}" msgstr "์•„ํ‹ฐํŒฉํŠธ {0}" -#. Key: PartyArtifact -#. SourceLocation: Source/P_RD/GameMode/RoomGameModeBase.cpp(929) -#: Source/P_RD/GameMode/RoomGameModeBase.cpp(929) -msgctxt "RoomGameModeBase,PartyArtifact" -msgid "Party-wide effect" -msgstr "ํŒŒํ‹ฐ ์ „์ฒด ํšจ๊ณผ" - #. Key: MercenaryLevel #. SourceLocation: Source/P_RD/GameMode/ShopGameMode.cpp(325) #: Source/P_RD/GameMode/ShopGameMode.cpp(325) @@ -7070,281 +7266,274 @@ msgid "Forgotten Citadel" msgstr "์žŠํžŒ ์„ฑ์ฑ„" #. Key: MercenaryMoveSummary -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2051) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2051) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2044) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2044) msgctxt "CombatLayoutHUD,MercenaryMoveSummary" msgid "Move" msgstr "์ด๋™" #. Key: PartySlotEmpty -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2120) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2120) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2113) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2113) msgctxt "CombatLayoutHUD,PartySlotEmpty" msgid "Empty Slot" msgstr "๋นˆ ์ž๋ฆฌ" #. Key: PreviousTurns -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2567) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2567) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2560) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2560) msgctxt "CombatLayoutHUD,PreviousTurns" msgid "View previous turns" msgstr "์ด์ „ ์ฐจ๋ก€ ๋ณด๊ธฐ" #. Key: NextTurns -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2569) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2569) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2562) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2562) msgctxt "CombatLayoutHUD,NextTurns" msgid "View upcoming turns" msgstr "๋‹ค์Œ ์ฐจ๋ก€ ๋ณด๊ธฐ" #. Key: Move -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2682) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2682) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2675) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2675) msgctxt "CombatLayoutHUD,Move" msgid "Move" msgstr "์ด๋™" #. Key: MoveCostPerTileShort -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2683) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2683) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2676) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2676) msgctxt "CombatLayoutHUD,MoveCostPerTileShort" msgid "1/tile" msgstr "1/์นธ" #. Key: MoveCost -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2684) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2684) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2677) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2677) msgctxt "CombatLayoutHUD,MoveCost" msgid "AP 1/tile" msgstr "AP 1/์นธ" #. Key: SkillCost -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2728) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2728) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2721) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2721) msgctxt "CombatLayoutHUD,SkillCost" msgid "AP {0}" msgstr "AP {0}" #. Key: SkillCardDamage -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2780) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2780) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2773) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2773) msgctxt "CombatLayoutHUD,SkillCardDamage" msgid "DMG {0}~{1}" msgstr "ํ”ผํ•ด {0}~{1}" #. Key: CombatObjectiveRemaining -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2946) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2946) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2939) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2939) msgctxt "CombatLayoutHUD,CombatObjectiveRemaining" msgid "Defeat all enemies โ€” {0} remaining" msgstr "๋ชจ๋“  ์  ์ฒ˜์น˜ โ€” ๋‚จ์€ ์  {0}" #. Key: MercenaryInventoryPageTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2972) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2972) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2965) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2965) msgctxt "CombatHUD,MercenaryInventoryPageTitle" msgid "Inventory" msgstr "์ธ๋ฒคํ† ๋ฆฌ" #. Key: MercenaryPageTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2973) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2973) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2966) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2966) msgctxt "CombatHUD,MercenaryPageTitle" msgid "Mercenaries" msgstr "์šฉ๋ณ‘" #. Key: ArtifactFallbackName -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3004) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3004) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2997) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(2997) msgctxt "CombatHUD,ArtifactFallbackName" msgid "Artifact" msgstr "์•„ํ‹ฐํŒฉํŠธ" #. Key: BattleStart -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3445) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3445) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3438) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3438) msgctxt "CombatAnnouncement,BattleStart" msgid "BATTLE START" msgstr "BATTLE START" #. Key: Round -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3512) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3512) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3505) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3505) msgctxt "CombatAnnouncement,Round" msgid "ROUND {0}" msgstr "ROUND {0}" #. Key: EndTurn -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3844) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3844) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3837) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3837) msgctxt "CombatLayoutHUD,EndTurn" msgid "End Turn" msgstr "ํ„ด ์ข…๋ฃŒ" #. Key: CancelAim -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3847) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3847) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3840) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(3840) msgctxt "CombatLayoutHUD,CancelAim" msgid "Cancel" msgstr "์ทจ์†Œ" -#. Key: SavingRun -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4890) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4890) -msgctxt "CombatLayoutHUD,SavingRun" -msgid "Saving..." -msgstr "์ €์žฅ ์ค‘..." - #. Key: SaveAndExitFailed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4949) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4949) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4874) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4874) msgctxt "CombatLayoutHUD,SaveAndExitFailed" msgid "Failed to save and exit." msgstr "์ €์žฅ ํ›„ ์ข…๋ฃŒ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." #. Key: AbandonRunFailed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4973) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4973) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4898) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(4898) msgctxt "CombatLayoutHUD,AbandonRunFailed" msgid "Failed to abandon the run." msgstr "๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค." #. Key: MonsterTabSkills -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5657) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5657) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5571) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5571) msgctxt "CombatLayoutHUD,MonsterTabSkills" msgid "Skills" msgstr "์Šคํ‚ฌ" #. Key: MonsterTabNoSkills -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5658) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5658) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5572) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5572) msgctxt "CombatLayoutHUD,MonsterTabNoSkills" msgid "Skills ยท None" msgstr "์Šคํ‚ฌ ยท ์—†์Œ" #. Key: MonsterEquipmentHeading -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5736) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5736) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5650) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5650) msgctxt "CombatLayoutHUD,MonsterEquipmentHeading" msgid "Equipment ยท Tap for details" msgstr "์žฅ๋น„ ยท ๋ˆŒ๋Ÿฌ์„œ ์ž์„ธํžˆ" #. Key: MonsterEquipmentEmpty -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5737) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5737) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5651) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(5651) msgctxt "CombatLayoutHUD,MonsterEquipmentEmpty" msgid "Equipment ยท None" msgstr "์žฅ๋น„ ยท ์—†์Œ" #. Key: UnitDetailLevel -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6302) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6302) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6216) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6216) msgctxt "CombatLayoutHUD,UnitDetailLevel" msgid "Lv.{0}" msgstr "Lv.{0}" #. Key: UnitDetailAlly -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6307) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6307) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6221) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6221) msgctxt "CombatLayoutHUD,UnitDetailAlly" msgid "Ally" msgstr "์•„๊ตฐ" #. Key: UnitDetailEnemy -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6308) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6308) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6222) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6222) msgctxt "CombatLayoutHUD,UnitDetailEnemy" msgid "Enemy" msgstr "์ " #. Key: UnitDetailIdentityAndHp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6310) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6310) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6224) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6224) msgctxt "CombatLayoutHUD,UnitDetailIdentityAndHp" msgid "{0} ยท {1} ยท HP {2}/{3}" msgstr "{0} ยท {1} ยท HP {2}/{3}" #. Key: UnitDetailWithDefense -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6316) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6316) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6230) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6230) msgctxt "CombatLayoutHUD,UnitDetailWithDefense" msgid "{0} ยท Defense {1}" msgstr "{0} ยท ๋ฐฉ์–ด {1}" #. Key: DetailChipLevel -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6338) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6338) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6252) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6252) msgctxt "CombatLayoutHUD,DetailChipLevel" msgid "Level" msgstr "๋ ˆ๋ฒจ" #. Key: DetailChipHp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6341) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6341) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6255) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6255) msgctxt "CombatLayoutHUD,DetailChipHp" msgid "HP" msgstr "HP" #. Key: DetailChipDefense -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6343) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6343) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6257) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6257) msgctxt "CombatLayoutHUD,DetailChipDefense" msgid "Defense" msgstr "๋ฐฉ์–ด" #. Key: DetailChipSpeed -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6345) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6345) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6259) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6259) msgctxt "CombatLayoutHUD,DetailChipSpeed" msgid "Speed" msgstr "์†๋„" #. Key: DetailChipAp -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6347) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6347) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6261) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6261) msgctxt "CombatLayoutHUD,DetailChipAp" msgid "AP" msgstr "AP" #. Key: UnitDetailChipCritical -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6348) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6348) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6262) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6262) msgctxt "CombatLayoutHUD,UnitDetailChipCritical" msgid "Crit" msgstr "์น˜๋ช…ํƒ€" #. Key: UnitDetailPassiveLine -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6355) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6355) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6269) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6269) msgctxt "CombatLayoutHUD,UnitDetailPassiveLine" msgid "ยท {0}" msgstr "ยท {0}" #. Key: UnitDetailNoPassives -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6358) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6358) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6272) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6272) msgctxt "CombatLayoutHUD,UnitDetailNoPassives" msgid "No passives" msgstr "ํŒจ์‹œ๋ธŒ ์—†์Œ" #. Key: UnitDetailEnemyThreatLegend -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6364) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6364) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6278) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6278) msgctxt "CombatLayoutHUD,UnitDetailEnemyThreatLegend" msgid "{0}\n\nThe board shows every tile this enemy can reach in one turn.\nBorder band = movement range, fill = attack range." msgstr "{0}\n\nํŒ์˜ ํ‘œ์‹œ๋Š” ์ด ์ ์ด ํ•œ ํ„ด์— ๋‹ฟ๋Š” ๊ณณ์ด๋‹ค.\nํ…Œ๋‘๋ฆฌ ๋ฐด๋“œ = ์ด๋™ ๋ฒ”์œ„, ์ฑ„์›€ = ๊ณต๊ฒฉ ๋ฒ”์œ„." #. Key: MoveDetailTitle -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6692) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6692) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6604) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6604) msgctxt "CombatLayoutHUD,MoveDetailTitle" msgid "Move" msgstr "์ด๋™" #. Key: MoveDetailDescription -#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6693) -#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6693) +#. SourceLocation: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6605) +#: Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp(6605) msgctxt "CombatLayoutHUD,MoveDetailDescription" msgid "Moving one tile costs 1 AP. (Up to {0} tiles)\n\nTap a tile to choose a destination, then tap the final tile again to confirm movement." msgstr "1์นธ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค 1 AP๊ฐ€ ์†Œ๋ชจ๋ฉ๋‹ˆ๋‹ค. (์ตœ๋Œ€ {0}์นธ)\n\n์ด๋™ํ•  ํƒ€์ผ์„ ๋ˆŒ๋Ÿฌ ๋ชฉ์ ์ง€๋ฅผ ์„ ํƒํ•˜๊ณ , ๋งˆ์ง€๋ง‰ ํƒ€์ผ์„ ๋‹ค์‹œ ๋ˆŒ๋Ÿฌ ์ด๋™์„ ํ™•์ •ํ•˜์„ธ์š”." @@ -8505,36 +8694,36 @@ msgid "(mock reward)" msgstr "(๋ชฉ์—… ๋ณด์ƒ)" #. Key: ChestOpen -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1860) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1860) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1861) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1861) msgctxt "RewardConcept03Widget,ChestOpen" msgid "Open Chest" msgstr "์ƒ์ž ์—ด๊ธฐ" #. Key: ChestOpenHint -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1864) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1864) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1865) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1865) msgctxt "RewardConcept03Widget,ChestOpenHint" msgid "Tap the chest to open it" msgstr "์ƒ์ž๋ฅผ ๋ˆŒ๋Ÿฌ ์—ฌ์„ธ์š”" #. Key: ClaimSelectedOne -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) msgctxt "RewardConcept03Widget,ClaimSelectedOne" msgid "Claim Selected Item" msgstr "์„ ํƒํ•œ 1๊ฐœ ๋ฐ›๊ธฐ" #. Key: Confirm -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1869) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1870) msgctxt "RewardConcept03Widget,Confirm" msgid "Confirm" msgstr "ํ™•์ •" #. Key: SelectedArtifact -#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1920) -#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1920) +#. SourceLocation: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1921) +#: Source/P_RD/UI/Reward/RewardConcept03Widget.cpp(1921) msgctxt "RewardConcept03Widget,SelectedArtifact" msgid "Selected" msgstr "์„ ํƒ๋จ" @@ -9289,197 +9478,197 @@ msgid "Cancel" msgstr "์ทจ์†Œ" #. Key: SkillNoteOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1285) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1285) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1277) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1277) msgctxt "ShopUIWidgetBase,SkillNoteOwned" msgid "{0} only ยท Owned" msgstr "{0} ์ „์šฉ ยท ์ด๋ฏธ ๋ณด์œ " #. Key: SkillNoteOtherJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1288) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1288) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1280) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1280) msgctxt "ShopUIWidgetBase,SkillNoteOtherJob" msgid "{0} only ยท Cannot equip" msgstr "{0} ์ „์šฉ ยท ์žฅ์ฐฉ ๋ถˆ๊ฐ€" #. Key: SkillNoteUnowned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1291) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1291) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1283) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1283) msgctxt "ShopUIWidgetBase,SkillNoteUnowned" msgid "{0} only ยท No mercenary owned" msgstr "{0} ์ „์šฉ ยท ๋ฏธ๋ณด์œ  ์šฉ๋ณ‘" #. Key: SkillNoteCommon -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1297) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1297) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1289) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1289) msgctxt "ShopUIWidgetBase,SkillNoteCommon" msgid "Common skill" msgstr "๊ณต์šฉ ์Šคํ‚ฌ" #. Key: SkillNoteJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1298) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1298) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1290) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1290) msgctxt "ShopUIWidgetBase,SkillNoteJob" msgid "{0} only" msgstr "{0} ์ „์šฉ" #. Key: SoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1573) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1573) msgctxt "ShopUIWidgetBase,SoldOut" msgid "Sold Out" msgstr "ํ’ˆ์ ˆ" #. Key: RailOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1585) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1585) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1577) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1577) msgctxt "ShopUIWidgetBase,RailOwned" msgid "Owned" msgstr "๋ณด์œ " #. Key: RailPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1589) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1589) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1581) msgctxt "ShopUIWidgetBase,RailPrice" msgid "{0} G" msgstr "{0} G" #. Key: SelectedJobUnitCount -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1683) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1683) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1675) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1675) msgctxt "ShopUIWidgetBase,SelectedJobUnitCount" msgid "{0}/{1}" msgstr "{0}/{1}" #. Key: RestPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1792) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1792) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1784) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1784) msgctxt "ShopUIWidgetBase,RestPrice" msgid "{0} G" msgstr "{0} G" #. Key: RestUsed -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1869) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1869) msgctxt "ShopUIWidgetBase,RestUsed" msgid "Rest Complete" msgstr "ํœด์‹ ์™„๋ฃŒ" #. Key: RestNotAffordable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1881) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1881) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1873) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1873) msgctxt "ShopUIWidgetBase,RestNotAffordable" msgid "Not enough Gold" msgstr "๊ณจ๋“œ ๋ถ€์กฑ" #. Key: RestNow -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1885) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1885) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1877) msgctxt "ShopUIWidgetBase,RestNow" msgid "Rest" msgstr "ํœด์‹ํ•˜๊ธฐ" #. Key: NoShopItems -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1890) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1890) msgctxt "ShopUIWidgetBase,NoShopItems" msgid "No items for sale" msgstr "ํŒ๋งค ์ƒํ’ˆ์ด ์—†์Šต๋‹ˆ๋‹ค" #. Key: NoSelectedPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1898) msgctxt "ShopUIWidgetBase,NoSelectedPrice" msgid "-" msgstr "-" #. Key: Unavailable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1914) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1914) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1906) msgctxt "ShopUIWidgetBase,Unavailable" msgid "Unavailable" msgstr "๊ตฌ๋งค ๋ถˆ๊ฐ€" #. Key: SelectedSoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1951) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1951) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1943) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1943) msgctxt "ShopUIWidgetBase,SelectedSoldOut" msgid "Sold Out" msgstr "ํ’ˆ์ ˆ" #. Key: SelectedPrice -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1952) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1952) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1944) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1944) msgctxt "ShopUIWidgetBase,SelectedPrice" msgid "{0} G" msgstr "{0} G" #. Key: BuySoldOut -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1969) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1969) msgctxt "ShopUIWidgetBase,BuySoldOut" msgid "Sold Out" msgstr "ํ’ˆ์ ˆ" #. Key: BuyNotAffordable -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1973) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1973) msgctxt "ShopUIWidgetBase,BuyNotAffordable" msgid "Not enough Gold" msgstr "๊ณจ๋“œ ๋ถ€์กฑ" #. Key: BuySelectTarget -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1977) msgctxt "ShopUIWidgetBase,BuySelectTarget" msgid "Select Target" msgstr "๋Œ€์ƒ ์„ ํƒ" #. Key: BuyAlreadyOwned -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1981) msgctxt "ShopUIWidgetBase,BuyAlreadyOwned" msgid "Owned" msgstr "์ด๋ฏธ ๋ณด์œ " #. Key: BuyOtherJob -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1993) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1993) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1985) msgctxt "ShopUIWidgetBase,BuyOtherJob" msgid "Wrong job" msgstr "์ง์—… ๋ถˆ์ผ์น˜" #. Key: BuyUnownedTarget -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1997) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1997) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1989) msgctxt "ShopUIWidgetBase,BuyUnownedTarget" msgid "No Mercenary Owned" msgstr "๋ฏธ๋ณด์œ  ์šฉ๋ณ‘" #. Key: EquipSelectedSkill -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2007) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2007) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1999) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(1999) msgctxt "ShopUIWidgetBase,EquipSelectedSkill" msgid "Equip" msgstr "์žฅ์ฐฉ" #. Key: ReplaceSelectedSkill -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2008) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2008) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2000) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2000) msgctxt "ShopUIWidgetBase,ReplaceSelectedSkill" msgid "Replace" msgstr "๊ต์ฒด" #. Key: BuySelected -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2012) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2012) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2004) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2004) msgctxt "ShopUIWidgetBase,BuySelected" msgid "Buy" msgstr "๊ตฌ๋งค" #. Key: GoldAmount -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2049) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2049) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2041) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2041) msgctxt "ShopUIWidgetBase,GoldAmount" msgid "{0} G" msgstr "{0} G" @@ -9491,6 +9680,13 @@ msgctxt "ShopUIWidgetBase,Leave" msgid "Leave" msgstr "๋‚˜๊ฐ€๊ธฐ" +#. Key: [{0}] +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2109) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2109) +msgctxt "ShopUIWidgetBase,[{0}]" +msgid "[{0}]" +msgstr "[{0}]" + #. Key: Shop #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(211) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(211) @@ -9498,34 +9694,27 @@ msgctxt "ShopUIWidgetBase,Shop" msgid "Shop" msgstr "์ƒ์ " -#. Key: [{0}] -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2117) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2117) -msgctxt "ShopUIWidgetBase,[{0}]" -msgid "[{0}]" -msgstr "[{0}]" - -#. Key: ArtifactTab -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) -msgctxt "ShopUIWidgetBase,ArtifactTab" -msgid "Artifacts" -msgstr "์•„ํ‹ฐํŒฉํŠธ" - #. Key: Sold Out -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2154) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2154) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2146) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2146) msgctxt "ShopUIWidgetBase,Sold Out" msgid "Sold Out" msgstr "ํ’ˆ์ ˆ" #. Key: {0} G -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2155) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2155) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2147) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2147) msgctxt "ShopUIWidgetBase,{0} G" msgid "{0} G" msgstr "{0} G" +#. Key: ArtifactTab +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(215) +msgctxt "ShopUIWidgetBase,ArtifactTab" +msgid "Artifacts" +msgstr "์•„ํ‹ฐํŒฉํŠธ" + #. Key: SkillTab #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(219) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(219) @@ -9548,22 +9737,22 @@ msgid "Hire Mercenaries" msgstr "์šฉ๋ณ‘ ๊ณ ์šฉ" #. Key: [{0}] {1} Lv.{2} -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2290) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2290) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2282) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2282) msgctxt "ShopUIWidgetBase,[{0}] {1} Lv.{2}" msgid "[{0}] {1} Lv.{2}" msgstr "[{0}] {1} Lv.{2}" #. Key: S{0}: {1} -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2304) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2304) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2296) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2296) msgctxt "ShopUIWidgetBase,S{0}: {1}" msgid "S{0}: {1}" msgstr "S{0}: {1}" #. Key: - -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2306) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2306) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2298) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2298) msgctxt "ShopUIWidgetBase,-" msgid "-" msgstr "-" @@ -9590,82 +9779,89 @@ msgid "Inventory" msgstr "์ธ๋ฒคํ† ๋ฆฌ" #. Key: ArtifactFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2468) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2468) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2460) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2460) msgctxt "ShopUIWidgetBase,ArtifactFallbackDescription" msgid "This Artifact applies to the entire party." msgstr "ํŒŒํ‹ฐ ์ „์ฒด์— ์ ์šฉ๋˜๋Š” ์•„ํ‹ฐํŒฉํŠธ์ž…๋‹ˆ๋‹ค." #. Key: SkillFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2469) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2469) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2461) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2461) msgctxt "ShopUIWidgetBase,SkillFallbackDescription" msgid "Equips to the selected mercenary's skill slot." msgstr "์„ ํƒํ•œ ์šฉ๋ณ‘์˜ ์Šคํ‚ฌ ์Šฌ๋กฏ์— ์žฅ์ฐฉํ•ฉ๋‹ˆ๋‹ค." #. Key: ArtifactDetailType -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2522) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2522) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2514) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2514) msgctxt "ShopUIWidgetBase,ArtifactDetailType" msgid "Artifact ยท Party-wide" msgstr "์•„ํ‹ฐํŒฉํŠธ ยท ํŒŒํ‹ฐ ๊ณต์šฉ" #. Key: SkillDetailType -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2523) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2523) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2515) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2515) msgctxt "ShopUIWidgetBase,SkillDetailType" msgid "Skill ยท {0}" msgstr "์Šคํ‚ฌ ยท {0}" #. Key: ArtifactEffectHeading -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2526) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2526) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2518) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2518) msgctxt "ShopUIWidgetBase,ArtifactEffectHeading" msgid "Effect" msgstr "ํšจ๊ณผ" #. Key: SkillEffectHeading -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2527) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2527) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2519) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2519) msgctxt "ShopUIWidgetBase,SkillEffectHeading" msgid "Skill Effects" msgstr "์Šคํ‚ฌ ํšจ๊ณผ" #. Key: LevelUpTitle -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2691) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2691) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2680) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2680) msgctxt "ShopUIWidgetBase,LevelUpTitle" msgid "Level Up" msgstr "๋ ˆ๋ฒจ์—…" #. Key: LevelUpNoCandidates -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2710) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2710) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2699) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2699) msgctxt "ShopUIWidgetBase,LevelUpNoCandidates" msgid "There are no new skills available to learn" msgstr "๋ฐฐ์šธ ์ˆ˜ ์žˆ๋Š” ์ƒˆ ์Šคํ‚ฌ์ด ์—†์Šต๋‹ˆ๋‹ค" #. Key: LevelUpChooseOne -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2711) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2711) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2700) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2700) msgctxt "ShopUIWidgetBase,LevelUpChooseOne" msgid "Choose 1" msgstr "1๊ฐœ ์„ ํƒ" #. Key: LevelUpSkip -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2716) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2716) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2705) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2705) msgctxt "ShopUIWidgetBase,LevelUpSkip" msgid "Skip Reward" msgstr "๋ฐ›์ง€ ์•Š๊ธฐ" #. Key: LevelUpEquip -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2718) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2718) +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2707) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(2707) msgctxt "ShopUIWidgetBase,LevelUpEquip" msgid "Select and Equip" msgstr "์„ ํƒํ•˜์—ฌ ์žฅ์ฐฉ" +#. Key: OwnedSkillFallbackDescription +#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(848) +#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(848) +msgctxt "ShopUIWidgetBase,OwnedSkillFallbackDescription" +msgid "This skill is currently equipped." +msgstr "ํ˜„์žฌ ์žฅ์ฐฉ ์ค‘์ธ ์Šคํ‚ฌ์ž…๋‹ˆ๋‹ค." + #. Key: ShopJobKnight #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(85) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(85) @@ -9673,13 +9869,6 @@ msgctxt "ShopUIWidgetBase,ShopJobKnight" msgid "Knight" msgstr "๊ธฐ์‚ฌ" -#. Key: OwnedSkillFallbackDescription -#. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(852) -#: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(852) -msgctxt "ShopUIWidgetBase,OwnedSkillFallbackDescription" -msgid "This skill is currently equipped." -msgstr "ํ˜„์žฌ ์žฅ์ฐฉ ์ค‘์ธ ์Šคํ‚ฌ์ž…๋‹ˆ๋‹ค." - #. Key: ShopJobRanger #. SourceLocation: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(86) #: Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp(86) diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/CombatTargetObstacleModel.cpp b/Source/P_RD/Actor/BoardActor/Obstacle/CombatTargetObstacleModel.cpp index 85bc686c4..73897b4e9 100644 --- a/Source/P_RD/Actor/BoardActor/Obstacle/CombatTargetObstacleModel.cpp +++ b/Source/P_RD/Actor/BoardActor/Obstacle/CombatTargetObstacleModel.cpp @@ -41,6 +41,8 @@ void UCombatTargetObstacleModel::PostInitializeComponentModels() { SkillComp->SetSkillFrom(ObstacleSpawn->mSkillDatas); } + + SetDifficulty(1); } void UCombatTargetObstacleModel::OnBeginRoom() diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.cpp b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.cpp new file mode 100644 index 000000000..76f7d82b1 --- /dev/null +++ b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.cpp @@ -0,0 +1,41 @@ +๏ปฟ#include "Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.h" +#include "Setting/GameTeamType.h" + +UDeathGimmickModel::UDeathGimmickModel() +{ + mTeamId = EGameTeamType::AllHostile; + + // ์‚ฌ๋ง ์‹œ 1ํšŒ ๋ฐœ๋™ + mRemainingTriggerCount = 1; +} + +bool UDeathGimmickModel::IsTargetable() const +{ + // ์‚ด์•„์žˆ๋Š” ๋™์•ˆ ์Šคํ‚ฌ์˜ ์กฐ์ค€ ๋ฐ ํ”ผ๊ฒฉ ๋Œ€์ƒ์ด ๋จ + return Super::IsTargetable(); +} + +void UDeathGimmickModel::OnPostDead() +{ + Super::OnPostDead(); + + // ์‚ฌ๋ง ์‹œ ์ž๊ธฐ ํƒ€์ผ์„ ์กฐ์ค€ํ•ด ๊ธฐ๋ฏน ๋ฐœ๋™ + TryTriggerGimmick(GetTileTransform().mIndex); +} + +bool UDeathGimmickModel::CanTriggerGimmick() const +{ + // ์ˆ˜๋ช…์„ ๋‹ค ์ผ์œผ๋ฉด ๋ฐœ๋™ ๋ถˆ๊ฐ€ + if (mRemainingTriggerCount == 0) + { + return false; + } + + // ์‚ฌ๋ง ์ƒํƒœ์ธ๋ฐ ์‚ฌ๋ง ๋ฐœ๋™์ด ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฐœ๋™ ๋ถˆ๊ฐ€ + if (IsDead() == true && mCanTriggerWhenDead == false) + { + return false; + } + + return true; +} \ No newline at end of file diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.h b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.h new file mode 100644 index 000000000..a6da7cef1 --- /dev/null +++ b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/DeathGimmickModel.h @@ -0,0 +1,39 @@ +/*****************************************************************//** + * @file DeathGimmickModel.h + * @brief ์‚ฌ๋ง ํŠธ๋ฆฌ๊ฑฐ ๊ธฐ๋ฏน ๋ชจ๋ธ ์ •์˜ ํ—ค๋” + * @author ๋ชจํ˜ธ์žฌ + * @date 2026-09-21 + *********************************************************************/ + +#pragma once + +#include "RDMinimal.h" +#include "Actor/BoardActor/Obstacle/Gimmick/GimmickModel.h" +#include "DeathGimmickModel.generated.h" + +/** + * @brief ์‚ฌ๋ง ํŠธ๋ฆฌ๊ฑฐ ๊ธฐ๋ฏน ๋ชจ๋ธ (ํญ๋ฐœ ๋ฐฐ๋Ÿด ๋“ฑ) + * @details ์ฒด๋ ฅ์„ ์žƒ๊ณ  ์‚ฌ๋งํ•  ๋•Œ ์žฅ์ฐฉ๋œ ์Šคํ‚ฌ์„ ๋ฐœ๋™ํ•˜๋Š” ๊ธฐ๋ฏน์˜ ๋ฒ ์ด์Šค ํด๋ž˜์Šค. + * ์œ ๋‹›๊ณผ ๋™์ผํ•œ ํƒ€์ผ/๋ธ”๋ก ๋ ˆ์ด์–ด๋ฅผ ๊ฐ€์ ธ ๊ธธ์„ ๋ง‰๊ณ , ์‚ด์•„์žˆ๋Š” ๋™์•ˆ ์กฐ์ค€ ๋ฐ ํ”ผ๊ฒฉ ๋Œ€์ƒ์ด ๋จ. + */ +UCLASS(Blueprintable) +class P_RD_API UDeathGimmickModel : public UGimmickModel +{ + GENERATED_BODY() + +public: + UDeathGimmickModel(); + + /* IBoardCombatTarget ์ƒ์† */ +public: + bool IsTargetable() const override; + void OnPostDead() override; + +protected: + bool CanTriggerGimmick() const override; + +protected: + // @brief ์‚ฌ๋ง ์‹œ์—๋„ ๋ฐœ๋™์„ ํ—ˆ์šฉํ• ์ง€ ์—ฌ๋ถ€ (์‚ฌ๋ง ์‹œ ๋ฐœ๋™ํ•˜๋Š” ๊ธฐ๋ฏน์šฉ) + UPROPERTY(Category = "Gimmick", EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "CanTriggerWhenDead")) + bool mCanTriggerWhenDead = true; +}; diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.cpp b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.cpp index 812faf4ec..76204cffd 100644 --- a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.cpp +++ b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.cpp @@ -29,10 +29,15 @@ void UGimmickModel::PostInitializeComponentModels() mTriggerSkillIndex = GimmickSpawn->mTriggerSkillIndex; } +bool UGimmickModel::CanTriggerGimmick() const +{ + return mRemainingTriggerCount != 0 && IsDead() == false; +} + bool UGimmickModel::TryTriggerGimmick(const FTileIndex& AimedTileIndex, TSharedPtr PresentationBarrier) { - // ์ˆ˜๋ช…์„ ๋‹ค ์ผ๊ฑฐ๋‚˜ ์ฃฝ์€ ๊ธฐ๋ฏน์€ ๋ฐœ๋™ ๋ถˆ๊ฐ€ - if (mRemainingTriggerCount == 0 || IsDead() == true) + // ์ˆ˜๋ช…์„ ๋‹ค ์ผ๊ฑฐ๋‚˜ ์ฃฝ์€ ๊ธฐ๋ฏน ๋“ฑ ๋ฐœ๋™ ์กฐ๊ฑด์— ๋งž์ง€ ์•Š์œผ๋ฉด ๋ถˆ๊ฐ€ + if (CanTriggerGimmick() == false) { return false; } @@ -53,16 +58,15 @@ bool UGimmickModel::TryTriggerGimmick(const FTileIndex& AimedTileIndex, TSharedP --mRemainingTriggerCount; } + USRPGCombatModel* CombatModel = GetWorldSubsystemModel(this); + checkf(CombatModel != nullptr, TEXT("์ „ํˆฌ ๋ชจ๋ธ nullptr")); + TSharedPtr EndHoldBarrier = CombatModel->GetCurrentActionEndHoldBarrier(); + // ์žฅ์ฐฉ๋œ ์Šคํ‚ฌ ๊ฐ•์ œ ์‹œ์ „ (๊ธฐ๋ฏน์€ ํ–‰๋™๋ ฅ ๊ฐœ๋…์ด ์—†์œผ๋ฏ€๋กœ ์†Œ๋ชจ ๊ฒ€์‚ฌ ์—†์ด ์‹œ์ „) FOnEndSkillUI EndCallback; - EndCallback.AddUObject(this, &UGimmickModel::OnGimmickSkillEnd); - - // ๋ฐฐ๋ฆฌ์–ด๋ฅผ ๋ฐ›์•˜์œผ๋ฉด, ๋ฐฐ๋ฆฌ์–ด ํฌ์ธํ„ฐ๋ฅผ ์บก์ฒ˜ํ•œ ๋นˆ ๋žŒ๋‹ค๋ฅผ ์ข…๋ฃŒ ์ฝœ๋ฐฑ์— ์ถ”๊ฐ€ - // ์Šคํ‚ฌ์ด ๋๋‚˜๋ฉด ์ฝœ๋ฐฑ์ด ์ •๋ฆฌ๋˜๊ณ , ๋žŒ๋‹ค๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด์„œ ์บก์ฒ˜๋œ ํฌ์ธํ„ฐ๋„ ํ•จ๊ป˜ ํ•ด์ œ๋จ - if (PresentationBarrier.IsValid() == true) - { - EndCallback.AddLambda([PresentationBarrier](const FActiveSkillContext&, const UStaticSkillData*) {}); - } + EndCallback.AddWeakLambda(this, [this, PresentationBarrier, EndHoldBarrier](const FActiveSkillContext& Context, const UStaticSkillData* SkillData) { + OnGimmickSkillEnd(Context, SkillData); + }); SkillComp->ForcedActivateSkill(GetTileMap(), mTriggerSkillIndex, AimedTileIndex, EndCallback); return true; diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.h b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.h index b80462ecf..f5070f09c 100644 --- a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.h +++ b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/GimmickModel.h @@ -34,6 +34,9 @@ class P_RD_API UGimmickModel : public UCombatTargetObstacleModel /* ๋ฐœ๋™ ๊ณตํ†ต๋ถ€ */ protected: + // @brief ๊ธฐ๋ฏน ๋ฐœ๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์‚ฌ (๊ธฐ๋ณธ: ์ˆ˜๋ช…์ด ๋‚จ์•„์žˆ๊ณ  ์‚ฌ๋งํ•˜์ง€ ์•Š์Œ) + virtual bool CanTriggerGimmick() const; + /** * @brief ๊ธฐ๋ฏน ๋ฐœ๋™ ์‹œ๋„ (ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๊ฐ์ง€ํ•œ ํŒŒ์ƒ ํด๋ž˜์Šค๊ฐ€ ํ˜ธ์ถœ) * @details ์žฅ์ฐฉ๋œ ์Šคํ‚ฌ์„ ๊ฐ•์ œ ์‹œ์ „ํ•˜๊ณ  ์ˆ˜๋ช…์„ ์ฐจ๊ฐ. diff --git a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/OverlapGimmickModel.cpp b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/OverlapGimmickModel.cpp index bcd3a4ce3..eea029e45 100644 --- a/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/OverlapGimmickModel.cpp +++ b/Source/P_RD/Actor/BoardActor/Obstacle/Gimmick/OverlapGimmickModel.cpp @@ -7,6 +7,10 @@ #include "Actor/BoardActor/Obstacle/Gimmick/OverlapGimmickModel.h" +#include "Actor/BoardActor/BoardCombatTarget.h" +#include "Component/BoardMovementComponent/BoardMovementComponentModel.h" +#include "Singleton/WorldSubsystem/PresentationBarrier.h" + UOverlapGimmickModel::UOverlapGimmickModel() { // ์œ ๋‹›์ด ๋ฐŸ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ ์œ ๋‹› ์•„๋ž˜ ๊น”๋ฆฌ๋Š” Overlay ๋ ˆ์ด์–ด + ํ†ตํ–‰ ๋น„์ฐจ๋‹จ์œผ๋กœ ์žฌ์„ค์ • @@ -31,6 +35,18 @@ void UOverlapGimmickModel::OnBeginTileOverlap(FTile* CurTile, UBoardActorModel* return; } + // ๋ฐŸ์€ ์œ ๋‹›์ด ๋ฐ€๋‹น ์ค‘์ด๋ฉด ๊ทธ ์ด๋™์˜ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์Šคํ‚ฌ์— ๋„˜๊น€ + // -> ์ด ํ•จ์ • ์Šคํ‚ฌ์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฐ€๋‹นํ•œ ์ชฝ์˜ ํŽ˜์ด์ฆˆ๊ฐ€ ๊ธฐ๋‹ค๋ฆผ (ํ•จ์ • ์—ฐ์‡„๊ฐ€ ํŽ˜์ด์ฆˆ ์•ˆ์— ํฌํ•จ๋จ) + // ๊ฑท๋‹ค๊ฐ€ ๋ฐŸ์•˜๊ฑฐ๋‚˜ ๋ฐฐ์น˜๋กœ ๊ฒน์นœ ๊ฒฝ์šฐ๋Š” ๋ฐฐ๋ฆฌ์–ด๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๊ธฐ์กด๊ณผ ๋™์ผ + TSharedPtr MoveEndBarrier; + if (IBoardCombatTarget* OtherCombatTarget = Cast(Other)) + { + if (UBoardMovementComponentModel* OtherMoveComp = OtherCombatTarget->GetBoardMovementComponentModel()) + { + MoveEndBarrier = OtherMoveComp->GetMoveEndBarrier(); + } + } + // ๋ฐŸํžŒ ์ž๋ฆฌ(์ž๊ธฐ ํƒ€์ผ)๋ฅผ ์กฐ์ค€ํ•ด ๋ฐœ๋™ - TryTriggerGimmick(GetTileTransform().mIndex); + TryTriggerGimmick(GetTileTransform().mIndex, MoveEndBarrier); } diff --git a/Source/P_RD/Actor/TileMap/TileMapModel.cpp b/Source/P_RD/Actor/TileMap/TileMapModel.cpp index 7646e8607..da1d78d81 100644 --- a/Source/P_RD/Actor/TileMap/TileMapModel.cpp +++ b/Source/P_RD/Actor/TileMap/TileMapModel.cpp @@ -907,7 +907,7 @@ bool UTileMapModel::IsInAimPattern(const FTileIndex& Origin, const FTileIndex& T case EAimPattern::Square: { // ์ค‘์‹ฌ ๊ธฐ์ค€ ์‚ฌ๊ฐํ˜• ๋ฒ”์œ„: ์ฒด๋น„์…ฐํ”„ ๊ฑฐ๋ฆฌ๊ฐ€ ์‚ฌ๊ฑฐ๋ฆฌ ์ด๋‚ด (๊ธฐ์ค€ ํƒ€์ผ ์ œ์™ธ) - const int32 Chebyshev = FMath::Max(FMath::Abs(DeltaX), FMath::Abs(DeltaY)); + const int32 Chebyshev = FTileIndex::ChebyshevDistance(Origin, Target); return Chebyshev != 0 && Chebyshev <= Range; } diff --git a/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.cpp b/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.cpp index daf2769eb..d3f792ce3 100644 --- a/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.cpp +++ b/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.cpp @@ -15,17 +15,17 @@ bool UBoardMovementComponentModel::MoveAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished) { - return StartPathInternal(PathTileIndexes, EBoardMoveMode::Normal, OnFinished); + return StartPathInternal(PathTileIndexes, EBoardMoveMode::Normal, OnFinished, nullptr); } -bool UBoardMovementComponentModel::PushAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished) +bool UBoardMovementComponentModel::PushAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished, TSharedPtr MoveEndBarrier) { - return StartPathInternal(PathTileIndexes, EBoardMoveMode::Push, OnFinished); + return StartPathInternal(PathTileIndexes, EBoardMoveMode::Push, OnFinished, MoveEndBarrier); } -bool UBoardMovementComponentModel::PullAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished) +bool UBoardMovementComponentModel::PullAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished, TSharedPtr MoveEndBarrier) { - return StartPathInternal(PathTileIndexes, EBoardMoveMode::Pull, OnFinished); + return StartPathInternal(PathTileIndexes, EBoardMoveMode::Pull, OnFinished, MoveEndBarrier); } bool UBoardMovementComponentModel::TeleportTo(const FTileTransform& NextTransform, FOnBoardMoveFinished OnFinished) @@ -88,7 +88,7 @@ bool UBoardMovementComponentModel::TryRegisterPendingPush(const FTileIndex& Trap return true; } -bool UBoardMovementComponentModel::StartPathInternal(const TArray& PathTileIndexes, EBoardMoveMode MoveMode, FOnBoardMoveFinished OnFinished) +bool UBoardMovementComponentModel::StartPathInternal(const TArray& PathTileIndexes, EBoardMoveMode MoveMode, FOnBoardMoveFinished OnFinished, TSharedPtr MoveEndBarrier) { // ์ด๋™ ์ค‘ ์žฌํ˜ธ์ถœ์ด๊ฑฐ๋‚˜ ๊ฒฝ๋กœ๊ฐ€ 2์นธ ๋ฏธ๋งŒ์ด๋ฉด ์‹œ์ž‘ ๊ฑฐ๋ถ€ if (IsMoving() == true || PathTileIndexes.Num() < 2) @@ -99,6 +99,7 @@ bool UBoardMovementComponentModel::StartPathInternal(const TArray& P mPathTileIndexes = PathTileIndexes; mMoveMode = MoveMode; mOnFinished = OnFinished; + mMoveEndBarrier = MoveEndBarrier; mCancelRequested = false; // ์ฒซ ์นธ์ด ์ด๋ฏธ ๋ง‰ํ˜”์œผ๋ฉด ์‹œ์ž‘ ์•ˆ ํ•จ (๊ฒฝ๋กœ ๊ณ„์‚ฐ ๋’ค ๋‹ค๋ฅธ ์œ ๋‹›์ด ๋จผ์ € ์ฐจ์ง€ํ•œ ๊ฒฝ์šฐ ๋“ฑ) @@ -222,6 +223,8 @@ void UBoardMovementComponentModel::OnStepPresentationFinished() // ์ทจ์†Œ ์š”์ฒญ๋์œผ๋ฉด ์™„๋ฃŒ ํ†ต์ง€ ์—†์ด ์ •์ง€ (๋ทฐ๊ฐ€ ๊ฑท๊ธฐ ์—ฐ์ถœ์„ ๋ฉˆ์ถ”๋„๋ก ๊ฒฝ๋กœ ์ข…๋ฃŒ๋Š” ํ†ต์ง€) if (mCancelRequested == true) { + // ์ด๋™ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด๊ฐ€ ResetMoveState ์‹คํ–‰์—๋„ ์‚ด์•„๋‚จ๋„๋ก ๋กœ์ปฌ ๋ณ€์ˆ˜์— ์ €์žฅ + TSharedPtr MoveEndBarrier = MoveTemp(mMoveEndBarrier); ResetMoveState(); BroadcastEndMovePath(); return; @@ -273,6 +276,8 @@ void UBoardMovementComponentModel::OnStepPresentationFinished() // ํ†ต์ง€๋ฅผ ๋ฐ›์€ ์ชฝ์ด ๋ฐ”๋กœ ์ƒˆ ์ด๋™์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ƒํƒœ๋ฅผ ๋จผ์ € ๋น„์šฐ๊ณ  ํ˜ธ์ถœ (๋น„์šฐ๋ฉด mOnFinished๋„ ์ง€์›Œ์ง€๋‹ˆ ๋ณต์‚ฌํ•ด ๋‘ ) // ๋ทฐ์˜ ๊ฒฝ๋กœ ์ข…๋ฃŒ ์ •๋ฆฌ๊ฐ€ ์™„๋ฃŒ ํ†ต์ง€๋ณด๋‹ค ๋จผ์ € ๋๋‚˜์•ผ ๋‹ค์Œ ์ด๋™ ์—ฐ์ถœ๊ณผ ์„ž์ด์ง€ ์•Š์Œ FOnBoardMoveFinished Finished = mOnFinished; + // ์ด๋™ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด๊ฐ€ ResetMoveState ์‹คํ–‰์—๋„ ์‚ด์•„๋‚จ๋„๋ก ๋กœ์ปฌ ๋ณ€์ˆ˜์— ์ €์žฅ + TSharedPtr MoveEndBarrier = MoveTemp(mMoveEndBarrier); ResetMoveState(); BroadcastEndMovePath(); Finished.ExecuteIfBound(); @@ -292,6 +297,7 @@ void UBoardMovementComponentModel::ResetMoveState() mCurrentStepIndex = INDEX_NONE; mCancelRequested = false; mOnFinished.Unbind(); + mMoveEndBarrier.Reset(); // ์—ฐ์‡„ ์ƒํƒœ ์ •๋ฆฌ (mMoveMode๋Š” ์œ ์ง€ํ•ด์„œ GetMoveMode()๊ฐ€ ๋งˆ์ง€๋ง‰ ๋ชจ๋“œ ๋ฐ˜ํ™˜) mChainedTrapTiles.Empty(); diff --git a/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.h b/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.h index 534c51880..d677d2f0b 100644 --- a/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.h +++ b/Source/P_RD/Component/BoardMovementComponent/BoardMovementComponentModel.h @@ -14,6 +14,7 @@ #include "BoardMovementComponentModel.generated.h" class UTileMapModel; +struct FPresentationBarrier; // @brief ์ด๋™ ์™„๋ฃŒ ํ†ต์ง€ ๋Œ€๋ฆฌ์ž (MoveAlongPath/PushAlongPath ํ˜ธ์ถœ์ž๊ฐ€ ์š”์ฒญ ๋‹จ์œ„๋กœ ๋ฐ›์Œ, ์ทจ์†Œ ์‹œ์—” ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ) DECLARE_DELEGATE(FOnBoardMoveFinished); @@ -47,18 +48,20 @@ class P_RD_API UBoardMovementComponentModel : public UComponentModel * @details ์ผ๋ฐ˜ ์ด๋™๊ณผ ๋‹ฌ๋ฆฌ ๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ ์œ ์ง€, AP ๋ฏธ์ฐจ๊ฐ. ๊ทธ ์™ธ ์Šคํ… ๋ฃจํ”„/๋ฒ ๋ฆฌ์–ด/์˜ค๋ฒ„๋žฉ์€ ๊ณต์œ  * @param PathTileIndexes ์‹œ์ž‘โ†’๋ชฉํ‘œ ๊ฒฝ๋กœ (์–‘ ๋ ํฌํ•จ, ์ธ๋ฑ์Šค 0 = ํ˜„์žฌ ํƒ€์ผ). ๋ฒฝ์ด๋‚˜ ์žฅ์• ๋ฌผ์— ๋ง‰ํžˆ๋Š” ๊ฑด ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•ด์„œ ๊ฒฝ๋กœ๋กœ ์ค˜์•ผํ•œ๋‹ค * @param OnFinished ์ด๋™ ์™„๋ฃŒ ํ†ต์ง€ + * @param MoveEndBarrier ์ด๋™ ์ข…๋ฃŒ(ํ•จ์ • ์—ฐ์‡„ ํฌํ•จ)๊นŒ์ง€ ๋ณด์œ ํ•  ๋ฐฐ๋ฆฌ์–ด. ๋ฐŸ์€ ํ•จ์ • ์Šคํ‚ฌ์—๋„ ์ „๋‹ฌ๋˜์–ด ๊ทธ ์Šคํ‚ฌ ์ข…๋ฃŒ๊นŒ์ง€ ์—ฐ์žฅ * @return ์‹œ์ž‘ ์„ฑ๊ณต ์—ฌ๋ถ€ (์ด๋™ ์ค‘ ์žฌํ˜ธ์ถœ์ด๊ฑฐ๋‚˜ ๊ฒฝ๋กœ๊ฐ€ 2์นธ ๋ฏธ๋งŒ์ด๋ฉด false) */ - bool PushAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished = FOnBoardMoveFinished()); + bool PushAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished = FOnBoardMoveFinished(), TSharedPtr MoveEndBarrier = nullptr); /** * @brief ํ™•์ • ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ๋‹น๊ธฐ๊ธฐ(๊ฐ•์ œ ์ด๋™) ์‹œ์ž‘ * @details ๋ฐ€์น˜๊ธฐ์™€ ๊ฐ™์€ ๊ทœ์น™ (๋ฐ”๋ผ๋ณด๋Š” ๋ฐฉํ–ฅ ์œ ์ง€, AP ๋ฏธ์ฐจ๊ฐ). ์ด๋™ ๋ชจ๋“œ๋งŒ ๋‹น๊ธฐ๊ธฐ๋กœ ๊ตฌ๋ถ„ * @param PathTileIndexes ์‹œ์ž‘โ†’๋ชฉํ‘œ ๊ฒฝ๋กœ (์–‘ ๋ ํฌํ•จ, ์ธ๋ฑ์Šค 0 = ํ˜„์žฌ ํƒ€์ผ). ์–ด๋””์„œ ๋ฉˆ์ถœ์ง€๋Š” ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•ด์„œ ๊ฒฝ๋กœ๋กœ ์ค˜์•ผํ•œ๋‹ค * @param OnFinished ์ด๋™ ์™„๋ฃŒ ํ†ต์ง€ + * @param MoveEndBarrier ์ด๋™ ์ข…๋ฃŒ(ํ•จ์ • ์—ฐ์‡„ ํฌํ•จ)๊นŒ์ง€ ๋ณด์œ ํ•  ๋ฐฐ๋ฆฌ์–ด. ๋ฐŸ์€ ํ•จ์ • ์Šคํ‚ฌ์—๋„ ์ „๋‹ฌ๋˜์–ด ๊ทธ ์Šคํ‚ฌ ์ข…๋ฃŒ๊นŒ์ง€ ์—ฐ์žฅ * @return ์‹œ์ž‘ ์„ฑ๊ณต ์—ฌ๋ถ€ (์ด๋™ ์ค‘ ์žฌํ˜ธ์ถœ์ด๊ฑฐ๋‚˜ ๊ฒฝ๋กœ๊ฐ€ 2์นธ ๋ฏธ๋งŒ์ด๋ฉด false) */ - bool PullAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished = FOnBoardMoveFinished()); + bool PullAlongPath(const TArray& PathTileIndexes, FOnBoardMoveFinished OnFinished = FOnBoardMoveFinished(), TSharedPtr MoveEndBarrier = nullptr); /** * @brief ๋ชฉํ‘œ ํƒ€์ผ๋กœ ์ฆ‰์‹œ ์ด๋™(ํ…”๋ ˆํฌํŠธ) ์‹œ์ž‘ @@ -87,6 +90,9 @@ class P_RD_API UBoardMovementComponentModel : public UComponentModel // @brief ํ˜„์žฌ ์ด๋™ ๋ชจ๋“œ (์ด๋™ ์ค‘์ด ์•„๋‹ˆ๋ฉด ๋งˆ์ง€๋ง‰ ๋ชจ๋“œ) EBoardMoveMode GetMoveMode() const; + // @brief ์š”์ฒญ์ž๊ฐ€ ๋„˜๊ธด ์ด๋™ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด. ์ด ์ด๋™์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ชฝ์ด ์—†์œผ๋ฉด nullptr (์ด๋™ ์ค‘ ์—ฌ๋ถ€๋Š” IsMoving) + TSharedPtr GetMoveEndBarrier() const { return mMoveEndBarrier; } + /** * @brief ์ง„ํ–‰ ์ค‘์ธ ์ด๋™ ์ทจ์†Œ * @details ์ง„ํ–‰ ์ค‘์ธ ์Šคํ…์˜ ์—ฐ์ถœ์ด ๋๋‚˜๋Š” ์‹œ์ ์— ์ •์ง€, ์™„๋ฃŒ ํ†ต์ง€ ์—†์Œ @@ -109,7 +115,7 @@ class P_RD_API UBoardMovementComponentModel : public UComponentModel /* ์Šคํ… ์ฒ˜๋ฆฌ */ private: // @brief ๊ณต์šฉ ์ด๋™ ์‹œ์ž‘ (MoveAlongPath/PushAlongPath/PullAlongPath์˜ ์‹ค์ œ ๊ตฌํ˜„) - bool StartPathInternal(const TArray& PathTileIndexes, EBoardMoveMode MoveMode, FOnBoardMoveFinished OnFinished); + bool StartPathInternal(const TArray& PathTileIndexes, EBoardMoveMode MoveMode, FOnBoardMoveFinished OnFinished, TSharedPtr MoveEndBarrier); // @brief ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ์›”๋“œ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ทฐ์— ํ†ต์ง€ (์ด๋™ ์‹œ์ž‘/๊ฒฝ๋กœ ๊ต์ฒด ๊ณต์šฉ) void BroadcastStartMovePath(); // @brief ์ด๋™ ์š”์ฒญ ์ „์ฒด ์ข…๋ฃŒ๋ฅผ ๋ทฐ์— ํ†ต์ง€ (์™„๋ฃŒ/์ทจ์†Œ ๊ณต์šฉ, ๊ฒฝ๋กœ ์ค‘๊ฐ„ ์ •์ง€ ํฌํ•จ) @@ -156,4 +162,7 @@ class P_RD_API UBoardMovementComponentModel : public UComponentModel // @brief ์ด๋ฒˆ ์ด๋™์˜ ์™„๋ฃŒ ํ†ต์ง€ ๋Œ€๋ฆฌ์ž FOnBoardMoveFinished mOnFinished; + + // @brief ์š”์ฒญ์ž๊ฐ€ ๋„˜๊ธด ์ด๋™ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด (์ข…๋ฃŒ ํ†ต์ง€๊นŒ์ง€ ๋งˆ์นœ ๋’ค ํ•ด์ œ ๋จ) + TSharedPtr mMoveEndBarrier; }; diff --git a/Source/P_RD/Component/SkillComponent/SkillComponentModel.cpp b/Source/P_RD/Component/SkillComponent/SkillComponentModel.cpp index bc8dd777b..2035aa61f 100644 --- a/Source/P_RD/Component/SkillComponent/SkillComponentModel.cpp +++ b/Source/P_RD/Component/SkillComponent/SkillComponentModel.cpp @@ -73,6 +73,8 @@ void FActiveSkillContext::Clear() mAnimationIndex = INDEX_NONE; mPhaseIndex = INDEX_NONE; + mIsDeactivationPending = false; + mEndCallback.Clear(); mFinalTileIndexes.Reset(); @@ -438,8 +440,22 @@ void USkillComponentModel::TriggerPhaseLayer(const FEventTriggerPayloadBase* Pay IBoardCombatTarget* OwnerCombatTarget = GetOwnerModel(); checkf(OwnerCombatTarget != nullptr, TEXT("์Šคํ‚ฌ์„ ์‹œ์ „ํ•  Owner๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์Œ")); + // ์•ž ํŽ˜์ด์ฆˆ๊ฐ€ ๋ฐ€๋‹น ์ข…๋ฃŒ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘์ด๊ฑฐ๋‚˜ ๋‚จ์€ ํŽ˜์ด์ฆˆ๊ฐ€ ์—†์œผ๋ฉด ๋…ธํ‹ฐํŒŒ์ด ๋ฌด์‹œ + if (IsWaitingForcedMove() == true || mActiveSkillContext.mPhaseIndex >= SkillData->mSkillPhaseLayers.Num()) + { + return; + } + const FSkillPhaseLayer& PhaseLayer = SkillData->mSkillPhaseLayers[mActiveSkillContext.mPhaseIndex]; + /* ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด */ + + // ์ด ๋ฐฐ๋ฆฌ์–ด๊ฐ€ ํ’€๋ฆฌ๋ฉด EndPhaseLayer๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ํŽ˜์ด์ฆˆ๊ฐ€ ๋๋‚จ + // ๋ฐ€๋‹น์ด ์žˆ์œผ๋ฉด ๋Œ€๊ธฐ์—ด์ด ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์žก๊ณ  ์žˆ๋‹ค๊ฐ€ ๋ชจ๋“  ๋Œ€์ƒ์ด ๋‹ค ๋ฐ€๋ฆฐ ๋’ค์— ํ’€๊ณ , ๋ฐ€๋‹น์ด ์—†์œผ๋ฉด ์ด ํ•จ์ˆ˜ ๋์—์„œ ๋ฐ”๋กœ ํ’€๋ฆผ + TSharedPtr PhaseBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + EndPhaseLayer(); + })); + /* ๋ชจ์…˜ ๋กœ๊ทธ ์‹œ์ž‘ */ GetWorldEventLogger(this)->BeginMotionLog(); @@ -485,7 +501,7 @@ void USkillComponentModel::TriggerPhaseLayer(const FEventTriggerPayloadBase* Pay } } - /* ์‹ค์ œ Effect ์ ์šฉ */ + /* ์‹ค์ œ Effect ์ ์šฉ (๋ฐ€๋‹น์€ ๋Œ€๊ธฐ์—ด์— ๋“ฑ๋ก๋งŒ ๋จ) */ { UBoardCombatTargetSnapshotData* OwnerSnapshot = OwnerCombatTarget->MakeSnapshotData(); @@ -510,40 +526,71 @@ void USkillComponentModel::TriggerPhaseLayer(const FEventTriggerPayloadBase* Pay mActiveSkillContext.mFinalTileIndexes, mActiveSkillContext.mAimedTileIndex ); + + // ์ดํŽ™ํŠธ๋ฅผ ์ ์šฉํ•˜๋Š” ์ค‘์— ๋“ค์–ด์˜จ ๋ฐ€๋‹น ์š”์ฒญ์€ ๋Œ€๊ธฐ์—ด์— ๋ชจ์ž„ + mShouldEnqueueForcedMove = true; for (int32 i = 0; i < EffectLayerNum; ++i) { const TInstancedStruct& EffectLayer = PhaseLayer.mSkillEffectLayers[i]; EffectLayer.Get().CommitEffect(Params); } + mShouldEnqueueForcedMove = false; } - /* ์ดํŽ™ํŠธ ํ›„ ์ด๋ฒคํŠธ๋“ค */ + /* Effect ํฌ์ธํŠธ ์ˆ˜์น˜ ๋น„์šฐ๊ธฐ */ { - UBoardCombatTargetSnapshotData* OwnerSnapshot = OwnerCombatTarget->MakeSnapshotData(); - - for (IBoardCombatTarget* OtherCombatTarget : mActiveSkillContext.mFinalCombatTargets) + for (int32 i = 0; i < EffectLayerNum; ++i) { - OtherCombatTarget->OnEndReceivingEffects(OwnerSnapshot, mActiveSkillContext, mActiveSkillContext.mPhaseIndex); + const TInstancedStruct& EffectLayer = PhaseLayer.mSkillEffectLayers[i]; + EffectLayer.Get().ClearFactorEffect(OwnerCombatTarget, FactorEffectHandleContainers[i].mHandles); } } - OwnerCombatTarget->OnEndApplyingEffects(mActiveSkillContext, mActiveSkillContext.mPhaseIndex); - /* Effect ํฌ์ธํŠธ ์ˆ˜์น˜ ๋น„์šฐ๊ธฐ */ + /* ๋ฏธ๋ค„๋†จ๋˜ ๋ฐ€๋‹น ์š”์ฒญ ์ˆœ์ฐจ ์ฒ˜๋ฆฌ */ + // ์ดํŽ™ํŠธ ์ ์šฉ ์ค‘์— ๋ชจ์•„๋‘” ๋ฐ€๋‹น ์š”์ฒญ์ด ์žˆ์œผ๋ฉด ์ง€๊ธˆ๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌ + // ๋Œ€๊ธฐ์—ด์ด ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ๋งˆ์ง€๋ง‰ ์š”์ฒญ๊นŒ์ง€ ๋‹ค ์ฒ˜๋ฆฌ๋œ ๋’ค์—์•ผ ๋ฐฐ๋ฆฌ์–ด๊ฐ€ ํ’€๋ฆฌ๊ณ  ํŽ˜์ด์ฆˆ๊ฐ€ ๋๋‚œ๋‹ค + if (mPendingForcedMoves.IsEmpty() == false) { - for (int32 i = 0; i < EffectLayerNum; ++i) + mForcedMovePhaseBarrier = PhaseBarrier; + StartNextForcedMove(); + } + + // ์ด ํ•จ์ˆ˜๊ฐ€ ๋“ค๊ณ  ์žˆ๋˜ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ๋†“๋Š”๋‹ค + // ๋ฐ€๋‹น์ด ์—†์—ˆ์œผ๋ฉด ์ด๊ฒŒ ๋งˆ์ง€๋ง‰ ์ฐธ์กฐ๋ผ์„œ ์—ฌ๊ธฐ์„œ ๋ฐ”๋กœ EndPhaseLayer๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค + // EndPhaseLayer ์•ˆ์—์„œ mPhaseIndex ๋“ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ฐ”๋€Œ๋ฏ€๋กœ ์ด ์ค„ ๋’ค์— ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ๋‘๋ฉด ์•ˆ ๋œ๋‹ค + PhaseBarrier.Reset(); +} + +void USkillComponentModel::EndPhaseLayer() +{ + checkf(mSkillEntries.IsValidIndex(mActiveSkillContext.mSkillIndex) == true, TEXT("์ž˜๋ชป๋œ ์‚ฌ์šฉ ์Šคํ‚ฌ ์ธ๋ฑ์Šค")); + + FSkillEntry& SkillEntry = mSkillEntries[mActiveSkillContext.mSkillIndex]; + const UStaticSkillData* SkillData = SkillEntry.mData; + checkf(SkillEntry.IsValid() == true, TEXT("๋นˆ ์Šคํ‚ฌ ์‹œ์ „ ์˜ค๋ฅ˜")); + + IBoardCombatTarget* OwnerCombatTarget = GetOwnerModel(); + checkf(OwnerCombatTarget != nullptr, TEXT("์Šคํ‚ฌ์„ ์‹œ์ „ํ•  Owner๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์Œ")); + + /* ์ดํŽ™ํŠธ ํ›„ ์ด๋ฒคํŠธ๋“ค */ + + { + UBoardCombatTargetSnapshotData* OwnerSnapshot = OwnerCombatTarget->MakeSnapshotData(); + + for (IBoardCombatTarget* OtherCombatTarget : mActiveSkillContext.mFinalCombatTargets) { - const TInstancedStruct& EffectLayer = PhaseLayer.mSkillEffectLayers[i]; - EffectLayer.Get().ClearFactorEffect(OwnerCombatTarget, FactorEffectHandleContainers[i].mHandles); + OtherCombatTarget->OnEndReceivingEffects(OwnerSnapshot, mActiveSkillContext, mActiveSkillContext.mPhaseIndex); } } + OwnerCombatTarget->OnEndApplyingEffects(mActiveSkillContext, mActiveSkillContext.mPhaseIndex); /* ๋ชจ์…˜ ๋กœ๊ทธ ์ข…๋ฃŒ */ GetWorldEventLogger(this)->EndMotionLog(); - /* ํŽ˜์ด์ฆˆ ์‹œ์ž‘ ์‹œ ๋Œ€๋ฆฌ์ž ํ˜ธ์ถœ */ + /* ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ ์‹œ ๋Œ€๋ฆฌ์ž ํ˜ธ์ถœ */ OnEndPhaseLayerUI.Broadcast(mActiveSkillContext.mPhaseIndex); @@ -556,6 +603,17 @@ void USkillComponentModel::TriggerPhaseLayer(const FEventTriggerPayloadBase* Pay PreparePhaseLayer(); } + + /* ๋ณด๋ฅ˜ํ–ˆ๋˜ ์Šคํ‚ฌ ์ข…๋ฃŒ ์žฌ๊ฐœ */ + + // ๋ฐ€๋‹น์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ์‹œ์ „์ž ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋จผ์ € ๋๋‚ฌ์œผ๋ฉด DeactivateSkill์ด ๋ณด๋ฅ˜ํ•˜๊ณ  ๋Œ์•„๊ฐ”์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ๋ถ€๋ฅธ๋‹ค + // ๋ณด๋ฅ˜๋œ ์  ์—†์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ํ•จ + // - ์‹œ์ „์ž ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์•„์ง ์ง„ํ–‰ ์ค‘์ด๋ฉด, ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋๋‚  ๋•Œ DeactivateSkill์ด ๋ถˆ๋ฆผ + // - DeactivateSkill์ด ์ด๋ฏธ ์‹คํ–‰ ์ค‘์ด๋ฉด, ๊ทธ์ชฝ์ด ๊ณ„์† ์ง„ํ–‰ํ•จ + if (mActiveSkillContext.mIsDeactivationPending == true) + { + DeactivateSkill(); + } } void USkillComponentModel::FlushRemainingPhaseLayers() @@ -568,6 +626,11 @@ void USkillComponentModel::FlushRemainingPhaseLayers() while (mActiveSkillContext.mPhaseIndex < SkillData->mSkillPhaseLayers.Num()) { + // ๋ฐ€๋‹น์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ํŽ˜์ด์ฆˆ๊ฐ€ ์ƒ๊ธฐ๋ฉด ๋ฉˆ์ถค. ๋ฐ€๋‹น์ด ๋๋‚˜๋ฉด DeactivateSkill์ด ๋‹ค์‹œ ๋ถˆ๋ ค์„œ ๋‚˜๋จธ์ง€๋ฅผ ์ด์–ด๊ฐ + if (IsWaitingForcedMove() == true) + { + break; + } TriggerPhaseLayer(nullptr); } } @@ -581,10 +644,27 @@ void USkillComponentModel::DeactivateSkill() IBoardCombatTarget* OwnerCombatTarget = GetOwnerModel(); checkf(OwnerCombatTarget != nullptr, TEXT("์Šคํ‚ฌ์„ ์‹œ์ „ํ•  Owner๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์Œ")); + /* ๋ฐ€๋‹น ๋Œ€๊ธฐ ์ค‘์ด๋ฉด ์Šคํ‚ฌ ์ข…๋ฃŒ ๋ณด๋ฅ˜ */ + + // ๋ณด๋ฅ˜ ํ‘œ์‹œ๋ฅผ ์ผœ๋‘๊ณ  ๋‚˜๊ฐ€๋ฉด, ๋ฐ€๋‹น์ด ๋๋‚  ๋•Œ EndPhaseLayer๊ฐ€ ์ด ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ๋ถ€๋ฆ„ + mActiveSkillContext.mIsDeactivationPending = false; + if (IsWaitingForcedMove() == true) + { + mActiveSkillContext.mIsDeactivationPending = true; + return; + } + /* ๋ฏธํ˜ธ์ถœํ•œ Phase ๋‹จ๊ณ„๋“ค ์ฒ˜๋ฆฌ */ FlushRemainingPhaseLayers(); + // ํ„ธ์–ด๋‚ด๋˜ ํŽ˜์ด์ฆˆ์— ๋ฐ€๋‹น์ด ์žˆ์–ด์„œ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋์œผ๋ฉด ์—ฌ๊ธฐ์„œ๋„ ๋ณด๋ฅ˜ + if (IsWaitingForcedMove() == true) + { + mActiveSkillContext.mIsDeactivationPending = true; + return; + } + /* ์Šคํ‚ฌ ์ข…๋ฃŒ ์ฝœ๋ฐฑ */ OwnerCombatTarget->OnEndUsingSkill(mActiveSkillContext.mSkillIndex); @@ -596,6 +676,40 @@ void USkillComponentModel::DeactivateSkill() mActiveSkillContext.Clear(); } +bool USkillComponentModel::EnqueueForcedMove(FOnStartForcedMove Start) +{ + // ๊ฐ•์ œ ๋ฐ€๋‹น์ด ์•„๋‹ˆ๋ผ๋ฉด ํ์—์„œ ๊บผ๋‚ด์ฃผ๋Š” ์ฃผ์ฒด๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ์— ๋„ฃ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•จ + if (mShouldEnqueueForcedMove == false) + { + return false; + } + + mPendingForcedMoves.Add(MoveTemp(Start)); + return true; +} + +void USkillComponentModel::StartNextForcedMove() +{ + // ๋‚จ์€ ์š”์ฒญ์ด ์—†์œผ๋ฉด ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ๋†“์Œ -> EndPhaseLayer ํ˜ธ์ถœ + if (mPendingForcedMoves.IsEmpty() == true) + { + mForcedMovePhaseBarrier.Reset(); + return; + } + + FOnStartForcedMove Start = MoveTemp(mPendingForcedMoves[0]); + mPendingForcedMoves.RemoveAt(0); + + // ์ด ๋Œ€์ƒ์˜ ์ด๋™(ํ•จ์ • ์—ฐ์‡„ ํฌํ•จ)์ด ๋๋‚˜๋ฉด ํ’€๋ฆฌ๋Š” ๋ฐฐ๋ฆฌ์–ด. ํ’€๋ฆฌ๋ฉด ๋‹ค์Œ ์š”์ฒญ ์ถœ๋ฐœ + TSharedPtr MoveEndBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + StartNextForcedMove(); + })); + + // ์ถœ๋ฐœ. ์ด๋™์„ ์‹œ์ž‘ํ–ˆ์œผ๋ฉด ์ด๋™ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ๋“ค๊ณ  ์žˆ๋‹ค๊ฐ€ ์ด๋™์ด ๋๋‚  ๋•Œ ๋†“์Œ + // ์‹œ์ž‘ํ•˜์ง€ ๋ชปํ–ˆ์œผ๋ฉด(๋ฉด์—ญ, ๋ฐ€ ๊ณณ ์—†์Œ, ์ด๋ฏธ ์ด๋™ ์ค‘) ์•„๋ฌด๋„ ์•ˆ ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ด ํ•จ์ˆ˜๊ฐ€ ๋๋‚  ๋•Œ ๋ฐ”๋กœ ํ’€๋ ค์„œ ๋‹ค์Œ ์š”์ฒญ์œผ๋กœ ๋„˜์–ด๊ฐ + Start.ExecuteIfBound(MoveEndBarrier); +} + bool USkillComponentModel::CanPreview(int32 SkillIndex) const { return true; @@ -624,7 +738,7 @@ const FActiveSkillContext& USkillComponentModel::GetActiveSkillContext() const return mActiveSkillContext; } -TArray USkillComponentModel::GetAimableTiles(UTileMapModel* MapModel, int32 SkillIndex) const +TArray USkillComponentModel::GetAimableTiles(const UTileMapModel* MapModel, int32 SkillIndex) const { checkf(mSkillEntries.IsValidIndex(SkillIndex) == true, TEXT("์ž˜๋ชป๋œ ์Šคํ‚ฌ ์ธ๋ฑ์Šค ๋ฒ”์œ„")); @@ -639,7 +753,7 @@ TArray USkillComponentModel::GetAimableTiles(UTileMapModel* MapModel return MapModel->GetAimableTiles(GetOwnerModel()->GetTileTransform().mIndex, AimRange, Pattern, CanAimObstacle, BlockerLayers); } -TArray USkillComponentModel::GetTargetTiles(UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const +TArray USkillComponentModel::GetTargetTiles(const UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const { checkf(mSkillEntries.IsValidIndex(SkillIndex) == true, TEXT("์ž˜๋ชป๋œ ์Šคํ‚ฌ ์ธ๋ฑ์Šค ๋ฒ”์œ„")); UStaticSkillData* StaticSkillData = mSkillEntries[SkillIndex].mData; @@ -648,7 +762,7 @@ TArray USkillComponentModel::GetTargetTiles(UTileMapModel* MapModel, return MapModel->GetTargetTiles(GetOwnerModel()->GetTileTransform().mIndex, AimedTileIndex, StaticSkillData->mTargetPattern); } -TArray USkillComponentModel::GetEffectTiles(UTileMapModel* MapModel, int32 SkillIndex, const TArray& TargetTileIndexes) const +TArray USkillComponentModel::GetEffectTiles(const UTileMapModel* MapModel, int32 SkillIndex, const TArray& TargetTileIndexes) const { checkf(mSkillEntries.IsValidIndex(SkillIndex) == true, TEXT("์ž˜๋ชป๋œ ์Šคํ‚ฌ ์ธ๋ฑ์Šค ๋ฒ”์œ„")); UStaticSkillData* StaticSkillData = mSkillEntries[SkillIndex].mData; @@ -671,7 +785,7 @@ TArray USkillComponentModel::GetEffectTiles(UTileMapModel* MapModel, return AllEffectTiles; } -TArray USkillComponentModel::GetEffectTiles(UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const +TArray USkillComponentModel::GetEffectTiles(const UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const { // ํƒ€๊ฒŸ ํŒจํ„ด์œผ๋กœ ์˜ํ–ฅ ๋ฒ”์œ„์˜ ์ค‘์‹ฌ์ด ๋  ํƒ€์ผ๋“ค์„ ์ˆ˜์ง‘ const TArray TargetTileIndexes = GetTargetTiles(MapModel, SkillIndex, AimedTileIndex); diff --git a/Source/P_RD/Component/SkillComponent/SkillComponentModel.h b/Source/P_RD/Component/SkillComponent/SkillComponentModel.h index af4156844..d3b0fe6af 100644 --- a/Source/P_RD/Component/SkillComponent/SkillComponentModel.h +++ b/Source/P_RD/Component/SkillComponent/SkillComponentModel.h @@ -30,6 +30,9 @@ DECLARE_MULTICAST_DELEGATE_TwoParams(FOnPlayPhaseLayerUI, const FActiveSkillCont DECLARE_MULTICAST_DELEGATE_OneParam(FOnEndPhaseLayerUI, int32 /*PhaseIndex*/); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnEndSkillUI, const FActiveSkillContext& /*Context*/, const UStaticSkillData* /*SkillData*/); +// @brief ๊ฐ•์ œ์ด๋™ ์ถœ๋ฐœ ๋Œ€๋ฆฌ์ž. ์ถœ๋ฐœ ์‹œ์ ์— ๊ฒฝ๋กœ๋ฅผ ์ •ํ•ด ์ด๋™์„ ์‹œ์ž‘. ์ด๋™์„ ์‹œ์ž‘ํ–ˆ์œผ๋ฉด MoveEndBarrier๋ฅผ ์ด๋™ ์ข…๋ฃŒ๊นŒ์ง€ ๋ณด์œ  +DECLARE_DELEGATE_OneParam(FOnStartForcedMove, TSharedPtr /*MoveEndBarrier*/); + /** * @brief ํ•œ ์Šฌ๋กฏ์— ์žฅ์ฐฉ๋œ ์Šคํ‚ฌ๊ณผ ๊ทธ๋กœ ์ธํ•ด ์„ค์น˜๋œ ๋Ÿฐํƒ€์ž„ ๊ฐ์ฒด ์ถ”์  */ @@ -85,6 +88,10 @@ struct FActiveSkillContext int32 mAnimationIndex = INDEX_NONE; int32 mPhaseIndex = INDEX_NONE; +public: + // @brief ์Šคํ‚ฌ ์ข…๋ฃŒ ๋ณด๋ฅ˜ ์—ฌ๋ถ€. ์‹œ์ „์ž ์—ฐ์ถœ์€ ๋๋‚ฌ์ง€๋งŒ ํ”ผ๊ฒฉ์ž ๋ฐ€๋‹น์ด ๋‚จ์•„์„œ DeactivateSkill์ด ์ค‘๋‹จ๋์œผ๋ฉด true (๋ฐ€๋‹น์ด ๋๋‚˜๋ฉด ๋‹ค์‹œ ํ˜ธ์ถœ๋จ) + bool mIsDeactivationPending = false; + public: FOnEndSkillUI mEndCallback; @@ -96,6 +103,8 @@ struct FActiveSkillContext /** * @brief ์•กํ‹ฐ๋ธŒ ์Šคํ‚ฌ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋ธ + * @details ํŽ˜์ด์ฆˆ์— ๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ๊ฐ€ ์žˆ์œผ๋ฉด ํ”ผ๊ฒฉ์ž ์ด๋™์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ๋ฅผ ๋ฏธ๋ฃธ. + * ์‹œ์ „์ž ์—ฐ์ถœ๊ณผ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ ์ค‘ ๋Šฆ๊ฒŒ ๋๋‚˜๋Š” ์ชฝ์—์„œ ์Šคํ‚ฌ ์ข…๋ฃŒ */ UCLASS() class P_RD_API USkillComponentModel : public UComponentModel @@ -162,6 +171,8 @@ class P_RD_API USkillComponentModel : public UComponentModel void PreparePhaseLayer(); void TriggerPhaseLayer(const FEventTriggerPayloadBase* Payload); + // @brief ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ ์ฒ˜๋ฆฌ. ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด ์†Œ๋ฉธ ์‹œ ํ˜ธ์ถœ + void EndPhaseLayer(); void FlushRemainingPhaseLayers(); void DeactivateSkill(); @@ -183,16 +194,41 @@ class P_RD_API USkillComponentModel : public UComponentModel */ virtual bool IsCritical(int32 Threshold) const; + /* ๊ฐ•์ œ์ด๋™ ๋Œ€๊ธฐ์—ด */ +public: + /** + * @brief ๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ ์š”์ฒญ์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์Œ + * @details ์ดํŽ™ํŠธ ์ ์šฉ ์ค‘์— ๋“ค์–ด์˜จ ์š”์ฒญ์€ ๋ฐ”๋กœ ๋ฐ€๋‹นํ•˜์ง€ ์•Š๊ณ  ๋ชจ์•„ ๋‘ . + * ์ดํŽ™ํŠธ ์ ์šฉ์ด ๋๋‚˜๋ฉด ๋ชจ์•„๋†จ๋˜ ์š”์ฒญ์„ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์„œ ์ฐจ๋ก€๋กœ ๋ฐ€๋‹นํ•˜๊ณ , ๋ชจ๋‘ ๋๋‚˜๋ฉด ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ + * @param Start ์ฐจ๋ก€๊ฐ€ ์˜ค๋ฉด ์‹คํ–‰ํ•  ์ถœ๋ฐœ ๋Œ€๋ฆฌ์ž (๊ทธ๋•Œ์˜ ๋ฐฐ์น˜๋กœ ๊ฒฝ๋กœ๋ฅผ ์ •ํ•ด ์ด๋™ ์‹œ์ž‘) + * @return ๋Œ€๊ธฐ์—ด์— ๋„ฃ์—ˆ์œผ๋ฉด true. ์ดํŽ™ํŠธ ์ ์šฉ ์ค‘์ด ์•„๋‹ˆ๋ฉด false (ํ˜ธ์ถœ์ž๊ฐ€ ๋ฐ”๋กœ ๋ฐ€๋ฉด ๋จ) + */ + bool EnqueueForcedMove(FOnStartForcedMove Start); + +private: + // @brief ๋Œ€๊ธฐ์—ด์—์„œ ๋‹ค์Œ ์ด๋™ ์š”์ฒญ์„ ๊บผ๋‚ด์„œ ์ถœ๋ฐœ. ๋ชจ๋“  ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฐฐ๋ฆฌ์–ด๋ฅผ ํ’€์–ด์„œ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ + void StartNextForcedMove(); + // @brief ๋ฐ€๋‹น์ด ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘์ธ์ง€ ์—ฌ๋ถ€ (๋Œ€๊ธฐ์—ด์ด ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์ฅ๊ณ  ์žˆ์œผ๋ฉด ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘) + bool IsWaitingForcedMove() const { return mForcedMovePhaseBarrier.IsValid(); } + +private: + // @brief ์ถœ๋ฐœ ๋Œ€๊ธฐ ์ค‘์ธ ์ด๋™ ์š”์ฒญ (๋“ฑ๋ก ์ˆœ์„œ = ์ถœ๋ฐœ ์ˆœ์„œ) + TArray mPendingForcedMoves; + // @brief ๋Œ€๊ธฐ์—ด์ด ์žก๊ณ  ์žˆ๋Š” ํŽ˜์ด์ฆˆ ๋ฐฐ๋ฆฌ์–ด. ๋งˆ์ง€๋ง‰ ์š”์ฒญ๊นŒ์ง€ ๋๋‚˜๋ฉด ๋†“์Œ + TSharedPtr mForcedMovePhaseBarrier; + // @brief ๋ฐ€๋‹น ์š”์ฒญ์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์–ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€. ํŽ˜์ด์ฆˆ ์ดํŽ™ํŠธ ์ ์šฉ ๋ฃจํ”„ ๋™์•ˆ๋งŒ ์ผœ์ง (๊บผ์ ธ ์žˆ์œผ๋ฉด Push/Pull์ด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐ”๋กœ ๋ฐˆ) + bool mShouldEnqueueForcedMove = false; + /* ์ถ”๊ฐ€ API */ public: bool IsAnySkillActivated() const; const FActiveSkillContext& GetActiveSkillContext() const; public: - TArray GetAimableTiles(UTileMapModel* MapModel, int32 SkillIndex) const; - TArray GetTargetTiles(UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const; - TArray GetEffectTiles(UTileMapModel* MapModel, int32 SkillIndex, const TArray& TargetTileIndexes) const; - TArray GetEffectTiles(UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const; + TArray GetAimableTiles(const UTileMapModel* MapModel, int32 SkillIndex) const; + TArray GetTargetTiles(const UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const; + TArray GetEffectTiles(const UTileMapModel* MapModel, int32 SkillIndex, const TArray& TargetTileIndexes) const; + TArray GetEffectTiles(const UTileMapModel* MapModel, int32 SkillIndex, const FTileIndex& AimedTileIndex) const; public: bool IsCooldown(int32 SkillIndex) const; diff --git a/Source/P_RD/DataAsset/ObstacleSpawnData/StaticPuddleGimmickSpawnData.h b/Source/P_RD/DataAsset/ObstacleSpawnData/StaticPuddleGimmickSpawnData.h index 7b598176c..dd93b2bca 100644 --- a/Source/P_RD/DataAsset/ObstacleSpawnData/StaticPuddleGimmickSpawnData.h +++ b/Source/P_RD/DataAsset/ObstacleSpawnData/StaticPuddleGimmickSpawnData.h @@ -29,5 +29,5 @@ class P_RD_API UStaticPuddleGimmickSpawnData : public UStaticGimmickSpawnData public: // @brief ์œ ์ง€๋˜๋Š” ๋ผ์šด๋“œ ์ˆ˜ (์Œ์ˆ˜ = ๋ฌด์ œํ•œ, 0 ์ž…๋ ฅ ๊ธˆ์ง€) UPROPERTY(Category = "Gimmick", EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "RoundLifetime")) - int32 mRoundLifetime = 3; + int32 mRoundLifetime = -1; }; diff --git a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer.h b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer.h index ae2014c6b..1535eaf14 100644 --- a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer.h +++ b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer.h @@ -59,6 +59,10 @@ struct P_RD_API FSkillEffectLayer public: virtual FText MakeDescription() const PURE_VIRTUAL(FSkillEffectLayer::MakeDescription, return FText::GetEmpty(); ); + +public: + // @brief ๋Œ€์ƒ์„ ๊ฐ•์ œ ์ด๋™์‹œํ‚ค๋Š” ์ดํŽ™ํŠธ(๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ) ๋ณด์œ  ์—ฌ๋ถ€ + virtual bool HasForcedMovement() const { return false; } }; USTRUCT(BlueprintType) diff --git a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Pull.h b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Pull.h index 1710ea16a..5cce135f7 100644 --- a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Pull.h +++ b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Pull.h @@ -25,4 +25,7 @@ struct P_RD_API FSkillEffectLayer_Pull : public FSkillEffectLayer_TagBase public: FText MakeDescription() const override; + +public: + bool HasForcedMovement() const override { return true; } }; diff --git a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Push.h b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Push.h index de575cc93..4dc840d7d 100644 --- a/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Push.h +++ b/Source/P_RD/DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Push.h @@ -26,4 +26,7 @@ struct P_RD_API FSkillEffectLayer_Push : public FSkillEffectLayer_TagBase public: FText MakeDescription() const override; + +public: + bool HasForcedMovement() const override { return true; } }; diff --git a/Source/P_RD/DataAsset/SkillData/StaticSkillData.cpp b/Source/P_RD/DataAsset/SkillData/StaticSkillData.cpp index 2be44f9d1..6c6e3f59f 100644 --- a/Source/P_RD/DataAsset/SkillData/StaticSkillData.cpp +++ b/Source/P_RD/DataAsset/SkillData/StaticSkillData.cpp @@ -162,6 +162,39 @@ EDataValidationResult UStaticSkillData::IsDataValid(FDataValidationContext& Cont ThisResult = EDataValidationResult::Invalid; } + // ๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ ๋ฐฐ์น˜ ์ˆœ์„œ ๊ฒ€์ฆ + // ๋ฐ€๋‹น์ด ์ค‘๊ฐ„์— ๋ผ๋ฉด ์‹œ์ „์ž์™€ ํ”ผ๊ฒฉ์ž์˜ ๋ชจ์…˜์ด ์–ด๊ธ‹๋‚˜์„œ ์–ด์ƒ‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์˜๋„๊ฐ€ ๋งž๋Š” ์ง€ ํ•œ ๋ฒˆ ๋” ํ™•์ธํ•ด๋ณด๋ผ๋Š” ์˜๋ฏธ์—์„œ ๊ฒฝ๊ณ  + const int32 LastPhaseIndex = mSkillPhaseLayers.Num() - 1; + for (int32 PhaseIndex = 0; PhaseIndex <= LastPhaseIndex; ++PhaseIndex) + { + const TArray>& Layers = mSkillPhaseLayers[PhaseIndex].mSkillEffectLayers; + bool HasPassedForcedMovement = false; + for (int32 LayerIndex = 0; LayerIndex < Layers.Num(); ++LayerIndex) + { + if (Layers[LayerIndex].IsValid() == false) + { + continue; + } + + // ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ๊ฐ€ ์•„๋‹Œ ๊ณณ์˜ ๋ฐ€๋‹น + const bool HasForced = Layers[LayerIndex].Get().HasForcedMovement(); + if (HasForced == true && PhaseIndex != LastPhaseIndex) + { + Context.AddWarning(FText::FromString(FString::Printf(TEXT("๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ๋ฅผ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ ์•„๋‹Œ ๊ณณ์— ๋ฐฐ์น˜ (%dํƒ€)"), PhaseIndex + 1))); + } + + // ๊ฐ™์€ ํŽ˜์ด์ฆˆ์—์„œ ๋ฐ€๋‹น ๋’ค์— ์˜ค๋Š” ๋‹ค๋ฅธ ์ดํŽ™ํŠธ + if (HasForced == true) + { + HasPassedForcedMovement = true; + } + else if (HasPassedForcedMovement == true) + { + Context.AddWarning(FText::FromString(FString::Printf(TEXT("๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ ๋’ค์— ๋‹ค๋ฅธ ์ดํŽ™ํŠธ ๋ฐฐ์น˜ (%dํƒ€ %d๋ฒˆ์งธ)"), PhaseIndex + 1, LayerIndex + 1))); + } + } + } + return CombineDataValidationResults(SuperResult, ThisResult); } #endif diff --git a/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.cpp b/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.cpp index e65b6ebc8..82fe7bc4b 100644 --- a/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.cpp +++ b/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.cpp @@ -37,8 +37,8 @@ EDataValidationResult UStaticUnitSkillData::IsDataValid(FDataValidationContext& } if ( - mSkillType == ESkillType::Attack && - mTargetPolicy.IsStatusPolicy() == true && + (mSkillType == ESkillType::Attack || mSkillType == ESkillType::Move) && + mTargetPolicy.IsStatusPolicy() == true && mTargetPolicy.mStatusTag.IsValid() == false ) { diff --git a/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.h b/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.h index 7b0615926..079b2084c 100644 --- a/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.h +++ b/Source/P_RD/DataAsset/SkillData/StaticUnitSkillData.h @@ -64,8 +64,8 @@ class P_RD_API UStaticUnitSkillData : public UStaticSkillData bool mIgnoreCondition = false; public: - // @brief ํƒ€๊ฒŸ ์„ ์ • ๊ธฐ์ค€ - UPROPERTY(Category = "AILogic", EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "TargetPolicy", EditCondition = "mSkillType == ESkillType::Attack", EditConditionHides)) + // @brief ํƒ€๊ฒŸ ์„ ์ • ๊ธฐ์ค€ (Move๋Š” ์ฐฉ์ง€ ํƒ€์ผ์„ ๊ณ ๋ฅผ ๋•Œ์˜ ๊ธฐ์ค€ ํƒ€๊ฒŸ ์„ ์ •์— ์‚ฌ์šฉ) + UPROPERTY(Category = "AILogic", EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "TargetPolicy", EditCondition = "mSkillType == ESkillType::Attack || mSkillType == ESkillType::Move", EditConditionHides)) FEnemyTargetPolicy mTargetPolicy; }; diff --git a/Source/P_RD/GameMode/CombatGameMode.cpp b/Source/P_RD/GameMode/CombatGameMode.cpp index 9d7dfaafd..a673f86b1 100644 --- a/Source/P_RD/GameMode/CombatGameMode.cpp +++ b/Source/P_RD/GameMode/CombatGameMode.cpp @@ -319,6 +319,9 @@ void ACombatGameMode::InitializeCombat() const FRoomTransactionState& Transactions = GetRunPersistData()->GetRoomTransactions(); mGoldRewardClaimed = Transactions.GoldClaimed; mExpRewardClaimed = Transactions.ExpClaimed; + mResumePendingLevelUpAfterExp = Transactions.ExpClaimed + && Transactions.LevelUpSkills.ContainsByPredicate( + [](const FLevelUpSkillReward& Reward) { return !Reward.Completed; }); mClaimedRewardChoiceIndices = Transactions.ClaimedChoices; mRewardSelectionClaimed = Transactions.SelectedArtifact.IsValid(); mSelectedRewardArtifactId = Transactions.SelectedArtifact; @@ -495,6 +498,8 @@ void ACombatGameMode::InitializeCombat() // HUD๊ฐ€ ๋จผ์ € ๋งŒ๋“ค์–ด์ ธ ์•ต์ปค๋ฅผ ๋“ฑ๋กํ•œ ๊ฒฝ์šฐ์—๋„ ๊ตฌ๋… ์งํ›„ ๊ฐ™์€ ๊ฐ’์„ ์นด๋ฉ”๋ผ์— ์ ์šฉํ•œ๋‹ค. HandleChangeFocusScreenAnchor(mCombatUIModel->GetFocusScreenAnchor()); mRewardUIModel->OnRewardClaimRequested.AddUniqueDynamic(this, &ACombatGameMode::HandleRewardClaimed); + mRewardUIModel->OnExperiencePresentationCompleted.AddUniqueDynamic( + this, &ACombatGameMode::HandleExperiencePresentationCompleted); mRewardUIModel->OnRewardSelectionRequested.AddUniqueDynamic( this, &ACombatGameMode::HandleRewardSelectionRequested); @@ -594,8 +599,7 @@ void ACombatGameMode::BeginCombatAfterEntrance() } UE_LOG(LogCombatGameMode, Display, TEXT("RD_BOSS_ENTRANCE combat begins after entrance=%d"), bHadEntrance); if (auto* Combat = GetWorldSubsystemModel(this)) Combat->BeginCombat(); - // Pending reward choices belong to the completed-room checkpoint, not a new EXP grant. - mLevelUpSkillRewardFlow->Open(GetRunPersistData(), GetPartyModel(), GetWorld()->GetFirstPlayerController()); + // A restored skill choice resumes only after the experience page is advanced. } UCombatUIModel* ACombatGameMode::GetCombatUIModel() const @@ -864,6 +868,14 @@ void ACombatGameMode::HandleRewardClaimed(ERewardClaimKind ClaimKind, int32 Choi } } +void ACombatGameMode::HandleExperiencePresentationCompleted() +{ + if (!mResumePendingLevelUpAfterExp || !mLevelUpSkillRewardFlow) return; + mResumePendingLevelUpAfterExp = false; + mLevelUpSkillRewardFlow->Open(GetRunPersistData(), GetPartyModel(), + GetWorld()->GetFirstPlayerController()); +} + void ACombatGameMode::HandleRewardSelectionRequested( const FPrimaryAssetId RewardId) { diff --git a/Source/P_RD/GameMode/CombatGameMode.h b/Source/P_RD/GameMode/CombatGameMode.h index d2cdbb6c2..089d6da9f 100644 --- a/Source/P_RD/GameMode/CombatGameMode.h +++ b/Source/P_RD/GameMode/CombatGameMode.h @@ -94,6 +94,8 @@ class P_RD_API ACombatGameMode : public ARoomGameModeBase UFUNCTION() void HandleRewardClaimed(ERewardClaimKind ClaimKind, int32 ChoiceIndex); + UFUNCTION() + void HandleExperiencePresentationCompleted(); /** @brief ์—˜๋ฆฌํŠธยท๋ณด์Šค SelectOne ์ •์ฑ… ์š”์ฒญ์„ ์‹ค์ œ ์•„ํ‹ฐํŒฉํŠธ ์ง€๊ธ‰์œผ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค. */ UFUNCTION() @@ -325,6 +327,7 @@ class P_RD_API ACombatGameMode : public ARoomGameModeBase UPROPERTY(Category = "UI", VisibleAnywhere, DuplicateTransient, meta = (DisplayName = "RewardUIModel")) TObjectPtr mRewardUIModel; UPROPERTY() TObjectPtr mLevelUpSkillRewardFlow; + bool mResumePendingLevelUpAfterExp = false; private: /** @brief ๋‹ค์Œ ์•ก์…˜/ํ„ด์ด ์‹œ์ž‘๋ผ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š์€ ์นด๋ฉ”๋ผ ๋ณต๊ท€ ๋Œ€๊ธฐ๋ฅผ ์ทจ์†Œํ•œ๋‹ค. */ diff --git a/Source/P_RD/GameMode/RoomGameModeBase.cpp b/Source/P_RD/GameMode/RoomGameModeBase.cpp index 01bfe91d8..d9cecb5e3 100644 --- a/Source/P_RD/GameMode/RoomGameModeBase.cpp +++ b/Source/P_RD/GameMode/RoomGameModeBase.cpp @@ -11,6 +11,8 @@ #include "Singleton/WorldSubsystem/WorldWidgetSubsystem.h" #include "Blueprint/UserWidget.h" #include "UI/RDUserWidget.h" +#include "UI/SettingsPanelWidget.h" +#include "Singleton/WorldSubsystem/WorldWidgetType.h" #include "Setting/RDWorldSettings.h" @@ -355,6 +357,13 @@ void ARoomGameModeBase::InitializeCommonRoom() void ARoomGameModeBase::BeginRoom() { Super::BeginRoom(); + if (USettingsPanelWidget* Settings = GetRunSettingsPanel()) + { + Settings->OnSaveAndExitRequested.AddUniqueDynamic( + this, &ARoomGameModeBase::HandleSettingsSaveAndExitRequested); + Settings->OnAbandonRunConfirmed.AddUniqueDynamic( + this, &ARoomGameModeBase::HandleSettingsAbandonConfirmed); + } /* ํ„ฐ์น˜ ์„ธํŒ… */ @@ -372,6 +381,69 @@ void ARoomGameModeBase::BeginRoom() PlayerController->SetInputMode(InputMode); } +USettingsPanelWidget* ARoomGameModeBase::GetRunSettingsPanel() const +{ + UWorld* World = GetWorld(); + UWorldWidgetSubsystem* Widgets = World ? World->GetSubsystem() : nullptr; + return Widgets ? Widgets->GetWorldWidget(EWorldWidgetType::InGameSettings) : nullptr; +} + +void ARoomGameModeBase::CompleteSettingsRunAction(bool bSuccess, bool bSaveAndExit) +{ + if (bSuccess) return; // The room transition owns the successful path. + mCommonSettingsRunActionPending = false; + if (USettingsPanelWidget* Settings = GetRunSettingsPanel()) + { + Settings->SetRunActionsEnabled(true); + Settings->SetStatusText(bSaveAndExit + ? NSLOCTEXT("RoomGameModeBase", "SaveAndExitFailed", "์ €์žฅ ํ›„ ์ข…๋ฃŒ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") + : NSLOCTEXT("RoomGameModeBase", "AbandonRunFailed", "๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.")); + } +} + +void ARoomGameModeBase::HandleSettingsSaveAndExitRequested() +{ + if (mCommonSettingsRunActionPending || IsSaveAndExitPending()) return; + USettingsPanelWidget* Settings = GetRunSettingsPanel(); + if (Settings) + { + Settings->SetRunActionsEnabled(false); + Settings->SetStatusText(NSLOCTEXT("RoomGameModeBase", "SavingRun", "์ €์žฅ ์ค‘...")); + } + USaveGameSubsystem* Saves = GetGameInstance() + ? GetGameInstance()->GetSubsystem() : nullptr; + if (!Saves) { CompleteSettingsRunAction(false, true); return; } + mCommonSettingsRunActionPending = true; + Saves->SaveOptionAsync(FAsyncSaveGameToSlotDelegate::CreateWeakLambda(this, + [this](const FString&, int32, bool bSaved) + { + if (!bSaved) { CompleteSettingsRunAction(false, true); return; } + SaveAndExitRunFromRoomAsync(FOnRoomSaveAndExitComplete::CreateWeakLambda(this, + [this](bool bSuccess) { CompleteSettingsRunAction(bSuccess, true); })); + })); +} + +void ARoomGameModeBase::HandleSettingsAbandonConfirmed() +{ + if (mCommonSettingsRunActionPending || IsSaveAndExitPending()) return; + USettingsPanelWidget* Settings = GetRunSettingsPanel(); + if (Settings) + { + Settings->HideAbandonConfirm(); + Settings->SetRunActionsEnabled(false); + Settings->SetStatusText(FText::GetEmpty()); + } + USaveGameSubsystem* Saves = GetGameInstance() + ? GetGameInstance()->GetSubsystem() : nullptr; + if (!Saves) { CompleteSettingsRunAction(false, false); return; } + mCommonSettingsRunActionPending = true; + Saves->SaveOptionAsync(FAsyncSaveGameToSlotDelegate::CreateWeakLambda(this, + [this](const FString&, int32, bool bSaved) + { + CompleteSettingsRunAction(bSaved && AbandonRunFromRoom(), false); + })); +} + bool ARoomGameModeBase::SelectNextRoom(int32 RoomRow, int32 RoomColumn) { if (mWasNextRoomPreloadRequested == true) diff --git a/Source/P_RD/GameMode/RoomGameModeBase.h b/Source/P_RD/GameMode/RoomGameModeBase.h index 6f334baf3..2239dc152 100644 --- a/Source/P_RD/GameMode/RoomGameModeBase.h +++ b/Source/P_RD/GameMode/RoomGameModeBase.h @@ -17,6 +17,7 @@ DECLARE_LOG_CATEGORY_EXTERN(LogRoomGameMode, Log, All) class UPartyModel; class UPlayerUnitModel; +class USettingsPanelWidget; struct FCombatArtifactUI; struct FSkillDetailUI; @@ -193,6 +194,12 @@ class P_RD_API ARoomGameModeBase : public ARDGameModeBase int32 mSelectedRoomColumn = INDEX_NONE; private: + USettingsPanelWidget* GetRunSettingsPanel() const; + UFUNCTION() void HandleSettingsSaveAndExitRequested(); + UFUNCTION() void HandleSettingsAbandonConfirmed(); + void CompleteSettingsRunAction(bool bSuccess, bool bSaveAndExit); + + bool mCommonSettingsRunActionPending = false; FName mSelectedRoomSpawnSettingName = NAME_None; bool mSaveAndExitPending = false; bool mFinalRunClosed = false; diff --git a/Source/P_RD/GameplayTagType.cpp b/Source/P_RD/GameplayTagType.cpp index bb91e2d1b..aee9f3053 100644 --- a/Source/P_RD/GameplayTagType.cpp +++ b/Source/P_RD/GameplayTagType.cpp @@ -34,6 +34,8 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Common_SupportBlast, "Animation.Montage.Skill.Mercenary.Common.SupportBlast"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Common_PyrrhicStrike, "Animation.Montage.Skill.Mercenary.Common.PyrrhicStrike"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Common_Passion, "Animation.Montage.Skill.Mercenary.Common.Passion"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Common_Leap, "Animation.Montage.Skill.Mercenary.Common.Leap"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Common_HourglassTurn, "Animation.Montage.Skill.Mercenary.Common.HourglassTurn"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_NormalSlash, "Animation.Montage.Skill.Mercenary.Knight.NormalSlash") UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_HeavyStrike, "Animation.Montage.Skill.Mercenary.Knight.HeavyStrike") @@ -57,6 +59,7 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_HolyShield, "Animation.Montage.Skill.Mercenary.Knight.HolyShield"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_Baptism, "Animation.Montage.Skill.Mercenary.Knight.Baptism"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_Sanctuary, "Animation.Montage.Skill.Mercenary.Knight.Sanctuary"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Knight_GuardianCharge, "Animation.Montage.Skill.Mercenary.Knight.GuardianCharge"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Ranger_NormalShot, "Animation.Montage.Skill.Mercenary.Ranger.NormalShot"); @@ -82,6 +85,7 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Ranger_BarrageKick, "Animation.Montage.Skill.Mercenary.Ranger.BarrageKick"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Ranger_AgileMovement, "Animation.Montage.Skill.Mercenary.Ranger.AgileMovement"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Ranger_Shockwave, "Animation.Montage.Skill.Mercenary.Ranger.Shockwave"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Ranger_Smoke, "Animation.Montage.Skill.Mercenary.Ranger.Smoke"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_NormalEnergyBall, "Animation.Montage.Skill.Mercenary.Mage.NormalEnergyBall"); @@ -105,6 +109,9 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_Annihilation, "Animation.Montage.Skill.Mercenary.Mage.Annihilation"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_GodOfDice, "Animation.Montage.Skill.Mercenary.Mage.GodOfDice"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_ThunderStorm, "Animation.Montage.Skill.Mercenary.Mage.ThunderStorm"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_Teleport, "Animation.Montage.Skill.Mercenary.Mage.Teleport"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_TimeAcceleration, "Animation.Montage.Skill.Mercenary.Mage.TimeAcceleration"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Mage_TickTock, "Animation.Montage.Skill.Mercenary.Mage.TickTock"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Barbarian_NormalSlash, "Animation.Montage.Skill.Mercenary.Barbarian.NormalSlash"); @@ -129,6 +136,7 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Barbarian_Cleave, "Animation.Montage.Skill.Mercenary.Barbarian.Cleave"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Barbarian_BloodRush, "Animation.Montage.Skill.Mercenary.Barbarian.BloodRush"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Barbarian_Unstoppable, "Animation.Montage.Skill.Mercenary.Barbarian.Unstoppable"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Barbarian_ImpactLeap, "Animation.Montage.Skill.Mercenary.Barbarian.ImpactLeap"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_NormalDoubleSlash, "Animation.Montage.Skill.Mercenary.Rogue.NormalDoubleSlash"); @@ -152,6 +160,9 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_Doping, "Animation.Montage.Skill.Mercenary.Rogue.Doping"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_PoisonBomb, "Animation.Montage.Skill.Mercenary.Rogue.PoisonBomb"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_Evasion, "Animation.Montage.Skill.Mercenary.Rogue.Evasion"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_FlashStep, "Animation.Montage.Skill.Mercenary.Rogue.FlashStep"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Rogue_Cheat, "Animation.Montage.Skill.Mercenary.Rogue.Cheat"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_NormalAttack, "Animation.Montage.Skill.Mercenary.Druid.NormalAttack"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_Longstrider, "Animation.Montage.Skill.Mercenary.Druid.Longstrider"); @@ -175,6 +186,7 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_AcidRain, "Animation.Montage.Skill.Mercenary.Druid.AcidRain"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_Invincibility, "Animation.Montage.Skill.Mercenary.Druid.Invincibility"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_ImmunityBoost, "Animation.Montage.Skill.Mercenary.Druid.ImmunityBoost"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Mercenary_Druid_BlessingOfTime, "Animation.Montage.Skill.Mercenary.Druid.BlessingOfTime"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Mushroom_Bodyslam, "Animation.Montage.Skill.Enemy.Mushroom.Bodyslam"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Mushroom_Spore_Exhaustion, "Animation.Montage.Skill.Enemy.Mushroom.Spore.Exhaustion"); @@ -246,11 +258,13 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Golem_Kick, "Animation.Montage.Skill.Enemy.Skeleton.Golem.Kick"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Golem_SeismicToss, "Animation.Montage.Skill.Enemy.Skeleton.Golem.SeismicToss"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Golem_Howl, "Animation.Montage.Skill.Enemy.Skeleton.Golem.Howl"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Golem_ImpactLeap, "Animation.Montage.Skill.Enemy.Skeleton.Golem.ImpactLeap"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Warrior_Whirlwind, "Animation.Montage.Skill.Enemy.Skeleton.Warrior.Whirlwind"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Warrior_PushAttack, "Animation.Montage.Skill.Enemy.Skeleton.Warrior.PushAttack"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Warrior_Rage, "Animation.Montage.Skill.Enemy.Skeleton.Warrior.Rage"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Warrior_HeavyStrike, "Animation.Montage.Skill.Enemy.Skeleton.Warrior.HeavyStrike"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Warrior_ImpactLeap, "Animation.Montage.Skill.Enemy.Skeleton.Warrior.ImpactLeap"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Mage_FireBall, "Animation.Montage.Skill.Enemy.Skeleton.Mage.FireBall"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Mage_EldritchBlast, "Animation.Montage.Skill.Enemy.Skeleton.Mage.EldritchBlast"); @@ -259,6 +273,7 @@ namespace AnimationTags UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Rogue_Assassinate, "Animation.Montage.Skill.Enemy.Skeleton.Rogue.Assassinate"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Rogue_SandToss, "Animation.Montage.Skill.Enemy.Skeleton.Rogue.SandToss"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Rogue_LegSweep, "Animation.Montage.Skill.Enemy.Skeleton.Rogue.LegSweep"); + UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Rogue_FlashStep, "Animation.Montage.Skill.Enemy.Skeleton.Rogue.FlashStep"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Ranger_RapidFire, "Animation.Montage.Skill.Enemy.Skeleton.Ranger.RapidFire"); UE_DEFINE_GAMEPLAY_TAG(Animation_Montage_Skill_Enemy_Skeleton_Ranger_SnipeShot, "Animation.Montage.Skill.Enemy.Skeleton.Ranger.SnipeShot"); diff --git a/Source/P_RD/GameplayTagType.h b/Source/P_RD/GameplayTagType.h index a265412b9..40624279a 100644 --- a/Source/P_RD/GameplayTagType.h +++ b/Source/P_RD/GameplayTagType.h @@ -55,6 +55,9 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Common_SupportBlast); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Common_PyrrhicStrike); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Common_Passion); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Common_Leap); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Common_HourglassTurn); + #pragma endregion @@ -82,6 +85,8 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Knight_HolyShield); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Knight_Baptism); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Knight_Sanctuary); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Knight_GuardianCharge); + #pragma endregion #pragma region Ranger @@ -108,6 +113,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Ranger_BarrageKick); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Ranger_AgileMovement); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Ranger_Shockwave); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Ranger_Smoke); #pragma endregion @@ -133,6 +139,10 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_Annihilation); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_GodOfDice); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_ThunderStorm); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_Teleport); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_TimeAcceleration); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Mage_TickTock); + #pragma endregion #pragma region Barbarian @@ -158,6 +168,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Barbarian_Cleave); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Barbarian_BloodRush); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Barbarian_Unstoppable); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Barbarian_ImpactLeap); #pragma endregion @@ -183,6 +194,9 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Rogue_Doping); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Rogue_PoisonBomb); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Rogue_Evasion); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Rogue_FlashStep); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Rogue_Cheat); + #pragma endregion #pragma region Druid @@ -208,6 +222,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Druid_AcidRain); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Druid_Invincibility); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Druid_ImmunityBoost); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Mercenary_Druid_BlessingOfTime); #pragma endregion @@ -317,6 +332,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Golem_Kick); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Golem_SeismicToss); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Golem_Howl); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Golem_ImpactLeap); #pragma endregion // ์Šคํ…Œ์ด์ง€ 3 @@ -325,6 +341,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Warrior_PushAttack); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Warrior_Rage); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Warrior_HeavyStrike); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Warrior_ImpactLeap); #pragma endregion #pragma region Skeleton_Mage @@ -337,6 +354,7 @@ namespace AnimationTags P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Rogue_Assassinate); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Rogue_SandToss); P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Rogue_LegSweep); + P_RD_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Animation_Montage_Skill_Enemy_Skeleton_Rogue_FlashStep); #pragma endregion #pragma region Skeleton_Ranger diff --git a/Source/P_RD/ObjectModel.cpp b/Source/P_RD/ObjectModel.cpp index 82f06c128..54abee75d 100644 --- a/Source/P_RD/ObjectModel.cpp +++ b/Source/P_RD/ObjectModel.cpp @@ -45,3 +45,13 @@ int32 UObjectModel::GetModelId() const { return mModelId; } + +bool UObjectModel::IsInitialized() const +{ + return mIsInitialized; +} + +bool UObjectModel::IsPendingDestroy() const +{ + return mIsPendingDestroy; +} diff --git a/Source/P_RD/ObjectModel.h b/Source/P_RD/ObjectModel.h index 4ed970ff2..b50d0dbc4 100644 --- a/Source/P_RD/ObjectModel.h +++ b/Source/P_RD/ObjectModel.h @@ -50,6 +50,9 @@ class P_RD_API UObjectModel : public UObject IObjectView* GetView() const; int32 GetModelId() const; + bool IsInitialized() const; + bool IsPendingDestroy() const; + protected: TWeakObjectPtr mView; diff --git a/Source/P_RD/Pawn/Enemy/EnemyUnitModel.cpp b/Source/P_RD/Pawn/Enemy/EnemyUnitModel.cpp index 5fc1fd142..d87b45be0 100644 --- a/Source/P_RD/Pawn/Enemy/EnemyUnitModel.cpp +++ b/Source/P_RD/Pawn/Enemy/EnemyUnitModel.cpp @@ -88,6 +88,8 @@ ESkillPriority UEnemyUnitModel::GetSkillPriority(int32 SkillSlot) const const FEnemyTargetPolicyOverride& UEnemyUnitModel::GetTargetPolicyOverride(int32 SkillSlot) const { - return mTargetPolicyOverrides[SkillSlot]; + // ์Šคํฐ ๋ฐ์ดํ„ฐ ์—†์ด ๋งŒ๋“  ๋ชจ๋ธ(ํ…Œ์ŠคํŠธ Mock ๋“ฑ)์€ ๋ฐฐ์—ด์ด ๋น„์–ด ์žˆ์œผ๋ฏ€๋กœ, ๋ฒ”์œ„ ๋ฐ–์ด๋ฉด ์˜ค๋ฒ„๋ผ์ด๋“œ ์—†์Œ์œผ๋กœ ์ทจ๊ธ‰ + static const FEnemyTargetPolicyOverride NoOverride; + return mTargetPolicyOverrides.IsValidIndex(SkillSlot) ? mTargetPolicyOverrides[SkillSlot] : NoOverride; } diff --git a/Source/P_RD/Pawn/Unit.cpp b/Source/P_RD/Pawn/Unit.cpp index d810c3f64..2582046e7 100644 --- a/Source/P_RD/Pawn/Unit.cpp +++ b/Source/P_RD/Pawn/Unit.cpp @@ -42,7 +42,7 @@ AUnit::AUnit() mMeshComp->AlwaysLoadOnClient = true; mMeshComp->AlwaysLoadOnServer = true; mMeshComp->bOwnerNoSee = false; - mMeshComp->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPose; + mMeshComp->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones; mMeshComp->bCastDynamicShadow = true; mMeshComp->bAffectDynamicIndirectLighting = true; mMeshComp->PrimaryComponentTick.TickGroup = TG_PrePhysics; diff --git a/Source/P_RD/SRPGFramework/SRPGAction.cpp b/Source/P_RD/SRPGFramework/SRPGAction.cpp index e79257cba..4cdf7f01e 100644 --- a/Source/P_RD/SRPGFramework/SRPGAction.cpp +++ b/Source/P_RD/SRPGFramework/SRPGAction.cpp @@ -73,31 +73,50 @@ void USRPGAction::EndAction() UE_LOG(LogSRPGCombat, Log, TEXT("์•ก์…˜ ์ข…๋ฃŒ: %s"), *GetClass()->GetName()); - // ์•ก์…˜ ์ข…๋ฃŒ ๋กœ์ง - OnEndAction(); + mEndHoldPresentationBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + // ์•ก์…˜ ์ข…๋ฃŒ ๋กœ์ง + OnEndAction(); - // ๋กœ๊ทธ ์ž‘์„ฑ - GetWorldEventLogger(this)->EndActionLog(); - - // ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก ํ•ด์ œ - USRPGCommandRouterModel* CommandRouterModel = GetWorldSubsystemModel(this); - checkf(CommandRouterModel != nullptr, TEXT("๋ช…๋ น ๋ผ์šฐํ„ฐ ๋ชจ๋ธ nullptr")); - CommandRouterModel->UnregisterCommandHandler(this); + // ๋กœ๊ทธ ์ž‘์„ฑ + GetWorldEventLogger(this)->EndActionLog(); - // ์ „ํˆฌ ์ƒํƒœ ํ‰๊ฐ€ - USRPGTurnContext* TurnContext = mParent.Get(); - checkf(TurnContext != nullptr, TEXT("ํ„ด ๊ฐ์ฒด nullptr")); - USRPGCombatModel* CombatModel = TurnContext->GetParent(); - checkf(CombatModel != nullptr, TEXT("์ „ํˆฌ ๋ชจ๋ธ nullptr")); - CombatModel->EvaluateCombatStates(); + // ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก ํ•ด์ œ + USRPGCommandRouterModel* CommandRouterModel = GetWorldSubsystemModel(this); + checkf(CommandRouterModel != nullptr, TEXT("๋ช…๋ น ๋ผ์šฐํ„ฐ ๋ชจ๋ธ nullptr")); + CommandRouterModel->UnregisterCommandHandler(this); - // ์ข…๋ฃŒ ์—ฐ์ถœ ์‹œ์ž‘ - TSharedPtr PresentationBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + // ์ „ํˆฌ ์ƒํƒœ ํ‰๊ฐ€ USRPGTurnContext* TurnContext = mParent.Get(); - checkf(TurnContext != nullptr, TEXT("์ด๋ฏธ ์ œ๊ฑฐ๋œ ํ„ด์—์„œ Action ์ข…๋ฃŒ ๋ช…๋ น ์˜ค๋ฅ˜")); - TurnContext->OnEndCurrentAction(this, mActionResult); + checkf(TurnContext != nullptr, TEXT("ํ„ด ๊ฐ์ฒด nullptr")); + USRPGCombatModel* CombatModel = TurnContext->GetParent(); + checkf(CombatModel != nullptr, TEXT("์ „ํˆฌ ๋ชจ๋ธ nullptr")); + CombatModel->EvaluateCombatStates(); + + // ์ข…๋ฃŒ ์—ฐ์ถœ ์‹œ์ž‘ + TSharedPtr PresentationBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + + USRPGTurnContext* TurnContext = mParent.Get(); + checkf(TurnContext != nullptr, TEXT("์ด๋ฏธ ์ œ๊ฑฐ๋œ ํ„ด์—์„œ Action ์ข…๋ฃŒ ๋ช…๋ น ์˜ค๋ฅ˜")); + TurnContext->OnEndCurrentAction(this, mActionResult); + })); + OnEndActionUI.Broadcast(PresentationBarrier, this, mActionResult); })); - OnEndActionUI.Broadcast(PresentationBarrier, this, mActionResult); + + DecrementEndHoldCount(); +} + +void USRPGAction::IncrementEndHoldCount() +{ + ++mEndHoldCount; +} + +void USRPGAction::DecrementEndHoldCount() +{ + --mEndHoldCount; + if (mEndHoldCount == 0) + { + mEndHoldPresentationBarrier.Reset(); + } } void USRPGAction::TryBeginAction() @@ -179,6 +198,21 @@ void USRPGAction::ReserveInitializeCommand(TInstancedStruct Comman mInitializeCommand = MoveTemp(Command); } +TSharedPtr USRPGAction::GetEndHoldBarrier() +{ + if (mEndHoldCount <= 0) + { + return nullptr; + } + + IncrementEndHoldCount(); + TSharedPtr HoldBarrier = FPresentationBarrier::Make(FOnFinishPresentation::CreateWeakLambda(this, [this]() { + DecrementEndHoldCount(); + })); + + return HoldBarrier; +} + TWeakObjectPtr USRPGAction::GetParent() const { return mParent; diff --git a/Source/P_RD/SRPGFramework/SRPGAction.h b/Source/P_RD/SRPGFramework/SRPGAction.h index 982717546..baebfd194 100644 --- a/Source/P_RD/SRPGFramework/SRPGAction.h +++ b/Source/P_RD/SRPGFramework/SRPGAction.h @@ -41,6 +41,10 @@ class USRPGAction : public UObject, public ISRPGCommandHandler void TickAction(float DeltaTime); void EndAction(); +private: + void IncrementEndHoldCount(); + void DecrementEndHoldCount(); + protected: /** * ์•ก์…˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜์—ฌ ์กฐ๊ฑด์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ํ•จ์ˆ˜ @@ -77,6 +81,9 @@ class USRPGAction : public UObject, public ISRPGCommandHandler void ReserveInitializeCommand(TInstancedStruct Command); /* ์™ธ๋ถ€ API */ +public: + TSharedPtr GetEndHoldBarrier(); + public: TWeakObjectPtr GetParent() const; UUnitModel* GetInstigator() const; @@ -87,6 +94,10 @@ class USRPGAction : public UObject, public ISRPGCommandHandler FOnBeginActionUI OnBeginActionUI; FOnEndActionUI OnEndActionUI; +protected: + int32 mEndHoldCount = 1; + TSharedPtr mEndHoldPresentationBarrier = nullptr; + protected: UPROPERTY(Category = Parent, VisibleAnywhere, BlueprintReadOnly, meta = (DisplayName = "Parent")) TWeakObjectPtr mParent; diff --git a/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.cpp b/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.cpp index 9346cb326..c34694747 100644 --- a/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.cpp +++ b/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.cpp @@ -84,6 +84,61 @@ namespace return BestCount > 0; } + /** + * @brief ์ด๋™ ์Šคํ‚ฌ์˜ ์ฐฉ์ง€ ํƒ€์ผ ์„ ํƒ ๊ฒฐ๊ณผ + */ + struct FMoveAimChoice + { + // @brief ์ฐฉ์ง€ ํƒ€์ผ (ํ›„๋ณด๊ฐ€ ์—†์œผ๋ฉด Invalid) + FTileIndex mTile = FTileIndex::Invalid; + // @brief ์ฐฉ์ง€ ํƒ€์ผ์—์„œ ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ๊นŒ์ง€ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ (๊ฒฝ๋กœ ์—†์Œ์€ MAX_int32) + int32 mPathDistance = MAX_int32; + // @brief ์ฐฉ์ง€ ํƒ€์ผ์—์„œ ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ๊นŒ์ง€ ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ + int32 mManhattanDistance = MAX_int32; + // @brief ์กฐ์ค€ ๊ฐ€๋Šฅํ•œ ๋นˆ ํƒ€์ผ ์ˆ˜ + int32 mCandidateCount = 0; + }; + + /** + * @brief ์ด๋™ ์Šคํ‚ฌ์˜ ์ฐฉ์ง€ ํƒ€์ผ ์„ ํƒ + * @details + * ํ˜„์žฌ ํƒ€์ผ์—์„œ ์กฐ์ค€ ๊ฐ€๋Šฅํ•œ ํƒ€์ผ ์ค‘ ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํƒ€์ผ ์„ ํƒ. + * 1์ˆœ์œ„ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ, 2์ˆœ์œ„ ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ, ์™„์ „ ๋™๋ฅ ์€ ๋จผ์ € ๋‚˜์˜จ ํƒ€์ผ (๋‚œ์ˆ˜ ์†Œ๋ชจ ์—†์Œ). + * ์กฐ์ค€ ์ง‘ํ•ฉ์€ ์‹คํ–‰ ์ง์ „ ๊ฒ€์ฆ(SRPGSkillAction)๊ณผ ๊ฐ™์€ ์Šคํ‚ฌ ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜๋กœ ๊ตฌํ•ด์„œ ๊ฒฐ๊ณผ ์ผ์น˜ ๋ณด์žฅ. + */ + FMoveAimChoice ChooseMoveAimTile(const UTileMapModel* Map, const UEnemyUnitModel* Enemy, + const USkillComponentModel* SkillComp, int32 SkillSlot, const FTileIndex& ReferenceTile) + { + FMoveAimChoice Choice; + + // ํ˜„์žฌ ํƒ€์ผ ๊ธฐ์ค€ ์กฐ์ค€ ๊ฐ€๋Šฅ ํƒ€์ผ (DA์˜ ์‚ฌ๊ฑฐ๋ฆฌ/ํŒจํ„ด/๋นˆ ํƒ€์ผ ์กฐ๊ฑด/์ฐจํ ์ ์šฉ) + const TArray AimTiles = SkillComp->GetAimableTiles(Map, SkillSlot); + Choice.mCandidateCount = AimTiles.Num(); + + // ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ์—์„œ ๊ฐ ํƒ€์ผ๊นŒ์ง€์˜ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ์žฅ (์ž๊ธฐ ์ž์‹ ์€ ์ž๋ฆฌ๋ฅผ ๋น„์šธ ์˜ˆ์ •์ด๋ฏ€๋กœ ์ฐจ๋‹จ์—์„œ ์ œ์™ธ) + const TArray DistanceField = Map->GetDistanceField(ReferenceTile, Enemy); + + for (const FTileIndex& Tile : AimTiles) + { + // ๊ฒฝ๋กœ ์—†์Œ(-1)์€ MAX_int32๋กœ ํ†ต์ผ (์ „์ˆ  ํƒ€์ผ ํ…Œ์ด๋ธ”๊ณผ ๊ฐ™์€ ๊ทœ์น™) + const int32 RawDistance = DistanceField[Map->TileIndexToLinearIndex(Tile)]; + const int32 PathDistance = (RawDistance >= 0) ? RawDistance : MAX_int32; + const int32 ManhattanDistance = FTileIndex::ManhattanDistance(Tile, ReferenceTile); + + // 1์ˆœ์œ„ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ, 2์ˆœ์œ„ ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ. ์™„์ „ ๋™๋ฅ ์ด๋ฉด ๋จผ์ € ๋‚˜์˜จ ํƒ€์ผ ์œ ์ง€ + const bool bBetter = (PathDistance != Choice.mPathDistance) + ? (PathDistance < Choice.mPathDistance) + : (ManhattanDistance < Choice.mManhattanDistance); + if (bBetter == true) + { + Choice.mTile = Tile; + Choice.mPathDistance = PathDistance; + Choice.mManhattanDistance = ManhattanDistance; + } + } + return Choice; + } + // @brief ์œ ๋‹› ๋กœ๊ทธ ๋ผ๋ฒจ (ํ‚ค์ด๋ฆ„#๋ชจ๋ธID) FString MakeUnitLabel(const UBoardActorModel* Model) { @@ -323,10 +378,12 @@ TArray> USRPGEnemyTurnPlanner::PlanTurn( // ์ „์ˆ  ํƒ€์ผ ํ…Œ์ด๋ธ” ๊ตฌ์„ฑ: ์ดํ›„ ํŒ๋‹จ์€ ์ „๋ถ€ ํ…Œ์ด๋ธ” ์กฐํšŒ๋กœ ์ฒ˜๋ฆฌ // ํ™•์ • ์Šคํ‚ฌ ํ•˜๋‚˜๋งŒ ์˜ฌ๋ฆฌ๋˜, ์Šฌ๋กฏ ์ธ๋ฑ์Šค๋ฅผ ๊ทธ๋Œ€๋กœ ์“ฐ๊ธฐ ์œ„ํ•ด ๋ฐฐ์—ด ํฌ๊ธฐ๋Š” ์Šฌ๋กฏ ์ˆ˜ ์œ ์ง€ // ์ž๊ธฐ ๋ฒ„ํ”„๋Š” ์กฐ์ค€ ํŒ๋‹จ์ด ์—†์œผ๋ฏ€๋กœ ๋น„์›Œ ๋‘๊ณ , ์‹œ์ „ ๋น„์šฉ์„ ๋จผ์ € ๋—€ ์˜ˆ์‚ฐ์œผ๋กœ๋งŒ ์ด๋™ + // ์ด๋™ ์Šคํ‚ฌ์€ ๋นˆ ํƒ€์ผ์„ ์กฐ์ค€ํ•˜๋ฏ€๋กœ ํƒ€๊ฒŸ ํƒ€์ผ ๊ธฐ์ค€์ธ ํ…Œ์ด๋ธ” ์กฐ์ค€ ํŒ์ •์—์„œ ์ œ์™ธ (์ œ์ž๋ฆฌ ์‹œ์ „์ด๋ผ ์ด๋™ ์˜ˆ์‚ฐ์€ ๊ทธ๋Œ€๋กœ) const bool bSpell = (ChosenSkill->mSkillType == ESkillType::Spell); + const bool bMove = (ChosenSkill->mSkillType == ESkillType::Move); TArray SkillDatas; SkillDatas.Init(nullptr, Skills.Num()); - if (bSpell == false) + if (bSpell == false && bMove == false) { SkillDatas[ChosenSkillSlot] = ChosenSkill; } @@ -373,7 +430,7 @@ TArray> USRPGEnemyTurnPlanner::PlanTurn( bSpell ? FEnemyTargetPolicy() : ChosenTargetPolicy, Table, TargetModels, AllTargets, EventStream); - // ํ™•์ • ์Šคํ‚ฌ๋กœ ์‹œ์ „ ๊ฐ€๋Šฅํ•œ ํƒ€๊ฒŸ ํ›„๋ณด ์ˆ˜์ง‘ (๋ฒ„ํ”„๋Š” ํ…Œ์ด๋ธ”์— ์Šคํ‚ฌ์ด ์—†์œผ๋ฏ€๋กœ ํ•ญ์ƒ ๋น„์–ด ์žˆ์Œ) + // ํ™•์ • ์Šคํ‚ฌ๋กœ ์‹œ์ „ ๊ฐ€๋Šฅํ•œ ํƒ€๊ฒŸ ํ›„๋ณด ์ˆ˜์ง‘ (๋ฒ„ํ”„์™€ ์ด๋™ ์Šคํ‚ฌ์€ ํ…Œ์ด๋ธ”์— ์Šคํ‚ฌ์ด ์—†์œผ๋ฏ€๋กœ ํ•ญ์ƒ ๋น„์–ด ์žˆ์Œ) TArray CastableTargets; for (int32 TargetIndex = 0; TargetIndex < TargetTiles.Num(); ++TargetIndex) { @@ -392,7 +449,31 @@ TArray> USRPGEnemyTurnPlanner::PlanTurn( CastableTargets.RemoveAll([ReferenceTarget](int32 Index) { return Index != ReferenceTarget; }); } - if (bSpell == true) + // ์ด๋™ ์Šคํ‚ฌ: ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋นˆ ํƒ€์ผ์„ ์ฐฉ์ง€ ํƒ€์ผ๋กœ ์„ ํƒ (ํ›„๋ณด๊ฐ€ ์—†์œผ๋ฉด Invalid) + const FMoveAimChoice MoveAim = bMove + ? ChooseMoveAimTile(TileMap, Enemy, SkillComp, ChosenSkillSlot, TargetTiles[ReferenceTarget]) + : FMoveAimChoice(); + + if (bMove == true && MoveAim.mTile != FTileIndex::Invalid) + { + // + // ์ด๋™ ์Šคํ‚ฌ: ๊ฑท์ง€ ์•Š๊ณ  ํ˜„์žฌ ํƒ€์ผ์—์„œ ์ฐฉ์ง€ ํƒ€์ผ์„ ์กฐ์ค€ํ•ด ์‹œ์ „ (ํ›„๋ณด๊ฐ€ ์—†์œผ๋ฉด ์•„๋ž˜ ์‹œ์ „ ๋ถˆ๊ฐ€ ๋ถ„๊ธฐ๋กœ) + // + AreaAim = MoveAim.mTile; + CanCast = true; + + // ํŒ๋‹จ๊ทผ๊ฑฐ ๋กœ๊ทธ: ๋ˆ„๊ตฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์–ด๋А ํƒ€์ผ์„ ๊ณจ๋ž๋Š”์ง€ + const FString PathDistanceText = (MoveAim.mPathDistance == MAX_int32) ? FString(TEXT("๋„๋‹ฌ๋ถˆ๊ฐ€")) : FString::FromInt(MoveAim.mPathDistance); + UE_LOG(LogSRPGEnemyPlanner, Log, TEXT("%s ์ด๋™์Šคํ‚ฌ: ๊ธฐ์ค€ํƒ€๊ฒŸ[%d]=%s@(%d,%d) ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„=%s, ์Šคํ‚ฌ[%d]=%s (%d,%d)โ†’(%d,%d) ๊ฒฝ๋กœ๊ฑฐ๋ฆฌ=%s ๋งจํ•ดํŠผ=%d ํ›„๋ณด=%d, ์‹œ์ „%d โ‰ค AP%d"), + *LogPrefix, ReferenceTarget, *MakeUnitLabel(TargetModels[ReferenceTarget]), + TargetTiles[ReferenceTarget].mX, TargetTiles[ReferenceTarget].mY, + *StaticEnum()->GetNameStringByValue(static_cast(ChosenTargetPolicy.mPriority)), + ChosenSkillSlot, *ChosenSkill->GetName(), + EnemyTile.mX, EnemyTile.mY, MoveAim.mTile.mX, MoveAim.mTile.mY, + *PathDistanceText, MoveAim.mManhattanDistance, MoveAim.mCandidateCount, + ChosenSkill->mRequiredActionPoint, ActionPoint); + } + else if (bSpell == true) { // // ์ž๊ธฐ ๋ฒ„ํ”„: ๋‚จ๋Š” ์˜ˆ์‚ฐ์œผ๋กœ ์ด๋™ ์„ฑํ–ฅ๋Œ€๋กœ ์ž๋ฆฌ๋ฅผ ์žก๊ณ  ๊ฑฐ๊ธฐ์„œ ์‹œ์ „ (๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ํƒ€์ผ์ด ํ›„๋ณด) @@ -472,7 +553,17 @@ TArray> USRPGEnemyTurnPlanner::PlanTurn( // ๊ณต๊ฒฉ ๋ถˆ๊ฐ€: ๋‹ค๋ฅธ ์Šคํ‚ฌ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์ด๋™๋งŒ (์˜ˆ์ƒ ์Šคํ‚ฌ๊ณผ ์‹ค์ œ ์Šคํ‚ฌ ์ผ์น˜ ๋ณด์žฅ) // // ํŒ๋‹จ๊ทผ๊ฑฐ ๋กœ๊ทธ: ์‹œ์ „ํ•˜์ง€ ๋ชปํ•œ ํ„ด์€ ๊ทผ๊ฑฐ๋ฅผ ์ƒ์„ธํžˆ ๋‚จ๊น€ - LogNoCastDetails(LogPrefix, EnemyTile, ActionPoint, Enemy->GetMoveTendency(), ChosenSkillSlot, ChosenSkill, TargetModels, TargetTiles, Table); + if (bMove == true) + { + // ์ด๋™ ์Šคํ‚ฌ์€ ํƒ€๊ฒŸ ํƒ€์ผ์„ ์กฐ์ค€ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํƒ€๊ฒŸ๋ณ„ ์กฐ์ค€ ์‚ฌ์œ  ๋Œ€์‹  ๋นˆ ํƒ€์ผ ํ›„๋ณด๊ฐ€ ์—†์—ˆ๋‹ค๋Š” ์‚ฌ์‹ค๋งŒ ๋‚จ๊น€ + UE_LOG(LogSRPGEnemyPlanner, Log, TEXT("%s ์ด๋™์Šคํ‚ฌ ์‹œ์ „๋ถˆ๊ฐ€: ์Šคํ‚ฌ[%d]=%s @(%d,%d) AP=%d ์‚ฌ๊ฑฐ๋ฆฌ=%d ํŒจํ„ด=%s โ†’ ์กฐ์ค€ ๋ฒ”์œ„ ์•ˆ์— ๋นˆ ํƒ€์ผ ์—†์Œ"), + *LogPrefix, ChosenSkillSlot, *ChosenSkill->GetName(), EnemyTile.mX, EnemyTile.mY, ActionPoint, ChosenSkill->mAimRange, + *StaticEnum()->GetNameStringByValue(static_cast(ChosenSkill->mAimPattern))); + } + else + { + LogNoCastDetails(LogPrefix, EnemyTile, ActionPoint, Enemy->GetMoveTendency(), ChosenSkillSlot, ChosenSkill, TargetModels, TargetTiles, Table); + } // Keep legacy Nearest/AttackAvailable movement and RNG behaviour exactly intact. const bool bLegacyMovement = ChosenTargetPolicy.mPriority == EEnemyTargetPriority::Nearest && !bChasePreferred; diff --git a/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.h b/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.h index b583e2b66..6f86254ce 100644 --- a/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.h +++ b/Source/P_RD/SRPGFramework/SRPGEnemyTurnPlanner.h @@ -36,6 +36,8 @@ struct FEnemyTargetPolicy; * -> ํ”Œ๋ ˆ์ด์–ด ํ„ด์— ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์ƒ ์Šคํ‚ฌ๊ณผ ์‹ค์ œ ์‹œ์ „ ์Šคํ‚ฌ์ด ํ•ญ์ƒ ์ผ์น˜ * - Attack: ํ™•์ • ์Šคํ‚ฌ๋กœ ์‹œ์ „ ๊ฐ€๋Šฅํ•œ ํƒ€๊ฒŸ์ด ์žˆ์œผ๋ฉด ์‹œ์ „, ์—†์œผ๋ฉด ๋‹ค๋ฅธ ์Šคํ‚ฌ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์ด๋™๋งŒ * - Spell: ์‹œ์ „ ๋น„์šฉ์„ ๋จผ์ € ๋–ผ๊ณ  ๋‚จ๋Š” ํ–‰๋™๋ ฅ์œผ๋กœ ์ด๋™ ์„ฑํ–ฅ๋Œ€๋กœ ์ž๋ฆฌ๋ฅผ ์žก์€ ๋’ค ์‹œ์ „ + * - Move: ๊ฑท์ง€ ์•Š๊ณ  ํ˜„์žฌ ํƒ€์ผ์—์„œ ์กฐ์ค€ ๊ฐ€๋Šฅํ•œ ๋นˆ ํƒ€์ผ ์ค‘ ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํƒ€์ผ์„ ์กฐ์ค€ํ•ด ์‹œ์ „, + * ๋นˆ ํƒ€์ผ์ด ์—†์œผ๋ฉด ๋‹ค๋ฅธ ์Šคํ‚ฌ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์ด๋™๋งŒ * @note * ํ„ด๋‹น ๋ณต์ˆ˜ ์‹œ์ „์ด ํ—ˆ์šฉ๋˜๋ฉด "๋ฉ€๋ฆฌ ๊ฐ€์„œ ํ•˜๋‚˜" ๋Œ€ "๊ฐ€๊นŒ์ด์„œ ๋‘˜" ๊ฐ™์€ ์กฐํ•ฉ ๋น„๊ต๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ * ํ”Œ๋ž˜๊ทธ ํ…Œ์ด๋ธ”์ด ์•„๋‹Œ ํ‰๊ฐ€ ํ•จ์ˆ˜ ๊ธฐ๋ฐ˜์œผ๋กœ ์žฌ์„ค๊ณ„ํ•ด์•ผ ํ•จ diff --git a/Source/P_RD/SRPGFramework/SRPGFrameworkType.h b/Source/P_RD/SRPGFramework/SRPGFrameworkType.h index 699b12846..4b6e15481 100644 --- a/Source/P_RD/SRPGFramework/SRPGFrameworkType.h +++ b/Source/P_RD/SRPGFramework/SRPGFrameworkType.h @@ -102,6 +102,24 @@ struct FTileIndex return HashCombine(GetTypeHash(Tile.mX), GetTypeHash(Tile.mY)); } + /** + * @brief ๋‘ ํƒ€์ผ ์‚ฌ์ด ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ (๊ฐ€๋กœ ๋ณ€์œ„ + ์„ธ๋กœ ๋ณ€์œ„) + * @details ์ง๊ต 4๋ฐฉํ–ฅ ์ด๋™ ๊ธฐ์ค€์˜ ์นธ ์ˆ˜ + */ + static int32 ManhattanDistance(const FTileIndex& A, const FTileIndex& B) + { + return FMath::Abs(A.mX - B.mX) + FMath::Abs(A.mY - B.mY); + } + + /** + * @brief ๋‘ ํƒ€์ผ ์‚ฌ์ด ์ฒด๋น„์…ฐํ”„ ๊ฑฐ๋ฆฌ (๊ฐ€๋กœ ๋ณ€์œ„์™€ ์„ธ๋กœ ๋ณ€์œ„ ์ค‘ ํฐ ๊ฐ’) + * @details ๋Œ€๊ฐ 1์นธ์„ ๊ฑฐ๋ฆฌ 1๋กœ ์ทจ๊ธ‰. Square ์กฐ์ค€ ํŒจํ„ด์˜ ์‚ฌ๊ฑฐ๋ฆฌ ๊ธฐ์ค€ + */ + static int32 ChebyshevDistance(const FTileIndex& A, const FTileIndex& B) + { + return FMath::Max(FMath::Abs(A.mX - B.mX), FMath::Abs(A.mY - B.mY)); + } + // @brief ๊ฐ€๋กœ(X) ๋ฐฉํ–ฅ ์ธ๋ฑ์Šค UPROPERTY(Category = "TileIndex", SaveGame, EditAnywhere, BlueprintReadWrite, meta = (DisplayName = "X")) int32 mX = 0; diff --git a/Source/P_RD/SRPGFramework/SRPGTurnContext.cpp b/Source/P_RD/SRPGFramework/SRPGTurnContext.cpp index c8588dc10..e918003dc 100644 --- a/Source/P_RD/SRPGFramework/SRPGTurnContext.cpp +++ b/Source/P_RD/SRPGFramework/SRPGTurnContext.cpp @@ -384,7 +384,7 @@ void USRPGTurnContext::OnHandleCommand(ESRPGCommandResult Result) { if (mTurnPhase == ESRPGTurnPhase::TurnPlay && mReservedActions.Num() > mHeadActionIndex) { - USRPGAction* const CurrentAction = mReservedActions[mHeadActionIndex]; + USRPGAction* CurrentAction = mReservedActions[mHeadActionIndex]; CurrentAction->TryBeginAction(); // TryBeginAction์˜ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๊ฐ€ ์ƒˆ ์ปค๋งจ๋“œ๋ฅผ ๋™๊ธฐ ์ œ์ถœํ•˜๋ฉด ํ˜„์žฌ ์•ก์…˜์ด ๋๋‚˜ head๊ฐ€ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค. @@ -398,6 +398,16 @@ void USRPGTurnContext::OnHandleCommand(ESRPGCommandResult Result) } } +TSharedPtr USRPGTurnContext::GetCurrentActionEndHoldBarrier() const +{ + if (mReservedActions.Num() > mHeadActionIndex) + { + USRPGAction* CurrentAction = mReservedActions[mHeadActionIndex]; + return CurrentAction->GetEndHoldBarrier(); + } + return nullptr; +} + USRPGCombatModel* USRPGTurnContext::GetParent() const { return mParent.Get(); diff --git a/Source/P_RD/SRPGFramework/SRPGTurnContext.h b/Source/P_RD/SRPGFramework/SRPGTurnContext.h index 599e28d2a..212587d3b 100644 --- a/Source/P_RD/SRPGFramework/SRPGTurnContext.h +++ b/Source/P_RD/SRPGFramework/SRPGTurnContext.h @@ -99,6 +99,9 @@ class USRPGTurnContext : public UObject void OnHandleCommand(ESRPGCommandResult Result); /* ์™ธ๋ถ€ API */ +public: + TSharedPtr GetCurrentActionEndHoldBarrier() const; + public: USRPGCombatModel* GetParent() const; UUnitModel* GetOwner() const; diff --git a/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.cpp b/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.cpp index c9cfffe5f..2464d587a 100644 --- a/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.cpp +++ b/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.cpp @@ -63,15 +63,25 @@ void USRPGCombatModel::Serialize(FArchive& Ar) void USRPGCombatModel::Tick(float DeltaTime) { USRPGTurnContext* CurTurnContext = GetCurrentTurnContext(); - if (mCombatPhase == ESRPGCombatRoomPhase::CombatPlay && CurTurnContext != nullptr) + if (mCombatPhase != ESRPGCombatRoomPhase::CombatEnd && CurTurnContext != nullptr) { CurTurnContext->TickTurn(DeltaTime); } } -bool USRPGCombatModel::IsTickable() const +ETickableTickType USRPGCombatModel::GetTickableTickType() const { - return true; + if (IsTemplate() == true || IsInitialized() == false) + { + return ETickableTickType::Never; + } + + return ETickableTickType::Conditional; +} + +bool USRPGCombatModel::IsAllowedToTick() const +{ + return IsInitialized(); } TStatId USRPGCombatModel::GetStatId() const @@ -710,6 +720,16 @@ bool USRPGCombatModel::UnregisterTurn(UUnitModel* Owner, bool IgnoreCurTurn) return true; } +int32 USRPGCombatModel::UnregisterAllTurn(UUnitModel* Owner, bool IncludeCurTurn) +{ + int32 UnregisterCount = 0; + while (UnregisterTurn(Owner, IncludeCurTurn) == true) + { + ++UnregisterCount; + } + return UnregisterCount; +} + bool USRPGCombatModel::EvaluateRound() { // A corrupted or stalled speed configuration must not block the game thread in Shipping. @@ -1038,7 +1058,7 @@ void USRPGCombatModel::UnregisterUnitModel(UUnitModel* UnitModel) /* ํ„ด ์ œ๊ฑฐ */ - UnregisterTurn(UnitModel); + UnregisterAllTurn(UnitModel); /* ์ œ๊ฑฐ */ @@ -1196,6 +1216,16 @@ void USRPGCombatModel::ForcedBeginTurn() CurTurnContext->BeginTurn(); } +TSharedPtr USRPGCombatModel::GetCurrentActionEndHoldBarrier() const +{ + if (HasAnyTurnContext() == true) + { + USRPGTurnContext* CurTurnContext = GetCurrentTurnContext(); + return CurTurnContext->GetCurrentActionEndHoldBarrier(); + } + return nullptr; +} + bool USRPGCombatModel::HasAnyTurnContext() const { return mTurnContextOrders.IsEmpty() == false; diff --git a/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.h b/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.h index fda6a8e6f..3a9bcf016 100644 --- a/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.h +++ b/Source/P_RD/Singleton/WorldSubsystem/SRPGCombatModel.h @@ -105,11 +105,12 @@ class P_RD_API USRPGCombatModel : public UObjectModel, public FTickableGameObjec /* UObjectModel ์ƒ์† */ public: void Serialize(FArchive& Ar) override; - + /* FTickableGameObject ์ƒ์† */ public: void Tick(float DeltaTime) override; - bool IsTickable() const override; + ETickableTickType GetTickableTickType() const override; + bool IsAllowedToTick() const override final; TStatId GetStatId() const override; /* ์ƒ๋ช… ์ฃผ๊ธฐ ํ•จ์ˆ˜ */ @@ -186,6 +187,7 @@ class P_RD_API USRPGCombatModel : public UObjectModel, public FTickableGameObjec */ bool UnregisterTurn(USRPGTurnContext* TurnContext, bool IgnoreCurTurn = true); bool UnregisterTurn(UUnitModel* Owner, bool IncludeCurTurn = true); + int32 UnregisterAllTurn(UUnitModel* Owner, bool IncludeCurTurn = true); protected: bool EvaluateRound(); @@ -231,6 +233,10 @@ class P_RD_API USRPGCombatModel : public UObjectModel, public FTickableGameObjec void ForcedBeginTurn(); /* ์™ธ๋ถ€ API ํ•จ์ˆ˜ */ + /* ์™ธ๋ถ€ API */ +public: + TSharedPtr GetCurrentActionEndHoldBarrier() const; + public: bool HasAnyTurnContext() const; int32 GetTurnContextCount() const; diff --git a/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Pull.cpp b/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Pull.cpp index 3cf82a109..1fe3f97a2 100644 --- a/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Pull.cpp +++ b/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Pull.cpp @@ -7,9 +7,41 @@ #include "Component/BoardMovementComponent/BoardMovementComponentModel.h" #include "Component/AttributeComponent/AttributeSetComponentModel.h" +#include "Component/SkillComponent/SkillComponentModel.h" #include "Simulation/Logger/EventLogger.h" +namespace +{ + // @brief ๋‹น๊ธฐ๊ธฐ ์ถœ๋ฐœ (๊ฒฝ๋กœ ๊ณ„์‚ฐ + ์ด๋™ ์‹œ์ž‘ + ๋กœ๊ทธ) + // ๊ด‘์—ญ ๋‹น๊ธฐ๊ธฐ๋Š” ์•ž ๋Œ€์ƒ์ด ๋‹น๊ฒจ์ง„ ๋’ค์˜ ๋ฐฐ์น˜๋กœ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์ดํŽ™ํŠธ ์ ์šฉ ์‹œ์ ์ด ์•„๋‹ˆ๋ผ ์ถœ๋ฐœ ์ฐจ๋ก€๊ฐ€ ์™”์„ ๋•Œ ์‹คํ–‰ + void StartPull(TSharedPtr MoveEndBarrier, UBoardActorModel* SourceModel, UBoardActorModel* TargetModel, UBoardMovementComponentModel* TargetMoveCompModel, UTileMapModel* TileMap, int32 PullDistance) + { + // ๋‹น๊ฒจ์ง€๋Š” ๊ฒฝ๋กœ ๊ณ„์‚ฐ (๊ฑฐ๋ฆฌ ์†Œ์ง„, ์‹œ์ „์ž์— ๋ถ™์Œ, ์ค‘๊ฐ„ ๋ง‰ํž˜ ์ค‘ ๋จผ์ € ์˜ค๋Š” ๊ณณ๊นŒ์ง€๋กœ ์งง์•„์ง) + const TArray PullPath = TileMap->GetPullPath(SourceModel->GetTileTransform().mIndex, TargetModel->GetTileTransform().mIndex, PullDistance); + + // ํ•œ ์นธ๋„ ๋‹น๊ธฐ์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ ๋Œ€์ƒ์ด ์ด๋™ ์ค‘์ด๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ํ•จ (์ด๋™ ์ค‘ ๋‹น๊ธฐ๊ธฐ๋Š” ์ง€์›ํ•˜์ง€ ์•Š์Œ) + const int32 PathNum = PullPath.Num(); + if (PathNum >= 2 && TargetMoveCompModel->IsMoving() == false) + { + // ์ •์ง€ ์ƒํƒœ ๋Œ€์ƒ: ์ฆ‰์‹œ ๋‹น๊ธฐ๊ธฐ ์‹œ์ž‘ + TargetMoveCompModel->PullAlongPath(PullPath, FOnBoardMoveFinished(), MoveEndBarrier); + + /* ๋กœ๊ทธ ์ž‘์„ฑ */ + + for (int32 PathIndex = 1; PathIndex < PathNum; ++PathIndex) + { + FSRPGTileEffectEventLog Log; + Log.mOccupancyState = ESRPGTileOccupancyState::Move; + Log.mPreTileIndex = PullPath[PathIndex - 1]; + Log.mNextTileIndex = PullPath[PathIndex]; + + GetWorldEventLogger(TargetModel)->LogTileEffect(TargetModel->GetModelId(), TargetModel->GetClass(), Log); + } + } + } +} + void UTacticalEffectExecutionCalculation_Pull::Execute(const FTacticalEffectCustomExecutionParameters& ExecutionParams, FTacticalEffectCustomExecutionOutput& OutExecutionOutput) const { Super::Execute(ExecutionParams, OutExecutionOutput); @@ -36,27 +68,14 @@ void UTacticalEffectExecutionCalculation_Pull::Execute(const FTacticalEffectCust UTileMapModel* TileMap = TargetMoveCompModel->GetTileMap(); checkf(TileMap != nullptr, TEXT("ํƒ€์ผ ๋งต nullptr")); - // ๋‹น๊ฒจ์ง€๋Š” ๊ฒฝ๋กœ ๊ณ„์‚ฐ (๊ฑฐ๋ฆฌ ์†Œ์ง„, ์‹œ์ „์ž์— ๋ถ™์Œ, ์ค‘๊ฐ„ ๋ง‰ํž˜ ์ค‘ ๋จผ์ € ์˜ค๋Š” ๊ณณ๊นŒ์ง€๋กœ ์งง์•„์ง) - const TArray PullPath = TileMap->GetPullPath(SourceModel->GetTileTransform().mIndex, TargetModel->GetTileTransform().mIndex, ExecutionParams.GetOwningSpec().GetStackCount()); + const int32 PullDistance = ExecutionParams.GetOwningSpec().GetStackCount(); - // ํ•œ ์นธ๋„ ๋‹น๊ธฐ์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ ๋Œ€์ƒ์ด ์ด๋™ ์ค‘์ด๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ํ•จ (์ด๋™ ์ค‘ ๋‹น๊ธฐ๊ธฐ๋Š” ์ง€์›ํ•˜์ง€ ์•Š์Œ) - const int32 PathNum = PullPath.Num(); - if (PathNum >= 2 && TargetMoveCompModel->IsMoving() == false) + // ์‹œ์ „์ž ์Šคํ‚ฌ์ด ํŽ˜์ด์ฆˆ ์ดํŽ™ํŠธ ์ ์šฉ ์ค‘์ด๋ฉด ํ์— ๋„ฃ์–ด ์ˆœ์ฐจ ์ถœ๋ฐœ, ์•„๋‹ˆ๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐ”๋กœ ์ถœ๋ฐœ + IBoardCombatTarget* SourceCombatTarget = Cast(SourceModel); + USkillComponentModel* SourceSkillComp = (SourceCombatTarget != nullptr) ? SourceCombatTarget->GetSkillComponentModel() : nullptr; + if (SourceSkillComp == nullptr || SourceSkillComp->EnqueueForcedMove(FOnStartForcedMove::CreateStatic(&StartPull, SourceModel, TargetModel, TargetMoveCompModel, TileMap, PullDistance)) == false) { - // ์ •์ง€ ์ƒํƒœ ๋Œ€์ƒ: ์ฆ‰์‹œ ๋‹น๊ธฐ๊ธฐ ์‹œ์ž‘ - TargetMoveCompModel->PullAlongPath(PullPath); - - /* ๋กœ๊ทธ ์ž‘์„ฑ */ - - for (int32 PathIndex = 1; PathIndex < PathNum; ++PathIndex) - { - FSRPGTileEffectEventLog Log; - Log.mOccupancyState = ESRPGTileOccupancyState::Move; - Log.mPreTileIndex = PullPath[PathIndex - 1]; - Log.mNextTileIndex = PullPath[PathIndex]; - - GetWorldEventLogger(TargetModel)->LogTileEffect(TargetModel->GetModelId(), TargetModel->GetClass(), Log); - } + StartPull(nullptr, SourceModel, TargetModel, TargetMoveCompModel, TileMap, PullDistance); } OutExecutionOutput.MarkDynamicMagnitudeHandledManually(); diff --git a/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Push.cpp b/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Push.cpp index 5caba82b4..36ccfa594 100644 --- a/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Push.cpp +++ b/Source/P_RD/TAS/Effect/Tag/TacticalEffect_Push.cpp @@ -7,9 +7,53 @@ #include "Component/BoardMovementComponent/BoardMovementComponentModel.h" #include "Component/AttributeComponent/AttributeSetComponentModel.h" +#include "Component/SkillComponent/SkillComponentModel.h" #include "Simulation/Logger/EventLogger.h" +namespace +{ + // @brief ๋ฐ€์น˜๊ธฐ ์ถœ๋ฐœ (๊ฒฝ๋กœ ๊ณ„์‚ฐ + ์ด๋™ ์‹œ์ž‘ + ๋กœ๊ทธ) + // ๊ด‘์—ญ ๋ฐ€์น˜๊ธฐ๋Š” ์•ž ๋Œ€์ƒ์ด ๋ฐ€๋ฆฐ ๋’ค์˜ ๋ฐฐ์น˜๋กœ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์ดํŽ™ํŠธ ์ ์šฉ ์‹œ์ ์ด ์•„๋‹ˆ๋ผ ์ถœ๋ฐœ ์ฐจ๋ก€๊ฐ€ ์™”์„ ๋•Œ ์‹คํ–‰ + void StartPush(TSharedPtr MoveEndBarrier, UBoardActorModel* SourceModel, UBoardActorModel* TargetModel, UBoardMovementComponentModel* TargetMoveCompModel, UTileMapModel* TileMap, int32 PushDistance) + { + const FTileIndex SourceTileIndex = SourceModel->GetTileTransform().mIndex; + const FTileIndex TargetTileIndex = TargetModel->GetTileTransform().mIndex; + + // ๋ฐ€๋ฆฌ๋Š” ๊ฒฝ๋กœ ๊ณ„์‚ฐ (๋’ค๊ฐ€ ๋ง‰ํžˆ๋ฉด ๋ง‰ํžˆ๊ธฐ ์ง์ „๊นŒ์ง€๋กœ ์งง์•„์ง) + // ์‹œ์ „์ž์™€ ๋Œ€์ƒ์ด ๊ฐ™์€ ํƒ€์ผ์ด๋ฉด ๋ฐœํŒ์ด๋ฏ€๋กœ ์‹œ์ „์žโ†’๋Œ€์ƒ ๋ฐฉํ–ฅ์„ ๊ตฌํ•  ์ˆ˜ ์—†์–ด ๋ฐœํŒ์˜ ๊ณ ์ • ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ€๊ณ , + // ๋‹ค๋ฅด๋ฉด ์œ ๋‹› ์Šคํ‚ฌ์ด๋ฏ€๋กœ ์‹œ์ „์ž์—์„œ ๋ฉ€์–ด์ง€๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ฏผ๋‹ค + const TArray PushPath = (SourceTileIndex == TargetTileIndex) + ? TileMap->GetPushPath(TargetTileIndex, SourceModel->GetTileTransform().mDirection, PushDistance) + : TileMap->GetPushPath(SourceTileIndex, TargetTileIndex, PushDistance); + + const int32 PathNum = PushPath.Num(); + if (TargetMoveCompModel->IsMoving() == true) + { + // ์ด๋™ ์ค‘์ธ ๋Œ€์ƒ: ๋“ฑ๋ก๋งŒ ํ•˜๊ณ , ์ด๋™ ๋ฃจํ”„๊ฐ€ ํ˜„์žฌ ์Šคํ…์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ ๋‚จ์€ ๊ฒฝ๋กœ๋ฅผ ๋ฐ€์น˜๊ธฐ ๊ฒฝ๋กœ๋กœ ๊ต์ฒด + // ํ•œ ์นธ๋„ ๋ฐ€๋ฆฌ์ง€ ๋ชปํ•ด๋„ ๋“ฑ๋กํ•ด์„œ ์ž”์—ฌ ๊ฑท๊ธฐ๋ฅผ ๋Š์Œ (๋ฐ€์น˜๊ธฐ ํ•จ์ •์„ ๋ฐŸ์œผ๋ฉด ๋ฐ€๋ฆฐ ๊ฑฐ๋ฆฌ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ด๋™ ์ข…๋ฃŒ) + TargetMoveCompModel->TryRegisterPendingPush(SourceTileIndex, PushPath); + } + else if (PathNum >= 2) + { + // ์ •์ง€ ์ƒํƒœ ๋Œ€์ƒ: ์ฆ‰์‹œ ๋ฐ€๊ธฐ ์‹œ์ž‘ (๋ฐฉ ์‹œ์ž‘ ์‹œ ๋ฐœํŒ ์œ„ ๋ฐฐ์น˜ ๋ฐœ๋™ ๋“ฑ). ํ•œ ์นธ๋„ ๋ฐ€๋ฆฌ์ง€ ๋ชปํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ํ•จ + TargetMoveCompModel->PushAlongPath(PushPath, FOnBoardMoveFinished(), MoveEndBarrier); + + /* ๋กœ๊ทธ ์ž‘์„ฑ */ + + for (int32 PathIndex = 1; PathIndex < PathNum; ++PathIndex) + { + FSRPGTileEffectEventLog Log; + Log.mOccupancyState = ESRPGTileOccupancyState::Move; + Log.mPreTileIndex = PushPath[PathIndex - 1]; + Log.mNextTileIndex = PushPath[PathIndex]; + + GetWorldEventLogger(TargetModel)->LogTileEffect(TargetModel->GetModelId(), TargetModel->GetClass(), Log); + } + } + } +} + void UTacticalEffectExecutionCalculation_Push::Execute(const FTacticalEffectCustomExecutionParameters& ExecutionParams, FTacticalEffectCustomExecutionOutput& OutExecutionOutput) const { Super::Execute(ExecutionParams, OutExecutionOutput); @@ -37,40 +81,14 @@ void UTacticalEffectExecutionCalculation_Push::Execute(const FTacticalEffectCust checkf(TileMap != nullptr, TEXT("ํƒ€์ผ ๋งต nullptr")); - const FTileIndex SourceTileIndex = SourceModel->GetTileTransform().mIndex; - const FTileIndex TargetTileIndex = TargetModel->GetTileTransform().mIndex; const int32 PushDistance = ExecutionParams.GetOwningSpec().GetStackCount(); - // ๋ฐ€๋ฆฌ๋Š” ๊ฒฝ๋กœ ๊ณ„์‚ฐ (๋’ค๊ฐ€ ๋ง‰ํžˆ๋ฉด ๋ง‰ํžˆ๊ธฐ ์ง์ „๊นŒ์ง€๋กœ ์งง์•„์ง) - // ์‹œ์ „์ž์™€ ๋Œ€์ƒ์ด ๊ฐ™์€ ํƒ€์ผ์ด๋ฉด ๋ฐœํŒ์ด๋ฏ€๋กœ ์‹œ์ „์žโ†’๋Œ€์ƒ ๋ฐฉํ–ฅ์„ ๊ตฌํ•  ์ˆ˜ ์—†์–ด ๋ฐœํŒ์˜ ๊ณ ์ • ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ€๊ณ , - // ๋‹ค๋ฅด๋ฉด ์œ ๋‹› ์Šคํ‚ฌ์ด๋ฏ€๋กœ ์‹œ์ „์ž์—์„œ ๋ฉ€์–ด์ง€๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๋ฏผ๋‹ค - const TArray PushPath = (SourceTileIndex == TargetTileIndex) - ? TileMap->GetPushPath(TargetTileIndex, SourceModel->GetTileTransform().mDirection, PushDistance) - : TileMap->GetPushPath(SourceTileIndex, TargetTileIndex, PushDistance); - - const int32 PathNum = PushPath.Num(); - if (TargetMoveCompModel->IsMoving() == true) - { - // ์ด๋™ ์ค‘์ธ ๋Œ€์ƒ: ๋“ฑ๋ก๋งŒ ํ•˜๊ณ , ์ด๋™ ๋ฃจํ”„๊ฐ€ ํ˜„์žฌ ์Šคํ…์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ ๋‚จ์€ ๊ฒฝ๋กœ๋ฅผ ๋ฐ€์น˜๊ธฐ ๊ฒฝ๋กœ๋กœ ๊ต์ฒด - // ํ•œ ์นธ๋„ ๋ฐ€๋ฆฌ์ง€ ๋ชปํ•ด๋„ ๋“ฑ๋กํ•ด์„œ ์ž”์—ฌ ๊ฑท๊ธฐ๋ฅผ ๋Š์Œ (๋ฐ€์น˜๊ธฐ ํ•จ์ •์„ ๋ฐŸ์œผ๋ฉด ๋ฐ€๋ฆฐ ๊ฑฐ๋ฆฌ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ด๋™ ์ข…๋ฃŒ) - TargetMoveCompModel->TryRegisterPendingPush(SourceTileIndex, PushPath); - } - else if (PathNum >= 2) + // ์‹œ์ „์ž ์Šคํ‚ฌ์ด ํŽ˜์ด์ฆˆ ์ดํŽ™ํŠธ ์ ์šฉ ์ค‘์ด๋ฉด ํ์— ๋„ฃ์–ด ์ˆœ์ฐจ ์ถœ๋ฐœ, ์•„๋‹ˆ๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐ”๋กœ ์ถœ๋ฐœ + IBoardCombatTarget* SourceCombatTarget = Cast(SourceModel); + USkillComponentModel* SourceSkillComp = (SourceCombatTarget != nullptr) ? SourceCombatTarget->GetSkillComponentModel() : nullptr; + if (SourceSkillComp == nullptr || SourceSkillComp->EnqueueForcedMove(FOnStartForcedMove::CreateStatic(&StartPush, SourceModel, TargetModel, TargetMoveCompModel, TileMap, PushDistance)) == false) { - // ์ •์ง€ ์ƒํƒœ ๋Œ€์ƒ: ์ฆ‰์‹œ ๋ฐ€๊ธฐ ์‹œ์ž‘ (๋ฐฉ ์‹œ์ž‘ ์‹œ ๋ฐœํŒ ์œ„ ๋ฐฐ์น˜ ๋ฐœ๋™ ๋“ฑ). ํ•œ ์นธ๋„ ๋ฐ€๋ฆฌ์ง€ ๋ชปํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ํ•จ - TargetMoveCompModel->PushAlongPath(PushPath); - - /* ๋กœ๊ทธ ์ž‘์„ฑ */ - - for (int32 PathIndex = 1; PathIndex < PathNum; ++PathIndex) - { - FSRPGTileEffectEventLog Log; - Log.mOccupancyState = ESRPGTileOccupancyState::Move; - Log.mPreTileIndex = PushPath[PathIndex - 1]; - Log.mNextTileIndex = PushPath[PathIndex]; - - GetWorldEventLogger(TargetModel)->LogTileEffect(TargetModel->GetModelId(), TargetModel->GetClass(), Log); - } + StartPush(nullptr, SourceModel, TargetModel, TargetMoveCompModel, TileMap, PushDistance); } OutExecutionOutput.MarkDynamicMagnitudeHandledManually(); diff --git a/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp b/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp index 8ff648344..4fe06bcb9 100644 --- a/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp +++ b/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.cpp @@ -470,10 +470,10 @@ void UCombatLayoutHUDWidget::NativeDestruct() // ํ™”๋ฉด์ด ๋ฐ”๋€ ๋’ค 0.5์ดˆ ํƒ€์ด๋จธ๊ฐ€ ์‚ด์•„์„œ ๋‹ซํžŒ HUD ์œ„์— ์ƒ์„ธ๋ฅผ ์—ฌ๋Š” ์ผ์„ ๋ง‰๋Š”๋‹ค. CancelStatusPress(); CancelMonsterSkillPress(); + mCommandLongPressTimerHandle.Cancel(); + mArtifactLongPressTimerHandle.Cancel(); if (UWorld* World = GetWorld()) { - World->GetTimerManager().ClearTimer(mCommandLongPressTimerHandle); - World->GetTimerManager().ClearTimer(mBoardLongPressTimerHandle); World->GetTimerManager().ClearTimer(mCombatAnnouncementTimerHandle); World->GetTimerManager().ClearTimer(mCombatResultStartDelayTimerHandle); } @@ -1445,15 +1445,11 @@ void UCombatLayoutHUDWidget::HandleAnyPressed() { continue; } - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().SetTimer(mCommandLongPressTimerHandle, - FTimerDelegate::CreateWeakLambda(this, [this, SlotIndex]() - { - HandleCommandLongPress(SlotIndex); - }), - LongPressSeconds, false); - } + mCommandLongPressTimerHandle.Start(this, LongPressSeconds, + FSimpleDelegate::CreateWeakLambda(this, [this, SlotIndex]() + { + HandleCommandLongPress(SlotIndex); + })); break; } @@ -1683,10 +1679,7 @@ void UCombatLayoutHUDWidget::HandleTurnPageRightClicked() void UCombatLayoutHUDWidget::HandleAnyReleased() { // ๋†“์•˜์œผ๋‹ˆ ์นด๋“œ ๊ธด ๋ˆ„๋ฆ„ ํŒ์ •์€ ๋๋‚ฌ๋‹ค. - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().ClearTimer(mCommandLongPressTimerHandle); - } + mCommandLongPressTimerHandle.Cancel(); if (mPressedTarget != nullptr) { @@ -3734,7 +3727,7 @@ FReply UCombatLayoutHUDWidget::NativeOnMouseMove(const FGeometry& InGeometry, && RDPointerGesture::HasMoved(mPressOrigin, InMouseEvent.GetScreenSpacePosition(), false)) { mPressMoved = true; - if (UWorld* World = GetWorld()) World->GetTimerManager().ClearTimer(mBoardLongPressTimerHandle); + mBoardLongPressTimerHandle.Cancel(); } return Super::NativeOnMouseMove(InGeometry, InMouseEvent); } @@ -4236,11 +4229,8 @@ FReply UCombatLayoutHUDWidget::NativeOnMouseButtonDown(const FGeometry& InGeomet mBoardPressIsTouch = false; mPressMoved = false; mPressActive = true; - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().SetTimer(mBoardLongPressTimerHandle, this, - &UCombatLayoutHUDWidget::HandleBoardLongPress, LongPressSeconds, false); - } + mBoardLongPressTimerHandle.Start(this, LongPressSeconds, + FSimpleDelegate::CreateUObject(this, &UCombatLayoutHUDWidget::HandleBoardLongPress)); return FReply::Handled(); } @@ -4257,11 +4247,8 @@ FReply UCombatLayoutHUDWidget::NativeOnTouchStarted(const FGeometry& InGeometry, mBoardPressIsTouch = true; mPressMoved = false; mPressActive = true; - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().SetTimer(mBoardLongPressTimerHandle, this, - &UCombatLayoutHUDWidget::HandleBoardLongPress, LongPressSeconds, false); - } + mBoardLongPressTimerHandle.Start(this, LongPressSeconds, + FSimpleDelegate::CreateUObject(this, &UCombatLayoutHUDWidget::HandleBoardLongPress)); return FReply::Handled(); } @@ -4322,7 +4309,7 @@ void UCombatLayoutHUDWidget::CancelBoardPress() { mPressActive = false; mPressMoved = true; - if (UWorld* World = GetWorld()) World->GetTimerManager().ClearTimer(mBoardLongPressTimerHandle); + mBoardLongPressTimerHandle.Cancel(); } void UCombatLayoutHUDWidget::ObserveBoardTouchDown(uint32 Pointer) @@ -4425,10 +4412,7 @@ FReply UCombatLayoutHUDWidget::NativeOnTouchMoved(const FGeometry& InGeometry, const bool bDragJustStarted = mPressActive && mPressMoved == false; mPressMoved = true; // ๋Œ๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ์ง€๋„๋ฅผ ๋ฏธ๋Š” ์†์„ ๊ธด ๋ˆ„๋ฆ„์œผ๋กœ ์˜ค์ธํ•˜์ง€ ์•Š๋Š”๋‹ค. - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().ClearTimer(mBoardLongPressTimerHandle); - } + mBoardLongPressTimerHandle.Cancel(); // 0823 ํ™•์ •: ์นด๋“œ๋Š” ์†์„ ๋—„ ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ **๋Œ๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ์ˆœ๊ฐ„** ์ ‘๋Š”๋‹ค. // ์†์„ ๋—€ ๋’ค์— ์ ‘ํžˆ๋ฉด ํ™”๋ฉด์„ ๋ฏธ๋Š” ๋‚ด๋‚ด ์นด๋“œ๊ฐ€ ์‹œ์•ผ๋ฅผ ๊ฐ€๋ฆฐ๋‹ค. if (bDragJustStarted && IsAiming() == false && mIsActionPlaying == false @@ -4467,10 +4451,7 @@ void UCombatLayoutHUDWidget::FinishBoardPress(const FVector2D& ScreenPosition) * ํ™•์ •์ด ๊ฐ™์ด ๋˜์–ด ๊ทธ ์ž๋ฆฌ์—์„œ ๋ฐœ๋™ํ–ˆ๋‹ค. */ // ๋†“์•˜์œผ๋‹ˆ ๊ธด ๋ˆ„๋ฆ„ ํŒ์ •์€ ๋๋‚ฌ๋‹ค. ๋ฐœํ™” ์ „์— ๋†“์•˜์œผ๋ฉด ํƒญ์ด๋‹ค. - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().ClearTimer(mBoardLongPressTimerHandle); - } + mBoardLongPressTimerHandle.Cancel(); if (mTurnSwipeConsumed) { mPressActive = false; @@ -4841,10 +4822,6 @@ void UCombatLayoutHUDWidget::HandleSettingsMenuClicked() // OnBackRequested๋งŒ ๋ณด๋‚ด๋”๋ผ๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ • ํ™”๋ฉด์— ๊ฐ‡ํžˆ์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค. Settings->OnBackRequested.AddUniqueDynamic( this, &UCombatLayoutHUDWidget::HandleSettingsPanelBackRequested); - Settings->OnSaveAndExitRequested.AddUniqueDynamic( - this, &UCombatLayoutHUDWidget::HandleSettingsPanelSaveAndExitRequested); - Settings->OnAbandonRunConfirmed.AddUniqueDynamic( - this, &UCombatLayoutHUDWidget::HandleSettingsPanelAbandonRunConfirmed); Settings->SetPanelMode(ESettingsPanelMode::InGame); // ์ „ํˆฌ ์ค‘์—๋Š” ๋Ÿฐ์„ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ํฌ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค. ํƒ€์ดํ‹€์—์„œ ์—ด ๋•Œ์™€ ๋‹ค๋ฅธ ์ ์ด๋‹ค. Settings->RefreshPanelState(true, true); @@ -4874,58 +4851,6 @@ void UCombatLayoutHUDWidget::HandleSettingsPanelBackRequested() RefreshWorldGestureInputBlock(); } -/** @brief ๋Ÿฐ ์•ก์…˜์„ ์ž ๊ทธ๊ณ  ์ €์žฅ ํ›„ ์ข…๋ฃŒ ์˜๋„๋ฅผ ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด์— ์ „๋‹ฌํ•œ๋‹ค. */ -void UCombatLayoutHUDWidget::HandleSettingsPanelSaveAndExitRequested() -{ - UWorld* World = GetWorld(); - UWorldWidgetSubsystem* WorldWidgetSubsystem = - World != nullptr ? World->GetSubsystem() : nullptr; - USettingsPanelWidget* Settings = WorldWidgetSubsystem != nullptr - ? WorldWidgetSubsystem->GetWorldWidget( - EWorldWidgetType::InGameSettings) - : nullptr; - if (Settings != nullptr) - { - Settings->SetRunActionsEnabled(false); - Settings->SetStatusText(LOCTEXT("SavingRun", "์ €์žฅ ์ค‘...")); - } - - if (mUIModel != nullptr) - { - mUIModel->RequestSaveAndExitRun(); - return; - } - HandleSaveAndExitCompleted(false); -} - -/** @brief ํ™•์ธ์ด ๋๋‚œ ๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์„ ๊ธฐ์กด UIModel -> CombatGameMode ๊ฒฝ๋กœ๋กœ ๋ณด๋‚ธ๋‹ค. */ -void UCombatLayoutHUDWidget::HandleSettingsPanelAbandonRunConfirmed() -{ - UWorld* World = GetWorld(); - UWorldWidgetSubsystem* WorldWidgetSubsystem = - World != nullptr ? World->GetSubsystem() : nullptr; - USettingsPanelWidget* Settings = WorldWidgetSubsystem != nullptr - ? WorldWidgetSubsystem->GetWorldWidget( - EWorldWidgetType::InGameSettings) - : nullptr; - if (Settings != nullptr) - { - Settings->HideAbandonConfirm(); - Settings->SetRunActionsEnabled(false); - Settings->SetStatusText(FText::GetEmpty()); - } - - if (mUIModel != nullptr) - { - mUIModel->RequestAbandonRun(); - return; - } - if (Settings != nullptr) - { - HandleAbandonRunCompleted(false); - } -} - /** @brief ์ €์žฅ/์ „ํ™˜ ์‹คํŒจ๋งŒ ํ˜„์žฌ ํ™”๋ฉด์—์„œ ๋ณต๊ตฌํ•œ๋‹ค. ์„ฑ๊ณต ์‹œ ๋ฐฉ ์ „ํ™˜์ด ์ด์–ด์ง„๋‹ค. */ void UCombatLayoutHUDWidget::HandleSaveAndExitCompleted(const bool bSuccess) { @@ -4989,21 +4914,17 @@ void UCombatLayoutHUDWidget::BeginArtifactPress(const int32 SlotIndex) { return; } - World->GetTimerManager().SetTimer(mArtifactLongPressTimerHandle, - FTimerDelegate::CreateWeakLambda(this, [this, SlotIndex]() - { - HandleArtifactLongPress(SlotIndex); - }), - LongPressSeconds, false); + mArtifactLongPressTimerHandle.Start(this, LongPressSeconds, + FSimpleDelegate::CreateWeakLambda(this, [this, SlotIndex]() + { + HandleArtifactLongPress(SlotIndex); + })); } void UCombatLayoutHUDWidget::HandleArtifactReleased() { // ๊พน ๋ˆ„๋ฅด๊ธฐ ์ „์— ๋–ผ๋ฉด ์•„๋ฌด ์ผ๋„ ์—†๋‹ค. - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().ClearTimer(mArtifactLongPressTimerHandle); - } + mArtifactLongPressTimerHandle.Cancel(); mArtifactPressedSlot = INDEX_NONE; } @@ -5268,14 +5189,11 @@ void UCombatLayoutHUDWidget::BeginMonsterSkillPress(const int32 SlotIndex) } mMonsterSkillPressActive = true; mMonsterSkillPressedSlot = SlotIndex; - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().SetTimer(mMonsterSkillLongPressTimerHandle, - FTimerDelegate::CreateWeakLambda(this, [this, SlotIndex]() - { - HandleMonsterSkillLongPress(SlotIndex); - }), LongPressSeconds, false); - } + mMonsterSkillLongPressTimerHandle.Start(this, LongPressSeconds, + FSimpleDelegate::CreateWeakLambda(this, [this, SlotIndex]() + { + HandleMonsterSkillLongPress(SlotIndex); + })); } /** @brief ์งง๊ฒŒ ๋—€ ์†์€ ์ƒ์„ธ๋ฅผ ์—ด์ง€ ์•Š๊ณ  ํ›„๋ณด๋งŒ ๋ฌด๋ฅธ๋‹ค. */ @@ -5307,11 +5225,7 @@ void UCombatLayoutHUDWidget::HandleMonsterSkillLongPress(const int32 SlotIndex) void UCombatLayoutHUDWidget::CancelMonsterSkillPress() { - if (UWorld* World = GetWorld()) - { - World->GetTimerManager().ClearTimer(mMonsterSkillLongPressTimerHandle); - } - mMonsterSkillLongPressTimerHandle.Invalidate(); + mMonsterSkillLongPressTimerHandle.Cancel(); mMonsterSkillPressedSlot = INDEX_NONE; mMonsterSkillPressActive = false; } @@ -6384,9 +6298,7 @@ void UCombatLayoutHUDWidget::TriggerMonsterSkillLongPressForTest(const int32 Slo bool UCombatLayoutHUDWidget::IsMonsterSkillLongPressPendingForTest() const { - const UWorld* World = GetWorld(); - return mMonsterSkillPressActive == true && World != nullptr - && World->GetTimerManager().IsTimerActive(mMonsterSkillLongPressTimerHandle); + return mMonsterSkillPressActive && mMonsterSkillLongPressTimerHandle.IsPending(); } bool UCombatLayoutHUDWidget::IsMonsterSkillPressActiveForTest(const int32 SlotIndex) const diff --git a/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.h b/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.h index 88e8fe440..36208ae5d 100644 --- a/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.h +++ b/Source/P_RD/UI/Combat/CombatLayoutHUDWidget.h @@ -20,6 +20,7 @@ */ #include "RDMinimal.h" +#include "UI/RealTimeLongPressTimer.h" #include "UI/Combat/CombatUIWidgetBase.h" #include "UI/Combat/CombatUITypes.h" @@ -362,10 +363,6 @@ class P_RD_API UCombatLayoutHUDWidget : public UCombatUIWidgetBase UFUNCTION() void HandleSettingsMenuClicked(); /** @brief ์„ค์ • ํŒจ๋„์˜ Back ์š”์ฒญ์„ ๋ฐ›์•„ ํŒจ๋„์„ ๋‹ซ๋Š”๋‹ค. */ UFUNCTION() void HandleSettingsPanelBackRequested(); - /** @brief ์„ค์ • ํŒจ๋„์˜ ์ €์žฅ ํ›„ ์ข…๋ฃŒ ์š”์ฒญ์„ UIModel๋กœ ์ „๋‹ฌํ•œ๋‹ค. */ - UFUNCTION() void HandleSettingsPanelSaveAndExitRequested(); - /** @brief ํ™•์ธ์„ ๋งˆ์นœ ๋Ÿฐ ํฌ๊ธฐ ์š”์ฒญ์„ ๊ธฐ์กด ์ „ํˆฌ UIModel ๊ฒฝ๋กœ๋กœ ์ „๋‹ฌํ•œ๋‹ค. */ - UFUNCTION() void HandleSettingsPanelAbandonRunConfirmed(); /** @brief ์ €์žฅ ๋˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์ „ํ™˜ ์‹คํŒจ ์‹œ ์„ค์ •ํŒ ์ž…๋ ฅ๊ณผ ์ƒํƒœ๋ฅผ ๋ณต๊ตฌํ•œ๋‹ค. */ UFUNCTION() void HandleSaveAndExitCompleted(bool bSuccess); /** @brief ๋Ÿฐ ํฌ๊ธฐ ๋˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์ „ํ™˜ ์‹คํŒจ ์‹œ ์„ค์ •ํŒ ์ž…๋ ฅ๊ณผ ์ƒํƒœ๋ฅผ ๋ณต๊ตฌํ•œ๋‹ค. */ @@ -390,7 +387,7 @@ class P_RD_API UCombatLayoutHUDWidget : public UCombatUIWidgetBase void BeginArtifactPress(int32 SlotIndex); UPROPERTY(Transient) TArray> mArtifactButtons; - FTimerHandle mArtifactLongPressTimerHandle; + FRealTimeLongPressTimer mArtifactLongPressTimerHandle; int32 mArtifactPressedSlot = INDEX_NONE; /** @@ -521,11 +518,11 @@ class P_RD_API UCombatLayoutHUDWidget : public UCombatUIWidgetBase * ๋˜๋Œ์•„์˜ค๊ณ , ์ ์ด๋ฉด ์œ„ํ˜‘ ๋ฒ”์œ„๋„ ํŒ์— ๊ฐ™์ด ์น ๋ ค ์˜จ๋‹ค. */ void HandleBoardLongPress(); - FTimerHandle mBoardLongPressTimerHandle; + FRealTimeLongPressTimer mBoardLongPressTimerHandle; /** @brief ์นด๋“œ๋ฅผ ์˜ค๋ž˜ ๋ˆŒ๋ €๋‹ค. ๊ทธ ์Šคํ‚ฌ์˜ ์ƒ์„ธ๋ฅผ ์š”์ฒญํ•˜๊ณ  ์ด์–ด์งˆ ํด๋ฆญ์€ ์‚ผํ‚จ๋‹ค. */ void HandleCommandLongPress(int32 SlotIndex); - FTimerHandle mCommandLongPressTimerHandle; + FRealTimeLongPressTimer mCommandLongPressTimerHandle; /** * @brief ๊ธด ๋ˆ„๋ฆ„์ด ๋ฐœํ™”ํ–ˆ์œผ๋ฉด ๋’ค๋”ฐ๋ผ ์˜ค๋Š” ํด๋ฆญ(๋—Œ)์„ ํ•œ ๋ฒˆ ๋ฌด์‹œํ•œ๋‹ค. @@ -1230,7 +1227,7 @@ class P_RD_API UCombatLayoutHUDWidget : public UCombatUIWidgetBase int32 mMonsterTabInspectedUnitId = INDEX_NONE; /** @brief ๋ณด์ด๋Š” ์Šฌ๋กฏโ†’FUnitDetailSkillUI::mSkillIndex ์™•๋ณต ์‹๋ณ„์ž. */ TArray mMonsterTabSkillIndices; - FTimerHandle mMonsterSkillLongPressTimerHandle; + FRealTimeLongPressTimer mMonsterSkillLongPressTimerHandle; int32 mMonsterSkillPressedSlot = INDEX_NONE; bool mMonsterSkillPressActive = false; // ์•„๋ž˜ ๋„ท๋„ ํ”„๋ ˆ์  ํ„ฐ ์บ์‹œ์˜ ๋น„์นœ ํฌ์ธํ„ฐ๋‹ค. ๊ฐ’ ์ฑ„์šฐ๊ธฐ๋Š” HUD ์ƒ์„ธ ๊ฒฝ๋กœ๊ฐ€ ํ•œ๋‹ค. diff --git a/Source/P_RD/UI/RealTimeLongPressTimer.h b/Source/P_RD/UI/RealTimeLongPressTimer.h new file mode 100644 index 000000000..4b05b8e9c --- /dev/null +++ b/Source/P_RD/UI/RealTimeLongPressTimer.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Containers/Ticker.h" +#include "HAL/PlatformTime.h" + +/** A cancelable hold timer measured in wall-clock seconds, independent of world time dilation. */ +class FRealTimeLongPressTimer +{ +public: + ~FRealTimeLongPressTimer() { Cancel(); } + + void Start(UObject* Owner, double DurationSeconds, FSimpleDelegate Callback) + { + Cancel(); + const double Deadline = FPlatformTime::Seconds() + DurationSeconds; + Handle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateWeakLambda(Owner, + [this, Deadline, Callback](float) + { + if (FPlatformTime::Seconds() < Deadline) return true; + Handle.Reset(); + Callback.ExecuteIfBound(); + return false; + })); + } + + void Cancel() + { + if (Handle.IsValid()) FTSTicker::GetCoreTicker().RemoveTicker(Handle); + Handle.Reset(); + } + + bool IsPending() const { return Handle.IsValid(); } + +private: + FTSTicker::FDelegateHandle Handle; +}; diff --git a/Source/P_RD/UI/Reward/RewardConcept03Widget.cpp b/Source/P_RD/UI/Reward/RewardConcept03Widget.cpp index e97299a6a..109b6e913 100644 --- a/Source/P_RD/UI/Reward/RewardConcept03Widget.cpp +++ b/Source/P_RD/UI/Reward/RewardConcept03Widget.cpp @@ -1005,6 +1005,7 @@ void URewardConcept03Widget::AdvanceRewardFlow() ClaimExperienceReward(); PresentationState = EPresentationState::ChestAwaitInput; SetCurrentStep(RewardConcept03::ChestStep); + if (UIModel != nullptr) UIModel->RequestExperiencePresentationCompleted(); break; case RewardConcept03::GoldStep: if (PresentationState == EPresentationState::AwaitGoldContinue) diff --git a/Source/P_RD/UI/Reward/RewardUIModel.h b/Source/P_RD/UI/Reward/RewardUIModel.h index d89e9570c..2c87047bf 100644 --- a/Source/P_RD/UI/Reward/RewardUIModel.h +++ b/Source/P_RD/UI/Reward/RewardUIModel.h @@ -15,6 +15,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRewardUIChanged); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRewardClaimed); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnExperiencePresentationCompleted); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRewardChoicesChanged); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRewardChosen, int32, ChoiceIndex); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnRewardClaimRequested, ERewardClaimKind, ClaimKind, int32, ChoiceIndex); @@ -43,6 +44,10 @@ class P_RD_API URewardUIModel : public UObject UPROPERTY(BlueprintAssignable, Category = "Reward|Input") FOnRewardClaimed OnRewardClaimed; + /** Experience screen was advanced, including when its grant was restored from a save. */ + UPROPERTY(BlueprintAssignable, Category = "Reward|Input") + FOnExperiencePresentationCompleted OnExperiencePresentationCompleted; + /** @brief ๋ฃธ ๋ณด์ƒ ํ•ญ๋ชฉ์ด ์„ค์ •/๊ฐฑ์‹ ๋์Œ์„ ์•Œ๋ฆผ. ์œ„์ ฏ์€ ๋ณด์ƒ ํ–‰์„ ๋‹ค์‹œ ๊ทธ๋ฆฐ๋‹ค. */ UPROPERTY(BlueprintAssignable, Category = "Reward|UI") FOnRewardChoicesChanged OnChoicesChanged; @@ -106,6 +111,10 @@ class P_RD_API URewardUIModel : public UObject UFUNCTION(BlueprintCallable, Category = "Reward|Push") void ConfirmSelectedReward(FPrimaryAssetId RewardId); UFUNCTION(BlueprintCallable, Category = "Reward|Push") void ConfirmGrantBundle(const FRewardGrantBundleResultUI& Result); UFUNCTION(BlueprintCallable, Category = "Reward|Input") void RequestFinishPresentation() { RequestClaim(); } + UFUNCTION(BlueprintCallable, Category = "Reward|Input") void RequestExperiencePresentationCompleted() + { + OnExperiencePresentationCompleted.Broadcast(); + } /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ์œ„์ ฏ์ด ์ฝ๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */ public: diff --git a/Source/P_RD/UI/RunOptionsRailWidget.cpp b/Source/P_RD/UI/RunOptionsRailWidget.cpp index 2a9665255..b40b3fcba 100644 --- a/Source/P_RD/UI/RunOptionsRailWidget.cpp +++ b/Source/P_RD/UI/RunOptionsRailWidget.cpp @@ -928,21 +928,17 @@ void URunOptionsRailWidget::BeginDetailPress( { return; } - GetWorld()->GetTimerManager().ClearTimer(DetailLongPressTimer); + DetailLongPressTimer.Cancel(); PressedDetailSlot = SlotIndex; bPressedDetailIsArtifact = bArtifact; bDetailLongPressTriggered = false; - GetWorld()->GetTimerManager().SetTimer(DetailLongPressTimer, - this, &URunOptionsRailWidget::FireHeldDetail, - DetailLongPressSeconds, false); + DetailLongPressTimer.Start(this, DetailLongPressSeconds, + FSimpleDelegate::CreateUObject(this, &URunOptionsRailWidget::FireHeldDetail)); } void URunOptionsRailWidget::EndDetailPress() { - if (GetWorld() != nullptr) - { - GetWorld()->GetTimerManager().ClearTimer(DetailLongPressTimer); - } + DetailLongPressTimer.Cancel(); PressedDetailSlot = INDEX_NONE; bDetailLongPressTriggered = false; } diff --git a/Source/P_RD/UI/RunOptionsRailWidget.h b/Source/P_RD/UI/RunOptionsRailWidget.h index c601f2a3a..6453e6026 100644 --- a/Source/P_RD/UI/RunOptionsRailWidget.h +++ b/Source/P_RD/UI/RunOptionsRailWidget.h @@ -2,6 +2,7 @@ // @brief ์ „ํˆฌ HUD์˜ ์ง€๋„ยท์šฉ๋ณ‘ยท๋ชฌ์Šคํ„ฐยท์„ค์ • ๋ ˆ์ผ์„ ๋ฐฉ ๊ณต์šฉ ํ™”๋ฉด์—์„œ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. #pragma once +#include "UI/RealTimeLongPressTimer.h" #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" @@ -192,7 +193,7 @@ class P_RD_API URunOptionsRailWidget : public UUserWidget bool bMapContext = false; bool bInventoryPageShown = false; int32 SelectedPartyMember = 0; - FTimerHandle DetailLongPressTimer; + FRealTimeLongPressTimer DetailLongPressTimer; int32 PressedDetailSlot = INDEX_NONE; bool bPressedDetailIsArtifact = false; bool bDetailLongPressTriggered = false; diff --git a/Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp b/Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp index 78b2bed09..a5a2d2963 100644 --- a/Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp +++ b/Source/P_RD/UI/Shop/ShopUIWidgetBase.cpp @@ -778,10 +778,10 @@ void UShopUIWidgetBase::BeginSkillSlotPress(const int32 SkillSlotIndex) return; } - GetWorld()->GetTimerManager().ClearTimer(mSkillLongPressTimer); + mSkillLongPressTimer.Cancel(); mPressedSkillSlotIndex = SkillSlotIndex; mSkillLongPressTriggered = false; - FTimerDelegate LongPressDelegate = FTimerDelegate::CreateWeakLambda(this, + FSimpleDelegate LongPressDelegate = FSimpleDelegate::CreateWeakLambda(this, [this, SkillSlotIndex]() { if (mPressedSkillSlotIndex == SkillSlotIndex) @@ -789,8 +789,7 @@ void UShopUIWidgetBase::BeginSkillSlotPress(const int32 SkillSlotIndex) ShowHeldSkillDetails(SkillSlotIndex); } }); - GetWorld()->GetTimerManager().SetTimer(mSkillLongPressTimer, - LongPressDelegate, SkillDetailLongPressSeconds, false); + mSkillLongPressTimer.Start(this, SkillDetailLongPressSeconds, LongPressDelegate); } void UShopUIWidgetBase::EndSkillSlotPress(const int32 SkillSlotIndex) @@ -799,10 +798,7 @@ void UShopUIWidgetBase::EndSkillSlotPress(const int32 SkillSlotIndex) { return; } - if (GetWorld() != nullptr) - { - GetWorld()->GetTimerManager().ClearTimer(mSkillLongPressTimer); - } + mSkillLongPressTimer.Cancel(); if (mSkillLongPressTriggered) { @@ -931,10 +927,10 @@ void UShopUIWidgetBase::BeginRailSlotPress(const int32 RailSlotIndex) { return; } - GetWorld()->GetTimerManager().ClearTimer(mRailLongPressTimer); + mRailLongPressTimer.Cancel(); mPressedRailSlotIndex = RailSlotIndex; mRailLongPressTriggered = false; - FTimerDelegate LongPressDelegate = FTimerDelegate::CreateWeakLambda(this, + FSimpleDelegate LongPressDelegate = FSimpleDelegate::CreateWeakLambda(this, [this, RailSlotIndex]() { if (mPressedRailSlotIndex == RailSlotIndex) @@ -942,8 +938,7 @@ void UShopUIWidgetBase::BeginRailSlotPress(const int32 RailSlotIndex) ShowHeldRailItemDetails(RailSlotIndex); } }); - GetWorld()->GetTimerManager().SetTimer(mRailLongPressTimer, - LongPressDelegate, SkillDetailLongPressSeconds, false); + mRailLongPressTimer.Start(this, SkillDetailLongPressSeconds, LongPressDelegate); } void UShopUIWidgetBase::EndRailSlotPress(const int32 RailSlotIndex) @@ -952,10 +947,7 @@ void UShopUIWidgetBase::EndRailSlotPress(const int32 RailSlotIndex) { return; } - if (GetWorld() != nullptr) - { - GetWorld()->GetTimerManager().ClearTimer(mRailLongPressTimer); - } + mRailLongPressTimer.Cancel(); mPressedRailSlotIndex = INDEX_NONE; mRailLongPressTriggered = false; } @@ -2567,11 +2559,8 @@ void UShopUIWidgetBase::ShowShopDetail(const FText& Name, void UShopUIWidgetBase::NativeDestruct() { RemoveFirstVisitGuide(); - if (GetWorld() != nullptr) - { - GetWorld()->GetTimerManager().ClearTimer(mSkillLongPressTimer); - GetWorld()->GetTimerManager().ClearTimer(mRailLongPressTimer); - } + mSkillLongPressTimer.Cancel(); + mRailLongPressTimer.Cancel(); mPressedSkillSlotIndex = INDEX_NONE; mSkillLongPressTriggered = false; mPressedRailSlotIndex = INDEX_NONE; diff --git a/Source/P_RD/UI/Shop/ShopUIWidgetBase.h b/Source/P_RD/UI/Shop/ShopUIWidgetBase.h index 67463050b..ae9168237 100644 --- a/Source/P_RD/UI/Shop/ShopUIWidgetBase.h +++ b/Source/P_RD/UI/Shop/ShopUIWidgetBase.h @@ -3,6 +3,7 @@ // @date 2026-06-18 #pragma once +#include "UI/RealTimeLongPressTimer.h" #include "RDMinimal.h" #include "TimerManager.h" @@ -474,12 +475,12 @@ class P_RD_API UShopUIWidgetBase : public URDUserWidget bool mIsArtifactInventoryOpen = false; /** ๋ชจ๋ฐ”์ผ ์žฅ์ฐฉ ์Šคํ‚ฌ ๊ธธ๊ฒŒ ๋ˆ„๋ฅด๊ธฐ ์ƒํƒœ. */ - FTimerHandle mSkillLongPressTimer; + FRealTimeLongPressTimer mSkillLongPressTimer; int32 mPressedSkillSlotIndex = INDEX_NONE; bool mSkillLongPressTriggered = false; /** ํŒ๋งค ์•„ํ‹ฐํŒฉํŠธ/์Šคํ‚ฌ ์นด๋“œ๋Š” ์†์„ ๋–ผ๊ธฐ ์ „ ์ž„๊ณ„์‹œ๊ฐ„์— ์ƒ์„ธ๋ฅผ ์—ฐ๋‹ค. */ - FTimerHandle mRailLongPressTimer; + FRealTimeLongPressTimer mRailLongPressTimer; int32 mPressedRailSlotIndex = INDEX_NONE; bool mRailLongPressTriggered = false; diff --git a/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.cpp b/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.cpp index a8e4ab965..50bc59fe5 100644 --- a/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.cpp +++ b/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.cpp @@ -19,6 +19,8 @@ int32 URefreshPullDescriptionsCommandlet::Main(const FString& Params) { FInternationalization::Get().SetCurrentCulture(TEXT("ko")); const bool bApply = FParse::Param(*Params, TEXT("Apply")); + FString SelectedAsset; + FParse::Value(*Params, TEXT("Asset="), SelectedAsset); auto& Registry = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")).Get(); Registry.ScanPathsSynchronous({TEXT("/Game/BP/DataAsset/Skill")}, true); TArray Assets; @@ -27,12 +29,17 @@ int32 URefreshPullDescriptionsCommandlet::Main(const FString& Params) for (const FAssetData& Asset : Assets) { auto* Skill = Cast(Asset.GetAsset()); - if (!Skill || !Skill->mDescription.ToString().Contains(TEXT("๋Œ€์ƒ์„ ์‹œ์ „์ž ์˜†๊นŒ์ง€ ๋Œ์–ด์˜ต๋‹ˆ๋‹ค."))) continue; + if (!Skill) continue; + if (!SelectedAsset.IsEmpty()) + { + if (Skill->GetPathName() != SelectedAsset) continue; + } + else if (!Skill->mDescription.ToString().Contains(TEXT("๋Œ€์ƒ์„ ์‹œ์ „์ž ์˜†๊นŒ์ง€ ๋Œ์–ด์˜ต๋‹ˆ๋‹ค."))) continue; bool bHasPull = false; for (const auto& Phase : Skill->mSkillPhaseLayers) for (const auto& Layer : Phase.mSkillEffectLayers) bHasPull |= Layer.IsValid() && Layer.GetScriptStruct()->IsChildOf(FSkillEffectLayer_Pull::StaticStruct()); - if (!bHasPull) continue; + if (SelectedAsset.IsEmpty() && !bHasPull) continue; const FText Description = Skill->MakeDescription(); if (Description.IsEmpty() || Description.ToString().Contains(TEXT("๋Œ€์ƒ์„ ์‹œ์ „์ž ์˜†๊นŒ์ง€ ๋Œ์–ด์˜ต๋‹ˆ๋‹ค."))) return 1; UE_LOG(LogTemp, Display, TEXT("RefreshPullDescriptions %s: %s -> %s"), @@ -46,5 +53,5 @@ int32 URefreshPullDescriptionsCommandlet::Main(const FString& Params) ++Changed; } UE_LOG(LogTemp, Display, TEXT("RefreshPullDescriptions: %d %s"), Changed, bApply ? TEXT("saved") : TEXT("would change")); - return 0; + return !SelectedAsset.IsEmpty() && Changed != 1 ? 1 : 0; } diff --git a/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.h b/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.h index ed1d8d29b..fd7b5a109 100644 --- a/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.h +++ b/Source/P_RDEditor/Commandlet/RefreshPullDescriptionsCommandlet.h @@ -4,6 +4,7 @@ #include "RefreshPullDescriptionsCommandlet.generated.h" // Preview stale generated pull descriptions; pass -Apply to save replacements. +// Use -Asset= to regenerate one explicitly selected skill. UCLASS() class URefreshPullDescriptionsCommandlet : public UCommandlet { diff --git a/Source/P_RDTests/Actor/BoardActor/GimmickModelTests.cpp b/Source/P_RDTests/Actor/BoardActor/GimmickModelTests.cpp index b7c1c5c23..35e43af31 100644 --- a/Source/P_RDTests/Actor/BoardActor/GimmickModelTests.cpp +++ b/Source/P_RDTests/Actor/BoardActor/GimmickModelTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "Actor/BoardActor/GimmickTestsHelper.h" // UMockOverlapGimmickModel, UMockGimmickVictimUnitModel @@ -47,10 +48,10 @@ namespace return nullptr; } - // @brief ๊ธฐ๋ฏน ์Šคํ‚ฌ ๊ณตํ†ต ๊ณจ๊ฒฉ (๋‹จํƒ€, ์ž๊ธฐ ํƒ€์ผ ์กฐ์ค€, ์ „ ํŒ€ ํƒ€๊ฒฉ) - UStaticSkillData* MakeGimmickSkillDataBase(UObject* Outer) + // @brief ๊ธฐ๋ฏน ์Šคํ‚ฌ ๊ณตํ†ต ๊ณจ๊ฒฉ (๋‹จํƒ€, ์ž๊ธฐ ํƒ€์ผ ์กฐ์ค€, ์ „ ํŒ€ ํƒ€๊ฒฉ). ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UStaticSkillData* MakeGimmickSkillDataBase(UObject* Outer, FTestObjectScope& Scope) { - UStaticSkillData* SkillData = NewObject(Outer); + UStaticSkillData* SkillData = Scope.New(Outer); // ์Šคํ‚ฌ ์‹œ์ „ ์‹œ ์ฟจ๋‹ค์šด ์ŠคํŽ™์„ ๋งŒ๋“ค๋ฏ€๋กœ ์‹ค์ œ ๊ธฐ๋ฏน DA์™€ ๊ฐ™์€ ๋ผ์šด๋“œ ์ฟจ๋‹ค์šด ์ง€์ • (๋ฏธ์ง€์ • ์‹œ ์ŠคํŽ™์ด ๋ฌดํšจ) SkillData->mCooldownEffectClass = UTacticalEffect_RoundCooldown::StaticClass(); SkillData->mSkillAnimationSet.mApplyMotionTags.Add(AnimationTags::Animation_Montage_Skill_Melee_Punch); @@ -65,9 +66,9 @@ namespace } // @brief ๊ธฐ์ ˆ ํŠธ๋žฉ ์Šคํ‚ฌ (๊ธฐ์ ˆ ํƒœ๊ทธ 1 ๋ถ€์—ฌ) - UStaticSkillData* MakeStunSkillData(UObject* Outer) + UStaticSkillData* MakeStunSkillData(UObject* Outer, FTestObjectScope& Scope) { - UStaticSkillData* SkillData = MakeGimmickSkillDataBase(Outer); + UStaticSkillData* SkillData = MakeGimmickSkillDataBase(Outer, Scope); TInstancedStruct Layer; Layer.InitializeAs(); @@ -77,9 +78,9 @@ namespace } // @brief ๋ฐ€์น˜๊ธฐ ๋ฐœํŒ ์Šคํ‚ฌ (์‹œ์ „์ž ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ€์นจ) - UStaticSkillData* MakePushSkillData(UObject* Outer, int32 PushDistance) + UStaticSkillData* MakePushSkillData(UObject* Outer, FTestObjectScope& Scope, int32 PushDistance) { - UStaticSkillData* SkillData = MakeGimmickSkillDataBase(Outer); + UStaticSkillData* SkillData = MakeGimmickSkillDataBase(Outer, Scope); TInstancedStruct Layer; Layer.InitializeAs(); @@ -97,9 +98,10 @@ namespace UMockUnitMovementComponentModel* Movement = nullptr; }; - // @brief 8x8 ํƒ€์ผ๋งต์— ๊ธฐ๋ฏน๊ณผ ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์Šคํ‚ฌ/์ˆ˜๋ช…์„ ์„ธํŒ… + // @brief 8x8 ํƒ€์ผ๋งต์— ๊ธฐ๋ฏน๊ณผ ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์Šคํ‚ฌ/์ˆ˜๋ช…์„ ์„ธํŒ… (์ƒ์„ฑ ๊ฐ์ฒด๋Š” ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) FGimmickFixture MakeGimmickFixture( UWorld* World, + FTestObjectScope& Scope, const FTileTransform& GimmickTransform, const FTileTransform& UnitTransform, UStaticSkillData* SkillData, @@ -107,11 +109,11 @@ namespace { FGimmickFixture Fixture; - Fixture.TileMap = NewObject(World); + Fixture.TileMap = Scope.New(World); Fixture.TileMap->SetDimensions(8, 8); // ๊ธฐ๋ฏน: ํƒ€์ผ๋งต ์ฃผ์ž… + ์Šคํ‚ฌ ์žฅ์ฐฉ + ์ˆ˜๋ช… ์„ธํŒ… ํ›„ ๋ฐฐ์น˜ - Fixture.Gimmick = NewObject(World); + Fixture.Gimmick = Scope.New(World); Fixture.Gimmick->Initialize(); Fixture.Gimmick->BeginPlay(); Fixture.Gimmick->SetTileMap(Fixture.TileMap); @@ -120,10 +122,10 @@ namespace Fixture.TileMap->PlaceActor(GimmickTransform, Fixture.Gimmick); // ํ”ผํ•ด์ž ์œ ๋‹›: ํƒ€์ผ๋งต ์ฃผ์ž… ์ด๋™ ์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ ํ›„ ๋ฐฐ์น˜ - Fixture.Unit = NewObject(World); + Fixture.Unit = Scope.New(World); Fixture.Unit->Initialize(); Fixture.Unit->BeginPlay(); - Fixture.Movement = NewObject(Fixture.Unit); + Fixture.Movement = Scope.New(Fixture.Unit); Fixture.Movement->SetTileMap(Fixture.TileMap); Fixture.Unit->SetBoardMovementComponentModel(Fixture.Movement); Fixture.TileMap->PlaceActor(UnitTransform, Fixture.Unit); @@ -155,10 +157,10 @@ namespace UMockUnitMovementComponentModel* Movement = nullptr; }; - // @brief ์žฅํŒ ์ƒ์„ฑ/๋ฐฐ์น˜ (ํƒ€์ผ๋งต ์ฃผ์ž… + ์Šคํ‚ฌ ์žฅ์ฐฉ + ๋ผ์šด๋“œ ์ˆ˜๋ช… ์„ธํŒ…) - UMockPuddleGimmickModel* MakePuddle(UWorld* World, UTileMapModel* TileMap, const FTileTransform& Transform, UStaticSkillData* SkillData, int32 RoundCount) + // @brief ์žฅํŒ ์ƒ์„ฑ/๋ฐฐ์น˜ (ํƒ€์ผ๋งต ์ฃผ์ž… + ์Šคํ‚ฌ ์žฅ์ฐฉ + ๋ผ์šด๋“œ ์ˆ˜๋ช… ์„ธํŒ…). ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UMockPuddleGimmickModel* MakePuddle(UWorld* World, FTestObjectScope& Scope, UTileMapModel* TileMap, const FTileTransform& Transform, UStaticSkillData* SkillData, int32 RoundCount) { - UMockPuddleGimmickModel* Puddle = NewObject(World); + UMockPuddleGimmickModel* Puddle = Scope.New(World); Puddle->Initialize(); Puddle->BeginPlay(); Puddle->SetTileMap(TileMap); @@ -168,9 +170,10 @@ namespace return Puddle; } - // @brief 8x8 ํƒ€์ผ๋งต์— ์žฅํŒ๊ณผ ์œ ๋‹›์„ ๋ฐฐ์น˜ + // @brief 8x8 ํƒ€์ผ๋งต์— ์žฅํŒ๊ณผ ์œ ๋‹›์„ ๋ฐฐ์น˜ (์ƒ์„ฑ ๊ฐ์ฒด๋Š” ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) FPuddleFixture MakePuddleFixture( UWorld* World, + FTestObjectScope& Scope, const FTileTransform& PuddleTransform, const FTileTransform& UnitTransform, UStaticSkillData* SkillData, @@ -178,16 +181,16 @@ namespace { FPuddleFixture Fixture; - Fixture.TileMap = NewObject(World); + Fixture.TileMap = Scope.New(World); Fixture.TileMap->SetDimensions(8, 8); - Fixture.Puddle = MakePuddle(World, Fixture.TileMap, PuddleTransform, SkillData, RoundCount); + Fixture.Puddle = MakePuddle(World, Scope,Fixture.TileMap, PuddleTransform, SkillData, RoundCount); // ํ”ผํ•ด์ž ์œ ๋‹›: ํƒ€์ผ๋งต ์ฃผ์ž… ์ด๋™ ์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ ํ›„ ๋ฐฐ์น˜ - Fixture.Unit = NewObject(World); + Fixture.Unit = Scope.New(World); Fixture.Unit->Initialize(); Fixture.Unit->BeginPlay(); - Fixture.Movement = NewObject(Fixture.Unit); + Fixture.Movement = Scope.New(Fixture.Unit); Fixture.Movement->SetTileMap(Fixture.TileMap); Fixture.Unit->SetBoardMovementComponentModel(Fixture.Movement); Fixture.TileMap->PlaceActor(UnitTransform, Fixture.Unit); @@ -195,13 +198,13 @@ namespace return Fixture; } - // @brief ์ถ”๊ฐ€ ํ”ผํ•ด์ž ์œ ๋‹› ์ƒ์„ฑ/๋ฐฐ์น˜ (2๋ฒˆ์งธ ์œ ๋‹›์ด ํ•„์š”ํ•œ ์ผ€์ด์Šค์šฉ) - UMockGimmickVictimUnitModel* MakeVictimUnit(UWorld* World, UTileMapModel* TileMap, const FTileTransform& UnitTransform, UMockUnitMovementComponentModel*& OutMovement) + // @brief ์ถ”๊ฐ€ ํ”ผํ•ด์ž ์œ ๋‹› ์ƒ์„ฑ/๋ฐฐ์น˜ (2๋ฒˆ์งธ ์œ ๋‹›์ด ํ•„์š”ํ•œ ์ผ€์ด์Šค์šฉ). ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UMockGimmickVictimUnitModel* MakeVictimUnit(UWorld* World, FTestObjectScope& Scope, UTileMapModel* TileMap, const FTileTransform& UnitTransform, UMockUnitMovementComponentModel*& OutMovement) { - UMockGimmickVictimUnitModel* Unit = NewObject(World); + UMockGimmickVictimUnitModel* Unit = Scope.New(World); Unit->Initialize(); Unit->BeginPlay(); - OutMovement = NewObject(Unit); + OutMovement = Scope.New(Unit); OutMovement->SetTileMap(TileMap); Unit->SetBoardMovementComponentModel(OutMovement); TileMap->PlaceActor(UnitTransform, Unit); @@ -222,6 +225,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FGimmickTriggerTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -237,10 +242,10 @@ bool FGimmickTriggerTests::RunTest(const FString& Parameters) // (2,2)์˜ ๊ธฐ์ ˆ ํŠธ๋žฉ(์ˆ˜๋ช… 1)์„ (1,2)->(3,2) ๊ฒฝ๋กœ ๋„์ค‘์— ๋ฐŸ์Œ FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), 1); Fixture.Movement->MoveAlongPath({ FTileIndex(1, 2), FTileIndex(2, 2), FTileIndex(3, 2) }); @@ -259,7 +264,7 @@ bool FGimmickTriggerTests::RunTest(const FString& Parameters) Fixture.TileMap->RemoveActor(Fixture.Unit); UMockUnitMovementComponentModel* SecondMovement = nullptr; - UMockGimmickVictimUnitModel* SecondUnit = MakeVictimUnit(World, Fixture.TileMap, FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), SecondMovement); + UMockGimmickVictimUnitModel* SecondUnit = MakeVictimUnit(World, Scope,Fixture.TileMap, FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), SecondMovement); SecondMovement->MoveAlongPath({ FTileIndex(1, 2), FTileIndex(2, 2) }); @@ -283,6 +288,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FGimmickLifetimeFilterTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -297,10 +304,10 @@ bool FGimmickLifetimeFilterTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1: ์ˆ˜๋ช… -1 ํŠธ๋žฉ์€ ๋ฐ˜๋ณต ๋ฐœ๋™, ์‚ฌ๋ง ์—†์Œ ===")); FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), -1); // ์ฒซ ๋ฒˆ์งธ ์œ ๋‹› ์ง„์ž… @@ -312,7 +319,7 @@ bool FGimmickLifetimeFilterTests::RunTest(const FString& Parameters) // ๋‘ ๋ฒˆ์งธ ์œ ๋‹› ์ง„์ž… UMockUnitMovementComponentModel* SecondMovement = nullptr; - UMockGimmickVictimUnitModel* SecondUnit = MakeVictimUnit(World, Fixture.TileMap, FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), SecondMovement); + UMockGimmickVictimUnitModel* SecondUnit = MakeVictimUnit(World, Scope,Fixture.TileMap, FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), SecondMovement); SecondMovement->MoveAlongPath({ FTileIndex(1, 2), FTileIndex(2, 2) }); TestTrue(TEXT("[Case1] ๋‘ ๋ฒˆ์งธ ์œ ๋‹›๋„ ๊ธฐ์ ˆ"), HasStunTag(SecondUnit)); @@ -323,18 +330,18 @@ bool FGimmickLifetimeFilterTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case2: ๋‹ค๋ฅธ Overlay ์•กํ„ฐ ์ง„์ž… -> ๋ฏธ๋ฐœ๋™ ===")); { FGimmickFixture FilterFixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), FTileTransform(FTileIndex(1, 1), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), 1); // ํŠธ๋žฉ ํƒ€์ผ ์œ„์— ๋‹ค๋ฅธ Overlay ๊ธฐ๋ฏน์„ ๋ฐฐ์น˜ (์œ ๋‹› ๋ ˆ์ด์–ด๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ๋ฐœ๋™ํ•˜๋ฉด ์•ˆ ๋จ) - UMockOverlapGimmickModel* OtherOverlay = NewObject(World); + UMockOverlapGimmickModel* OtherOverlay = Scope.New(World); OtherOverlay->Initialize(); OtherOverlay->BeginPlay(); OtherOverlay->SetTileMap(FilterFixture.TileMap); - OtherOverlay->GetSkillComponentModel()->SetSkillFrom(TArray>{ MakeStunSkillData(World) }); + OtherOverlay->GetSkillComponentModel()->SetSkillFrom(TArray>{ MakeStunSkillData(World, Scope) }); OtherOverlay->SetRemainingTriggerCount(1); FilterFixture.TileMap->PlaceActor(FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), OtherOverlay); @@ -363,6 +370,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FGimmickPlaceAndPushTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -378,10 +387,10 @@ bool FGimmickPlaceAndPushTests::RunTest(const FString& Parameters) { // ํ”ฝ์Šค์ฒ˜๊ฐ€ ์œ ๋‹›์„ ํŠธ๋žฉ ํƒ€์ผ (2,2)์— ๋ฐ”๋กœ ๋ฐฐ์น˜ FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), 1); TestTrue(TEXT("[Case1] ๋ฐฐ์น˜ ์ฆ‰์‹œ ๊ธฐ์ ˆ ๋ถ€์—ฌ"), HasStunTag(Fixture.Unit)); @@ -393,10 +402,10 @@ bool FGimmickPlaceAndPushTests::RunTest(const FString& Parameters) { // (3,2)์˜ ๋ฐœํŒ์ด Right(+Y)๋ฅผ ๋ฐ”๋ผ๋ด„. ์œ ๋‹›์€ (2,2)->(4,2)๋กœ ๊ฑท๋Š” ์ค‘ FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(3, 2), ETileActorDirection::Right), FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), - MakePushSkillData(World, 2), + MakePushSkillData(World, Scope, 2), 1); Fixture.Movement->MoveAlongPath({ FTileIndex(2, 2), FTileIndex(3, 2), FTileIndex(4, 2) }); @@ -410,10 +419,10 @@ bool FGimmickPlaceAndPushTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3: ๋ฐœํŒ ์œ„ ๋ฐฐ์น˜ -> ์ฆ‰์‹œ +Y๋กœ 2์นธ ๋ฐ€๋ฆผ ===")); { FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Right), FTileTransform(FTileIndex(5, 2), ETileActorDirection::Forward), - MakePushSkillData(World, 2), + MakePushSkillData(World, Scope, 2), 1); TestTrue(TEXT("[Case3] ๋ฐฐ์น˜ ์ฆ‰์‹œ ๋ฐ€๋ฆฐ ์œ„์น˜ ๋„์ฐฉ"), Fixture.Unit->GetTileTransform().mIndex == FTileIndex(5, 4)); @@ -437,6 +446,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FGimmickPullThroughTrapTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -448,9 +459,9 @@ bool FGimmickPullThroughTrapTests::RunTest(const FString& Parameters) } // @brief ์‹œ์ „์ž ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ๋Œ€์ƒ์—๊ฒŒ ๋‹น๊ธฐ๊ธฐ ์ดํŽ™ํŠธ ์ ์šฉ - auto ApplyPull = [World](UTileMapModel* TileMap, const FTileIndex& CasterTile, UMockGimmickVictimUnitModel* Victim, int32 PullDistance) + auto ApplyPull = [World, &Scope](UTileMapModel* TileMap, const FTileIndex& CasterTile, UMockGimmickVictimUnitModel* Victim, int32 PullDistance) { - UMockEnemyUnitModel* Caster = NewObject(World); + UMockEnemyUnitModel* Caster = Scope.New(World); Caster->Initialize(); Caster->BeginPlay(); TileMap->PlaceActor(FTileTransform(CasterTile, ETileActorDirection::Forward), Caster); @@ -467,10 +478,10 @@ bool FGimmickPullThroughTrapTests::RunTest(const FString& Parameters) { // ๋ฐœํŒ์€ ๊ฒฝ๋กœ ๋ฐ– (7,7)์— ๋‘์–ด ๊ด€์—ฌํ•˜์ง€ ์•Š๊ฒŒ ํ•จ FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(7, 7), ETileActorDirection::Forward), FTileTransform(FTileIndex(2, 1), ETileActorDirection::Backward), - MakePushSkillData(World, 2), + MakePushSkillData(World, Scope, 2), 1); ApplyPull(Fixture.TileMap, FTileIndex(2, 5), Fixture.Unit, 3); @@ -484,10 +495,10 @@ bool FGimmickPullThroughTrapTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case2: ๋‹น๊ธฐ๊ธฐ ๊ฒฝ๋กœ ์œ„ (2,3) ๋ฐœํŒ(Left, -Y) -> ๋ฐœํŒ์—์„œ -Y๋กœ 2์นธ ๋ฐ€๋ ค (2,1) ๋„์ฐฉ ===")); { FGimmickFixture Fixture = MakeGimmickFixture( - World, + World, Scope, FTileTransform(FTileIndex(2, 3), ETileActorDirection::Left), FTileTransform(FTileIndex(2, 1), ETileActorDirection::Backward), - MakePushSkillData(World, 2), + MakePushSkillData(World, Scope, 2), 1); ApplyPull(Fixture.TileMap, FTileIndex(2, 5), Fixture.Unit, 3); @@ -515,6 +526,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPuddleRoundEndTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -529,10 +542,10 @@ bool FPuddleRoundEndTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1: ์žฅํŒ ์ง„์ž… -> ๊ธฐ์ ˆ 1, ๋ผ์šด๋“œ ๋ -> ๊ธฐ์ ˆ 2, ์ˆ˜๋ช… 2 -> 1 ===")); FPuddleFixture Fixture = MakePuddleFixture( - World, + World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), FTileTransform(FTileIndex(1, 2), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), 2); Fixture.Movement->MoveAlongPath({ FTileIndex(1, 2), FTileIndex(2, 2) }); @@ -557,10 +570,10 @@ bool FPuddleRoundEndTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3: ์ˆ˜๋ช… 1 ์žฅํŒ ์œ„ ์œ ๋‹›, ๋ผ์šด๋“œ ๋ -> ๋ฐœ๋™ ํ›„ ์‚ฌ๋ง ===")); { FPuddleFixture LastFixture = MakePuddleFixture( - World, + World, Scope, FTileTransform(FTileIndex(4, 4), ETileActorDirection::Forward), FTileTransform(FTileIndex(4, 4), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), 1); LastFixture.Puddle->TriggerRoundEnd(nullptr); @@ -573,10 +586,10 @@ bool FPuddleRoundEndTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4: ์ˆ˜๋ช… -1 ์žฅํŒ์€ ๋ผ์šด๋“œ๊ฐ€ ์ง€๋‚˜๋„ ์œ ์ง€ ===")); { FPuddleFixture InfFixture = MakePuddleFixture( - World, + World, Scope, FTileTransform(FTileIndex(6, 6), ETileActorDirection::Forward), FTileTransform(FTileIndex(6, 6), ETileActorDirection::Forward), - MakeStunSkillData(World), + MakeStunSkillData(World, Scope), -1); InfFixture.Puddle->TriggerRoundEnd(nullptr); @@ -604,6 +617,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPuddleReplaceTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -618,19 +633,19 @@ bool FPuddleReplaceTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1: (2,2) ์œ ๋‹› ์œ„์— ์žฅํŒ ๋ฐฐ์น˜ -> ์ฆ‰์‹œ ๊ธฐ์ ˆ ===")); // ์œ ๋‹›์„ ๋จผ์ € ์„ธ์šฐ๊ณ , ๊ทธ ํƒ€์ผ์— ์žฅํŒ์„ ๋‚˜์ค‘์— ๊น– - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 8); UMockUnitMovementComponentModel* Movement = nullptr; - UMockGimmickVictimUnitModel* Unit = MakeVictimUnit(World, TileMap, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), Movement); + UMockGimmickVictimUnitModel* Unit = MakeVictimUnit(World, Scope,TileMap, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), Movement); const FTileTransform PuddleTransform(FTileIndex(2, 2), ETileActorDirection::Forward); - UMockPuddleGimmickModel* First = MakePuddle(World, TileMap, PuddleTransform, MakeStunSkillData(World), 3); + UMockPuddleGimmickModel* First = MakePuddle(World, Scope,TileMap, PuddleTransform, MakeStunSkillData(World, Scope), 3); TestEqual(TEXT("[Case1] ์žฅํŒ์ด ๊น”๋ฆฌ์ž๋งˆ์ž ๊ธฐ์ ˆ 1"), GetStunCount(Unit), 1); /* Case2: ์ƒˆ ์žฅํŒ์ด ๊ธฐ์กด ์žฅํŒ์„ ๋ฎ์–ด์”€ */ AddInfo(TEXT("=== Case2: ๊ฐ™์€ ํƒ€์ผ์— ๋‘ ๋ฒˆ์งธ ์žฅํŒ -> ์ฒซ ์žฅํŒ ์ดํƒˆ+์‚ฌ๋ง, ์ƒˆ ์žฅํŒ๋งŒ ์ž”๋ฅ˜ ===")); - UMockPuddleGimmickModel* Second = MakePuddle(World, TileMap, PuddleTransform, MakeStunSkillData(World), 3); + UMockPuddleGimmickModel* Second = MakePuddle(World, Scope,TileMap, PuddleTransform, MakeStunSkillData(World, Scope), 3); const TArray Puddles = TileMap->GetActorsOnTile(PuddleTransform.mIndex, ETileLayerFlag::Overlay); TestEqual(TEXT("[Case2] ํƒ€์ผ ์œ„ ์žฅํŒ์€ 1๊ฐœ"), Puddles.Num(), 1); @@ -668,6 +683,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPuddleRoundEndEventTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForGimmickTests(); if (World == nullptr) { @@ -678,10 +695,10 @@ bool FPuddleRoundEndEventTests::RunTest(const FString& Parameters) return false; } - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 8); - UMockGimmickCombatModel* CombatModel = NewObject(World); + UMockGimmickCombatModel* CombatModel = Scope.New(World); CombatModel->SetTileMap(TileMap); /* Case1: ์ค‘๋ณต ๋“ฑ๋ก ๋ฐฉ์ง€ */ @@ -696,14 +713,14 @@ bool FPuddleRoundEndEventTests::RunTest(const FString& Parameters) /* Case2: ๋ณด๋“œ ์œ„ ๋ชจ๋“  ์žฅํŒ ์ผ๊ด„ ๋ฐœ๋™ */ AddInfo(TEXT("=== Case2: ์žฅํŒ 3๊ฐœ(์œ ๋‹› 2 + ๋นˆ 1), ์ด๋ฒคํŠธ 1ํšŒ -> ์œ ๋‹› ๊ธฐ์ ˆ +1, ์ˆ˜๋ช… ์ „๋ถ€ -1 ===")); - UMockPuddleGimmickModel* PuddleA = MakePuddle(World, TileMap, FTileTransform(FTileIndex(1, 1), ETileActorDirection::Forward), MakeStunSkillData(World), 3); - UMockPuddleGimmickModel* PuddleB = MakePuddle(World, TileMap, FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), MakeStunSkillData(World), 3); - UMockPuddleGimmickModel* PuddleC = MakePuddle(World, TileMap, FTileTransform(FTileIndex(3, 3), ETileActorDirection::Forward), MakeStunSkillData(World), 3); + UMockPuddleGimmickModel* PuddleA = MakePuddle(World, Scope,TileMap, FTileTransform(FTileIndex(1, 1), ETileActorDirection::Forward), MakeStunSkillData(World, Scope), 3); + UMockPuddleGimmickModel* PuddleB = MakePuddle(World, Scope,TileMap, FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), MakeStunSkillData(World, Scope), 3); + UMockPuddleGimmickModel* PuddleC = MakePuddle(World, Scope,TileMap, FTileTransform(FTileIndex(3, 3), ETileActorDirection::Forward), MakeStunSkillData(World, Scope), 3); UMockUnitMovementComponentModel* MovementA = nullptr; UMockUnitMovementComponentModel* MovementB = nullptr; - UMockGimmickVictimUnitModel* UnitA = MakeVictimUnit(World, TileMap, FTileTransform(FTileIndex(1, 1), ETileActorDirection::Forward), MovementA); - UMockGimmickVictimUnitModel* UnitB = MakeVictimUnit(World, TileMap, FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), MovementB); + UMockGimmickVictimUnitModel* UnitA = MakeVictimUnit(World, Scope,TileMap, FTileTransform(FTileIndex(1, 1), ETileActorDirection::Forward), MovementA); + UMockGimmickVictimUnitModel* UnitB = MakeVictimUnit(World, Scope,TileMap, FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), MovementB); CombatModel->TriggerAllRoundEndEvents(); diff --git a/Source/P_RDTests/Actor/TileMap/TileMapModelTests.cpp b/Source/P_RDTests/Actor/TileMap/TileMapModelTests.cpp index 58f1ece03..2876a1305 100644 --- a/Source/P_RDTests/Actor/TileMap/TileMapModelTests.cpp +++ b/Source/P_RDTests/Actor/TileMap/TileMapModelTests.cpp @@ -1,4 +1,4 @@ -/*****************************************************************//** +๏ปฟ/*****************************************************************//** * @file TileMapModelTests.cpp * @brief UTileMapModel ํƒ€๊ฒŸ๋ฒ”์œ„/์˜ํ–ฅ๋ฒ”์œ„/์กฐ์ค€๊ฐ€๋Šฅ(CanAim)/์œ„ํ˜‘๋ฒ”์œ„(GetThreatRanges) ์œ ๋‹›ํ…Œ์ŠคํŠธ * @details @@ -11,6 +11,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" // UMockPlayerUnitModel (์ ์œ  ํŒ์ •์šฉ ์œ ๋‹› Mock) @@ -41,17 +42,15 @@ namespace return nullptr; } - // @brief ์œ„ํ˜‘ ๋ฒ”์œ„ ํ…Œ์ŠคํŠธ์šฉ ์Šคํ‚ฌ ์ƒ์„ฑ (KeepAlive์— ๋“ฑ๋กํ•ด GC ๋ฐฉ์ง€) - UStaticUnitSkillData* MakeThreatSkill(UWorld* World, TArray& KeepAlive, EAimPattern AimPattern, int32 AimRange, int32 RequiredActionPoint) + // @brief ์œ„ํ˜‘ ๋ฒ”์œ„ ํ…Œ์ŠคํŠธ์šฉ ์Šคํ‚ฌ ์ƒ์„ฑ (์Šค์ฝ”ํ”„์— ๋“ฑ๋กํ•ด GC ๋ฐฉ์ง€ + ์ข…๋ฃŒ ์‹œ ํŒŒ๊ดด) + UStaticUnitSkillData* MakeThreatSkill(UWorld* World, FTestObjectScope& Scope, EAimPattern AimPattern, int32 AimRange, int32 RequiredActionPoint) { - UStaticUnitSkillData* Skill = NewObject(World); + UStaticUnitSkillData* Skill = Scope.New(World); Skill->mAimPattern = AimPattern; Skill->mAimRange = AimRange; Skill->mCanAimBoardActor = true; Skill->mAimBlockerMask = static_cast(ETileLayerFlag::Obstacle | ETileLayerFlag::Unit); Skill->mRequiredActionPoint = RequiredActionPoint; - Skill->AddToRoot(); - KeepAlive.Add(Skill); return Skill; } } @@ -64,6 +63,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FTileMapModelTargetTilesTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -75,7 +76,7 @@ bool FTileMapModelTargetTilesTests::RunTest(const FString& Parameters) } // ๋งต (8x8): ์‹œ์ „์ž C=(0,0) - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 8); const FTileIndex Caster(0, 0); @@ -116,7 +117,7 @@ bool FTileMapModelTargetTilesTests::RunTest(const FString& Parameters) */ AddInfo(TEXT("=== Case3: LineToTarget / ๊ฒฝ๋กœ ์œ„ ์ ์œ  -> ๊ฒฝ๋กœ ๋ถˆ๋ณ€ ===")); { - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 0)), Blocker); const TArray Tiles = TileMap->GetTargetTiles(Caster, FTileIndex(3, 0), ETargetPattern::LineToTarget); @@ -164,6 +165,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FTileMapModelEffectTilesTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -175,11 +178,11 @@ bool FTileMapModelEffectTilesTests::RunTest(const FString& Parameters) } // ๋งต (8x1): ์ ์œ  ์œ ๋‹› U=(3,0) - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 1); // ์ ์œ  ์œ ๋‹› ๋ฐฐ์น˜ (Unit ๋ ˆ์ด์–ด ํŒ์ •๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(3, 0)), Blocker); /** @@ -232,6 +235,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FTileMapModelCanAimTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -249,12 +254,12 @@ bool FTileMapModelCanAimTests::RunTest(const FString& Parameters) * CanAim(์›์ , ํƒ€์ผ) == GetAimableTiles(์›์ ).Contains(ํƒ€์ผ)์„ ์ „์ˆ˜ ํ™•์ธํ•œ๋‹ค. */ // ๋งต (7x5): ์›์  O=(1,2), ์‹œ์•ผ/์ ์œ  ๋ณ€ํ™”๋ฅผ ๋งŒ๋“ค ์œ ๋‹› U1=(3,2), U2=(2,1) - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(7, 5); - UMockPlayerUnitModel* Unit1 = NewObject(World); + UMockPlayerUnitModel* Unit1 = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(3, 2)), Unit1); - UMockPlayerUnitModel* Unit2 = NewObject(World); + UMockPlayerUnitModel* Unit2 = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 1)), Unit2); const FTileIndex Origin(1, 2); @@ -312,6 +317,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -322,9 +329,6 @@ bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) return false; } - // ์œ ๋‹›ํ…Œ์ŠคํŠธ ๋™์•ˆ ์Šคํ‚ฌ ๋ฐ์ดํ„ฐ๊ฐ€ GC ๋‹นํ•˜์ง€ ์•Š๋„๋ก ๊ฑธ์–ด๋‘๋Š” ์žฅ์น˜ - TArray KeepAlive; - /** * Case1: ์‹œ์ „๋น„์šฉ = ํ–‰๋™๋ ฅ (๊ธฐํš์•ˆ ์˜ˆ์‹œ A) * -> ์ด๋™์€ 3์นธ๊นŒ์ง€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ด๋™ํ•˜๋ฉด ์‹œ์ „ ์˜ˆ์‚ฐ์ด ๋‚จ์ง€ ์•Š์•„ ๊ณต๊ฒฉ์€ ์ œ์ž๋ฆฌ์—์„œ๋งŒ @@ -334,15 +338,15 @@ bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) */ AddInfo(TEXT("=== Case1: ์‹œ์ „๋น„์šฉ = ํ–‰๋™๋ ฅ -> ์ œ์ž๋ฆฌ ์‹œ์ „๋งŒ ===")); { - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(5, 5); // ์  ์œ ๋‹› ๋ฐฐ์น˜ (์ ์œ /์ฐจํ ์ œ์™ธ ํŒ์ •์šฉ โ€” ๋ ˆ์ด์–ด๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Enemy = NewObject(World); + UMockPlayerUnitModel* Enemy = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 2)), Enemy); // ๋นˆ ์Šฌ๋กฏ(nullptr)์ด ๋ฌด์‹œ๋˜๋Š”์ง€ ํ•จ๊ป˜ ๊ฒ€์ฆ - const TArray Skills = { nullptr, MakeThreatSkill(World, KeepAlive, EAimPattern::Cross, 1, 3) }; + const TArray Skills = { nullptr, MakeThreatSkill(World, Scope, EAimPattern::Cross, 1, 3) }; TArray MoveTiles; TArray AttackTiles; @@ -366,14 +370,14 @@ bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) */ AddInfo(TEXT("=== Case2: ์‹œ์ „๋น„์šฉ 1 -> ์ด๋™ ํ›„ ์‹œ์ „์œผ๋กœ ๊ณต๊ฒฉ๋ฒ”์œ„ ํ™•์žฅ ===")); { - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(5, 5); // ์  ์œ ๋‹› ๋ฐฐ์น˜ (์ ์œ /์ฐจํ ์ œ์™ธ ํŒ์ •์šฉ โ€” ๋ ˆ์ด์–ด๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Enemy = NewObject(World); + UMockPlayerUnitModel* Enemy = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 2)), Enemy); - const TArray Skills = { MakeThreatSkill(World, KeepAlive, EAimPattern::Cross, 2, 1) }; + const TArray Skills = { MakeThreatSkill(World, Scope, EAimPattern::Cross, 2, 1) }; TArray MoveTiles; TArray AttackTiles; @@ -393,16 +397,16 @@ bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) */ AddInfo(TEXT("=== Case3: ์ฐจ๋‹จ ์œ ๋‹› -> ํ†ต๊ณผ ๋ถˆ๊ฐ€ + ์ฐจํ ===")); { - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(6, 1); // ์  ์œ ๋‹›๊ณผ ์ฐจ๋‹จ ์œ ๋‹› ๋ฐฐ์น˜ (๋ ˆ์ด์–ด๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Enemy = NewObject(World); + UMockPlayerUnitModel* Enemy = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(0, 0)), Enemy); - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 0)), Blocker); - const TArray Skills = { MakeThreatSkill(World, KeepAlive, EAimPattern::Cross, 2, 1) }; + const TArray Skills = { MakeThreatSkill(World, Scope, EAimPattern::Cross, 2, 1) }; TArray MoveTiles; TArray AttackTiles; @@ -416,11 +420,6 @@ bool FTileMapModelThreatRangesTests::RunTest(const FString& Parameters) TestFalse(TEXT("[Case3] (3,0) ๋ฏธํฌํ•จ (์ฐจ๋‹จ ์œ ๋‹› ๋„ˆ๋จธ ์ฐจํ)"), AttackTiles.Contains(FTileIndex(3, 0))); } - // GC ์•ˆ๋‹นํ•˜๋ ค๊ณ  KeepAlive์— ๋งค๋‹ฌ์•„๋†จ๋˜ ์Šคํ‚ฌ ๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐ ํ•ด์ œ -> GC ๋Œ€์ƒ - for (UObject* Object : KeepAlive) - if (IsValid(Object)) - Object->RemoveFromRoot(); - return true; } @@ -464,6 +463,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FTileMapModelPushPathByDirectionTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -474,7 +475,7 @@ bool FTileMapModelPushPathByDirectionTests::RunTest(const FString& Parameters) return false; } - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 8); /* Case1: ๋นˆ ๋งต์—์„œ ๋ฐฉํ–ฅ๋Œ€๋กœ ๋๊นŒ์ง€ ๋ฐ€๋ฆผ */ @@ -489,7 +490,7 @@ bool FTileMapModelPushPathByDirectionTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case2: ์ ์œ  ์นธ์— ๋ง‰ํž˜ ===")); { // (2,4)์— ์ฐจ๋‹จ ์œ ๋‹› ๋ฐฐ์น˜ (๋ ˆ์ด์–ด๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 4)), Blocker); const TArray Path = TileMap->GetPushPath(FTileIndex(2, 2), ETileActorDirection::Right, 3); @@ -532,6 +533,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FTileMapModelPullPathTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTileMapTests(); if (World == nullptr) { @@ -542,11 +545,11 @@ bool FTileMapModelPullPathTests::RunTest(const FString& Parameters) return false; } - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(8, 8); // ์‹œ์ „์ž ์ž๋ฆฌ๋Š” ์‹ค์ œ์ฒ˜๋Ÿผ ์œ ๋‹›์ด ์ ์œ  (๋ ˆ์ด์–ด๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) - UMockPlayerUnitModel* Puller = NewObject(World); + UMockPlayerUnitModel* Puller = Scope.New(World); /* Case1: ์ผ์ง์„  -> ์‹œ์ „์ž ๋ฐ”๋กœ ์•ž(๋ฉด ์ ‘์ด‰)๊นŒ์ง€ */ AddInfo(TEXT("=== Case1: ์ผ์ง์„  (2,1)->(2,5) ์‹œ์ „์ž -> (2,4)๊นŒ์ง€ ===")); @@ -588,7 +591,7 @@ bool FTileMapModelPullPathTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4: (2,3) ์ ์œ  -> (2,2)๊นŒ์ง€ ===")); { TileMap->PlaceActor(FTileTransform(FTileIndex(2, 5)), Puller); - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 3)), Blocker); const TArray Path = TileMap->GetPullPath(FTileIndex(2, 5), FTileIndex(2, 1), 8); diff --git a/Source/P_RDTests/Component/ArtifactComponent/ArtifactComponentModelTests.cpp b/Source/P_RDTests/Component/ArtifactComponent/ArtifactComponentModelTests.cpp index 4061b236c..9c2bae4cd 100644 --- a/Source/P_RDTests/Component/ArtifactComponent/ArtifactComponentModelTests.cpp +++ b/Source/P_RDTests/Component/ArtifactComponent/ArtifactComponentModelTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "GameplayTagContainer.h" @@ -38,18 +39,20 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FArtifactComponentModelTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag StartTiming = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); // ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋งŒ ์œ ๋‹› ์—†์ด ์ƒ์„ฑ - UArtifactComponentModel* ArtifactComp = NewObject(); - UPassiveComponentModel* PassiveComp = NewObject(); + UArtifactComponentModel* ArtifactComp = Scope.New(); + UPassiveComponentModel* PassiveComp = Scope.New(); if (!TestNotNull(TEXT("์•„ํ‹ฐํŒฉํŠธ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ"), ArtifactComp) || !TestNotNull(TEXT("ํŒจ์‹œ๋ธŒ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ"), PassiveComp)) { return false; } // ํŒจ์‹œ๋ธŒ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ์ œ๋„ค๋ฆญ ํŒจ์‹œ๋ธŒ + AttackFactor ์ดํŽ™ํŠธ + ์ˆ˜์น˜ 5 + OnStartTurn ์‹œ์  - UStaticPassiveData* PassiveData = NewObject(); + UStaticPassiveData* PassiveData = Scope.New(); PassiveData->mPassiveClass = UTacticalPassive_Generic::StaticClass(); FPassiveEffectEntry& Effect = PassiveData->mEffects.AddDefaulted_GetRef(); Effect.mEffectClass = UTacticalEffect_AttackFactor_AddBase::StaticClass(); @@ -57,7 +60,7 @@ bool FArtifactComponentModelTests::RunTest(const FString& Parameters) PassiveData->mActivateTimingTag = StartTiming; // ์•„ํ‹ฐํŽ™ํŠธ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ์œ„ ํŒจ์‹œ๋ธŒ๋ฅผ ์—ฐ๊ด€ - UStaticArtifactData* Artifact = NewObject(); + UStaticArtifactData* Artifact = Scope.New(); Artifact->mStaticPassiveData.Add(TSoftObjectPtr(PassiveData)); // ์žฅ์ฐฉ: ํŒจ์‹œ๋ธŒ๊ฐ€ ์„ค์น˜๋ผ์•ผ ํ•จ diff --git a/Source/P_RDTests/Component/ArtifactComponent/ArtifactStatModifierTests.cpp b/Source/P_RDTests/Component/ArtifactComponent/ArtifactStatModifierTests.cpp index d093f0472..3ad7d7d63 100644 --- a/Source/P_RDTests/Component/ArtifactComponent/ArtifactStatModifierTests.cpp +++ b/Source/P_RDTests/Component/ArtifactComponent/ArtifactStatModifierTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "TAS/TASAttributeTestsHelper.h" @@ -52,6 +53,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FArtifactStatModifierTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + // ๋ผ์ด๋ธŒ ์›”๋“œ ํ™•๋ณด (TAS ์†์„ฑ ํ…Œ์ŠคํŠธ์™€ ๋™์ผ ํ™˜๊ฒฝ) UWorld* World = FindAnyGameWorld(); if (World == nullptr) @@ -79,12 +82,14 @@ bool FArtifactStatModifierTests::RunTest(const FString& Parameters) UTacticalFrameworkModel* FrameworkModel = Cast(RoomInstance->mAliveSubsystemModels.FindRef(UTacticalFrameworkModel::StaticClass())); if (FrameworkModel == nullptr) { - FrameworkModel = NewObject(RoomInstance); + FrameworkModel = Scope.New(RoomInstance); RoomInstance->mAliveSubsystemModels.Add(UTacticalFrameworkModel::StaticClass(), FrameworkModel); + // ํ…Œ์ŠคํŠธ๊ฐ€ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ํŒŒ๊ดด ์ „์— ๋“ฑ๋ก ํ•ด์ œ + Scope.Defer([RoomInstance]() { RoomInstance->mAliveSubsystemModels.Remove(UTacticalFrameworkModel::StaticClass()); }); } // ์†์„ฑ ์ปดํฌ๋„ŒํŠธ Mock - UTASActorModelMock* MockActorModel = NewObject(World); + UTASActorModelMock* MockActorModel = Scope.New(World); MockActorModel->Initialize(); MockActorModel->BeginPlay(); UAttributeSetComponentModel* AttrComp = MockActorModel->GetAttributeComponent(); @@ -99,7 +104,7 @@ bool FArtifactStatModifierTests::RunTest(const FString& Parameters) TestEqual(TEXT("๊ธฐ๋ณธ ๊ณต๊ฒฉ๋ ฅ 10"), AttrComp->GetAttributeCurrentValue(AttackFactor), 10.f); // ์•„ํ‹ฐํŽ™ํŠธ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ๊ณต๊ฒฉ๋ ฅ +5 ๊ณ ์œ  ์Šคํƒฏ - UStaticArtifactData* Artifact = NewObject(); + UStaticArtifactData* Artifact = Scope.New(); FTacticalModifierInfo Mod; Mod.mAttribute = AttackFactor; Mod.mModifierOp = ETacticalModOp::AddBase; @@ -107,7 +112,7 @@ bool FArtifactStatModifierTests::RunTest(const FString& Parameters) Artifact->mStatModifiers.Add(Mod); // ์žฅ์ฐฉ: ์Šคํƒฏ ์ดํŽ™ํŠธ๊ฐ€ ์ž์‹ ์—๊ฒŒ ์ ์šฉ (ํŒจ์‹œ๋ธŒ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถˆํ•„์š” โ†’ nullptr) - UArtifactComponentModel* ArtifactComp = NewObject(); + UArtifactComponentModel* ArtifactComp = Scope.New(); const bool bEquipped = ArtifactComp->EquipInternal(Artifact, nullptr, AttrComp); TestTrue(TEXT("์žฅ์ฐฉ ์„ฑ๊ณต"), bEquipped); TestEqual(TEXT("์žฅ์ฐฉ ํ›„ ๊ณต๊ฒฉ๋ ฅ 15 (๊ธฐ๋ณธ 10 + ์Šคํƒฏ 5)"), AttrComp->GetAttributeCurrentValue(AttackFactor), 15.f); diff --git a/Source/P_RDTests/Component/BoardMovementComponent/PushMovementTests.cpp b/Source/P_RDTests/Component/BoardMovementComponent/PushMovementTests.cpp index 373d131b8..d51b3cc3f 100644 --- a/Source/P_RDTests/Component/BoardMovementComponent/PushMovementTests.cpp +++ b/Source/P_RDTests/Component/BoardMovementComponent/PushMovementTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" // UMockEnemyUnitModel @@ -49,20 +50,20 @@ namespace UMockUnitMovementComponentModel* Movement = nullptr; }; - // @brief 8x8 ํƒ€์ผ๋งต์— ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐ - FPushMovementFixture MakePushMovementFixture(UWorld* World, const FTileTransform& StartTransform) + // @brief 8x8 ํƒ€์ผ๋งต์— ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐ (์ƒ์„ฑ ๊ฐ์ฒด๋Š” ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + FPushMovementFixture MakePushMovementFixture(UWorld* World, FTestObjectScope& Scope, const FTileTransform& StartTransform) { FPushMovementFixture Fixture; - Fixture.TileMap = NewObject(World); + Fixture.TileMap = Scope.New(World); Fixture.TileMap->SetDimensions(8, 8); - Fixture.Unit = NewObject(World); + Fixture.Unit = Scope.New(World); Fixture.Unit->Initialize(); Fixture.Unit->BeginPlay(); // ์œ ๋‹›์„ Outer๋กœ ๋งŒ๋“ค์–ด์„œ GetOwnerModel()(Outer ์ฒด์ธ ํƒ์ƒ‰)์ด ์œ ๋‹›์„ ์ฐพ๊ฒŒ ํ•จ - Fixture.Movement = NewObject(Fixture.Unit); + Fixture.Movement = Scope.New(Fixture.Unit); Fixture.Movement->SetTileMap(Fixture.TileMap); Fixture.TileMap->PlaceActor(StartTransform, Fixture.Unit); @@ -83,6 +84,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementBasicTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -97,7 +100,7 @@ bool FPushMovementBasicTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1: PushAlongPath -> ๋„์ฐฉ, ๋ฐฉํ–ฅ ๋ถˆ๋ณ€, OnFinished 1ํšŒ ===")); { // (2,2)์—์„œ Left๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ์œ ๋‹›์„ +X๋กœ 2์นธ ๋ฐ€์นจ - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Left)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Left)); int32 FinishCount = 0; const bool Started = Fixture.Movement->PushAlongPath( @@ -118,7 +121,7 @@ bool FPushMovementBasicTests::RunTest(const FString& Parameters) /* Case2: AP ์ •์‚ฐ (์ผ๋ฐ˜ ์ด๋™ ์ฐจ๊ฐ vs ๋ฐ€์น˜๊ธฐ ๋ถˆ๋ณ€) */ AddInfo(TEXT("=== Case2: ์ผ๋ฐ˜ ์ด๋™ AP ์ฐจ๊ฐ vs ๋ฐ€์น˜๊ธฐ AP ๋ถˆ๋ณ€ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); UAttributeSetComponentModel* AttrComp = Fixture.Unit->GetAttributeComponentModel(); if (TestNotNull(TEXT("[Case2] ์†์„ฑ ์ปดํฌ๋„ŒํŠธ"), AttrComp) == false) @@ -142,7 +145,7 @@ bool FPushMovementBasicTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3: PullAlongPath -> ๋„์ฐฉ, ๋ฐฉํ–ฅ ๋ถˆ๋ณ€, AP ๋ถˆ๋ณ€, ๋งˆ์ง€๋ง‰ ๋ชจ๋“œ Pull ===")); { // (5,2)์—์„œ Left๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ์œ ๋‹›์„ -X๋กœ 2์นธ ๋‹น๊น€ - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); UAttributeSetComponentModel* AttrComp = Fixture.Unit->GetAttributeComponentModel(); const float BeforePull = AttrComp->GetAttributeCurrentValue(UUnitAttributeSet::GetActionPointAttribute()); @@ -175,6 +178,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementChainTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -188,7 +193,7 @@ bool FPushMovementChainTests::RunTest(const FString& Parameters) /* Case1: ๊ฑท๊ธฐ ์ค‘ ํ•จ์ • ๋“ฑ๋ก -> ๊ฒฝ๋กœ ๊ต์ฒด */ AddInfo(TEXT("=== Case1: ๊ฑท๊ธฐ ์ค‘ ๋“ฑ๋ก -> ์ž”์—ฌ ๊ฑท๊ธฐ ํ๊ธฐ, ๋ฐ€์น˜๊ธฐ ๊ฒฝ๋กœ ์™„์ฃผ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // (3,2)์— ๋ฐ€์น˜๊ธฐ ํ•จ์ •์ด ์žˆ๋Š” ์ƒํ™ฉ: ๋„์ฐฉ ํ†ต์ง€์—์„œ +Y 2์นธ ๋ฐ€์น˜๊ธฐ ๋“ฑ๋ก TArray RegisterResults; @@ -221,7 +226,7 @@ bool FPushMovementChainTests::RunTest(const FString& Parameters) /* Case2: ๊ฐ™์€ ํ•จ์ • 1ํšŒ ์ œํ•œ + ์ƒˆ ์š”์ฒญ์—์„œ ๊ธฐ๋ก ์ดˆ๊ธฐํ™” */ AddInfo(TEXT("=== Case2: ๊ฐ™์€ ํ•จ์ • ์žฌ๋“ฑ๋ก ๊ฑฐ๋ถ€, ์ƒˆ ์š”์ฒญ์ด๋ฉด ๋‹ค์‹œ ํ—ˆ์šฉ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // ํ•จ์ • ํ‚ค๋ฅผ (3,2)๋กœ ๊ณ ์ •ํ•˜๊ณ  ๋งค ๋„์ฐฉ๋งˆ๋‹ค ๋“ฑ๋ก ์‹œ๋„: ์ฒซ ๋ฐœ๋™๋งŒ ์„ฑ๊ณตํ•ด์•ผ ํ•จ TArray RegisterResults; @@ -259,7 +264,7 @@ bool FPushMovementChainTests::RunTest(const FString& Parameters) /* Case3: ๋ฐ€ ๊ณณ์ด ์—†๋Š” ํ•จ์ • -> ์ž”์—ฌ ๊ฑท๊ธฐ ํ๊ธฐ, ํ•จ์ • ์นธ์—์„œ ์™„๋ฃŒ */ AddInfo(TEXT("=== Case3: ์ œ์ž๋ฆฌ 1์นธ ๊ฒฝ๋กœ ๋“ฑ๋ก -> ์ž”์—ฌ ๊ฑท๊ธฐ ํ๊ธฐ, ํ•จ์ • ์นธ์—์„œ ์™„๋ฃŒ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // (3,2)์— ๋ฐ€์น˜๊ธฐ ํ•จ์ •์ด ์žˆ์ง€๋งŒ ๋ฐ€๋ฆด ๊ณณ์ด ๋ง‰ํžŒ ์ƒํ™ฉ: ๋„์ฐฉ ํ†ต์ง€์—์„œ ์ œ์ž๋ฆฌ 1์นธ ๊ฒฝ๋กœ ๋“ฑ๋ก TArray RegisterResults; @@ -326,6 +331,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementGuardTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -336,7 +343,7 @@ bool FPushMovementGuardTests::RunTest(const FString& Parameters) return false; } - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); /* Case1: ์ •์ง€ ์ƒํƒœ ๋“ฑ๋ก ๊ฑฐ๋ถ€ (์ •์ง€ ๋Œ€์ƒ์€ PushAlongPath๋ฅผ ์“ฐ๋ผ๋Š” ์‹ ํ˜ธ) */ AddInfo(TEXT("=== Case1: ์ •์ง€ ์ƒํƒœ TryRegisterPendingPush -> false ===")); @@ -385,6 +392,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementCancelTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -395,7 +404,7 @@ bool FPushMovementCancelTests::RunTest(const FString& Parameters) return false; } - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // (3,2)๋กœ ํ–ฅํ•˜๋Š” ์Šคํ…์ด ์‹œ์ž‘๋˜๋ฉด ์ทจ์†Œ ์š”์ฒญ (์Šคํ… ์—ฐ์ถœ ์ข…๋ฃŒ ์‹œ์ ์— ๋ฐ˜์˜๋จ) FDelegateHandle CancelHandle = Fixture.Unit->OnStartMoveStep.AddLambda( @@ -462,6 +471,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementBlockedTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -476,10 +487,10 @@ bool FPushMovementBlockedTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1: ์ด๋™ ์ค‘ ๋‹ค์Œ ์นธ ์ ์œ  -> ์ง์ „ ์นธ์—์„œ ์™„๋ฃŒ ===")); { // (5,2)์—์„œ (3,2)๊นŒ์ง€ ๋‹น๊ฒจ์ง€๋Š” ์œ ๋‹› - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); // ๋‹ค๋ฅธ ์œ ๋‹›: (4,2) ๋„์ฐฉ ํ†ต์ง€ ์‹œ์ ์— ๋ชฉ์ ์ง€ (3,2)๋ฅผ ๋จผ์ € ์ฐจ์ง€ (๋™์‹œ์— ๋‹น๊ฒจ์ง„ ์œ ๋‹›์ด ๋จผ์ € ๋„์ฐฉํ•œ ์ƒํ™ฉ) - UMockEnemyUnitModel* Blocker = NewObject(World); + UMockEnemyUnitModel* Blocker = Scope.New(World); Blocker->Initialize(); Blocker->BeginPlay(); FDelegateHandle BlockHandle = Fixture.Unit->OnEndMoveStep.AddLambda( @@ -511,10 +522,10 @@ bool FPushMovementBlockedTests::RunTest(const FString& Parameters) /* Case2: ์‹œ์ž‘ ์ „์— ์ฒซ ์นธ์ด ๋ง‰ํž˜ */ AddInfo(TEXT("=== Case2: ์ฒซ ์นธ ์ ์œ  -> ์‹œ์ž‘ ๊ฑฐ๋ถ€, ์ œ์ž๋ฆฌ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(5, 2), ETileActorDirection::Left)); // ๋‹ค๋ฅธ ์œ ๋‹›์ด ์ฒซ ์ด๋™ ์นธ (4,2)์— ์ด๋ฏธ ์„œ ์žˆ์Œ - UMockEnemyUnitModel* Blocker = NewObject(World); + UMockEnemyUnitModel* Blocker = Scope.New(World); Blocker->Initialize(); Blocker->BeginPlay(); Fixture.TileMap->PlaceActor(FTileTransform(FTileIndex(4, 2), ETileActorDirection::Forward), Blocker); @@ -550,6 +561,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FPushMovementStatusEffectTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForPushTests(); if (World == nullptr) { @@ -576,7 +589,7 @@ bool FPushMovementStatusEffectTests::RunTest(const FString& Parameters) /* Case1: ๊ฑท๋Š” ์ค‘ ์†๋ฐ• -> ์ •์ง€ */ AddInfo(TEXT("=== Case1: ๊ฑท๋Š” ์ค‘ ์†๋ฐ• -> ๊ทธ ์นธ์—์„œ ์ •์ง€, ๋‚จ์€ ๊ฒฝ๋กœ ํ๊ธฐ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); FDelegateHandle StatusHandle = AddStatusOnArrive(Fixture, EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Root); int32 FinishCount = 0; @@ -597,7 +610,7 @@ bool FPushMovementStatusEffectTests::RunTest(const FString& Parameters) /* Case2: ๋ฐ€๋ฆฌ๋Š” ์ค‘ ๊ธฐ์ ˆ -> ๋๊นŒ์ง€ ๋ฐ€๋ฆผ */ AddInfo(TEXT("=== Case2: ๋ฐ€๋ฆฌ๋Š” ์ค‘ ๊ธฐ์ ˆ -> ๋๊นŒ์ง€ ๋ฐ€๋ฆผ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); FDelegateHandle StatusHandle = AddStatusOnArrive(Fixture, EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Stun); Fixture.Movement->PushAlongPath({ FTileIndex(2, 2), FTileIndex(3, 2), FTileIndex(4, 2) }); @@ -611,7 +624,7 @@ bool FPushMovementStatusEffectTests::RunTest(const FString& Parameters) /* Case3: ๋ฐ€๋ฆฌ๋Š” ์ค‘ ์†๋ฐ• -> ๋๊นŒ์ง€ ๋ฐ€๋ฆผ */ AddInfo(TEXT("=== Case3: ๋ฐ€๋ฆฌ๋Š” ์ค‘ ์†๋ฐ• -> ๋๊นŒ์ง€ ๋ฐ€๋ฆผ ===")); { - FPushMovementFixture Fixture = MakePushMovementFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FPushMovementFixture Fixture = MakePushMovementFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); FDelegateHandle StatusHandle = AddStatusOnArrive(Fixture, EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Root); Fixture.Movement->PushAlongPath({ FTileIndex(2, 2), FTileIndex(3, 2), FTileIndex(4, 2) }); diff --git a/Source/P_RDTests/Component/BoardMovementComponent/TeleportMovementTests.cpp b/Source/P_RDTests/Component/BoardMovementComponent/TeleportMovementTests.cpp index 31d184e2d..bf2f2561c 100644 --- a/Source/P_RDTests/Component/BoardMovementComponent/TeleportMovementTests.cpp +++ b/Source/P_RDTests/Component/BoardMovementComponent/TeleportMovementTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" // UMockEnemyUnitModel @@ -49,30 +50,30 @@ namespace UMockUnitMovementComponentModel* Movement = nullptr; }; - // @brief 8x8 ํƒ€์ผ๋งต์— ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐ - FTeleportFixture MakeTeleportFixture(UWorld* World, const FTileTransform& StartTransform) + // @brief 8x8 ํƒ€์ผ๋งต์— ์œ ๋‹›์„ ๋ฐฐ์น˜ํ•˜๊ณ  ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฐ๊ฒฐ (์ƒ์„ฑ ๊ฐ์ฒด๋Š” ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + FTeleportFixture MakeTeleportFixture(UWorld* World, FTestObjectScope& Scope, const FTileTransform& StartTransform) { FTeleportFixture Fixture; - Fixture.TileMap = NewObject(World); + Fixture.TileMap = Scope.New(World); Fixture.TileMap->SetDimensions(8, 8); - Fixture.Unit = NewObject(World); + Fixture.Unit = Scope.New(World); Fixture.Unit->Initialize(); Fixture.Unit->BeginPlay(); // ์œ ๋‹›์„ Outer๋กœ ๋งŒ๋“ค์–ด์„œ GetOwnerModel()(Outer ์ฒด์ธ ํƒ์ƒ‰)์ด ์œ ๋‹›์„ ์ฐพ๊ฒŒ ํ•จ - Fixture.Movement = NewObject(Fixture.Unit); + Fixture.Movement = Scope.New(Fixture.Unit); Fixture.Movement->SetTileMap(Fixture.TileMap); Fixture.TileMap->PlaceActor(StartTransform, Fixture.Unit); return Fixture; } - // @brief ์˜ค๋ฒ„๋žฉ ๊ด€์ธก Mock์„ ํƒ€์ผ์— ๋ฐฐ์น˜ - UMockOverlapSensorModel* PlaceSensor(const FTeleportFixture& Fixture, const FTileIndex& TileIndex) + // @brief ์˜ค๋ฒ„๋žฉ ๊ด€์ธก Mock์„ ํƒ€์ผ์— ๋ฐฐ์น˜ (์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + UMockOverlapSensorModel* PlaceSensor(const FTeleportFixture& Fixture, FTestObjectScope& Scope, const FTileIndex& TileIndex) { - UMockOverlapSensorModel* Sensor = NewObject(Fixture.TileMap); + UMockOverlapSensorModel* Sensor = Scope.New(Fixture.TileMap); Fixture.TileMap->PlaceActor(FTileTransform(TileIndex, ETileActorDirection::Forward), Sensor); return Sensor; } @@ -92,6 +93,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FTeleportMovementBasicTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTeleportTests(); if (World == nullptr) { @@ -102,9 +105,9 @@ bool FTeleportMovementBasicTests::RunTest(const FString& Parameters) return false; } - FTeleportFixture Fixture = MakeTeleportFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Left)); - UMockOverlapSensorModel* StartSensor = PlaceSensor(Fixture, FTileIndex(2, 2)); - UMockOverlapSensorModel* EndSensor = PlaceSensor(Fixture, FTileIndex(5, 5)); + FTeleportFixture Fixture = MakeTeleportFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Left)); + UMockOverlapSensorModel* StartSensor = PlaceSensor(Fixture, Scope, FTileIndex(2, 2)); + UMockOverlapSensorModel* EndSensor = PlaceSensor(Fixture, Scope, FTileIndex(5, 5)); UAttributeSetComponentModel* AttrComp = Fixture.Unit->GetAttributeComponentModel(); if (TestNotNull(TEXT("์†์„ฑ ์ปดํฌ๋„ŒํŠธ"), AttrComp) == false) @@ -154,6 +157,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FTeleportMovementTrapTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTeleportTests(); if (World == nullptr) { @@ -164,10 +169,10 @@ bool FTeleportMovementTrapTests::RunTest(const FString& Parameters) return false; } - FTeleportFixture Fixture = MakeTeleportFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FTeleportFixture Fixture = MakeTeleportFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // (5,5) ํ•จ์ •: ์ง„์ž… ํ†ต์ง€์—์„œ +Y๋กœ 2์นธ ๋ฐ€์น˜๊ธฐ ์‹œ๋„ (๋ฐ€์น˜๊ธฐ ์ดํŽ™ํŠธ์˜ ์ •์ง€ ๋Œ€์ƒ ๊ฒฝ๋กœ ํ‰๋‚ด) - UMockOverlapSensorModel* TrapSensor = PlaceSensor(Fixture, FTileIndex(5, 5)); + UMockOverlapSensorModel* TrapSensor = PlaceSensor(Fixture, Scope, FTileIndex(5, 5)); bool MovingAtOverlap = true; bool PushStarted = false; TrapSensor->mOnBeginOverlap.BindLambda([&]() @@ -206,6 +211,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FTeleportMovementGuardTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForTeleportTests(); if (World == nullptr) { @@ -219,9 +226,9 @@ bool FTeleportMovementGuardTests::RunTest(const FString& Parameters) /* Case1: ๋ง‰ํžŒ ํƒ€์ผ */ AddInfo(TEXT("=== Case1: ๋„์ฐฉ ํƒ€์ผ ์ ์œ  -> ์‹œ์ž‘ ๊ฑฐ๋ถ€, ์ œ์ž๋ฆฌ ===")); { - FTeleportFixture Fixture = MakeTeleportFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FTeleportFixture Fixture = MakeTeleportFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); - UMockEnemyUnitModel* Blocker = NewObject(World); + UMockEnemyUnitModel* Blocker = Scope.New(World); Blocker->Initialize(); Blocker->BeginPlay(); Fixture.TileMap->PlaceActor(FTileTransform(FTileIndex(5, 5), ETileActorDirection::Forward), Blocker); @@ -244,7 +251,7 @@ bool FTeleportMovementGuardTests::RunTest(const FString& Parameters) /* Case2: ๊ฑท๋Š” ์ค‘ */ AddInfo(TEXT("=== Case2: ๊ฑท๋Š” ์ค‘ ํ…”๋ ˆํฌํŠธ ๊ฑฐ๋ถ€, ๊ฑท๊ธฐ ์ข…๋ฃŒ ํ›„ ํ—ˆ์šฉ ===")); { - FTeleportFixture Fixture = MakeTeleportFixture(World, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); + FTeleportFixture Fixture = MakeTeleportFixture(World, Scope, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward)); // ๋ทฐ ํ‰๋‚ด: ๊ฑท๊ธฐ ์Šคํ… ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์žก์•„ ๊ฑท๋Š” ์ค‘ ์ƒํƒœ๋ฅผ ์œ ์ง€ TSharedPtr HeldStepBarrier; diff --git a/Source/P_RDTests/Component/BoardMovementComponent/UnitMovementComponentModelTests.cpp b/Source/P_RDTests/Component/BoardMovementComponent/UnitMovementComponentModelTests.cpp index 537fb0492..83cc8a798 100644 --- a/Source/P_RDTests/Component/BoardMovementComponent/UnitMovementComponentModelTests.cpp +++ b/Source/P_RDTests/Component/BoardMovementComponent/UnitMovementComponentModelTests.cpp @@ -8,6 +8,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" @@ -47,6 +48,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FUnitRootTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForRootTests(); if (World == nullptr) { @@ -58,7 +61,7 @@ bool FUnitRootTests::RunTest(const FString& Parameters) } // ์œ ๋‹› ์ƒ์„ฑ (์Šคํฐ ๋ฐ์ดํ„ฐ ์—†์ด ๋„๋Š” ํ”Œ๋ž˜๋„ˆ์šฉ Mock ์žฌ์‚ฌ์šฉ) - UMockEnemyUnitModel* Unit = NewObject(World); + UMockEnemyUnitModel* Unit = Scope.New(World); Unit->Initialize(); Unit->BeginPlay(); diff --git a/Source/P_RDTests/Component/EquipmentComponent/EquipmentComponentModelTests.cpp b/Source/P_RDTests/Component/EquipmentComponent/EquipmentComponentModelTests.cpp index 29337db3a..a11207755 100644 --- a/Source/P_RDTests/Component/EquipmentComponent/EquipmentComponentModelTests.cpp +++ b/Source/P_RDTests/Component/EquipmentComponent/EquipmentComponentModelTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "GameplayTagContainer.h" @@ -38,18 +39,20 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FEquipmentComponentModelTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag StartTiming = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); // ์ปดํฌ๋„ŒํŠธ (์˜ค๋„ˆ ์—†์ด ๋…๋ฆฝ ์ƒ์„ฑ, ๋‚ด๋ถ€ ์‹œ๋“œ๋กœ ํ˜•์ œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ์ฃผ์ž…) - UEquipmentComponentModel* EquipComp = NewObject(); - UPassiveComponentModel* PassiveComp = NewObject(); + UEquipmentComponentModel* EquipComp = Scope.New(); + UPassiveComponentModel* PassiveComp = Scope.New(); if (!TestNotNull(TEXT("์žฅ๋น„ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ"), EquipComp) || !TestNotNull(TEXT("ํŒจ์‹œ๋ธŒ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ"), PassiveComp)) { return false; } // ํŒจ์‹œ๋ธŒ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ์ œ๋„ค๋ฆญ ํŒจ์‹œ๋ธŒ + AttackFactor ์ดํŽ™ํŠธ + ์ˆ˜์น˜ 5 + OnStartTurn ์‹œ์  - UStaticPassiveData* PassiveData = NewObject(); + UStaticPassiveData* PassiveData = Scope.New(); PassiveData->mPassiveClass = UTacticalPassive_Generic::StaticClass(); FPassiveEffectEntry& Effect = PassiveData->mEffects.AddDefaulted_GetRef(); Effect.mEffectClass = UTacticalEffect_AttackFactor_AddBase::StaticClass(); @@ -57,7 +60,7 @@ bool FEquipmentComponentModelTests::RunTest(const FString& Parameters) PassiveData->mActivateTimingTag = StartTiming; // ๋ฌด๊ธฐ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ์œ„ ํŒจ์‹œ๋ธŒ๋ฅผ ์ฐธ์กฐ - UStaticEquipmentData* Weapon = NewObject(); + UStaticEquipmentData* Weapon = Scope.New(); Weapon->mStaticPassiveData.Add(TSoftObjectPtr(PassiveData)); // ์žฅ์ฐฉ: ํŒจ์‹œ๋ธŒ๊ฐ€ ์„ค์น˜๋ผ์•ผ ํ•จ diff --git a/Source/P_RDTests/Component/EquipmentComponent/EquipmentStatModifierTests.cpp b/Source/P_RDTests/Component/EquipmentComponent/EquipmentStatModifierTests.cpp index 0d4230b4f..06d38051c 100644 --- a/Source/P_RDTests/Component/EquipmentComponent/EquipmentStatModifierTests.cpp +++ b/Source/P_RDTests/Component/EquipmentComponent/EquipmentStatModifierTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "TAS/TASAttributeTestsHelper.h" @@ -52,6 +53,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FEquipmentStatModifierTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + // ๋ผ์ด๋ธŒ ์›”๋“œ ํ™•๋ณด (TAS ์†์„ฑ ํ…Œ์ŠคํŠธ์™€ ๋™์ผ ํ™˜๊ฒฝ) UWorld* World = FindAnyGameWorld(); if (World == nullptr) @@ -79,12 +82,14 @@ bool FEquipmentStatModifierTests::RunTest(const FString& Parameters) UTacticalFrameworkModel* FrameworkModel = Cast(RoomInstance->mAliveSubsystemModels.FindRef(UTacticalFrameworkModel::StaticClass())); if (FrameworkModel == nullptr) { - FrameworkModel = NewObject(RoomInstance); + FrameworkModel = Scope.New(RoomInstance); RoomInstance->mAliveSubsystemModels.Add(UTacticalFrameworkModel::StaticClass(), FrameworkModel); + // ํ…Œ์ŠคํŠธ๊ฐ€ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ํŒŒ๊ดด ์ „์— ๋“ฑ๋ก ํ•ด์ œ + Scope.Defer([RoomInstance]() { RoomInstance->mAliveSubsystemModels.Remove(UTacticalFrameworkModel::StaticClass()); }); } // ์†์„ฑ ์ปดํฌ๋„ŒํŠธ ๋ชจํฌ (UUnitAttributeSet ๋ถ€์ฐฉ) - UTASActorModelMock* MockActorModel = NewObject(World); + UTASActorModelMock* MockActorModel = Scope.New(World); MockActorModel->Initialize(); MockActorModel->BeginPlay(); UAttributeSetComponentModel* AttrComp = MockActorModel->GetAttributeComponent(); @@ -99,7 +104,7 @@ bool FEquipmentStatModifierTests::RunTest(const FString& Parameters) TestEqual(TEXT("๊ธฐ๋ณธ ๊ณต๊ฒฉ๋ ฅ 10"), AttrComp->GetAttributeCurrentValue(AttackPoint), 10.f); // ๋ฌด๊ธฐ DA (์ฝ”๋“œ ๊ตฌ์„ฑ): ๊ณต๊ฒฉ๋ ฅ +5 ๊ณ ์œ  ์Šคํƒฏ - UStaticEquipmentData* Weapon = NewObject(); + UStaticEquipmentData* Weapon = Scope.New(); FTacticalModifierInfo Mod; Mod.mAttribute = AttackPoint; Mod.mModifierOp = ETacticalModOp::AddBase; @@ -107,7 +112,7 @@ bool FEquipmentStatModifierTests::RunTest(const FString& Parameters) Weapon->mStatModifiers.Add(Mod); // ์žฅ์ฐฉ: ์Šคํƒฏ ์ดํŽ™ํŠธ๊ฐ€ ์ž์‹ ์—๊ฒŒ ์ ์šฉ (ํŒจ์‹œ๋ธŒ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถˆํ•„์š” โ†’ nullptr) - UEquipmentComponentModel* EquipComp = NewObject(); + UEquipmentComponentModel* EquipComp = Scope.New(); const bool bEquipped = EquipComp->EquipInternal(Weapon, nullptr, AttrComp); TestTrue(TEXT("์žฅ์ฐฉ ์„ฑ๊ณต"), bEquipped); TestEqual(TEXT("์žฅ์ฐฉ ํ›„ ๊ณต๊ฒฉ๋ ฅ 15 (๊ธฐ๋ณธ 10 + ์Šคํƒฏ 5)"), AttrComp->GetAttributeCurrentValue(AttackPoint), 15.f); diff --git a/Source/P_RDTests/Component/PassiveComponent/PassiveComponentModelTests.cpp b/Source/P_RDTests/Component/PassiveComponent/PassiveComponentModelTests.cpp index 0e959689e..8259864cb 100644 --- a/Source/P_RDTests/Component/PassiveComponent/PassiveComponentModelTests.cpp +++ b/Source/P_RDTests/Component/PassiveComponent/PassiveComponentModelTests.cpp @@ -8,6 +8,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "GameplayTagContainer.h" @@ -32,11 +33,13 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveComponentModelTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag StartTiming = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartApplyingEffect")); const FGameplayTag EndTiming = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndApplyingEffect")); const FGameplayTag UnusedTiming = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); - UPassiveComponentModel* Component = NewObject(); + UPassiveComponentModel* Component = Scope.New(); if (!TestNotNull(TEXT("์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ"), Component)) { return false; diff --git a/Source/P_RDTests/Component/SkillComponent/SkillComponentModelTests.cpp b/Source/P_RDTests/Component/SkillComponent/SkillComponentModelTests.cpp index 9a2eec6c0..a1db16d3f 100644 --- a/Source/P_RDTests/Component/SkillComponent/SkillComponentModelTests.cpp +++ b/Source/P_RDTests/Component/SkillComponent/SkillComponentModelTests.cpp @@ -8,6 +8,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" @@ -39,10 +40,10 @@ namespace return nullptr; } - // @brief ํ…Œ์ŠคํŠธ์šฉ ๋”๋ฏธ ์Šคํ‚ฌ ์ƒ์„ฑ. ์ง์—… ๋ฌด๊ด€, ์‹œ์ „ ๋น„์šฉ 0 - UStaticSkillData* MakeDummySkill(UWorld* World) + // @brief ํ…Œ์ŠคํŠธ์šฉ ๋”๋ฏธ ์Šคํ‚ฌ ์ƒ์„ฑ. ์ง์—… ๋ฌด๊ด€, ์‹œ์ „ ๋น„์šฉ 0. ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UStaticSkillData* MakeDummySkill(UWorld* World, FTestObjectScope& Scope) { - UStaticUnitSkillData* Skill = NewObject(World); + UStaticUnitSkillData* Skill = Scope.New(World); Skill->mJobType = EUnitJobType::Common; Skill->mRequiredActionPoint = 0; // ๋ชจ์…˜ ๋ ˆ์ด์–ด ์—†์œผ๋ฉด ๋ฏธ์žฅ์ฐฉ์œผ๋กœ ํŒ์ •ํ•˜๋ฏ€๋กœ ๋”๋ฏธ 1๊ฐœ ์ถ”๊ฐ€ @@ -59,6 +60,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FSkillComponentStatusEffectTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorldForSkillTests(); if (World == nullptr) { @@ -70,7 +73,7 @@ bool FSkillComponentStatusEffectTests::RunTest(const FString& Parameters) } // ์œ ๋‹› ์ƒ์„ฑ ํ›„ ์Šฌ๋กฏ 0์— ๋”๋ฏธ ์Šคํ‚ฌ ์žฅ์ฐฉ - UMockEnemyUnitModel* Unit = NewObject(World); + UMockEnemyUnitModel* Unit = Scope.New(World); Unit->Initialize(); Unit->BeginPlay(); @@ -86,7 +89,7 @@ bool FSkillComponentStatusEffectTests::RunTest(const FString& Parameters) } SkillComp->SetSkillFrom(TArray>()); - SkillComp->SetSkill(0, MakeDummySkill(World)); + SkillComp->SetSkill(0, MakeDummySkill(World, Scope)); /* [1] ๊ธฐ๋ณธ ์ƒํƒœ: ์‚ฌ์šฉ ๊ฐ€๋Šฅ */ TestTrue(TEXT("๊ธฐ๋ณธ: ์Šคํ‚ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅ"), SkillComp->CanActiveSkill(0)); diff --git a/Source/P_RDTests/Component/SkillComponent/SkillForcedMoveSyncTests.cpp b/Source/P_RDTests/Component/SkillComponent/SkillForcedMoveSyncTests.cpp new file mode 100644 index 000000000..5138b3a44 --- /dev/null +++ b/Source/P_RDTests/Component/SkillComponent/SkillForcedMoveSyncTests.cpp @@ -0,0 +1,663 @@ +๏ปฟ/*****************************************************************//** + * @file SkillForcedMoveSyncTests.cpp + * @brief ๋ฐ€๋‹น ํŽ˜์ด์ฆˆ ๋™๊ธฐํ™” ์œ ๋‹›ํ…Œ์ŠคํŠธ + * @details + * ๋ฐ€์น˜๊ธฐ/๋‹น๊ธฐ๊ธฐ๊ฐ€ ์žˆ๋Š” ํŽ˜์ด์ฆˆ๋Š” ํ”ผ๊ฒฉ์ž ์ด๋™์ด ๋๋‚œ ๋’ค์— ์ข…๋ฃŒ๋˜๊ณ , ๊ด‘์—ญ์€ ๋Œ€์ƒ ํ•˜๋‚˜์”ฉ ์ˆœ์ฐจ ์ถœ๋ฐœํ•˜๋Š”์ง€ ๊ฒ€์ฆ. + * ๋ฐฐ๋ฆฌ์–ด ๊ตฌ๋…์ž๊ฐ€ ์—†์œผ๋ฉด ๋™๊ธฐ ์™„์ฃผ(์‹œ๋ฎฌ๋ ˆ์ด์…˜), ํ…Œ์ŠคํŠธ๊ฐ€ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์žก๊ณ  ์žˆ์œผ๋ฉด ๋ผ์ด๋ธŒ์ฒ˜๋Ÿผ ๋‹จ๊ณ„๋ณ„ ์ง„ํ–‰. + * @author ์ด๋ฌธํ™˜ + * @date 2026-09-20 + *********************************************************************/ + +#include "P_RDTests.h" +#include "TestObjectScope.h" +#include "Misc/AutomationTest.h" + +#include "Actor/BoardActor/GimmickTestsHelper.h" // UMockOverlapGimmickModel, UMockGimmickVictimUnitModel +#include "Component/BoardMovementComponent/BoardMovementTestsHelper.h" // UMockUnitMovementComponentModel + +#include "GameplayTagType.h" +#include "Actor/TileMap/TileMapModel.h" +#include "Animation/BoardActorAnimType.h" +#include "Component/SkillComponent/SkillComponentModel.h" +#include "Component/AttributeComponent/AttributeSetComponentModel.h" +#include "DataAsset/SkillData/StaticSkillData.h" +#include "DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Push.h" +#include "DataAsset/SkillData/SkillEffectLayer/SkillEffectLayer_Stun.h" +#include "Singleton/WorldSubsystem/PresentationBarrier.h" +#include "TAS/Effect/Cooldown/TacticalEffect_Cooldown.h" + +#include "Engine/World.h" +#include "Engine/Engine.h" + +#if WITH_EDITOR +#include "Misc/DataValidation.h" +#endif + +namespace +{ + // @brief ํ…Œ์ŠคํŠธ์šฉ ์›”๋“œ ํš๋“ (PIE/Game ์šฐ์„ ) + UWorld* GetAnyGameWorldForForcedMoveTests() + { + if (GEngine == nullptr) + { + return nullptr; + } + for (const FWorldContext& Context : GEngine->GetWorldContexts()) + { + if ((Context.WorldType == EWorldType::PIE || Context.WorldType == EWorldType::Game) && Context.World() != nullptr) + { + return Context.World(); + } + } + return nullptr; + } + + /* ์Šคํ‚ฌ ๋ฐ์ดํ„ฐ */ + + // @brief ์Šคํ‚ฌ ๊ณตํ†ต ๊ณจ๊ฒฉ (๋‹จํƒ€, ์ž๊ธฐ ํƒ€์ผ ์กฐ์ค€, ์ „ ํŒ€ ํƒ€๊ฒฉ). ์˜ํ–ฅ ๋ฒ”์œ„๋Š” ํ˜ธ์ถœ์ž๊ฐ€ ์ง€์ •. ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UStaticSkillData* MakeSkillDataBase(UObject* Outer, FTestObjectScope& Scope, EEffectPattern EffectPattern, int32 EffectArea) + { + UStaticSkillData* SkillData = Scope.New(Outer); + // ์Šคํ‚ฌ ์‹œ์ „ ์‹œ ์ฟจ๋‹ค์šด ์ŠคํŽ™์„ ๋งŒ๋“ค๋ฏ€๋กœ ๋ผ์šด๋“œ ์ฟจ๋‹ค์šด ์ง€์ • (๋ฏธ์ง€์ • ์‹œ ์ŠคํŽ™์ด ๋ฌดํšจ) + SkillData->mCooldownEffectClass = UTacticalEffect_RoundCooldown::StaticClass(); + SkillData->mSkillAnimationSet.mApplyMotionTags.Add(AnimationTags::Animation_Montage_Skill_Melee_Punch); + SkillData->mSkillAnimationSet.mAutoRotateTowardTarget = false; + SkillData->mTargetPattern = ETargetPattern::TargetOnly; + SkillData->mEffectPattern = EffectPattern; + SkillData->mEffectArea = EffectArea; + + FSkillPhaseLayer Phase; + Phase.mTeamAttitudeFilter = StaticCast(ETeamAttitudeFilter::All); + SkillData->mSkillPhaseLayers.Add(Phase); + return SkillData; + } + + // @brief ๋ฐ€์น˜๊ธฐ ๋ ˆ์ด์–ด (TagGain = ๋ฐ€์น  ์นธ ์ˆ˜) + TInstancedStruct MakePushLayer(int32 PushDistance) + { + TInstancedStruct Layer; + Layer.InitializeAs(); + Layer.GetMutable().mTagGain = PushDistance; + return Layer; + } + + // @brief ๊ธฐ์ ˆ ๋ ˆ์ด์–ด (๋ฐ€๋‹น์ด ์•„๋‹Œ ์ดํŽ™ํŠธ ๋Œ€ํ‘œ) + TInstancedStruct MakeStunLayer() + { + TInstancedStruct Layer; + Layer.InitializeAs(); + Layer.GetMutable().mTagGain = 1; + return Layer; + } + + // @brief ์‹œ์ „์ž ์Šคํ‚ฌ: ์ž๊ธฐ ํƒ€์ผ ๊ธฐ์ค€ ์‚ฌ๊ฐํ˜• 2์นธ ๋ฒ”์œ„ ๋ฐ€์น˜๊ธฐ (์‚ฌ๊ฐํ˜•์€ ์ฐจ๋‹จ ๋ ˆ์ด์–ด์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ฒ”์œ„ ์•ˆ์„ ์ „๋ถ€ ํฌํ•จํ•˜๋ฏ€๋กœ ์ผ์ง์„  ๋‘ ๋ช…๋„ ๊ฐ™์ด ๋งž์Œ) + UStaticSkillData* MakeAreaPushSkillData(UObject* Outer, FTestObjectScope& Scope, int32 PushDistance) + { + UStaticSkillData* SkillData = MakeSkillDataBase(Outer, Scope, EEffectPattern::Square, 2); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakePushLayer(PushDistance)); + return SkillData; + } + + // @brief ๋ฐœํŒ ์Šคํ‚ฌ: ๋ฐŸ์€ ์ž๋ฆฌ ํ•œ ์นธ, ๋ฐœํŒ ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ€์น˜๊ธฐ + UStaticSkillData* MakeTrapPushSkillData(UObject* Outer, FTestObjectScope& Scope, int32 PushDistance) + { + UStaticSkillData* SkillData = MakeSkillDataBase(Outer, Scope, EEffectPattern::Single, 0); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakePushLayer(PushDistance)); + return SkillData; + } + + /* ํ”ฝ์Šค์ฒ˜ */ + + // @brief ํƒ€์ผ๋งต ์ฃผ์ž… ๊ธฐ๋ฏน ์ƒ์„ฑ/๋ฐฐ์น˜. ์‹œ์ „์ž ๋˜๋Š” ๋ฐœํŒ์œผ๋กœ ์‚ฌ์šฉ. ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UMockOverlapGimmickModel* MakeGimmick(UWorld* World, FTestObjectScope& Scope, UTileMapModel* TileMap, const FTileTransform& Transform, UStaticSkillData* SkillData, int32 TriggerCount) + { + UMockOverlapGimmickModel* Gimmick = Scope.New(World); + Gimmick->Initialize(); + Gimmick->BeginPlay(); + Gimmick->SetTileMap(TileMap); + Gimmick->GetSkillComponentModel()->SetSkillFrom(TArray>{ SkillData }); + Gimmick->SetRemainingTriggerCount(TriggerCount); + TileMap->PlaceActor(Transform, Gimmick); + return Gimmick; + } + + // @brief ํ”ผ๊ฒฉ ์œ ๋‹› ์ƒ์„ฑ/๋ฐฐ์น˜ (ํƒ€์ผ๋งต ์ฃผ์ž… ์ด๋™ ์ปดํฌ๋„ŒํŠธ ์—ฐ๊ฒฐ). ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UMockGimmickVictimUnitModel* MakeVictim(UWorld* World, FTestObjectScope& Scope, UTileMapModel* TileMap, const FTileTransform& Transform) + { + UMockGimmickVictimUnitModel* Unit = Scope.New(World); + Unit->Initialize(); + Unit->BeginPlay(); + UMockUnitMovementComponentModel* Movement = Scope.New(Unit); + Movement->SetTileMap(TileMap); + Unit->SetBoardMovementComponentModel(Movement); + TileMap->PlaceActor(Transform, Unit); + return Unit; + } + + // @brief ๊ณต์šฉ ํ”ฝ์Šค์ฒ˜: 8x8 ํƒ€์ผ๋งต + (2,2) ์‹œ์ „์ž. ์Šคํ‚ฌ์€ ForcedActivateSkill๋กœ ์ง์ ‘ ์‹œ์ „ (์˜ค๋ฒ„๋žฉ ๊ฒฝ์œ  ์•ˆ ํ•จ) + struct FSyncFixture + { + UTileMapModel* TileMap = nullptr; + UMockOverlapGimmickModel* Caster = nullptr; + USkillComponentModel* SkillComp = nullptr; + + // @brief ์‹œ์ „์ž ์ž๊ธฐ ํƒ€์ผ ์กฐ์ค€์œผ๋กœ ์‹œ์ „ (์‚ฌ๊ฐํ˜• ๋ฒ”์œ„๊ฐ€ ์ฃผ๋ณ€ 2์นธ์„ ๋ฎ์Œ) + void Cast() const + { + SkillComp->ForcedActivateSkill(TileMap, 0, Caster->GetTileTransform().mIndex); + } + }; + + FSyncFixture MakeSyncFixture(UWorld* World, FTestObjectScope& Scope, UStaticSkillData* SkillData) + { + FSyncFixture Fixture; + Fixture.TileMap = Scope.New(World); + Fixture.TileMap->SetDimensions(8, 8); + // ์‹œ์ „์ž๋Š” ์˜ค๋ฒ„๋žฉ์œผ๋กœ ๋ฐœ๋™ํ•˜์ง€ ์•Š๋„๋ก ์ˆ˜๋ช… 0 + Fixture.Caster = MakeGimmick(World, Scope, Fixture.TileMap, FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), SkillData, 0); + Fixture.SkillComp = Fixture.Caster->GetSkillComponentModel(); + return Fixture; + } + + /* ๊ด€์ธก */ + + // @brief ์Šคํ‚ฌ ํŽ˜์ด์ฆˆ/์ข…๋ฃŒ ์ด๋ฒคํŠธ์™€ ์œ ๋‹› ์ด๋™ ์ข…๋ฃŒ ์ˆœ์„œ ๊ธฐ๋ก + struct FEventRecorder + { + TArray mEvents; + int32 mPhaseEndCount = 0; + int32 mSkillEndCount = 0; + + void BindSkill(USkillComponentModel* SkillComp) + { + SkillComp->OnEndPhaseLayerUI.AddLambda([this](int32) { + ++mPhaseEndCount; + mEvents.Add(TEXT("PhaseEnd")); + }); + SkillComp->OnEndSkillUI.AddLambda([this](const FActiveSkillContext&, const UStaticSkillData*) { + ++mSkillEndCount; + mEvents.Add(TEXT("SkillEnd")); + }); + } + + void BindMove(UBoardActorModel* Unit, const FString& Name) + { + Unit->OnEndMovePath.AddLambda([this, Name](const FTileTransform&, const FTransform&) { + mEvents.Add(Name + TEXT(":MoveEnd")); + }); + } + + FString Joined() const + { + return FString::Join(mEvents, TEXT(" > ")); + } + }; + + /* ๋ผ์ด๋ธŒ ํ‰๋‚ด */ + + // @brief ์œ ๋‹›์˜ ์Šคํ… ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์žก์•„ ๋‘๊ณ  ํ•˜๋‚˜์”ฉ ํ’€์–ด ์ด๋™์„ ๋‹จ๊ณ„๋ณ„๋กœ ์ง„ํ–‰ + struct FStepHolder + { + TArray> mHeld; + + void Bind(UBoardActorModel* Unit) + { + Unit->OnStartMoveStep.AddLambda([this](const FTileTransform&, const FTransform&, TSharedPtr Barrier, float, EBoardMoveMode) { + mHeld.Add(Barrier); + }); + } + + bool IsHolding() const + { + return mHeld.IsEmpty() == false; + } + + // @brief ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์Šคํ… ํ•˜๋‚˜ ํ’€๊ธฐ. ํ‘ธ๋Š” ๋„์ค‘ ๋‹ค์Œ ์Šคํ…์ด ๋“ค์–ด์™€ ๋ฐฐ์—ด์ด ๋ฐ”๋€Œ์–ด๋„ ์•ˆ์ „ํ•˜๋„๋ก ๋จผ์ € ๋นผ๋‚ธ ๋’ค Reset + bool ReleaseNext() + { + if (mHeld.IsEmpty() == true) + { + return false; + } + TSharedPtr Barrier = mHeld[0]; + mHeld.RemoveAt(0); + Barrier.Reset(); + return true; + } + + // @brief ์ด ์œ ๋‹›์˜ ์ด๋™์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ์ „๋ถ€ ํ’€๊ธฐ + void ReleaseAll() + { + while (ReleaseNext() == true) + { + } + } + }; + + // @brief ์‹œ์ „์ž ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์žก์•„ ๋‘๊ณ , ๋…ธํ‹ฐํŒŒ์ด ๋ฐœํ™”์™€ ์—ฐ์ถœ ์ข…๋ฃŒ๋ฅผ ํ…Œ์ŠคํŠธ๊ฐ€ ์ œ์–ด + struct FMotionHolder + { + TSharedPtr mHeld; + FBoardActorAnimationContext mContext; + + void Bind(UBoardActorModel* Caster) + { + Caster->OnPlayAnimationUI.AddLambda([this](TSharedPtr Barrier, const FBoardActorAnimationContext& Context) { + mHeld = Barrier; + mContext = Context; + }); + } + + // @brief HitLogic ๋…ธํ‹ฐํŒŒ์ด ๋ฐœํ™” -> TriggerPhaseLayer + void FireHitLogic() + { + mContext.mMontageEvents.FindChecked(AnimationTags::Animation_Event_Skill_HitLogic).OnTriggerAnimationEvent.Broadcast(mContext, nullptr, nullptr); + } + + // @brief ์—ฐ์ถœ ์ข…๋ฃŒ -> ์Šคํ‚ฌ ์ข…๋ฃŒ ๋ฐฐ๋ฆฌ์–ด ํ•ด์ œ + void Release() + { + mHeld.Reset(); + } + }; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSkillForcedMoveSyncSimTests, + "P_RD.SRPG.SkillComponent.ForcedMoveSync.Sim", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter +) + +/** + * @brief ์‹œ๋ฎฌ๋ ˆ์ด์…˜(๋ฐฐ๋ฆฌ์–ด ๊ตฌ๋…์ž ์—†์Œ) ๋™๊ธฐ ์™„์ฃผ ๊ฒ€์ฆ + * 1) ๋ฐ€์น˜๊ธฐ 1๋ช…: ๋„์ฐฉ ์œ„์น˜, ์ด๋ฒคํŠธ ์ˆœ์„œ ์ด๋™๋ -> ํŽ˜์ด์ฆˆ๋ -> ์Šคํ‚ฌ๋ + * 2) ๋ฐ€๋ฆฌ๋‹ค ๋ฐœํŒ ๋ฐŸ๊ณ  ์žฌ๋ฐ€๋ฆผ: ํŽ˜์ด์ฆˆ ๋ ์‹œ์  ์œ„์น˜ == ์ตœ์ข… ์œ„์น˜ (ํ•จ์ • ์—ฐ์‡„๊ฐ€ ํŽ˜์ด์ฆˆ ์•ˆ์— ํฌํ•จ) + * 3) ๋ฉด์—ญ ๋Œ€์ƒ: ์•ˆ ๋ฐ€๋ฆฌ๊ณ  ํŽ˜์ด์ฆˆ/์Šคํ‚ฌ ์ •์ƒ ์ข…๋ฃŒ + */ +bool FSkillForcedMoveSyncSimTests::RunTest(const FString& Parameters) +{ + FTestObjectScope Scope; + + UWorld* World = GetAnyGameWorldForForcedMoveTests(); + if (World == nullptr) + { + World = GWorld; + } + if (TestNotNull(TEXT("์œ ํšจํ•œ UWorld"), World) == false) + { + return false; + } + + /* Case1: ๊ธฐ๋ณธ */ + AddInfo(TEXT("=== Case1: (3,2) ๋Œ€์ƒ +x๋กœ 2์นธ ๋ฐ€๋ฆผ -> (5,2). ์ˆœ์„œ ์ด๋™๋ > ํŽ˜์ด์ฆˆ๋ > ์Šคํ‚ฌ๋ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + Recorder.BindMove(UnitA, TEXT("A")); + + Fixture.Cast(); + + TestTrue(TEXT("[Case1] A (5,2) ๋„์ฐฉ"), UnitA->GetTileTransform().mIndex == FTileIndex(5, 2)); + TestEqual(TEXT("[Case1] ์ด๋ฒคํŠธ ์ˆœ์„œ"), Recorder.Joined(), FString(TEXT("A:MoveEnd > PhaseEnd > SkillEnd"))); + TestFalse(TEXT("[Case1] ์Šคํ‚ฌ ์ข…๋ฃŒ ์ƒํƒœ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + /* Case2: ํ•จ์ • ์—ฐ์‡„ */ + AddInfo(TEXT("=== Case2: ๊ฒฝ๋กœ ์œ„ (4,2) ๋ฐœํŒ(+y 1์นธ) -> (4,3) ๋„์ฐฉ. ํŽ˜์ด์ฆˆ ๋ ์‹œ์  ์œ„์น˜ == ์ตœ์ข… ์œ„์น˜ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + // ๋ฐœํŒ์ด Right(+y)๋ฅผ ๋ฐ”๋ผ๋ด„. ๋ฐ€๋ฆฌ๋˜ A๊ฐ€ (4,2)๋ฅผ ๋ฐŸ์œผ๋ฉด +y๋กœ 1์นธ ์žฌ๋ฐ€๋ฆผ + UMockOverlapGimmickModel* Trap = MakeGimmick(World, Scope, Fixture.TileMap, FTileTransform(FTileIndex(4, 2), ETileActorDirection::Right), MakeTrapPushSkillData(World, Scope, 1), 1); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + + // ํŽ˜์ด์ฆˆ ๋ ์‹œ์ ์˜ A ์œ„์น˜ ๊ธฐ๋ก + FTileIndex IndexAtPhaseEnd = FTileIndex::Invalid; + Fixture.SkillComp->OnEndPhaseLayerUI.AddLambda([&](int32) { + IndexAtPhaseEnd = UnitA->GetTileTransform().mIndex; + }); + + Fixture.Cast(); + + TestTrue(TEXT("[Case2] A ๋ฐœํŒ ๋ฐฉํ–ฅ์œผ๋กœ ์žฌ๋ฐ€๋ฆฐ (4,3) ๋„์ฐฉ"), UnitA->GetTileTransform().mIndex == FTileIndex(4, 3)); + TestTrue(TEXT("[Case2] ํŽ˜์ด์ฆˆ ๋ ์‹œ์  ์œ„์น˜ == ์ตœ์ข… ์œ„์น˜"), IndexAtPhaseEnd == FTileIndex(4, 3)); + TestEqual(TEXT("[Case2] ๋ฐœํŒ ์ˆ˜๋ช… ์ฐจ๊ฐ"), Trap->GetRemainingTriggerCount(), 0); + TestEqual(TEXT("[Case2] ์‹œ์ „์ž ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mPhaseEndCount, 1); + TestEqual(TEXT("[Case2] ์‹œ์ „์ž ์Šคํ‚ฌ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mSkillEndCount, 1); + } + + /* Case3: ๋ฉด์—ญ */ + AddInfo(TEXT("=== Case3: ๊ฐ•์ œ์ด๋™ ๋ฉด์—ญ ๋Œ€์ƒ -> ์ œ์ž๋ฆฌ, ํŽ˜์ด์ฆˆ/์Šคํ‚ฌ ์ •์ƒ ์ข…๋ฃŒ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + UnitA->GetAttributeComponentModel()->AddLooseGameplayTag(EffectTags::GameplayEffect_StatusEffect_RoundDuration_Buff_ForcedMovementImmunity); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + + Fixture.Cast(); + + TestTrue(TEXT("[Case3] A ์ œ์ž๋ฆฌ (3,2)"), UnitA->GetTileTransform().mIndex == FTileIndex(3, 2)); + TestEqual(TEXT("[Case3] ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mPhaseEndCount, 1); + TestEqual(TEXT("[Case3] ์Šคํ‚ฌ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mSkillEndCount, 1); + TestFalse(TEXT("[Case3] ์Šคํ‚ฌ ์ข…๋ฃŒ ์ƒํƒœ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSkillForcedMoveSyncLiveTests, + "P_RD.SRPG.SkillComponent.ForcedMoveSync.Live", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter +) + +/** + * @brief ๋ผ์ด๋ธŒ ํ‰๋‚ด(์Šคํ…/๋ชจ์…˜ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ณด์œ ) ๋‹จ๊ณ„๋ณ„ ์ง„ํ–‰ ๊ฒ€์ฆ + * 1) ์Šคํ…์„ ํ•˜๋‚˜์”ฉ ํ’€ ๋•Œ๋งˆ๋‹ค ์œ„์น˜๊ฐ€ ๋ฐ”๋€Œ๊ณ , ๋‹ค ๋ฐ€๋ ค์•ผ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ, ๋ชจ์…˜์ด ํ’€๋ ค์•ผ ์Šคํ‚ฌ ์ข…๋ฃŒ + * 2) ๋ชจ์…˜์ด ๋จผ์ € ๋๋‚˜๋„ ์Šคํ‚ฌ์€ ์•ˆ ๋๋‚˜๊ณ , ๋ฐ€๋ฆผ์ด ๋๋‚œ ๋’ค ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ -> ์Šคํ‚ฌ ์ข…๋ฃŒ (๋ณด๋ฅ˜ -> ์žฌ๊ฐœ) + * 3) ๋ฐ€๋‹น ๋Œ€๊ธฐ ์ค‘ ๋‘ ๋ฒˆ์งธ ๋…ธํ‹ฐํŒŒ์ด๋Š” ๋ฌด์‹œ + */ +bool FSkillForcedMoveSyncLiveTests::RunTest(const FString& Parameters) +{ + FTestObjectScope Scope; + + UWorld* World = GetAnyGameWorldForForcedMoveTests(); + if (World == nullptr) + { + World = GWorld; + } + if (TestNotNull(TEXT("์œ ํšจํ•œ UWorld"), World) == false) + { + return false; + } + + /* Case1: ํŽ˜์ด์ฆˆ๊ฐ€ ๋ฐ€๋ฆผ์„ ๊ธฐ๋‹ค๋ฆผ */ + AddInfo(TEXT("=== Case1: ์Šคํ… 1 -> (4,2), ์Šคํ… 2 -> (5,2) ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ, ๋ชจ์…˜ ํ•ด์ œ -> ์Šคํ‚ฌ ์ข…๋ฃŒ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + FStepHolder StepsA; + StepsA.Bind(UnitA); + FMotionHolder Motion; + Motion.Bind(Fixture.Caster); + + Fixture.Cast(); + TestTrue(TEXT("[Case1] ์‹œ์ „ ํ›„ ๋ชจ์…˜ ๋ฐฐ๋ฆฌ์–ด ๋ณด์œ "), Motion.mHeld.IsValid()); + TestEqual(TEXT("[Case1] ๋…ธํ‹ฐํŒŒ์ด ์ „ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 0"), Recorder.mPhaseEndCount, 0); + + Motion.FireHitLogic(); + TestTrue(TEXT("[Case1] ๋…ธํ‹ฐํŒŒ์ด ์งํ›„ A ๋…ผ๋ฆฌ ์œ„์น˜ (4,2)"), UnitA->GetTileTransform().mIndex == FTileIndex(4, 2)); + TestEqual(TEXT("[Case1] ๋…ธํ‹ฐํŒŒ์ด ์งํ›„ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 0"), Recorder.mPhaseEndCount, 0); + + StepsA.ReleaseNext(); + TestTrue(TEXT("[Case1] ์Šคํ… 1 ํ•ด์ œ ํ›„ A (5,2)"), UnitA->GetTileTransform().mIndex == FTileIndex(5, 2)); + TestEqual(TEXT("[Case1] ์Šคํ… 1 ํ•ด์ œ ํ›„ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 0"), Recorder.mPhaseEndCount, 0); + + StepsA.ReleaseNext(); + TestEqual(TEXT("[Case1] ์Šคํ… 2 ํ•ด์ œ ํ›„ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1"), Recorder.mPhaseEndCount, 1); + TestEqual(TEXT("[Case1] ๋ชจ์…˜ ํ•ด์ œ ์ „ ์Šคํ‚ฌ ์ข…๋ฃŒ 0"), Recorder.mSkillEndCount, 0); + + Motion.Release(); + TestEqual(TEXT("[Case1] ๋ชจ์…˜ ํ•ด์ œ ํ›„ ์Šคํ‚ฌ ์ข…๋ฃŒ 1"), Recorder.mSkillEndCount, 1); + TestFalse(TEXT("[Case1] ์Šคํ‚ฌ ์ข…๋ฃŒ ์ƒํƒœ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + /* Case2: ์—ฐ์ถœ์ด ๋จผ์ € ๋๋‚จ */ + AddInfo(TEXT("=== Case2: ๋…ธํ‹ฐํŒŒ์ด ํ›„ ๋ชจ์…˜ ๋จผ์ € ํ•ด์ œ -> ์Šคํ‚ฌ ์ข…๋ฃŒ 0. ์Šคํ… ๋‹ค ํ’€๋ฉด ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ > ์Šคํ‚ฌ ์ข…๋ฃŒ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + FStepHolder StepsA; + StepsA.Bind(UnitA); + FMotionHolder Motion; + Motion.Bind(Fixture.Caster); + + Fixture.Cast(); + Motion.FireHitLogic(); + Motion.Release(); + + TestEqual(TEXT("[Case2] ๋ชจ์…˜ ํ•ด์ œ ํ›„์—๋„ ์Šคํ‚ฌ ์ข…๋ฃŒ 0 (๋ฐ€๋ฆผ ๋Œ€๊ธฐ๋กœ ๋ณด๋ฅ˜)"), Recorder.mSkillEndCount, 0); + TestTrue(TEXT("[Case2] ์Šคํ‚ฌ ํ™œ์„ฑ ์œ ์ง€"), Fixture.SkillComp->IsAnySkillActivated()); + + StepsA.ReleaseAll(); + + TestTrue(TEXT("[Case2] A (5,2) ๋„์ฐฉ"), UnitA->GetTileTransform().mIndex == FTileIndex(5, 2)); + TestEqual(TEXT("[Case2] ์ด๋ฒคํŠธ ์ˆœ์„œ"), Recorder.Joined(), FString(TEXT("PhaseEnd > SkillEnd"))); + TestFalse(TEXT("[Case2] ์Šคํ‚ฌ ์ข…๋ฃŒ ์ƒํƒœ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + /* Case3: ๋Œ€๊ธฐ ์ค‘ ๋…ธํ‹ฐํŒŒ์ด ๋ฌด์‹œ */ + AddInfo(TEXT("=== Case3: ์Šคํ… ๋ณด์œ  ์ค‘ ๋…ธํ‹ฐํŒŒ์ด 2ํšŒ -> ๋‘ ๋ฒˆ์งธ ๋ฌด์‹œ, ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1ํšŒ, ์Šคํ‚ฌ ์ •์ƒ ์ข…๋ฃŒ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + FStepHolder StepsA; + StepsA.Bind(UnitA); + FMotionHolder Motion; + Motion.Bind(Fixture.Caster); + + Fixture.Cast(); + Motion.FireHitLogic(); + Motion.FireHitLogic(); + + TestEqual(TEXT("[Case3] ๋‘ ๋ฒˆ์งธ ๋…ธํ‹ฐํŒŒ์ด ํ›„์—๋„ ๋ณด์œ  ์Šคํ… 1๊ฐœ (์ƒˆ ์ด๋™ ์—†์Œ)"), StepsA.mHeld.Num(), 1); + + StepsA.ReleaseAll(); + Motion.Release(); + + TestTrue(TEXT("[Case3] A (5,2) ๋„์ฐฉ"), UnitA->GetTileTransform().mIndex == FTileIndex(5, 2)); + TestEqual(TEXT("[Case3] ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mPhaseEndCount, 1); + TestEqual(TEXT("[Case3] ์Šคํ‚ฌ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mSkillEndCount, 1); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSkillForcedMoveSyncSequentialTests, + "P_RD.SRPG.SkillComponent.ForcedMoveSync.Sequential", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter +) + +/** + * @brief ๊ด‘์—ญ ๋ฐ€์น˜๊ธฐ ์ˆœ์ฐจ ์ถœ๋ฐœ ๊ฒ€์ฆ + * 1) ๋…ธํ‹ฐํŒŒ์ด ์งํ›„ ํ•œ ๋ช…๋งŒ ์ถœ๋ฐœ. ๊ทธ ์œ ๋‹›์ด ๋‹ค ๋ฐ€๋ฆฐ ๋’ค ๋‹ค์Œ ์œ ๋‹› ์ถœ๋ฐœ. ๋‘˜ ๋‹ค ๋๋‚˜์•ผ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ + * 2) ์ผ์ง์„  ๋‘ ๋ช…: ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ตœ์ข… ์œ„์น˜ == ๋ผ์ด๋ธŒ ํ‰๋‚ด ์ตœ์ข… ์œ„์น˜ + */ +bool FSkillForcedMoveSyncSequentialTests::RunTest(const FString& Parameters) +{ + FTestObjectScope Scope; + + UWorld* World = GetAnyGameWorldForForcedMoveTests(); + if (World == nullptr) + { + World = GWorld; + } + if (TestNotNull(TEXT("์œ ํšจํ•œ UWorld"), World) == false) + { + return false; + } + + /* Case1: ์ˆœ์ฐจ ์ถœ๋ฐœ */ + AddInfo(TEXT("=== Case1: A (3,2), C (2,3) -> ํ•œ ๋ช…์”ฉ ์ถœ๋ฐœ, ๋‘˜ ๋‹ค ๋๋‚˜์•ผ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ ===")); + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + UMockGimmickVictimUnitModel* UnitC = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(2, 3), ETileActorDirection::Forward)); + + FEventRecorder Recorder; + Recorder.BindSkill(Fixture.SkillComp); + FStepHolder StepsA; + StepsA.Bind(UnitA); + FStepHolder StepsC; + StepsC.Bind(UnitC); + FMotionHolder Motion; + Motion.Bind(Fixture.Caster); + + Fixture.Cast(); + Motion.FireHitLogic(); + + // ์–ด๋А ์ชฝ์ด ๋จผ์ €์ธ์ง€๋Š” ๋Œ€์ƒ ๋ชฉ๋ก ์ˆœ์„œ์— ๋‹ฌ๋ ธ์œผ๋ฏ€๋กœ, ์ถœ๋ฐœํ•œ ์ชฝ์„ First๋กœ ์žก์Œ + const bool IsAFirst = StepsA.IsHolding(); + FStepHolder& First = IsAFirst ? StepsA : StepsC; + FStepHolder& Second = IsAFirst ? StepsC : StepsA; + TestTrue(TEXT("[Case1] ๋…ธํ‹ฐํŒŒ์ด ์งํ›„ ํ•œ ๋ช…์€ ์ถœ๋ฐœ"), First.IsHolding()); + TestFalse(TEXT("[Case1] ๋…ธํ‹ฐํŒŒ์ด ์งํ›„ ๋‹ค๋ฅธ ํ•œ ๋ช…์€ ๋Œ€๊ธฐ"), Second.IsHolding()); + + First.ReleaseAll(); + TestTrue(TEXT("[Case1] ์ฒซ ์œ ๋‹› ์™„๋ฃŒ ํ›„ ๋‹ค์Œ ์œ ๋‹› ์ถœ๋ฐœ"), Second.IsHolding()); + TestEqual(TEXT("[Case1] ์ฒซ ์œ ๋‹› ์™„๋ฃŒ ์‹œ์  ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 0"), Recorder.mPhaseEndCount, 0); + + Second.ReleaseAll(); + TestEqual(TEXT("[Case1] ๋‘˜ ๋‹ค ์™„๋ฃŒ ํ›„ ํŽ˜์ด์ฆˆ ์ข…๋ฃŒ 1"), Recorder.mPhaseEndCount, 1); + + Motion.Release(); + TestTrue(TEXT("[Case1] A (5,2) ๋„์ฐฉ"), UnitA->GetTileTransform().mIndex == FTileIndex(5, 2)); + TestTrue(TEXT("[Case1] C (2,5) ๋„์ฐฉ"), UnitC->GetTileTransform().mIndex == FTileIndex(2, 5)); + TestEqual(TEXT("[Case1] ์Šคํ‚ฌ ์ข…๋ฃŒ 1ํšŒ"), Recorder.mSkillEndCount, 1); + } + + /* Case2: ์‹œ๋ฎฌ๋ ˆ์ด์…˜ == ๋ผ์ด๋ธŒ */ + AddInfo(TEXT("=== Case2: A (3,2), B (4,2) ์ผ์ง์„  -> ์‹œ๋ฎฌ๋ ˆ์ด์…˜๊ณผ ๋ผ์ด๋ธŒ ํ‰๋‚ด์˜ ์ตœ์ข… ์œ„์น˜ ๋™์ผ ===")); + { + // ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (๊ตฌ๋…์ž ์—†์Œ) + FTileIndex SimA; + FTileIndex SimB; + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + UMockGimmickVictimUnitModel* UnitB = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(4, 2), ETileActorDirection::Forward)); + + Fixture.Cast(); + + SimA = UnitA->GetTileTransform().mIndex; + SimB = UnitB->GetTileTransform().mIndex; + TestFalse(TEXT("[Case2] ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์Šคํ‚ฌ ์ข…๋ฃŒ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + // ๋ผ์ด๋ธŒ ํ‰๋‚ด (์Šคํ… ๋ณด์œ  ํ›„ ๋“ค์–ด์˜ค๋Š” ์ˆœ์„œ๋Œ€๋กœ ํ•ด์ œ) + FTileIndex LiveA; + FTileIndex LiveB; + { + FSyncFixture Fixture = MakeSyncFixture(World, Scope, MakeAreaPushSkillData(World, Scope, 2)); + UMockGimmickVictimUnitModel* UnitA = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(3, 2), ETileActorDirection::Forward)); + UMockGimmickVictimUnitModel* UnitB = MakeVictim(World, Scope, Fixture.TileMap,FTileTransform(FTileIndex(4, 2), ETileActorDirection::Forward)); + + FStepHolder StepsA; + StepsA.Bind(UnitA); + FStepHolder StepsB; + StepsB.Bind(UnitB); + FMotionHolder Motion; + Motion.Bind(Fixture.Caster); + + Fixture.Cast(); + Motion.FireHitLogic(); + + // ํ•œ ๋ฒˆ์— ํ•œ ๋ช…๋งŒ ์›€์ง์ด๋ฏ€๋กœ ์žกํžŒ ์Šคํ…์„ ์ฐพ์•„ ํ’€๊ธฐ๋ฅผ ๋ฐ˜๋ณต + while (StepsA.ReleaseNext() == true || StepsB.ReleaseNext() == true) + { + } + Motion.Release(); + + LiveA = UnitA->GetTileTransform().mIndex; + LiveB = UnitB->GetTileTransform().mIndex; + TestFalse(TEXT("[Case2] ๋ผ์ด๋ธŒ ์Šคํ‚ฌ ์ข…๋ฃŒ"), Fixture.SkillComp->IsAnySkillActivated()); + } + + TestTrue(TEXT("[Case2] A ์ตœ์ข… ์œ„์น˜ ๋™์ผ"), SimA == LiveA); + TestTrue(TEXT("[Case2] B ์ตœ์ข… ์œ„์น˜ ๋™์ผ"), SimB == LiveB); + AddInfo(FString::Printf(TEXT("[Case2] A (%d,%d) B (%d,%d)"), SimA.mX, SimA.mY, SimB.mX, SimB.mY)); + } + + return true; +} + +#if WITH_EDITOR + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FSkillForcedMoveSyncDataValidationTests, + "P_RD.SRPG.SkillComponent.ForcedMoveSync.DataValidation", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter +) + +/** + * @brief ๋ฐ€๋‹น ๋ฐฐ์น˜ ์ˆœ์„œ ๊ฒ€์ฆ ๊ฒฝ๊ณ  + * 1) ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ๊ฐ€ ์•„๋‹Œ ๊ณณ์˜ Push -> ๊ฒฝ๊ณ  + * 2) ๊ฐ™์€ ํŽ˜์ด์ฆˆ์—์„œ Push ๋’ค์— ๋‹ค๋ฅธ ์ดํŽ™ํŠธ -> ๊ฒฝ๊ณ  + * 3) ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ์˜ ๋งˆ์ง€๋ง‰ ์ดํŽ™ํŠธ -> ๊ฒฝ๊ณ  ์—†์Œ + */ +bool FSkillForcedMoveSyncDataValidationTests::RunTest(const FString& Parameters) +{ + FTestObjectScope Scope; + + UWorld* World = GetAnyGameWorldForForcedMoveTests(); + if (World == nullptr) + { + World = GWorld; + } + if (TestNotNull(TEXT("์œ ํšจํ•œ UWorld"), World) == false) + { + return false; + } + + // @brief ๊ฒ€์ฆ ์‹คํ–‰ ํ›„ ๊ฒฝ๊ณ  ์ˆ˜ + auto CountWarnings = [](const UStaticSkillData* SkillData) -> int32 + { + FDataValidationContext Context; + SkillData->IsDataValid(Context); + return Context.GetNumWarnings(); + }; + + /* Case1: ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ ์•„๋‹Œ ๊ณณ */ + AddInfo(TEXT("=== Case1: ํŽ˜์ด์ฆˆ 2๊ฐœ, Push๊ฐ€ 0๋ฒˆ ํŽ˜์ด์ฆˆ -> ๊ฒฝ๊ณ  ===")); + { + UStaticSkillData* SkillData = MakeSkillDataBase(World, Scope, EEffectPattern::Single, 0); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakePushLayer(1)); + SkillData->mSkillPhaseLayers.AddDefaulted(); + SkillData->mSkillPhaseLayers[1].mSkillEffectLayers.Add(MakeStunLayer()); + + TestTrue(TEXT("[Case1] ๊ฒฝ๊ณ  1๊ฐœ ์ด์ƒ"), CountWarnings(SkillData) >= 1); + } + + /* Case2: Push ๋’ค์— ๋‹ค๋ฅธ ์ดํŽ™ํŠธ */ + AddInfo(TEXT("=== Case2: ํŽ˜์ด์ฆˆ 1๊ฐœ, Push ๋’ค์— Stun -> ๊ฒฝ๊ณ  ===")); + { + UStaticSkillData* SkillData = MakeSkillDataBase(World, Scope, EEffectPattern::Single, 0); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakePushLayer(1)); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakeStunLayer()); + + TestTrue(TEXT("[Case2] ๊ฒฝ๊ณ  1๊ฐœ ์ด์ƒ"), CountWarnings(SkillData) >= 1); + } + + /* Case3: ๊ทœ์น™ ์ค€์ˆ˜ */ + AddInfo(TEXT("=== Case3: ํŽ˜์ด์ฆˆ 2๊ฐœ, ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ฆˆ์˜ ๋งˆ์ง€๋ง‰์ด Push -> ๊ฒฝ๊ณ  ์—†์Œ ===")); + { + UStaticSkillData* SkillData = MakeSkillDataBase(World, Scope, EEffectPattern::Single, 0); + SkillData->mSkillPhaseLayers[0].mSkillEffectLayers.Add(MakeStunLayer()); + SkillData->mSkillPhaseLayers.AddDefaulted(); + SkillData->mSkillPhaseLayers[1].mSkillEffectLayers.Add(MakeStunLayer()); + SkillData->mSkillPhaseLayers[1].mSkillEffectLayers.Add(MakePushLayer(1)); + + TestEqual(TEXT("[Case3] ๊ฒฝ๊ณ  0๊ฐœ"), CountWarnings(SkillData), 0); + } + + return true; +} + +#endif diff --git a/Source/P_RDTests/SRPGFramework/BoardActorMoveTests.cpp b/Source/P_RDTests/SRPGFramework/BoardActorMoveTests.cpp index 8e0895457..baf393294 100644 --- a/Source/P_RDTests/SRPGFramework/BoardActorMoveTests.cpp +++ b/Source/P_RDTests/SRPGFramework/BoardActorMoveTests.cpp @@ -11,6 +11,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" // UMockPlayerUnitModel @@ -84,6 +85,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FBoardActorMoveStepBarrierTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorld(); if (World == nullptr) { @@ -97,7 +100,7 @@ bool FBoardActorMoveStepBarrierTests::RunTest(const FString& Parameters) // OnStartMoveStep() ๊ตฌ๋…์ž๋ฅผ ์—†๊ฒŒ ํ•ด์„œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜๋ชจ๋“œ ํ…Œ์ŠคํŠธ AddInfo(TEXT("=== Case1: ๊ตฌ๋…์ž ์—†์Œ -> ์‹œ๋ฎฌ๋ ˆ์ด์…˜๋ชจ๋“œ -> ์ฆ‰์‹œ ์™„๋ฃŒ ===")); { - UMockPlayerUnitModel* Unit = NewObject(World); + UMockPlayerUnitModel* Unit = Scope.New(World); bool bFinished = false; { @@ -116,7 +119,7 @@ bool FBoardActorMoveStepBarrierTests::RunTest(const FString& Parameters) // OnStartMoveStep ๊ตฌ๋…์ž๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋ผ์ด๋ธŒ๋ชจ๋“œ ํ…Œ์ŠคํŠธ AddInfo(TEXT("=== Case2: ๊ตฌ๋…์ž ์žˆ์Œ -> ๋ผ์ด๋ธŒ๋ชจ๋“œ -> ๊ตฌ๋…์ž๊ฐ€ ๋†“์œผ๋ฉด ์™„๋ฃŒ ===")); { - UMockPlayerUnitModel* Unit = NewObject(World); + UMockPlayerUnitModel* Unit = Scope.New(World); // ๋ทฐ ์—ญํ• ์˜ ๊ตฌ๋…์ž (Barrier๋ฅผ ๋ณด๊ด€ํ•˜๊ณ  ์žˆ์–ด์„œ ์ฐธ์กฐ๊ฐ€ 0์ด ์•ˆ ๋˜๊ฒŒ ์œ ์ง€) TSharedPtr HeldBarrier; diff --git a/Source/P_RDTests/SRPGFramework/BoardActorRotateTests.cpp b/Source/P_RDTests/SRPGFramework/BoardActorRotateTests.cpp index 352fd813d..9d0a49969 100644 --- a/Source/P_RDTests/SRPGFramework/BoardActorRotateTests.cpp +++ b/Source/P_RDTests/SRPGFramework/BoardActorRotateTests.cpp @@ -12,6 +12,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" // UMockPlayerUnitModel @@ -55,6 +56,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( */ bool FBoardActorRotateTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorld(); if (World == nullptr) { @@ -66,10 +69,10 @@ bool FBoardActorRotateTests::RunTest(const FString& Parameters) } // ํƒ€์ผ๋งต๊ณผ ์œ ๋‹› ์ค€๋น„ - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(5, 5); - UMockPlayerUnitModel* Unit = NewObject(World); + UMockPlayerUnitModel* Unit = Scope.New(World); TileMap->PlaceActor(FTileTransform(FTileIndex(2, 2), ETileActorDirection::Forward), Unit); // ๋ทฐ ์—ญํ• ์˜ ๊ตฌ๋…์ž (๋ฐœํ–‰ ํšŸ์ˆ˜์™€ ๋ฐฐ๋ฆฌ์–ด ์ˆ˜์‹  ๊ธฐ๋ก) diff --git a/Source/P_RDTests/SRPGFramework/EnemyTurnPlannerTests.cpp b/Source/P_RDTests/SRPGFramework/EnemyTurnPlannerTests.cpp index d1ad9a252..8536bcfd9 100644 --- a/Source/P_RDTests/SRPGFramework/EnemyTurnPlannerTests.cpp +++ b/Source/P_RDTests/SRPGFramework/EnemyTurnPlannerTests.cpp @@ -14,6 +14,8 @@ * ์ž๊ธฐ ๋ฒ„ํ”„: ๋ฒ„ํ”„ ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์œผ๋ฉด ๊ณต๊ฒฉ ํ™•์ •(Case8-1), ๋ฒ„ํ”„ ์šฐ์„ ์ˆœ์œ„ ๋†’์œผ๋ฉด ๋น„์šฉ ๋–ผ๊ณ  ์„ฑํ–ฅ ์ด๋™ ํ›„ ๋ฒ„ํ”„(Case8-2), * ๋ฒ„ํ”„๋งŒ ๋ณด์œ  ์‹œ ์„ฑํ–ฅ ์ด๋™(Case8-3), ๊ณต๊ฒฉ ํ™•์ • ํ›„ ์‚ฌ๊ฑฐ๋ฆฌ ๋ฐ–์ด๋ฉด ๋ฒ„ํ”„๋กœ ์•ˆ ๋ฐ”๊พธ๊ณ  ์ ‘๊ทผ(Case8-4), * ๊ณต๊ฒฉ ํ™•์ • ํ›„ ๋น„์šฉ ๋ถ€์กฑ์ด๋ฉด ๋ฒ„ํ”„ ์—†์ด ์„ ์ ์ด๋™(Case8-5). + * ์ด๋™ ์Šคํ‚ฌ: ๊ฑท์ง€ ์•Š๊ณ  ๋นˆ ํƒ€์ผ ์กฐ์ค€(Case9-1), ์ ์œ  ํƒ€์ผ ์ œ์™ธ(Case9-2), ๊ฒฝ๋กœ ์—†์œผ๋ฉด ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ๋กœ ๋น„๊ต(Case9-3), + * ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„๋กœ ๊ธฐ์ค€ ํƒ€๊ฒŸ ์„ ์ •(Case9-4), ๋นˆ ํƒ€์ผ ์—†์œผ๋ฉด ์‹œ์ „ ์—†์ด ์ ‘๊ทผ(Case9-5). * @note * ์žฅ์• ๋ฌผ์€ ์•„์ง ๊ตฌํ˜„์ฒด๊ฐ€ ์—†์–ด์„œ ์ œ์™ธ. ๋‚˜์ค‘์— ๊ตฌํ˜„์ฒด๊ฐ€ ๋‚˜์˜ค๋ฉด ์œ ๋‹›ํ…Œ์ŠคํŠธ์— ์ถ”๊ฐ€ ํ•„์š” * @author ์ด๋ฌธํ™˜ @@ -21,6 +23,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "SRPGFramework/EnemyTurnPlannerTestsHelper.h" @@ -84,16 +87,16 @@ namespace return nullptr; } - // @brief ํ…Œ์ŠคํŠธ์šฉ ์ผ๋ฐ˜๊ณต๊ฒฉ ์Šคํ‚ฌ ์ƒ์„ฑ (KeepAlive์— ๋“ฑ๋กํ•ด GC ๋ฐฉ์ง€) + // @brief ํ…Œ์ŠคํŠธ์šฉ ์ผ๋ฐ˜๊ณต๊ฒฉ ์Šคํ‚ฌ ์ƒ์„ฑ (์Šค์ฝ”ํ”„์— ๋“ฑ๋กํ•ด GC ๋ฐฉ์ง€ + ์ข…๋ฃŒ ์‹œ ํŒŒ๊ดด) // @param EffectPattern ์˜ํ–ฅ ๋ฒ”์œ„ ํŒจํ„ด (Single ์กฐ์ค€ ์Šคํ‚ฌ์€ ์ด ๋ฒ”์œ„๋กœ ํƒ€๊ฒฉ ์—ฌ๋ถ€๊ฐ€ ๊ฒฐ์ •๋จ) // @param EffectArea ์˜ํ–ฅ ๋ฒ”์œ„ ํฌ๊ธฐ // @param SkillCost ์‹œ์ „ ๋น„์šฉ (ํ”Œ๋ž˜๋„ˆ AP ํŒ์ •์šฉ, 0์ด๋ฉด ๋น„์šฉ ์—†์Œ) // @param SkillType ์Šคํ‚ฌ ํƒ€์ž… (Attack์€ ๊ณต๊ฒฉ ํ›„๋ณด, Spell์€ ์ž๊ธฐ ๋ฒ„ํ”„) - UStaticSkillData* MakeSkill(UWorld* World, TArray& KeepAlive, EAimPattern AimPattern, int32 AimRange, + UStaticSkillData* MakeSkill(UWorld* World, FTestObjectScope& Scope, EAimPattern AimPattern, int32 AimRange, EEffectPattern EffectPattern = EEffectPattern::Single, int32 EffectArea = 0, int32 SkillCost = 0, ESkillType SkillType = ESkillType::Attack) { - UStaticUnitSkillData* Skill = NewObject(World); + UStaticUnitSkillData* Skill = Scope.New(World); Skill->mJobType = EUnitJobType::Common; // ์ง์—… ๋ฌด๊ด€ (์ง์—… ๋ถˆ์ผ์น˜๋ฉด SetSkill์ด ์žฅ์ฐฉ ๊ฑฐ๋ถ€) Skill->mSkillType = SkillType; Skill->mRequiredActionPoint = SkillCost; @@ -106,13 +109,11 @@ namespace Skill->mEffectBlockerMask = static_cast(ETileLayerFlag::Obstacle | ETileLayerFlag::Unit); // ๋ชจ์…˜ ๋ ˆ์ด์–ด ์—†์œผ๋ฉด FSkillEntry::IsValid()๊ฐ€ ๋ฏธ์žฅ์ฐฉ์œผ๋กœ ํŒ์ •ํ•˜๋ฏ€๋กœ ๋”๋ฏธ 1๊ฐœ ์ถ”๊ฐ€ Skill->mSkillPhaseLayers.AddDefaulted(); - Skill->AddToRoot(); - KeepAlive.Add(Skill); return Skill; } // @brief ์  ์œ ๋‹›์˜ ํ•œ ํ„ด์„ ๊ณ„ํšํ•ด ์ปค๋งจ๋“œ ๋ชฉ๋ก ๋ฐ˜ํ™˜ - // @param KeepAlive SkillComponent๊ฐ€ ์•ฝ์ฐธ์กฐ๋ผ GC ์•ˆ๋‹นํ•˜๋„๋ก ๋ถ™์žก์•„๋‘๋Š” ์žฅ์น˜ + // @param Scope ์ƒ์„ฑ ๊ฐ์ฒด ๋“ฑ๋ก (GC ๋ฐฉ์ง€ + ์ข…๋ฃŒ ์‹œ ํŒŒ๊ดด) // @param AimPattern ์Šคํ‚ฌ ์กฐ์ค€ ํŒจํ„ด (Cross/Star ์ง์‚ฌ๋Š” ์‹œ์•ผ ๊ฒ€์‚ฌ ๊ฒฝ๋กœ๋ฅผ ํƒœ์›€) // @param Slot1AimRange ์Šฌ๋กฏ 1์— ์žฅ์ฐฉํ•  Square ์Šคํ‚ฌ์˜ ์‚ฌ๊ฑฐ๋ฆฌ (0์ด๋ฉด ๋ฏธ์žฅ์ฐฉ. ๋‹ค์ค‘ ์Šคํ‚ฌ ์„ ํƒ ๊ฒ€์ฆ์šฉ) // @param BlockerIndex ๊ธธ/์‹œ์•ผ๋ฅผ ๋ง‰๋Š” ์ œ3์˜ ์œ ๋‹› ๋ฐฐ์น˜ ์ขŒํ‘œ (Invalid๋ฉด ๋ฏธ๋ฐฐ์น˜. ์šฐํšŒ ์ ‘๊ทผ ๊ฒ€์ฆ์šฉ) @@ -128,7 +129,7 @@ namespace // @param Slot1Cooldown ์Šฌ๋กฏ 1์„ ์ฟจ๋‹ค์šด ์ƒํƒœ๋กœ ๋‘˜์ง€ (์ฟจ๋‹ค์šด์ด๋ฉด ์ฐจ์ˆœ์œ„ ๊ฒ€์ฆ์šฉ) TArray> Plan( UWorld* World, - TArray& KeepAlive, + FTestObjectScope& Scope, EMoveTendency Tendency, int32 MoveRange, int32 AimRange, @@ -151,16 +152,16 @@ namespace bool Slot1Cooldown = false) { // ํƒ€์ผ๋งต ์ƒ์„ฑ - UTileMapModel* TileMap = NewObject(World); + UTileMapModel* TileMap = Scope.New(World); TileMap->SetDimensions(TileMapWidth, TileMapHeight); // ํ”Œ๋ ˆ์ด์–ด์œ ๋‹› ์ƒ์„ฑ (๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ๊ณง ํƒ€๊ฒŸ ์ธ๋ฑ์Šค) TArray Players; - UMockPlayerUnitModel* Player = NewObject(World); + UMockPlayerUnitModel* Player = Scope.New(World); Players.Add(Player); // ์ ์œ ๋‹› ์ƒ์„ฑ - UMockEnemyUnitModel* Enemy = NewObject(World); + UMockEnemyUnitModel* Enemy = Scope.New(World); Enemy->Initialize(); Enemy->BeginPlay(); Enemy->SetMoveTendency(Tendency); @@ -177,12 +178,12 @@ namespace // ์Šคํ‚ฌ ์ถ”๊ฐ€: ์ผ๋ฐ˜๊ณต๊ฒฉ ๊ณ„์—ด (๋ฒ„ํ”„๋งŒ ๊ฐ€์ง„ ์  ๊ฒ€์ฆ ์‹œ ์ƒ๋žต) if (HasAttack == true) { - Enemy->GetSkillComponentModel()->SetSkill(0, MakeSkill(World, KeepAlive, AimPattern, AimRange, EffectPattern, EffectArea, SkillCost)); + Enemy->GetSkillComponentModel()->SetSkill(0, MakeSkill(World, Scope, AimPattern, AimRange, EffectPattern, EffectArea, SkillCost)); } // ์Šฌ๋กฏ 1 ์Šคํ‚ฌ(์˜ต์…˜): ๋‹ค์ค‘ ์Šคํ‚ฌ ์„ ํƒ ๊ฒ€์ฆ์šฉ (์šฐ์„ ์ˆœ์œ„/์ฟจ๋‹ค์šด ์ง€์ • ๊ฐ€๋Šฅ) if (Slot1AimRange > 0) { - Enemy->GetSkillComponentModel()->SetSkill(1, MakeSkill(World, KeepAlive, EAimPattern::Square, Slot1AimRange)); + Enemy->GetSkillComponentModel()->SetSkill(1, MakeSkill(World, Scope, EAimPattern::Square, Slot1AimRange)); Enemy->SetSkillPriority(1, Slot1Priority); if (Slot1Cooldown == true) { @@ -192,7 +193,7 @@ namespace // ์Šฌ๋กฏ 2 ์ž๊ธฐ ๋ฒ„ํ”„(์˜ต์…˜): Single ์กฐ์ค€, ์˜ํ–ฅ ๋ฒ”์œ„ ์ž๊ธฐ ์นธ if (Slot2SpellCost > 0) { - Enemy->GetSkillComponentModel()->SetSkill(2, MakeSkill(World, KeepAlive, EAimPattern::Single, 0, + Enemy->GetSkillComponentModel()->SetSkill(2, MakeSkill(World, Scope, EAimPattern::Single, 0, EEffectPattern::Single, 0, Slot2SpellCost, ESkillType::Spell)); Enemy->SetSkillPriority(2, Slot2Priority); } @@ -204,7 +205,7 @@ namespace // ๋‘ ๋ฒˆ์งธ ํ”Œ๋ ˆ์ด์–ด(์˜ต์…˜): ๋‹ค์ค‘ ํƒ€๊ฒŸ ์„ ํƒ ๊ฒ€์ฆ์šฉ if (TileMap->IsValidIndex(SecondPlayerIndex)) { - UMockPlayerUnitModel* SecondPlayer = NewObject(World); + UMockPlayerUnitModel* SecondPlayer = Scope.New(World); Players.Add(SecondPlayer); TileMap->PlaceActor(FTileTransform(SecondPlayerIndex), SecondPlayer); } @@ -212,7 +213,7 @@ namespace // ์ฐจ๋‹จ ์œ ๋‹›(์˜ต์…˜): ๊ธธ/์‹œ์•ผ๋ฅผ ๋ง‰๋Š” ์ œ3์˜ ์œ ๋‹› (Unit ๋ ˆ์ด์–ด ์ ์œ ๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ) if (TileMap->IsValidIndex(BlockerIndex)) { - UMockPlayerUnitModel* Blocker = NewObject(World); + UMockPlayerUnitModel* Blocker = Scope.New(World); TileMap->PlaceActor(FTileTransform(BlockerIndex), Blocker); } @@ -223,6 +224,73 @@ namespace return USRPGEnemyTurnPlanner::PlanTurn(Enemy, Players, TileMap, Stream); } + // @brief ์ด๋™ ์Šคํ‚ฌ ํ•˜๋‚˜๋งŒ ๊ฐ€์ง„ ์  ์œ ๋‹›์˜ ํ•œ ํ„ด์„ ๊ณ„ํšํ•ด ์ปค๋งจ๋“œ ๋ชฉ๋ก ๋ฐ˜ํ™˜ + // @param Scope ์ƒ์„ฑ ๊ฐ์ฒด ๋“ฑ๋ก (GC ๋ฐฉ์ง€ + ์ข…๋ฃŒ ์‹œ ํŒŒ๊ดด) + // @param ActionPoint ์  ์œ ๋‹›์˜ ํ–‰๋™๋ ฅ + // @param AimRange ์ด๋™ ์Šคํ‚ฌ์˜ ์กฐ์ค€ ์‚ฌ๊ฑฐ๋ฆฌ (Square ํŒจํ„ด, ๋นˆ ํƒ€์ผ๋งŒ ์กฐ์ค€) + // @param SkillCost ์ด๋™ ์Šคํ‚ฌ์˜ ์‹œ์ „ ๋น„์šฉ + // @param PlayerIndexes ํ”Œ๋ ˆ์ด์–ด ๋ฐฐ์น˜ ์ขŒํ‘œ๋“ค (๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ๊ณง ํƒ€๊ฒŸ ์ธ๋ฑ์Šค) + // @param BlockerIndexes ํƒ€์ผ์„ ์ ์œ ํ•˜๋Š” ์ œ3์˜ ์œ ๋‹› ๋ฐฐ์น˜ ์ขŒํ‘œ๋“ค (ํƒ€๊ฒŸ ์•„๋‹˜. ์ ์œ  ์ œ์™ธ์™€ ๊ฒฝ๋กœ ์ฐจ๋‹จ ๊ฒ€์ฆ์šฉ) + // @param Priority ์ด๋™ ์Šคํ‚ฌ์˜ ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„ (๊ธฐ์ค€ ํƒ€๊ฒŸ ์„ ์ • ๊ฒ€์ฆ์šฉ) + TArray> PlanMoveSkill( + UWorld* World, + FTestObjectScope& Scope, + int32 ActionPoint, + int32 AimRange, + int32 SkillCost, + int32 TileMapWidth, + int32 TileMapHeight, + FTileIndex EnemyIndex, + const TArray& PlayerIndexes, + const TArray& BlockerIndexes = TArray(), + EEnemyTargetPriority Priority = EEnemyTargetPriority::Nearest) + { + // ํƒ€์ผ๋งต ์ƒ์„ฑ + UTileMapModel* TileMap = Scope.New(World); + TileMap->SetDimensions(TileMapWidth, TileMapHeight); + + // ์ ์œ ๋‹› ์ƒ์„ฑ (์‹œ์ „ ๋ถˆ๊ฐ€ ์‹œ ์ ‘๊ทผ ์ด๋™ ๊ฒ€์ฆ์„ ์œ„ํ•ด ๊ทผ๊ฑฐ๋ฆฌ ์„ฑํ–ฅ) + UMockEnemyUnitModel* Enemy = Scope.New(World); + Enemy->Initialize(); + Enemy->BeginPlay(); + Enemy->SetMoveTendency(EMoveTendency::MoveClose); + Enemy->GetAttributeComponentModel()->ApplyModToAttribute(UEnemyUnitAttributeSet::GetActionPointAttribute(), ETacticalModOp::Override, ActionPoint); + + // ์ด๋™ ์Šคํ‚ฌ ์ƒ์„ฑ: ์ ์œ  ํƒ€์ผ์€ ์กฐ์ค€ ๋ถˆ๊ฐ€, ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„๋Š” ์Šคํ‚ฌ DA ๊ฐ’์œผ๋กœ ์ง€์ • + UStaticUnitSkillData* MoveSkill = CastChecked(MakeSkill(World, Scope, EAimPattern::Square, AimRange, + EEffectPattern::Single, 0, SkillCost, ESkillType::Move)); + MoveSkill->mCanAimBoardActor = false; + MoveSkill->mTargetPolicy.mPriority = Priority; + + // ์Šคํ‚ฌ ์Šฌ๋กฏ ํ’€ ํ• ๋‹น ํ›„ ์Šฌ๋กฏ 0์— ์žฅ์ฐฉ + Enemy->GetSkillComponentModel()->SetSkillFrom(TArray>()); + Enemy->GetSkillComponentModel()->SetSkill(0, MoveSkill); + + // ์ ์œ ๋‹› ๋ฐฐ์น˜ + TileMap->PlaceActor(FTileTransform(EnemyIndex), Enemy); + + // ํ”Œ๋ ˆ์ด์–ด์œ ๋‹› ์ƒ์„ฑ ๋ฐ ๋ฐฐ์น˜ (๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ๊ณง ํƒ€๊ฒŸ ์ธ๋ฑ์Šค) + TArray Players; + for (const FTileIndex& PlayerIndex : PlayerIndexes) + { + UMockPlayerUnitModel* Player = Scope.New(World); + Players.Add(Player); + TileMap->PlaceActor(FTileTransform(PlayerIndex), Player); + } + + // ์ฐจ๋‹จ ์œ ๋‹› ๋ฐฐ์น˜ (Unit ๋ ˆ์ด์–ด ์ ์œ ๋งŒ ํ•„์š”ํ•˜๋‹ˆ ํ”Œ๋ ˆ์ด์–ด Mock ์žฌ์‚ฌ์šฉ, ํƒ€๊ฒŸ ๋ชฉ๋ก์—๋Š” ๋„ฃ์ง€ ์•Š์Œ) + for (const FTileIndex& BlockerIndex : BlockerIndexes) + { + UMockPlayerUnitModel* Blocker = Scope.New(World); + TileMap->PlaceActor(FTileTransform(BlockerIndex), Blocker); + } + + // ๊ณ ์ • ์‹œ๋“œ ์ŠคํŠธ๋ฆผ (ํ…Œ์ŠคํŠธ ๊ฒฐ์ •์„ฑ ๋ณด์žฅ) + const FRandomStream Stream(20260710); + + return USRPGEnemyTurnPlanner::PlanTurn(Enemy, Players, TileMap, Stream); + } + // @brief ์ปค๋งจ๋“œ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๊ณ , ๋งˆ์ง€๋ง‰์€ ํ•ญ์ƒ ํ„ด ์ข…๋ฃŒ์ธ ์ง€ ๊ฒ€์ฆ void CheckTail(FAutomationTestBase& Test, const TArray>& Commands, const TCHAR* Label) { @@ -267,6 +335,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + UWorld* World = GetAnyGameWorld(); if (World == nullptr) { @@ -277,9 +347,6 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) return false; } - // ์œ ๋‹›ํ…Œ์ŠคํŠธ ๋™์•ˆ SkillComponent๊ฐ€ GC ๋‹นํ•˜์ง€ ์•Š๋„๋ก ๊ฑธ์–ด๋‘๋Š” ์žฅ์น˜ - TArray KeepAlive; - /** * ์ผ€์ด์Šค ๋ ˆ์ด๋ธ”: CaseX-Y * X = ์ด๋™์„ฑํ–ฅ (1:์›๊ฑฐ๋ฆฌ/MoveAway, 2:๋“ฑ๊ฑฐ๋ฆฌ/HoldRange, 3:๊ทผ๊ฑฐ๋ฆฌ/MoveClose) @@ -296,7 +363,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1-1: ์›๊ฑฐ๋ฆฌ(MoveAway), ์กฐ์ค€ ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 6, 3, 8, 2, FTileIndex(2, 1), FTileIndex(1, 0)); @@ -322,7 +389,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1-2: ์›๊ฑฐ๋ฆฌ(MoveAway) / ์กฐ์ค€ ๋ถˆ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 4, 3, 10, 3, FTileIndex(0, 1), FTileIndex(9, 1)); @@ -338,7 +405,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case1-3: ์›๊ฑฐ๋ฆฌ(MoveAway) / ์ง์‚ฌ / ์ผ์ง์„  ํ›„ํ‡ด ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 6, 4, 8, 1, FTileIndex(1, 0), FTileIndex(0, 0), @@ -365,7 +432,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case2-1: ๋“ฑ๊ฑฐ๋ฆฌ(HoldRange) / ์กฐ์ค€ ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1)); @@ -382,7 +449,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case2-2: ๋“ฑ๊ฑฐ๋ฆฌ(HoldRange) / ์กฐ์ค€ ๋ถˆ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 4, 1, 10, 3, FTileIndex(0, 1), FTileIndex(9, 1)); @@ -398,7 +465,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3-1: ๊ทผ๊ฑฐ๋ฆฌ(MoveClose) / ์กฐ์ค€ ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1)); @@ -420,7 +487,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3-2: ๊ทผ๊ฑฐ๋ฆฌ(MoveClose) / ์ด๋™ ํ›„์—๋„ ์กฐ์ค€ ๋ถˆ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 4, 1, 10, 3, FTileIndex(0, 1), FTileIndex(9, 1)); @@ -437,7 +504,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case3-3: ๊ทผ๊ฑฐ๋ฆฌ(MoveClose) / ๋ชน์— ๋ง‰ํž˜ / ์šฐํšŒ ์ ‘๊ทผ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 2, 4, 8, 2, FTileIndex(2, 1), FTileIndex(0, 1), @@ -456,7 +523,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4-1: ๋‹ค์ค‘ ์Šคํ‚ฌ / ๋™์ˆœ์œ„ ๋žœ๋ค ์„ ํƒ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -479,7 +546,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4-2: ๋‹ค์ค‘ ์Šคํ‚ฌ / ์šฐ์„ ์ˆœ์œ„ ๋†’์€ ์Šฌ๋กฏ ์„ ํƒ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -510,7 +577,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4-3: ๋‹ค์ค‘ ์Šคํ‚ฌ / ์ตœ์šฐ์„  ์Šฌ๋กฏ ์ฟจ๋‹ค์šด์ด๋ฉด ์ฐจ์ˆœ์œ„ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -544,7 +611,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case4-4: ๋‹ค์ค‘ ์Šคํ‚ฌ / ์ตœ์šฐ์„  ์Šฌ๋กฏ ์‚ฌ๊ฑฐ๋ฆฌ ๋ฐ–์ด๋ฉด ์Šคํ‚ฌ ์œ ์ง€ํ•˜๊ณ  ์ ‘๊ทผ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 2, 5, 10, 3, FTileIndex(0, 1), FTileIndex(4, 1), @@ -570,7 +637,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case5-1: ๋‹ค์ค‘ ํ”Œ๋ ˆ์ด์–ด / ์ตœ๊ทผ์ ‘ ํƒ€๊ฒŸ ์„ ํƒ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -596,7 +663,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case5-2: ๋‹ค์ค‘ ํ”Œ๋ ˆ์ด์–ด / ์‹œ์ „ ๊ฐ€๋Šฅํ•œ ํƒ€๊ฒŸ ์šฐ์„  ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 2, 1, 7, 1, FTileIndex(2, 0), FTileIndex(0, 0), @@ -628,7 +695,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case5-3: ๋‹ค์ค‘ ํ”Œ๋ ˆ์ด์–ด / ๊ท ํ˜• ํ›„ํ‡ด ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 2, 3, 7, 1, FTileIndex(2, 0), FTileIndex(0, 0), @@ -659,7 +726,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case5-4: ๋‹ค์ค‘ ํ”Œ๋ ˆ์ด์–ด / ์ตœ๊ทผ์ ‘ ์ ‘๊ทผ ํด๋ฐฑ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 2, 1, 10, 3, FTileIndex(4, 1), FTileIndex(9, 1), @@ -678,7 +745,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case6-1: ์†๋ฐ• / ์ œ์ž๋ฆฌ ์กฐ์ค€ ๊ฐ€๋Šฅ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 6, 3, 8, 2, FTileIndex(2, 1), FTileIndex(1, 0), @@ -700,7 +767,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case6-2: ์†๋ฐ• / ์‚ฌ๊ฑฐ๋ฆฌ ๋ฐ– ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 6, 1, 8, 2, FTileIndex(6, 1), FTileIndex(0, 0), @@ -722,7 +789,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case6-3: ์†๋ฐ• / ๋น„์šฉ ์žˆ๋Š” ์Šคํ‚ฌ ์‹œ์ „ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 6, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -747,7 +814,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case7-1: Single ์กฐ์ค€ / ์˜ํ–ฅ ๋ฒ”์œ„๋กœ ์ธ์ ‘ ํƒ€๊ฒฉ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 0, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -775,7 +842,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case7-2: Single ์กฐ์ค€ / ์ถœ๋ฐœ ์นธ ๋„ˆ๋จธ ํƒ€๊ฒฉ / ์ž๊ธฐ ์ฐจํ ํšŒ๊ท€ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 6, 0, 8, 1, FTileIndex(1, 0), FTileIndex(0, 0), @@ -807,7 +874,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case7-3: Single ์กฐ์ค€ / ์˜ํ–ฅ ๋ฒ”์œ„ ๋ฐ– / ์ ‘๊ทผ ํด๋ฐฑ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 4, 0, 10, 3, FTileIndex(0, 1), FTileIndex(9, 1), @@ -828,7 +895,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case8-1: ๊ณต๊ฒฉ ๊ฐ€๋Šฅ / ๋ฒ„ํ”„ ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ / ๊ณต๊ฒฉ ํ™•์ • ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::HoldRange, + World, Scope, EMoveTendency::HoldRange, 3, 1, 6, 3, FTileIndex(2, 1), FTileIndex(3, 1), @@ -862,7 +929,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case8-2: ๋ฒ„ํ”„ ์šฐ์„ ์ˆœ์œ„ ๋†’์Œ / ๋น„์šฉ ๋–ผ๊ณ  ์„ฑํ–ฅ ์ด๋™ ํ›„ ๋ฒ„ํ”„ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 4, 1, 10, 3, FTileIndex(0, 1), FTileIndex(3, 1), @@ -901,7 +968,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case8-4: ๊ณต๊ฒฉ ํ™•์ • / ์‚ฌ๊ฑฐ๋ฆฌ ๋ฐ– / ๋ฒ„ํ”„๋กœ ์•ˆ ๋ฐ”๊พธ๊ณ  ์ ‘๊ทผ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 3, 1, 10, 3, FTileIndex(0, 1), FTileIndex(9, 1), @@ -928,7 +995,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case8-5: ๊ณต๊ฒฉ ํ™•์ • / ์‹œ์ „ ๋น„์šฉ ๋ถ€์กฑ / ๋ฒ„ํ”„ ์—†์ด ์„ ์ ์ด๋™ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveClose, + World, Scope, EMoveTendency::MoveClose, 4, 1, 10, 3, FTileIndex(0, 1), FTileIndex(3, 1), @@ -962,7 +1029,7 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) AddInfo(TEXT("=== Case8-3: ๋ฒ„ํ”„๋งŒ ๋ณด์œ  / ์„ฑํ–ฅ ์ด๋™ ํ›„ ๋ฒ„ํ”„ ===")); { const TArray> Commands = Plan( - World, KeepAlive, EMoveTendency::MoveAway, + World, Scope, EMoveTendency::MoveAway, 4, 1, 8, 1, FTileIndex(2, 0), FTileIndex(0, 0), @@ -990,10 +1057,126 @@ bool FEnemyTurnPlannerTests::RunTest(const FString& Parameters) } } - // GC ์•ˆ๋‹นํ•˜๋ ค๊ณ  KeepAlive์— ๋งˆ๋‹ฌ์•„๋†จ๋˜ SkillComponent ์—ฐ๊ฒฐ ํ•ด์ œ -> GC ๋Œ€์ƒ - for (UObject* Object : KeepAlive) - if (IsValid(Object)) - Object->RemoveFromRoot(); + /** + * ์ผ€์ด์Šค ๋ ˆ์ด๋ธ”: Case9-Y (์ด๋™ ์Šคํ‚ฌ. ๋นˆ ํƒ€์ผ๋งŒ ์กฐ์ค€ํ•˜๋Š” Square ํŒจํ„ด) + * ์ด๋™ ์Šคํ‚ฌ์€ ๊ฑท์ง€ ์•Š๊ณ  ํ˜„์žฌ ํƒ€์ผ์—์„œ ์‹œ์ „ํ•˜๋ฏ€๋กœ ์ด๋™์ปค๋งจ๋“œ๊ฐ€ ์—†์–ด์•ผ ํ•จ. + * ์ฐฉ์ง€ ํƒ€์ผ์€ ๊ธฐ์ค€ ํƒ€๊ฒŸ ํƒ€์ผ๊นŒ์ง€ 1์ˆœ์œ„ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ, 2์ˆœ์œ„ ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ํƒ€์ผ. + */ + + /** + * Case9-1: ์ด๋™ ์Šคํ‚ฌ / ๋นˆ ํƒ€์ผ ์กฐ์ค€ + * -> ๊ฑท์ง€ ์•Š๊ณ  ๊ธฐ์ค€ ํƒ€๊ฒŸ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋นˆ ํƒ€์ผ์„ ์กฐ์ค€ํ•ด ์‹œ์ „ + * ๋งต (8x1): E(0,0) P(6,0), ์‚ฌ๊ฑฐ๋ฆฌ 3 + * -> ํ›„๋ณด (1,0)(2,0)(3,0) ์ค‘ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ 3์œผ๋กœ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด (3,0) + */ + AddInfo(TEXT("=== Case9-1: ์ด๋™ ์Šคํ‚ฌ / ๋นˆ ํƒ€์ผ ์กฐ์ค€ ===")); + { + const TArray> Commands = PlanMoveSkill( + World, Scope, + /*ActionPoint*/6, /*AimRange*/3, /*SkillCost*/2, + 8, 1, + FTileIndex(0, 0), + { FTileIndex(6, 0) }); + CheckTail(*this, Commands, TEXT("Case9-1")); + TestTrue(TEXT("[Case9-1] ์ด๋™์ปค๋งจ๋“œ ์—†์Œ(์ œ์ž๋ฆฌ ์‹œ์ „)"), FindMoveCommand(Commands) == nullptr); + const FSRPGSkillCastCommand* Cast = FindCast(Commands); + if (TestTrue(TEXT("[Case9-1] ์Šคํ‚ฌ์ปค๋งจ๋“œ ์กด์žฌ"), Cast != nullptr)) + { + TestEqual(TEXT("[Case9-1] ์ด๋™ ์Šคํ‚ฌ ์Šฌ๋กฏ 0 ์„ ํƒ"), Cast->mSkillIndex, 0); + TestTrue(TEXT("[Case9-1] ์กฐ์ค€ ํƒ€์ผ=(3,0)"), Cast->mTargetIndex == FTileIndex(3, 0)); + } + } + + /** + * Case9-2: ์ด๋™ ์Šคํ‚ฌ / ์ ์œ  ํƒ€์ผ ์ œ์™ธ + * -> ๊ธฐ์ค€ ํƒ€๊ฒŸ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํƒ€์ผ์ด ๋‹ค๋ฅธ ์œ ๋‹›์—๊ฒŒ ์ ์œ ๋˜์–ด ์žˆ์œผ๋ฉด ๊ทธ ๋‹ค์Œ์œผ๋กœ ๊ฐ€๊นŒ์šด ๋นˆ ํƒ€์ผ ์„ ํƒ + * ๋งต (8x2): E(0,0) P(4,0) B(3,0), ์‚ฌ๊ฑฐ๋ฆฌ 3 + * -> (3,0)์€ ์ ์œ ๋ผ ์ œ์™ธ, ์šฐํšŒ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ 2์ธ (3,1) + */ + AddInfo(TEXT("=== Case9-2: ์ด๋™ ์Šคํ‚ฌ / ์ ์œ  ํƒ€์ผ ์ œ์™ธ ===")); + { + const TArray> Commands = PlanMoveSkill( + World, Scope, + /*ActionPoint*/6, /*AimRange*/3, /*SkillCost*/2, + 8, 2, + FTileIndex(0, 0), + { FTileIndex(4, 0) }, + { FTileIndex(3, 0) }); + CheckTail(*this, Commands, TEXT("Case9-2")); + TestTrue(TEXT("[Case9-2] ์ด๋™์ปค๋งจ๋“œ ์—†์Œ(์ œ์ž๋ฆฌ ์‹œ์ „)"), FindMoveCommand(Commands) == nullptr); + const FSRPGSkillCastCommand* Cast = FindCast(Commands); + if (TestTrue(TEXT("[Case9-2] ์Šคํ‚ฌ์ปค๋งจ๋“œ ์กด์žฌ"), Cast != nullptr)) + { + TestTrue(TEXT("[Case9-2] ์ ์œ  ํƒ€์ผ (3,0)์€ ์กฐ์ค€ํ•˜์ง€ ์•Š์Œ"), Cast->mTargetIndex != FTileIndex(3, 0)); + TestTrue(TEXT("[Case9-2] ์กฐ์ค€ ํƒ€์ผ=(3,1)"), Cast->mTargetIndex == FTileIndex(3, 1)); + } + } + + /** + * Case9-3: ์ด๋™ ์Šคํ‚ฌ / ๊ธฐ์ค€ ํƒ€๊ฒŸ๊นŒ์ง€ ๊ฒฝ๋กœ ์—†์Œ + * -> ํ›„๋ณด ์ „๋ถ€ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ™์œผ๋ฏ€๋กœ(๋„๋‹ฌ ๋ถˆ๊ฐ€) ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ํƒ€์ผ ์„ ํƒ + * ๋งต (8x1): E(0,0) B(4,0) P(5,0), ์‚ฌ๊ฑฐ๋ฆฌ 3 + * -> ํ›„๋ณด (1,0)(2,0)(3,0) ์ค‘ ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ 2์ธ (3,0). ๋จผ์ € ๋‚˜์˜ค๋Š” (1,0)์ด ๋ฝ‘ํžˆ๋ฉด 2์ˆœ์œ„ ๋น„๊ต ๋ˆ„๋ฝ + */ + AddInfo(TEXT("=== Case9-3: ์ด๋™ ์Šคํ‚ฌ / ๊ฒฝ๋กœ ์—†์Œ / ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ ๋น„๊ต ===")); + { + const TArray> Commands = PlanMoveSkill( + World, Scope, + /*ActionPoint*/6, /*AimRange*/3, /*SkillCost*/2, + 8, 1, + FTileIndex(0, 0), + { FTileIndex(5, 0) }, + { FTileIndex(4, 0) }); + CheckTail(*this, Commands, TEXT("Case9-3")); + TestTrue(TEXT("[Case9-3] ์ด๋™์ปค๋งจ๋“œ ์—†์Œ(์ œ์ž๋ฆฌ ์‹œ์ „)"), FindMoveCommand(Commands) == nullptr); + const FSRPGSkillCastCommand* Cast = FindCast(Commands); + if (TestTrue(TEXT("[Case9-3] ์Šคํ‚ฌ์ปค๋งจ๋“œ ์กด์žฌ"), Cast != nullptr)) + { + TestTrue(TEXT("[Case9-3] ์กฐ์ค€ ํƒ€์ผ=(3,0)"), Cast->mTargetIndex == FTileIndex(3, 0)); + } + } + + /** + * Case9-4: ์ด๋™ ์Šคํ‚ฌ / ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„ Farthest + * -> ๊ฐ€์žฅ ๋จผ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ๊ธฐ์ค€ ํƒ€๊ฒŸ์œผ๋กœ ์‚ผ์•„ ๊ทธ ์˜†์— ์ฐฉ์ง€ (ํ›„๋ฐฉ ์นจํˆฌ) + * ๋งต (9x1): P0(2,0) E(4,0) P1(8,0), ์‚ฌ๊ฑฐ๋ฆฌ 3 + * -> ๊ธฐ์ค€ ํƒ€๊ฒŸ์€ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ 4์ธ P1, ์ฐฉ์ง€ ํƒ€์ผ์€ P1 ์˜† (7,0). Nearest์˜€๋‹ค๋ฉด P0 ์˜† + */ + AddInfo(TEXT("=== Case9-4: ์ด๋™ ์Šคํ‚ฌ / ๋Œ€์ƒ์šฐ์„ ์ˆœ์œ„ Farthest ===")); + { + const TArray> Commands = PlanMoveSkill( + World, Scope, + /*ActionPoint*/6, /*AimRange*/3, /*SkillCost*/2, + 9, 1, + FTileIndex(4, 0), + { FTileIndex(2, 0), FTileIndex(8, 0) }, + TArray(), + EEnemyTargetPriority::Farthest); + CheckTail(*this, Commands, TEXT("Case9-4")); + TestTrue(TEXT("[Case9-4] ์ด๋™์ปค๋งจ๋“œ ์—†์Œ(์ œ์ž๋ฆฌ ์‹œ์ „)"), FindMoveCommand(Commands) == nullptr); + const FSRPGSkillCastCommand* Cast = FindCast(Commands); + if (TestTrue(TEXT("[Case9-4] ์Šคํ‚ฌ์ปค๋งจ๋“œ ์กด์žฌ"), Cast != nullptr)) + { + TestTrue(TEXT("[Case9-4] ์กฐ์ค€ ํƒ€์ผ=(7,0)"), Cast->mTargetIndex == FTileIndex(7, 0)); + } + } + + /** + * Case9-5: ์ด๋™ ์Šคํ‚ฌ / ์กฐ์ค€ ๊ฐ€๋Šฅํ•œ ๋นˆ ํƒ€์ผ ์—†์Œ + * -> ๋‹ค๋ฅธ ์Šคํ‚ฌ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์‹œ์ „ ์—†์ด ๊ธฐ์ค€ ํƒ€๊ฒŸ์—๊ฒŒ ์ ‘๊ทผ (์‹œ์ „ ๋น„์šฉ์€ ์ด๋™ ์˜ˆ์‚ฐ์—์„œ ๋–ผ์ง€ ์•Š์Œ) + * ๋งต (6x1): E(0,0) P(5,0), ์‚ฌ๊ฑฐ๋ฆฌ 0 (ํ›„๋ณด ์—†์Œ), ํ–‰๋™๋ ฅ 3 + * -> ํ–‰๋™๋ ฅ 3์„ ์ „๋ถ€ ์จ์„œ (3,0)์œผ๋กœ ์ ‘๊ทผ + */ + AddInfo(TEXT("=== Case9-5: ์ด๋™ ์Šคํ‚ฌ / ๋นˆ ํƒ€์ผ ์—†์Œ / ์ ‘๊ทผ ํด๋ฐฑ ===")); + { + const TArray> Commands = PlanMoveSkill( + World, Scope, + /*ActionPoint*/3, /*AimRange*/0, /*SkillCost*/1, + 6, 1, + FTileIndex(0, 0), + { FTileIndex(5, 0) }); + CheckApproachNoCast(*this, Commands, TEXT("Case9-5"), FTileIndex(3, 0)); + } return true; } diff --git a/Source/P_RDTests/SRPGFramework/TileIndexTests.cpp b/Source/P_RDTests/SRPGFramework/TileIndexTests.cpp new file mode 100644 index 000000000..f7f64401d --- /dev/null +++ b/Source/P_RDTests/SRPGFramework/TileIndexTests.cpp @@ -0,0 +1,83 @@ +๏ปฟ/*****************************************************************//** + * @file TileIndexTests.cpp + * @brief FTileIndex ๊ฑฐ๋ฆฌ ํ•จ์ˆ˜ ์œ ๋‹›ํ…Œ์ŠคํŠธ + * @details + * ๋งจํ•ดํŠผ ๊ฑฐ๋ฆฌ์™€ ์ฒด๋น„์…ฐํ”„ ๊ฑฐ๋ฆฌ ๊ฒ€์ฆ. + * ๋‘ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐˆ๋ฆฌ๋Š” ์ตœ์†Œ ์‚ฌ๋ก€(๋Œ€๊ฐ 1์นธ)๋ฅผ ํฌํ•จํ•ด ๊ตฌํ˜„์ด ์„œ๋กœ ๋’ค๋ฐ”๋€Œ๋Š” ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€. + * @author ์ด๋ฌธํ™˜ + * @date 2026-09-21 + *********************************************************************/ + +#include "P_RDTests.h" +#include "Misc/AutomationTest.h" +#include "SRPGFramework/SRPGFrameworkType.h" + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FTileIndexDistanceTests, + "P_RD.SRPG.TileIndex.Distance", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter +) + +bool FTileIndexDistanceTests::RunTest(const FString& Parameters) +{ + AddInfo(TEXT("๊ฐ™์€ ์นธ: ๋‘ ๊ฑฐ๋ฆฌ ๋ชจ๋‘ 0")); + { + const FTileIndex Tile(3, 4); + TestEqual(TEXT("๊ฐ™์€ ์นธ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Tile, Tile), 0); + TestEqual(TEXT("๊ฐ™์€ ์นธ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Tile, Tile), 0); + } + + AddInfo(TEXT("์ง๊ต 3์นธ: ๋‘ ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ™์Œ")); + { + const FTileIndex Origin(2, 2); + const FTileIndex Horizontal(5, 2); + const FTileIndex Vertical(2, 5); + TestEqual(TEXT("๊ฐ€๋กœ 3์นธ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Origin, Horizontal), 3); + TestEqual(TEXT("๊ฐ€๋กœ 3์นธ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Origin, Horizontal), 3); + TestEqual(TEXT("์„ธ๋กœ 3์นธ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Origin, Vertical), 3); + TestEqual(TEXT("์„ธ๋กœ 3์นธ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Origin, Vertical), 3); + } + + AddInfo(TEXT("๋Œ€๊ฐ 1์นธ: ๋‘ ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐˆ๋ฆฌ๋Š” ์ตœ์†Œ ์‚ฌ๋ก€")); + { + const FTileIndex Origin(2, 2); + const FTileIndex Diagonal(3, 3); + TestEqual(TEXT("๋Œ€๊ฐ 1์นธ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Origin, Diagonal), 2); + TestEqual(TEXT("๋Œ€๊ฐ 1์นธ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Origin, Diagonal), 1); + } + + AddInfo(TEXT("๊ฐ€๋กœ 2, ์„ธ๋กœ 5: ๋งจํ•ดํŠผ์€ ํ•ฉ, ์ฒด๋น„์…ฐํ”„๋Š” ํฐ ๊ฐ’")); + { + const FTileIndex Origin(1, 1); + const FTileIndex Target(3, 6); + TestEqual(TEXT("๊ฐ€๋กœ 2 ์„ธ๋กœ 5 ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Origin, Target), 7); + TestEqual(TEXT("๊ฐ€๋กœ 2 ์„ธ๋กœ 5 ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Origin, Target), 5); + } + + AddInfo(TEXT("์Œ์ˆ˜ ๋ฐฉํ–ฅ ๋ณ€์œ„: ์ ˆ๋Œ“๊ฐ’ ๊ธฐ์ค€")); + { + const FTileIndex Origin(5, 5); + const FTileIndex Target(3, 0); + TestEqual(TEXT("์Œ์ˆ˜ ๋ฐฉํ–ฅ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(Origin, Target), 7); + TestEqual(TEXT("์Œ์ˆ˜ ๋ฐฉํ–ฅ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(Origin, Target), 5); + } + + AddInfo(TEXT("์Œ์ˆ˜ ์ขŒํ‘œ: ๋ฌดํšจ ์ธ๋ฑ์Šค(-1,-1)๊ฐ€ ๋“ค์–ด์™€๋„ ๊ณ„์‚ฐ์€ ์ •์˜๋จ")); + { + const FTileIndex Target(2, 1); + TestEqual(TEXT("์Œ์ˆ˜ ์ขŒํ‘œ ๋งจํ•ดํŠผ"), FTileIndex::ManhattanDistance(FTileIndex::Invalid, Target), 5); + TestEqual(TEXT("์Œ์ˆ˜ ์ขŒํ‘œ ์ฒด๋น„์…ฐํ”„"), FTileIndex::ChebyshevDistance(FTileIndex::Invalid, Target), 3); + } + + AddInfo(TEXT("๋Œ€์นญ์„ฑ: ์ธ์ž ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ”๋„ ๊ฐ™์€ ๊ฐ’")); + { + const FTileIndex A(0, 7); + const FTileIndex B(4, 2); + TestEqual(TEXT("๋งจํ•ดํŠผ ๋Œ€์นญ"), FTileIndex::ManhattanDistance(A, B), FTileIndex::ManhattanDistance(B, A)); + TestEqual(TEXT("์ฒด๋น„์…ฐํ”„ ๋Œ€์นญ"), FTileIndex::ChebyshevDistance(A, B), FTileIndex::ChebyshevDistance(B, A)); + TestEqual(TEXT("๋งจํ•ดํŠผ ๊ฐ’"), FTileIndex::ManhattanDistance(A, B), 9); + TestEqual(TEXT("์ฒด๋น„์…ฐํ”„ ๊ฐ’"), FTileIndex::ChebyshevDistance(A, B), 5); + } + + return true; +} diff --git a/Source/P_RDTests/Singleton/PartyArtifactRestoreTests.cpp b/Source/P_RDTests/Singleton/PartyArtifactRestoreTests.cpp index f0822c1f8..8478a0557 100644 --- a/Source/P_RDTests/Singleton/PartyArtifactRestoreTests.cpp +++ b/Source/P_RDTests/Singleton/PartyArtifactRestoreTests.cpp @@ -9,6 +9,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "GameplayTagContainer.h" #include "Engine/Engine.h" @@ -51,6 +52,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPartyArtifactRestoreTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + /* ์›”๋“œ์™€ ํ”„๋ ˆ์ž„์›Œํฌ ๋ชจ๋ธ ํ™•๋ณด (ํŒŒํ‹ฐ ์—ฐ๊ฒฐ ์‹œ ์†์„ฑ ์ดˆ๊ธฐํ™”์— ํ•„์š”) */ UWorld* World = GetRestoreTestWorld(); if (TestNotNull(TEXT("์œ ํšจํ•œ ์›”๋“œ"), World) == false) @@ -71,9 +74,9 @@ bool FPartyArtifactRestoreTests::RunTest(const FString& Parameters) const FPrimaryAssetId ArtifactId(TEXT("Artifact"), TEXT("DA_Artifact_A001_ChaliceOfLife")); /* ํŒŒํ‹ฐ์™€ ๊ตฌ์„ฑ์› 2๋ช… ์ƒ์„ฑ (๋ณต์› ๊ฒฝ๋กœ์ฒ˜๋Ÿผ ์›”๋“œ ์†Œ์†์œผ๋กœ ์ดˆ๊ธฐํ™”) */ - UPartyModel* PartyModel = NewObject(World); - UMockPartyMemberModel* MemberA = NewObject(World); - UMockPartyMemberModel* MemberB = NewObject(World); + UPartyModel* PartyModel = Scope.New(World); + UMockPartyMemberModel* MemberA = Scope.New(World); + UMockPartyMemberModel* MemberB = Scope.New(World); for (UMockPartyMemberModel* Member : { MemberA, MemberB }) { Member->SetStaticSpawnData(KnightData); @@ -82,7 +85,7 @@ bool FPartyArtifactRestoreTests::RunTest(const FString& Parameters) PartyModel->Initialize(); /* ์˜๊ตฌ๋ฐ์ดํ„ฐ์— ์•„ํ‹ฐํŒฉํŠธ ์‹œ๋“œ ํ›„ ๋™๊ธฐํ™” (์…‹์งธ ์Šฌ๋กฏ์€ ๋นˆ ์ž๋ฆฌ) */ - UPartyArtifactRestoreTestData* PersistData = NewObject(); + UPartyArtifactRestoreTestData* PersistData = Scope.New(); PersistData->SeedArtifact(ArtifactId); TArray> Players = { MemberA, MemberB, nullptr }; PersistData->Sync(PartyModel, Players); @@ -102,10 +105,5 @@ bool FPartyArtifactRestoreTests::RunTest(const FString& Parameters) /* ๋นˆ ์Šฌ๋กฏ์€ ๊ทธ๋Œ€๋กœ */ TestNull(TEXT("์…‹์งธ ์Šฌ๋กฏ ๋น„์–ด ์žˆ์Œ"), PartyModel->GetPlayerUnitModel(2)); - /* ์ •๋ฆฌ */ - PartyModel->Uninitialize(); - MemberA->Uninitialize(); - MemberB->Uninitialize(); - return true; } diff --git a/Source/P_RDTests/Singleton/RunCheckpointTests.cpp b/Source/P_RDTests/Singleton/RunCheckpointTests.cpp index ed185087e..ff464dfbd 100644 --- a/Source/P_RDTests/Singleton/RunCheckpointTests.cpp +++ b/Source/P_RDTests/Singleton/RunCheckpointTests.cpp @@ -1,4 +1,4 @@ -#include "P_RDTests.h" +๏ปฟ#include "P_RDTests.h" #include "Misc/AutomationTest.h" #include "Singleton/RunCheckpointTestsHelper.h" #include "SaveGame/SaveCheckpoint.h" @@ -198,6 +198,10 @@ bool FCheckpointStalledRoundGuardTest::RunTest(const FString& Parameters) AddExpectedError(TEXT("Combat speed cannot produce a turn"), EAutomationExpectedErrorFlags::Contains, 1); TestFalse(TEXT("Empty combat returns instead of spinning in Shipping"), Model->EvaluateEmptyRound()); TestEqual(TEXT("Blocked combat reports once"), BlockedCount, 1); + + Model->Destroy(); + Preview->Destroy(); + return true; } diff --git a/Source/P_RDTests/TAS/Passive/PassiveConditionTests.cpp b/Source/P_RDTests/TAS/Passive/PassiveConditionTests.cpp index cdcb7f879..cf48bddac 100644 --- a/Source/P_RDTests/TAS/Passive/PassiveConditionTests.cpp +++ b/Source/P_RDTests/TAS/Passive/PassiveConditionTests.cpp @@ -11,6 +11,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "TAS/Passive/PassiveCondition.h" @@ -22,10 +23,10 @@ namespace { - // HP / MaxHP / ํƒ€์ผ ์œ„์น˜๋ฅผ ๊ฐ€์ง„ ์Šค๋ƒ…์ƒท ์ƒ์„ฑ - UBoardCombatTargetSnapshotData* MakeSnapshot(float HP, float MaxHP, const FTileIndex& Tile) + // HP / MaxHP / ํƒ€์ผ ์œ„์น˜๋ฅผ ๊ฐ€์ง„ ์Šค๋ƒ…์ƒท ์ƒ์„ฑ (์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + UBoardCombatTargetSnapshotData* MakeSnapshot(FTestObjectScope& Scope, float HP, float MaxHP, const FTileIndex& Tile) { - UBoardCombatTargetSnapshotData* Snapshot = NewObject(); + UBoardCombatTargetSnapshotData* Snapshot = Scope.New(); Snapshot->mAttributes.Add(UCombatTargetAttributeSet::GetHPAttribute(), HP); Snapshot->mAttributes.Add(UCombatTargetAttributeSet::GetMaxHPAttribute(), MaxHP); Snapshot->mTileTransform.mIndex = Tile; @@ -98,8 +99,10 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveConditionResolveTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + // ์†Œ์œ ์ž: HP 30 / MaxHP 100, ๋””๋ฒ„ํ”„ ์•ฝํ™” 1 + ์ทจ์•ฝ 2 - UBoardCombatTargetSnapshotData* Owner = MakeSnapshot(30.f, 100.f, FTileIndex(0, 0)); + UBoardCombatTargetSnapshotData* Owner = MakeSnapshot(Scope, 30.f, 100.f, FTileIndex(0, 0)); Owner->mEffectCounts.Add(EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Weakness, 1); Owner->mEffectCounts.Add(EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Vulnerability, 2); Owner->mEffectCounts.Add(EffectTags::GameplayEffect_StatusEffect_RoundDuration_Buff_Vigor, 1); @@ -158,11 +161,13 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveConditionSpatialTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + // ์†Œ์œ ์ž (0,0), ํƒ€๊ฒŸ 0 (2,3), ํƒ€๊ฒŸ 1 (1,0) FPassiveActivateContext Ctx; - Ctx.mOwnerSnapshot = MakeSnapshot(100.f, 100.f, FTileIndex(0, 0)); - Ctx.mTargetSnapshots.Add(MakeSnapshot(100.f, 100.f, FTileIndex(2, 3))); - Ctx.mTargetSnapshots.Add(MakeSnapshot(100.f, 100.f, FTileIndex(1, 0))); + Ctx.mOwnerSnapshot = MakeSnapshot(Scope, 100.f, 100.f, FTileIndex(0, 0)); + Ctx.mTargetSnapshots.Add(MakeSnapshot(Scope, 100.f, 100.f, FTileIndex(2, 3))); + Ctx.mTargetSnapshots.Add(MakeSnapshot(Scope, 100.f, 100.f, FTileIndex(1, 0))); FDynamicPassiveData_Generic State; float Value = 0.f; @@ -214,9 +219,11 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveConditionEvaluateAllTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + // ์†Œ์œ ์ž HP 30 / MaxHP 100, ์นด์šดํ„ฐ 6 FPassiveActivateContext Ctx; - Ctx.mOwnerSnapshot = MakeSnapshot(30.f, 100.f, FTileIndex(0, 0)); + Ctx.mOwnerSnapshot = MakeSnapshot(Scope, 30.f, 100.f, FTileIndex(0, 0)); FDynamicPassiveData_Generic State; State.mCounter = 6; diff --git a/Source/P_RDTests/TAS/Passive/TacticalPassiveGenericTests.cpp b/Source/P_RDTests/TAS/Passive/TacticalPassiveGenericTests.cpp index 249f14bec..f911eec66 100644 --- a/Source/P_RDTests/TAS/Passive/TacticalPassiveGenericTests.cpp +++ b/Source/P_RDTests/TAS/Passive/TacticalPassiveGenericTests.cpp @@ -8,6 +8,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "TAS/TASAttributeTestsHelper.h" #include "TAS/Passive/PassiveTestsHelper.h" @@ -58,8 +59,8 @@ namespace return FGameplayTag::RequestGameplayTag(FName(TagName)); } - // ๋ณด๋“œ์•กํ„ฐ ๋ชฉ ์ƒ์„ฑ - UMockBoardActorModel* MakeMockActor(FAutomationTestBase& Test) + // ๋ณด๋“œ์•กํ„ฐ ๋ชฉ ์ƒ์„ฑ (์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + UMockBoardActorModel* MakeMockActor(FAutomationTestBase& Test, FTestObjectScope& Scope) { UWorld* World = GetAnyGameWorld(); if (World == nullptr) @@ -87,11 +88,13 @@ namespace UTacticalFrameworkModel* FrameworkModel = Cast(RoomInstance->mAliveSubsystemModels.FindRef(UTacticalFrameworkModel::StaticClass())); if (FrameworkModel == nullptr) { - FrameworkModel = NewObject(RoomInstance); + FrameworkModel = Scope.New(RoomInstance); RoomInstance->mAliveSubsystemModels.Add(UTacticalFrameworkModel::StaticClass(), FrameworkModel); + // ํ…Œ์ŠคํŠธ๊ฐ€ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ํŒŒ๊ดด ์ „์— ๋“ฑ๋ก ํ•ด์ œ + Scope.Defer([RoomInstance]() { RoomInstance->mAliveSubsystemModels.Remove(UTacticalFrameworkModel::StaticClass()); }); } - UMockBoardActorModel* Actor = NewObject(World); + UMockBoardActorModel* Actor = Scope.New(World); Actor->Initialize(); Actor->BeginPlay(); return Actor; @@ -145,10 +148,10 @@ namespace return Condition; } - // Generic์šฉ DA ์กฐ๋ฆฝ: ํšจ๊ณผ 1๊ฐœ ๊ธฐ๋ณธํ˜•. ์กฐ๊ฑด/์บก์ฒ˜/์ถ”๊ฐ€ ํšจ๊ณผ๋Š” ํ˜ธ์ถœ๋ถ€์—์„œ ์ฑ„์›€ - UStaticPassiveData* MakeGenericData(FGameplayTag Activate, FGameplayTag Deactivate, TSubclassOf EffectClass, const FPassiveOperand& Magnitude) + // Generic์šฉ DA ์กฐ๋ฆฝ: ํšจ๊ณผ 1๊ฐœ ๊ธฐ๋ณธํ˜•. ์กฐ๊ฑด/์บก์ฒ˜/์ถ”๊ฐ€ ํšจ๊ณผ๋Š” ํ˜ธ์ถœ๋ถ€์—์„œ ์ฑ„์›€. ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก + UStaticPassiveData* MakeGenericData(FTestObjectScope& Scope, FGameplayTag Activate, FGameplayTag Deactivate, TSubclassOf EffectClass, const FPassiveOperand& Magnitude) { - UStaticPassiveData* Data = NewObject(); + UStaticPassiveData* Data = Scope.New(); Data->mActivateTimingTag = Activate; Data->mDeactivateTimingTag = Deactivate; @@ -159,10 +162,10 @@ namespace return Data; } - // Generic ํŒจ์‹œ๋ธŒ ์ƒ์„ฑ - UTacticalPassive_Generic* MakeGenericPassive(UStaticPassiveData* Data) + // Generic ํŒจ์‹œ๋ธŒ ์ƒ์„ฑ (์Šค์ฝ”ํ”„์— ๋“ฑ๋ก) + UTacticalPassive_Generic* MakeGenericPassive(FTestObjectScope& Scope, UStaticPassiveData* Data) { - UTacticalPassive_Generic* Passive = NewObject(); + UTacticalPassive_Generic* Passive = Scope.New(); Passive->SetStaticData(Data); return Passive; } @@ -188,7 +191,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericBasicTest::RunTest(const FString& Parameters) { - UMockBoardActorModel* Actor = MakeMockActor(*this); + FTestObjectScope Scope; + + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -202,8 +207,8 @@ bool FPassiveGenericBasicTest::RunTest(const FString& Parameters) const FGameplayTag OnEndRoom = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndRoom")); // ์กฐ๊ฑด ์—†์ด ํž ๋ฐฐ์œจ 1.25๋ฅผ ๋ฃธ ๋™์•ˆ ์œ ์ง€ํ•˜๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnStartRoom, OnEndRoom, UTacticalEffect_HealFactor_MultiplyAdditive::StaticClass(), MakeConstOperand(1.25f)); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartRoom, OnEndRoom, UTacticalEffect_HealFactor_MultiplyAdditive::StaticClass(), MakeConstOperand(1.25f)); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; @@ -236,7 +241,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericConditionTest::RunTest(const FString& Parameters) { - UMockBoardActorModel* Actor = MakeMockActor(*this); + FTestObjectScope Scope; + + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -250,12 +257,12 @@ bool FPassiveGenericConditionTest::RunTest(const FString& Parameters) const FGameplayTag OnEndTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndTurn")); // ์ฒด๋ ฅ์ด ์ ˆ๋ฐ˜ ์ดํ•˜๋ฉด ๋ฐฉ์–ด๋„ 4๋ฅผ ์ฃผ๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); Data->mConditions.Add(MakeCondition( MakeAttrOperand(UCombatTargetAttributeSet::GetHPAttribute(), EPassiveOperandSource::Self), EPassiveCompareOp::LessEqual, MakeAttrOperand(UCombatTargetAttributeSet::GetMaxHPAttribute(), EPassiveOperandSource::Self, 0.5f))); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // HP 80: ์กฐ๊ฑด ๊ฑฐ์ง“์ด๋ผ ๋ฏธ๋ฐœ๋™ { @@ -293,7 +300,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericCounterTest::RunTest(const FString& Parameters) { - UMockBoardActorModel* Actor = MakeMockActor(*this); + FTestObjectScope Scope; + + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -310,7 +319,7 @@ bool FPassiveGenericCounterTest::RunTest(const FString& Parameters) // ๋งค 3๋ฒˆ์งธ ์Šคํ‚ฌ ์‚ฌ์šฉ์— ๊ณต๊ฒฉ ๋ณด๋„ˆ์Šค๋ฅผ ์ฃผ๋Š” DA auto MakeCounterData = [&]() -> UStaticPassiveData* { - UStaticPassiveData* Data = MakeGenericData(OnStartUsingSkill, OnEndUsingSkill, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartUsingSkill, OnEndUsingSkill, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); Data->mConditions.Add(MakeCondition(MakeCounterOperand(), EPassiveCompareOp::ModuloZero, MakeConstOperand(3.f))); return Data; }; @@ -321,7 +330,7 @@ bool FPassiveGenericCounterTest::RunTest(const FString& Parameters) // 8ํšŒ ๋ฐ˜๋ณต: 3์˜ ๋ฐฐ์ˆ˜ ํšŒ์ฐจ๋งŒ ๋ฐœ๋™ { - UTacticalPassive_Generic* Passive = MakeGenericPassive(MakeCounterData()); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, MakeCounterData()); for (int32 Hit = 1; Hit <= 8; ++Hit) { const bool bExpectFire = (Hit % 3 == 0); @@ -339,7 +348,7 @@ bool FPassiveGenericCounterTest::RunTest(const FString& Parameters) { UStaticPassiveData* Data = MakeCounterData(); Data->mCounterResetTimingTag = OnEndTurn; - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // ๋ฐœ๋™ ์—†์ด 2ํšŒ ์ง„ํ–‰ for (int32 Hit = 1; Hit <= 2; ++Hit) @@ -368,7 +377,7 @@ bool FPassiveGenericCounterTest::RunTest(const FString& Parameters) MakeAttrOperand(UCombatTargetAttributeSet::GetHPAttribute(), EPassiveOperandSource::Self), EPassiveCompareOp::Less, MakeConstOperand(50.f))); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // Self ์กฐ๊ฑด์€ ์†Œ์œ ์ž ์Šค๋ƒ…์ƒท์œผ๋กœ ํŒ์ •ํ•˜๋ฏ€๋กœ HP ๋ณ€๊ฒฝ ์‹œ๋งˆ๋‹ค ์Šค๋ƒ…์ƒท ๊ฐฑ์‹  FPassiveActivateContext SnapshotCtx; @@ -408,6 +417,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericCaptureTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnStartUsingSkill = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartUsingSkill")); const FGameplayTag OnEndUsingSkill = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndUsingSkill")); @@ -415,7 +426,7 @@ bool FPassiveGenericCaptureTest::RunTest(const FString& Parameters) // bDamaged: ์บก์ฒ˜์™€ ๋ฐœ๋™ ์‚ฌ์ด์— ์ฒด๋ ฅ์„ ๊นŽ์„์ง€ auto RunCase = [&](bool bDamaged) -> float { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return -1.f; @@ -425,7 +436,7 @@ bool FPassiveGenericCaptureTest::RunTest(const FString& Parameters) Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetHPAttribute(), 80.f); // ์Šคํ‚ฌ ์‹œ์ž‘์— HP๋ฅผ ์บก์ฒ˜ํ•˜๊ณ , ์ข…๋ฃŒ์— ํ˜„์žฌ HP์™€ ๋น„๊ตํ•˜๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnEndUsingSkill, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndUsingSkill, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); Data->mCaptureTimingTag = OnStartUsingSkill; FPassiveCaptureEntry Capture; Capture.mKey = FName(TEXT("HP")); @@ -435,7 +446,7 @@ bool FPassiveGenericCaptureTest::RunTest(const FString& Parameters) MakeAttrOperand(UCombatTargetAttributeSet::GetHPAttribute(), EPassiveOperandSource::Self), EPassiveCompareOp::Less, MakeCapturedOperand(FName(TEXT("HP")), EPassiveOperandSource::Self))); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // ์Šค๋ƒ…์ƒท์„ ์ƒˆ๋กœ ๋– ์„œ Ctx๋ฅผ ๊ตฌ์„ฑ auto MakeCtx = [&]() -> FPassiveActivateContext @@ -483,11 +494,13 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericMagnitudeTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnEndTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndTurn")); // ์†์„ฑ๊ฐ’ ์ˆ˜์น˜: ๊ณต๊ฒฉ๋ ฅ๋งŒํผ ๋ฐฉ์–ด๋„๋ฅผ ์–ป๋Š” DA { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -495,9 +508,9 @@ bool FPassiveGenericMagnitudeTest::RunTest(const FString& Parameters) UAttributeSetComponentModel* Comp = Actor->GetAttributeComponentModel(); Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetAttackFactorAttribute(), 3.f); - UStaticPassiveData* Data = MakeGenericData(OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeAttrOperand(UCombatTargetAttributeSet::GetAttackFactorAttribute(), EPassiveOperandSource::Self)); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // ์ˆ˜์น˜ ๊ณ„์‚ฐ์ด ์Šค๋ƒ…์ƒท์„ ์ฝ์œผ๋ฏ€๋กœ ์†Œ์œ ์ž ์Šค๋ƒ…์ƒท ํ•„์š” FPassiveActivateContext Ctx; @@ -511,7 +524,7 @@ bool FPassiveGenericMagnitudeTest::RunTest(const FString& Parameters) // ํšจ๊ณผ 2๊ฐœ: ๋ฐฉ์–ด๋„ +4์™€ ์ฒด๋ ฅ +5 ๋™์‹œ ์ ์šฉ { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -520,12 +533,12 @@ bool FPassiveGenericMagnitudeTest::RunTest(const FString& Parameters) Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetMaxHPAttribute(), 100.f); Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetHPAttribute(), 50.f); - UStaticPassiveData* Data = MakeGenericData(OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndTurn, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); FPassiveEffectEntry Second; Second.mEffectClass = UTacticalEffect_HP::StaticClass(); Second.mMagnitude = MakeConstOperand(5.f); Data->mEffects.Add(Second); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; @@ -551,14 +564,16 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnStartTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); const FGameplayTag OnEndTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndTurn")); // ํšจ๊ณผ ๋Œ€์ƒ: Self๋ฉด ์†Œ์œ ์ž๋งŒ, Targets๋ฉด ํƒ€๊ฒŸ ์ „๋ถ€ { - UMockBoardActorModel* Player = MakeMockActor(*this); - UMockBoardActorModel* Target1 = MakeMockActor(*this); - UMockBoardActorModel* Target2 = MakeMockActor(*this); + UMockBoardActorModel* Player = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target1 = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target2 = MakeMockActor(*this, Scope); if (Player == nullptr || Target1 == nullptr || Target2 == nullptr) { return false; @@ -577,9 +592,9 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) // Self: ์†Œ์œ ์ž๋งŒ +5 { - UStaticPassiveData* Data = MakeGenericData(OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); Data->mEffectTarget = EPassiveEffectTarget::Self; - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); DriveTiming(Passive, OnStartTurn, Ctx); TestEqual(TEXT("Self ๋ฐœ๋™: ์†Œ์œ ์ž 15"), PlayerComp->GetAttributeCurrentValue(UCombatTargetAttributeSet::GetAttackFactorAttribute()), 15.f); @@ -590,9 +605,9 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) // Targets: ํƒ€๊ฒŸ ์ „๋ถ€ +5, ์†Œ์œ ์ž๋Š” ๊ทธ๋Œ€๋กœ { - UStaticPassiveData* Data = MakeGenericData(OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); Data->mEffectTarget = EPassiveEffectTarget::Targets; - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); DriveTiming(Passive, OnStartTurn, Ctx); TestEqual(TEXT("Targets ๋ฐœ๋™: ํƒ€๊ฒŸ1 15"), TargetComp1->GetAttributeCurrentValue(UCombatTargetAttributeSet::GetAttackFactorAttribute()), 15.f); @@ -608,9 +623,9 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) { auto RunCase = [&](EPassiveTargetQuantifier Quantifier, float HP1, float HP2) -> float { - UMockBoardActorModel* Player = MakeMockActor(*this); - UMockBoardActorModel* Target1 = MakeMockActor(*this); - UMockBoardActorModel* Target2 = MakeMockActor(*this); + UMockBoardActorModel* Player = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target1 = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target2 = MakeMockActor(*this, Scope); if (Player == nullptr || Target1 == nullptr || Target2 == nullptr) { return -1.f; @@ -622,14 +637,14 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) TargetComp1->SetAttributeBaseValue(UCombatTargetAttributeSet::GetAttackFactorAttribute(), 10.f); TargetComp2->SetAttributeBaseValue(UCombatTargetAttributeSet::GetAttackFactorAttribute(), 10.f); - UStaticPassiveData* Data = MakeGenericData(OnStartTurn, FGameplayTag(), UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartTurn, FGameplayTag(), UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); Data->mEffectTarget = EPassiveEffectTarget::Targets; Data->mTargetQuantifier = Quantifier; Data->mConditions.Add(MakeCondition( MakeAttrOperand(UCombatTargetAttributeSet::GetHPAttribute(), EPassiveOperandSource::Target), EPassiveCompareOp::Less, MakeConstOperand(50.f))); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Player; @@ -650,7 +665,7 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) // Infinite ํšจ๊ณผ 2๊ฐœ: ๋™์‹œ ์ ์šฉ, ์žฌ๋ฐœ๋™ ๊ฐฑ์‹ , ํ•ด์ œ๊นŒ์ง€ { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -659,12 +674,12 @@ bool FPassiveGenericTargetTest::RunTest(const FString& Parameters) Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetAttackFactorAttribute(), 10.f); Comp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetHealFactorAttribute(), 1.f); - UStaticPassiveData* Data = MakeGenericData(OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartTurn, OnEndTurn, UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); FPassiveEffectEntry Second; Second.mEffectClass = UTacticalEffect_HealFactor_MultiplyAdditive::StaticClass(); Second.mMagnitude = MakeConstOperand(1.25f); Data->mEffects.Add(Second); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; @@ -702,12 +717,14 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericNoTargetTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnEndApplyingEffect = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndApplyingEffect")); // ์†Œ์œ ์ž AttackFactor 10, HP 30์œผ๋กœ ๋‘๊ณ  ๋นˆ ํƒ€๊ฒŸ ์ปจํ…์ŠคํŠธ๋กœ ๋ฐœ๋™. ๋ฐ˜ํ™˜๊ฐ’์€ ๋ฐœ๋™ ํ›„ ์†Œ์œ ์ž AttackFactor auto RunCase = [&](const TArray& Conditions) -> float { - UMockBoardActorModel* Player = MakeMockActor(*this); + UMockBoardActorModel* Player = MakeMockActor(*this, Scope); if (Player == nullptr) { return -1.f; @@ -716,9 +733,9 @@ bool FPassiveGenericNoTargetTest::RunTest(const FString& Parameters) PlayerComp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetAttackFactorAttribute(), 10.f); PlayerComp->SetAttributeBaseValue(UCombatTargetAttributeSet::GetHPAttribute(), 30.f); - UStaticPassiveData* Data = MakeGenericData(OnEndApplyingEffect, FGameplayTag(), UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndApplyingEffect, FGameplayTag(), UTacticalEffect_AttackFactor_AddBase::StaticClass(), MakeConstOperand(5.f)); Data->mConditions = Conditions; - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // ํƒ€๊ฒŸ๊ณผ ํƒ€๊ฒŸ ์Šค๋ƒ…์ƒท์„ ๋น„์›Œ๋‘” ์ปจํ…์ŠคํŠธ FPassiveActivateContext Ctx; @@ -769,6 +786,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericTagTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnStartTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); const FGameplayTag OnEndTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndTurn")); @@ -777,7 +796,7 @@ bool FPassiveGenericTagTest::RunTest(const FString& Parameters) // ์ƒํƒœ์ด์ƒ ์Šคํƒ: ์ˆ˜์น˜๊ฐ€ ์Šคํƒ ์ˆ˜๋กœ ๋“ค์–ด๊ฐ { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -786,8 +805,8 @@ bool FPassiveGenericTagTest::RunTest(const FString& Parameters) TestFalse(TEXT("์ ์šฉ ์ „: ์ทจ์•ฝ ํƒœ๊ทธ ์—†์Œ"), Comp->HasMatchingGameplayTag(VulnerabilityTag)); // ์ทจ์•ฝ 3์Šคํƒ์„ ์ฃผ๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnEndTurn, FGameplayTag(), UTacticalEffect_GetVulnerability::StaticClass(), MakeConstOperand(3.f)); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndTurn, FGameplayTag(), UTacticalEffect_GetVulnerability::StaticClass(), MakeConstOperand(3.f)); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; @@ -801,7 +820,7 @@ bool FPassiveGenericTagTest::RunTest(const FString& Parameters) // Infinite ํƒœ๊ทธ ๋ถ€์—ฌ: ํ•ด์ œ ์‹œ ํƒœ๊ทธ ํšŒ์ˆ˜ { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -810,8 +829,8 @@ bool FPassiveGenericTagTest::RunTest(const FString& Parameters) TestFalse(TEXT("์ ์šฉ ์ „: ์ทจ์•ฝ ํƒœ๊ทธ ์—†์Œ"), Comp->HasMatchingGameplayTag(VulnerabilityTag)); // GrantedTags ๋ชฉ ์ดํŽ™ํŠธ๋ฅผ ํ„ด ๋™์•ˆ ์œ ์ง€ํ•˜๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnStartTurn, OnEndTurn, UMockGrantedTagTacticalEffect::StaticClass(), MakeConstOperand(1.f)); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UStaticPassiveData* Data = MakeGenericData(Scope, OnStartTurn, OnEndTurn, UMockGrantedTagTacticalEffect::StaticClass(), MakeConstOperand(1.f)); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; @@ -841,6 +860,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericStatusStackTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnStartTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartTurn")); const FGameplayTag OnEndTurn = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndTurn")); const FTacticalEffectQuery StrengthQuery = FTacticalEffectQuery::MakeQuery_MatchAnyEffectTags(FGameplayTagContainer(EffectTags::GameplayEffect_StatusEffect_Infinite_Buff_Strength)); @@ -848,12 +869,12 @@ bool FPassiveGenericStatusStackTest::RunTest(const FString& Parameters) // ์™„๋ ฅ ๋ฒ„ํ”„ 3์Šคํƒ์„ ํ„ด ๋™์•ˆ ์œ ์ง€ํ•˜๋Š” DA auto MakeStrengthData = [&]() -> UStaticPassiveData* { - return MakeGenericData(OnStartTurn, OnEndTurn, UTacticalEffect_Buff_Strength::StaticClass(), MakeConstOperand(3.f)); + return MakeGenericData(Scope, OnStartTurn, OnEndTurn, UTacticalEffect_Buff_Strength::StaticClass(), MakeConstOperand(3.f)); }; // ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ 2์Šคํƒ ์œ„์— 3์Šคํƒ์„ ์–น๊ณ , ํ•ด์ œํ•˜๋ฉด 3์Šคํƒ๋งŒ ๋น ์ง€๋Š”์ง€ { - UMockBoardActorModel* Actor = MakeMockActor(*this); + UMockBoardActorModel* Actor = MakeMockActor(*this, Scope); if (Actor == nullptr) { return false; @@ -866,7 +887,7 @@ bool FPassiveGenericStatusStackTest::RunTest(const FString& Parameters) Comp->ApplyTacticalEffectSpecToSelf(*OtherSpec); TestEqual(TEXT("์ ์šฉ ์ „: ๋‹ค๋ฅธ ์ถœ์ฒ˜ 2์Šคํƒ"), Comp->GetAggregatedStackCount(StrengthQuery), 2); - UTacticalPassive_Generic* Passive = MakeGenericPassive(MakeStrengthData()); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, MakeStrengthData()); FPassiveActivateContext Ctx; Ctx.mOwner = Actor; Ctx.mTargets.Add(Actor); @@ -878,25 +899,6 @@ bool FPassiveGenericStatusStackTest::RunTest(const FString& Parameters) TestEqual(TEXT("ํ•ด์ œ: ํŒจ์‹œ๋ธŒ 3์Šคํƒ๋งŒ ๋น ์ ธ 2์Šคํƒ"), Comp->GetAggregatedStackCount(StrengthQuery), 2); } - // ๋ฉด์—ญ ๋Œ€์ƒ์—๊ฒŒ๋Š” ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š”์ง€ - { - UMockBoardActorModel* Actor = MakeMockActor(*this); - if (Actor == nullptr) - { - return false; - } - UAttributeSetComponentModel* Comp = Actor->GetAttributeComponentModel(); - Comp->AddLooseGameplayTag(EffectTags::GameplayEffect_ActorState_Immunity); - - UTacticalPassive_Generic* Passive = MakeGenericPassive(MakeStrengthData()); - FPassiveActivateContext Ctx; - Ctx.mOwner = Actor; - Ctx.mTargets.Add(Actor); - - DriveTiming(Passive, OnStartTurn, Ctx); - TestEqual(TEXT("๋ฉด์—ญ: 0์Šคํƒ"), Comp->GetAggregatedStackCount(StrengthQuery), 0); - } - return true; } @@ -912,13 +914,15 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FPassiveGenericCapturedTargetsTest::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + const FGameplayTag OnStartApplyingEffect = PassiveTiming(TEXT("GameplayAbility.Passive.OnStartApplyingEffect")); const FGameplayTag OnEndUsingSkill = PassiveTiming(TEXT("GameplayAbility.Passive.OnEndUsingSkill")); - UMockBoardActorModel* Owner = MakeMockActor(*this); - UMockBoardActorModel* Target1 = MakeMockActor(*this); - UMockBoardActorModel* Target2 = MakeMockActor(*this); - UMockBoardActorModel* Target3 = MakeMockActor(*this); + UMockBoardActorModel* Owner = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target1 = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target2 = MakeMockActor(*this, Scope); + UMockBoardActorModel* Target3 = MakeMockActor(*this, Scope); if (Owner == nullptr || Target1 == nullptr || Target2 == nullptr || Target3 == nullptr) { return false; @@ -931,7 +935,7 @@ bool FPassiveGenericCapturedTargetsTest::RunTest(const FString& Parameters) Target3->GetAttributeComponentModel()->SetAttributeBaseValue(UCombatTargetAttributeSet::GetHPAttribute(), 80.f); // ์ดํŽ™ํŠธ ์ ์šฉ ์‹œ์ ์— ๋Œ€์ƒ HP๋ฅผ ์บก์ฒ˜ํ•˜๊ณ , ์Šคํ‚ฌ ์ข…๋ฃŒ ์‹œ ์บก์ฒ˜ํ•œ ๋Œ€์ƒ ์ค‘ HP๊ฐ€ ์ค„์–ด๋“  ๊ฒŒ ์žˆ์œผ๋ฉด ๋ฐฉ์–ด๋„ 4๋ฅผ ์–ป๋Š” DA - UStaticPassiveData* Data = MakeGenericData(OnEndUsingSkill, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); + UStaticPassiveData* Data = MakeGenericData(Scope, OnEndUsingSkill, FGameplayTag(), UTacticalEffect_Defense::StaticClass(), MakeConstOperand(4.f)); Data->mCaptureTimingTag = OnStartApplyingEffect; Data->mActivateOnCapturedTargets = true; FPassiveCaptureEntry CaptureEntry; @@ -942,7 +946,7 @@ bool FPassiveGenericCapturedTargetsTest::RunTest(const FString& Parameters) MakeAttrOperand(UCombatTargetAttributeSet::GetHPAttribute(), EPassiveOperandSource::Target), EPassiveCompareOp::Less, MakeCapturedOperand(FName(TEXT("HP")), EPassiveOperandSource::Target))); - UTacticalPassive_Generic* Passive = MakeGenericPassive(Data); + UTacticalPassive_Generic* Passive = MakeGenericPassive(Scope, Data); // ํŽ˜์ด์ฆˆ Ctx: ์Šคํ‚ฌ ๋Œ€์ƒ๋“ค๊ณผ ์Šค๋ƒ…์ƒท auto Capture = [&](std::initializer_list Targets) diff --git a/Source/P_RDTests/TAS/StatusEffectRoundDurationTests.cpp b/Source/P_RDTests/TAS/StatusEffectRoundDurationTests.cpp index 5c4e85af1..17839fb7e 100644 --- a/Source/P_RDTests/TAS/StatusEffectRoundDurationTests.cpp +++ b/Source/P_RDTests/TAS/StatusEffectRoundDurationTests.cpp @@ -20,6 +20,7 @@ *********************************************************************/ #include "P_RDTests.h" +#include "TestObjectScope.h" #include "Misc/AutomationTest.h" #include "TASAttributeTestsHelper.h" #include "GameplayTagType.h" @@ -75,6 +76,8 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( bool FStatusEffectRoundDurationTests::RunTest(const FString& Parameters) { + FTestObjectScope Scope; + /* 1. ์›”๋“œ ๋ฐ FrameworkModel ํ™˜๊ฒฝ ์ค€๋น„ */ UWorld* World = FindAnyGameWorld(); @@ -102,15 +105,17 @@ bool FStatusEffectRoundDurationTests::RunTest(const FString& Parameters) UTacticalFrameworkModel* FrameworkModel = Cast(RoomInstance->mAliveSubsystemModels.FindRef(UTacticalFrameworkModel::StaticClass())); if (FrameworkModel == nullptr) { - FrameworkModel = NewObject(RoomInstance); + FrameworkModel = Scope.New(RoomInstance); RoomInstance->mAliveSubsystemModels.Add(UTacticalFrameworkModel::StaticClass(), FrameworkModel); + // ํ…Œ์ŠคํŠธ๊ฐ€ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ํŒŒ๊ดด ์ „์— ๋“ฑ๋ก ํ•ด์ œ + Scope.Defer([RoomInstance]() { RoomInstance->mAliveSubsystemModels.Remove(UTacticalFrameworkModel::StaticClass()); }); } const FGameplayTag StunTag = EffectTags::GameplayEffect_StatusEffect_RoundDuration_Debuff_Stun; /* ํ…Œ์ŠคํŠธ 1: ๋‹ค๋ฅธ ์œ ๋‹›๋งŒ ํ„ด์„ ๋ฐ›์€ ๋ผ์šด๋“œ์—์„œ๋„ ๊ธฐ์ ˆ ์Šคํƒ์ด ๋ผ์šด๋“œ๋‹น 1์”ฉ ๊ฐ์†Œ */ { - UTASActorModelMock* MockActorModel = NewObject(World); + UTASActorModelMock* MockActorModel = Scope.New(World); MockActorModel->Initialize(); MockActorModel->BeginPlay(); @@ -174,7 +179,7 @@ bool FStatusEffectRoundDurationTests::RunTest(const FString& Parameters) /* ํ…Œ์ŠคํŠธ 2: ๋ผ์šด๋“œ๊ฐ€ ์ง„ํ–‰๋˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ์ ˆ ์Šคํƒ์ด ์ค„์ง€ ์•Š์Œ */ { - UTASActorModelMock* MockActorModel = NewObject(World); + UTASActorModelMock* MockActorModel = Scope.New(World); MockActorModel->Initialize(); MockActorModel->BeginPlay(); diff --git a/Source/P_RDTests/TestObjectScope.h b/Source/P_RDTests/TestObjectScope.h new file mode 100644 index 000000000..516e193bb --- /dev/null +++ b/Source/P_RDTests/TestObjectScope.h @@ -0,0 +1,132 @@ +๏ปฟ/*****************************************************************//** + * @file TestObjectScope.h + * @brief ํ…Œ์ŠคํŠธ์šฉ UObject ์ƒ์„ฑ/์ •๋ฆฌ ์Šค์ฝ”ํ”„ + * @details + * RunTest ์•ˆ์—์„œ ๋งŒ๋“  UObject๋ฅผ ๋“ฑ๋กํ•ด ๋‘์—ˆ๋‹ค๊ฐ€ ์Šค์ฝ”ํ”„ ์ข…๋ฃŒ ์‹œ ์ผ๊ด„ ํŒŒ๊ดด. + * ๋“ฑ๋ก๋œ ๊ฐ์ฒด๋Š” ์Šค์ฝ”ํ”„๊ฐ€ ์‚ด์•„ ์žˆ๋Š” ๋™์•ˆ GC์—์„œ ๋ณดํ˜ธ๋จ (FGCObject). + * ํŒŒ๊ดด๋Š” ๋“ฑ๋ก ์—ญ์ˆœ. UObjectModel ๊ณ„์—ด์€ ์ธ๊ฒŒ์ž„ ํŒŒ๊ดด ๊ฒฝ๋กœ์™€ ๊ฐ™์ด + * EndPlay(์•กํ„ฐ๋งŒ) -> Uninitialize ํ›„ MarkAsGarbage. + * @author ์ด๋ฌธํ™˜ + * @date 2026-09-23 + *********************************************************************/ + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/GCObject.h" +#include "Actor/ActorModel.h" + +/** + * @brief ํ…Œ์ŠคํŠธ์šฉ UObject ์ƒ์„ฑ/์ •๋ฆฌ ์Šค์ฝ”ํ”„ + * @details RunTest ์ฒซ ์ค„์— ๋กœ์ปฌ๋กœ ์„ ์–ธ. New๋กœ ๋งŒ๋“  ๊ฐ์ฒด๋Š” ์ด๋ฅธ return์„ ํฌํ•จํ•œ + * ๋ชจ๋“  ์ข…๋ฃŒ ๊ฒฝ๋กœ์—์„œ ํŒŒ๊ดด๋จ. ํ…Œ์ŠคํŠธ ๋ณธ๋ฌธ์€ EndPlay/Uninitialize๋ฅผ ์ง์ ‘ ๋ถ€๋ฅด์ง€ ์•Š์Œ + */ +class FTestObjectScope : public FGCObject +{ +public: + FTestObjectScope() = default; + ~FTestObjectScope(); + + // ๋ณต์‚ฌ ๊ธˆ์ง€ (ํŒŒ๊ดด๊ฐ€ ๋‘ ๋ฒˆ ์ผ์–ด๋‚˜์ง€ ์•Š๋„๋ก) + FTestObjectScope(const FTestObjectScope&) = delete; + FTestObjectScope& operator=(const FTestObjectScope&) = delete; + +public: + // @brief ๊ฐ์ฒด ์ƒ์„ฑ + ๋“ฑ๋ก (NewObject ๋Œ€์ฒด) + template + T* New(UObject* Outer = GetTransientPackage(), UClass* Class = nullptr); + + // @brief ์™ธ๋ถ€์—์„œ ๋งŒ๋“  ๊ฐ์ฒด ๋“ฑ๋ก (DuplicateObject ๋“ฑ) + template + T* Add(T* Object); + + // @brief ํŒŒ๊ดด ์ง์ „์— ์‹คํ–‰ํ•  ์ •๋ฆฌ ์ž‘์—… ๋“ฑ๋ก (๋“ฑ๋ก ์—ญ์ˆœ ์‹คํ–‰) + void Defer(TFunction Task); + +public: + // FGCObject: ๋“ฑ๋ก ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ๋กœ ๋ณด๊ณ ํ•ด ํ…Œ์ŠคํŠธ ๋„์ค‘ GC ๋ฐฉ์ง€ + void AddReferencedObjects(FReferenceCollector& Collector) override; + FString GetReferencerName() const override; + +private: + // @brief ๋“ฑ๋ก๋œ ๊ฐ์ฒด (๋“ฑ๋ก ์ˆœ์„œ ์œ ์ง€) + TArray> mObjects; + // @brief ํŒŒ๊ดด ์ „ ์‹คํ–‰ํ•  ์ •๋ฆฌ ์ž‘์—… + TArray> mDeferred; +}; + +// @brief ๊ฐ์ฒด ์ƒ์„ฑ + ๋“ฑ๋ก (NewObject ๋Œ€์ฒด) +template +T* FTestObjectScope::New(UObject* Outer, UClass* Class) +{ + T* Object = Class != nullptr ? NewObject(Outer, Class) : NewObject(Outer); + return Add(Object); +} + +// @brief ์™ธ๋ถ€์—์„œ ๋งŒ๋“  ๊ฐ์ฒด ๋“ฑ๋ก (DuplicateObject ๋“ฑ) +template +T* FTestObjectScope::Add(T* Object) +{ + if (Object != nullptr) + { + mObjects.Add(Object); + } + return Object; +} + +// @brief ํŒŒ๊ดด ์ง์ „์— ์‹คํ–‰ํ•  ์ •๋ฆฌ ์ž‘์—… ๋“ฑ๋ก (๋“ฑ๋ก ์—ญ์ˆœ ์‹คํ–‰) +inline void FTestObjectScope::Defer(TFunction Task) +{ + mDeferred.Add(MoveTemp(Task)); +} + +// @brief ๋“ฑ๋ก ์—ญ์ˆœ์œผ๋กœ ์ •๋ฆฌ ์ž‘์—… ์‹คํ–‰ ํ›„ ๊ฐ์ฒด ํŒŒ๊ดด +inline FTestObjectScope::~FTestObjectScope() +{ + // 1. ํŒŒ๊ดด ์ „ ์ •๋ฆฌ ์ž‘์—… (๋“ฑ๋ก ํ•ด์ œ ๋“ฑ) ์—ญ์ˆœ ์‹คํ–‰ + for (int32 Index = mDeferred.Num() - 1; Index >= 0; --Index) + { + mDeferred[Index](); + } + mDeferred.Reset(); + + // 2. ๊ฐ์ฒด ํŒŒ๊ดด (๋“ฑ๋ก ์—ญ์ˆœ: ์ปดํฌ๋„ŒํŠธ -> ์œ ๋‹› -> ํƒ€์ผ๋งต ์ˆœ์œผ๋กœ ๋‚ด๋ ค๊ฐ) + for (int32 Index = mObjects.Num() - 1; Index >= 0; --Index) + { + UObject* Object = mObjects[Index]; + if (IsValid(Object) == false) + { + continue; + } + + // ์ธ๊ฒŒ์ž„ ํŒŒ๊ดด ๊ฒฝ๋กœ์™€ ๋™์ผ + if (UObjectModel* Model = Cast(Object)) + { + if (UActorModel* ActorModel = Cast(Model)) + { + ActorModel->EndPlay(); + } + Model->Uninitialize(); + } + + // ์™ธ๋ถ€์—์„œ ๋ฃจํŠธ์— ๋งค๋‹จ ๊ฐ์ฒด๋Š” ๋จผ์ € ํ’€์–ด์•ผ GC ๋Œ€์ƒ์ด ๋จ + if (Object->IsRooted()) + { + Object->RemoveFromRoot(); + } + Object->MarkAsGarbage(); + } + mObjects.Reset(); +} + +// @brief ํ…Œ์ŠคํŠธ ๋„์ค‘ GC๊ฐ€ ๋Œ์•„๋„ ์‚ด์•„๋‚จ๊ฒŒ GC ์ฐธ์กฐ๋กœ ๋“ฑ๋ก +inline void FTestObjectScope::AddReferencedObjects(FReferenceCollector& Collector) +{ + Collector.AddReferencedObjects(mObjects); +} + +// @brief GC ๋””๋ฒ„๊ทธ ์ถœ๋ ฅ์šฉ ์ฐธ์กฐ์ž ์ด๋ฆ„ +inline FString FTestObjectScope::GetReferencerName() const +{ + return TEXT("FTestObjectScope"); +} diff --git a/Source/P_RDTests/UI/RealTimeLongPressTimerTests.cpp b/Source/P_RDTests/UI/RealTimeLongPressTimerTests.cpp new file mode 100644 index 000000000..10ced19cb --- /dev/null +++ b/Source/P_RDTests/UI/RealTimeLongPressTimerTests.cpp @@ -0,0 +1,31 @@ +#include "Misc/AutomationTest.h" +#include "UI/RealTimeLongPressTimer.h" +#include "UI/Reward/RewardUIModel.h" +#include "HAL/PlatformProcess.h" +#include "UObject/StrongObjectPtr.h" + +#if WITH_DEV_AUTOMATION_TESTS +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FRealTimeLongPressTimerTest, + "P_RD.UI.LongPress.RealTimeClock", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +bool FRealTimeLongPressTimerTest::RunTest(const FString& Parameters) +{ + TStrongObjectPtr Owner(NewObject()); + FRealTimeLongPressTimer Timer; + int32 Fired = 0; + Timer.Start(Owner.Get(), 0.08, FSimpleDelegate::CreateLambda([&Fired]() { ++Fired; })); + FTSTicker::GetCoreTicker().Tick(4.f); // Simulated fast game ticks must not expire a real-time hold. + TestEqual(TEXT("Accelerated tick does not trigger long press"), Fired, 0); + Timer.Cancel(); + FPlatformProcess::Sleep(0.1f); + FTSTicker::GetCoreTicker().Tick(0.f); + TestEqual(TEXT("Canceled hold stays canceled"), Fired, 0); + Timer.Start(Owner.Get(), 0.08, FSimpleDelegate::CreateLambda([&Fired]() { ++Fired; })); + FPlatformProcess::Sleep(0.1f); + FTSTicker::GetCoreTicker().Tick(0.f); + TestEqual(TEXT("Real elapsed time triggers hold once"), Fired, 1); + TestFalse(TEXT("Expired hold is no longer pending"), Timer.IsPending()); + return true; +} +#endif diff --git a/Source/P_RDTests/UI/RewardFlowTests.cpp b/Source/P_RDTests/UI/RewardFlowTests.cpp index 140b0d592..1d664b0d4 100644 --- a/Source/P_RDTests/UI/RewardFlowTests.cpp +++ b/Source/P_RDTests/UI/RewardFlowTests.cpp @@ -1,7 +1,9 @@ #include "UI/RewardFlowTests.h" #include "Misc/AutomationTest.h" +#include "Editor.h" #include "Singleton/InstanceSubsystem/PersistentData.h" +#include "UI/Reward/RewardConcept03Widget.h" #include "UI/Reward/RewardUIModel.h" #include "UObject/StrongObjectPtr.h" @@ -19,8 +21,45 @@ void URewardFlowTestListener::HandleClaimConfirmed(ERewardClaimKind ClaimKind, i mLastConfirmationChoiceIndex = ChoiceIndex; } +void URewardFlowTestListener::HandleExperiencePresentationCompleted() +{ + ++mExperiencePresentationCount; +} + #if WITH_DEV_AUTOMATION_TESTS +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FRestoredExperiencePresentationOrderTest, + "P_RD.UI.Reward.RestoredExperiencePresentationOrder", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter) + +bool FRestoredExperiencePresentationOrderTest::RunTest(const FString& Parameters) +{ + UWorld* World = GEditor ? GEditor->GetEditorWorldContext().World() : nullptr; + if (!TestNotNull(TEXT("Editor world"), World)) return false; + UClass* Class = LoadClass(nullptr, + TEXT("/Game/UI/RewardConcept03New/WBP_RewardConcept03_Frameless_NoArtifact.WBP_RewardConcept03_Frameless_NoArtifact_C")); + if (!TestNotNull(TEXT("Reward screen"), Class)) return false; + URewardConcept03Widget* Widget = CreateWidget(World, Class); + if (!TestNotNull(TEXT("Reward widget"), Widget)) return false; + TStrongObjectPtr Model(NewObject()); + TStrongObjectPtr Listener(NewObject()); + FRewardUI RestoredReward; + RestoredReward.mExpGained = 0; + Model->SetReward(RestoredReward); + Model->OnExperiencePresentationCompleted.AddDynamic(Listener.Get(), + &URewardFlowTestListener::HandleExperiencePresentationCompleted); + Widget->BindUIModel(Model.Get()); + Widget->ResetRewardFlow(); + TestEqual(TEXT("Restored reward starts at experience"), Widget->GetCurrentStepIndex(), 0); + TestEqual(TEXT("Level-up is not requested before experience continues"), + Listener->mExperiencePresentationCount, 0); + Widget->AdvanceRewardFlow(); + TestEqual(TEXT("Experience page advances once"), Listener->mExperiencePresentationCount, 1); + TestEqual(TEXT("Chest page is ready behind level-up choice"), Widget->GetCurrentStepIndex(), 1); + Widget->RemoveFromParent(); + return true; +} + IMPLEMENT_SIMPLE_AUTOMATION_TEST( FRewardClaimAcknowledgementTest, "P_RD.UI.Reward.ClaimAcknowledgement", diff --git a/Source/P_RDTests/UI/RewardFlowTests.h b/Source/P_RDTests/UI/RewardFlowTests.h index 935dfa0b0..863e14a6b 100644 --- a/Source/P_RDTests/UI/RewardFlowTests.h +++ b/Source/P_RDTests/UI/RewardFlowTests.h @@ -18,8 +18,12 @@ class URewardFlowTestListener : public UObject UFUNCTION() void HandleClaimConfirmed(ERewardClaimKind ClaimKind, int32 ChoiceIndex); + UFUNCTION() + void HandleExperiencePresentationCompleted(); + int32 mRequestCount = 0; int32 mConfirmationCount = 0; + int32 mExperiencePresentationCount = 0; ERewardClaimKind mLastRequestKind = ERewardClaimKind::Gold; ERewardClaimKind mLastConfirmationKind = ERewardClaimKind::Gold; int32 mLastRequestChoiceIndex = INDEX_NONE; diff --git a/SourceArt/UI/ReleaseIcons/BlessingOfTime.png b/SourceArt/UI/ReleaseIcons/BlessingOfTime.png new file mode 100644 index 000000000..22ca1a1e8 Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/BlessingOfTime.png differ diff --git a/SourceArt/UI/ReleaseIcons/BrokenClock.png b/SourceArt/UI/ReleaseIcons/BrokenClock.png new file mode 100644 index 000000000..27001bbe9 Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/BrokenClock.png differ diff --git a/SourceArt/UI/ReleaseIcons/Cheat.png b/SourceArt/UI/ReleaseIcons/Cheat.png new file mode 100644 index 000000000..37a66f0db Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/Cheat.png differ diff --git a/SourceArt/UI/ReleaseIcons/HourglassTurn.png b/SourceArt/UI/ReleaseIcons/HourglassTurn.png new file mode 100644 index 000000000..ccb9d4bf8 Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/HourglassTurn.png differ diff --git a/SourceArt/UI/ReleaseIcons/Inkpot.png b/SourceArt/UI/ReleaseIcons/Inkpot.png new file mode 100644 index 000000000..0290b214b Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/Inkpot.png differ diff --git a/SourceArt/UI/ReleaseIcons/MagicHat.png b/SourceArt/UI/ReleaseIcons/MagicHat.png new file mode 100644 index 000000000..a416c538b Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/MagicHat.png differ diff --git a/SourceArt/UI/ReleaseIcons/TickTock.png b/SourceArt/UI/ReleaseIcons/TickTock.png new file mode 100644 index 000000000..29148b781 Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/TickTock.png differ diff --git a/SourceArt/UI/ReleaseIcons/TimeAcceleration.png b/SourceArt/UI/ReleaseIcons/TimeAcceleration.png new file mode 100644 index 000000000..d2519ae8c Binary files /dev/null and b/SourceArt/UI/ReleaseIcons/TimeAcceleration.png differ diff --git a/Tools/Localization/README.md b/Tools/Localization/README.md index 7bd2e3ce1..f040f025a 100644 --- a/Tools/Localization/README.md +++ b/Tools/Localization/README.md @@ -45,6 +45,8 @@ svnversion .\Content\SVN ## ์—์…‹ ์ด๋ฆ„ ๋ณ€๊ฒฝ +ํŠน์ • ์Šคํ‚ฌ์— ์˜ˆ์ „ FText ์›๋ฌธ์ด ์ €์žฅ๋œ ๊ฒฝ์šฐ์—๋Š” `-run=RefreshPullDescriptions -Asset=<์ „์ฒด ์˜ค๋ธŒ์ ํŠธ ๊ฒฝ๋กœ> -Apply`๋กœ ํ•ด๋‹น ์Šคํ‚ฌ์˜ ์„ค๋ช…๋งŒ ์žฌ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: `-Asset=/Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Attack_Rare_SharpenBlade.DA_Rogue_Attack_Rare_SharpenBlade`. ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์‹คํŒจํ•˜๋ฉฐ, `-Apply`๋ฅผ ์ƒ๋žตํ•˜๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋งŒ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. + ํŒŒ์ผ ํƒ์ƒ‰๊ธฐ์—์„œ `.uasset` ์ด๋ฆ„๋งŒ ๋ฐ”๊พธ์ง€ ๋ง๊ณ  Unreal Editor์˜ ์ด๋ฆ„ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ €์žฅ๋œ ์ฐธ์กฐ๋ฅผ ๊ฐฑ์‹ ํ•˜๊ณ  ์ด์ „ redirector์˜ ์ฐธ์กฐ๊ฐ€ ๋‚จ์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•œ ๋‹ค์Œ ๋ฒˆ์—ญ์„ ์žฌ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ๋ฐฐํฌํ•œ ์Šคํ‚ฌ์˜ ์—์…‹ ์ด๋ฆ„์„ ๋ฐ”๊พผ ๊ฒฝ์šฐ์—๋Š” ์ €์žฅ๋œ `FPrimaryAssetId`๋„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณจ๋ ˜์˜ `DA_Goelm_*` โ†’ `DA_Golem_*` ๋ณ€๊ฒฝ์€ `DefaultGame.ini`์˜ `PrimaryAssetIdRedirects`๋กœ ์ด์ „ ID๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, `GolemSkillReferences` ํ…Œ์ŠคํŠธ๊ฐ€ ์‹ค์ œ ์—์…‹ ๋ฐ ์œ ๋‹› ์ฐธ์กฐ์™€ ํ•จ๊ป˜ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. diff --git a/Tools/import_release_icons.py b/Tools/import_release_icons.py new file mode 100644 index 000000000..668acda89 --- /dev/null +++ b/Tools/import_release_icons.py @@ -0,0 +1,51 @@ +"""Import beta 15 icons and bind the eight new production data assets.""" +from pathlib import Path +import json +import unreal + +unreal.SystemLibrary.execute_console_command(None, 'Interchange.FeatureFlags.Import.PNG 0') +source = Path(unreal.Paths.project_dir()) / 'SourceArt/UI/ReleaseIcons' +destination = '/Game/BP/ReleaseIcons' +targets = [ + ('BrokenClock', '/Game/BP/DataAsset/Artifact/DA_Artifact_A046_BrokenClock'), + ('MagicHat', '/Game/BP/DataAsset/Artifact/DA_Artifact_A047_MagicHat'), + ('Inkpot', '/Game/BP/DataAsset/Artifact/DA_Artifact_A048_Inkpot'), + ('HourglassTurn', '/Game/BP/DataAsset/Skill/Common/DA_Common_Spell_Epic_HourglassTurn'), + ('BlessingOfTime', '/Game/BP/DataAsset/Skill/Mercenary/Druid/DA_Druid_Spell_Epic_BlessingOfTime'), + ('TickTock', '/Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Epic_TickTock'), + ('TimeAcceleration', '/Game/BP/DataAsset/Skill/Mercenary/Mage/DA_Mage_Spell_Rare_TimeAcceleration'), + ('Cheat', '/Game/BP/DataAsset/Skill/Mercenary/Rogue/DA_Rogue_Spell_Epic_Cheat'), +] +report = [] +for name, asset_path in targets: + filename = source / (name + '.png') + data = unreal.load_asset(asset_path) + if not filename.is_file() or data is None: + raise RuntimeError('Missing source image or data asset: ' + name) + task = unreal.AssetImportTask() + task.filename = str(filename) + task.destination_path = destination + task.destination_name = 'T_Beta15_' + name + task.automated = True + task.factory = unreal.TextureFactory() + task.replace_existing = True + task.save = False + unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) + texture = unreal.load_asset(destination + '/' + task.destination_name) + if not isinstance(texture, unreal.Texture2D): + raise RuntimeError('Texture import failed: ' + name) + texture.set_editor_property('compression_settings', unreal.TextureCompressionSettings.TC_EDITOR_ICON) + texture.set_editor_property('lod_group', unreal.TextureGroup.TEXTUREGROUP_UI) + texture.set_editor_property('mip_gen_settings', unreal.TextureMipGenSettings.TMGS_NO_MIPMAPS) + texture.set_editor_property('srgb', True) + texture.set_editor_property('max_texture_size', 512) + if not unreal.EditorAssetLibrary.save_loaded_asset(texture): + raise RuntimeError('Texture save failed: ' + name) + data.set_editor_property('mIcon', texture) + if not unreal.EditorAssetLibrary.save_loaded_asset(data): + raise RuntimeError('Data asset save failed: ' + name) + report.append({'asset': data.get_path_name(), 'icon': texture.get_path_name()}) + unreal.log('RELEASE_ICON_MAPPED ' + name) +report_path = Path(unreal.Paths.project_saved_dir()) / 'ReleaseIconBindings.json' +report_path.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding='utf-8') +unreal.log('RELEASE_ICON_IMPORT_COMPLETE count=%d report=%s' % (len(report), report_path))