summaryrefslogtreecommitdiff
path: root/Valheim_v0.141.2_r202102
diff options
context:
space:
mode:
Diffstat (limited to 'Valheim_v0.141.2_r202102')
-rw-r--r--Valheim_v0.141.2_r202102/.gitignore6
-rw-r--r--Valheim_v0.141.2_r202102/Doc/作弊.txt10
-rw-r--r--Valheim_v0.141.2_r202102/Doc/分析/0_分析.xlsxbin0 -> 1697725 bytes
-rw-r--r--Valheim_v0.141.2_r202102/Doc/分析/1_地形生成.xlsxbin0 -> 18088 bytes
-rw-r--r--Valheim_v0.141.2_r202102/Doc/分析/2_寻路.xlsxbin0 -> 317898 bytes
-rw-r--r--Valheim_v0.141.2_r202102/Doc/反编译和mod.txt9
-rw-r--r--Valheim_v0.141.2_r202102/Doc/说明.txt4
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/AlphaMotion.cs18
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonImageColor.cs31
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonSfx.cs54
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonTextColor.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiBar.cs141
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiPixelFix.cs17
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiScaler.cs56
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localization.cs307
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localize.cs9
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/TabHandler.cs102
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGamePad.cs89
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGroupHandler.cs135
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHandler.cs110
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHint.cs40
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UISelectableGroup.cs11
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UITooltip.cs153
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Uirotate.cs11
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/assembly_guiutils.csproj30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles.Demo/LuxParticles_ExtendedFlycam.cs75
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_AmbientLighting.cs224
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_DirectionalLight.cs42
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_LocalAmbientLighting.cs71
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_lux/assembly_lux.csproj21
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/ExampleWheelController.cs38
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionComponent.cs190
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionModel.cs87
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AntialiasingModel.cs222
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomComponent.cs116
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomModel.cs117
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsComponent.cs237
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsModel.cs141
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationComponent.cs63
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationModel.cs49
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingComponent.cs352
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingCurve.cs64
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingModel.cs319
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldComponent.cs155
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldModel.cs71
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringComponent.cs61
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringModel.cs35
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationComponent.cs177
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationModel.cs97
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogComponent.cs97
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogModel.cs44
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FxaaComponent.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GetSetAttribute.cs13
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainComponent.cs62
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainModel.cs59
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GraphicsUtils.cs126
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MaterialFactory.cs43
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MinAttribute.cs11
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurComponent.cs426
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurModel.cs55
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingBehaviour.cs406
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponent.cs17
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentBase.cs23
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentCommandBuffer.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentRenderTexture.cs8
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingContext.cs39
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingModel.cs33
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingProfile.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/RenderTextureFactory.cs57
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionComponent.cs227
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionModel.cs141
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TaaComponent.cs184
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballAttribute.cs11
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballGroupAttribute.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutComponent.cs38
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutModel.cs49
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteComponent.cs48
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteModel.cs87
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/assembly_postprocessing.csproj28
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/RunTimeCombineAndRelease.cs43
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombine.cs171
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombineMaster.cs6
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/assembly_simplemeshcombine.csproj18
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/AAMode.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Antialiasing.cs139
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Bloom.cs333
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomAndFlares.cs257
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomOptimized.cs96
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomScreenBlendMode.cs7
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Blur.cs80
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BlurOptimized.cs84
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CameraMotionBlur.cs382
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionCurves.cs180
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionLookup.cs142
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionRamp.cs16
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastEnhance.cs67
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastStretch.cs178
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CreaseShading.cs76
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfField.cs350
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfFieldDeprecated.cs451
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/EdgeDetection.cs96
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Fisheye.cs43
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/GlobalFog.cs92
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Grayscale.cs20
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/HDRBloomMode.cs8
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffectBase.cs45
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffects.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/LensflareStyle34.cs8
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/MotionBlur.cs52
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndGrain.cs158
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndScratches.cs138
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsBase.cs233
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsHelper.cs172
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Quads.cs102
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenOverlay.cs53
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientObscurance.cs105
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientOcclusion.cs161
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SepiaTone.cs13
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SunShafts.cs134
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TiltShift.cs80
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Tonemapping.cs226
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Triangles.cs95
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TweakMode34.cs7
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Twirl.cs20
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/VignetteAndChromaticAberration.cs110
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Vortex.cs19
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/assembly_sunshafts.csproj18
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/BitMaskAttribute.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Cover.cs82
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/DictionaryExt.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/DrawBounds.cs16
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/HideWhenRunning.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/ListExtra.cs27
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/LookAt.cs35
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Pool.cs30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/QuaternionExt.cs10
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/StringExtensionMethods.cs18
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/SyncedList.cs129
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Timer.cs51
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/TriggerTracker.cs35
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Utils.cs504
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/Vector2i.cs104
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZInput.cs522
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZLog.cs28
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_utils/assembly_utils.csproj28
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/.gitignore399
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimalAI.cs80
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimationEffect.cs102
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Aoe.cs331
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Attack.cs988
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AudioMan.cs496
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AutoJumpLedge.cs19
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BaseAI.cs1461
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beacon.cs46
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Bed.cs201
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beehive.cs186
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Billboard.cs37
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BiomeEnvSetup.cs23
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BossStone.cs111
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CamShaker.cs65
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CameraEffects.cs127
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chair.cs73
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ChangeLog.cs15
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Character.cs2567
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterAnimEvent.cs525
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterDrop.cs118
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs48
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chat.cs568
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CircleProjector.cs63
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ClutterSystem.cs472
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ConnectPanel.cs215
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Console.cs654
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Container.cs417
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CookingStation.cs363
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Corpse.cs67
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CraftingStation.cs317
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CreatureSpawner.cs160
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DLCMan.cs98
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DamageText.cs181
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DepthCamera.cs39
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Destructible.cs213
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DestructibleType.cs7
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DistantFogEmitter.cs114
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Door.cs166
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DreamTexts.cs61
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropOnDestroyed.cs46
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropTable.cs152
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonDB.cs105
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonGenerator.cs787
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectArea.cs108
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectFade.cs66
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectList.cs88
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EmitterRotation.cs37
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnemyHud.cs216
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvEntry.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvMan.cs987
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvSetup.cs108
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvZone.cs49
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EventZone.cs38
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Feedback.cs91
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FejdStartup.cs1393
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fermenter.cs342
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fireplace.cs307
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fish.cs373
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FishingFloat.cs313
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Floating.cs174
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FollowPlayer.cs37
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FootStep.cs401
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Game.cs575
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GameCamera.cs663
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Gibber.cs114
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GlobalWind.cs98
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Growup.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GuidePoint.cs28
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Heightmap.cs1111
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HeightmapBuilder.cs273
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitArea.cs25
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitData.cs625
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HotkeyBar.cs156
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HoverText.cs16
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hoverable.cs6
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hud.cs1171
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Humanoid.cs1550
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IDestructible.cs6
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IEquipmentVisual.cs4
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IProjectile.cs8
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ISocket.cs30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IWaterInteractable.cs10
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ImpactEffect.cs159
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InputFieldSubmit.cs24
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstanceRenderer.cs176
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstantiatePrefab.cs22
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interactable.cs6
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interpolate.cs456
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Inventory.cs755
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGrid.cs378
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGui.cs1535
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemDrop.cs970
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStand.cs392
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStyle.cs9
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/KeyHints.cs95
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ladder.cs50
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ledge.cs40
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LevelEffects.cs99
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Leviathan.cs91
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightFlicker.cs71
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightLod.cs106
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineAttach.cs27
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineConnect.cs141
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Location.cs118
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LocationProxy.cs43
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LodFadeInOut.cs30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LootSpawner.cs89
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MasterClient.cs291
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs344
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Menu.cs131
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuScene.cs41
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuShipMovement.cs23
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MessageHud.cs305
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock.cs233
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock5.cs472
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Minimap.cs1463
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MistEmitter.cs91
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MonsterAI.cs744
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MovementTest.cs30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MusicMan.cs473
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/NavmeshTest.cs62
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ObjectDB.cs104
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Odin.cs55
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/OfferingBowl.cs213
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ParticleDecal.cs42
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pathfinding.cs755
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pickable.cs146
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PickableItem.cs194
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Piece.cs332
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PieceTable.cs224
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Plant.cs243
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Player.cs4732
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerController.cs173
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerCustomizaton.cs176
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerProfile.cs444
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PointGenerator.cs70
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PrivateArea.cs546
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Procreation.cs144
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Projectile.cs375
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ragdoll.cs193
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandEventSystem.cs504
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomAnimation.cs101
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomEvent.cs119
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomFlyingBird.cs273
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomIdle.cs48
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomMovement.cs22
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpawn.cs59
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpeak.cs45
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Raven.cs563
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Recipe.cs37
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ReflectionUpdate.cs84
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Room.cs119
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoomConnection.cs35
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RopeAttachment.cs66
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethod.cs74
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethodBase.cs4
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RuneStone.cs83
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SEMan.cs321
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Burning.cs54
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Cozy.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Finder.cs71
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Frost.cs36
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Harpooned.cs128
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs36
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Poison.cs50
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Rested.cs98
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Shield.cs36
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Smoke.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Spawn.cs32
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Stats.cs322
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Wet.cs41
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SceneLoader.cs23
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs93
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ServerCtrl.cs53
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Settings.cs582
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ship.cs746
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipConstructor.cs58
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipControlls.cs175
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipEffects.cs150
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShuffleClass.cs20
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Sign.cs82
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Skills.cs333
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SkillsDialog.cs56
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SleepText.cs43
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdate.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdater.cs41
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smelter.cs519
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smoke.cs128
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeLod.cs5
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeRenderer.cs26
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeSpawner.cs73
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SnapToGround.cs63
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnAbility.cs164
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnArea.cs198
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnOnDamaged.cs29
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnSystem.cs510
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StateController.cs53
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticPhysics.cs122
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticTarget.cs80
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StationExtension.cs158
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StatusEffect.cs268
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StealthSystem.cs83
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SteamManager.cs166
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StoreGui.cs354
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Switch.cs56
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tail.cs116
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Talker.cs60
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tameable.cs239
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Teleport.cs64
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportHome.cs13
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorld.cs159
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs21
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainLod.cs37
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainModifier.cs246
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestCollision.cs19
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneCharacter.cs82
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneSetup.cs13
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextInput.cs93
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextReceiver.cs6
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextViewer.cs155
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextsDialog.cs196
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ThorFly.cs24
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Thunder.cs133
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TimedDestruction.cs51
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleImage.cs30
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleSwitch.cs53
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TombStone.cs217
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tracker.cs34
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Trader.cs168
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeBase.cs183
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeLog.cs139
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tutorial.cs64
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vagon.cs333
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.csproj273
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.sln25
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valkyrie.cs192
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VariantDialog.cs58
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vegvisir.cs38
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Version.cs101
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VisEquipment.cs1022
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterMark.cs12
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterTrigger.cs24
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterVolume.cs237
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WayStone.cs71
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTear.cs792
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTearUpdater.cs41
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Windmill.cs91
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/World.cs236
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WorldGenerator.cs1069
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZBroastcast.cs174
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector.cs150
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector2.cs131
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDO.cs1076
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOComparer.cs14
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOID.cs105
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOMan.cs1207
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOPool.cs69
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNat.cs32
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNet.cs1488
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetPeer.cs44
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetScene.cs423
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetView.cs226
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNtp.cs137
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZPackage.cs293
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRoutedRpc.cs234
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRpc.cs405
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSFX.cs219
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket.cs449
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket2.cs440
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs427
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamSocket.cs340
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncAnimation.cs217
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncTransform.cs327
-rw-r--r--Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZoneSystem.cs1712
433 files changed, 87546 insertions, 0 deletions
diff --git a/Valheim_v0.141.2_r202102/.gitignore b/Valheim_v0.141.2_r202102/.gitignore
new file mode 100644
index 0000000..223208c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/.gitignore
@@ -0,0 +1,6 @@
+~*.*
+*.log
+Dump
+Valheim/MelonLoader/
+Valheim/Mods/
+Game/ \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Doc/作弊.txt b/Valheim_v0.141.2_r202102/Doc/作弊.txt
new file mode 100644
index 0000000..3daed88
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/作弊.txt
@@ -0,0 +1,10 @@
+https://valheim.fandom.com/wiki/Item_IDs
+https://valheim.fandom.com/wiki/Armor
+https://www.dexerto.com/gaming/valheim-cheats-all-codes-console-commands-how-enter-them-1696329/
+https://www.rockpapershotgun.com/valheim-cheats-spawn-item-list-console-commands-creative-mode#valheim-spawn-item-codes
+
+https://commands.gg/valheim/items
+
+老版本输入imacheater而不是devcommands
+
+
diff --git a/Valheim_v0.141.2_r202102/Doc/分析/0_分析.xlsx b/Valheim_v0.141.2_r202102/Doc/分析/0_分析.xlsx
new file mode 100644
index 0000000..d5e5b83
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/分析/0_分析.xlsx
Binary files differ
diff --git a/Valheim_v0.141.2_r202102/Doc/分析/1_地形生成.xlsx b/Valheim_v0.141.2_r202102/Doc/分析/1_地形生成.xlsx
new file mode 100644
index 0000000..10237e2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/分析/1_地形生成.xlsx
Binary files differ
diff --git a/Valheim_v0.141.2_r202102/Doc/分析/2_寻路.xlsx b/Valheim_v0.141.2_r202102/Doc/分析/2_寻路.xlsx
new file mode 100644
index 0000000..16d6fc4
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/分析/2_寻路.xlsx
Binary files differ
diff --git a/Valheim_v0.141.2_r202102/Doc/反编译和mod.txt b/Valheim_v0.141.2_r202102/Doc/反编译和mod.txt
new file mode 100644
index 0000000..229f382
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/反编译和mod.txt
@@ -0,0 +1,9 @@
+https://www.youtube.com/watch?v=XPFvHo1UCTE&ab_channel=SBToonz
+
+https://github.com/Valheim-Modding/Wiki/wiki/Valheim-Unity-Project-Guide
+
+https://github.com/heinermann/ValheimExportHelper
+
+https://www.youtube.com/watch?v=_61pLVH2qPk&ab_channel=BetterCoder
+
+https://www.youtube.com/watch?v=OanlUYSZkZA&ab_channel=Azumatt \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Doc/说明.txt b/Valheim_v0.141.2_r202102/Doc/说明.txt
new file mode 100644
index 0000000..d0d9dab
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Doc/说明.txt
@@ -0,0 +1,4 @@
+Know-How
+分析源码的目的是为了得到Know-How(实现某效果、目标、目的的具体方法、做法、诀窍,也就是经验)
+
+Valheim非常精炼(凝练),代码量不过7w,缺做到了开放世界、 沙盒、RPG,非常值得学习
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/AlphaMotion.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/AlphaMotion.cs
new file mode 100644
index 0000000..02e4d4c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/AlphaMotion.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+public class AlphaMotion : MonoBehaviour
+{
+ public float m_rotSpeed = 100f;
+
+ public float m_rotAngle = 0.2f;
+
+ private void Start()
+ {
+ }
+
+ private void Update()
+ {
+ float time = Time.time;
+ base.transform.localRotation = Quaternion.Euler(0f, 0f, Mathf.Sin(time * m_rotSpeed) * m_rotAngle);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonImageColor.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonImageColor.cs
new file mode 100644
index 0000000..4591548
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonImageColor.cs
@@ -0,0 +1,31 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ButtonImageColor : MonoBehaviour
+{
+ public Image m_image;
+
+ private Color m_defaultColor = Color.white;
+
+ public Color m_disabledColor = Color.grey;
+
+ private Button m_button;
+
+ private void Awake()
+ {
+ m_button = GetComponent<Button>();
+ m_defaultColor = m_image.color;
+ }
+
+ private void Update()
+ {
+ if (m_button.IsInteractable())
+ {
+ m_image.color = m_defaultColor;
+ }
+ else
+ {
+ m_image.color = m_disabledColor;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonSfx.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonSfx.cs
new file mode 100644
index 0000000..9a4dbb3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonSfx.cs
@@ -0,0 +1,54 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class ButtonSfx : MonoBehaviour, ISelectHandler, IEventSystemHandler
+{
+ public GameObject m_sfxPrefab;
+
+ public GameObject m_selectSfxPrefab;
+
+ private Selectable m_selectable;
+
+ private static int m_lastTriggerFrame;
+
+ private const int m_minDeltaFrames = 2;
+
+ private void Start()
+ {
+ m_selectable = GetComponent<Selectable>();
+ Button button = m_selectable as Button;
+ if ((bool)button)
+ {
+ button.onClick.AddListener(OnClick);
+ return;
+ }
+ Toggle toggle = m_selectable as Toggle;
+ if ((bool)toggle)
+ {
+ toggle.onValueChanged.AddListener(OnChange);
+ }
+ }
+
+ private void OnClick()
+ {
+ if ((bool)m_sfxPrefab && Time.frameCount - m_lastTriggerFrame > 2)
+ {
+ Object.Instantiate(m_sfxPrefab);
+ m_lastTriggerFrame = Time.frameCount;
+ }
+ }
+
+ private void OnChange(bool v)
+ {
+ if ((bool)m_sfxPrefab && Time.frameCount - m_lastTriggerFrame > 2)
+ {
+ Object.Instantiate(m_sfxPrefab);
+ m_lastTriggerFrame = Time.frameCount;
+ }
+ }
+
+ public void OnSelect(BaseEventData eventData)
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonTextColor.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonTextColor.cs
new file mode 100644
index 0000000..050cb7d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/ButtonTextColor.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ButtonTextColor : MonoBehaviour
+{
+ private Color m_defaultColor = Color.white;
+
+ public Color m_disabledColor = Color.grey;
+
+ private Button m_button;
+
+ private Text m_text;
+
+ private Sprite m_sprite;
+
+ private void Awake()
+ {
+ m_button = GetComponent<Button>();
+ m_text = GetComponentInChildren<Text>();
+ m_defaultColor = m_text.color;
+ }
+
+ private void Update()
+ {
+ if (m_button.IsInteractable())
+ {
+ m_text.color = m_defaultColor;
+ }
+ else
+ {
+ m_text.color = m_disabledColor;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiBar.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiBar.cs
new file mode 100644
index 0000000..a43f316
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiBar.cs
@@ -0,0 +1,141 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class GuiBar : MonoBehaviour
+{
+ public RectTransform m_bar;
+
+ public bool m_smoothDrain;
+
+ public bool m_smoothFill;
+
+ public float m_smoothSpeed = 1f;
+
+ public float m_changeDelay;
+
+ private float m_value = 1f;
+
+ private float m_maxValue = 1f;
+
+ private float m_width;
+
+ private float m_smoothValue = 1f;
+
+ private float m_delayTimer;
+
+ private bool m_firstSet = true;
+
+ private Image m_barImage;
+
+ private Color m_originalColor;
+
+ private void Awake()
+ {
+ m_width = m_bar.sizeDelta.x;
+ m_barImage = m_bar.GetComponent<Image>();
+ if ((bool)m_barImage)
+ {
+ m_originalColor = m_barImage.color;
+ }
+ }
+
+ private void OnEnable()
+ {
+ m_delayTimer = 0f;
+ m_smoothValue = Mathf.Clamp01(m_value / m_maxValue);
+ }
+
+ public void SetWidth(float width)
+ {
+ if (m_width != width)
+ {
+ m_width = width;
+ m_bar.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, m_width * m_smoothValue);
+ }
+ }
+
+ public void SetValue(float value)
+ {
+ if (m_value == value && !m_firstSet)
+ {
+ return;
+ }
+ if (m_firstSet)
+ {
+ m_firstSet = false;
+ m_value = value;
+ m_smoothValue = Mathf.Clamp01(m_value / m_maxValue);
+ SetBar(m_smoothValue);
+ }
+ else
+ {
+ if ((value < m_value && m_smoothDrain) || (value > m_value && m_smoothFill))
+ {
+ m_delayTimer = m_changeDelay;
+ }
+ m_value = value;
+ }
+ }
+
+ public void SetMaxValue(float value)
+ {
+ if (m_maxValue != value)
+ {
+ float num = m_smoothValue * m_maxValue;
+ m_maxValue = value;
+ m_smoothValue = Mathf.Clamp01(num / m_maxValue);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ m_delayTimer -= Time.deltaTime;
+ if (m_delayTimer <= 0f)
+ {
+ float num = Mathf.Clamp01(m_value / m_maxValue);
+ if (num > m_smoothValue && m_smoothFill)
+ {
+ m_smoothValue = Mathf.Clamp01(Mathf.MoveTowards(m_smoothValue, num, m_smoothSpeed * Time.deltaTime));
+ }
+ else if (num < m_smoothValue && m_smoothDrain)
+ {
+ m_smoothValue = Mathf.Clamp01(Mathf.MoveTowards(m_smoothValue, num, m_smoothSpeed * Time.deltaTime));
+ }
+ else
+ {
+ m_smoothValue = num;
+ }
+ SetBar(m_smoothValue);
+ }
+ }
+
+ private void SetBar(float i)
+ {
+ m_bar.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, m_width * i);
+ }
+
+ public void SetColor(Color color)
+ {
+ if ((bool)m_barImage)
+ {
+ m_barImage.color = color;
+ }
+ }
+
+ public Color GetColor()
+ {
+ if ((bool)m_barImage)
+ {
+ return m_barImage.color;
+ }
+ return Color.white;
+ }
+
+ public void ResetColor()
+ {
+ if ((bool)m_barImage)
+ {
+ m_barImage.color = m_originalColor;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiPixelFix.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiPixelFix.cs
new file mode 100644
index 0000000..0c00a86
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiPixelFix.cs
@@ -0,0 +1,17 @@
+using UnityEngine;
+
+public class GuiPixelFix : MonoBehaviour
+{
+ private void LateUpdate()
+ {
+ RectTransform rectTransform = base.transform as RectTransform;
+ if (!(rectTransform.parent == null))
+ {
+ Rect rect = (rectTransform.parent as RectTransform).rect;
+ Vector2 offsetMax = rectTransform.offsetMax;
+ offsetMax.x = ((rect.width % 2f != 0f) ? 1 : 0);
+ offsetMax.y = ((rect.height % 2f != 0f) ? 1 : 0);
+ rectTransform.offsetMax = offsetMax;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiScaler.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiScaler.cs
new file mode 100644
index 0000000..6d556ab
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/GuiScaler.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class GuiScaler : MonoBehaviour
+{
+ private static List<GuiScaler> m_scalers = new List<GuiScaler>();
+
+ private static int m_minWidth = 1920;
+
+ private static int m_minHeight = 1080;
+
+ private CanvasScaler m_canvasScaler;
+
+ private static float m_largeGuiScale = 1f;
+
+ private void Awake()
+ {
+ m_canvasScaler = GetComponent<CanvasScaler>();
+ m_scalers.Add(this);
+ m_largeGuiScale = PlayerPrefs.GetFloat("GuiScale", 1f);
+ }
+
+ private void OnDestroy()
+ {
+ m_scalers.Remove(this);
+ }
+
+ private void Update()
+ {
+ UpdateScale();
+ }
+
+ private void UpdateScale()
+ {
+ float screenSizeFactor = GetScreenSizeFactor();
+ m_canvasScaler.scaleFactor = screenSizeFactor;
+ }
+
+ private float GetScreenSizeFactor()
+ {
+ float a = (float)Screen.width / (float)m_minWidth;
+ float b = (float)Screen.height / (float)m_minHeight;
+ return Mathf.Min(a, b) * m_largeGuiScale;
+ }
+
+ public static void LoadGuiScale()
+ {
+ m_largeGuiScale = PlayerPrefs.GetFloat("GuiScale", 1f);
+ }
+
+ public static void SetScale(float scale)
+ {
+ m_largeGuiScale = scale;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localization.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localization.cs
new file mode 100644
index 0000000..243a09c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localization.cs
@@ -0,0 +1,307 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Localization
+{
+ private static Localization m_instance;
+
+ private char[] m_endChars = " (){}[]+-!?/\\\\&%,.:-=<>\n".ToCharArray();
+
+ private Dictionary<string, string> m_translations = new Dictionary<string, string>();
+
+ private List<string> m_languages = new List<string>();
+
+ public static Localization instance
+ {
+ get
+ {
+ if (m_instance == null)
+ {
+ Initialize();
+ }
+ return m_instance;
+ }
+ }
+
+ private static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new Localization();
+ }
+ }
+
+ private Localization()
+ {
+ m_languages = LoadLanguages();
+ SetupLanguage("English");
+ string @string = PlayerPrefs.GetString("language", "");
+ if (@string != "")
+ {
+ SetupLanguage(@string);
+ }
+ }
+
+ public void SetLanguage(string language)
+ {
+ PlayerPrefs.SetString("language", language);
+ }
+
+ public string GetSelectedLanguage()
+ {
+ return PlayerPrefs.GetString("language", "English");
+ }
+
+ public string GetNextLanguage(string lang)
+ {
+ for (int i = 0; i < m_languages.Count; i++)
+ {
+ if (m_languages[i] == lang)
+ {
+ if (i + 1 < m_languages.Count)
+ {
+ return m_languages[i + 1];
+ }
+ return m_languages[0];
+ }
+ }
+ return m_languages[0];
+ }
+
+ public string GetPrevLanguage(string lang)
+ {
+ for (int i = 0; i < m_languages.Count; i++)
+ {
+ if (m_languages[i] == lang)
+ {
+ if (i - 1 >= 0)
+ {
+ return m_languages[i - 1];
+ }
+ return m_languages[m_languages.Count - 1];
+ }
+ }
+ return m_languages[0];
+ }
+
+ public void Localize(Transform root)
+ {
+ Text[] componentsInChildren = root.gameObject.GetComponentsInChildren<Text>(includeInactive: true);
+ foreach (Text text in componentsInChildren)
+ {
+ text.text = Localize(text.text);
+ }
+ }
+
+ public string Localize(string text, params string[] words)
+ {
+ string text2 = Localize(text);
+ return InsertWords(text2, words);
+ }
+
+ private string InsertWords(string text, string[] words)
+ {
+ for (int i = 0; i < words.Length; i++)
+ {
+ string newValue = words[i];
+ text = text.Replace("$" + (i + 1), newValue);
+ }
+ return text;
+ }
+
+ public string Localize(string text)
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ int num = 0;
+ string word;
+ int wordStart;
+ int wordEnd;
+ while (FindNextWord(text, num, out word, out wordStart, out wordEnd))
+ {
+ stringBuilder.Append(text.Substring(num, wordStart - num));
+ stringBuilder.Append(Translate(word));
+ num = wordEnd;
+ }
+ stringBuilder.Append(text.Substring(num));
+ return stringBuilder.ToString();
+ }
+
+ private bool FindNextWord(string text, int startIndex, out string word, out int wordStart, out int wordEnd)
+ {
+ if (startIndex >= text.Length - 1)
+ {
+ word = null;
+ wordStart = -1;
+ wordEnd = -1;
+ return false;
+ }
+ wordStart = text.IndexOf('$', startIndex);
+ if (wordStart != -1)
+ {
+ int num = text.IndexOfAny(m_endChars, wordStart);
+ if (num != -1)
+ {
+ word = text.Substring(wordStart + 1, num - wordStart - 1);
+ wordEnd = num;
+ }
+ else
+ {
+ word = text.Substring(wordStart + 1);
+ wordEnd = text.Length;
+ }
+ return true;
+ }
+ word = null;
+ wordEnd = -1;
+ return false;
+ }
+
+ private string Translate(string word)
+ {
+ if (word.StartsWith("KEY_"))
+ {
+ string bindingName = word.Substring(4);
+ return GetBoundKeyString(bindingName);
+ }
+ if (m_translations.TryGetValue(word, out var value))
+ {
+ return value;
+ }
+ return "[" + word + "]";
+ }
+
+ public string GetBoundKeyString(string bindingName)
+ {
+ string boundKeyString = ZInput.instance.GetBoundKeyString(bindingName);
+ if (boundKeyString.Length > 0 && boundKeyString[0] == '$' && m_translations.TryGetValue(boundKeyString.Substring(1), out var value))
+ {
+ return value;
+ }
+ return boundKeyString;
+ }
+
+ private void AddWord(string key, string text)
+ {
+ m_translations.Remove(key);
+ m_translations.Add(key, text);
+ }
+
+ private void Clear()
+ {
+ m_translations.Clear();
+ }
+
+ public bool SetupLanguage(string language)
+ {
+ TextAsset textAsset = Resources.Load("localization", typeof(TextAsset)) as TextAsset;
+ if (textAsset == null)
+ {
+ ZLog.LogWarning("Failed to load language file");
+ return false;
+ }
+ StringReader stringReader = new StringReader(textAsset.text);
+ string[] array = stringReader.ReadLine().Split(',');
+ int num = -1;
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i] == language)
+ {
+ num = i;
+ break;
+ }
+ }
+ if (num == -1)
+ {
+ ZLog.LogWarning("Failed to find language:" + language);
+ return false;
+ }
+ List<List<string>> list = DoQuoteLineSplit(stringReader);
+ ZLog.Log("Lines " + list.Count);
+ foreach (List<string> item in list)
+ {
+ if (item.Count == 0)
+ {
+ continue;
+ }
+ string text = item[0];
+ if (text.StartsWith("//") || text.Length == 0)
+ {
+ continue;
+ }
+ if (item.Count <= num)
+ {
+ ZLog.Log("Missing " + language + " translation for:" + text);
+ continue;
+ }
+ string text2 = item[num];
+ if (string.IsNullOrEmpty(text2) || text2[0] == '\r')
+ {
+ ZLog.Log("Missing translation for " + text);
+ text2 = item[1];
+ }
+ AddWord(text, text2);
+ }
+ ZLog.Log("Loaded localization " + language);
+ return true;
+ }
+
+ private List<List<string>> DoQuoteLineSplit(StringReader reader)
+ {
+ List<List<string>> list = new List<List<string>>();
+ List<string> list2 = new List<string>();
+ StringBuilder stringBuilder = new StringBuilder();
+ bool flag = false;
+ while (true)
+ {
+ int num = reader.Read();
+ switch (num)
+ {
+ case -1:
+ list2.Add(stringBuilder.ToString());
+ list.Add(list2);
+ return list;
+ case 34:
+ flag = !flag;
+ continue;
+ case 44:
+ if (!flag)
+ {
+ list2.Add(stringBuilder.ToString());
+ stringBuilder.Length = 0;
+ continue;
+ }
+ break;
+ }
+ if (num == 10 && !flag)
+ {
+ list2.Add(stringBuilder.ToString());
+ stringBuilder.Length = 0;
+ list.Add(list2);
+ list2 = new List<string>();
+ }
+ else
+ {
+ stringBuilder.Append((char)num);
+ }
+ }
+ }
+
+ public List<string> GetLanguages()
+ {
+ return m_languages;
+ }
+
+ private List<string> LoadLanguages()
+ {
+ string[] array = new StringReader((Resources.Load("localization", typeof(TextAsset)) as TextAsset).text).ReadLine().Split(',');
+ List<string> list = new List<string>();
+ for (int i = 1; i < array.Length; i++)
+ {
+ list.Add(array[i]);
+ }
+ return list;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localize.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localize.cs
new file mode 100644
index 0000000..39ae6c5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Localize.cs
@@ -0,0 +1,9 @@
+using UnityEngine;
+
+public class Localize : MonoBehaviour
+{
+ private void Awake()
+ {
+ Localization.instance.Localize(base.transform);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/TabHandler.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/TabHandler.cs
new file mode 100644
index 0000000..ae40fc7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/TabHandler.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.UI;
+
+public class TabHandler : MonoBehaviour
+{
+ [Serializable]
+ public class Tab
+ {
+ public Button m_button;
+
+ public RectTransform m_page;
+
+ public bool m_default;
+
+ public UnityEvent m_onClick;
+ }
+
+ public bool m_gamepadInput;
+
+ public List<Tab> m_tabs = new List<Tab>();
+
+ private int m_selected;
+
+ private void Awake()
+ {
+ int activeTab = 0;
+ for (int i = 0; i < m_tabs.Count; i++)
+ {
+ Tab tab = m_tabs[i];
+ tab.m_button.onClick.AddListener(delegate
+ {
+ OnClick(tab.m_button);
+ });
+ Transform transform = tab.m_button.gameObject.transform.Find("Selected");
+ if ((bool)transform)
+ {
+ transform.GetComponentInChildren<Text>().text = tab.m_button.GetComponentInChildren<Text>().text;
+ }
+ if (tab.m_default)
+ {
+ activeTab = i;
+ }
+ }
+ SetActiveTab(activeTab);
+ }
+
+ private void Update()
+ {
+ if (m_gamepadInput)
+ {
+ if (ZInput.GetButtonDown("JoyTabLeft"))
+ {
+ SetActiveTab(Mathf.Max(0, m_selected - 1));
+ }
+ if (ZInput.GetButtonDown("JoyTabRight"))
+ {
+ SetActiveTab(Mathf.Min(m_tabs.Count - 1, m_selected + 1));
+ }
+ }
+ }
+
+ private void OnClick(Button button)
+ {
+ SetActiveTab(button);
+ }
+
+ private void SetActiveTab(Button button)
+ {
+ for (int i = 0; i < m_tabs.Count; i++)
+ {
+ if (m_tabs[i].m_button == button)
+ {
+ SetActiveTab(i);
+ break;
+ }
+ }
+ }
+
+ public void SetActiveTab(int index)
+ {
+ m_selected = index;
+ for (int i = 0; i < m_tabs.Count; i++)
+ {
+ Tab tab = m_tabs[i];
+ bool flag = i == index;
+ tab.m_page.gameObject.SetActive(flag);
+ tab.m_button.interactable = !flag;
+ Transform transform = tab.m_button.gameObject.transform.Find("Selected");
+ if ((bool)transform)
+ {
+ transform.gameObject.SetActive(flag);
+ }
+ if (flag)
+ {
+ tab.m_onClick.Invoke();
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGamePad.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGamePad.cs
new file mode 100644
index 0000000..1bab59e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGamePad.cs
@@ -0,0 +1,89 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class UIGamePad : MonoBehaviour
+{
+ public KeyCode m_keyCode;
+
+ public string m_zinputKey;
+
+ public GameObject m_hint;
+
+ private Button m_button;
+
+ private Toggle m_toggle;
+
+ private UIGroupHandler m_group;
+
+ private static int m_lastInteractFrame;
+
+ private void Start()
+ {
+ m_group = GetComponentInParent<UIGroupHandler>();
+ m_button = GetComponent<Button>();
+ m_toggle = GetComponent<Toggle>();
+ if ((bool)m_hint)
+ {
+ m_hint.SetActive(value: false);
+ }
+ }
+
+ private bool IsInteractive()
+ {
+ if (m_button != null && !m_button.IsInteractable())
+ {
+ return false;
+ }
+ if ((bool)m_toggle)
+ {
+ if (!m_toggle.IsInteractable())
+ {
+ return false;
+ }
+ if ((bool)m_toggle.group && !m_toggle.group.allowSwitchOff && m_toggle.isOn)
+ {
+ return false;
+ }
+ }
+ if ((bool)m_group && !m_group.IsActive())
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void Update()
+ {
+ bool flag = IsInteractive();
+ if ((bool)m_hint)
+ {
+ m_hint.SetActive(flag && ZInput.IsGamepadActive());
+ }
+ if (flag && Time.frameCount - m_lastInteractFrame >= 2 && ButtonPressed())
+ {
+ m_lastInteractFrame = Time.frameCount;
+ ZLog.Log("Button pressed " + base.gameObject.name + " frame:" + Time.frameCount);
+ if (m_button != null)
+ {
+ m_button.OnSubmit(null);
+ }
+ if (m_toggle != null)
+ {
+ m_toggle.OnSubmit(null);
+ }
+ }
+ }
+
+ private bool ButtonPressed()
+ {
+ if (!string.IsNullOrEmpty(m_zinputKey) && ZInput.GetButtonDown(m_zinputKey))
+ {
+ return true;
+ }
+ if (m_keyCode != 0 && Input.GetKeyDown(m_keyCode))
+ {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGroupHandler.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGroupHandler.cs
new file mode 100644
index 0000000..e0d6cde
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIGroupHandler.cs
@@ -0,0 +1,135 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class UIGroupHandler : MonoBehaviour
+{
+ public GameObject m_defaultElement;
+
+ public GameObject m_enableWhenActiveAndGamepad;
+
+ public int m_groupPriority;
+
+ private CanvasGroup m_canvasGroup;
+
+ private bool m_userActive = true;
+
+ private bool m_active = true;
+
+ private static List<UIGroupHandler> m_groups = new List<UIGroupHandler>();
+
+ private void Awake()
+ {
+ m_groups.Add(this);
+ m_canvasGroup = GetComponent<CanvasGroup>();
+ }
+
+ private void OnDestroy()
+ {
+ m_groups.Remove(this);
+ }
+
+ private void OnEnable()
+ {
+ }
+
+ private void OnDisable()
+ {
+ if (m_active)
+ {
+ m_active = false;
+ ResetActiveElement();
+ }
+ }
+
+ private Selectable FindSelectable(GameObject root)
+ {
+ return root.GetComponentInChildren<Selectable>(includeInactive: false);
+ }
+
+ private bool IsHighestPriority()
+ {
+ if (!m_userActive)
+ {
+ return false;
+ }
+ foreach (UIGroupHandler group in m_groups)
+ {
+ if (!(group == this) && group.gameObject.activeInHierarchy && group.m_groupPriority > m_groupPriority)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void ResetActiveElement()
+ {
+ if ((bool)EventSystem.current && (bool)EventSystem.current.currentSelectedGameObject && EventSystem.current.currentSelectedGameObject.gameObject.GetComponentInParent<UIGroupHandler>() == this)
+ {
+ EventSystem.current.SetSelectedGameObject(null);
+ }
+ }
+
+ private void Update()
+ {
+ bool flag = IsHighestPriority();
+ if (flag != m_active)
+ {
+ ZLog.Log("UI Group status changed " + base.gameObject.name + " = " + flag);
+ ResetActiveElement();
+ }
+ m_active = flag;
+ if ((bool)m_canvasGroup)
+ {
+ m_canvasGroup.interactable = flag;
+ }
+ if ((bool)m_enableWhenActiveAndGamepad)
+ {
+ m_enableWhenActiveAndGamepad.SetActive(m_active && ZInput.IsGamepadActive());
+ }
+ if (m_active && m_defaultElement != null && ZInput.IsGamepadActive() && !HaveSelectedObject())
+ {
+ Selectable selectable = FindSelectable(m_defaultElement);
+ if ((bool)selectable)
+ {
+ ZLog.Log("Activating default element " + m_defaultElement.name);
+ EventSystem.current.SetSelectedGameObject(selectable.gameObject);
+ selectable.OnSelect(null);
+ }
+ }
+ }
+
+ private bool HaveSelectedObject()
+ {
+ if (EventSystem.current.currentSelectedGameObject == null)
+ {
+ return false;
+ }
+ if (!EventSystem.current.currentSelectedGameObject.activeInHierarchy)
+ {
+ return false;
+ }
+ Selectable component = EventSystem.current.currentSelectedGameObject.GetComponent<Selectable>();
+ if ((bool)component && !component.IsInteractable())
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public void SetActive(bool active)
+ {
+ m_userActive = active;
+ if (!m_userActive && (bool)m_enableWhenActiveAndGamepad)
+ {
+ m_enableWhenActiveAndGamepad.SetActive(value: false);
+ }
+ }
+
+ public bool IsActive()
+ {
+ return m_active;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHandler.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHandler.cs
new file mode 100644
index 0000000..7086fca
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHandler.cs
@@ -0,0 +1,110 @@
+using System;
+using UnityEngine;
+using UnityEngine.EventSystems;
+
+public class UIInputHandler : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler
+{
+ public Action<UIInputHandler> m_onLeftClick;
+
+ public Action<UIInputHandler> m_onLeftDown;
+
+ public Action<UIInputHandler> m_onLeftUp;
+
+ public Action<UIInputHandler> m_onRightClick;
+
+ public Action<UIInputHandler> m_onRightDown;
+
+ public Action<UIInputHandler> m_onRightUp;
+
+ public Action<UIInputHandler> m_onMiddleClick;
+
+ public Action<UIInputHandler> m_onMiddleDown;
+
+ public Action<UIInputHandler> m_onMiddleUp;
+
+ public Action<UIInputHandler> m_onPointerEnter;
+
+ public Action<UIInputHandler> m_onPointerExit;
+
+ public void OnPointerDown(PointerEventData eventData)
+ {
+ if (eventData.button == PointerEventData.InputButton.Right)
+ {
+ if (m_onRightDown != null)
+ {
+ m_onRightDown(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Left)
+ {
+ if (m_onLeftDown != null)
+ {
+ m_onLeftDown(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Middle && m_onMiddleDown != null)
+ {
+ m_onMiddleDown(this);
+ }
+ }
+
+ public void OnPointerUp(PointerEventData eventData)
+ {
+ if (eventData.button == PointerEventData.InputButton.Right)
+ {
+ if (m_onRightUp != null)
+ {
+ m_onRightUp(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Left)
+ {
+ if (m_onLeftUp != null)
+ {
+ m_onLeftUp(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Middle && m_onMiddleUp != null)
+ {
+ m_onMiddleUp(this);
+ }
+ }
+
+ public void OnPointerClick(PointerEventData eventData)
+ {
+ if (eventData.button == PointerEventData.InputButton.Right)
+ {
+ if (m_onRightClick != null)
+ {
+ m_onRightClick(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Left)
+ {
+ if (m_onLeftClick != null)
+ {
+ m_onLeftClick(this);
+ }
+ }
+ else if (eventData.button == PointerEventData.InputButton.Middle && m_onMiddleClick != null)
+ {
+ m_onMiddleClick(this);
+ }
+ }
+
+ public void OnPointerEnter(PointerEventData eventData)
+ {
+ if (m_onPointerEnter != null)
+ {
+ m_onPointerEnter(this);
+ }
+ }
+
+ public void OnPointerExit(PointerEventData eventData)
+ {
+ if (m_onPointerExit != null)
+ {
+ m_onPointerExit(this);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHint.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHint.cs
new file mode 100644
index 0000000..6701a54
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UIInputHint.cs
@@ -0,0 +1,40 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class UIInputHint : MonoBehaviour
+{
+ public GameObject m_gamepadHint;
+
+ public GameObject m_mouseKeyboardHint;
+
+ private Button m_button;
+
+ private UIGroupHandler m_group;
+
+ private void Start()
+ {
+ m_group = GetComponentInParent<UIGroupHandler>();
+ m_button = GetComponent<Button>();
+ if ((bool)m_gamepadHint)
+ {
+ m_gamepadHint.SetActive(value: false);
+ }
+ if ((bool)m_mouseKeyboardHint)
+ {
+ m_mouseKeyboardHint.SetActive(value: false);
+ }
+ }
+
+ private void Update()
+ {
+ bool flag = (m_button == null || m_button.IsInteractable()) && (m_group == null || m_group.IsActive());
+ if (m_gamepadHint != null)
+ {
+ m_gamepadHint.SetActive(flag && ZInput.IsGamepadActive());
+ }
+ if (m_mouseKeyboardHint != null)
+ {
+ m_mouseKeyboardHint.SetActive(flag && ZInput.IsMouseActive());
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UISelectableGroup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UISelectableGroup.cs
new file mode 100644
index 0000000..1aa87c1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UISelectableGroup.cs
@@ -0,0 +1,11 @@
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class UISelectableGroup : Selectable
+{
+ public override void OnSelect(BaseEventData eventData)
+ {
+ base.OnSelect(eventData);
+ ZLog.Log("Select a child");
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UITooltip.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UITooltip.cs
new file mode 100644
index 0000000..2e667f9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/UITooltip.cs
@@ -0,0 +1,153 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class UITooltip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
+{
+ public GameObject m_tooltipPrefab;
+
+ public string m_text = "";
+
+ public string m_topic = "";
+
+ public GameObject m_gamepadFocusObject;
+
+ private static UITooltip m_current;
+
+ private static GameObject m_tooltip;
+
+ private static GameObject m_hovered;
+
+ private const float m_showDelay = 0.5f;
+
+ private float m_showTimer;
+
+ private void LateUpdate()
+ {
+ if (m_current == this && !m_tooltip.activeSelf)
+ {
+ m_showTimer += Time.deltaTime;
+ if (m_showTimer > 0.5f)
+ {
+ m_tooltip.SetActive(value: true);
+ }
+ }
+ if (ZInput.IsGamepadActive() && !ZInput.IsMouseActive())
+ {
+ if (m_gamepadFocusObject != null)
+ {
+ if (m_gamepadFocusObject.activeSelf && m_current != this)
+ {
+ OnHoverStart(m_gamepadFocusObject);
+ }
+ else if (!m_gamepadFocusObject.activeSelf && m_current == this)
+ {
+ HideTooltip();
+ }
+ if (m_current == this && m_tooltip != null)
+ {
+ RectTransform obj = base.gameObject.transform as RectTransform;
+ Vector3[] array = new Vector3[4];
+ obj.GetWorldCorners(array);
+ m_tooltip.transform.position = array[2];
+ Utils.ClampUIToScreen(m_tooltip.transform as RectTransform);
+ }
+ }
+ }
+ else if (m_current == this)
+ {
+ if (m_hovered == null)
+ {
+ HideTooltip();
+ return;
+ }
+ if (!RectTransformUtility.RectangleContainsScreenPoint(m_hovered.transform as RectTransform, Input.mousePosition))
+ {
+ HideTooltip();
+ return;
+ }
+ m_tooltip.transform.position = Input.mousePosition;
+ Utils.ClampUIToScreen(m_tooltip.transform as RectTransform);
+ }
+ }
+
+ private void OnDisable()
+ {
+ if (m_current == this)
+ {
+ HideTooltip();
+ }
+ }
+
+ public void OnPointerEnter(PointerEventData eventData)
+ {
+ OnHoverStart(eventData.pointerEnter);
+ }
+
+ private void OnHoverStart(GameObject go)
+ {
+ if ((bool)m_current)
+ {
+ HideTooltip();
+ }
+ if (m_tooltip == null && (m_text != "" || m_topic != ""))
+ {
+ m_tooltip = Object.Instantiate(m_tooltipPrefab, base.transform.GetComponentInParent<Canvas>().transform);
+ UpdateTextElements();
+ Utils.ClampUIToScreen(m_tooltip.transform as RectTransform);
+ m_hovered = go;
+ m_current = this;
+ m_tooltip.SetActive(value: false);
+ m_showTimer = 0f;
+ }
+ }
+
+ private void UpdateTextElements()
+ {
+ if (m_tooltip != null)
+ {
+ Transform transform = Utils.FindChild(m_tooltip.transform, "Text");
+ if (transform != null)
+ {
+ transform.GetComponent<Text>().text = Localization.instance.Localize(m_text);
+ }
+ Transform transform2 = Utils.FindChild(m_tooltip.transform, "Topic");
+ if (transform2 != null)
+ {
+ transform2.GetComponent<Text>().text = Localization.instance.Localize(m_topic);
+ }
+ }
+ }
+
+ public void OnPointerExit(PointerEventData eventData)
+ {
+ if (m_current == this)
+ {
+ HideTooltip();
+ }
+ }
+
+ public static void HideTooltip()
+ {
+ if ((bool)m_tooltip)
+ {
+ Object.Destroy(m_tooltip);
+ m_current = null;
+ m_tooltip = null;
+ m_hovered = null;
+ }
+ }
+
+ public void Set(string topic, string text)
+ {
+ if (!(topic == m_topic) || !(text == m_text))
+ {
+ m_topic = topic;
+ m_text = text;
+ if (m_current == this && m_tooltip != null)
+ {
+ UpdateTextElements();
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Uirotate.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Uirotate.cs
new file mode 100644
index 0000000..32e8872
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/Uirotate.cs
@@ -0,0 +1,11 @@
+using UnityEngine;
+
+public class Uirotate : MonoBehaviour
+{
+ public float m_speed = 1f;
+
+ private void Update()
+ {
+ base.transform.Rotate(0f, 0f, Time.deltaTime * m_speed);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/assembly_guiutils.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/assembly_guiutils.csproj
new file mode 100644
index 0000000..237e9bc
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_guiutils/assembly_guiutils.csproj
@@ -0,0 +1,30 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_guiutils</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UI">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UI.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_utils">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_utils.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles.Demo/LuxParticles_ExtendedFlycam.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles.Demo/LuxParticles_ExtendedFlycam.cs
new file mode 100644
index 0000000..a5c7242
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles.Demo/LuxParticles_ExtendedFlycam.cs
@@ -0,0 +1,75 @@
+using UnityEngine;
+
+namespace LuxParticles.Demo;
+
+public class LuxParticles_ExtendedFlycam : MonoBehaviour
+{
+ public float cameraSensitivity = 90f;
+
+ public float climbSpeed = 4f;
+
+ public float normalMoveSpeed = 10f;
+
+ public float slowMoveFactor = 0.25f;
+
+ public float fastMoveFactor = 3f;
+
+ private float rotationX;
+
+ private float rotationY;
+
+ private bool isOrtho;
+
+ private Camera cam;
+
+ private void Start()
+ {
+ rotationX = base.transform.eulerAngles.y;
+ cam = GetComponent<Camera>();
+ if (cam != null)
+ {
+ isOrtho = cam.orthographic;
+ }
+ }
+
+ private void Update()
+ {
+ float deltaTime = Time.deltaTime;
+ rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * deltaTime;
+ rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * deltaTime;
+ rotationY = Mathf.Clamp(rotationY, -90f, 90f);
+ Quaternion b = Quaternion.AngleAxis(rotationX, Vector3.up);
+ b *= Quaternion.AngleAxis(rotationY, Vector3.left);
+ base.transform.localRotation = Quaternion.Slerp(base.transform.localRotation, b, deltaTime * 6f);
+ if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
+ {
+ base.transform.position += base.transform.forward * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Vertical") * deltaTime;
+ base.transform.position += base.transform.right * (normalMoveSpeed * fastMoveFactor) * Input.GetAxis("Horizontal") * deltaTime;
+ }
+ else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
+ {
+ base.transform.position += base.transform.forward * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Vertical") * deltaTime;
+ base.transform.position += base.transform.right * (normalMoveSpeed * slowMoveFactor) * Input.GetAxis("Horizontal") * deltaTime;
+ }
+ else
+ {
+ if (isOrtho)
+ {
+ cam.orthographicSize *= 1f - Input.GetAxis("Vertical") * deltaTime;
+ }
+ else
+ {
+ base.transform.position += base.transform.forward * normalMoveSpeed * Input.GetAxis("Vertical") * deltaTime;
+ }
+ base.transform.position += base.transform.right * normalMoveSpeed * Input.GetAxis("Horizontal") * deltaTime;
+ }
+ if (Input.GetKey(KeyCode.Q))
+ {
+ base.transform.position -= base.transform.up * climbSpeed * deltaTime;
+ }
+ if (Input.GetKey(KeyCode.E))
+ {
+ base.transform.position += base.transform.up * climbSpeed * deltaTime;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_AmbientLighting.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_AmbientLighting.cs
new file mode 100644
index 0000000..1319d84
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_AmbientLighting.cs
@@ -0,0 +1,224 @@
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace LuxParticles;
+
+[ExecuteInEditMode]
+public class LuxParticles_AmbientLighting : MonoBehaviour
+{
+ public bool UpdatePerFrame = true;
+
+ public bool AlwaysUseSH;
+
+ private SphericalHarmonicsL2 probe;
+
+ private Vector4[] SHLighting = new Vector4[7];
+
+ private int Lux_SHAr;
+
+ private int Lux_SHAg;
+
+ private int Lux_SHAb;
+
+ private int Lux_SHBr;
+
+ private int Lux_SHBg;
+
+ private int Lux_SHBb;
+
+ private int Lux_SHC;
+
+ private int Lux_L_SHAr;
+
+ private int Lux_L_SHAg;
+
+ private int Lux_L_SHAb;
+
+ private int Lux_L_SHBr;
+
+ private int Lux_L_SHBg;
+
+ private int Lux_L_SHBb;
+
+ private int Lux_L_SHC;
+
+ private int Lux_AmbientMode;
+
+ private const float k0 = 0.2820948f;
+
+ private const float k1 = 0.48860252f;
+
+ private const float k2 = 1.0925485f;
+
+ private const float k3 = 0.31539157f;
+
+ private const float k4 = 0.54627424f;
+
+ private static float[] ks = new float[9] { 0.2820948f, -0.48860252f, 0.48860252f, -0.48860252f, 1.0925485f, -1.0925485f, 0.31539157f, -1.0925485f, 0.54627424f };
+
+ private int managedParticleSystems;
+
+ private void OnEnable()
+ {
+ Lux_SHAr = Shader.PropertyToID("_Lux_SHAr");
+ Lux_SHAg = Shader.PropertyToID("_Lux_SHAg");
+ Lux_SHAb = Shader.PropertyToID("_Lux_SHAb");
+ Lux_SHBr = Shader.PropertyToID("_Lux_SHBr");
+ Lux_SHBg = Shader.PropertyToID("_Lux_SHBg");
+ Lux_SHBb = Shader.PropertyToID("_Lux_SHBb");
+ Lux_SHC = Shader.PropertyToID("_Lux_SHC");
+ Lux_L_SHAr = Shader.PropertyToID("_Lux_L_SHAr");
+ Lux_L_SHAg = Shader.PropertyToID("_Lux_L_SHAg");
+ Lux_L_SHAb = Shader.PropertyToID("_Lux_L_SHAb");
+ Lux_L_SHBr = Shader.PropertyToID("_Lux_L_SHBr");
+ Lux_L_SHBg = Shader.PropertyToID("_Lux_L_SHBg");
+ Lux_L_SHBb = Shader.PropertyToID("_Lux_L_SHBb");
+ Lux_L_SHC = Shader.PropertyToID("_Lux_L_SHC");
+ Lux_AmbientMode = Shader.PropertyToID("_Lux_AmbientMode");
+ Invoke("UpdateAmbientLighting", 0f);
+ }
+
+ private void LateUpdate()
+ {
+ if (UpdatePerFrame)
+ {
+ UpdateAmbientLighting();
+ }
+ else if (LuxParticles_LocalAmbientLighting.LocalProbes != null)
+ {
+ if (managedParticleSystems < LuxParticles_LocalAmbientLighting.LocalProbes.Count)
+ {
+ UpdateAmbientLightingForNewParticleSystems();
+ }
+ managedParticleSystems = LuxParticles_LocalAmbientLighting.LocalProbes.Count;
+ }
+ }
+
+ public void UpdateAmbientLighting()
+ {
+ bool flag = false;
+ if (LuxParticles_LocalAmbientLighting.LocalProbes != null && LuxParticles_LocalAmbientLighting.LocalProbes.Count > 0)
+ {
+ flag = true;
+ }
+ if (RenderSettings.ambientMode == AmbientMode.Flat && !flag && !AlwaysUseSH)
+ {
+ Shader.SetGlobalFloat(Lux_AmbientMode, 0f);
+ return;
+ }
+ if (RenderSettings.ambientMode == AmbientMode.Trilight && !flag && !AlwaysUseSH)
+ {
+ Shader.SetGlobalFloat(Lux_AmbientMode, 1f);
+ return;
+ }
+ Shader.SetGlobalFloat(Lux_AmbientMode, 2f);
+ if (RenderSettings.ambientMode == AmbientMode.Skybox)
+ {
+ probe = RenderSettings.ambientProbe;
+ }
+ else
+ {
+ LightProbes.GetInterpolatedProbe(base.transform.position, null, out probe);
+ }
+ PremultiplyCoefficients(probe);
+ GetShaderConstantsFromNormalizedSH(ref probe, IsSkyLighting: true);
+ SetSHLighting();
+ if (LuxParticles_LocalAmbientLighting.LocalProbes == null)
+ {
+ return;
+ }
+ for (int i = 0; i != LuxParticles_LocalAmbientLighting.LocalProbes.Count; i++)
+ {
+ LuxParticles_LocalAmbientLighting luxParticles_LocalAmbientLighting = LuxParticles_LocalAmbientLighting.LocalProbes[i];
+ if (luxParticles_LocalAmbientLighting.IsVisible)
+ {
+ LightProbes.GetInterpolatedProbe(luxParticles_LocalAmbientLighting.trans.position + luxParticles_LocalAmbientLighting.SampleOffset, null, out probe);
+ PremultiplyCoefficients(probe);
+ GetShaderConstantsFromNormalizedSH(ref probe, IsSkyLighting: false);
+ MaterialPropertyBlock block = LuxParticles_LocalAmbientLighting.LocalProbes[i].m_block;
+ block.Clear();
+ block.SetVector(Lux_L_SHAr, SHLighting[0]);
+ block.SetVector(Lux_L_SHAg, SHLighting[1]);
+ block.SetVector(Lux_L_SHAb, SHLighting[2]);
+ block.SetVector(Lux_L_SHBr, SHLighting[3]);
+ block.SetVector(Lux_L_SHBg, SHLighting[4]);
+ block.SetVector(Lux_L_SHBb, SHLighting[5]);
+ block.SetVector(Lux_L_SHC, SHLighting[6]);
+ LuxParticles_LocalAmbientLighting.LocalProbes[i].rend.SetPropertyBlock(block);
+ }
+ }
+ }
+
+ public void UpdateAmbientLightingForNewParticleSystems()
+ {
+ int count = LuxParticles_LocalAmbientLighting.LocalProbes.Count;
+ for (int i = managedParticleSystems; i != count; i++)
+ {
+ LuxParticles_LocalAmbientLighting luxParticles_LocalAmbientLighting = LuxParticles_LocalAmbientLighting.LocalProbes[i];
+ LightProbes.GetInterpolatedProbe(luxParticles_LocalAmbientLighting.trans.position + luxParticles_LocalAmbientLighting.SampleOffset, null, out probe);
+ PremultiplyCoefficients(probe);
+ GetShaderConstantsFromNormalizedSH(ref probe, IsSkyLighting: false);
+ MaterialPropertyBlock block = LuxParticles_LocalAmbientLighting.LocalProbes[i].m_block;
+ block.Clear();
+ block.SetVector(Lux_L_SHAr, SHLighting[0]);
+ block.SetVector(Lux_L_SHAg, SHLighting[1]);
+ block.SetVector(Lux_L_SHAb, SHLighting[2]);
+ block.SetVector(Lux_L_SHBr, SHLighting[3]);
+ block.SetVector(Lux_L_SHBg, SHLighting[4]);
+ block.SetVector(Lux_L_SHBb, SHLighting[5]);
+ block.SetVector(Lux_L_SHC, SHLighting[6]);
+ LuxParticles_LocalAmbientLighting.LocalProbes[i].rend.SetPropertyBlock(block);
+ }
+ }
+
+ private static SphericalHarmonicsL2 PremultiplyCoefficients(SphericalHarmonicsL2 sh)
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 9; j++)
+ {
+ sh[i, j] *= ks[j];
+ }
+ }
+ return sh;
+ }
+
+ private void GetShaderConstantsFromNormalizedSH(ref SphericalHarmonicsL2 ambientProbe, bool IsSkyLighting)
+ {
+ float num = 1f;
+ if (IsSkyLighting)
+ {
+ num = RenderSettings.ambientIntensity;
+ if (QualitySettings.activeColorSpace == ColorSpace.Linear)
+ {
+ num = Mathf.Pow(num, 2.2f);
+ }
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ SHLighting[i].x = ambientProbe[i, 3] * num;
+ SHLighting[i].y = ambientProbe[i, 1] * num;
+ SHLighting[i].z = ambientProbe[i, 2] * num;
+ SHLighting[i].w = (ambientProbe[i, 0] - ambientProbe[i, 6]) * num;
+ SHLighting[i + 3].x = ambientProbe[i, 4] * num;
+ SHLighting[i + 3].y = ambientProbe[i, 5] * num;
+ SHLighting[i + 3].z = ambientProbe[i, 6] * 3f * num;
+ SHLighting[i + 3].w = ambientProbe[i, 7] * num;
+ }
+ SHLighting[6].x = ambientProbe[0, 8] * num;
+ SHLighting[6].y = ambientProbe[1, 8] * num;
+ SHLighting[6].z = ambientProbe[2, 8] * num;
+ SHLighting[6].w = 1f;
+ }
+
+ private void SetSHLighting()
+ {
+ Shader.SetGlobalVector(Lux_SHAr, SHLighting[0]);
+ Shader.SetGlobalVector(Lux_SHAg, SHLighting[1]);
+ Shader.SetGlobalVector(Lux_SHAb, SHLighting[2]);
+ Shader.SetGlobalVector(Lux_SHBr, SHLighting[3]);
+ Shader.SetGlobalVector(Lux_SHBg, SHLighting[4]);
+ Shader.SetGlobalVector(Lux_SHBb, SHLighting[5]);
+ Shader.SetGlobalVector(Lux_SHC, SHLighting[6]);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_DirectionalLight.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_DirectionalLight.cs
new file mode 100644
index 0000000..0da147a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_DirectionalLight.cs
@@ -0,0 +1,42 @@
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace LuxParticles;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Light))]
+public class LuxParticles_DirectionalLight : MonoBehaviour
+{
+ private Light m_light;
+
+ private CommandBuffer GetShadowCascades_CB;
+
+ private void OnEnable()
+ {
+ m_light = GetComponent<Light>();
+ if (GetShadowCascades_CB == null)
+ {
+ GetShadowCascades_CB = new CommandBuffer();
+ GetShadowCascades_CB.name = "LuxParticles GetShadowCascades";
+ GetShadowCascades_CB.SetGlobalTexture("_LuxParticles_CascadedShadowMap", BuiltinRenderTextureType.CurrentActive);
+ }
+ m_light.AddCommandBuffer(LightEvent.AfterShadowMap, GetShadowCascades_CB);
+ }
+
+ private void OnDisable()
+ {
+ if ((bool)GetComponent<Light>() && GetShadowCascades_CB != null)
+ {
+ GetComponent<Light>().RemoveCommandBuffer(LightEvent.AfterShadowMap, GetShadowCascades_CB);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (GetShadowCascades_CB != null)
+ {
+ GetShadowCascades_CB.Release();
+ GetShadowCascades_CB = null;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_LocalAmbientLighting.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_LocalAmbientLighting.cs
new file mode 100644
index 0000000..3e5f393
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/LuxParticles/LuxParticles_LocalAmbientLighting.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace LuxParticles;
+
+[ExecuteInEditMode]
+public class LuxParticles_LocalAmbientLighting : MonoBehaviour
+{
+ public static List<LuxParticles_LocalAmbientLighting> LocalProbes = new List<LuxParticles_LocalAmbientLighting>();
+
+ public Vector3 SampleOffset = Vector3.zero;
+
+ [NonSerialized]
+ public Transform trans;
+
+ [NonSerialized]
+ public Renderer rend;
+
+ [NonSerialized]
+ public MaterialPropertyBlock m_block;
+
+ [NonSerialized]
+ public bool IsVisible;
+
+ private void OnEnable()
+ {
+ trans = GetComponent<Transform>();
+ rend = GetComponent<Renderer>();
+ m_block = new MaterialPropertyBlock();
+ IsVisible = true;
+ Register();
+ }
+
+ private void Register()
+ {
+ LocalProbes.Add(this);
+ }
+
+ private void OnDisable()
+ {
+ LocalProbes.Remove(this);
+ if (m_block != null)
+ {
+ m_block.Clear();
+ rend.SetPropertyBlock(m_block);
+ m_block = null;
+ }
+ }
+
+ private void OnDestroy()
+ {
+ LocalProbes.Remove(this);
+ if (m_block != null)
+ {
+ m_block.Clear();
+ rend.SetPropertyBlock(m_block);
+ m_block = null;
+ }
+ }
+
+ private void OnBecameVisible()
+ {
+ IsVisible = true;
+ }
+
+ private void OnBecameInvisible()
+ {
+ IsVisible = false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_lux/assembly_lux.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/assembly_lux.csproj
new file mode 100644
index 0000000..16145c3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_lux/assembly_lux.csproj
@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_lux</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/ExampleWheelController.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/ExampleWheelController.cs
new file mode 100644
index 0000000..a2f05e0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/ExampleWheelController.cs
@@ -0,0 +1,38 @@
+using UnityEngine;
+
+public class ExampleWheelController : MonoBehaviour
+{
+ private static class Uniforms
+ {
+ internal static readonly int _MotionAmount = Shader.PropertyToID("_MotionAmount");
+ }
+
+ public float acceleration;
+
+ public Renderer motionVectorRenderer;
+
+ private Rigidbody m_Rigidbody;
+
+ private void Start()
+ {
+ m_Rigidbody = GetComponent<Rigidbody>();
+ m_Rigidbody.maxAngularVelocity = 100f;
+ }
+
+ private void Update()
+ {
+ if (Input.GetKey(KeyCode.UpArrow))
+ {
+ m_Rigidbody.AddRelativeTorque(new Vector3(-1f * acceleration, 0f, 0f), ForceMode.Acceleration);
+ }
+ else if (Input.GetKey(KeyCode.DownArrow))
+ {
+ m_Rigidbody.AddRelativeTorque(new Vector3(1f * acceleration, 0f, 0f), ForceMode.Acceleration);
+ }
+ float value = (0f - m_Rigidbody.angularVelocity.x) / 100f;
+ if ((bool)motionVectorRenderer)
+ {
+ motionVectorRenderer.material.SetFloat(Uniforms._MotionAmount, Mathf.Clamp(value, -0.25f, 0.25f));
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionComponent.cs
new file mode 100644
index 0000000..6dbb292
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionComponent.cs
@@ -0,0 +1,190 @@
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class AmbientOcclusionComponent : PostProcessingComponentCommandBuffer<AmbientOcclusionModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _Intensity = Shader.PropertyToID("_Intensity");
+
+ internal static readonly int _IntensityFar = Shader.PropertyToID("_IntensityFar");
+
+ internal static readonly int _FarDistance = Shader.PropertyToID("_FarDistance");
+
+ internal static readonly int _Radius = Shader.PropertyToID("_Radius");
+
+ internal static readonly int _FogParams = Shader.PropertyToID("_FogParams");
+
+ internal static readonly int _Downsample = Shader.PropertyToID("_Downsample");
+
+ internal static readonly int _SampleCount = Shader.PropertyToID("_SampleCount");
+
+ internal static readonly int _OcclusionTexture1 = Shader.PropertyToID("_OcclusionTexture1");
+
+ internal static readonly int _OcclusionTexture2 = Shader.PropertyToID("_OcclusionTexture2");
+
+ internal static readonly int _OcclusionTexture = Shader.PropertyToID("_OcclusionTexture");
+
+ internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
+
+ internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
+ }
+
+ private enum OcclusionSource
+ {
+ DepthTexture,
+ DepthNormalsTexture,
+ GBuffer
+ }
+
+ private const string k_BlitShaderString = "Hidden/Post FX/Blit";
+
+ private const string k_ShaderString = "Hidden/Post FX/Ambient Occlusion";
+
+ private readonly RenderTargetIdentifier[] m_MRT = new RenderTargetIdentifier[2]
+ {
+ BuiltinRenderTextureType.GBuffer0,
+ BuiltinRenderTextureType.CameraTarget
+ };
+
+ private OcclusionSource occlusionSource
+ {
+ get
+ {
+ if (context.isGBufferAvailable && !base.model.settings.forceForwardCompatibility)
+ {
+ return OcclusionSource.GBuffer;
+ }
+ if (base.model.settings.highPrecision && (!context.isGBufferAvailable || base.model.settings.forceForwardCompatibility))
+ {
+ return OcclusionSource.DepthTexture;
+ }
+ return OcclusionSource.DepthNormalsTexture;
+ }
+ }
+
+ private bool ambientOnlySupported
+ {
+ get
+ {
+ if (context.isHdr && base.model.settings.ambientOnly && context.isGBufferAvailable)
+ {
+ return !base.model.settings.forceForwardCompatibility;
+ }
+ return false;
+ }
+ }
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.intensity > 0f)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ DepthTextureMode depthTextureMode = DepthTextureMode.None;
+ if (occlusionSource == OcclusionSource.DepthTexture)
+ {
+ depthTextureMode |= DepthTextureMode.Depth;
+ }
+ if (occlusionSource != OcclusionSource.GBuffer)
+ {
+ depthTextureMode |= DepthTextureMode.DepthNormals;
+ }
+ return depthTextureMode;
+ }
+
+ public override string GetName()
+ {
+ return "Ambient Occlusion";
+ }
+
+ public override CameraEvent GetCameraEvent()
+ {
+ if (!ambientOnlySupported || context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.AmbientOcclusion))
+ {
+ return CameraEvent.BeforeImageEffectsOpaque;
+ }
+ return CameraEvent.BeforeReflections;
+ }
+
+ public override void PopulateCommandBuffer(CommandBuffer cb)
+ {
+ AmbientOcclusionModel.Settings settings = base.model.settings;
+ Material mat = context.materialFactory.Get("Hidden/Post FX/Blit");
+ Material material = context.materialFactory.Get("Hidden/Post FX/Ambient Occlusion");
+ material.shaderKeywords = null;
+ material.SetFloat(Uniforms._Intensity, settings.intensity);
+ material.SetFloat(Uniforms._IntensityFar, settings.intensityFar);
+ material.SetFloat(Uniforms._FarDistance, settings.farDistance);
+ material.SetFloat(Uniforms._Radius, settings.radius);
+ material.SetFloat(Uniforms._Downsample, settings.downsampling ? 0.5f : 1f);
+ material.SetInt(Uniforms._SampleCount, (int)settings.sampleCount);
+ if (!context.isGBufferAvailable && RenderSettings.fog)
+ {
+ material.SetVector(Uniforms._FogParams, new Vector3(RenderSettings.fogDensity, RenderSettings.fogStartDistance, RenderSettings.fogEndDistance));
+ switch (RenderSettings.fogMode)
+ {
+ case FogMode.Linear:
+ material.EnableKeyword("FOG_LINEAR");
+ break;
+ case FogMode.Exponential:
+ material.EnableKeyword("FOG_EXP");
+ break;
+ case FogMode.ExponentialSquared:
+ material.EnableKeyword("FOG_EXP2");
+ break;
+ }
+ }
+ else
+ {
+ material.EnableKeyword("FOG_OFF");
+ }
+ int width = context.width;
+ int height = context.height;
+ int num = ((!settings.downsampling) ? 1 : 2);
+ int occlusionTexture = Uniforms._OcclusionTexture1;
+ cb.GetTemporaryRT(occlusionTexture, width / num, height / num, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
+ cb.Blit(null, occlusionTexture, material, (int)occlusionSource);
+ int occlusionTexture2 = Uniforms._OcclusionTexture2;
+ cb.GetTemporaryRT(occlusionTexture2, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, occlusionTexture);
+ cb.Blit(occlusionTexture, occlusionTexture2, material, (occlusionSource == OcclusionSource.GBuffer) ? 4 : 3);
+ cb.ReleaseTemporaryRT(occlusionTexture);
+ occlusionTexture = Uniforms._OcclusionTexture;
+ cb.GetTemporaryRT(occlusionTexture, width, height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, occlusionTexture2);
+ cb.Blit(occlusionTexture2, occlusionTexture, material, 5);
+ cb.ReleaseTemporaryRT(occlusionTexture2);
+ if (context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.AmbientOcclusion))
+ {
+ cb.SetGlobalTexture(Uniforms._MainTex, occlusionTexture);
+ cb.Blit(occlusionTexture, BuiltinRenderTextureType.CameraTarget, material, 8);
+ context.Interrupt();
+ }
+ else if (ambientOnlySupported)
+ {
+ cb.SetRenderTarget(m_MRT, BuiltinRenderTextureType.CameraTarget);
+ cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 7);
+ }
+ else
+ {
+ RenderTextureFormat format = (context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);
+ int tempRT = Uniforms._TempRT;
+ cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear, format);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0);
+ cb.SetGlobalTexture(Uniforms._MainTex, tempRT);
+ cb.Blit(tempRT, BuiltinRenderTextureType.CameraTarget, material, 6);
+ cb.ReleaseTemporaryRT(tempRT);
+ }
+ cb.ReleaseTemporaryRT(occlusionTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionModel.cs
new file mode 100644
index 0000000..82593a7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AmbientOcclusionModel.cs
@@ -0,0 +1,87 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class AmbientOcclusionModel : PostProcessingModel
+{
+ public enum SampleCount
+ {
+ Lowest = 3,
+ Low = 6,
+ Medium = 10,
+ High = 16
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ [Range(0f, 4f)]
+ [Tooltip("Degree of darkness produced by the effect.")]
+ public float intensity;
+
+ [Range(0f, 4f)]
+ [Tooltip("Degree of darkness produced by the effect at far distance.")]
+ public float intensityFar;
+
+ [Tooltip("Radius of sample points, which affects extent of darkened areas.")]
+ public float farDistance;
+
+ [Min(0.0001f)]
+ [Tooltip("Radius of sample points, which affects extent of darkened areas.")]
+ public float radius;
+
+ [Tooltip("Number of sample points, which affects quality and performance.")]
+ public SampleCount sampleCount;
+
+ [Tooltip("Halves the resolution of the effect to increase performance at the cost of visual quality.")]
+ public bool downsampling;
+
+ [Tooltip("Forces compatibility with Forward rendered objects when working with the Deferred rendering path.")]
+ public bool forceForwardCompatibility;
+
+ [Tooltip("Enables the ambient-only mode in that the effect only affects ambient lighting. This mode is only available with the Deferred rendering path and HDR rendering.")]
+ public bool ambientOnly;
+
+ [Tooltip("Toggles the use of a higher precision depth texture with the forward rendering path (may impact performances). Has no effect with the deferred rendering path.")]
+ public bool highPrecision;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.intensity = 1f;
+ result.intensityFar = 2f;
+ result.farDistance = 100f;
+ result.radius = 0.3f;
+ result.sampleCount = SampleCount.Medium;
+ result.downsampling = true;
+ result.forceForwardCompatibility = false;
+ result.ambientOnly = false;
+ result.highPrecision = false;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AntialiasingModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AntialiasingModel.cs
new file mode 100644
index 0000000..d5bda1d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/AntialiasingModel.cs
@@ -0,0 +1,222 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class AntialiasingModel : PostProcessingModel
+{
+ public enum Method
+ {
+ Fxaa,
+ Taa
+ }
+
+ public enum FxaaPreset
+ {
+ ExtremePerformance,
+ Performance,
+ Default,
+ Quality,
+ ExtremeQuality
+ }
+
+ [Serializable]
+ public struct FxaaQualitySettings
+ {
+ [Tooltip("The amount of desired sub-pixel aliasing removal. Effects the sharpeness of the output.")]
+ [Range(0f, 1f)]
+ public float subpixelAliasingRemovalAmount;
+
+ [Tooltip("The minimum amount of local contrast required to qualify a region as containing an edge.")]
+ [Range(0.063f, 0.333f)]
+ public float edgeDetectionThreshold;
+
+ [Tooltip("Local contrast adaptation value to disallow the algorithm from executing on the darker regions.")]
+ [Range(0f, 0.0833f)]
+ public float minimumRequiredLuminance;
+
+ public static FxaaQualitySettings[] presets = new FxaaQualitySettings[5]
+ {
+ new FxaaQualitySettings
+ {
+ subpixelAliasingRemovalAmount = 0f,
+ edgeDetectionThreshold = 0.333f,
+ minimumRequiredLuminance = 0.0833f
+ },
+ new FxaaQualitySettings
+ {
+ subpixelAliasingRemovalAmount = 0.25f,
+ edgeDetectionThreshold = 0.25f,
+ minimumRequiredLuminance = 0.0833f
+ },
+ new FxaaQualitySettings
+ {
+ subpixelAliasingRemovalAmount = 0.75f,
+ edgeDetectionThreshold = 0.166f,
+ minimumRequiredLuminance = 0.0833f
+ },
+ new FxaaQualitySettings
+ {
+ subpixelAliasingRemovalAmount = 1f,
+ edgeDetectionThreshold = 0.125f,
+ minimumRequiredLuminance = 0.0625f
+ },
+ new FxaaQualitySettings
+ {
+ subpixelAliasingRemovalAmount = 1f,
+ edgeDetectionThreshold = 0.063f,
+ minimumRequiredLuminance = 0.0312f
+ }
+ };
+ }
+
+ [Serializable]
+ public struct FxaaConsoleSettings
+ {
+ [Tooltip("The amount of spread applied to the sampling coordinates while sampling for subpixel information.")]
+ [Range(0.33f, 0.5f)]
+ public float subpixelSpreadAmount;
+
+ [Tooltip("This value dictates how sharp the edges in the image are kept; a higher value implies sharper edges.")]
+ [Range(2f, 8f)]
+ public float edgeSharpnessAmount;
+
+ [Tooltip("The minimum amount of local contrast required to qualify a region as containing an edge.")]
+ [Range(0.125f, 0.25f)]
+ public float edgeDetectionThreshold;
+
+ [Tooltip("Local contrast adaptation value to disallow the algorithm from executing on the darker regions.")]
+ [Range(0.04f, 0.06f)]
+ public float minimumRequiredLuminance;
+
+ public static FxaaConsoleSettings[] presets = new FxaaConsoleSettings[5]
+ {
+ new FxaaConsoleSettings
+ {
+ subpixelSpreadAmount = 0.33f,
+ edgeSharpnessAmount = 8f,
+ edgeDetectionThreshold = 0.25f,
+ minimumRequiredLuminance = 0.06f
+ },
+ new FxaaConsoleSettings
+ {
+ subpixelSpreadAmount = 0.33f,
+ edgeSharpnessAmount = 8f,
+ edgeDetectionThreshold = 0.125f,
+ minimumRequiredLuminance = 0.06f
+ },
+ new FxaaConsoleSettings
+ {
+ subpixelSpreadAmount = 0.5f,
+ edgeSharpnessAmount = 8f,
+ edgeDetectionThreshold = 0.125f,
+ minimumRequiredLuminance = 0.05f
+ },
+ new FxaaConsoleSettings
+ {
+ subpixelSpreadAmount = 0.5f,
+ edgeSharpnessAmount = 4f,
+ edgeDetectionThreshold = 0.125f,
+ minimumRequiredLuminance = 0.04f
+ },
+ new FxaaConsoleSettings
+ {
+ subpixelSpreadAmount = 0.5f,
+ edgeSharpnessAmount = 2f,
+ edgeDetectionThreshold = 0.125f,
+ minimumRequiredLuminance = 0.04f
+ }
+ };
+ }
+
+ [Serializable]
+ public struct FxaaSettings
+ {
+ public FxaaPreset preset;
+
+ public static FxaaSettings defaultSettings
+ {
+ get
+ {
+ FxaaSettings result = default(FxaaSettings);
+ result.preset = FxaaPreset.Default;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct TaaSettings
+ {
+ [Tooltip("The diameter (in texels) inside which jitter samples are spread. Smaller values result in crisper but more aliased output, while larger values result in more stable but blurrier output.")]
+ [Range(0.1f, 1f)]
+ public float jitterSpread;
+
+ [Tooltip("Controls the amount of sharpening applied to the color buffer.")]
+ [Range(0f, 3f)]
+ public float sharpen;
+
+ [Tooltip("The blend coefficient for a stationary fragment. Controls the percentage of history sample blended into the final color.")]
+ [Range(0f, 0.99f)]
+ public float stationaryBlending;
+
+ [Tooltip("The blend coefficient for a fragment with significant motion. Controls the percentage of history sample blended into the final color.")]
+ [Range(0f, 0.99f)]
+ public float motionBlending;
+
+ public static TaaSettings defaultSettings
+ {
+ get
+ {
+ TaaSettings result = default(TaaSettings);
+ result.jitterSpread = 0.75f;
+ result.sharpen = 0.3f;
+ result.stationaryBlending = 0.95f;
+ result.motionBlending = 0.85f;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ public Method method;
+
+ public FxaaSettings fxaaSettings;
+
+ public TaaSettings taaSettings;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.method = Method.Fxaa;
+ result.fxaaSettings = FxaaSettings.defaultSettings;
+ result.taaSettings = TaaSettings.defaultSettings;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomComponent.cs
new file mode 100644
index 0000000..83d499e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomComponent.cs
@@ -0,0 +1,116 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class BloomComponent : PostProcessingComponentRenderTexture<BloomModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure");
+
+ internal static readonly int _Threshold = Shader.PropertyToID("_Threshold");
+
+ internal static readonly int _Curve = Shader.PropertyToID("_Curve");
+
+ internal static readonly int _PrefilterOffs = Shader.PropertyToID("_PrefilterOffs");
+
+ internal static readonly int _SampleScale = Shader.PropertyToID("_SampleScale");
+
+ internal static readonly int _BaseTex = Shader.PropertyToID("_BaseTex");
+
+ internal static readonly int _BloomTex = Shader.PropertyToID("_BloomTex");
+
+ internal static readonly int _Bloom_Settings = Shader.PropertyToID("_Bloom_Settings");
+
+ internal static readonly int _Bloom_DirtTex = Shader.PropertyToID("_Bloom_DirtTex");
+
+ internal static readonly int _Bloom_DirtIntensity = Shader.PropertyToID("_Bloom_DirtIntensity");
+ }
+
+ private const int k_MaxPyramidBlurLevel = 16;
+
+ private readonly RenderTexture[] m_BlurBuffer1 = new RenderTexture[16];
+
+ private readonly RenderTexture[] m_BlurBuffer2 = new RenderTexture[16];
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.bloom.intensity > 0f)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public void Prepare(RenderTexture source, Material uberMaterial, Texture autoExposure)
+ {
+ BloomModel.BloomSettings bloom = base.model.settings.bloom;
+ BloomModel.LensDirtSettings lensDirt = base.model.settings.lensDirt;
+ Material material = context.materialFactory.Get("Hidden/Post FX/Bloom");
+ material.shaderKeywords = null;
+ material.SetTexture(Uniforms._AutoExposure, autoExposure);
+ int width = context.width / 2;
+ int num = context.height / 2;
+ RenderTextureFormat format = (Application.isMobilePlatform ? RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR);
+ float num2 = Mathf.Log(num, 2f) + bloom.radius - 8f;
+ int num3 = (int)num2;
+ int num4 = Mathf.Clamp(num3, 1, 16);
+ float thresholdLinear = bloom.thresholdLinear;
+ material.SetFloat(Uniforms._Threshold, thresholdLinear);
+ float num5 = thresholdLinear * bloom.softKnee + 1E-05f;
+ material.SetVector(value: new Vector3(thresholdLinear - num5, num5 * 2f, 0.25f / num5), nameID: Uniforms._Curve);
+ material.SetFloat(Uniforms._PrefilterOffs, bloom.antiFlicker ? (-0.5f) : 0f);
+ float num6 = 0.5f + num2 - (float)num3;
+ material.SetFloat(Uniforms._SampleScale, num6);
+ if (bloom.antiFlicker)
+ {
+ material.EnableKeyword("ANTI_FLICKER");
+ }
+ RenderTexture renderTexture = context.renderTextureFactory.Get(width, num, 0, format);
+ Graphics.Blit(source, renderTexture, material, 0);
+ RenderTexture renderTexture2 = renderTexture;
+ for (int i = 0; i < num4; i++)
+ {
+ m_BlurBuffer1[i] = context.renderTextureFactory.Get(renderTexture2.width / 2, renderTexture2.height / 2, 0, format);
+ int pass = ((i == 0) ? 1 : 2);
+ Graphics.Blit(renderTexture2, m_BlurBuffer1[i], material, pass);
+ renderTexture2 = m_BlurBuffer1[i];
+ }
+ for (int num7 = num4 - 2; num7 >= 0; num7--)
+ {
+ RenderTexture renderTexture3 = m_BlurBuffer1[num7];
+ material.SetTexture(Uniforms._BaseTex, renderTexture3);
+ m_BlurBuffer2[num7] = context.renderTextureFactory.Get(renderTexture3.width, renderTexture3.height, 0, format);
+ Graphics.Blit(renderTexture2, m_BlurBuffer2[num7], material, 3);
+ renderTexture2 = m_BlurBuffer2[num7];
+ }
+ RenderTexture renderTexture4 = renderTexture2;
+ for (int j = 0; j < 16; j++)
+ {
+ if (m_BlurBuffer1[j] != null)
+ {
+ context.renderTextureFactory.Release(m_BlurBuffer1[j]);
+ }
+ if (m_BlurBuffer2[j] != null && m_BlurBuffer2[j] != renderTexture4)
+ {
+ context.renderTextureFactory.Release(m_BlurBuffer2[j]);
+ }
+ m_BlurBuffer1[j] = null;
+ m_BlurBuffer2[j] = null;
+ }
+ context.renderTextureFactory.Release(renderTexture);
+ uberMaterial.SetTexture(Uniforms._BloomTex, renderTexture4);
+ uberMaterial.SetVector(Uniforms._Bloom_Settings, new Vector2(num6, bloom.intensity));
+ if (lensDirt.intensity > 0f && lensDirt.texture != null)
+ {
+ uberMaterial.SetTexture(Uniforms._Bloom_DirtTex, lensDirt.texture);
+ uberMaterial.SetFloat(Uniforms._Bloom_DirtIntensity, lensDirt.intensity);
+ uberMaterial.EnableKeyword("BLOOM_LENS_DIRT");
+ }
+ else
+ {
+ uberMaterial.EnableKeyword("BLOOM");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomModel.cs
new file mode 100644
index 0000000..0569d62
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BloomModel.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class BloomModel : PostProcessingModel
+{
+ [Serializable]
+ public struct BloomSettings
+ {
+ [Min(0f)]
+ [Tooltip("Strength of the bloom filter.")]
+ public float intensity;
+
+ [Min(0f)]
+ [Tooltip("Filters out pixels under this level of brightness.")]
+ public float threshold;
+
+ [Range(0f, 1f)]
+ [Tooltip("Makes transition between under/over-threshold gradual (0 = hard threshold, 1 = soft threshold).")]
+ public float softKnee;
+
+ [Range(1f, 7f)]
+ [Tooltip("Changes extent of veiling effects in a screen resolution-independent fashion.")]
+ public float radius;
+
+ [Tooltip("Reduces flashing noise with an additional filter.")]
+ public bool antiFlicker;
+
+ public float thresholdLinear
+ {
+ get
+ {
+ return Mathf.GammaToLinearSpace(threshold);
+ }
+ set
+ {
+ threshold = Mathf.LinearToGammaSpace(value);
+ }
+ }
+
+ public static BloomSettings defaultSettings
+ {
+ get
+ {
+ BloomSettings result = default(BloomSettings);
+ result.intensity = 0.5f;
+ result.threshold = 1.1f;
+ result.softKnee = 0.5f;
+ result.radius = 4f;
+ result.antiFlicker = false;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct LensDirtSettings
+ {
+ [Tooltip("Dirtiness texture to add smudges or dust to the lens.")]
+ public Texture texture;
+
+ [Min(0f)]
+ [Tooltip("Amount of lens dirtiness.")]
+ public float intensity;
+
+ public static LensDirtSettings defaultSettings
+ {
+ get
+ {
+ LensDirtSettings result = default(LensDirtSettings);
+ result.texture = null;
+ result.intensity = 3f;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ public BloomSettings bloom;
+
+ public LensDirtSettings lensDirt;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.bloom = BloomSettings.defaultSettings;
+ result.lensDirt = LensDirtSettings.defaultSettings;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsComponent.cs
new file mode 100644
index 0000000..2bc5413
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsComponent.cs
@@ -0,0 +1,237 @@
+using System.Collections.Generic;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class BuiltinDebugViewsComponent : PostProcessingComponentCommandBuffer<BuiltinDebugViewsModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _DepthScale = Shader.PropertyToID("_DepthScale");
+
+ internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
+
+ internal static readonly int _Opacity = Shader.PropertyToID("_Opacity");
+
+ internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
+
+ internal static readonly int _TempRT2 = Shader.PropertyToID("_TempRT2");
+
+ internal static readonly int _Amplitude = Shader.PropertyToID("_Amplitude");
+
+ internal static readonly int _Scale = Shader.PropertyToID("_Scale");
+ }
+
+ private enum Pass
+ {
+ Depth,
+ Normals,
+ MovecOpacity,
+ MovecImaging,
+ MovecArrows
+ }
+
+ private class ArrowArray
+ {
+ public Mesh mesh { get; private set; }
+
+ public int columnCount { get; private set; }
+
+ public int rowCount { get; private set; }
+
+ public void BuildMesh(int columns, int rows)
+ {
+ Vector3[] array = new Vector3[6]
+ {
+ new Vector3(0f, 0f, 0f),
+ new Vector3(0f, 1f, 0f),
+ new Vector3(0f, 1f, 0f),
+ new Vector3(-1f, 1f, 0f),
+ new Vector3(0f, 1f, 0f),
+ new Vector3(1f, 1f, 0f)
+ };
+ int num = 6 * columns * rows;
+ List<Vector3> list = new List<Vector3>(num);
+ List<Vector2> list2 = new List<Vector2>(num);
+ for (int i = 0; i < rows; i++)
+ {
+ for (int j = 0; j < columns; j++)
+ {
+ Vector2 item = new Vector2((0.5f + (float)j) / (float)columns, (0.5f + (float)i) / (float)rows);
+ for (int k = 0; k < 6; k++)
+ {
+ list.Add(array[k]);
+ list2.Add(item);
+ }
+ }
+ }
+ int[] array2 = new int[num];
+ for (int l = 0; l < num; l++)
+ {
+ array2[l] = l;
+ }
+ mesh = new Mesh
+ {
+ hideFlags = HideFlags.DontSave
+ };
+ mesh.SetVertices(list);
+ mesh.SetUVs(0, list2);
+ mesh.SetIndices(array2, MeshTopology.Lines, 0);
+ mesh.UploadMeshData(markNoLongerReadable: true);
+ columnCount = columns;
+ rowCount = rows;
+ }
+
+ public void Release()
+ {
+ GraphicsUtils.Destroy(mesh);
+ mesh = null;
+ }
+ }
+
+ private const string k_ShaderString = "Hidden/Post FX/Builtin Debug Views";
+
+ private ArrowArray m_Arrows;
+
+ public override bool active
+ {
+ get
+ {
+ if (!base.model.IsModeActive(BuiltinDebugViewsModel.Mode.Depth) && !base.model.IsModeActive(BuiltinDebugViewsModel.Mode.Normals))
+ {
+ return base.model.IsModeActive(BuiltinDebugViewsModel.Mode.MotionVectors);
+ }
+ return true;
+ }
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ BuiltinDebugViewsModel.Mode mode = base.model.settings.mode;
+ DepthTextureMode depthTextureMode = DepthTextureMode.None;
+ switch (mode)
+ {
+ case BuiltinDebugViewsModel.Mode.Normals:
+ depthTextureMode |= DepthTextureMode.DepthNormals;
+ break;
+ case BuiltinDebugViewsModel.Mode.MotionVectors:
+ depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
+ break;
+ case BuiltinDebugViewsModel.Mode.Depth:
+ depthTextureMode |= DepthTextureMode.Depth;
+ break;
+ }
+ return depthTextureMode;
+ }
+
+ public override CameraEvent GetCameraEvent()
+ {
+ if (base.model.settings.mode != BuiltinDebugViewsModel.Mode.MotionVectors)
+ {
+ return CameraEvent.BeforeImageEffectsOpaque;
+ }
+ return CameraEvent.BeforeImageEffects;
+ }
+
+ public override string GetName()
+ {
+ return "Builtin Debug Views";
+ }
+
+ public override void PopulateCommandBuffer(CommandBuffer cb)
+ {
+ BuiltinDebugViewsModel.Settings settings = base.model.settings;
+ Material material = context.materialFactory.Get("Hidden/Post FX/Builtin Debug Views");
+ material.shaderKeywords = null;
+ if (context.isGBufferAvailable)
+ {
+ material.EnableKeyword("SOURCE_GBUFFER");
+ }
+ switch (settings.mode)
+ {
+ case BuiltinDebugViewsModel.Mode.Depth:
+ DepthPass(cb);
+ break;
+ case BuiltinDebugViewsModel.Mode.Normals:
+ DepthNormalsPass(cb);
+ break;
+ case BuiltinDebugViewsModel.Mode.MotionVectors:
+ MotionVectorsPass(cb);
+ break;
+ }
+ context.Interrupt();
+ }
+
+ private void DepthPass(CommandBuffer cb)
+ {
+ Material mat = context.materialFactory.Get("Hidden/Post FX/Builtin Debug Views");
+ BuiltinDebugViewsModel.DepthSettings depth = base.model.settings.depth;
+ cb.SetGlobalFloat(Uniforms._DepthScale, 1f / depth.scale);
+ cb.Blit(null, BuiltinRenderTextureType.CameraTarget, mat, 0);
+ }
+
+ private void DepthNormalsPass(CommandBuffer cb)
+ {
+ Material mat = context.materialFactory.Get("Hidden/Post FX/Builtin Debug Views");
+ cb.Blit(null, BuiltinRenderTextureType.CameraTarget, mat, 1);
+ }
+
+ private void MotionVectorsPass(CommandBuffer cb)
+ {
+ Material material = context.materialFactory.Get("Hidden/Post FX/Builtin Debug Views");
+ BuiltinDebugViewsModel.MotionVectorsSettings motionVectors = base.model.settings.motionVectors;
+ int num = Uniforms._TempRT;
+ cb.GetTemporaryRT(num, context.width, context.height, 0, FilterMode.Bilinear);
+ cb.SetGlobalFloat(Uniforms._Opacity, motionVectors.sourceOpacity);
+ cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, num, material, 2);
+ if (motionVectors.motionImageOpacity > 0f && motionVectors.motionImageAmplitude > 0f)
+ {
+ int tempRT = Uniforms._TempRT2;
+ cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Bilinear);
+ cb.SetGlobalFloat(Uniforms._Opacity, motionVectors.motionImageOpacity);
+ cb.SetGlobalFloat(Uniforms._Amplitude, motionVectors.motionImageAmplitude);
+ cb.SetGlobalTexture(Uniforms._MainTex, num);
+ cb.Blit(num, tempRT, material, 3);
+ cb.ReleaseTemporaryRT(num);
+ num = tempRT;
+ }
+ if (motionVectors.motionVectorsOpacity > 0f && motionVectors.motionVectorsAmplitude > 0f)
+ {
+ PrepareArrows();
+ float num2 = 1f / (float)motionVectors.motionVectorsResolution;
+ float x = num2 * (float)context.height / (float)context.width;
+ cb.SetGlobalVector(Uniforms._Scale, new Vector2(x, num2));
+ cb.SetGlobalFloat(Uniforms._Opacity, motionVectors.motionVectorsOpacity);
+ cb.SetGlobalFloat(Uniforms._Amplitude, motionVectors.motionVectorsAmplitude);
+ cb.DrawMesh(m_Arrows.mesh, Matrix4x4.identity, material, 0, 4);
+ }
+ cb.SetGlobalTexture(Uniforms._MainTex, num);
+ cb.Blit(num, BuiltinRenderTextureType.CameraTarget);
+ cb.ReleaseTemporaryRT(num);
+ }
+
+ private void PrepareArrows()
+ {
+ int motionVectorsResolution = base.model.settings.motionVectors.motionVectorsResolution;
+ int num = motionVectorsResolution * Screen.width / Screen.height;
+ if (m_Arrows == null)
+ {
+ m_Arrows = new ArrowArray();
+ }
+ if (m_Arrows.columnCount != num || m_Arrows.rowCount != motionVectorsResolution)
+ {
+ m_Arrows.Release();
+ m_Arrows.BuildMesh(num, motionVectorsResolution);
+ }
+ }
+
+ public override void OnDisable()
+ {
+ if (m_Arrows != null)
+ {
+ m_Arrows.Release();
+ }
+ m_Arrows = null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsModel.cs
new file mode 100644
index 0000000..eab95e0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/BuiltinDebugViewsModel.cs
@@ -0,0 +1,141 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class BuiltinDebugViewsModel : PostProcessingModel
+{
+ [Serializable]
+ public struct DepthSettings
+ {
+ [Range(0f, 1f)]
+ [Tooltip("Scales the camera far plane before displaying the depth map.")]
+ public float scale;
+
+ public static DepthSettings defaultSettings
+ {
+ get
+ {
+ DepthSettings result = default(DepthSettings);
+ result.scale = 1f;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct MotionVectorsSettings
+ {
+ [Range(0f, 1f)]
+ [Tooltip("Opacity of the source render.")]
+ public float sourceOpacity;
+
+ [Range(0f, 1f)]
+ [Tooltip("Opacity of the per-pixel motion vector colors.")]
+ public float motionImageOpacity;
+
+ [Min(0f)]
+ [Tooltip("Because motion vectors are mainly very small vectors, you can use this setting to make them more visible.")]
+ public float motionImageAmplitude;
+
+ [Range(0f, 1f)]
+ [Tooltip("Opacity for the motion vector arrows.")]
+ public float motionVectorsOpacity;
+
+ [Range(8f, 64f)]
+ [Tooltip("The arrow density on screen.")]
+ public int motionVectorsResolution;
+
+ [Min(0f)]
+ [Tooltip("Tweaks the arrows length.")]
+ public float motionVectorsAmplitude;
+
+ public static MotionVectorsSettings defaultSettings
+ {
+ get
+ {
+ MotionVectorsSettings result = default(MotionVectorsSettings);
+ result.sourceOpacity = 1f;
+ result.motionImageOpacity = 0f;
+ result.motionImageAmplitude = 16f;
+ result.motionVectorsOpacity = 1f;
+ result.motionVectorsResolution = 24;
+ result.motionVectorsAmplitude = 64f;
+ return result;
+ }
+ }
+ }
+
+ public enum Mode
+ {
+ None,
+ Depth,
+ Normals,
+ MotionVectors,
+ AmbientOcclusion,
+ EyeAdaptation,
+ FocusPlane,
+ PreGradingLog,
+ LogLut,
+ UserLut
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ public Mode mode;
+
+ public DepthSettings depth;
+
+ public MotionVectorsSettings motionVectors;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.mode = Mode.None;
+ result.depth = DepthSettings.defaultSettings;
+ result.motionVectors = MotionVectorsSettings.defaultSettings;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public bool willInterrupt
+ {
+ get
+ {
+ if (!IsModeActive(Mode.None) && !IsModeActive(Mode.EyeAdaptation) && !IsModeActive(Mode.PreGradingLog) && !IsModeActive(Mode.LogLut))
+ {
+ return !IsModeActive(Mode.UserLut);
+ }
+ return false;
+ }
+ }
+
+ public override void Reset()
+ {
+ settings = Settings.defaultSettings;
+ }
+
+ public bool IsModeActive(Mode mode)
+ {
+ return m_Settings.mode == mode;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationComponent.cs
new file mode 100644
index 0000000..ffe2df8
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationComponent.cs
@@ -0,0 +1,63 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class ChromaticAberrationComponent : PostProcessingComponentRenderTexture<ChromaticAberrationModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _ChromaticAberration_Amount = Shader.PropertyToID("_ChromaticAberration_Amount");
+
+ internal static readonly int _ChromaticAberration_Spectrum = Shader.PropertyToID("_ChromaticAberration_Spectrum");
+ }
+
+ private Texture2D m_SpectrumLut;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.intensity > 0f)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override void OnDisable()
+ {
+ GraphicsUtils.Destroy(m_SpectrumLut);
+ m_SpectrumLut = null;
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ ChromaticAberrationModel.Settings settings = base.model.settings;
+ Texture2D texture2D = settings.spectralTexture;
+ if (texture2D == null)
+ {
+ if (m_SpectrumLut == null)
+ {
+ m_SpectrumLut = new Texture2D(3, 1, TextureFormat.RGB24, mipChain: false)
+ {
+ name = "Chromatic Aberration Spectrum Lookup",
+ filterMode = FilterMode.Bilinear,
+ wrapMode = TextureWrapMode.Clamp,
+ anisoLevel = 0,
+ hideFlags = HideFlags.DontSave
+ };
+ Color[] pixels = new Color[3]
+ {
+ new Color(1f, 0f, 0f),
+ new Color(0f, 1f, 0f),
+ new Color(0f, 0f, 1f)
+ };
+ m_SpectrumLut.SetPixels(pixels);
+ m_SpectrumLut.Apply();
+ }
+ texture2D = m_SpectrumLut;
+ }
+ uberMaterial.EnableKeyword("CHROMATIC_ABERRATION");
+ uberMaterial.SetFloat(Uniforms._ChromaticAberration_Amount, settings.intensity * 0.03f);
+ uberMaterial.SetTexture(Uniforms._ChromaticAberration_Spectrum, texture2D);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationModel.cs
new file mode 100644
index 0000000..a648f9f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ChromaticAberrationModel.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class ChromaticAberrationModel : PostProcessingModel
+{
+ [Serializable]
+ public struct Settings
+ {
+ [Tooltip("Shift the hue of chromatic aberrations.")]
+ public Texture2D spectralTexture;
+
+ [Range(0f, 1f)]
+ [Tooltip("Amount of tangential distortion.")]
+ public float intensity;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.spectralTexture = null;
+ result.intensity = 0.1f;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingComponent.cs
new file mode 100644
index 0000000..948d9c6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingComponent.cs
@@ -0,0 +1,352 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class ColorGradingComponent : PostProcessingComponentRenderTexture<ColorGradingModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _LutParams = Shader.PropertyToID("_LutParams");
+
+ internal static readonly int _NeutralTonemapperParams1 = Shader.PropertyToID("_NeutralTonemapperParams1");
+
+ internal static readonly int _NeutralTonemapperParams2 = Shader.PropertyToID("_NeutralTonemapperParams2");
+
+ internal static readonly int _HueShift = Shader.PropertyToID("_HueShift");
+
+ internal static readonly int _Saturation = Shader.PropertyToID("_Saturation");
+
+ internal static readonly int _Contrast = Shader.PropertyToID("_Contrast");
+
+ internal static readonly int _Balance = Shader.PropertyToID("_Balance");
+
+ internal static readonly int _Lift = Shader.PropertyToID("_Lift");
+
+ internal static readonly int _InvGamma = Shader.PropertyToID("_InvGamma");
+
+ internal static readonly int _Gain = Shader.PropertyToID("_Gain");
+
+ internal static readonly int _Slope = Shader.PropertyToID("_Slope");
+
+ internal static readonly int _Power = Shader.PropertyToID("_Power");
+
+ internal static readonly int _Offset = Shader.PropertyToID("_Offset");
+
+ internal static readonly int _ChannelMixerRed = Shader.PropertyToID("_ChannelMixerRed");
+
+ internal static readonly int _ChannelMixerGreen = Shader.PropertyToID("_ChannelMixerGreen");
+
+ internal static readonly int _ChannelMixerBlue = Shader.PropertyToID("_ChannelMixerBlue");
+
+ internal static readonly int _Curves = Shader.PropertyToID("_Curves");
+
+ internal static readonly int _LogLut = Shader.PropertyToID("_LogLut");
+
+ internal static readonly int _LogLut_Params = Shader.PropertyToID("_LogLut_Params");
+
+ internal static readonly int _ExposureEV = Shader.PropertyToID("_ExposureEV");
+ }
+
+ private const int k_InternalLogLutSize = 32;
+
+ private const int k_CurvePrecision = 128;
+
+ private const float k_CurveStep = 1f / 128f;
+
+ private Texture2D m_GradingCurves;
+
+ private Color[] m_pixels = new Color[256];
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ private float StandardIlluminantY(float x)
+ {
+ return 2.87f * x - 3f * x * x - 0.27509508f;
+ }
+
+ private Vector3 CIExyToLMS(float x, float y)
+ {
+ float num = 1f;
+ float num2 = num * x / y;
+ float num3 = num * (1f - x - y) / y;
+ float x2 = 0.7328f * num2 + 0.4296f * num - 0.1624f * num3;
+ float y2 = -0.7036f * num2 + 1.6975f * num + 0.0061f * num3;
+ float z = 0.003f * num2 + 0.0136f * num + 0.9834f * num3;
+ return new Vector3(x2, y2, z);
+ }
+
+ private Vector3 CalculateColorBalance(float temperature, float tint)
+ {
+ float num = temperature / 55f;
+ float num2 = tint / 55f;
+ float x = 0.31271f - num * ((num < 0f) ? 0.1f : 0.05f);
+ float y = StandardIlluminantY(x) + num2 * 0.05f;
+ Vector3 vector = new Vector3(0.949237f, 1.03542f, 1.08728f);
+ Vector3 vector2 = CIExyToLMS(x, y);
+ return new Vector3(vector.x / vector2.x, vector.y / vector2.y, vector.z / vector2.z);
+ }
+
+ private static Color NormalizeColor(Color c)
+ {
+ float num = (c.r + c.g + c.b) / 3f;
+ if (Mathf.Approximately(num, 0f))
+ {
+ return new Color(1f, 1f, 1f, c.a);
+ }
+ Color result = default(Color);
+ result.r = c.r / num;
+ result.g = c.g / num;
+ result.b = c.b / num;
+ result.a = c.a;
+ return result;
+ }
+
+ private static Vector3 ClampVector(Vector3 v, float min, float max)
+ {
+ return new Vector3(Mathf.Clamp(v.x, min, max), Mathf.Clamp(v.y, min, max), Mathf.Clamp(v.z, min, max));
+ }
+
+ public static Vector3 GetLiftValue(Color lift)
+ {
+ Color color = NormalizeColor(lift);
+ float num = (color.r + color.g + color.b) / 3f;
+ float x = (color.r - num) * 0.1f + lift.a;
+ float y = (color.g - num) * 0.1f + lift.a;
+ float z = (color.b - num) * 0.1f + lift.a;
+ return ClampVector(new Vector3(x, y, z), -1f, 1f);
+ }
+
+ public static Vector3 GetGammaValue(Color gamma)
+ {
+ Color color = NormalizeColor(gamma);
+ float num = (color.r + color.g + color.b) / 3f;
+ gamma.a *= ((gamma.a < 0f) ? 0.8f : 5f);
+ float b = Mathf.Pow(2f, (color.r - num) * 0.5f) + gamma.a;
+ float b2 = Mathf.Pow(2f, (color.g - num) * 0.5f) + gamma.a;
+ float b3 = Mathf.Pow(2f, (color.b - num) * 0.5f) + gamma.a;
+ float x = 1f / Mathf.Max(0.01f, b);
+ float y = 1f / Mathf.Max(0.01f, b2);
+ float z = 1f / Mathf.Max(0.01f, b3);
+ return ClampVector(new Vector3(x, y, z), 0f, 5f);
+ }
+
+ public static Vector3 GetGainValue(Color gain)
+ {
+ Color color = NormalizeColor(gain);
+ float num = (color.r + color.g + color.b) / 3f;
+ gain.a *= ((gain.a > 0f) ? 3f : 1f);
+ float x = Mathf.Pow(2f, (color.r - num) * 0.5f) + gain.a;
+ float y = Mathf.Pow(2f, (color.g - num) * 0.5f) + gain.a;
+ float z = Mathf.Pow(2f, (color.b - num) * 0.5f) + gain.a;
+ return ClampVector(new Vector3(x, y, z), 0f, 4f);
+ }
+
+ public static void CalculateLiftGammaGain(Color lift, Color gamma, Color gain, out Vector3 outLift, out Vector3 outGamma, out Vector3 outGain)
+ {
+ outLift = GetLiftValue(lift);
+ outGamma = GetGammaValue(gamma);
+ outGain = GetGainValue(gain);
+ }
+
+ public static Vector3 GetSlopeValue(Color slope)
+ {
+ Color color = NormalizeColor(slope);
+ float num = (color.r + color.g + color.b) / 3f;
+ slope.a *= 0.5f;
+ float x = (color.r - num) * 0.1f + slope.a + 1f;
+ float y = (color.g - num) * 0.1f + slope.a + 1f;
+ float z = (color.b - num) * 0.1f + slope.a + 1f;
+ return ClampVector(new Vector3(x, y, z), 0f, 2f);
+ }
+
+ public static Vector3 GetPowerValue(Color power)
+ {
+ Color color = NormalizeColor(power);
+ float num = (color.r + color.g + color.b) / 3f;
+ power.a *= 0.5f;
+ float b = (color.r - num) * 0.1f + power.a + 1f;
+ float b2 = (color.g - num) * 0.1f + power.a + 1f;
+ float b3 = (color.b - num) * 0.1f + power.a + 1f;
+ float x = 1f / Mathf.Max(0.01f, b);
+ float y = 1f / Mathf.Max(0.01f, b2);
+ float z = 1f / Mathf.Max(0.01f, b3);
+ return ClampVector(new Vector3(x, y, z), 0.5f, 2.5f);
+ }
+
+ public static Vector3 GetOffsetValue(Color offset)
+ {
+ Color color = NormalizeColor(offset);
+ float num = (color.r + color.g + color.b) / 3f;
+ offset.a *= 0.5f;
+ float x = (color.r - num) * 0.05f + offset.a;
+ float y = (color.g - num) * 0.05f + offset.a;
+ float z = (color.b - num) * 0.05f + offset.a;
+ return ClampVector(new Vector3(x, y, z), -0.8f, 0.8f);
+ }
+
+ public static void CalculateSlopePowerOffset(Color slope, Color power, Color offset, out Vector3 outSlope, out Vector3 outPower, out Vector3 outOffset)
+ {
+ outSlope = GetSlopeValue(slope);
+ outPower = GetPowerValue(power);
+ outOffset = GetOffsetValue(offset);
+ }
+
+ private TextureFormat GetCurveFormat()
+ {
+ if (SystemInfo.SupportsTextureFormat(TextureFormat.RGBAHalf))
+ {
+ return TextureFormat.RGBAHalf;
+ }
+ return TextureFormat.RGBA32;
+ }
+
+ private Texture2D GetCurveTexture()
+ {
+ if (m_GradingCurves == null)
+ {
+ m_GradingCurves = new Texture2D(128, 2, GetCurveFormat(), mipChain: false, linear: true)
+ {
+ name = "Internal Curves Texture",
+ hideFlags = HideFlags.DontSave,
+ anisoLevel = 0,
+ wrapMode = TextureWrapMode.Clamp,
+ filterMode = FilterMode.Bilinear
+ };
+ }
+ ColorGradingModel.CurvesSettings curves = base.model.settings.curves;
+ curves.hueVShue.Cache();
+ curves.hueVSsat.Cache();
+ for (int i = 0; i < 128; i++)
+ {
+ float t = (float)i * (1f / 128f);
+ float r = curves.hueVShue.Evaluate(t);
+ float g = curves.hueVSsat.Evaluate(t);
+ float b = curves.satVSsat.Evaluate(t);
+ float a = curves.lumVSsat.Evaluate(t);
+ m_pixels[i] = new Color(r, g, b, a);
+ float a2 = curves.master.Evaluate(t);
+ float r2 = curves.red.Evaluate(t);
+ float g2 = curves.green.Evaluate(t);
+ float b2 = curves.blue.Evaluate(t);
+ m_pixels[i + 128] = new Color(r2, g2, b2, a2);
+ }
+ m_GradingCurves.SetPixels(m_pixels);
+ m_GradingCurves.Apply(updateMipmaps: false, makeNoLongerReadable: false);
+ return m_GradingCurves;
+ }
+
+ private bool IsLogLutValid(RenderTexture lut)
+ {
+ if (lut != null && lut.IsCreated())
+ {
+ return lut.height == 32;
+ }
+ return false;
+ }
+
+ private RenderTextureFormat GetLutFormat()
+ {
+ if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
+ {
+ return RenderTextureFormat.ARGBHalf;
+ }
+ return RenderTextureFormat.ARGB32;
+ }
+
+ private void GenerateLut()
+ {
+ ColorGradingModel.Settings settings = base.model.settings;
+ if (!IsLogLutValid(base.model.bakedLut))
+ {
+ GraphicsUtils.Destroy(base.model.bakedLut);
+ base.model.bakedLut = new RenderTexture(1024, 32, 0, GetLutFormat())
+ {
+ name = "Color Grading Log LUT",
+ hideFlags = HideFlags.DontSave,
+ filterMode = FilterMode.Bilinear,
+ wrapMode = TextureWrapMode.Clamp,
+ anisoLevel = 0
+ };
+ }
+ Material material = context.materialFactory.Get("Hidden/Post FX/Lut Generator");
+ material.SetVector(Uniforms._LutParams, new Vector4(32f, 0.00048828125f, 1f / 64f, 1.032258f));
+ material.shaderKeywords = null;
+ ColorGradingModel.TonemappingSettings tonemapping = settings.tonemapping;
+ switch (tonemapping.tonemapper)
+ {
+ case ColorGradingModel.Tonemapper.Neutral:
+ {
+ material.EnableKeyword("TONEMAPPING_NEUTRAL");
+ float num = tonemapping.neutralBlackIn * 20f + 1f;
+ float num2 = tonemapping.neutralBlackOut * 10f + 1f;
+ float num3 = tonemapping.neutralWhiteIn / 20f;
+ float num4 = 1f - tonemapping.neutralWhiteOut / 20f;
+ float t = num / num2;
+ float t2 = num3 / num4;
+ float y = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, t));
+ float z = Mathf.LerpUnclamped(0.01f, 0.24f, t2);
+ float w = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.2f, t));
+ material.SetVector(Uniforms._NeutralTonemapperParams1, new Vector4(0.2f, y, z, w));
+ material.SetVector(Uniforms._NeutralTonemapperParams2, new Vector4(0.02f, 0.3f, tonemapping.neutralWhiteLevel, tonemapping.neutralWhiteClip / 10f));
+ break;
+ }
+ case ColorGradingModel.Tonemapper.ACES:
+ material.EnableKeyword("TONEMAPPING_FILMIC");
+ break;
+ }
+ material.SetFloat(Uniforms._HueShift, settings.basic.hueShift / 360f);
+ material.SetFloat(Uniforms._Saturation, settings.basic.saturation);
+ material.SetFloat(Uniforms._Contrast, settings.basic.contrast);
+ material.SetVector(Uniforms._Balance, CalculateColorBalance(settings.basic.temperature, settings.basic.tint));
+ CalculateLiftGammaGain(settings.colorWheels.linear.lift, settings.colorWheels.linear.gamma, settings.colorWheels.linear.gain, out var outLift, out var outGamma, out var outGain);
+ material.SetVector(Uniforms._Lift, outLift);
+ material.SetVector(Uniforms._InvGamma, outGamma);
+ material.SetVector(Uniforms._Gain, outGain);
+ CalculateSlopePowerOffset(settings.colorWheels.log.slope, settings.colorWheels.log.power, settings.colorWheels.log.offset, out var outSlope, out var outPower, out var outOffset);
+ material.SetVector(Uniforms._Slope, outSlope);
+ material.SetVector(Uniforms._Power, outPower);
+ material.SetVector(Uniforms._Offset, outOffset);
+ material.SetVector(Uniforms._ChannelMixerRed, settings.channelMixer.red);
+ material.SetVector(Uniforms._ChannelMixerGreen, settings.channelMixer.green);
+ material.SetVector(Uniforms._ChannelMixerBlue, settings.channelMixer.blue);
+ material.SetTexture(Uniforms._Curves, GetCurveTexture());
+ Graphics.Blit(null, base.model.bakedLut, material, 0);
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ if (base.model.isDirty || !IsLogLutValid(base.model.bakedLut))
+ {
+ GenerateLut();
+ base.model.isDirty = false;
+ }
+ uberMaterial.EnableKeyword(context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.PreGradingLog) ? "COLOR_GRADING_LOG_VIEW" : "COLOR_GRADING");
+ RenderTexture bakedLut = base.model.bakedLut;
+ uberMaterial.SetTexture(Uniforms._LogLut, bakedLut);
+ uberMaterial.SetVector(Uniforms._LogLut_Params, new Vector3(1f / (float)bakedLut.width, 1f / (float)bakedLut.height, (float)bakedLut.height - 1f));
+ float value = Mathf.Exp(base.model.settings.basic.postExposure * 0.6931472f);
+ uberMaterial.SetFloat(Uniforms._ExposureEV, value);
+ }
+
+ public void OnGUI()
+ {
+ RenderTexture bakedLut = base.model.bakedLut;
+ GUI.DrawTexture(new Rect(context.viewport.x * (float)Screen.width + 8f, 8f, bakedLut.width, bakedLut.height), bakedLut);
+ }
+
+ public override void OnDisable()
+ {
+ GraphicsUtils.Destroy(m_GradingCurves);
+ GraphicsUtils.Destroy(base.model.bakedLut);
+ m_GradingCurves = null;
+ base.model.bakedLut = null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingCurve.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingCurve.cs
new file mode 100644
index 0000000..49ea13a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingCurve.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public sealed class ColorGradingCurve
+{
+ public AnimationCurve curve;
+
+ [SerializeField]
+ private bool m_Loop;
+
+ [SerializeField]
+ private float m_ZeroValue;
+
+ [SerializeField]
+ private float m_Range;
+
+ private AnimationCurve m_InternalLoopingCurve;
+
+ public ColorGradingCurve(AnimationCurve curve, float zeroValue, bool loop, Vector2 bounds)
+ {
+ this.curve = curve;
+ m_ZeroValue = zeroValue;
+ m_Loop = loop;
+ m_Range = bounds.magnitude;
+ }
+
+ public void Cache()
+ {
+ if (!m_Loop)
+ {
+ return;
+ }
+ int length = curve.length;
+ if (length >= 2)
+ {
+ if (m_InternalLoopingCurve == null)
+ {
+ m_InternalLoopingCurve = new AnimationCurve();
+ }
+ Keyframe key = curve[length - 1];
+ key.time -= m_Range;
+ Keyframe key2 = curve[0];
+ key2.time += m_Range;
+ m_InternalLoopingCurve.keys = curve.keys;
+ m_InternalLoopingCurve.AddKey(key);
+ m_InternalLoopingCurve.AddKey(key2);
+ }
+ }
+
+ public float Evaluate(float t)
+ {
+ if (curve.length == 0)
+ {
+ return m_ZeroValue;
+ }
+ if (!m_Loop || curve.length == 1)
+ {
+ return curve.Evaluate(t);
+ }
+ return m_InternalLoopingCurve.Evaluate(t);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingModel.cs
new file mode 100644
index 0000000..5d5a45b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ColorGradingModel.cs
@@ -0,0 +1,319 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class ColorGradingModel : PostProcessingModel
+{
+ public enum Tonemapper
+ {
+ None,
+ ACES,
+ Neutral
+ }
+
+ [Serializable]
+ public struct TonemappingSettings
+ {
+ [Tooltip("Tonemapping algorithm to use at the end of the color grading process. Use \"Neutral\" if you need a customizable tonemapper or \"Filmic\" to give a standard filmic look to your scenes.")]
+ public Tonemapper tonemapper;
+
+ [Range(-0.1f, 0.1f)]
+ public float neutralBlackIn;
+
+ [Range(1f, 20f)]
+ public float neutralWhiteIn;
+
+ [Range(-0.09f, 0.1f)]
+ public float neutralBlackOut;
+
+ [Range(1f, 19f)]
+ public float neutralWhiteOut;
+
+ [Range(0.1f, 20f)]
+ public float neutralWhiteLevel;
+
+ [Range(1f, 10f)]
+ public float neutralWhiteClip;
+
+ public static TonemappingSettings defaultSettings
+ {
+ get
+ {
+ TonemappingSettings result = default(TonemappingSettings);
+ result.tonemapper = Tonemapper.Neutral;
+ result.neutralBlackIn = 0.02f;
+ result.neutralWhiteIn = 10f;
+ result.neutralBlackOut = 0f;
+ result.neutralWhiteOut = 10f;
+ result.neutralWhiteLevel = 5.3f;
+ result.neutralWhiteClip = 10f;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct BasicSettings
+ {
+ [Tooltip("Adjusts the overall exposure of the scene in EV units. This is applied after HDR effect and right before tonemapping so it won't affect previous effects in the chain.")]
+ public float postExposure;
+
+ [Range(-100f, 100f)]
+ [Tooltip("Sets the white balance to a custom color temperature.")]
+ public float temperature;
+
+ [Range(-100f, 100f)]
+ [Tooltip("Sets the white balance to compensate for a green or magenta tint.")]
+ public float tint;
+
+ [Range(-180f, 180f)]
+ [Tooltip("Shift the hue of all colors.")]
+ public float hueShift;
+
+ [Range(0f, 2f)]
+ [Tooltip("Pushes the intensity of all colors.")]
+ public float saturation;
+
+ [Range(0f, 2f)]
+ [Tooltip("Expands or shrinks the overall range of tonal values.")]
+ public float contrast;
+
+ public static BasicSettings defaultSettings
+ {
+ get
+ {
+ BasicSettings result = default(BasicSettings);
+ result.postExposure = 0f;
+ result.temperature = 0f;
+ result.tint = 0f;
+ result.hueShift = 0f;
+ result.saturation = 1f;
+ result.contrast = 1f;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct ChannelMixerSettings
+ {
+ public Vector3 red;
+
+ public Vector3 green;
+
+ public Vector3 blue;
+
+ [HideInInspector]
+ public int currentEditingChannel;
+
+ public static ChannelMixerSettings defaultSettings
+ {
+ get
+ {
+ ChannelMixerSettings result = default(ChannelMixerSettings);
+ result.red = new Vector3(1f, 0f, 0f);
+ result.green = new Vector3(0f, 1f, 0f);
+ result.blue = new Vector3(0f, 0f, 1f);
+ result.currentEditingChannel = 0;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct LogWheelsSettings
+ {
+ [Trackball("GetSlopeValue")]
+ public Color slope;
+
+ [Trackball("GetPowerValue")]
+ public Color power;
+
+ [Trackball("GetOffsetValue")]
+ public Color offset;
+
+ public static LogWheelsSettings defaultSettings
+ {
+ get
+ {
+ LogWheelsSettings result = default(LogWheelsSettings);
+ result.slope = Color.clear;
+ result.power = Color.clear;
+ result.offset = Color.clear;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct LinearWheelsSettings
+ {
+ [Trackball("GetLiftValue")]
+ public Color lift;
+
+ [Trackball("GetGammaValue")]
+ public Color gamma;
+
+ [Trackball("GetGainValue")]
+ public Color gain;
+
+ public static LinearWheelsSettings defaultSettings
+ {
+ get
+ {
+ LinearWheelsSettings result = default(LinearWheelsSettings);
+ result.lift = Color.clear;
+ result.gamma = Color.clear;
+ result.gain = Color.clear;
+ return result;
+ }
+ }
+ }
+
+ public enum ColorWheelMode
+ {
+ Linear,
+ Log
+ }
+
+ [Serializable]
+ public struct ColorWheelsSettings
+ {
+ public ColorWheelMode mode;
+
+ [TrackballGroup]
+ public LogWheelsSettings log;
+
+ [TrackballGroup]
+ public LinearWheelsSettings linear;
+
+ public static ColorWheelsSettings defaultSettings
+ {
+ get
+ {
+ ColorWheelsSettings result = default(ColorWheelsSettings);
+ result.mode = ColorWheelMode.Log;
+ result.log = LogWheelsSettings.defaultSettings;
+ result.linear = LinearWheelsSettings.defaultSettings;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct CurvesSettings
+ {
+ public ColorGradingCurve master;
+
+ public ColorGradingCurve red;
+
+ public ColorGradingCurve green;
+
+ public ColorGradingCurve blue;
+
+ public ColorGradingCurve hueVShue;
+
+ public ColorGradingCurve hueVSsat;
+
+ public ColorGradingCurve satVSsat;
+
+ public ColorGradingCurve lumVSsat;
+
+ [HideInInspector]
+ public int e_CurrentEditingCurve;
+
+ [HideInInspector]
+ public bool e_CurveY;
+
+ [HideInInspector]
+ public bool e_CurveR;
+
+ [HideInInspector]
+ public bool e_CurveG;
+
+ [HideInInspector]
+ public bool e_CurveB;
+
+ public static CurvesSettings defaultSettings
+ {
+ get
+ {
+ CurvesSettings result = default(CurvesSettings);
+ result.master = new ColorGradingCurve(new AnimationCurve(new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f)), 0f, loop: false, new Vector2(0f, 1f));
+ result.red = new ColorGradingCurve(new AnimationCurve(new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f)), 0f, loop: false, new Vector2(0f, 1f));
+ result.green = new ColorGradingCurve(new AnimationCurve(new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f)), 0f, loop: false, new Vector2(0f, 1f));
+ result.blue = new ColorGradingCurve(new AnimationCurve(new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f)), 0f, loop: false, new Vector2(0f, 1f));
+ result.hueVShue = new ColorGradingCurve(new AnimationCurve(), 0.5f, loop: true, new Vector2(0f, 1f));
+ result.hueVSsat = new ColorGradingCurve(new AnimationCurve(), 0.5f, loop: true, new Vector2(0f, 1f));
+ result.satVSsat = new ColorGradingCurve(new AnimationCurve(), 0.5f, loop: false, new Vector2(0f, 1f));
+ result.lumVSsat = new ColorGradingCurve(new AnimationCurve(), 0.5f, loop: false, new Vector2(0f, 1f));
+ result.e_CurrentEditingCurve = 0;
+ result.e_CurveY = true;
+ result.e_CurveR = false;
+ result.e_CurveG = false;
+ result.e_CurveB = false;
+ return result;
+ }
+ }
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ public TonemappingSettings tonemapping;
+
+ public BasicSettings basic;
+
+ public ChannelMixerSettings channelMixer;
+
+ public ColorWheelsSettings colorWheels;
+
+ public CurvesSettings curves;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.tonemapping = TonemappingSettings.defaultSettings;
+ result.basic = BasicSettings.defaultSettings;
+ result.channelMixer = ChannelMixerSettings.defaultSettings;
+ result.colorWheels = ColorWheelsSettings.defaultSettings;
+ result.curves = CurvesSettings.defaultSettings;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ OnValidate();
+ }
+ }
+
+ public bool isDirty { get; internal set; }
+
+ public RenderTexture bakedLut { get; internal set; }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ OnValidate();
+ }
+
+ public override void OnValidate()
+ {
+ isDirty = true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldComponent.cs
new file mode 100644
index 0000000..787f3ff
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldComponent.cs
@@ -0,0 +1,155 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class DepthOfFieldComponent : PostProcessingComponentRenderTexture<DepthOfFieldModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _DepthOfFieldTex = Shader.PropertyToID("_DepthOfFieldTex");
+
+ internal static readonly int _DepthOfFieldCoCTex = Shader.PropertyToID("_DepthOfFieldCoCTex");
+
+ internal static readonly int _Distance = Shader.PropertyToID("_Distance");
+
+ internal static readonly int _LensCoeff = Shader.PropertyToID("_LensCoeff");
+
+ internal static readonly int _MaxCoC = Shader.PropertyToID("_MaxCoC");
+
+ internal static readonly int _RcpMaxCoC = Shader.PropertyToID("_RcpMaxCoC");
+
+ internal static readonly int _RcpAspect = Shader.PropertyToID("_RcpAspect");
+
+ internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
+
+ internal static readonly int _CoCTex = Shader.PropertyToID("_CoCTex");
+
+ internal static readonly int _TaaParams = Shader.PropertyToID("_TaaParams");
+
+ internal static readonly int _DepthOfFieldParams = Shader.PropertyToID("_DepthOfFieldParams");
+ }
+
+ private const string k_ShaderString = "Hidden/Post FX/Depth Of Field";
+
+ private RenderTexture m_CoCHistory;
+
+ private const float k_FilmHeight = 0.024f;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.Depth;
+ }
+
+ private float CalculateFocalLength()
+ {
+ DepthOfFieldModel.Settings settings = base.model.settings;
+ if (!settings.useCameraFov)
+ {
+ return settings.focalLength / 1000f;
+ }
+ float num = context.camera.fieldOfView * ((float)Math.PI / 180f);
+ return 0.012f / Mathf.Tan(0.5f * num);
+ }
+
+ private float CalculateMaxCoCRadius(int screenHeight)
+ {
+ float num = (float)base.model.settings.kernelSize * 4f + 6f;
+ return Mathf.Min(0.05f, num / (float)screenHeight);
+ }
+
+ private bool CheckHistory(int width, int height)
+ {
+ if (m_CoCHistory != null && m_CoCHistory.IsCreated() && m_CoCHistory.width == width)
+ {
+ return m_CoCHistory.height == height;
+ }
+ return false;
+ }
+
+ private RenderTextureFormat SelectFormat(RenderTextureFormat primary, RenderTextureFormat secondary)
+ {
+ if (SystemInfo.SupportsRenderTextureFormat(primary))
+ {
+ return primary;
+ }
+ if (SystemInfo.SupportsRenderTextureFormat(secondary))
+ {
+ return secondary;
+ }
+ return RenderTextureFormat.Default;
+ }
+
+ public void Prepare(RenderTexture source, Material uberMaterial, bool antialiasCoC, Vector2 taaJitter, float taaBlending)
+ {
+ DepthOfFieldModel.Settings settings = base.model.settings;
+ RenderTextureFormat format = RenderTextureFormat.DefaultHDR;
+ RenderTextureFormat format2 = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf);
+ float num = CalculateFocalLength();
+ float num2 = Mathf.Max(settings.focusDistance, num);
+ float num3 = (float)source.width / (float)source.height;
+ float num4 = num * num / (settings.aperture * (num2 - num) * 0.024f * 2f);
+ float num5 = CalculateMaxCoCRadius(source.height);
+ Material material = context.materialFactory.Get("Hidden/Post FX/Depth Of Field");
+ material.SetFloat(Uniforms._Distance, num2);
+ material.SetFloat(Uniforms._LensCoeff, num4);
+ material.SetFloat(Uniforms._MaxCoC, num5);
+ material.SetFloat(Uniforms._RcpMaxCoC, 1f / num5);
+ material.SetFloat(Uniforms._RcpAspect, 1f / num3);
+ RenderTexture renderTexture = context.renderTextureFactory.Get(context.width, context.height, 0, format2, RenderTextureReadWrite.Linear);
+ Graphics.Blit(null, renderTexture, material, 0);
+ if (antialiasCoC)
+ {
+ material.SetTexture(Uniforms._CoCTex, renderTexture);
+ float z = (CheckHistory(context.width, context.height) ? taaBlending : 0f);
+ material.SetVector(Uniforms._TaaParams, new Vector3(taaJitter.x, taaJitter.y, z));
+ RenderTexture temporary = RenderTexture.GetTemporary(context.width, context.height, 0, format2);
+ Graphics.Blit(m_CoCHistory, temporary, material, 1);
+ context.renderTextureFactory.Release(renderTexture);
+ if (m_CoCHistory != null)
+ {
+ RenderTexture.ReleaseTemporary(m_CoCHistory);
+ }
+ renderTexture = (m_CoCHistory = temporary);
+ }
+ RenderTexture renderTexture2 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, format);
+ material.SetTexture(Uniforms._CoCTex, renderTexture);
+ Graphics.Blit(source, renderTexture2, material, 2);
+ RenderTexture renderTexture3 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, format);
+ Graphics.Blit(renderTexture2, renderTexture3, material, (int)(3 + settings.kernelSize));
+ Graphics.Blit(renderTexture3, renderTexture2, material, 7);
+ uberMaterial.SetVector(Uniforms._DepthOfFieldParams, new Vector3(num2, num4, num5));
+ if (context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.FocusPlane))
+ {
+ uberMaterial.EnableKeyword("DEPTH_OF_FIELD_COC_VIEW");
+ context.Interrupt();
+ }
+ else
+ {
+ uberMaterial.SetTexture(Uniforms._DepthOfFieldTex, renderTexture2);
+ uberMaterial.SetTexture(Uniforms._DepthOfFieldCoCTex, renderTexture);
+ uberMaterial.EnableKeyword("DEPTH_OF_FIELD");
+ }
+ context.renderTextureFactory.Release(renderTexture3);
+ }
+
+ public override void OnDisable()
+ {
+ if (m_CoCHistory != null)
+ {
+ RenderTexture.ReleaseTemporary(m_CoCHistory);
+ }
+ m_CoCHistory = null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldModel.cs
new file mode 100644
index 0000000..6ead0de
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DepthOfFieldModel.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class DepthOfFieldModel : PostProcessingModel
+{
+ public enum KernelSize
+ {
+ Small,
+ Medium,
+ Large,
+ VeryLarge
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ [Min(0.1f)]
+ [Tooltip("Distance to the point of focus.")]
+ public float focusDistance;
+
+ [Range(0.05f, 32f)]
+ [Tooltip("Ratio of aperture (known as f-stop or f-number). The smaller the value is, the shallower the depth of field is.")]
+ public float aperture;
+
+ [Range(1f, 300f)]
+ [Tooltip("Distance between the lens and the film. The larger the value is, the shallower the depth of field is.")]
+ public float focalLength;
+
+ [Tooltip("Calculate the focal length automatically from the field-of-view value set on the camera. Using this setting isn't recommended.")]
+ public bool useCameraFov;
+
+ [Tooltip("Convolution kernel size of the bokeh filter, which determines the maximum radius of bokeh. It also affects the performance (the larger the kernel is, the longer the GPU time is required).")]
+ public KernelSize kernelSize;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.focusDistance = 10f;
+ result.aperture = 5.6f;
+ result.focalLength = 50f;
+ result.useCameraFov = false;
+ result.kernelSize = KernelSize.Medium;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringComponent.cs
new file mode 100644
index 0000000..f5f2395
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringComponent.cs
@@ -0,0 +1,61 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class DitheringComponent : PostProcessingComponentRenderTexture<DitheringModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _DitheringTex = Shader.PropertyToID("_DitheringTex");
+
+ internal static readonly int _DitheringCoords = Shader.PropertyToID("_DitheringCoords");
+ }
+
+ private Texture2D[] noiseTextures;
+
+ private int textureIndex;
+
+ private const int k_TextureCount = 64;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override void OnDisable()
+ {
+ noiseTextures = null;
+ }
+
+ private void LoadNoiseTextures()
+ {
+ noiseTextures = new Texture2D[64];
+ for (int i = 0; i < 64; i++)
+ {
+ noiseTextures[i] = Resources.Load<Texture2D>("Bluenoise64/LDR_LLL1_" + i);
+ }
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ if (++textureIndex >= 64)
+ {
+ textureIndex = 0;
+ }
+ float value = Random.value;
+ float value2 = Random.value;
+ if (noiseTextures == null)
+ {
+ LoadNoiseTextures();
+ }
+ Texture2D texture2D = noiseTextures[textureIndex];
+ uberMaterial.EnableKeyword("DITHERING");
+ uberMaterial.SetTexture(Uniforms._DitheringTex, texture2D);
+ uberMaterial.SetVector(Uniforms._DitheringCoords, new Vector4((float)context.width / (float)texture2D.width, (float)context.height / (float)texture2D.height, value, value2));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringModel.cs
new file mode 100644
index 0000000..1258f2e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/DitheringModel.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class DitheringModel : PostProcessingModel
+{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, Size = 1)]
+ public struct Settings
+ {
+ public static Settings defaultSettings => default(Settings);
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationComponent.cs
new file mode 100644
index 0000000..8e754b0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationComponent.cs
@@ -0,0 +1,177 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class EyeAdaptationComponent : PostProcessingComponentRenderTexture<EyeAdaptationModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _Params = Shader.PropertyToID("_Params");
+
+ internal static readonly int _Speed = Shader.PropertyToID("_Speed");
+
+ internal static readonly int _ScaleOffsetRes = Shader.PropertyToID("_ScaleOffsetRes");
+
+ internal static readonly int _ExposureCompensation = Shader.PropertyToID("_ExposureCompensation");
+
+ internal static readonly int _AutoExposure = Shader.PropertyToID("_AutoExposure");
+
+ internal static readonly int _DebugWidth = Shader.PropertyToID("_DebugWidth");
+ }
+
+ private ComputeShader m_EyeCompute;
+
+ private ComputeBuffer m_HistogramBuffer;
+
+ private readonly RenderTexture[] m_AutoExposurePool = new RenderTexture[2];
+
+ private int m_AutoExposurePingPing;
+
+ private RenderTexture m_CurrentAutoExposure;
+
+ private RenderTexture m_DebugHistogram;
+
+ private static uint[] s_EmptyHistogramBuffer;
+
+ private bool m_FirstFrame = true;
+
+ private const int k_HistogramBins = 64;
+
+ private const int k_HistogramThreadX = 16;
+
+ private const int k_HistogramThreadY = 16;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && SystemInfo.supportsComputeShaders)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public void ResetHistory()
+ {
+ m_FirstFrame = true;
+ }
+
+ public override void OnEnable()
+ {
+ m_FirstFrame = true;
+ }
+
+ public override void OnDisable()
+ {
+ RenderTexture[] autoExposurePool = m_AutoExposurePool;
+ for (int i = 0; i < autoExposurePool.Length; i++)
+ {
+ GraphicsUtils.Destroy(autoExposurePool[i]);
+ }
+ if (m_HistogramBuffer != null)
+ {
+ m_HistogramBuffer.Release();
+ }
+ m_HistogramBuffer = null;
+ if (m_DebugHistogram != null)
+ {
+ m_DebugHistogram.Release();
+ }
+ m_DebugHistogram = null;
+ }
+
+ private Vector4 GetHistogramScaleOffsetRes()
+ {
+ EyeAdaptationModel.Settings settings = base.model.settings;
+ float num = settings.logMax - settings.logMin;
+ float num2 = 1f / num;
+ float y = (float)(-settings.logMin) * num2;
+ return new Vector4(num2, y, Mathf.Floor((float)context.width / 2f), Mathf.Floor((float)context.height / 2f));
+ }
+
+ public Texture Prepare(RenderTexture source, Material uberMaterial)
+ {
+ EyeAdaptationModel.Settings settings = base.model.settings;
+ if (m_EyeCompute == null)
+ {
+ m_EyeCompute = Resources.Load<ComputeShader>("Shaders/EyeHistogram");
+ }
+ Material material = context.materialFactory.Get("Hidden/Post FX/Eye Adaptation");
+ material.shaderKeywords = null;
+ if (m_HistogramBuffer == null)
+ {
+ m_HistogramBuffer = new ComputeBuffer(64, 4);
+ }
+ if (s_EmptyHistogramBuffer == null)
+ {
+ s_EmptyHistogramBuffer = new uint[64];
+ }
+ Vector4 histogramScaleOffsetRes = GetHistogramScaleOffsetRes();
+ RenderTexture renderTexture = context.renderTextureFactory.Get((int)histogramScaleOffsetRes.z, (int)histogramScaleOffsetRes.w, 0, source.format);
+ Graphics.Blit(source, renderTexture);
+ if (m_AutoExposurePool[0] == null || !m_AutoExposurePool[0].IsCreated())
+ {
+ m_AutoExposurePool[0] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
+ }
+ if (m_AutoExposurePool[1] == null || !m_AutoExposurePool[1].IsCreated())
+ {
+ m_AutoExposurePool[1] = new RenderTexture(1, 1, 0, RenderTextureFormat.RFloat);
+ }
+ m_HistogramBuffer.SetData(s_EmptyHistogramBuffer);
+ int kernelIndex = m_EyeCompute.FindKernel("KEyeHistogram");
+ m_EyeCompute.SetBuffer(kernelIndex, "_Histogram", m_HistogramBuffer);
+ m_EyeCompute.SetTexture(kernelIndex, "_Source", renderTexture);
+ m_EyeCompute.SetVector("_ScaleOffsetRes", histogramScaleOffsetRes);
+ m_EyeCompute.Dispatch(kernelIndex, Mathf.CeilToInt((float)renderTexture.width / 16f), Mathf.CeilToInt((float)renderTexture.height / 16f), 1);
+ context.renderTextureFactory.Release(renderTexture);
+ settings.highPercent = Mathf.Clamp(settings.highPercent, 1.01f, 99f);
+ settings.lowPercent = Mathf.Clamp(settings.lowPercent, 1f, settings.highPercent - 0.01f);
+ material.SetBuffer("_Histogram", m_HistogramBuffer);
+ material.SetVector(Uniforms._Params, new Vector4(settings.lowPercent * 0.01f, settings.highPercent * 0.01f, Mathf.Exp(settings.minLuminance * 0.6931472f), Mathf.Exp(settings.maxLuminance * 0.6931472f)));
+ material.SetVector(Uniforms._Speed, new Vector2(settings.speedDown, settings.speedUp));
+ material.SetVector(Uniforms._ScaleOffsetRes, histogramScaleOffsetRes);
+ material.SetFloat(Uniforms._ExposureCompensation, settings.keyValue);
+ if (settings.dynamicKeyValue)
+ {
+ material.EnableKeyword("AUTO_KEY_VALUE");
+ }
+ if (m_FirstFrame || !Application.isPlaying)
+ {
+ m_CurrentAutoExposure = m_AutoExposurePool[0];
+ Graphics.Blit(null, m_CurrentAutoExposure, material, 1);
+ Graphics.Blit(m_AutoExposurePool[0], m_AutoExposurePool[1]);
+ }
+ else
+ {
+ int autoExposurePingPing = m_AutoExposurePingPing;
+ RenderTexture source2 = m_AutoExposurePool[++autoExposurePingPing % 2];
+ RenderTexture renderTexture2 = m_AutoExposurePool[++autoExposurePingPing % 2];
+ Graphics.Blit(source2, renderTexture2, material, (int)settings.adaptationType);
+ m_AutoExposurePingPing = ++autoExposurePingPing % 2;
+ m_CurrentAutoExposure = renderTexture2;
+ }
+ if (context.profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.EyeAdaptation))
+ {
+ if (m_DebugHistogram == null || !m_DebugHistogram.IsCreated())
+ {
+ m_DebugHistogram = new RenderTexture(256, 128, 0, RenderTextureFormat.ARGB32)
+ {
+ filterMode = FilterMode.Point,
+ wrapMode = TextureWrapMode.Clamp
+ };
+ }
+ material.SetFloat(Uniforms._DebugWidth, m_DebugHistogram.width);
+ Graphics.Blit(null, m_DebugHistogram, material, 2);
+ }
+ m_FirstFrame = false;
+ return m_CurrentAutoExposure;
+ }
+
+ public void OnGUI()
+ {
+ if (!(m_DebugHistogram == null) && m_DebugHistogram.IsCreated())
+ {
+ GUI.DrawTexture(new Rect(context.viewport.x * (float)Screen.width + 8f, 8f, m_DebugHistogram.width, m_DebugHistogram.height), m_DebugHistogram);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationModel.cs
new file mode 100644
index 0000000..aab9a3d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/EyeAdaptationModel.cs
@@ -0,0 +1,97 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class EyeAdaptationModel : PostProcessingModel
+{
+ public enum EyeAdaptationType
+ {
+ Progressive,
+ Fixed
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ [Range(1f, 99f)]
+ [Tooltip("Filters the dark part of the histogram when computing the average luminance to avoid very dark pixels from contributing to the auto exposure. Unit is in percent.")]
+ public float lowPercent;
+
+ [Range(1f, 99f)]
+ [Tooltip("Filters the bright part of the histogram when computing the average luminance to avoid very dark pixels from contributing to the auto exposure. Unit is in percent.")]
+ public float highPercent;
+
+ [Tooltip("Minimum average luminance to consider for auto exposure (in EV).")]
+ public float minLuminance;
+
+ [Tooltip("Maximum average luminance to consider for auto exposure (in EV).")]
+ public float maxLuminance;
+
+ [Min(0f)]
+ [Tooltip("Exposure bias. Use this to offset the global exposure of the scene.")]
+ public float keyValue;
+
+ [Tooltip("Set this to true to let Unity handle the key value automatically based on average luminance.")]
+ public bool dynamicKeyValue;
+
+ [Tooltip("Use \"Progressive\" if you want the auto exposure to be animated. Use \"Fixed\" otherwise.")]
+ public EyeAdaptationType adaptationType;
+
+ [Min(0f)]
+ [Tooltip("Adaptation speed from a dark to a light environment.")]
+ public float speedUp;
+
+ [Min(0f)]
+ [Tooltip("Adaptation speed from a light to a dark environment.")]
+ public float speedDown;
+
+ [Range(-16f, -1f)]
+ [Tooltip("Lower bound for the brightness range of the generated histogram (in EV). The bigger the spread between min & max, the lower the precision will be.")]
+ public int logMin;
+
+ [Range(1f, 16f)]
+ [Tooltip("Upper bound for the brightness range of the generated histogram (in EV). The bigger the spread between min & max, the lower the precision will be.")]
+ public int logMax;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.lowPercent = 45f;
+ result.highPercent = 95f;
+ result.minLuminance = -5f;
+ result.maxLuminance = 1f;
+ result.keyValue = 0.25f;
+ result.dynamicKeyValue = true;
+ result.adaptationType = EyeAdaptationType.Progressive;
+ result.speedUp = 2f;
+ result.speedDown = 1f;
+ result.logMin = -8;
+ result.logMax = 4;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogComponent.cs
new file mode 100644
index 0000000..229f23d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogComponent.cs
@@ -0,0 +1,97 @@
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class FogComponent : PostProcessingComponentCommandBuffer<FogModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _FogColor = Shader.PropertyToID("_FogColor");
+
+ internal static readonly int _Density = Shader.PropertyToID("_Density");
+
+ internal static readonly int _Start = Shader.PropertyToID("_Start");
+
+ internal static readonly int _End = Shader.PropertyToID("_End");
+
+ internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
+
+ internal static readonly int _TopLeft = Shader.PropertyToID("_TopLeft");
+
+ internal static readonly int _TopRight = Shader.PropertyToID("_TopRight");
+
+ internal static readonly int _BottomLeft = Shader.PropertyToID("_BottomLeft");
+
+ internal static readonly int _BottomRight = Shader.PropertyToID("_BottomRight");
+
+ internal static readonly int _SunDir = Shader.PropertyToID("_SunDir");
+
+ internal static readonly int _SunFogColor = Shader.PropertyToID("_SunFogColor");
+ }
+
+ private const string k_ShaderString = "Hidden/Post FX/Fog";
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && context.isGBufferAvailable && RenderSettings.fog)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override string GetName()
+ {
+ return "Fog";
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.Depth;
+ }
+
+ public override CameraEvent GetCameraEvent()
+ {
+ return CameraEvent.AfterImageEffectsOpaque;
+ }
+
+ public override void PopulateCommandBuffer(CommandBuffer cb)
+ {
+ FogModel.Settings settings = base.model.settings;
+ Material material = context.materialFactory.Get("Hidden/Post FX/Fog");
+ material.shaderKeywords = null;
+ Color value = (GraphicsUtils.isLinearColorSpace ? RenderSettings.fogColor.linear : RenderSettings.fogColor);
+ material.SetColor(Uniforms._FogColor, value);
+ material.SetFloat(Uniforms._Density, RenderSettings.fogDensity);
+ material.SetFloat(Uniforms._Start, RenderSettings.fogStartDistance);
+ material.SetFloat(Uniforms._End, RenderSettings.fogEndDistance);
+ Vector3 direction = context.camera.ViewportPointToRay(new Vector3(0f, 1f, 0f)).direction;
+ Vector3 direction2 = context.camera.ViewportPointToRay(new Vector3(1f, 1f, 0f)).direction;
+ Vector3 direction3 = context.camera.ViewportPointToRay(new Vector3(0f, 0f, 0f)).direction;
+ Vector3 direction4 = context.camera.ViewportPointToRay(new Vector3(1f, 0f, 0f)).direction;
+ material.SetVector(Uniforms._TopLeft, direction);
+ material.SetVector(Uniforms._TopRight, direction2);
+ material.SetVector(Uniforms._BottomLeft, direction3);
+ material.SetVector(Uniforms._BottomRight, direction4);
+ switch (RenderSettings.fogMode)
+ {
+ case FogMode.Linear:
+ material.EnableKeyword("FOG_LINEAR");
+ break;
+ case FogMode.Exponential:
+ material.EnableKeyword("FOG_EXP");
+ break;
+ case FogMode.ExponentialSquared:
+ material.EnableKeyword("FOG_EXP2");
+ break;
+ }
+ RenderTextureFormat format = (context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);
+ cb.GetTemporaryRT(Uniforms._TempRT, context.width, context.height, 24, FilterMode.Bilinear, format);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, Uniforms._TempRT);
+ cb.Blit(Uniforms._TempRT, BuiltinRenderTextureType.CameraTarget, material, settings.excludeSkybox ? 1 : 0);
+ cb.ReleaseTemporaryRT(Uniforms._TempRT);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogModel.cs
new file mode 100644
index 0000000..4a7f4cd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FogModel.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class FogModel : PostProcessingModel
+{
+ [Serializable]
+ public struct Settings
+ {
+ [Tooltip("Should the fog affect the skybox?")]
+ public bool excludeSkybox;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.excludeSkybox = true;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FxaaComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FxaaComponent.cs
new file mode 100644
index 0000000..236085b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/FxaaComponent.cs
@@ -0,0 +1,34 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class FxaaComponent : PostProcessingComponentRenderTexture<AntialiasingModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _QualitySettings = Shader.PropertyToID("_QualitySettings");
+
+ internal static readonly int _ConsoleSettings = Shader.PropertyToID("_ConsoleSettings");
+ }
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.method == AntialiasingModel.Method.Fxaa)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public void Render(RenderTexture source, RenderTexture destination)
+ {
+ AntialiasingModel.FxaaSettings fxaaSettings = base.model.settings.fxaaSettings;
+ Material material = context.materialFactory.Get("Hidden/Post FX/FXAA");
+ AntialiasingModel.FxaaQualitySettings fxaaQualitySettings = AntialiasingModel.FxaaQualitySettings.presets[(int)fxaaSettings.preset];
+ AntialiasingModel.FxaaConsoleSettings fxaaConsoleSettings = AntialiasingModel.FxaaConsoleSettings.presets[(int)fxaaSettings.preset];
+ material.SetVector(Uniforms._QualitySettings, new Vector3(fxaaQualitySettings.subpixelAliasingRemovalAmount, fxaaQualitySettings.edgeDetectionThreshold, fxaaQualitySettings.minimumRequiredLuminance));
+ material.SetVector(Uniforms._ConsoleSettings, new Vector4(fxaaConsoleSettings.subpixelSpreadAmount, fxaaConsoleSettings.edgeSharpnessAmount, fxaaConsoleSettings.edgeDetectionThreshold, fxaaConsoleSettings.minimumRequiredLuminance));
+ Graphics.Blit(source, destination, material, 0);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GetSetAttribute.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GetSetAttribute.cs
new file mode 100644
index 0000000..1b34e7d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GetSetAttribute.cs
@@ -0,0 +1,13 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class GetSetAttribute : PropertyAttribute
+{
+ public readonly string name;
+
+ public bool dirty;
+
+ public GetSetAttribute(string name)
+ {
+ this.name = name;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainComponent.cs
new file mode 100644
index 0000000..cc2be5d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainComponent.cs
@@ -0,0 +1,62 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class GrainComponent : PostProcessingComponentRenderTexture<GrainModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _Grain_Params1 = Shader.PropertyToID("_Grain_Params1");
+
+ internal static readonly int _Grain_Params2 = Shader.PropertyToID("_Grain_Params2");
+
+ internal static readonly int _GrainTex = Shader.PropertyToID("_GrainTex");
+
+ internal static readonly int _Phase = Shader.PropertyToID("_Phase");
+ }
+
+ private RenderTexture m_GrainLookupRT;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.intensity > 0f && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf))
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override void OnDisable()
+ {
+ GraphicsUtils.Destroy(m_GrainLookupRT);
+ m_GrainLookupRT = null;
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ GrainModel.Settings settings = base.model.settings;
+ uberMaterial.EnableKeyword("GRAIN");
+ float realtimeSinceStartup = Time.realtimeSinceStartup;
+ float value = Random.value;
+ float value2 = Random.value;
+ if (m_GrainLookupRT == null || !m_GrainLookupRT.IsCreated())
+ {
+ GraphicsUtils.Destroy(m_GrainLookupRT);
+ m_GrainLookupRT = new RenderTexture(192, 192, 0, RenderTextureFormat.ARGBHalf)
+ {
+ filterMode = FilterMode.Bilinear,
+ wrapMode = TextureWrapMode.Repeat,
+ anisoLevel = 0,
+ name = "Grain Lookup Texture"
+ };
+ m_GrainLookupRT.Create();
+ }
+ Material material = context.materialFactory.Get("Hidden/Post FX/Grain Generator");
+ material.SetFloat(Uniforms._Phase, realtimeSinceStartup / 20f);
+ Graphics.Blit(null, m_GrainLookupRT, material, settings.colored ? 1 : 0);
+ uberMaterial.SetTexture(Uniforms._GrainTex, m_GrainLookupRT);
+ uberMaterial.SetVector(Uniforms._Grain_Params1, new Vector2(settings.luminanceContribution, settings.intensity * 20f));
+ uberMaterial.SetVector(Uniforms._Grain_Params2, new Vector4((float)context.width / (float)m_GrainLookupRT.width / settings.size, (float)context.height / (float)m_GrainLookupRT.height / settings.size, value, value2));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainModel.cs
new file mode 100644
index 0000000..20ca694
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GrainModel.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class GrainModel : PostProcessingModel
+{
+ [Serializable]
+ public struct Settings
+ {
+ [Tooltip("Enable the use of colored grain.")]
+ public bool colored;
+
+ [Range(0f, 1f)]
+ [Tooltip("Grain strength. Higher means more visible grain.")]
+ public float intensity;
+
+ [Range(0.3f, 3f)]
+ [Tooltip("Grain particle size.")]
+ public float size;
+
+ [Range(0f, 1f)]
+ [Tooltip("Controls the noisiness response curve based on scene luminance. Lower values mean less noise in dark areas.")]
+ public float luminanceContribution;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.colored = true;
+ result.intensity = 0.5f;
+ result.size = 1f;
+ result.luminanceContribution = 0.8f;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GraphicsUtils.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GraphicsUtils.cs
new file mode 100644
index 0000000..d662af3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/GraphicsUtils.cs
@@ -0,0 +1,126 @@
+namespace UnityEngine.PostProcessing;
+
+public static class GraphicsUtils
+{
+ private static Texture2D s_WhiteTexture;
+
+ private static Mesh s_Quad;
+
+ public static bool isLinearColorSpace => QualitySettings.activeColorSpace == ColorSpace.Linear;
+
+ public static bool supportsDX11
+ {
+ get
+ {
+ if (SystemInfo.graphicsShaderLevel >= 50)
+ {
+ return SystemInfo.supportsComputeShaders;
+ }
+ return false;
+ }
+ }
+
+ public static Texture2D whiteTexture
+ {
+ get
+ {
+ if (s_WhiteTexture != null)
+ {
+ return s_WhiteTexture;
+ }
+ s_WhiteTexture = new Texture2D(1, 1, TextureFormat.ARGB32, mipChain: false);
+ s_WhiteTexture.SetPixel(0, 0, new Color(1f, 1f, 1f, 1f));
+ s_WhiteTexture.Apply();
+ return s_WhiteTexture;
+ }
+ }
+
+ public static Mesh quad
+ {
+ get
+ {
+ if (s_Quad != null)
+ {
+ return s_Quad;
+ }
+ Vector3[] vertices = new Vector3[4]
+ {
+ new Vector3(-1f, -1f, 0f),
+ new Vector3(1f, 1f, 0f),
+ new Vector3(1f, -1f, 0f),
+ new Vector3(-1f, 1f, 0f)
+ };
+ Vector2[] uv = new Vector2[4]
+ {
+ new Vector2(0f, 0f),
+ new Vector2(1f, 1f),
+ new Vector2(1f, 0f),
+ new Vector2(0f, 1f)
+ };
+ int[] triangles = new int[6] { 0, 1, 2, 1, 0, 3 };
+ s_Quad = new Mesh
+ {
+ vertices = vertices,
+ uv = uv,
+ triangles = triangles
+ };
+ s_Quad.RecalculateNormals();
+ s_Quad.RecalculateBounds();
+ return s_Quad;
+ }
+ }
+
+ public static void Blit(Material material, int pass)
+ {
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ material.SetPass(pass);
+ GL.Begin(5);
+ GL.TexCoord2(0f, 0f);
+ GL.Vertex3(0f, 0f, 0.1f);
+ GL.TexCoord2(1f, 0f);
+ GL.Vertex3(1f, 0f, 0.1f);
+ GL.TexCoord2(0f, 1f);
+ GL.Vertex3(0f, 1f, 0.1f);
+ GL.TexCoord2(1f, 1f);
+ GL.Vertex3(1f, 1f, 0.1f);
+ GL.End();
+ GL.PopMatrix();
+ }
+
+ public static void ClearAndBlit(Texture source, RenderTexture destination, Material material, int pass, bool clearColor = true, bool clearDepth = false)
+ {
+ RenderTexture active = RenderTexture.active;
+ RenderTexture.active = destination;
+ GL.Clear(clearDepth: false, clearColor, Color.clear);
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ material.SetTexture("_MainTex", source);
+ material.SetPass(pass);
+ GL.Begin(5);
+ GL.TexCoord2(0f, 0f);
+ GL.Vertex3(0f, 0f, 0.1f);
+ GL.TexCoord2(1f, 0f);
+ GL.Vertex3(1f, 0f, 0.1f);
+ GL.TexCoord2(0f, 1f);
+ GL.Vertex3(0f, 1f, 0.1f);
+ GL.TexCoord2(1f, 1f);
+ GL.Vertex3(1f, 1f, 0.1f);
+ GL.End();
+ GL.PopMatrix();
+ RenderTexture.active = active;
+ }
+
+ public static void Destroy(Object obj)
+ {
+ if (obj != null)
+ {
+ Object.Destroy(obj);
+ }
+ }
+
+ public static void Dispose()
+ {
+ Destroy(s_Quad);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MaterialFactory.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MaterialFactory.cs
new file mode 100644
index 0000000..0f046d1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MaterialFactory.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class MaterialFactory : IDisposable
+{
+ private Dictionary<string, Material> m_Materials;
+
+ public MaterialFactory()
+ {
+ m_Materials = new Dictionary<string, Material>();
+ }
+
+ public Material Get(string shaderName)
+ {
+ if (!m_Materials.TryGetValue(shaderName, out var value))
+ {
+ Shader shader = Shader.Find(shaderName);
+ if (shader == null)
+ {
+ throw new ArgumentException($"Shader not found ({shaderName})");
+ }
+ value = new Material(shader)
+ {
+ name = string.Format("PostFX - {0}", shaderName.Substring(shaderName.LastIndexOf("/") + 1)),
+ hideFlags = HideFlags.DontSave
+ };
+ m_Materials.Add(shaderName, value);
+ }
+ return value;
+ }
+
+ public void Dispose()
+ {
+ Dictionary<string, Material>.Enumerator enumerator = m_Materials.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ GraphicsUtils.Destroy(enumerator.Current.Value);
+ }
+ m_Materials.Clear();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MinAttribute.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MinAttribute.cs
new file mode 100644
index 0000000..cc991ef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MinAttribute.cs
@@ -0,0 +1,11 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class MinAttribute : PropertyAttribute
+{
+ public readonly float min;
+
+ public MinAttribute(float min)
+ {
+ this.min = min;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurComponent.cs
new file mode 100644
index 0000000..e2586ac
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurComponent.cs
@@ -0,0 +1,426 @@
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class MotionBlurComponent : PostProcessingComponentCommandBuffer<MotionBlurModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _VelocityScale = Shader.PropertyToID("_VelocityScale");
+
+ internal static readonly int _MaxBlurRadius = Shader.PropertyToID("_MaxBlurRadius");
+
+ internal static readonly int _RcpMaxBlurRadius = Shader.PropertyToID("_RcpMaxBlurRadius");
+
+ internal static readonly int _VelocityTex = Shader.PropertyToID("_VelocityTex");
+
+ internal static readonly int _MainTex = Shader.PropertyToID("_MainTex");
+
+ internal static readonly int _Tile2RT = Shader.PropertyToID("_Tile2RT");
+
+ internal static readonly int _Tile4RT = Shader.PropertyToID("_Tile4RT");
+
+ internal static readonly int _Tile8RT = Shader.PropertyToID("_Tile8RT");
+
+ internal static readonly int _TileMaxOffs = Shader.PropertyToID("_TileMaxOffs");
+
+ internal static readonly int _TileMaxLoop = Shader.PropertyToID("_TileMaxLoop");
+
+ internal static readonly int _TileVRT = Shader.PropertyToID("_TileVRT");
+
+ internal static readonly int _NeighborMaxTex = Shader.PropertyToID("_NeighborMaxTex");
+
+ internal static readonly int _LoopCount = Shader.PropertyToID("_LoopCount");
+
+ internal static readonly int _TempRT = Shader.PropertyToID("_TempRT");
+
+ internal static readonly int _History1LumaTex = Shader.PropertyToID("_History1LumaTex");
+
+ internal static readonly int _History2LumaTex = Shader.PropertyToID("_History2LumaTex");
+
+ internal static readonly int _History3LumaTex = Shader.PropertyToID("_History3LumaTex");
+
+ internal static readonly int _History4LumaTex = Shader.PropertyToID("_History4LumaTex");
+
+ internal static readonly int _History1ChromaTex = Shader.PropertyToID("_History1ChromaTex");
+
+ internal static readonly int _History2ChromaTex = Shader.PropertyToID("_History2ChromaTex");
+
+ internal static readonly int _History3ChromaTex = Shader.PropertyToID("_History3ChromaTex");
+
+ internal static readonly int _History4ChromaTex = Shader.PropertyToID("_History4ChromaTex");
+
+ internal static readonly int _History1Weight = Shader.PropertyToID("_History1Weight");
+
+ internal static readonly int _History2Weight = Shader.PropertyToID("_History2Weight");
+
+ internal static readonly int _History3Weight = Shader.PropertyToID("_History3Weight");
+
+ internal static readonly int _History4Weight = Shader.PropertyToID("_History4Weight");
+ }
+
+ private enum Pass
+ {
+ VelocitySetup,
+ TileMax1,
+ TileMax2,
+ TileMaxV,
+ NeighborMax,
+ Reconstruction,
+ FrameCompression,
+ FrameBlendingChroma,
+ FrameBlendingRaw
+ }
+
+ public class ReconstructionFilter
+ {
+ private RenderTextureFormat m_VectorRTFormat = RenderTextureFormat.RGHalf;
+
+ private RenderTextureFormat m_PackedRTFormat = RenderTextureFormat.ARGB2101010;
+
+ public ReconstructionFilter()
+ {
+ CheckTextureFormatSupport();
+ }
+
+ private void CheckTextureFormatSupport()
+ {
+ if (!SystemInfo.SupportsRenderTextureFormat(m_PackedRTFormat))
+ {
+ m_PackedRTFormat = RenderTextureFormat.ARGB32;
+ }
+ }
+
+ public bool IsSupported()
+ {
+ return SystemInfo.supportsMotionVectors;
+ }
+
+ public void ProcessImage(PostProcessingContext context, CommandBuffer cb, ref MotionBlurModel.Settings settings, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material)
+ {
+ int num = (int)(5f * (float)context.height / 100f);
+ int num2 = ((num - 1) / 8 + 1) * 8;
+ float value = settings.shutterAngle / 360f;
+ cb.SetGlobalFloat(Uniforms._VelocityScale, value);
+ cb.SetGlobalFloat(Uniforms._MaxBlurRadius, num);
+ cb.SetGlobalFloat(Uniforms._RcpMaxBlurRadius, 1f / (float)num);
+ int velocityTex = Uniforms._VelocityTex;
+ cb.GetTemporaryRT(velocityTex, context.width, context.height, 0, FilterMode.Point, m_PackedRTFormat, RenderTextureReadWrite.Linear);
+ cb.Blit(null, velocityTex, material, 0);
+ int tile2RT = Uniforms._Tile2RT;
+ cb.GetTemporaryRT(tile2RT, context.width / 2, context.height / 2, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, velocityTex);
+ cb.Blit(velocityTex, tile2RT, material, 1);
+ int tile4RT = Uniforms._Tile4RT;
+ cb.GetTemporaryRT(tile4RT, context.width / 4, context.height / 4, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, tile2RT);
+ cb.Blit(tile2RT, tile4RT, material, 2);
+ cb.ReleaseTemporaryRT(tile2RT);
+ int tile8RT = Uniforms._Tile8RT;
+ cb.GetTemporaryRT(tile8RT, context.width / 8, context.height / 8, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, tile4RT);
+ cb.Blit(tile4RT, tile8RT, material, 2);
+ cb.ReleaseTemporaryRT(tile4RT);
+ Vector2 vector = Vector2.one * ((float)num2 / 8f - 1f) * -0.5f;
+ cb.SetGlobalVector(Uniforms._TileMaxOffs, vector);
+ cb.SetGlobalFloat(Uniforms._TileMaxLoop, (int)((float)num2 / 8f));
+ int tileVRT = Uniforms._TileVRT;
+ cb.GetTemporaryRT(tileVRT, context.width / num2, context.height / num2, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, tile8RT);
+ cb.Blit(tile8RT, tileVRT, material, 3);
+ cb.ReleaseTemporaryRT(tile8RT);
+ int neighborMaxTex = Uniforms._NeighborMaxTex;
+ int width = context.width / num2;
+ int height = context.height / num2;
+ cb.GetTemporaryRT(neighborMaxTex, width, height, 0, FilterMode.Point, m_VectorRTFormat, RenderTextureReadWrite.Linear);
+ cb.SetGlobalTexture(Uniforms._MainTex, tileVRT);
+ cb.Blit(tileVRT, neighborMaxTex, material, 4);
+ cb.ReleaseTemporaryRT(tileVRT);
+ cb.SetGlobalFloat(Uniforms._LoopCount, Mathf.Clamp(settings.sampleCount / 2, 1, 64));
+ cb.SetGlobalTexture(Uniforms._MainTex, source);
+ cb.Blit(source, destination, material, 5);
+ cb.ReleaseTemporaryRT(velocityTex);
+ cb.ReleaseTemporaryRT(neighborMaxTex);
+ }
+ }
+
+ public class FrameBlendingFilter
+ {
+ private struct Frame
+ {
+ public RenderTexture lumaTexture;
+
+ public RenderTexture chromaTexture;
+
+ private float m_Time;
+
+ private RenderTargetIdentifier[] m_MRT;
+
+ public float CalculateWeight(float strength, float currentTime)
+ {
+ if (Mathf.Approximately(m_Time, 0f))
+ {
+ return 0f;
+ }
+ float num = Mathf.Lerp(80f, 16f, strength);
+ return Mathf.Exp((m_Time - currentTime) * num);
+ }
+
+ public void Release()
+ {
+ if (lumaTexture != null)
+ {
+ RenderTexture.ReleaseTemporary(lumaTexture);
+ }
+ if (chromaTexture != null)
+ {
+ RenderTexture.ReleaseTemporary(chromaTexture);
+ }
+ lumaTexture = null;
+ chromaTexture = null;
+ }
+
+ public void MakeRecord(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material)
+ {
+ Release();
+ lumaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
+ chromaTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.R8, RenderTextureReadWrite.Linear);
+ lumaTexture.filterMode = FilterMode.Point;
+ chromaTexture.filterMode = FilterMode.Point;
+ if (m_MRT == null)
+ {
+ m_MRT = new RenderTargetIdentifier[2];
+ }
+ m_MRT[0] = lumaTexture;
+ m_MRT[1] = chromaTexture;
+ cb.SetGlobalTexture(Uniforms._MainTex, source);
+ cb.SetRenderTarget(m_MRT, lumaTexture);
+ cb.DrawMesh(GraphicsUtils.quad, Matrix4x4.identity, material, 0, 6);
+ m_Time = Time.time;
+ }
+
+ public void MakeRecordRaw(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, RenderTextureFormat format)
+ {
+ Release();
+ lumaTexture = RenderTexture.GetTemporary(width, height, 0, format);
+ lumaTexture.filterMode = FilterMode.Point;
+ cb.SetGlobalTexture(Uniforms._MainTex, source);
+ cb.Blit(source, lumaTexture);
+ m_Time = Time.time;
+ }
+ }
+
+ private bool m_UseCompression;
+
+ private RenderTextureFormat m_RawTextureFormat;
+
+ private Frame[] m_FrameList;
+
+ private int m_LastFrameCount;
+
+ public FrameBlendingFilter()
+ {
+ m_UseCompression = CheckSupportCompression();
+ m_RawTextureFormat = GetPreferredRenderTextureFormat();
+ m_FrameList = new Frame[4];
+ }
+
+ public void Dispose()
+ {
+ Frame[] frameList = m_FrameList;
+ foreach (Frame frame in frameList)
+ {
+ frame.Release();
+ }
+ }
+
+ public void PushFrame(CommandBuffer cb, RenderTargetIdentifier source, int width, int height, Material material)
+ {
+ int frameCount = Time.frameCount;
+ if (frameCount != m_LastFrameCount)
+ {
+ int num = frameCount % m_FrameList.Length;
+ if (m_UseCompression)
+ {
+ m_FrameList[num].MakeRecord(cb, source, width, height, material);
+ }
+ else
+ {
+ m_FrameList[num].MakeRecordRaw(cb, source, width, height, m_RawTextureFormat);
+ }
+ m_LastFrameCount = frameCount;
+ }
+ }
+
+ public void BlendFrames(CommandBuffer cb, float strength, RenderTargetIdentifier source, RenderTargetIdentifier destination, Material material)
+ {
+ float time = Time.time;
+ Frame frameRelative = GetFrameRelative(-1);
+ Frame frameRelative2 = GetFrameRelative(-2);
+ Frame frameRelative3 = GetFrameRelative(-3);
+ Frame frameRelative4 = GetFrameRelative(-4);
+ cb.SetGlobalTexture(Uniforms._History1LumaTex, frameRelative.lumaTexture);
+ cb.SetGlobalTexture(Uniforms._History2LumaTex, frameRelative2.lumaTexture);
+ cb.SetGlobalTexture(Uniforms._History3LumaTex, frameRelative3.lumaTexture);
+ cb.SetGlobalTexture(Uniforms._History4LumaTex, frameRelative4.lumaTexture);
+ cb.SetGlobalTexture(Uniforms._History1ChromaTex, frameRelative.chromaTexture);
+ cb.SetGlobalTexture(Uniforms._History2ChromaTex, frameRelative2.chromaTexture);
+ cb.SetGlobalTexture(Uniforms._History3ChromaTex, frameRelative3.chromaTexture);
+ cb.SetGlobalTexture(Uniforms._History4ChromaTex, frameRelative4.chromaTexture);
+ cb.SetGlobalFloat(Uniforms._History1Weight, frameRelative.CalculateWeight(strength, time));
+ cb.SetGlobalFloat(Uniforms._History2Weight, frameRelative2.CalculateWeight(strength, time));
+ cb.SetGlobalFloat(Uniforms._History3Weight, frameRelative3.CalculateWeight(strength, time));
+ cb.SetGlobalFloat(Uniforms._History4Weight, frameRelative4.CalculateWeight(strength, time));
+ cb.SetGlobalTexture(Uniforms._MainTex, source);
+ cb.Blit(source, destination, material, m_UseCompression ? 7 : 8);
+ }
+
+ private static bool CheckSupportCompression()
+ {
+ if (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8))
+ {
+ return SystemInfo.supportedRenderTargetCount > 1;
+ }
+ return false;
+ }
+
+ private static RenderTextureFormat GetPreferredRenderTextureFormat()
+ {
+ RenderTextureFormat[] array = new RenderTextureFormat[3]
+ {
+ RenderTextureFormat.RGB565,
+ RenderTextureFormat.ARGB1555,
+ RenderTextureFormat.ARGB4444
+ };
+ foreach (RenderTextureFormat renderTextureFormat in array)
+ {
+ if (SystemInfo.SupportsRenderTextureFormat(renderTextureFormat))
+ {
+ return renderTextureFormat;
+ }
+ }
+ return RenderTextureFormat.Default;
+ }
+
+ private Frame GetFrameRelative(int offset)
+ {
+ int num = (Time.frameCount + m_FrameList.Length + offset) % m_FrameList.Length;
+ return m_FrameList[num];
+ }
+ }
+
+ private ReconstructionFilter m_ReconstructionFilter;
+
+ private FrameBlendingFilter m_FrameBlendingFilter;
+
+ private bool m_FirstFrame = true;
+
+ public ReconstructionFilter reconstructionFilter
+ {
+ get
+ {
+ if (m_ReconstructionFilter == null)
+ {
+ m_ReconstructionFilter = new ReconstructionFilter();
+ }
+ return m_ReconstructionFilter;
+ }
+ }
+
+ public FrameBlendingFilter frameBlendingFilter
+ {
+ get
+ {
+ if (m_FrameBlendingFilter == null)
+ {
+ m_FrameBlendingFilter = new FrameBlendingFilter();
+ }
+ return m_FrameBlendingFilter;
+ }
+ }
+
+ public override bool active
+ {
+ get
+ {
+ MotionBlurModel.Settings settings = base.model.settings;
+ if (base.model.enabled && ((settings.shutterAngle > 0f && reconstructionFilter.IsSupported()) || settings.frameBlending > 0f) && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override string GetName()
+ {
+ return "Motion Blur";
+ }
+
+ public void ResetHistory()
+ {
+ if (m_FrameBlendingFilter != null)
+ {
+ m_FrameBlendingFilter.Dispose();
+ }
+ m_FrameBlendingFilter = null;
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
+ }
+
+ public override CameraEvent GetCameraEvent()
+ {
+ return CameraEvent.BeforeImageEffects;
+ }
+
+ public override void OnEnable()
+ {
+ m_FirstFrame = true;
+ }
+
+ public override void PopulateCommandBuffer(CommandBuffer cb)
+ {
+ if (m_FirstFrame)
+ {
+ m_FirstFrame = false;
+ return;
+ }
+ Material material = context.materialFactory.Get("Hidden/Post FX/Motion Blur");
+ Material mat = context.materialFactory.Get("Hidden/Post FX/Blit");
+ MotionBlurModel.Settings settings = base.model.settings;
+ RenderTextureFormat format = (context.isHdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);
+ int tempRT = Uniforms._TempRT;
+ cb.GetTemporaryRT(tempRT, context.width, context.height, 0, FilterMode.Point, format);
+ if (settings.shutterAngle > 0f && settings.frameBlending > 0f)
+ {
+ reconstructionFilter.ProcessImage(context, cb, ref settings, BuiltinRenderTextureType.CameraTarget, tempRT, material);
+ frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material);
+ frameBlendingFilter.PushFrame(cb, tempRT, context.width, context.height, material);
+ }
+ else if (settings.shutterAngle > 0f)
+ {
+ cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0);
+ reconstructionFilter.ProcessImage(context, cb, ref settings, tempRT, BuiltinRenderTextureType.CameraTarget, material);
+ }
+ else if (settings.frameBlending > 0f)
+ {
+ cb.SetGlobalTexture(Uniforms._MainTex, BuiltinRenderTextureType.CameraTarget);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, tempRT, mat, 0);
+ frameBlendingFilter.BlendFrames(cb, settings.frameBlending, tempRT, BuiltinRenderTextureType.CameraTarget, material);
+ frameBlendingFilter.PushFrame(cb, tempRT, context.width, context.height, material);
+ }
+ cb.ReleaseTemporaryRT(tempRT);
+ }
+
+ public override void OnDisable()
+ {
+ if (m_FrameBlendingFilter != null)
+ {
+ m_FrameBlendingFilter.Dispose();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurModel.cs
new file mode 100644
index 0000000..5b0a996
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/MotionBlurModel.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class MotionBlurModel : PostProcessingModel
+{
+ [Serializable]
+ public struct Settings
+ {
+ [Range(0f, 360f)]
+ [Tooltip("The angle of rotary shutter. Larger values give longer exposure.")]
+ public float shutterAngle;
+
+ [Range(4f, 32f)]
+ [Tooltip("The amount of sample points, which affects quality and performances.")]
+ public int sampleCount;
+
+ [Range(0f, 1f)]
+ [Tooltip("The strength of multiple frame blending. The opacity of preceding frames are determined from this coefficient and time differences.")]
+ public float frameBlending;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.shutterAngle = 270f;
+ result.sampleCount = 10;
+ result.frameBlending = 0f;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingBehaviour.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingBehaviour.cs
new file mode 100644
index 0000000..5f9dccd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingBehaviour.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+[ImageEffectAllowedInSceneView]
+[RequireComponent(typeof(Camera))]
+[DisallowMultipleComponent]
+[ExecuteInEditMode]
+[AddComponentMenu("Effects/Post-Processing Behaviour", -1)]
+public class PostProcessingBehaviour : MonoBehaviour
+{
+ public PostProcessingProfile profile;
+
+ public Func<Vector2, Matrix4x4> jitteredMatrixFunc;
+
+ private Dictionary<Type, KeyValuePair<CameraEvent, CommandBuffer>> m_CommandBuffers;
+
+ private List<PostProcessingComponentBase> m_Components;
+
+ private Dictionary<PostProcessingComponentBase, bool> m_ComponentStates;
+
+ private MaterialFactory m_MaterialFactory;
+
+ private RenderTextureFactory m_RenderTextureFactory;
+
+ private PostProcessingContext m_Context;
+
+ private Camera m_Camera;
+
+ private PostProcessingProfile m_PreviousProfile;
+
+ private bool m_RenderingInSceneView;
+
+ private BuiltinDebugViewsComponent m_DebugViews;
+
+ private AmbientOcclusionComponent m_AmbientOcclusion;
+
+ private ScreenSpaceReflectionComponent m_ScreenSpaceReflection;
+
+ private FogComponent m_FogComponent;
+
+ private MotionBlurComponent m_MotionBlur;
+
+ private TaaComponent m_Taa;
+
+ private EyeAdaptationComponent m_EyeAdaptation;
+
+ private DepthOfFieldComponent m_DepthOfField;
+
+ private BloomComponent m_Bloom;
+
+ private ChromaticAberrationComponent m_ChromaticAberration;
+
+ private ColorGradingComponent m_ColorGrading;
+
+ private UserLutComponent m_UserLut;
+
+ private GrainComponent m_Grain;
+
+ private VignetteComponent m_Vignette;
+
+ private DitheringComponent m_Dithering;
+
+ private FxaaComponent m_Fxaa;
+
+ private List<PostProcessingComponentBase> m_ComponentsToEnable = new List<PostProcessingComponentBase>();
+
+ private List<PostProcessingComponentBase> m_ComponentsToDisable = new List<PostProcessingComponentBase>();
+
+ private void OnEnable()
+ {
+ m_CommandBuffers = new Dictionary<Type, KeyValuePair<CameraEvent, CommandBuffer>>();
+ m_MaterialFactory = new MaterialFactory();
+ m_RenderTextureFactory = new RenderTextureFactory();
+ m_Context = new PostProcessingContext();
+ m_Components = new List<PostProcessingComponentBase>();
+ m_DebugViews = AddComponent(new BuiltinDebugViewsComponent());
+ m_AmbientOcclusion = AddComponent(new AmbientOcclusionComponent());
+ m_ScreenSpaceReflection = AddComponent(new ScreenSpaceReflectionComponent());
+ m_FogComponent = AddComponent(new FogComponent());
+ m_MotionBlur = AddComponent(new MotionBlurComponent());
+ m_Taa = AddComponent(new TaaComponent());
+ m_EyeAdaptation = AddComponent(new EyeAdaptationComponent());
+ m_DepthOfField = AddComponent(new DepthOfFieldComponent());
+ m_Bloom = AddComponent(new BloomComponent());
+ m_ChromaticAberration = AddComponent(new ChromaticAberrationComponent());
+ m_ColorGrading = AddComponent(new ColorGradingComponent());
+ m_UserLut = AddComponent(new UserLutComponent());
+ m_Grain = AddComponent(new GrainComponent());
+ m_Vignette = AddComponent(new VignetteComponent());
+ m_Dithering = AddComponent(new DitheringComponent());
+ m_Fxaa = AddComponent(new FxaaComponent());
+ m_ComponentStates = new Dictionary<PostProcessingComponentBase, bool>();
+ foreach (PostProcessingComponentBase component in m_Components)
+ {
+ m_ComponentStates.Add(component, value: false);
+ }
+ base.useGUILayout = false;
+ }
+
+ private void OnPreCull()
+ {
+ m_Camera = GetComponent<Camera>();
+ if (profile == null || m_Camera == null)
+ {
+ return;
+ }
+ PostProcessingContext postProcessingContext = m_Context.Reset();
+ postProcessingContext.profile = profile;
+ postProcessingContext.renderTextureFactory = m_RenderTextureFactory;
+ postProcessingContext.materialFactory = m_MaterialFactory;
+ postProcessingContext.camera = m_Camera;
+ m_DebugViews.Init(postProcessingContext, profile.debugViews);
+ m_AmbientOcclusion.Init(postProcessingContext, profile.ambientOcclusion);
+ m_ScreenSpaceReflection.Init(postProcessingContext, profile.screenSpaceReflection);
+ m_FogComponent.Init(postProcessingContext, profile.fog);
+ m_MotionBlur.Init(postProcessingContext, profile.motionBlur);
+ m_Taa.Init(postProcessingContext, profile.antialiasing);
+ m_EyeAdaptation.Init(postProcessingContext, profile.eyeAdaptation);
+ m_DepthOfField.Init(postProcessingContext, profile.depthOfField);
+ m_Bloom.Init(postProcessingContext, profile.bloom);
+ m_ChromaticAberration.Init(postProcessingContext, profile.chromaticAberration);
+ m_ColorGrading.Init(postProcessingContext, profile.colorGrading);
+ m_UserLut.Init(postProcessingContext, profile.userLut);
+ m_Grain.Init(postProcessingContext, profile.grain);
+ m_Vignette.Init(postProcessingContext, profile.vignette);
+ m_Dithering.Init(postProcessingContext, profile.dithering);
+ m_Fxaa.Init(postProcessingContext, profile.antialiasing);
+ if (m_PreviousProfile != profile)
+ {
+ DisableComponents();
+ m_PreviousProfile = profile;
+ }
+ CheckObservers();
+ DepthTextureMode depthTextureMode = postProcessingContext.camera.depthTextureMode;
+ foreach (PostProcessingComponentBase component in m_Components)
+ {
+ if (component.active)
+ {
+ depthTextureMode |= component.GetCameraFlags();
+ }
+ }
+ postProcessingContext.camera.depthTextureMode = depthTextureMode;
+ if (!m_RenderingInSceneView && m_Taa.active && !profile.debugViews.willInterrupt)
+ {
+ m_Taa.SetProjectionMatrix(jitteredMatrixFunc);
+ }
+ }
+
+ private void OnPreRender()
+ {
+ if (!(profile == null))
+ {
+ TryExecuteCommandBuffer(m_DebugViews);
+ TryExecuteCommandBuffer(m_AmbientOcclusion);
+ TryExecuteCommandBuffer(m_ScreenSpaceReflection);
+ TryExecuteCommandBuffer(m_FogComponent);
+ if (!m_RenderingInSceneView)
+ {
+ TryExecuteCommandBuffer(m_MotionBlur);
+ }
+ }
+ }
+
+ private void OnPostRender()
+ {
+ if (!(profile == null) && !(m_Camera == null) && !m_RenderingInSceneView && m_Taa.active && !profile.debugViews.willInterrupt)
+ {
+ m_Context.camera.ResetProjectionMatrix();
+ }
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (profile == null || m_Camera == null)
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ bool flag = false;
+ bool active = m_Fxaa.active;
+ bool flag2 = m_Taa.active && !m_RenderingInSceneView;
+ bool num = m_DepthOfField.active && !m_RenderingInSceneView;
+ Material material = m_MaterialFactory.Get("Hidden/Post FX/Uber Shader");
+ material.shaderKeywords = null;
+ RenderTexture renderTexture = source;
+ if (flag2)
+ {
+ RenderTexture renderTexture2 = m_RenderTextureFactory.Get(renderTexture);
+ m_Taa.Render(renderTexture, renderTexture2);
+ renderTexture = renderTexture2;
+ }
+ Texture texture = GraphicsUtils.whiteTexture;
+ if (m_EyeAdaptation.active)
+ {
+ flag = true;
+ texture = m_EyeAdaptation.Prepare(renderTexture, material);
+ }
+ material.SetTexture("_AutoExposure", texture);
+ if (num)
+ {
+ flag = true;
+ m_DepthOfField.Prepare(renderTexture, material, flag2, m_Taa.jitterVector, m_Taa.model.settings.taaSettings.motionBlending);
+ }
+ if (m_Bloom.active)
+ {
+ flag = true;
+ m_Bloom.Prepare(renderTexture, material, texture);
+ }
+ flag |= TryPrepareUberImageEffect(m_ChromaticAberration, material);
+ flag |= TryPrepareUberImageEffect(m_ColorGrading, material);
+ flag |= TryPrepareUberImageEffect(m_Vignette, material);
+ flag |= TryPrepareUberImageEffect(m_UserLut, material);
+ Material material2 = (active ? m_MaterialFactory.Get("Hidden/Post FX/FXAA") : null);
+ if (active)
+ {
+ material2.shaderKeywords = null;
+ TryPrepareUberImageEffect(m_Grain, material2);
+ TryPrepareUberImageEffect(m_Dithering, material2);
+ if (flag)
+ {
+ RenderTexture renderTexture3 = m_RenderTextureFactory.Get(renderTexture);
+ Graphics.Blit(renderTexture, renderTexture3, material, 0);
+ renderTexture = renderTexture3;
+ }
+ m_Fxaa.Render(renderTexture, destination);
+ }
+ else
+ {
+ flag |= TryPrepareUberImageEffect(m_Grain, material);
+ flag |= TryPrepareUberImageEffect(m_Dithering, material);
+ if (flag)
+ {
+ if (!GraphicsUtils.isLinearColorSpace)
+ {
+ material.EnableKeyword("UNITY_COLORSPACE_GAMMA");
+ }
+ Graphics.Blit(renderTexture, destination, material, 0);
+ }
+ }
+ if (!flag && !active)
+ {
+ Graphics.Blit(renderTexture, destination);
+ }
+ m_RenderTextureFactory.ReleaseAll();
+ }
+
+ private void OnGUI()
+ {
+ if (Event.current.type == EventType.Repaint && !(profile == null) && !(m_Camera == null))
+ {
+ if (m_EyeAdaptation.active && profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.EyeAdaptation))
+ {
+ m_EyeAdaptation.OnGUI();
+ }
+ else if (m_ColorGrading.active && profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.LogLut))
+ {
+ m_ColorGrading.OnGUI();
+ }
+ else if (m_UserLut.active && profile.debugViews.IsModeActive(BuiltinDebugViewsModel.Mode.UserLut))
+ {
+ m_UserLut.OnGUI();
+ }
+ }
+ }
+
+ private void OnDisable()
+ {
+ foreach (KeyValuePair<CameraEvent, CommandBuffer> value in m_CommandBuffers.Values)
+ {
+ m_Camera.RemoveCommandBuffer(value.Key, value.Value);
+ value.Value.Dispose();
+ }
+ m_CommandBuffers.Clear();
+ if (profile != null)
+ {
+ DisableComponents();
+ }
+ m_Components.Clear();
+ m_MaterialFactory.Dispose();
+ m_RenderTextureFactory.Dispose();
+ GraphicsUtils.Dispose();
+ }
+
+ public void ResetTemporalEffects()
+ {
+ m_Taa.ResetHistory();
+ m_MotionBlur.ResetHistory();
+ m_EyeAdaptation.ResetHistory();
+ }
+
+ private void CheckObservers()
+ {
+ foreach (KeyValuePair<PostProcessingComponentBase, bool> componentState in m_ComponentStates)
+ {
+ PostProcessingComponentBase key = componentState.Key;
+ bool flag = key.GetModel().enabled;
+ if (flag != componentState.Value)
+ {
+ if (flag)
+ {
+ m_ComponentsToEnable.Add(key);
+ }
+ else
+ {
+ m_ComponentsToDisable.Add(key);
+ }
+ }
+ }
+ for (int i = 0; i < m_ComponentsToDisable.Count; i++)
+ {
+ PostProcessingComponentBase postProcessingComponentBase = m_ComponentsToDisable[i];
+ m_ComponentStates[postProcessingComponentBase] = false;
+ postProcessingComponentBase.OnDisable();
+ }
+ for (int j = 0; j < m_ComponentsToEnable.Count; j++)
+ {
+ PostProcessingComponentBase postProcessingComponentBase2 = m_ComponentsToEnable[j];
+ m_ComponentStates[postProcessingComponentBase2] = true;
+ postProcessingComponentBase2.OnEnable();
+ }
+ m_ComponentsToDisable.Clear();
+ m_ComponentsToEnable.Clear();
+ }
+
+ private void DisableComponents()
+ {
+ foreach (PostProcessingComponentBase component in m_Components)
+ {
+ PostProcessingModel model = component.GetModel();
+ if (model != null && model.enabled)
+ {
+ component.OnDisable();
+ }
+ }
+ }
+
+ private CommandBuffer AddCommandBuffer<T>(CameraEvent evt, string name) where T : PostProcessingModel
+ {
+ CommandBuffer value = new CommandBuffer
+ {
+ name = name
+ };
+ KeyValuePair<CameraEvent, CommandBuffer> value2 = new KeyValuePair<CameraEvent, CommandBuffer>(evt, value);
+ m_CommandBuffers.Add(typeof(T), value2);
+ m_Camera.AddCommandBuffer(evt, value2.Value);
+ return value2.Value;
+ }
+
+ private void RemoveCommandBuffer<T>() where T : PostProcessingModel
+ {
+ Type typeFromHandle = typeof(T);
+ if (m_CommandBuffers.TryGetValue(typeFromHandle, out var value))
+ {
+ m_Camera.RemoveCommandBuffer(value.Key, value.Value);
+ m_CommandBuffers.Remove(typeFromHandle);
+ value.Value.Dispose();
+ }
+ }
+
+ private CommandBuffer GetCommandBuffer<T>(CameraEvent evt, string name) where T : PostProcessingModel
+ {
+ if (!m_CommandBuffers.TryGetValue(typeof(T), out var value))
+ {
+ return AddCommandBuffer<T>(evt, name);
+ }
+ if (value.Key != evt)
+ {
+ RemoveCommandBuffer<T>();
+ return AddCommandBuffer<T>(evt, name);
+ }
+ return value.Value;
+ }
+
+ private void TryExecuteCommandBuffer<T>(PostProcessingComponentCommandBuffer<T> component) where T : PostProcessingModel
+ {
+ if (component.active)
+ {
+ CommandBuffer commandBuffer = GetCommandBuffer<T>(component.GetCameraEvent(), component.GetName());
+ commandBuffer.Clear();
+ component.PopulateCommandBuffer(commandBuffer);
+ }
+ else
+ {
+ RemoveCommandBuffer<T>();
+ }
+ }
+
+ private bool TryPrepareUberImageEffect<T>(PostProcessingComponentRenderTexture<T> component, Material material) where T : PostProcessingModel
+ {
+ if (!component.active)
+ {
+ return false;
+ }
+ component.Prepare(material);
+ return true;
+ }
+
+ private T AddComponent<T>(T component) where T : PostProcessingComponentBase
+ {
+ m_Components.Add(component);
+ return component;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponent.cs
new file mode 100644
index 0000000..08c2ba7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponent.cs
@@ -0,0 +1,17 @@
+namespace UnityEngine.PostProcessing;
+
+public abstract class PostProcessingComponent<T> : PostProcessingComponentBase where T : PostProcessingModel
+{
+ public T model { get; internal set; }
+
+ public virtual void Init(PostProcessingContext pcontext, T pmodel)
+ {
+ context = pcontext;
+ model = pmodel;
+ }
+
+ public override PostProcessingModel GetModel()
+ {
+ return model;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentBase.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentBase.cs
new file mode 100644
index 0000000..491f371
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentBase.cs
@@ -0,0 +1,23 @@
+namespace UnityEngine.PostProcessing;
+
+public abstract class PostProcessingComponentBase
+{
+ public PostProcessingContext context;
+
+ public abstract bool active { get; }
+
+ public virtual DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.None;
+ }
+
+ public virtual void OnEnable()
+ {
+ }
+
+ public virtual void OnDisable()
+ {
+ }
+
+ public abstract PostProcessingModel GetModel();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentCommandBuffer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentCommandBuffer.cs
new file mode 100644
index 0000000..a8a9408
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentCommandBuffer.cs
@@ -0,0 +1,12 @@
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public abstract class PostProcessingComponentCommandBuffer<T> : PostProcessingComponent<T> where T : PostProcessingModel
+{
+ public abstract CameraEvent GetCameraEvent();
+
+ public abstract string GetName();
+
+ public abstract void PopulateCommandBuffer(CommandBuffer cb);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentRenderTexture.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentRenderTexture.cs
new file mode 100644
index 0000000..8284bb2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingComponentRenderTexture.cs
@@ -0,0 +1,8 @@
+namespace UnityEngine.PostProcessing;
+
+public abstract class PostProcessingComponentRenderTexture<T> : PostProcessingComponent<T> where T : PostProcessingModel
+{
+ public virtual void Prepare(Material material)
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingContext.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingContext.cs
new file mode 100644
index 0000000..ab810a1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingContext.cs
@@ -0,0 +1,39 @@
+namespace UnityEngine.PostProcessing;
+
+public class PostProcessingContext
+{
+ public PostProcessingProfile profile;
+
+ public Camera camera;
+
+ public MaterialFactory materialFactory;
+
+ public RenderTextureFactory renderTextureFactory;
+
+ public bool interrupted { get; private set; }
+
+ public bool isGBufferAvailable => camera.actualRenderingPath == RenderingPath.DeferredShading;
+
+ public bool isHdr => camera.allowHDR;
+
+ public int width => camera.pixelWidth;
+
+ public int height => camera.pixelHeight;
+
+ public Rect viewport => camera.rect;
+
+ public void Interrupt()
+ {
+ interrupted = true;
+ }
+
+ public PostProcessingContext Reset()
+ {
+ profile = null;
+ camera = null;
+ materialFactory = null;
+ renderTextureFactory = null;
+ interrupted = false;
+ return this;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingModel.cs
new file mode 100644
index 0000000..986b42b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingModel.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public abstract class PostProcessingModel
+{
+ [SerializeField]
+ [GetSet("enabled")]
+ private bool m_Enabled;
+
+ public bool enabled
+ {
+ get
+ {
+ return m_Enabled;
+ }
+ set
+ {
+ m_Enabled = value;
+ if (value)
+ {
+ OnValidate();
+ }
+ }
+ }
+
+ public abstract void Reset();
+
+ public virtual void OnValidate()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingProfile.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingProfile.cs
new file mode 100644
index 0000000..3c847b3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/PostProcessingProfile.cs
@@ -0,0 +1,34 @@
+namespace UnityEngine.PostProcessing;
+
+public class PostProcessingProfile : ScriptableObject
+{
+ public BuiltinDebugViewsModel debugViews = new BuiltinDebugViewsModel();
+
+ public FogModel fog = new FogModel();
+
+ public AntialiasingModel antialiasing = new AntialiasingModel();
+
+ public AmbientOcclusionModel ambientOcclusion = new AmbientOcclusionModel();
+
+ public ScreenSpaceReflectionModel screenSpaceReflection = new ScreenSpaceReflectionModel();
+
+ public DepthOfFieldModel depthOfField = new DepthOfFieldModel();
+
+ public MotionBlurModel motionBlur = new MotionBlurModel();
+
+ public EyeAdaptationModel eyeAdaptation = new EyeAdaptationModel();
+
+ public BloomModel bloom = new BloomModel();
+
+ public ColorGradingModel colorGrading = new ColorGradingModel();
+
+ public UserLutModel userLut = new UserLutModel();
+
+ public ChromaticAberrationModel chromaticAberration = new ChromaticAberrationModel();
+
+ public GrainModel grain = new GrainModel();
+
+ public VignetteModel vignette = new VignetteModel();
+
+ public DitheringModel dithering = new DitheringModel();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/RenderTextureFactory.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/RenderTextureFactory.cs
new file mode 100644
index 0000000..51d9f15
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/RenderTextureFactory.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class RenderTextureFactory : IDisposable
+{
+ private HashSet<RenderTexture> m_TemporaryRTs;
+
+ public RenderTextureFactory()
+ {
+ m_TemporaryRTs = new HashSet<RenderTexture>();
+ }
+
+ public RenderTexture Get(RenderTexture baseRenderTexture)
+ {
+ return Get(baseRenderTexture.width, baseRenderTexture.height, baseRenderTexture.depth, baseRenderTexture.format, (!baseRenderTexture.sRGB) ? RenderTextureReadWrite.Linear : RenderTextureReadWrite.sRGB, baseRenderTexture.filterMode, baseRenderTexture.wrapMode);
+ }
+
+ public RenderTexture Get(int width, int height, int depthBuffer = 0, RenderTextureFormat format = RenderTextureFormat.ARGBHalf, RenderTextureReadWrite rw = RenderTextureReadWrite.Default, FilterMode filterMode = FilterMode.Bilinear, TextureWrapMode wrapMode = TextureWrapMode.Clamp, string name = "FactoryTempTexture")
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, depthBuffer, format, rw);
+ temporary.filterMode = filterMode;
+ temporary.wrapMode = wrapMode;
+ temporary.name = name;
+ m_TemporaryRTs.Add(temporary);
+ return temporary;
+ }
+
+ public void Release(RenderTexture rt)
+ {
+ if (!(rt == null))
+ {
+ if (!m_TemporaryRTs.Contains(rt))
+ {
+ throw new ArgumentException($"Attempting to remove a RenderTexture that was not allocated: {rt}");
+ }
+ m_TemporaryRTs.Remove(rt);
+ RenderTexture.ReleaseTemporary(rt);
+ }
+ }
+
+ public void ReleaseAll()
+ {
+ HashSet<RenderTexture>.Enumerator enumerator = m_TemporaryRTs.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ RenderTexture.ReleaseTemporary(enumerator.Current);
+ }
+ m_TemporaryRTs.Clear();
+ }
+
+ public void Dispose()
+ {
+ ReleaseAll();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionComponent.cs
new file mode 100644
index 0000000..e94b2ac
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionComponent.cs
@@ -0,0 +1,227 @@
+using System;
+using UnityEngine.Rendering;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class ScreenSpaceReflectionComponent : PostProcessingComponentCommandBuffer<ScreenSpaceReflectionModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _RayStepSize = Shader.PropertyToID("_RayStepSize");
+
+ internal static readonly int _AdditiveReflection = Shader.PropertyToID("_AdditiveReflection");
+
+ internal static readonly int _BilateralUpsampling = Shader.PropertyToID("_BilateralUpsampling");
+
+ internal static readonly int _TreatBackfaceHitAsMiss = Shader.PropertyToID("_TreatBackfaceHitAsMiss");
+
+ internal static readonly int _AllowBackwardsRays = Shader.PropertyToID("_AllowBackwardsRays");
+
+ internal static readonly int _TraceBehindObjects = Shader.PropertyToID("_TraceBehindObjects");
+
+ internal static readonly int _MaxSteps = Shader.PropertyToID("_MaxSteps");
+
+ internal static readonly int _FullResolutionFiltering = Shader.PropertyToID("_FullResolutionFiltering");
+
+ internal static readonly int _HalfResolution = Shader.PropertyToID("_HalfResolution");
+
+ internal static readonly int _HighlightSuppression = Shader.PropertyToID("_HighlightSuppression");
+
+ internal static readonly int _PixelsPerMeterAtOneMeter = Shader.PropertyToID("_PixelsPerMeterAtOneMeter");
+
+ internal static readonly int _ScreenEdgeFading = Shader.PropertyToID("_ScreenEdgeFading");
+
+ internal static readonly int _ReflectionBlur = Shader.PropertyToID("_ReflectionBlur");
+
+ internal static readonly int _MaxRayTraceDistance = Shader.PropertyToID("_MaxRayTraceDistance");
+
+ internal static readonly int _FadeDistance = Shader.PropertyToID("_FadeDistance");
+
+ internal static readonly int _LayerThickness = Shader.PropertyToID("_LayerThickness");
+
+ internal static readonly int _SSRMultiplier = Shader.PropertyToID("_SSRMultiplier");
+
+ internal static readonly int _FresnelFade = Shader.PropertyToID("_FresnelFade");
+
+ internal static readonly int _FresnelFadePower = Shader.PropertyToID("_FresnelFadePower");
+
+ internal static readonly int _ReflectionBufferSize = Shader.PropertyToID("_ReflectionBufferSize");
+
+ internal static readonly int _ScreenSize = Shader.PropertyToID("_ScreenSize");
+
+ internal static readonly int _InvScreenSize = Shader.PropertyToID("_InvScreenSize");
+
+ internal static readonly int _ProjInfo = Shader.PropertyToID("_ProjInfo");
+
+ internal static readonly int _CameraClipInfo = Shader.PropertyToID("_CameraClipInfo");
+
+ internal static readonly int _ProjectToPixelMatrix = Shader.PropertyToID("_ProjectToPixelMatrix");
+
+ internal static readonly int _WorldToCameraMatrix = Shader.PropertyToID("_WorldToCameraMatrix");
+
+ internal static readonly int _CameraToWorldMatrix = Shader.PropertyToID("_CameraToWorldMatrix");
+
+ internal static readonly int _Axis = Shader.PropertyToID("_Axis");
+
+ internal static readonly int _CurrentMipLevel = Shader.PropertyToID("_CurrentMipLevel");
+
+ internal static readonly int _NormalAndRoughnessTexture = Shader.PropertyToID("_NormalAndRoughnessTexture");
+
+ internal static readonly int _HitPointTexture = Shader.PropertyToID("_HitPointTexture");
+
+ internal static readonly int _BlurTexture = Shader.PropertyToID("_BlurTexture");
+
+ internal static readonly int _FilteredReflections = Shader.PropertyToID("_FilteredReflections");
+
+ internal static readonly int _FinalReflectionTexture = Shader.PropertyToID("_FinalReflectionTexture");
+
+ internal static readonly int _TempTexture = Shader.PropertyToID("_TempTexture");
+ }
+
+ private enum PassIndex
+ {
+ RayTraceStep,
+ CompositeFinal,
+ Blur,
+ CompositeSSR,
+ MinMipGeneration,
+ HitPointToReflections,
+ BilateralKeyPack,
+ BlitDepthAsCSZ,
+ PoissonBlur
+ }
+
+ private bool k_HighlightSuppression;
+
+ private bool k_TraceBehindObjects = true;
+
+ private bool k_TreatBackfaceHitAsMiss;
+
+ private bool k_BilateralUpsample = true;
+
+ private readonly int[] m_ReflectionTextures = new int[5];
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && context.isGBufferAvailable)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.Depth;
+ }
+
+ public override void OnEnable()
+ {
+ m_ReflectionTextures[0] = Shader.PropertyToID("_ReflectionTexture0");
+ m_ReflectionTextures[1] = Shader.PropertyToID("_ReflectionTexture1");
+ m_ReflectionTextures[2] = Shader.PropertyToID("_ReflectionTexture2");
+ m_ReflectionTextures[3] = Shader.PropertyToID("_ReflectionTexture3");
+ m_ReflectionTextures[4] = Shader.PropertyToID("_ReflectionTexture4");
+ }
+
+ public override string GetName()
+ {
+ return "Screen Space Reflection";
+ }
+
+ public override CameraEvent GetCameraEvent()
+ {
+ return CameraEvent.AfterFinalPass;
+ }
+
+ public override void PopulateCommandBuffer(CommandBuffer cb)
+ {
+ ScreenSpaceReflectionModel.Settings settings = base.model.settings;
+ Camera camera = context.camera;
+ int num = ((settings.reflection.reflectionQuality == ScreenSpaceReflectionModel.SSRResolution.High) ? 1 : 2);
+ int num2 = context.width / num;
+ int num3 = context.height / num;
+ float num4 = context.width;
+ float num5 = context.height;
+ float num6 = num4 / 2f;
+ float num7 = num5 / 2f;
+ Material material = context.materialFactory.Get("Hidden/Post FX/Screen Space Reflection");
+ material.SetInt(Uniforms._RayStepSize, settings.reflection.stepSize);
+ material.SetInt(Uniforms._AdditiveReflection, (settings.reflection.blendType == ScreenSpaceReflectionModel.SSRReflectionBlendType.Additive) ? 1 : 0);
+ material.SetInt(Uniforms._BilateralUpsampling, k_BilateralUpsample ? 1 : 0);
+ material.SetInt(Uniforms._TreatBackfaceHitAsMiss, k_TreatBackfaceHitAsMiss ? 1 : 0);
+ material.SetInt(Uniforms._AllowBackwardsRays, settings.reflection.reflectBackfaces ? 1 : 0);
+ material.SetInt(Uniforms._TraceBehindObjects, k_TraceBehindObjects ? 1 : 0);
+ material.SetInt(Uniforms._MaxSteps, settings.reflection.iterationCount);
+ material.SetInt(Uniforms._FullResolutionFiltering, 0);
+ material.SetInt(Uniforms._HalfResolution, (settings.reflection.reflectionQuality != 0) ? 1 : 0);
+ material.SetInt(Uniforms._HighlightSuppression, k_HighlightSuppression ? 1 : 0);
+ float value = num4 / (-2f * Mathf.Tan(camera.fieldOfView / 180f * (float)Math.PI * 0.5f));
+ material.SetFloat(Uniforms._PixelsPerMeterAtOneMeter, value);
+ material.SetFloat(Uniforms._ScreenEdgeFading, settings.screenEdgeMask.intensity);
+ material.SetFloat(Uniforms._ReflectionBlur, settings.reflection.reflectionBlur);
+ material.SetFloat(Uniforms._MaxRayTraceDistance, settings.reflection.maxDistance);
+ material.SetFloat(Uniforms._FadeDistance, settings.intensity.fadeDistance);
+ material.SetFloat(Uniforms._LayerThickness, settings.reflection.widthModifier);
+ material.SetFloat(Uniforms._SSRMultiplier, settings.intensity.reflectionMultiplier);
+ material.SetFloat(Uniforms._FresnelFade, settings.intensity.fresnelFade);
+ material.SetFloat(Uniforms._FresnelFadePower, settings.intensity.fresnelFadePower);
+ Matrix4x4 projectionMatrix = camera.projectionMatrix;
+ Vector4 value2 = new Vector4(-2f / (num4 * projectionMatrix[0]), -2f / (num5 * projectionMatrix[5]), (1f - projectionMatrix[2]) / projectionMatrix[0], (1f + projectionMatrix[6]) / projectionMatrix[5]);
+ Vector3 vector = (float.IsPositiveInfinity(camera.farClipPlane) ? new Vector3(camera.nearClipPlane, -1f, 1f) : new Vector3(camera.nearClipPlane * camera.farClipPlane, camera.nearClipPlane - camera.farClipPlane, camera.farClipPlane));
+ material.SetVector(Uniforms._ReflectionBufferSize, new Vector2(num2, num3));
+ material.SetVector(Uniforms._ScreenSize, new Vector2(num4, num5));
+ material.SetVector(Uniforms._InvScreenSize, new Vector2(1f / num4, 1f / num5));
+ material.SetVector(Uniforms._ProjInfo, value2);
+ material.SetVector(Uniforms._CameraClipInfo, vector);
+ Matrix4x4 matrix4x = default(Matrix4x4);
+ matrix4x.SetRow(0, new Vector4(num6, 0f, 0f, num6));
+ matrix4x.SetRow(1, new Vector4(0f, num7, 0f, num7));
+ matrix4x.SetRow(2, new Vector4(0f, 0f, 1f, 0f));
+ matrix4x.SetRow(3, new Vector4(0f, 0f, 0f, 1f));
+ Matrix4x4 value3 = matrix4x * projectionMatrix;
+ material.SetMatrix(Uniforms._ProjectToPixelMatrix, value3);
+ material.SetMatrix(Uniforms._WorldToCameraMatrix, camera.worldToCameraMatrix);
+ material.SetMatrix(Uniforms._CameraToWorldMatrix, camera.worldToCameraMatrix.inverse);
+ RenderTextureFormat format = (context.isHdr ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32);
+ int normalAndRoughnessTexture = Uniforms._NormalAndRoughnessTexture;
+ int hitPointTexture = Uniforms._HitPointTexture;
+ int blurTexture = Uniforms._BlurTexture;
+ int filteredReflections = Uniforms._FilteredReflections;
+ int finalReflectionTexture = Uniforms._FinalReflectionTexture;
+ int tempTexture = Uniforms._TempTexture;
+ cb.GetTemporaryRT(normalAndRoughnessTexture, -1, -1, 0, FilterMode.Point, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
+ cb.GetTemporaryRT(hitPointTexture, num2, num3, 0, FilterMode.Bilinear, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
+ for (int i = 0; i < 5; i++)
+ {
+ cb.GetTemporaryRT(m_ReflectionTextures[i], num2 >> i, num3 >> i, 0, FilterMode.Bilinear, format);
+ }
+ cb.GetTemporaryRT(filteredReflections, num2, num3, 0, (!k_BilateralUpsample) ? FilterMode.Bilinear : FilterMode.Point, format);
+ cb.GetTemporaryRT(finalReflectionTexture, num2, num3, 0, FilterMode.Point, format);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, normalAndRoughnessTexture, material, 6);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, hitPointTexture, material, 0);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, filteredReflections, material, 5);
+ cb.Blit(filteredReflections, m_ReflectionTextures[0], material, 8);
+ for (int j = 1; j < 5; j++)
+ {
+ int num8 = m_ReflectionTextures[j - 1];
+ int num9 = j;
+ cb.GetTemporaryRT(blurTexture, num2 >> num9, num3 >> num9, 0, FilterMode.Bilinear, format);
+ cb.SetGlobalVector(Uniforms._Axis, new Vector4(1f, 0f, 0f, 0f));
+ cb.SetGlobalFloat(Uniforms._CurrentMipLevel, (float)j - 1f);
+ cb.Blit(num8, blurTexture, material, 2);
+ cb.SetGlobalVector(Uniforms._Axis, new Vector4(0f, 1f, 0f, 0f));
+ num8 = m_ReflectionTextures[j];
+ cb.Blit(blurTexture, num8, material, 2);
+ cb.ReleaseTemporaryRT(blurTexture);
+ }
+ cb.Blit(m_ReflectionTextures[0], finalReflectionTexture, material, 3);
+ cb.GetTemporaryRT(tempTexture, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear, format);
+ cb.Blit(BuiltinRenderTextureType.CameraTarget, tempTexture, material, 1);
+ cb.Blit(tempTexture, BuiltinRenderTextureType.CameraTarget);
+ cb.ReleaseTemporaryRT(tempTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionModel.cs
new file mode 100644
index 0000000..2552044
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/ScreenSpaceReflectionModel.cs
@@ -0,0 +1,141 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class ScreenSpaceReflectionModel : PostProcessingModel
+{
+ public enum SSRResolution
+ {
+ High = 0,
+ Low = 2
+ }
+
+ public enum SSRReflectionBlendType
+ {
+ PhysicallyBased,
+ Additive
+ }
+
+ [Serializable]
+ public struct IntensitySettings
+ {
+ [Tooltip("Nonphysical multiplier for the SSR reflections. 1.0 is physically based.")]
+ [Range(0f, 2f)]
+ public float reflectionMultiplier;
+
+ [Tooltip("How far away from the maxDistance to begin fading SSR.")]
+ [Range(0f, 1000f)]
+ public float fadeDistance;
+
+ [Tooltip("Amplify Fresnel fade out. Increase if floor reflections look good close to the surface and bad farther 'under' the floor.")]
+ [Range(0f, 1f)]
+ public float fresnelFade;
+
+ [Tooltip("Higher values correspond to a faster Fresnel fade as the reflection changes from the grazing angle.")]
+ [Range(0.1f, 10f)]
+ public float fresnelFadePower;
+ }
+
+ [Serializable]
+ public struct ReflectionSettings
+ {
+ [Tooltip("How the reflections are blended into the render.")]
+ public SSRReflectionBlendType blendType;
+
+ [Tooltip("Half resolution SSRR is much faster, but less accurate.")]
+ public SSRResolution reflectionQuality;
+
+ [Tooltip("Maximum reflection distance in world units.")]
+ [Range(0.1f, 300f)]
+ public float maxDistance;
+
+ [Tooltip("Max raytracing length.")]
+ [Range(16f, 1024f)]
+ public int iterationCount;
+
+ [Tooltip("Log base 2 of ray tracing coarse step size. Higher traces farther, lower gives better quality silhouettes.")]
+ [Range(1f, 16f)]
+ public int stepSize;
+
+ [Tooltip("Typical thickness of columns, walls, furniture, and other objects that reflection rays might pass behind.")]
+ [Range(0.01f, 10f)]
+ public float widthModifier;
+
+ [Tooltip("Blurriness of reflections.")]
+ [Range(0.1f, 8f)]
+ public float reflectionBlur;
+
+ [Tooltip("Disable for a performance gain in scenes where most glossy objects are horizontal, like floors, water, and tables. Leave on for scenes with glossy vertical objects.")]
+ public bool reflectBackfaces;
+ }
+
+ [Serializable]
+ public struct ScreenEdgeMask
+ {
+ [Tooltip("Higher = fade out SSRR near the edge of the screen so that reflections don't pop under camera motion.")]
+ [Range(0f, 1f)]
+ public float intensity;
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ public ReflectionSettings reflection;
+
+ public IntensitySettings intensity;
+
+ public ScreenEdgeMask screenEdgeMask;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.reflection = new ReflectionSettings
+ {
+ blendType = SSRReflectionBlendType.PhysicallyBased,
+ reflectionQuality = SSRResolution.Low,
+ maxDistance = 100f,
+ iterationCount = 256,
+ stepSize = 3,
+ widthModifier = 0.5f,
+ reflectionBlur = 1f,
+ reflectBackfaces = false
+ };
+ result.intensity = new IntensitySettings
+ {
+ reflectionMultiplier = 1f,
+ fadeDistance = 100f,
+ fresnelFade = 1f,
+ fresnelFadePower = 1f
+ };
+ result.screenEdgeMask = new ScreenEdgeMask
+ {
+ intensity = 0.03f
+ };
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TaaComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TaaComponent.cs
new file mode 100644
index 0000000..d02e1a9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TaaComponent.cs
@@ -0,0 +1,184 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+public sealed class TaaComponent : PostProcessingComponentRenderTexture<AntialiasingModel>
+{
+ private static class Uniforms
+ {
+ internal static int _Jitter = Shader.PropertyToID("_Jitter");
+
+ internal static int _SharpenParameters = Shader.PropertyToID("_SharpenParameters");
+
+ internal static int _FinalBlendParameters = Shader.PropertyToID("_FinalBlendParameters");
+
+ internal static int _HistoryTex = Shader.PropertyToID("_HistoryTex");
+
+ internal static int _MainTex = Shader.PropertyToID("_MainTex");
+ }
+
+ private const string k_ShaderString = "Hidden/Post FX/Temporal Anti-aliasing";
+
+ private const int k_SampleCount = 8;
+
+ private readonly RenderBuffer[] m_MRT = new RenderBuffer[2];
+
+ private int m_SampleIndex;
+
+ private bool m_ResetHistory = true;
+
+ private RenderTexture m_HistoryTexture;
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled && base.model.settings.method == AntialiasingModel.Method.Taa && SystemInfo.supportsMotionVectors && SystemInfo.supportedRenderTargetCount >= 2)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public Vector2 jitterVector { get; private set; }
+
+ public override DepthTextureMode GetCameraFlags()
+ {
+ return DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
+ }
+
+ public void ResetHistory()
+ {
+ m_ResetHistory = true;
+ }
+
+ public void SetProjectionMatrix(Func<Vector2, Matrix4x4> jitteredFunc)
+ {
+ AntialiasingModel.TaaSettings taaSettings = base.model.settings.taaSettings;
+ Vector2 vector = GenerateRandomOffset();
+ vector *= taaSettings.jitterSpread;
+ context.camera.nonJitteredProjectionMatrix = context.camera.projectionMatrix;
+ if (jitteredFunc != null)
+ {
+ context.camera.projectionMatrix = jitteredFunc(vector);
+ }
+ else
+ {
+ context.camera.projectionMatrix = (context.camera.orthographic ? GetOrthographicProjectionMatrix(vector) : GetPerspectiveProjectionMatrix(vector));
+ }
+ context.camera.useJitteredProjectionMatrixForTransparentRendering = false;
+ vector.x /= context.width;
+ vector.y /= context.height;
+ context.materialFactory.Get("Hidden/Post FX/Temporal Anti-aliasing").SetVector(Uniforms._Jitter, vector);
+ jitterVector = vector;
+ }
+
+ public void Render(RenderTexture source, RenderTexture destination)
+ {
+ Material material = context.materialFactory.Get("Hidden/Post FX/Temporal Anti-aliasing");
+ material.shaderKeywords = null;
+ AntialiasingModel.TaaSettings taaSettings = base.model.settings.taaSettings;
+ if (m_ResetHistory || m_HistoryTexture == null || m_HistoryTexture.width != source.width || m_HistoryTexture.height != source.height)
+ {
+ if ((bool)m_HistoryTexture)
+ {
+ RenderTexture.ReleaseTemporary(m_HistoryTexture);
+ }
+ m_HistoryTexture = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
+ m_HistoryTexture.name = "TAA History";
+ Graphics.Blit(source, m_HistoryTexture, material, 2);
+ }
+ material.SetVector(Uniforms._SharpenParameters, new Vector4(taaSettings.sharpen, 0f, 0f, 0f));
+ material.SetVector(Uniforms._FinalBlendParameters, new Vector4(taaSettings.stationaryBlending, taaSettings.motionBlending, 6000f, 0f));
+ material.SetTexture(Uniforms._MainTex, source);
+ material.SetTexture(Uniforms._HistoryTex, m_HistoryTexture);
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
+ temporary.name = "TAA History";
+ m_MRT[0] = destination.colorBuffer;
+ m_MRT[1] = temporary.colorBuffer;
+ Graphics.SetRenderTarget(m_MRT, source.depthBuffer);
+ GraphicsUtils.Blit(material, context.camera.orthographic ? 1 : 0);
+ RenderTexture.ReleaseTemporary(m_HistoryTexture);
+ m_HistoryTexture = temporary;
+ m_ResetHistory = false;
+ }
+
+ private float GetHaltonValue(int index, int radix)
+ {
+ float num = 0f;
+ float num2 = 1f / (float)radix;
+ while (index > 0)
+ {
+ num += (float)(index % radix) * num2;
+ index /= radix;
+ num2 /= (float)radix;
+ }
+ return num;
+ }
+
+ private Vector2 GenerateRandomOffset()
+ {
+ Vector2 result = new Vector2(GetHaltonValue(m_SampleIndex & 0x3FF, 2), GetHaltonValue(m_SampleIndex & 0x3FF, 3));
+ if (++m_SampleIndex >= 8)
+ {
+ m_SampleIndex = 0;
+ }
+ return result;
+ }
+
+ private Matrix4x4 GetPerspectiveProjectionMatrix(Vector2 offset)
+ {
+ float num = Mathf.Tan((float)Math.PI / 360f * context.camera.fieldOfView);
+ float num2 = num * context.camera.aspect;
+ offset.x *= num2 / (0.5f * (float)context.width);
+ offset.y *= num / (0.5f * (float)context.height);
+ float num3 = (offset.x - num2) * context.camera.nearClipPlane;
+ float num4 = (offset.x + num2) * context.camera.nearClipPlane;
+ float num5 = (offset.y + num) * context.camera.nearClipPlane;
+ float num6 = (offset.y - num) * context.camera.nearClipPlane;
+ Matrix4x4 result = default(Matrix4x4);
+ result[0, 0] = 2f * context.camera.nearClipPlane / (num4 - num3);
+ result[0, 1] = 0f;
+ result[0, 2] = (num4 + num3) / (num4 - num3);
+ result[0, 3] = 0f;
+ result[1, 0] = 0f;
+ result[1, 1] = 2f * context.camera.nearClipPlane / (num5 - num6);
+ result[1, 2] = (num5 + num6) / (num5 - num6);
+ result[1, 3] = 0f;
+ result[2, 0] = 0f;
+ result[2, 1] = 0f;
+ result[2, 2] = (0f - (context.camera.farClipPlane + context.camera.nearClipPlane)) / (context.camera.farClipPlane - context.camera.nearClipPlane);
+ result[2, 3] = (0f - 2f * context.camera.farClipPlane * context.camera.nearClipPlane) / (context.camera.farClipPlane - context.camera.nearClipPlane);
+ result[3, 0] = 0f;
+ result[3, 1] = 0f;
+ result[3, 2] = -1f;
+ result[3, 3] = 0f;
+ return result;
+ }
+
+ private Matrix4x4 GetOrthographicProjectionMatrix(Vector2 offset)
+ {
+ float orthographicSize = context.camera.orthographicSize;
+ float num = orthographicSize * context.camera.aspect;
+ offset.x *= num / (0.5f * (float)context.width);
+ offset.y *= orthographicSize / (0.5f * (float)context.height);
+ float left = offset.x - num;
+ float right = offset.x + num;
+ float top = offset.y + orthographicSize;
+ float bottom = offset.y - orthographicSize;
+ return Matrix4x4.Ortho(left, right, bottom, top, context.camera.nearClipPlane, context.camera.farClipPlane);
+ }
+
+ public override void OnDisable()
+ {
+ if (m_HistoryTexture != null)
+ {
+ RenderTexture.ReleaseTemporary(m_HistoryTexture);
+ }
+ m_HistoryTexture = null;
+ m_SampleIndex = 0;
+ ResetHistory();
+ context.camera.useJitteredProjectionMatrixForTransparentRendering = true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballAttribute.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballAttribute.cs
new file mode 100644
index 0000000..0f37d97
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballAttribute.cs
@@ -0,0 +1,11 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class TrackballAttribute : PropertyAttribute
+{
+ public readonly string method;
+
+ public TrackballAttribute(string method)
+ {
+ this.method = method;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballGroupAttribute.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballGroupAttribute.cs
new file mode 100644
index 0000000..c64ea0e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/TrackballGroupAttribute.cs
@@ -0,0 +1,5 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class TrackballGroupAttribute : PropertyAttribute
+{
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutComponent.cs
new file mode 100644
index 0000000..69399bf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutComponent.cs
@@ -0,0 +1,38 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class UserLutComponent : PostProcessingComponentRenderTexture<UserLutModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _UserLut = Shader.PropertyToID("_UserLut");
+
+ internal static readonly int _UserLut_Params = Shader.PropertyToID("_UserLut_Params");
+ }
+
+ public override bool active
+ {
+ get
+ {
+ UserLutModel.Settings settings = base.model.settings;
+ if (base.model.enabled && settings.lut != null && settings.contribution > 0f && settings.lut.height == (int)Mathf.Sqrt(settings.lut.width))
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ UserLutModel.Settings settings = base.model.settings;
+ uberMaterial.EnableKeyword("USER_LUT");
+ uberMaterial.SetTexture(Uniforms._UserLut, settings.lut);
+ uberMaterial.SetVector(Uniforms._UserLut_Params, new Vector4(1f / (float)settings.lut.width, 1f / (float)settings.lut.height, (float)settings.lut.height - 1f, settings.contribution));
+ }
+
+ public void OnGUI()
+ {
+ UserLutModel.Settings settings = base.model.settings;
+ GUI.DrawTexture(new Rect(context.viewport.x * (float)Screen.width + 8f, 8f, settings.lut.width, settings.lut.height), settings.lut);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutModel.cs
new file mode 100644
index 0000000..8cab02f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/UserLutModel.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class UserLutModel : PostProcessingModel
+{
+ [Serializable]
+ public struct Settings
+ {
+ [Tooltip("Custom lookup texture (strip format, e.g. 256x16).")]
+ public Texture2D lut;
+
+ [Range(0f, 1f)]
+ [Tooltip("Blending factor.")]
+ public float contribution;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.lut = null;
+ result.contribution = 1f;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteComponent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteComponent.cs
new file mode 100644
index 0000000..b1c4b8f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteComponent.cs
@@ -0,0 +1,48 @@
+namespace UnityEngine.PostProcessing;
+
+public sealed class VignetteComponent : PostProcessingComponentRenderTexture<VignetteModel>
+{
+ private static class Uniforms
+ {
+ internal static readonly int _Vignette_Color = Shader.PropertyToID("_Vignette_Color");
+
+ internal static readonly int _Vignette_Center = Shader.PropertyToID("_Vignette_Center");
+
+ internal static readonly int _Vignette_Settings = Shader.PropertyToID("_Vignette_Settings");
+
+ internal static readonly int _Vignette_Mask = Shader.PropertyToID("_Vignette_Mask");
+
+ internal static readonly int _Vignette_Opacity = Shader.PropertyToID("_Vignette_Opacity");
+ }
+
+ public override bool active
+ {
+ get
+ {
+ if (base.model.enabled)
+ {
+ return !context.interrupted;
+ }
+ return false;
+ }
+ }
+
+ public override void Prepare(Material uberMaterial)
+ {
+ VignetteModel.Settings settings = base.model.settings;
+ uberMaterial.SetColor(Uniforms._Vignette_Color, settings.color);
+ if (settings.mode == VignetteModel.Mode.Classic)
+ {
+ uberMaterial.SetVector(Uniforms._Vignette_Center, settings.center);
+ uberMaterial.EnableKeyword("VIGNETTE_CLASSIC");
+ float z = (1f - settings.roundness) * 6f + settings.roundness;
+ uberMaterial.SetVector(Uniforms._Vignette_Settings, new Vector4(settings.intensity * 3f, settings.smoothness * 5f, z, settings.rounded ? 1f : 0f));
+ }
+ else if (settings.mode == VignetteModel.Mode.Masked && settings.mask != null && settings.opacity > 0f)
+ {
+ uberMaterial.EnableKeyword("VIGNETTE_MASKED");
+ uberMaterial.SetTexture(Uniforms._Vignette_Mask, settings.mask);
+ uberMaterial.SetFloat(Uniforms._Vignette_Opacity, settings.opacity);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteModel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteModel.cs
new file mode 100644
index 0000000..963ce2d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/UnityEngine.PostProcessing/VignetteModel.cs
@@ -0,0 +1,87 @@
+using System;
+
+namespace UnityEngine.PostProcessing;
+
+[Serializable]
+public class VignetteModel : PostProcessingModel
+{
+ public enum Mode
+ {
+ Classic,
+ Masked
+ }
+
+ [Serializable]
+ public struct Settings
+ {
+ [Tooltip("Use the \"Classic\" mode for parametric controls. Use the \"Masked\" mode to use your own texture mask.")]
+ public Mode mode;
+
+ [ColorUsage(false)]
+ [Tooltip("Vignette color. Use the alpha channel for transparency.")]
+ public Color color;
+
+ [Tooltip("Sets the vignette center point (screen center is [0.5,0.5]).")]
+ public Vector2 center;
+
+ [Range(0f, 1f)]
+ [Tooltip("Amount of vignetting on screen.")]
+ public float intensity;
+
+ [Range(0.01f, 1f)]
+ [Tooltip("Smoothness of the vignette borders.")]
+ public float smoothness;
+
+ [Range(0f, 1f)]
+ [Tooltip("Lower values will make a square-ish vignette.")]
+ public float roundness;
+
+ [Tooltip("A black and white mask to use as a vignette.")]
+ public Texture mask;
+
+ [Range(0f, 1f)]
+ [Tooltip("Mask opacity.")]
+ public float opacity;
+
+ [Tooltip("Should the vignette be perfectly round or be dependent on the current aspect ratio?")]
+ public bool rounded;
+
+ public static Settings defaultSettings
+ {
+ get
+ {
+ Settings result = default(Settings);
+ result.mode = Mode.Classic;
+ result.color = new Color(0f, 0f, 0f, 1f);
+ result.center = new Vector2(0.5f, 0.5f);
+ result.intensity = 0.45f;
+ result.smoothness = 0.2f;
+ result.roundness = 1f;
+ result.mask = null;
+ result.opacity = 1f;
+ result.rounded = false;
+ return result;
+ }
+ }
+ }
+
+ [SerializeField]
+ private Settings m_Settings = Settings.defaultSettings;
+
+ public Settings settings
+ {
+ get
+ {
+ return m_Settings;
+ }
+ set
+ {
+ m_Settings = value;
+ }
+ }
+
+ public override void Reset()
+ {
+ m_Settings = Settings.defaultSettings;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/assembly_postprocessing.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/assembly_postprocessing.csproj
new file mode 100644
index 0000000..5939417
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_postprocessing/assembly_postprocessing.csproj
@@ -0,0 +1,28 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_postprocessing</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PhysicsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Core" />
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.IMGUIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/RunTimeCombineAndRelease.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/RunTimeCombineAndRelease.cs
new file mode 100644
index 0000000..65f1d0f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/RunTimeCombineAndRelease.cs
@@ -0,0 +1,43 @@
+using UnityEngine;
+
+public class RunTimeCombineAndRelease : MonoBehaviour
+{
+ public SimpleMeshCombine simpleMeshCombine;
+
+ public float combineTime = 0.5f;
+
+ public float releaseTime = 2f;
+
+ public void Awake()
+ {
+ simpleMeshCombine = GetComponent<SimpleMeshCombine>();
+ }
+
+ public void Start()
+ {
+ if (simpleMeshCombine == null)
+ {
+ Debug.Log("Couldn't find SMC, aborting");
+ return;
+ }
+ Invoke("Combine", combineTime);
+ Invoke("Release", releaseTime);
+ }
+
+ public void Combine()
+ {
+ simpleMeshCombine.CombineMeshes();
+ Debug.Log("Combined");
+ }
+
+ public void Release()
+ {
+ simpleMeshCombine.EnableRenderers(e: true);
+ if (!(simpleMeshCombine.combined == null))
+ {
+ Object.Destroy(simpleMeshCombine.combined);
+ simpleMeshCombine.combinedGameOjects = null;
+ Debug.Log("Released");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombine.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombine.cs
new file mode 100644
index 0000000..a503bf6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombine.cs
@@ -0,0 +1,171 @@
+using System.Collections;
+using UnityEngine;
+
+[AddComponentMenu("Simple Mesh Combine")]
+public class SimpleMeshCombine : MonoBehaviour
+{
+ public GameObject[] combinedGameOjects;
+
+ public GameObject combined;
+
+ public string meshName = "Combined_Meshes";
+
+ public bool _canGenerateLightmapUV;
+
+ public int vCount;
+
+ public bool generateLightmapUV;
+
+ public float lightmapScale = 1f;
+
+ public GameObject copyTarget;
+
+ public bool destroyOldColliders;
+
+ public bool keepStructure = true;
+
+ public Mesh autoOverwrite;
+
+ public bool setStatic = true;
+
+ public void EnableRenderers(bool e)
+ {
+ for (int i = 0; i < combinedGameOjects.Length && !(combinedGameOjects[i] == null); i++)
+ {
+ Renderer component = combinedGameOjects[i].GetComponent<Renderer>();
+ if (component != null)
+ {
+ component.enabled = e;
+ }
+ }
+ }
+
+ public MeshFilter[] FindEnabledMeshes()
+ {
+ MeshFilter[] array = null;
+ int num = 0;
+ array = base.transform.GetComponentsInChildren<MeshFilter>();
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i].GetComponent<MeshRenderer>() != null && array[i].GetComponent<MeshRenderer>().enabled)
+ {
+ num++;
+ }
+ }
+ MeshFilter[] array2 = new MeshFilter[num];
+ num = 0;
+ for (int j = 0; j < array.Length; j++)
+ {
+ if (array[j].GetComponent<MeshRenderer>() != null && array[j].GetComponent<MeshRenderer>().enabled)
+ {
+ array2[num] = array[j];
+ num++;
+ }
+ }
+ return array2;
+ }
+
+ public void CombineMeshes()
+ {
+ GameObject gameObject = new GameObject();
+ gameObject.name = "_Combined Mesh [" + base.name + "]";
+ gameObject.gameObject.AddComponent<MeshFilter>();
+ gameObject.gameObject.AddComponent<MeshRenderer>();
+ MeshFilter[] array = null;
+ array = FindEnabledMeshes();
+ ArrayList arrayList = new ArrayList();
+ ArrayList arrayList2 = new ArrayList();
+ combinedGameOjects = new GameObject[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ combinedGameOjects[i] = array[i].gameObject;
+ MeshRenderer component = array[i].GetComponent<MeshRenderer>();
+ array[i].transform.gameObject.GetComponent<Renderer>().enabled = false;
+ if (array[i].sharedMesh == null)
+ {
+ break;
+ }
+ for (int j = 0; j < array[i].sharedMesh.subMeshCount; j++)
+ {
+ if (component == null)
+ {
+ break;
+ }
+ if (j < component.sharedMaterials.Length && j < array[i].sharedMesh.subMeshCount)
+ {
+ int num = Contains(arrayList, component.sharedMaterials[j]);
+ if (num == -1)
+ {
+ arrayList.Add(component.sharedMaterials[j]);
+ num = arrayList.Count - 1;
+ }
+ arrayList2.Add(new ArrayList());
+ CombineInstance combineInstance = default(CombineInstance);
+ combineInstance.transform = component.transform.localToWorldMatrix;
+ combineInstance.mesh = array[i].sharedMesh;
+ combineInstance.subMeshIndex = j;
+ (arrayList2[num] as ArrayList).Add(combineInstance);
+ }
+ }
+ }
+ Mesh[] array2 = new Mesh[arrayList.Count];
+ CombineInstance[] array3 = new CombineInstance[arrayList.Count];
+ for (int k = 0; k < arrayList.Count; k++)
+ {
+ CombineInstance[] combine = (arrayList2[k] as ArrayList).ToArray(typeof(CombineInstance)) as CombineInstance[];
+ array2[k] = new Mesh();
+ array2[k].CombineMeshes(combine, mergeSubMeshes: true, useMatrices: true);
+ array3[k] = default(CombineInstance);
+ array3[k].mesh = array2[k];
+ array3[k].subMeshIndex = 0;
+ }
+ Mesh mesh2 = (gameObject.GetComponent<MeshFilter>().sharedMesh = new Mesh());
+ Mesh mesh3 = mesh2;
+ mesh3.Clear();
+ mesh3.CombineMeshes(array3, mergeSubMeshes: false, useMatrices: false);
+ gameObject.GetComponent<MeshFilter>().sharedMesh = mesh3;
+ Mesh[] array4 = array2;
+ foreach (Mesh obj in array4)
+ {
+ obj.Clear();
+ Object.DestroyImmediate(obj);
+ }
+ MeshRenderer meshRenderer = gameObject.GetComponent<MeshFilter>().GetComponent<MeshRenderer>();
+ if (meshRenderer == null)
+ {
+ meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
+ }
+ Material[] materials = arrayList.ToArray(typeof(Material)) as Material[];
+ meshRenderer.materials = materials;
+ combined = gameObject.gameObject;
+ EnableRenderers(e: false);
+ gameObject.transform.parent = base.transform;
+ gameObject.GetComponent<MeshFilter>().sharedMesh.RecalculateBounds();
+ vCount = gameObject.GetComponent<MeshFilter>().sharedMesh.vertexCount;
+ if (vCount > 65536)
+ {
+ Debug.LogWarning("Vertex Count: " + vCount + "- Vertex Count too high, please divide mesh combine into more groups. Max 65536 for each mesh");
+ _canGenerateLightmapUV = false;
+ }
+ else
+ {
+ _canGenerateLightmapUV = true;
+ }
+ if (setStatic)
+ {
+ combined.isStatic = true;
+ }
+ }
+
+ public int Contains(ArrayList l, Material n)
+ {
+ for (int i = 0; i < l.Count; i++)
+ {
+ if (l[i] as Material == n)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombineMaster.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombineMaster.cs
new file mode 100644
index 0000000..119731e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/SimpleMeshCombineMaster.cs
@@ -0,0 +1,6 @@
+using UnityEngine;
+
+public class SimpleMeshCombineMaster : MonoBehaviour
+{
+ public bool generateLightmapUV;
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/assembly_simplemeshcombine.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/assembly_simplemeshcombine.csproj
new file mode 100644
index 0000000..3a9185e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_simplemeshcombine/assembly_simplemeshcombine.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_simplemeshcombine</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/AAMode.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/AAMode.cs
new file mode 100644
index 0000000..5c47b2e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/AAMode.cs
@@ -0,0 +1,12 @@
+namespace UnityStandardAssets.ImageEffects;
+
+public enum AAMode
+{
+ FXAA2,
+ FXAA3Console,
+ FXAA1PresetA,
+ FXAA1PresetB,
+ NFAA,
+ SSAA,
+ DLAA
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Antialiasing.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Antialiasing.cs
new file mode 100644
index 0000000..73794bf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Antialiasing.cs
@@ -0,0 +1,139 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Other/Antialiasing")]
+public class Antialiasing : PostEffectsBase
+{
+ public AAMode mode = AAMode.FXAA3Console;
+
+ public bool showGeneratedNormals;
+
+ public float offsetScale = 0.2f;
+
+ public float blurRadius = 18f;
+
+ public float edgeThresholdMin = 0.05f;
+
+ public float edgeThreshold = 0.2f;
+
+ public float edgeSharpness = 4f;
+
+ public bool dlaaSharp;
+
+ public Shader ssaaShader;
+
+ private Material ssaa;
+
+ public Shader dlaaShader;
+
+ private Material dlaa;
+
+ public Shader nfaaShader;
+
+ private Material nfaa;
+
+ public Shader shaderFXAAPreset2;
+
+ private Material materialFXAAPreset2;
+
+ public Shader shaderFXAAPreset3;
+
+ private Material materialFXAAPreset3;
+
+ public Shader shaderFXAAII;
+
+ private Material materialFXAAII;
+
+ public Shader shaderFXAAIII;
+
+ private Material materialFXAAIII;
+
+ public Material CurrentAAMaterial()
+ {
+ Material material = null;
+ return mode switch
+ {
+ AAMode.FXAA3Console => materialFXAAIII,
+ AAMode.FXAA2 => materialFXAAII,
+ AAMode.FXAA1PresetA => materialFXAAPreset2,
+ AAMode.FXAA1PresetB => materialFXAAPreset3,
+ AAMode.NFAA => nfaa,
+ AAMode.SSAA => ssaa,
+ AAMode.DLAA => dlaa,
+ _ => null,
+ };
+ }
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ materialFXAAPreset2 = CreateMaterial(shaderFXAAPreset2, materialFXAAPreset2);
+ materialFXAAPreset3 = CreateMaterial(shaderFXAAPreset3, materialFXAAPreset3);
+ materialFXAAII = CreateMaterial(shaderFXAAII, materialFXAAII);
+ materialFXAAIII = CreateMaterial(shaderFXAAIII, materialFXAAIII);
+ nfaa = CreateMaterial(nfaaShader, nfaa);
+ ssaa = CreateMaterial(ssaaShader, ssaa);
+ dlaa = CreateMaterial(dlaaShader, dlaa);
+ if (!ssaaShader.isSupported)
+ {
+ NotSupported();
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ public void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ }
+ else if (mode == AAMode.FXAA3Console && materialFXAAIII != null)
+ {
+ materialFXAAIII.SetFloat("_EdgeThresholdMin", edgeThresholdMin);
+ materialFXAAIII.SetFloat("_EdgeThreshold", edgeThreshold);
+ materialFXAAIII.SetFloat("_EdgeSharpness", edgeSharpness);
+ Graphics.Blit(source, destination, materialFXAAIII);
+ }
+ else if (mode == AAMode.FXAA1PresetB && materialFXAAPreset3 != null)
+ {
+ Graphics.Blit(source, destination, materialFXAAPreset3);
+ }
+ else if (mode == AAMode.FXAA1PresetA && materialFXAAPreset2 != null)
+ {
+ source.anisoLevel = 4;
+ Graphics.Blit(source, destination, materialFXAAPreset2);
+ source.anisoLevel = 0;
+ }
+ else if (mode == AAMode.FXAA2 && materialFXAAII != null)
+ {
+ Graphics.Blit(source, destination, materialFXAAII);
+ }
+ else if (mode == AAMode.SSAA && ssaa != null)
+ {
+ Graphics.Blit(source, destination, ssaa);
+ }
+ else if (mode == AAMode.DLAA && dlaa != null)
+ {
+ source.anisoLevel = 0;
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height);
+ Graphics.Blit(source, temporary, dlaa, 0);
+ Graphics.Blit(temporary, destination, dlaa, (!dlaaSharp) ? 1 : 2);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ else if (mode == AAMode.NFAA && nfaa != null)
+ {
+ source.anisoLevel = 0;
+ nfaa.SetFloat("_OffsetScale", offsetScale);
+ nfaa.SetFloat("_BlurRadius", blurRadius);
+ Graphics.Blit(source, destination, nfaa, showGeneratedNormals ? 1 : 0);
+ }
+ else
+ {
+ Graphics.Blit(source, destination);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Bloom.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Bloom.cs
new file mode 100644
index 0000000..14f6340
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Bloom.cs
@@ -0,0 +1,333 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Bloom and Glow/Bloom")]
+public class Bloom : PostEffectsBase
+{
+ public enum LensFlareStyle
+ {
+ Ghosting,
+ Anamorphic,
+ Combined
+ }
+
+ public enum TweakMode
+ {
+ Basic,
+ Complex
+ }
+
+ public enum HDRBloomMode
+ {
+ Auto,
+ On,
+ Off
+ }
+
+ public enum BloomScreenBlendMode
+ {
+ Screen,
+ Add
+ }
+
+ public enum BloomQuality
+ {
+ Cheap,
+ High
+ }
+
+ public TweakMode tweakMode;
+
+ public BloomScreenBlendMode screenBlendMode = BloomScreenBlendMode.Add;
+
+ public HDRBloomMode hdr;
+
+ private bool doHdr;
+
+ public float sepBlurSpread = 2.5f;
+
+ public BloomQuality quality = BloomQuality.High;
+
+ public float bloomIntensity = 0.5f;
+
+ public float bloomThreshold = 0.5f;
+
+ public Color bloomThresholdColor = Color.white;
+
+ public int bloomBlurIterations = 2;
+
+ public int hollywoodFlareBlurIterations = 2;
+
+ public float flareRotation;
+
+ public LensFlareStyle lensflareMode = LensFlareStyle.Anamorphic;
+
+ public float hollyStretchWidth = 2.5f;
+
+ public float lensflareIntensity;
+
+ public float lensflareThreshold = 0.3f;
+
+ public float lensFlareSaturation = 0.75f;
+
+ public Color flareColorA = new Color(0.4f, 0.4f, 0.8f, 0.75f);
+
+ public Color flareColorB = new Color(0.4f, 0.8f, 0.8f, 0.75f);
+
+ public Color flareColorC = new Color(0.8f, 0.4f, 0.8f, 0.75f);
+
+ public Color flareColorD = new Color(0.8f, 0.4f, 0f, 0.75f);
+
+ public Texture2D lensFlareVignetteMask;
+
+ public Shader lensFlareShader;
+
+ private Material lensFlareMaterial;
+
+ public Shader screenBlendShader;
+
+ private Material screenBlend;
+
+ public Shader blurAndFlaresShader;
+
+ private Material blurAndFlaresMaterial;
+
+ public Shader brightPassFilterShader;
+
+ private Material brightPassFilterMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ screenBlend = CheckShaderAndCreateMaterial(screenBlendShader, screenBlend);
+ lensFlareMaterial = CheckShaderAndCreateMaterial(lensFlareShader, lensFlareMaterial);
+ blurAndFlaresMaterial = CheckShaderAndCreateMaterial(blurAndFlaresShader, blurAndFlaresMaterial);
+ brightPassFilterMaterial = CheckShaderAndCreateMaterial(brightPassFilterShader, brightPassFilterMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ public void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ doHdr = false;
+ if (hdr == HDRBloomMode.Auto)
+ {
+ doHdr = source.format == RenderTextureFormat.ARGBHalf && GetComponent<Camera>().allowHDR;
+ }
+ else
+ {
+ doHdr = hdr == HDRBloomMode.On;
+ }
+ doHdr = doHdr && supportHDRTextures;
+ BloomScreenBlendMode bloomScreenBlendMode = screenBlendMode;
+ if (doHdr)
+ {
+ bloomScreenBlendMode = BloomScreenBlendMode.Add;
+ }
+ RenderTextureFormat format = (doHdr ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default);
+ int width = source.width / 2;
+ int height = source.height / 2;
+ int width2 = source.width / 4;
+ int height2 = source.height / 4;
+ float num = 1f * (float)source.width / (1f * (float)source.height);
+ float num2 = 0.001953125f;
+ RenderTexture temporary = RenderTexture.GetTemporary(width2, height2, 0, format);
+ RenderTexture temporary2 = RenderTexture.GetTemporary(width, height, 0, format);
+ if (quality > BloomQuality.Cheap)
+ {
+ Graphics.Blit(source, temporary2, screenBlend, 2);
+ RenderTexture temporary3 = RenderTexture.GetTemporary(width2, height2, 0, format);
+ Graphics.Blit(temporary2, temporary3, screenBlend, 2);
+ Graphics.Blit(temporary3, temporary, screenBlend, 6);
+ RenderTexture.ReleaseTemporary(temporary3);
+ }
+ else
+ {
+ Graphics.Blit(source, temporary2);
+ Graphics.Blit(temporary2, temporary, screenBlend, 6);
+ }
+ RenderTexture.ReleaseTemporary(temporary2);
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width2, height2, 0, format);
+ BrightFilter(bloomThreshold * bloomThresholdColor, temporary, renderTexture);
+ if (bloomBlurIterations < 1)
+ {
+ bloomBlurIterations = 1;
+ }
+ else if (bloomBlurIterations > 10)
+ {
+ bloomBlurIterations = 10;
+ }
+ for (int i = 0; i < bloomBlurIterations; i++)
+ {
+ float num3 = (1f + (float)i * 0.25f) * sepBlurSpread;
+ RenderTexture temporary4 = RenderTexture.GetTemporary(width2, height2, 0, format);
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(0f, num3 * num2, 0f, 0f));
+ Graphics.Blit(renderTexture, temporary4, blurAndFlaresMaterial, 4);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary4;
+ temporary4 = RenderTexture.GetTemporary(width2, height2, 0, format);
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(num3 / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(renderTexture, temporary4, blurAndFlaresMaterial, 4);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary4;
+ if (quality > BloomQuality.Cheap)
+ {
+ if (i == 0)
+ {
+ Graphics.SetRenderTarget(temporary);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(renderTexture, temporary);
+ }
+ else
+ {
+ temporary.MarkRestoreExpected();
+ Graphics.Blit(renderTexture, temporary, screenBlend, 10);
+ }
+ }
+ }
+ if (quality > BloomQuality.Cheap)
+ {
+ Graphics.SetRenderTarget(renderTexture);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(temporary, renderTexture, screenBlend, 6);
+ }
+ if (lensflareIntensity > Mathf.Epsilon)
+ {
+ RenderTexture temporary5 = RenderTexture.GetTemporary(width2, height2, 0, format);
+ if (lensflareMode == LensFlareStyle.Ghosting)
+ {
+ BrightFilter(lensflareThreshold, renderTexture, temporary5);
+ if (quality > BloomQuality.Cheap)
+ {
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(0f, 1.5f / (1f * (float)temporary.height), 0f, 0f));
+ Graphics.SetRenderTarget(temporary);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(temporary5, temporary, blurAndFlaresMaterial, 4);
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(1.5f / (1f * (float)temporary.width), 0f, 0f, 0f));
+ Graphics.SetRenderTarget(temporary5);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(temporary, temporary5, blurAndFlaresMaterial, 4);
+ }
+ Vignette(0.975f, temporary5, temporary5);
+ BlendFlares(temporary5, renderTexture);
+ }
+ else
+ {
+ float num4 = 1f * Mathf.Cos(flareRotation);
+ float num5 = 1f * Mathf.Sin(flareRotation);
+ float num6 = hollyStretchWidth * 1f / num * num2;
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(num4, num5, 0f, 0f));
+ blurAndFlaresMaterial.SetVector("_Threshhold", new Vector4(lensflareThreshold, 1f, 0f, 0f));
+ blurAndFlaresMaterial.SetVector("_TintColor", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * flareColorA.a * lensflareIntensity);
+ blurAndFlaresMaterial.SetFloat("_Saturation", lensFlareSaturation);
+ temporary.DiscardContents();
+ Graphics.Blit(temporary5, temporary, blurAndFlaresMaterial, 2);
+ temporary5.DiscardContents();
+ Graphics.Blit(temporary, temporary5, blurAndFlaresMaterial, 3);
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(num4 * num6, num5 * num6, 0f, 0f));
+ blurAndFlaresMaterial.SetFloat("_StretchWidth", hollyStretchWidth);
+ temporary.DiscardContents();
+ Graphics.Blit(temporary5, temporary, blurAndFlaresMaterial, 1);
+ blurAndFlaresMaterial.SetFloat("_StretchWidth", hollyStretchWidth * 2f);
+ temporary5.DiscardContents();
+ Graphics.Blit(temporary, temporary5, blurAndFlaresMaterial, 1);
+ blurAndFlaresMaterial.SetFloat("_StretchWidth", hollyStretchWidth * 4f);
+ temporary.DiscardContents();
+ Graphics.Blit(temporary5, temporary, blurAndFlaresMaterial, 1);
+ for (int j = 0; j < hollywoodFlareBlurIterations; j++)
+ {
+ num6 = hollyStretchWidth * 2f / num * num2;
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(num6 * num4, num6 * num5, 0f, 0f));
+ temporary5.DiscardContents();
+ Graphics.Blit(temporary, temporary5, blurAndFlaresMaterial, 4);
+ blurAndFlaresMaterial.SetVector("_Offsets", new Vector4(num6 * num4, num6 * num5, 0f, 0f));
+ temporary.DiscardContents();
+ Graphics.Blit(temporary5, temporary, blurAndFlaresMaterial, 4);
+ }
+ if (lensflareMode == LensFlareStyle.Anamorphic)
+ {
+ AddTo(1f, temporary, renderTexture);
+ }
+ else
+ {
+ Vignette(1f, temporary, temporary5);
+ BlendFlares(temporary5, temporary);
+ AddTo(1f, temporary, renderTexture);
+ }
+ }
+ RenderTexture.ReleaseTemporary(temporary5);
+ }
+ int pass = (int)bloomScreenBlendMode;
+ screenBlend.SetFloat("_Intensity", bloomIntensity);
+ screenBlend.SetTexture("_ColorBuffer", source);
+ if (quality > BloomQuality.Cheap)
+ {
+ RenderTexture temporary6 = RenderTexture.GetTemporary(width, height, 0, format);
+ Graphics.Blit(renderTexture, temporary6);
+ Graphics.Blit(temporary6, destination, screenBlend, pass);
+ RenderTexture.ReleaseTemporary(temporary6);
+ }
+ else
+ {
+ Graphics.Blit(renderTexture, destination, screenBlend, pass);
+ }
+ RenderTexture.ReleaseTemporary(temporary);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+
+ private void AddTo(float intensity_, RenderTexture from, RenderTexture to)
+ {
+ screenBlend.SetFloat("_Intensity", intensity_);
+ to.MarkRestoreExpected();
+ Graphics.Blit(from, to, screenBlend, 9);
+ }
+
+ private void BlendFlares(RenderTexture from, RenderTexture to)
+ {
+ lensFlareMaterial.SetVector("colorA", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorB", new Vector4(flareColorB.r, flareColorB.g, flareColorB.b, flareColorB.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorC", new Vector4(flareColorC.r, flareColorC.g, flareColorC.b, flareColorC.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorD", new Vector4(flareColorD.r, flareColorD.g, flareColorD.b, flareColorD.a) * lensflareIntensity);
+ to.MarkRestoreExpected();
+ Graphics.Blit(from, to, lensFlareMaterial);
+ }
+
+ private void BrightFilter(float thresh, RenderTexture from, RenderTexture to)
+ {
+ brightPassFilterMaterial.SetVector("_Threshhold", new Vector4(thresh, thresh, thresh, thresh));
+ Graphics.Blit(from, to, brightPassFilterMaterial, 0);
+ }
+
+ private void BrightFilter(Color threshColor, RenderTexture from, RenderTexture to)
+ {
+ brightPassFilterMaterial.SetVector("_Threshhold", threshColor);
+ Graphics.Blit(from, to, brightPassFilterMaterial, 1);
+ }
+
+ private void Vignette(float amount, RenderTexture from, RenderTexture to)
+ {
+ if ((bool)lensFlareVignetteMask)
+ {
+ screenBlend.SetTexture("_ColorBuffer", lensFlareVignetteMask);
+ to.MarkRestoreExpected();
+ Graphics.Blit((from == to) ? null : from, to, screenBlend, (from == to) ? 7 : 3);
+ }
+ else if (from != to)
+ {
+ Graphics.SetRenderTarget(to);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(from, to);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomAndFlares.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomAndFlares.cs
new file mode 100644
index 0000000..1c4428c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomAndFlares.cs
@@ -0,0 +1,257 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Bloom and Glow/BloomAndFlares (3.5, Deprecated)")]
+public class BloomAndFlares : PostEffectsBase
+{
+ public TweakMode34 tweakMode;
+
+ public BloomScreenBlendMode screenBlendMode = BloomScreenBlendMode.Add;
+
+ public HDRBloomMode hdr;
+
+ private bool doHdr;
+
+ public float sepBlurSpread = 1.5f;
+
+ public float useSrcAlphaAsMask = 0.5f;
+
+ public float bloomIntensity = 1f;
+
+ public float bloomThreshold = 0.5f;
+
+ public int bloomBlurIterations = 2;
+
+ public bool lensflares;
+
+ public int hollywoodFlareBlurIterations = 2;
+
+ public LensflareStyle34 lensflareMode = LensflareStyle34.Anamorphic;
+
+ public float hollyStretchWidth = 3.5f;
+
+ public float lensflareIntensity = 1f;
+
+ public float lensflareThreshold = 0.3f;
+
+ public Color flareColorA = new Color(0.4f, 0.4f, 0.8f, 0.75f);
+
+ public Color flareColorB = new Color(0.4f, 0.8f, 0.8f, 0.75f);
+
+ public Color flareColorC = new Color(0.8f, 0.4f, 0.8f, 0.75f);
+
+ public Color flareColorD = new Color(0.8f, 0.4f, 0f, 0.75f);
+
+ public Texture2D lensFlareVignetteMask;
+
+ public Shader lensFlareShader;
+
+ private Material lensFlareMaterial;
+
+ public Shader vignetteShader;
+
+ private Material vignetteMaterial;
+
+ public Shader separableBlurShader;
+
+ private Material separableBlurMaterial;
+
+ public Shader addBrightStuffOneOneShader;
+
+ private Material addBrightStuffBlendOneOneMaterial;
+
+ public Shader screenBlendShader;
+
+ private Material screenBlend;
+
+ public Shader hollywoodFlaresShader;
+
+ private Material hollywoodFlaresMaterial;
+
+ public Shader brightPassFilterShader;
+
+ private Material brightPassFilterMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ screenBlend = CheckShaderAndCreateMaterial(screenBlendShader, screenBlend);
+ lensFlareMaterial = CheckShaderAndCreateMaterial(lensFlareShader, lensFlareMaterial);
+ vignetteMaterial = CheckShaderAndCreateMaterial(vignetteShader, vignetteMaterial);
+ separableBlurMaterial = CheckShaderAndCreateMaterial(separableBlurShader, separableBlurMaterial);
+ addBrightStuffBlendOneOneMaterial = CheckShaderAndCreateMaterial(addBrightStuffOneOneShader, addBrightStuffBlendOneOneMaterial);
+ hollywoodFlaresMaterial = CheckShaderAndCreateMaterial(hollywoodFlaresShader, hollywoodFlaresMaterial);
+ brightPassFilterMaterial = CheckShaderAndCreateMaterial(brightPassFilterShader, brightPassFilterMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ doHdr = false;
+ if (hdr == HDRBloomMode.Auto)
+ {
+ doHdr = source.format == RenderTextureFormat.ARGBHalf && GetComponent<Camera>().allowHDR;
+ }
+ else
+ {
+ doHdr = hdr == HDRBloomMode.On;
+ }
+ doHdr = doHdr && supportHDRTextures;
+ BloomScreenBlendMode pass = screenBlendMode;
+ if (doHdr)
+ {
+ pass = BloomScreenBlendMode.Add;
+ }
+ RenderTextureFormat format = (doHdr ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.Default);
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width / 2, source.height / 2, 0, format);
+ RenderTexture temporary2 = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0, format);
+ RenderTexture temporary3 = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0, format);
+ RenderTexture temporary4 = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0, format);
+ float num = 1f * (float)source.width / (1f * (float)source.height);
+ float num2 = 0.001953125f;
+ Graphics.Blit(source, temporary, screenBlend, 2);
+ Graphics.Blit(temporary, temporary2, screenBlend, 2);
+ RenderTexture.ReleaseTemporary(temporary);
+ BrightFilter(bloomThreshold, useSrcAlphaAsMask, temporary2, temporary3);
+ temporary2.DiscardContents();
+ if (bloomBlurIterations < 1)
+ {
+ bloomBlurIterations = 1;
+ }
+ for (int i = 0; i < bloomBlurIterations; i++)
+ {
+ float num3 = (1f + (float)i * 0.5f) * sepBlurSpread;
+ separableBlurMaterial.SetVector("offsets", new Vector4(0f, num3 * num2, 0f, 0f));
+ RenderTexture obj = ((i == 0) ? temporary3 : temporary2);
+ Graphics.Blit(obj, temporary4, separableBlurMaterial);
+ obj.DiscardContents();
+ separableBlurMaterial.SetVector("offsets", new Vector4(num3 / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(temporary4, temporary2, separableBlurMaterial);
+ temporary4.DiscardContents();
+ }
+ if (lensflares)
+ {
+ if (lensflareMode == LensflareStyle34.Ghosting)
+ {
+ BrightFilter(lensflareThreshold, 0f, temporary2, temporary4);
+ temporary2.DiscardContents();
+ Vignette(0.975f, temporary4, temporary3);
+ temporary4.DiscardContents();
+ BlendFlares(temporary3, temporary2);
+ temporary3.DiscardContents();
+ }
+ else
+ {
+ hollywoodFlaresMaterial.SetVector("_threshold", new Vector4(lensflareThreshold, 1f / (1f - lensflareThreshold), 0f, 0f));
+ hollywoodFlaresMaterial.SetVector("tintColor", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * flareColorA.a * lensflareIntensity);
+ Graphics.Blit(temporary4, temporary3, hollywoodFlaresMaterial, 2);
+ temporary4.DiscardContents();
+ Graphics.Blit(temporary3, temporary4, hollywoodFlaresMaterial, 3);
+ temporary3.DiscardContents();
+ hollywoodFlaresMaterial.SetVector("offsets", new Vector4(sepBlurSpread * 1f / num * num2, 0f, 0f, 0f));
+ hollywoodFlaresMaterial.SetFloat("stretchWidth", hollyStretchWidth);
+ Graphics.Blit(temporary4, temporary3, hollywoodFlaresMaterial, 1);
+ temporary4.DiscardContents();
+ hollywoodFlaresMaterial.SetFloat("stretchWidth", hollyStretchWidth * 2f);
+ Graphics.Blit(temporary3, temporary4, hollywoodFlaresMaterial, 1);
+ temporary3.DiscardContents();
+ hollywoodFlaresMaterial.SetFloat("stretchWidth", hollyStretchWidth * 4f);
+ Graphics.Blit(temporary4, temporary3, hollywoodFlaresMaterial, 1);
+ temporary4.DiscardContents();
+ if (lensflareMode == LensflareStyle34.Anamorphic)
+ {
+ for (int j = 0; j < hollywoodFlareBlurIterations; j++)
+ {
+ separableBlurMaterial.SetVector("offsets", new Vector4(hollyStretchWidth * 2f / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(temporary3, temporary4, separableBlurMaterial);
+ temporary3.DiscardContents();
+ separableBlurMaterial.SetVector("offsets", new Vector4(hollyStretchWidth * 2f / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(temporary4, temporary3, separableBlurMaterial);
+ temporary4.DiscardContents();
+ }
+ AddTo(1f, temporary3, temporary2);
+ temporary3.DiscardContents();
+ }
+ else
+ {
+ for (int k = 0; k < hollywoodFlareBlurIterations; k++)
+ {
+ separableBlurMaterial.SetVector("offsets", new Vector4(hollyStretchWidth * 2f / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(temporary3, temporary4, separableBlurMaterial);
+ temporary3.DiscardContents();
+ separableBlurMaterial.SetVector("offsets", new Vector4(hollyStretchWidth * 2f / num * num2, 0f, 0f, 0f));
+ Graphics.Blit(temporary4, temporary3, separableBlurMaterial);
+ temporary4.DiscardContents();
+ }
+ Vignette(1f, temporary3, temporary4);
+ temporary3.DiscardContents();
+ BlendFlares(temporary4, temporary3);
+ temporary4.DiscardContents();
+ AddTo(1f, temporary3, temporary2);
+ temporary3.DiscardContents();
+ }
+ }
+ }
+ screenBlend.SetFloat("_Intensity", bloomIntensity);
+ screenBlend.SetTexture("_ColorBuffer", source);
+ Graphics.Blit(temporary2, destination, screenBlend, (int)pass);
+ RenderTexture.ReleaseTemporary(temporary2);
+ RenderTexture.ReleaseTemporary(temporary3);
+ RenderTexture.ReleaseTemporary(temporary4);
+ }
+
+ private void AddTo(float intensity_, RenderTexture from, RenderTexture to)
+ {
+ addBrightStuffBlendOneOneMaterial.SetFloat("_Intensity", intensity_);
+ Graphics.Blit(from, to, addBrightStuffBlendOneOneMaterial);
+ }
+
+ private void BlendFlares(RenderTexture from, RenderTexture to)
+ {
+ lensFlareMaterial.SetVector("colorA", new Vector4(flareColorA.r, flareColorA.g, flareColorA.b, flareColorA.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorB", new Vector4(flareColorB.r, flareColorB.g, flareColorB.b, flareColorB.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorC", new Vector4(flareColorC.r, flareColorC.g, flareColorC.b, flareColorC.a) * lensflareIntensity);
+ lensFlareMaterial.SetVector("colorD", new Vector4(flareColorD.r, flareColorD.g, flareColorD.b, flareColorD.a) * lensflareIntensity);
+ Graphics.Blit(from, to, lensFlareMaterial);
+ }
+
+ private void BrightFilter(float thresh, float useAlphaAsMask, RenderTexture from, RenderTexture to)
+ {
+ if (doHdr)
+ {
+ brightPassFilterMaterial.SetVector("threshold", new Vector4(thresh, 1f, 0f, 0f));
+ }
+ else
+ {
+ brightPassFilterMaterial.SetVector("threshold", new Vector4(thresh, 1f / (1f - thresh), 0f, 0f));
+ }
+ brightPassFilterMaterial.SetFloat("useSrcAlphaAsMask", useAlphaAsMask);
+ Graphics.Blit(from, to, brightPassFilterMaterial);
+ }
+
+ private void Vignette(float amount, RenderTexture from, RenderTexture to)
+ {
+ if ((bool)lensFlareVignetteMask)
+ {
+ screenBlend.SetTexture("_ColorBuffer", lensFlareVignetteMask);
+ Graphics.Blit(from, to, screenBlend, 3);
+ }
+ else
+ {
+ vignetteMaterial.SetFloat("vignetteIntensity", amount);
+ Graphics.Blit(from, to, vignetteMaterial);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomOptimized.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomOptimized.cs
new file mode 100644
index 0000000..9b90a75
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomOptimized.cs
@@ -0,0 +1,96 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Bloom and Glow/Bloom (Optimized)")]
+public class BloomOptimized : PostEffectsBase
+{
+ public enum Resolution
+ {
+ Low,
+ High
+ }
+
+ public enum BlurType
+ {
+ Standard,
+ Sgx
+ }
+
+ [Range(0f, 1.5f)]
+ public float threshold = 0.25f;
+
+ [Range(0f, 2.5f)]
+ public float intensity = 0.75f;
+
+ [Range(0.25f, 5.5f)]
+ public float blurSize = 1f;
+
+ private Resolution resolution;
+
+ [Range(1f, 4f)]
+ public int blurIterations = 1;
+
+ public BlurType blurType;
+
+ public Shader fastBloomShader;
+
+ private Material fastBloomMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ fastBloomMaterial = CheckShaderAndCreateMaterial(fastBloomShader, fastBloomMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnDisable()
+ {
+ if ((bool)fastBloomMaterial)
+ {
+ Object.DestroyImmediate(fastBloomMaterial);
+ }
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ int num = ((resolution == Resolution.Low) ? 4 : 2);
+ float num2 = ((resolution == Resolution.Low) ? 0.5f : 1f);
+ fastBloomMaterial.SetVector("_Parameter", new Vector4(blurSize * num2, 0f, threshold, intensity));
+ source.filterMode = FilterMode.Bilinear;
+ int width = source.width / num;
+ int height = source.height / num;
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width, height, 0, source.format);
+ renderTexture.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(source, renderTexture, fastBloomMaterial, 1);
+ int num3 = ((blurType != 0) ? 2 : 0);
+ for (int i = 0; i < blurIterations; i++)
+ {
+ fastBloomMaterial.SetVector("_Parameter", new Vector4(blurSize * num2 + (float)i * 1f, 0f, threshold, intensity));
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, source.format);
+ temporary.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(renderTexture, temporary, fastBloomMaterial, 2 + num3);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ temporary = RenderTexture.GetTemporary(width, height, 0, source.format);
+ temporary.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(renderTexture, temporary, fastBloomMaterial, 3 + num3);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ }
+ fastBloomMaterial.SetTexture("_Bloom", renderTexture);
+ Graphics.Blit(source, destination, fastBloomMaterial, 0);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomScreenBlendMode.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomScreenBlendMode.cs
new file mode 100644
index 0000000..621cc01
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BloomScreenBlendMode.cs
@@ -0,0 +1,7 @@
+namespace UnityStandardAssets.ImageEffects;
+
+public enum BloomScreenBlendMode
+{
+ Screen,
+ Add
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Blur.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Blur.cs
new file mode 100644
index 0000000..d250a75
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Blur.cs
@@ -0,0 +1,80 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Blur/Blur")]
+public class Blur : MonoBehaviour
+{
+ [Range(0f, 10f)]
+ public int iterations = 3;
+
+ [Range(0f, 1f)]
+ public float blurSpread = 0.6f;
+
+ public Shader blurShader;
+
+ private static Material m_Material;
+
+ protected Material material
+ {
+ get
+ {
+ if (m_Material == null)
+ {
+ m_Material = new Material(blurShader);
+ m_Material.hideFlags = HideFlags.DontSave;
+ }
+ return m_Material;
+ }
+ }
+
+ protected void OnDisable()
+ {
+ if ((bool)m_Material)
+ {
+ Object.DestroyImmediate(m_Material);
+ }
+ }
+
+ protected void Start()
+ {
+ if (!SystemInfo.supportsImageEffects)
+ {
+ base.enabled = false;
+ }
+ else if (!blurShader || !material.shader.isSupported)
+ {
+ base.enabled = false;
+ }
+ }
+
+ public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
+ {
+ float num = 0.5f + (float)iteration * blurSpread;
+ Graphics.BlitMultiTap(source, dest, material, new Vector2(0f - num, 0f - num), new Vector2(0f - num, num), new Vector2(num, num), new Vector2(num, 0f - num));
+ }
+
+ private void DownSample4x(RenderTexture source, RenderTexture dest)
+ {
+ float num = 1f;
+ Graphics.BlitMultiTap(source, dest, material, new Vector2(0f - num, 0f - num), new Vector2(0f - num, num), new Vector2(num, num), new Vector2(num, 0f - num));
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ int width = source.width / 4;
+ int height = source.height / 4;
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width, height, 0);
+ DownSample4x(source, renderTexture);
+ for (int i = 0; i < iterations; i++)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0);
+ FourTapCone(renderTexture, temporary, i);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ }
+ Graphics.Blit(renderTexture, destination);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BlurOptimized.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BlurOptimized.cs
new file mode 100644
index 0000000..43c55f5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/BlurOptimized.cs
@@ -0,0 +1,84 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Blur/Blur (Optimized)")]
+public class BlurOptimized : PostEffectsBase
+{
+ public enum BlurType
+ {
+ StandardGauss,
+ SgxGauss
+ }
+
+ [Range(0f, 2f)]
+ public int downsample = 1;
+
+ [Range(0f, 10f)]
+ public float blurSize = 3f;
+
+ [Range(1f, 4f)]
+ public int blurIterations = 2;
+
+ public BlurType blurType;
+
+ public Shader blurShader;
+
+ private Material blurMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ blurMaterial = CheckShaderAndCreateMaterial(blurShader, blurMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ public void OnDisable()
+ {
+ if ((bool)blurMaterial)
+ {
+ Object.DestroyImmediate(blurMaterial);
+ }
+ }
+
+ public void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ float num = 1f / (1f * (float)(1 << downsample));
+ blurMaterial.SetVector("_Parameter", new Vector4(blurSize * num, (0f - blurSize) * num, 0f, 0f));
+ source.filterMode = FilterMode.Bilinear;
+ int width = source.width >> downsample;
+ int height = source.height >> downsample;
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width, height, 0, source.format);
+ renderTexture.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(source, renderTexture, blurMaterial, 0);
+ int num2 = ((blurType != 0) ? 2 : 0);
+ for (int i = 0; i < blurIterations; i++)
+ {
+ float num3 = (float)i * 1f;
+ blurMaterial.SetVector("_Parameter", new Vector4(blurSize * num + num3, (0f - blurSize) * num - num3, 0f, 0f));
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, source.format);
+ temporary.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(renderTexture, temporary, blurMaterial, 1 + num2);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ temporary = RenderTexture.GetTemporary(width, height, 0, source.format);
+ temporary.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(renderTexture, temporary, blurMaterial, 2 + num2);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ }
+ Graphics.Blit(renderTexture, destination);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CameraMotionBlur.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CameraMotionBlur.cs
new file mode 100644
index 0000000..7af41d3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CameraMotionBlur.cs
@@ -0,0 +1,382 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Camera/Camera Motion Blur")]
+public class CameraMotionBlur : PostEffectsBase
+{
+ public enum MotionBlurFilter
+ {
+ CameraMotion,
+ LocalBlur,
+ Reconstruction,
+ ReconstructionDX11,
+ ReconstructionDisc
+ }
+
+ private static float MAX_RADIUS = 10f;
+
+ public MotionBlurFilter filterType = MotionBlurFilter.Reconstruction;
+
+ public bool preview;
+
+ public Vector3 previewScale = Vector3.one;
+
+ public float movementScale;
+
+ public float rotationScale = 1f;
+
+ public float maxVelocity = 8f;
+
+ public float minVelocity = 0.1f;
+
+ public float velocityScale = 0.375f;
+
+ public float softZDistance = 0.005f;
+
+ public int velocityDownsample = 1;
+
+ public LayerMask excludeLayers = 0;
+
+ private GameObject tmpCam;
+
+ public Shader shader;
+
+ public Shader dx11MotionBlurShader;
+
+ public Shader replacementClear;
+
+ private Material motionBlurMaterial;
+
+ private Material dx11MotionBlurMaterial;
+
+ public Texture2D noiseTexture;
+
+ public float jitter = 0.05f;
+
+ public bool showVelocity;
+
+ public float showVelocityScale = 1f;
+
+ private Matrix4x4 currentViewProjMat;
+
+ private Matrix4x4[] currentStereoViewProjMat;
+
+ private Matrix4x4 prevViewProjMat;
+
+ private Matrix4x4[] prevStereoViewProjMat;
+
+ private int prevFrameCount;
+
+ private bool wasActive;
+
+ private Vector3 prevFrameForward = Vector3.forward;
+
+ private Vector3 prevFrameUp = Vector3.up;
+
+ private Vector3 prevFramePos = Vector3.zero;
+
+ private Camera _camera;
+
+ private void CalculateViewProjection()
+ {
+ Matrix4x4 worldToCameraMatrix = _camera.worldToCameraMatrix;
+ Matrix4x4 gPUProjectionMatrix = GL.GetGPUProjectionMatrix(_camera.projectionMatrix, renderIntoTexture: true);
+ currentViewProjMat = gPUProjectionMatrix * worldToCameraMatrix;
+ if (_camera.stereoEnabled)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ Matrix4x4 stereoViewMatrix = _camera.GetStereoViewMatrix((i != 0) ? Camera.StereoscopicEye.Right : Camera.StereoscopicEye.Left);
+ Matrix4x4 stereoProjectionMatrix = _camera.GetStereoProjectionMatrix((i != 0) ? Camera.StereoscopicEye.Right : Camera.StereoscopicEye.Left);
+ stereoProjectionMatrix = GL.GetGPUProjectionMatrix(stereoProjectionMatrix, renderIntoTexture: true);
+ currentStereoViewProjMat[i] = stereoProjectionMatrix * stereoViewMatrix;
+ }
+ }
+ }
+
+ private new void Start()
+ {
+ CheckResources();
+ if (_camera == null)
+ {
+ _camera = GetComponent<Camera>();
+ }
+ wasActive = base.gameObject.activeInHierarchy;
+ currentStereoViewProjMat = new Matrix4x4[2];
+ prevStereoViewProjMat = new Matrix4x4[2];
+ CalculateViewProjection();
+ Remember();
+ wasActive = false;
+ }
+
+ private void OnEnable()
+ {
+ if (_camera == null)
+ {
+ _camera = GetComponent<Camera>();
+ }
+ _camera.depthTextureMode |= DepthTextureMode.Depth;
+ }
+
+ private void OnDisable()
+ {
+ if (null != motionBlurMaterial)
+ {
+ Object.DestroyImmediate(motionBlurMaterial);
+ motionBlurMaterial = null;
+ }
+ if (null != dx11MotionBlurMaterial)
+ {
+ Object.DestroyImmediate(dx11MotionBlurMaterial);
+ dx11MotionBlurMaterial = null;
+ }
+ if (null != tmpCam)
+ {
+ Object.DestroyImmediate(tmpCam);
+ tmpCam = null;
+ }
+ }
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true, needHdr: true);
+ motionBlurMaterial = CheckShaderAndCreateMaterial(shader, motionBlurMaterial);
+ if (supportDX11 && filterType == MotionBlurFilter.ReconstructionDX11)
+ {
+ dx11MotionBlurMaterial = CheckShaderAndCreateMaterial(dx11MotionBlurShader, dx11MotionBlurMaterial);
+ }
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ if (filterType == MotionBlurFilter.CameraMotion)
+ {
+ StartFrame();
+ }
+ RenderTextureFormat format = (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf) ? RenderTextureFormat.RGHalf : RenderTextureFormat.ARGBHalf);
+ RenderTexture temporary = RenderTexture.GetTemporary(divRoundUp(source.width, velocityDownsample), divRoundUp(source.height, velocityDownsample), 0, format);
+ int num = 1;
+ int num2 = 1;
+ maxVelocity = Mathf.Max(2f, maxVelocity);
+ float num3 = maxVelocity;
+ bool flag = filterType == MotionBlurFilter.ReconstructionDX11 && dx11MotionBlurMaterial == null;
+ if (filterType == MotionBlurFilter.Reconstruction || flag || filterType == MotionBlurFilter.ReconstructionDisc)
+ {
+ maxVelocity = Mathf.Min(maxVelocity, MAX_RADIUS);
+ num = divRoundUp(temporary.width, (int)maxVelocity);
+ num2 = divRoundUp(temporary.height, (int)maxVelocity);
+ num3 = temporary.width / num;
+ }
+ else
+ {
+ num = divRoundUp(temporary.width, (int)maxVelocity);
+ num2 = divRoundUp(temporary.height, (int)maxVelocity);
+ num3 = temporary.width / num;
+ }
+ RenderTexture temporary2 = RenderTexture.GetTemporary(num, num2, 0, format);
+ RenderTexture temporary3 = RenderTexture.GetTemporary(num, num2, 0, format);
+ temporary.filterMode = FilterMode.Point;
+ temporary2.filterMode = FilterMode.Point;
+ temporary3.filterMode = FilterMode.Point;
+ if ((bool)noiseTexture)
+ {
+ noiseTexture.filterMode = FilterMode.Point;
+ }
+ source.wrapMode = TextureWrapMode.Clamp;
+ temporary.wrapMode = TextureWrapMode.Clamp;
+ temporary3.wrapMode = TextureWrapMode.Clamp;
+ temporary2.wrapMode = TextureWrapMode.Clamp;
+ CalculateViewProjection();
+ if (base.gameObject.activeInHierarchy && !wasActive)
+ {
+ Remember();
+ }
+ wasActive = base.gameObject.activeInHierarchy;
+ Matrix4x4 matrix4x = Matrix4x4.Inverse(currentViewProjMat);
+ motionBlurMaterial.SetMatrix("_InvViewProj", matrix4x);
+ motionBlurMaterial.SetMatrix("_PrevViewProj", prevViewProjMat);
+ motionBlurMaterial.SetMatrix("_ToPrevViewProjCombined", prevViewProjMat * matrix4x);
+ if (_camera.stereoEnabled)
+ {
+ Matrix4x4[] array = new Matrix4x4[2]
+ {
+ Matrix4x4.Inverse(currentStereoViewProjMat[0]),
+ Matrix4x4.Inverse(currentStereoViewProjMat[1])
+ };
+ Matrix4x4 value = prevStereoViewProjMat[0] * array[0];
+ motionBlurMaterial.SetMatrix("_StereoToPrevViewProjCombined0", value);
+ motionBlurMaterial.SetMatrix("_StereoToPrevViewProjCombined1", prevStereoViewProjMat[1] * array[1]);
+ }
+ motionBlurMaterial.SetFloat("_MaxVelocity", num3);
+ motionBlurMaterial.SetFloat("_MaxRadiusOrKInPaper", num3);
+ motionBlurMaterial.SetFloat("_MinVelocity", minVelocity);
+ motionBlurMaterial.SetFloat("_VelocityScale", velocityScale);
+ motionBlurMaterial.SetFloat("_Jitter", jitter);
+ motionBlurMaterial.SetTexture("_NoiseTex", noiseTexture);
+ motionBlurMaterial.SetTexture("_VelTex", temporary);
+ motionBlurMaterial.SetTexture("_NeighbourMaxTex", temporary3);
+ motionBlurMaterial.SetTexture("_TileTexDebug", temporary2);
+ if (preview)
+ {
+ Matrix4x4 worldToCameraMatrix = _camera.worldToCameraMatrix;
+ Matrix4x4 identity = Matrix4x4.identity;
+ identity.SetTRS(previewScale * 0.3333f, Quaternion.identity, Vector3.one);
+ Matrix4x4 gPUProjectionMatrix = GL.GetGPUProjectionMatrix(_camera.projectionMatrix, renderIntoTexture: true);
+ prevViewProjMat = gPUProjectionMatrix * identity * worldToCameraMatrix;
+ motionBlurMaterial.SetMatrix("_PrevViewProj", prevViewProjMat);
+ motionBlurMaterial.SetMatrix("_ToPrevViewProjCombined", prevViewProjMat * matrix4x);
+ }
+ if (filterType == MotionBlurFilter.CameraMotion)
+ {
+ Vector4 zero = Vector4.zero;
+ float num4 = Vector3.Dot(base.transform.up, Vector3.up);
+ Vector3 rhs = prevFramePos - base.transform.position;
+ float magnitude = rhs.magnitude;
+ float num5 = 1f;
+ num5 = Vector3.Angle(base.transform.up, prevFrameUp) / _camera.fieldOfView * ((float)source.width * 0.75f);
+ zero.x = rotationScale * num5;
+ num5 = Vector3.Angle(base.transform.forward, prevFrameForward) / _camera.fieldOfView * ((float)source.width * 0.75f);
+ zero.y = rotationScale * num4 * num5;
+ num5 = Vector3.Angle(base.transform.forward, prevFrameForward) / _camera.fieldOfView * ((float)source.width * 0.75f);
+ zero.z = rotationScale * (1f - num4) * num5;
+ if (magnitude > Mathf.Epsilon && movementScale > Mathf.Epsilon)
+ {
+ zero.w = movementScale * Vector3.Dot(base.transform.forward, rhs) * ((float)source.width * 0.5f);
+ zero.x += movementScale * Vector3.Dot(base.transform.up, rhs) * ((float)source.width * 0.5f);
+ zero.y += movementScale * Vector3.Dot(base.transform.right, rhs) * ((float)source.width * 0.5f);
+ }
+ if (preview)
+ {
+ motionBlurMaterial.SetVector("_BlurDirectionPacked", new Vector4(previewScale.y, previewScale.x, 0f, previewScale.z) * 0.5f * _camera.fieldOfView);
+ }
+ else
+ {
+ motionBlurMaterial.SetVector("_BlurDirectionPacked", zero);
+ }
+ }
+ else
+ {
+ Graphics.Blit(source, temporary, motionBlurMaterial, 0);
+ Camera camera = null;
+ if (excludeLayers.value != 0)
+ {
+ camera = GetTmpCam();
+ }
+ if ((bool)camera && excludeLayers.value != 0 && (bool)replacementClear && replacementClear.isSupported)
+ {
+ camera.targetTexture = temporary;
+ camera.cullingMask = excludeLayers;
+ camera.RenderWithShader(replacementClear, "");
+ }
+ }
+ if (!preview && Time.frameCount != prevFrameCount)
+ {
+ prevFrameCount = Time.frameCount;
+ Remember();
+ }
+ source.filterMode = FilterMode.Bilinear;
+ if (showVelocity)
+ {
+ motionBlurMaterial.SetFloat("_DisplayVelocityScale", showVelocityScale);
+ Graphics.Blit(temporary, destination, motionBlurMaterial, 1);
+ }
+ else if (filterType == MotionBlurFilter.ReconstructionDX11 && !flag)
+ {
+ dx11MotionBlurMaterial.SetFloat("_MinVelocity", minVelocity);
+ dx11MotionBlurMaterial.SetFloat("_VelocityScale", velocityScale);
+ dx11MotionBlurMaterial.SetFloat("_Jitter", jitter);
+ dx11MotionBlurMaterial.SetTexture("_NoiseTex", noiseTexture);
+ dx11MotionBlurMaterial.SetTexture("_VelTex", temporary);
+ dx11MotionBlurMaterial.SetTexture("_NeighbourMaxTex", temporary3);
+ dx11MotionBlurMaterial.SetFloat("_SoftZDistance", Mathf.Max(0.00025f, softZDistance));
+ dx11MotionBlurMaterial.SetFloat("_MaxRadiusOrKInPaper", num3);
+ Graphics.Blit(temporary, temporary2, dx11MotionBlurMaterial, 0);
+ Graphics.Blit(temporary2, temporary3, dx11MotionBlurMaterial, 1);
+ Graphics.Blit(source, destination, dx11MotionBlurMaterial, 2);
+ }
+ else if (filterType == MotionBlurFilter.Reconstruction || flag)
+ {
+ motionBlurMaterial.SetFloat("_SoftZDistance", Mathf.Max(0.00025f, softZDistance));
+ Graphics.Blit(temporary, temporary2, motionBlurMaterial, 2);
+ Graphics.Blit(temporary2, temporary3, motionBlurMaterial, 3);
+ Graphics.Blit(source, destination, motionBlurMaterial, 4);
+ }
+ else if (filterType == MotionBlurFilter.CameraMotion)
+ {
+ Graphics.Blit(source, destination, motionBlurMaterial, 6);
+ }
+ else if (filterType == MotionBlurFilter.ReconstructionDisc)
+ {
+ motionBlurMaterial.SetFloat("_SoftZDistance", Mathf.Max(0.00025f, softZDistance));
+ Graphics.Blit(temporary, temporary2, motionBlurMaterial, 2);
+ Graphics.Blit(temporary2, temporary3, motionBlurMaterial, 3);
+ Graphics.Blit(source, destination, motionBlurMaterial, 7);
+ }
+ else
+ {
+ Graphics.Blit(source, destination, motionBlurMaterial, 5);
+ }
+ RenderTexture.ReleaseTemporary(temporary);
+ RenderTexture.ReleaseTemporary(temporary2);
+ RenderTexture.ReleaseTemporary(temporary3);
+ }
+
+ private void Remember()
+ {
+ prevViewProjMat = currentViewProjMat;
+ prevFrameForward = base.transform.forward;
+ prevFrameUp = base.transform.up;
+ prevFramePos = base.transform.position;
+ prevStereoViewProjMat[0] = currentStereoViewProjMat[0];
+ prevStereoViewProjMat[1] = currentStereoViewProjMat[1];
+ }
+
+ private Camera GetTmpCam()
+ {
+ if (tmpCam == null)
+ {
+ string text = "_" + _camera.name + "_MotionBlurTmpCam";
+ GameObject gameObject = GameObject.Find(text);
+ if (null == gameObject)
+ {
+ tmpCam = new GameObject(text, typeof(Camera));
+ }
+ else
+ {
+ tmpCam = gameObject;
+ }
+ }
+ tmpCam.hideFlags = HideFlags.DontSave;
+ tmpCam.transform.position = _camera.transform.position;
+ tmpCam.transform.rotation = _camera.transform.rotation;
+ tmpCam.transform.localScale = _camera.transform.localScale;
+ tmpCam.GetComponent<Camera>().CopyFrom(_camera);
+ tmpCam.GetComponent<Camera>().enabled = false;
+ tmpCam.GetComponent<Camera>().depthTextureMode = DepthTextureMode.None;
+ tmpCam.GetComponent<Camera>().clearFlags = CameraClearFlags.Nothing;
+ return tmpCam.GetComponent<Camera>();
+ }
+
+ private void StartFrame()
+ {
+ prevFramePos = Vector3.Slerp(prevFramePos, base.transform.position, 0.75f);
+ }
+
+ private static int divRoundUp(int x, int d)
+ {
+ return (x + d - 1) / d;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionCurves.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionCurves.cs
new file mode 100644
index 0000000..1242f66
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionCurves.cs
@@ -0,0 +1,180 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Color Correction (Curves, Saturation)")]
+public class ColorCorrectionCurves : PostEffectsBase
+{
+ public enum ColorCorrectionMode
+ {
+ Simple,
+ Advanced
+ }
+
+ public AnimationCurve redChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public AnimationCurve greenChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public AnimationCurve blueChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public bool useDepthCorrection;
+
+ public AnimationCurve zCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public AnimationCurve depthRedChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public AnimationCurve depthGreenChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ public AnimationCurve depthBlueChannel = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
+
+ private Material ccMaterial;
+
+ private Material ccDepthMaterial;
+
+ private Material selectiveCcMaterial;
+
+ private Texture2D rgbChannelTex;
+
+ private Texture2D rgbDepthChannelTex;
+
+ private Texture2D zCurveTex;
+
+ public float saturation = 1f;
+
+ public bool selectiveCc;
+
+ public Color selectiveFromColor = Color.white;
+
+ public Color selectiveToColor = Color.white;
+
+ public ColorCorrectionMode mode;
+
+ public bool updateTextures = true;
+
+ public Shader colorCorrectionCurvesShader;
+
+ public Shader simpleColorCorrectionCurvesShader;
+
+ public Shader colorCorrectionSelectiveShader;
+
+ private bool updateTexturesOnStartup = true;
+
+ private new void Start()
+ {
+ base.Start();
+ updateTexturesOnStartup = true;
+ }
+
+ private void Awake()
+ {
+ }
+
+ public override bool CheckResources()
+ {
+ CheckSupport(mode == ColorCorrectionMode.Advanced);
+ ccMaterial = CheckShaderAndCreateMaterial(simpleColorCorrectionCurvesShader, ccMaterial);
+ ccDepthMaterial = CheckShaderAndCreateMaterial(colorCorrectionCurvesShader, ccDepthMaterial);
+ selectiveCcMaterial = CheckShaderAndCreateMaterial(colorCorrectionSelectiveShader, selectiveCcMaterial);
+ if (!rgbChannelTex)
+ {
+ rgbChannelTex = new Texture2D(256, 4, TextureFormat.ARGB32, mipChain: false, linear: true);
+ }
+ if (!rgbDepthChannelTex)
+ {
+ rgbDepthChannelTex = new Texture2D(256, 4, TextureFormat.ARGB32, mipChain: false, linear: true);
+ }
+ if (!zCurveTex)
+ {
+ zCurveTex = new Texture2D(256, 1, TextureFormat.ARGB32, mipChain: false, linear: true);
+ }
+ rgbChannelTex.hideFlags = HideFlags.DontSave;
+ rgbDepthChannelTex.hideFlags = HideFlags.DontSave;
+ zCurveTex.hideFlags = HideFlags.DontSave;
+ rgbChannelTex.wrapMode = TextureWrapMode.Clamp;
+ rgbDepthChannelTex.wrapMode = TextureWrapMode.Clamp;
+ zCurveTex.wrapMode = TextureWrapMode.Clamp;
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ public void UpdateParameters()
+ {
+ CheckResources();
+ if (redChannel != null && greenChannel != null && blueChannel != null)
+ {
+ for (float num = 0f; num <= 1f; num += 0.003921569f)
+ {
+ float num2 = Mathf.Clamp(redChannel.Evaluate(num), 0f, 1f);
+ float num3 = Mathf.Clamp(greenChannel.Evaluate(num), 0f, 1f);
+ float num4 = Mathf.Clamp(blueChannel.Evaluate(num), 0f, 1f);
+ rgbChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 0, new Color(num2, num2, num2));
+ rgbChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 1, new Color(num3, num3, num3));
+ rgbChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 2, new Color(num4, num4, num4));
+ float num5 = Mathf.Clamp(zCurve.Evaluate(num), 0f, 1f);
+ zCurveTex.SetPixel((int)Mathf.Floor(num * 255f), 0, new Color(num5, num5, num5));
+ num2 = Mathf.Clamp(depthRedChannel.Evaluate(num), 0f, 1f);
+ num3 = Mathf.Clamp(depthGreenChannel.Evaluate(num), 0f, 1f);
+ num4 = Mathf.Clamp(depthBlueChannel.Evaluate(num), 0f, 1f);
+ rgbDepthChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 0, new Color(num2, num2, num2));
+ rgbDepthChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 1, new Color(num3, num3, num3));
+ rgbDepthChannelTex.SetPixel((int)Mathf.Floor(num * 255f), 2, new Color(num4, num4, num4));
+ }
+ rgbChannelTex.Apply();
+ rgbDepthChannelTex.Apply();
+ zCurveTex.Apply();
+ }
+ }
+
+ private void UpdateTextures()
+ {
+ UpdateParameters();
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ if (updateTexturesOnStartup)
+ {
+ UpdateParameters();
+ updateTexturesOnStartup = false;
+ }
+ if (useDepthCorrection)
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+ }
+ RenderTexture renderTexture = destination;
+ if (selectiveCc)
+ {
+ renderTexture = RenderTexture.GetTemporary(source.width, source.height);
+ }
+ if (useDepthCorrection)
+ {
+ ccDepthMaterial.SetTexture("_RgbTex", rgbChannelTex);
+ ccDepthMaterial.SetTexture("_ZCurve", zCurveTex);
+ ccDepthMaterial.SetTexture("_RgbDepthTex", rgbDepthChannelTex);
+ ccDepthMaterial.SetFloat("_Saturation", saturation);
+ Graphics.Blit(source, renderTexture, ccDepthMaterial);
+ }
+ else
+ {
+ ccMaterial.SetTexture("_RgbTex", rgbChannelTex);
+ ccMaterial.SetFloat("_Saturation", saturation);
+ Graphics.Blit(source, renderTexture, ccMaterial);
+ }
+ if (selectiveCc)
+ {
+ selectiveCcMaterial.SetColor("selColor", selectiveFromColor);
+ selectiveCcMaterial.SetColor("targetColor", selectiveToColor);
+ Graphics.Blit(renderTexture, destination, selectiveCcMaterial);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionLookup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionLookup.cs
new file mode 100644
index 0000000..07ce1e3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionLookup.cs
@@ -0,0 +1,142 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Color Correction (3D Lookup Texture)")]
+public class ColorCorrectionLookup : PostEffectsBase
+{
+ public Shader shader;
+
+ private Material material;
+
+ public Texture3D converted3DLut;
+
+ public string basedOnTempTex = "";
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ material = CheckShaderAndCreateMaterial(shader, material);
+ if (!isSupported || !SystemInfo.supports3DTextures)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnDisable()
+ {
+ if ((bool)material)
+ {
+ Object.DestroyImmediate(material);
+ material = null;
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if ((bool)converted3DLut)
+ {
+ Object.DestroyImmediate(converted3DLut);
+ }
+ converted3DLut = null;
+ }
+
+ public void SetIdentityLut()
+ {
+ int num = 16;
+ Color[] array = new Color[num * num * num];
+ float num2 = 1f / (1f * (float)num - 1f);
+ for (int i = 0; i < num; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ for (int k = 0; k < num; k++)
+ {
+ array[i + j * num + k * num * num] = new Color((float)i * 1f * num2, (float)j * 1f * num2, (float)k * 1f * num2, 1f);
+ }
+ }
+ }
+ if ((bool)converted3DLut)
+ {
+ Object.DestroyImmediate(converted3DLut);
+ }
+ converted3DLut = new Texture3D(num, num, num, TextureFormat.ARGB32, mipChain: false);
+ converted3DLut.SetPixels(array);
+ converted3DLut.Apply();
+ basedOnTempTex = "";
+ }
+
+ public bool ValidDimensions(Texture2D tex2d)
+ {
+ if (!tex2d)
+ {
+ return false;
+ }
+ if (tex2d.height != Mathf.FloorToInt(Mathf.Sqrt(tex2d.width)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public void Convert(Texture2D temp2DTex, string path)
+ {
+ if ((bool)temp2DTex)
+ {
+ int num = temp2DTex.width * temp2DTex.height;
+ num = temp2DTex.height;
+ if (!ValidDimensions(temp2DTex))
+ {
+ Debug.LogWarning("The given 2D texture " + temp2DTex.name + " cannot be used as a 3D LUT.");
+ basedOnTempTex = "";
+ return;
+ }
+ Color[] pixels = temp2DTex.GetPixels();
+ Color[] array = new Color[pixels.Length];
+ for (int i = 0; i < num; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ for (int k = 0; k < num; k++)
+ {
+ int num2 = num - j - 1;
+ array[i + j * num + k * num * num] = pixels[k * num + i + num2 * num * num];
+ }
+ }
+ }
+ if ((bool)converted3DLut)
+ {
+ Object.DestroyImmediate(converted3DLut);
+ }
+ converted3DLut = new Texture3D(num, num, num, TextureFormat.ARGB32, mipChain: false);
+ converted3DLut.SetPixels(array);
+ converted3DLut.Apply();
+ basedOnTempTex = path;
+ }
+ else
+ {
+ Debug.LogError("Couldn't color correct with 3D LUT texture. Image Effect will be disabled.");
+ }
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources() || !SystemInfo.supports3DTextures)
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ if (converted3DLut == null)
+ {
+ SetIdentityLut();
+ }
+ int width = converted3DLut.width;
+ converted3DLut.wrapMode = TextureWrapMode.Clamp;
+ material.SetFloat("_Scale", (float)(width - 1) / (1f * (float)width));
+ material.SetFloat("_Offset", 1f / (2f * (float)width));
+ material.SetTexture("_ClutTex", converted3DLut);
+ Graphics.Blit(source, destination, material, (QualitySettings.activeColorSpace == ColorSpace.Linear) ? 1 : 0);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionRamp.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionRamp.cs
new file mode 100644
index 0000000..82caf1f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ColorCorrectionRamp.cs
@@ -0,0 +1,16 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Color Correction (Ramp)")]
+public class ColorCorrectionRamp : ImageEffectBase
+{
+ public Texture textureRamp;
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ base.material.SetTexture("_RampTex", textureRamp);
+ Graphics.Blit(source, destination, base.material);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastEnhance.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastEnhance.cs
new file mode 100644
index 0000000..8001766
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastEnhance.cs
@@ -0,0 +1,67 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Color Adjustments/Contrast Enhance (Unsharp Mask)")]
+public class ContrastEnhance : PostEffectsBase
+{
+ [Range(0f, 1f)]
+ public float intensity = 0.5f;
+
+ [Range(0f, 0.999f)]
+ public float threshold;
+
+ private Material separableBlurMaterial;
+
+ private Material contrastCompositeMaterial;
+
+ [Range(0f, 1f)]
+ public float blurSpread = 1f;
+
+ public Shader separableBlurShader;
+
+ public Shader contrastCompositeShader;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ contrastCompositeMaterial = CheckShaderAndCreateMaterial(contrastCompositeShader, contrastCompositeMaterial);
+ separableBlurMaterial = CheckShaderAndCreateMaterial(separableBlurShader, separableBlurMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ int width = source.width;
+ int height = source.height;
+ RenderTexture temporary = RenderTexture.GetTemporary(width / 2, height / 2, 0);
+ Graphics.Blit(source, temporary);
+ RenderTexture temporary2 = RenderTexture.GetTemporary(width / 4, height / 4, 0);
+ Graphics.Blit(temporary, temporary2);
+ RenderTexture.ReleaseTemporary(temporary);
+ separableBlurMaterial.SetVector("offsets", new Vector4(0f, blurSpread * 1f / (float)temporary2.height, 0f, 0f));
+ RenderTexture temporary3 = RenderTexture.GetTemporary(width / 4, height / 4, 0);
+ Graphics.Blit(temporary2, temporary3, separableBlurMaterial);
+ RenderTexture.ReleaseTemporary(temporary2);
+ separableBlurMaterial.SetVector("offsets", new Vector4(blurSpread * 1f / (float)temporary2.width, 0f, 0f, 0f));
+ temporary2 = RenderTexture.GetTemporary(width / 4, height / 4, 0);
+ Graphics.Blit(temporary3, temporary2, separableBlurMaterial);
+ RenderTexture.ReleaseTemporary(temporary3);
+ contrastCompositeMaterial.SetTexture("_MainTexBlurred", temporary2);
+ contrastCompositeMaterial.SetFloat("intensity", intensity);
+ contrastCompositeMaterial.SetFloat("threshold", threshold);
+ Graphics.Blit(source, destination, contrastCompositeMaterial);
+ RenderTexture.ReleaseTemporary(temporary2);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastStretch.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastStretch.cs
new file mode 100644
index 0000000..a843a7d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ContrastStretch.cs
@@ -0,0 +1,178 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Contrast Stretch")]
+public class ContrastStretch : MonoBehaviour
+{
+ [Range(0.0001f, 1f)]
+ public float adaptationSpeed = 0.02f;
+
+ [Range(0f, 1f)]
+ public float limitMinimum = 0.2f;
+
+ [Range(0f, 1f)]
+ public float limitMaximum = 0.6f;
+
+ private RenderTexture[] adaptRenderTex = new RenderTexture[2];
+
+ private int curAdaptIndex;
+
+ public Shader shaderLum;
+
+ private Material m_materialLum;
+
+ public Shader shaderReduce;
+
+ private Material m_materialReduce;
+
+ public Shader shaderAdapt;
+
+ private Material m_materialAdapt;
+
+ public Shader shaderApply;
+
+ private Material m_materialApply;
+
+ protected Material materialLum
+ {
+ get
+ {
+ if (m_materialLum == null)
+ {
+ m_materialLum = new Material(shaderLum);
+ m_materialLum.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return m_materialLum;
+ }
+ }
+
+ protected Material materialReduce
+ {
+ get
+ {
+ if (m_materialReduce == null)
+ {
+ m_materialReduce = new Material(shaderReduce);
+ m_materialReduce.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return m_materialReduce;
+ }
+ }
+
+ protected Material materialAdapt
+ {
+ get
+ {
+ if (m_materialAdapt == null)
+ {
+ m_materialAdapt = new Material(shaderAdapt);
+ m_materialAdapt.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return m_materialAdapt;
+ }
+ }
+
+ protected Material materialApply
+ {
+ get
+ {
+ if (m_materialApply == null)
+ {
+ m_materialApply = new Material(shaderApply);
+ m_materialApply.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return m_materialApply;
+ }
+ }
+
+ private void Start()
+ {
+ if (!SystemInfo.supportsImageEffects)
+ {
+ base.enabled = false;
+ }
+ else if (!shaderAdapt.isSupported || !shaderApply.isSupported || !shaderLum.isSupported || !shaderReduce.isSupported)
+ {
+ base.enabled = false;
+ }
+ }
+
+ private void OnEnable()
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ if (!adaptRenderTex[i])
+ {
+ adaptRenderTex[i] = new RenderTexture(1, 1, 0);
+ adaptRenderTex[i].hideFlags = HideFlags.HideAndDontSave;
+ }
+ }
+ }
+
+ private void OnDisable()
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ Object.DestroyImmediate(adaptRenderTex[i]);
+ adaptRenderTex[i] = null;
+ }
+ if ((bool)m_materialLum)
+ {
+ Object.DestroyImmediate(m_materialLum);
+ }
+ if ((bool)m_materialReduce)
+ {
+ Object.DestroyImmediate(m_materialReduce);
+ }
+ if ((bool)m_materialAdapt)
+ {
+ Object.DestroyImmediate(m_materialAdapt);
+ }
+ if ((bool)m_materialApply)
+ {
+ Object.DestroyImmediate(m_materialApply);
+ }
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ RenderTexture renderTexture = RenderTexture.GetTemporary(source.width / 1, source.height / 1);
+ Graphics.Blit(source, renderTexture, materialLum);
+ while (renderTexture.width > 1 || renderTexture.height > 1)
+ {
+ int num = renderTexture.width / 2;
+ if (num < 1)
+ {
+ num = 1;
+ }
+ int num2 = renderTexture.height / 2;
+ if (num2 < 1)
+ {
+ num2 = 1;
+ }
+ RenderTexture temporary = RenderTexture.GetTemporary(num, num2);
+ Graphics.Blit(renderTexture, temporary, materialReduce);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ }
+ CalculateAdaptation(renderTexture);
+ materialApply.SetTexture("_AdaptTex", adaptRenderTex[curAdaptIndex]);
+ Graphics.Blit(source, destination, materialApply);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+
+ private void CalculateAdaptation(Texture curTexture)
+ {
+ int num = curAdaptIndex;
+ curAdaptIndex = (curAdaptIndex + 1) % 2;
+ float value = 1f - Mathf.Pow(1f - adaptationSpeed, 30f * Time.deltaTime);
+ value = Mathf.Clamp(value, 0.01f, 1f);
+ materialAdapt.SetTexture("_CurTex", curTexture);
+ materialAdapt.SetVector("_AdaptParams", new Vector4(value, limitMinimum, limitMaximum, 0f));
+ Graphics.SetRenderTarget(adaptRenderTex[curAdaptIndex]);
+ GL.Clear(clearDepth: false, clearColor: true, Color.black);
+ Graphics.Blit(adaptRenderTex[num], adaptRenderTex[curAdaptIndex], materialAdapt);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CreaseShading.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CreaseShading.cs
new file mode 100644
index 0000000..237e56d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/CreaseShading.cs
@@ -0,0 +1,76 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Edge Detection/Crease Shading")]
+public class CreaseShading : PostEffectsBase
+{
+ public float intensity = 0.5f;
+
+ public int softness = 1;
+
+ public float spread = 1f;
+
+ public Shader blurShader;
+
+ private Material blurMaterial;
+
+ public Shader depthFetchShader;
+
+ private Material depthFetchMaterial;
+
+ public Shader creaseApplyShader;
+
+ private Material creaseApplyMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ blurMaterial = CheckShaderAndCreateMaterial(blurShader, blurMaterial);
+ depthFetchMaterial = CheckShaderAndCreateMaterial(depthFetchShader, depthFetchMaterial);
+ creaseApplyMaterial = CheckShaderAndCreateMaterial(creaseApplyShader, creaseApplyMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ int width = source.width;
+ int height = source.height;
+ float num = 1f * (float)width / (1f * (float)height);
+ float num2 = 0.001953125f;
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0);
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width / 2, height / 2, 0);
+ Graphics.Blit(source, temporary, depthFetchMaterial);
+ Graphics.Blit(temporary, renderTexture);
+ for (int i = 0; i < softness; i++)
+ {
+ RenderTexture temporary2 = RenderTexture.GetTemporary(width / 2, height / 2, 0);
+ blurMaterial.SetVector("offsets", new Vector4(0f, spread * num2, 0f, 0f));
+ Graphics.Blit(renderTexture, temporary2, blurMaterial);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary2;
+ temporary2 = RenderTexture.GetTemporary(width / 2, height / 2, 0);
+ blurMaterial.SetVector("offsets", new Vector4(spread * num2 / num, 0f, 0f, 0f));
+ Graphics.Blit(renderTexture, temporary2, blurMaterial);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary2;
+ }
+ creaseApplyMaterial.SetTexture("_HrDepthTex", temporary);
+ creaseApplyMaterial.SetTexture("_LrDepthTex", renderTexture);
+ creaseApplyMaterial.SetFloat("intensity", intensity);
+ Graphics.Blit(source, destination, creaseApplyMaterial);
+ RenderTexture.ReleaseTemporary(temporary);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfField.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfField.cs
new file mode 100644
index 0000000..8b9d11a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfField.cs
@@ -0,0 +1,350 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Camera/Depth of Field (Lens Blur, Scatter, DX11)")]
+public class DepthOfField : PostEffectsBase
+{
+ public enum BlurType
+ {
+ DiscBlur,
+ DX11
+ }
+
+ public enum BlurSampleCount
+ {
+ Low,
+ Medium,
+ High
+ }
+
+ public bool visualizeFocus;
+
+ public float focalLength = 10f;
+
+ public float focalSize = 0.05f;
+
+ public float aperture = 0.5f;
+
+ public Transform focalTransform;
+
+ public float maxBlurSize = 2f;
+
+ public bool highResolution;
+
+ public BlurType blurType;
+
+ public BlurSampleCount blurSampleCount = BlurSampleCount.High;
+
+ public bool nearBlur;
+
+ public float foregroundOverlap = 1f;
+
+ public Shader dofHdrShader;
+
+ private Material dofHdrMaterial;
+
+ public Shader dx11BokehShader;
+
+ private Material dx11bokehMaterial;
+
+ public float dx11BokehThreshold = 0.5f;
+
+ public float dx11SpawnHeuristic = 0.0875f;
+
+ public Texture2D dx11BokehTexture;
+
+ public float dx11BokehScale = 1.2f;
+
+ public float dx11BokehIntensity = 2.5f;
+
+ private float focalDistance01 = 10f;
+
+ private ComputeBuffer cbDrawArgs;
+
+ private ComputeBuffer cbPoints;
+
+ private float internalBlurWidth = 1f;
+
+ private Camera cachedCamera;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ dofHdrMaterial = CheckShaderAndCreateMaterial(dofHdrShader, dofHdrMaterial);
+ if (supportDX11 && blurType == BlurType.DX11)
+ {
+ dx11bokehMaterial = CheckShaderAndCreateMaterial(dx11BokehShader, dx11bokehMaterial);
+ CreateComputeResources();
+ }
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnEnable()
+ {
+ cachedCamera = GetComponent<Camera>();
+ cachedCamera.depthTextureMode |= DepthTextureMode.Depth;
+ }
+
+ private void OnDisable()
+ {
+ ReleaseComputeResources();
+ if ((bool)dofHdrMaterial)
+ {
+ Object.DestroyImmediate(dofHdrMaterial);
+ }
+ dofHdrMaterial = null;
+ if ((bool)dx11bokehMaterial)
+ {
+ Object.DestroyImmediate(dx11bokehMaterial);
+ }
+ dx11bokehMaterial = null;
+ }
+
+ private void ReleaseComputeResources()
+ {
+ if (cbDrawArgs != null)
+ {
+ cbDrawArgs.Release();
+ }
+ cbDrawArgs = null;
+ if (cbPoints != null)
+ {
+ cbPoints.Release();
+ }
+ cbPoints = null;
+ }
+
+ private void CreateComputeResources()
+ {
+ if (cbDrawArgs == null)
+ {
+ cbDrawArgs = new ComputeBuffer(1, 16, ComputeBufferType.DrawIndirect);
+ int[] data = new int[4] { 0, 1, 0, 0 };
+ cbDrawArgs.SetData(data);
+ }
+ if (cbPoints == null)
+ {
+ cbPoints = new ComputeBuffer(90000, 28, ComputeBufferType.Append);
+ }
+ }
+
+ private float FocalDistance01(float worldDist)
+ {
+ return cachedCamera.WorldToViewportPoint((worldDist - cachedCamera.nearClipPlane) * cachedCamera.transform.forward + cachedCamera.transform.position).z / (cachedCamera.farClipPlane - cachedCamera.nearClipPlane);
+ }
+
+ private void WriteCoc(RenderTexture fromTo, bool fgDilate)
+ {
+ dofHdrMaterial.SetTexture("_FgOverlap", null);
+ if (nearBlur && fgDilate)
+ {
+ int width = fromTo.width / 2;
+ int height = fromTo.height / 2;
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, fromTo.format);
+ Graphics.Blit(fromTo, temporary, dofHdrMaterial, 4);
+ float num = internalBlurWidth * foregroundOverlap;
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, num, 0f, num));
+ RenderTexture temporary2 = RenderTexture.GetTemporary(width, height, 0, fromTo.format);
+ Graphics.Blit(temporary, temporary2, dofHdrMaterial, 2);
+ RenderTexture.ReleaseTemporary(temporary);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(num, 0f, 0f, num));
+ temporary = RenderTexture.GetTemporary(width, height, 0, fromTo.format);
+ Graphics.Blit(temporary2, temporary, dofHdrMaterial, 2);
+ RenderTexture.ReleaseTemporary(temporary2);
+ dofHdrMaterial.SetTexture("_FgOverlap", temporary);
+ fromTo.MarkRestoreExpected();
+ Graphics.Blit(fromTo, fromTo, dofHdrMaterial, 13);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ else
+ {
+ fromTo.MarkRestoreExpected();
+ Graphics.Blit(fromTo, fromTo, dofHdrMaterial, 0);
+ }
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ float num = (float)source.width / 1024f;
+ if (aperture < 0f)
+ {
+ aperture = 0f;
+ }
+ if (maxBlurSize < 0.1f)
+ {
+ maxBlurSize = 0.1f;
+ }
+ focalSize = Mathf.Clamp(focalSize, 0f, 2f);
+ internalBlurWidth = Mathf.Max(maxBlurSize, 0f) * num;
+ focalDistance01 = (focalTransform ? (cachedCamera.WorldToViewportPoint(focalTransform.position).z / cachedCamera.farClipPlane) : FocalDistance01(focalLength));
+ dofHdrMaterial.SetVector("_CurveParams", new Vector4(1f, focalSize, 1f / (1f - aperture) - 1f, focalDistance01));
+ RenderTexture renderTexture = null;
+ RenderTexture renderTexture2 = null;
+ RenderTexture renderTexture3 = null;
+ RenderTexture renderTexture4 = null;
+ float num2 = internalBlurWidth * foregroundOverlap;
+ if (visualizeFocus)
+ {
+ WriteCoc(source, fgDilate: true);
+ Graphics.Blit(source, destination, dofHdrMaterial, 16);
+ }
+ else if (blurType == BlurType.DX11 && (bool)dx11bokehMaterial)
+ {
+ if (highResolution)
+ {
+ internalBlurWidth = ((internalBlurWidth < 0.1f) ? 0.1f : internalBlurWidth);
+ num2 = internalBlurWidth * foregroundOverlap;
+ renderTexture = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
+ WriteCoc(source, fgDilate: false);
+ renderTexture3 = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ renderTexture4 = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ Graphics.Blit(source, renderTexture3, dofHdrMaterial, 15);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, 1.5f, 0f, 1.5f));
+ Graphics.Blit(renderTexture3, renderTexture4, dofHdrMaterial, 19);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(1.5f, 0f, 0f, 1.5f));
+ Graphics.Blit(renderTexture4, renderTexture3, dofHdrMaterial, 19);
+ if (nearBlur)
+ {
+ Graphics.Blit(source, renderTexture4, dofHdrMaterial, 4);
+ }
+ dx11bokehMaterial.SetTexture("_BlurredColor", renderTexture3);
+ dx11bokehMaterial.SetFloat("_SpawnHeuristic", dx11SpawnHeuristic);
+ dx11bokehMaterial.SetVector("_BokehParams", new Vector4(dx11BokehScale, dx11BokehIntensity, Mathf.Clamp(dx11BokehThreshold, 0.005f, 4f), internalBlurWidth));
+ dx11bokehMaterial.SetTexture("_FgCocMask", nearBlur ? renderTexture4 : null);
+ Graphics.SetRandomWriteTarget(1, cbPoints);
+ Graphics.Blit(source, renderTexture, dx11bokehMaterial, 0);
+ Graphics.ClearRandomWriteTargets();
+ if (nearBlur)
+ {
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, num2, 0f, num2));
+ Graphics.Blit(renderTexture4, renderTexture3, dofHdrMaterial, 2);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(num2, 0f, 0f, num2));
+ Graphics.Blit(renderTexture3, renderTexture4, dofHdrMaterial, 2);
+ Graphics.Blit(renderTexture4, renderTexture, dofHdrMaterial, 3);
+ }
+ Graphics.Blit(renderTexture, temporary, dofHdrMaterial, 20);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(internalBlurWidth, 0f, 0f, internalBlurWidth));
+ Graphics.Blit(renderTexture, source, dofHdrMaterial, 5);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, internalBlurWidth, 0f, internalBlurWidth));
+ Graphics.Blit(source, temporary, dofHdrMaterial, 21);
+ Graphics.SetRenderTarget(temporary);
+ ComputeBuffer.CopyCount(cbPoints, cbDrawArgs, 0);
+ dx11bokehMaterial.SetBuffer("pointBuffer", cbPoints);
+ dx11bokehMaterial.SetTexture("_MainTex", dx11BokehTexture);
+ dx11bokehMaterial.SetVector("_Screen", new Vector3(1f / (1f * (float)source.width), 1f / (1f * (float)source.height), internalBlurWidth));
+ dx11bokehMaterial.SetPass(2);
+ Graphics.DrawProceduralIndirectNow(MeshTopology.Points, cbDrawArgs);
+ Graphics.Blit(temporary, destination);
+ RenderTexture.ReleaseTemporary(temporary);
+ RenderTexture.ReleaseTemporary(renderTexture3);
+ RenderTexture.ReleaseTemporary(renderTexture4);
+ }
+ else
+ {
+ renderTexture = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ renderTexture2 = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ num2 = internalBlurWidth * foregroundOverlap;
+ WriteCoc(source, fgDilate: false);
+ source.filterMode = FilterMode.Bilinear;
+ Graphics.Blit(source, renderTexture, dofHdrMaterial, 6);
+ renderTexture3 = RenderTexture.GetTemporary(renderTexture.width >> 1, renderTexture.height >> 1, 0, renderTexture.format);
+ renderTexture4 = RenderTexture.GetTemporary(renderTexture.width >> 1, renderTexture.height >> 1, 0, renderTexture.format);
+ Graphics.Blit(renderTexture, renderTexture3, dofHdrMaterial, 15);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, 1.5f, 0f, 1.5f));
+ Graphics.Blit(renderTexture3, renderTexture4, dofHdrMaterial, 19);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(1.5f, 0f, 0f, 1.5f));
+ Graphics.Blit(renderTexture4, renderTexture3, dofHdrMaterial, 19);
+ RenderTexture renderTexture5 = null;
+ if (nearBlur)
+ {
+ renderTexture5 = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ Graphics.Blit(source, renderTexture5, dofHdrMaterial, 4);
+ }
+ dx11bokehMaterial.SetTexture("_BlurredColor", renderTexture3);
+ dx11bokehMaterial.SetFloat("_SpawnHeuristic", dx11SpawnHeuristic);
+ dx11bokehMaterial.SetVector("_BokehParams", new Vector4(dx11BokehScale, dx11BokehIntensity, Mathf.Clamp(dx11BokehThreshold, 0.005f, 4f), internalBlurWidth));
+ dx11bokehMaterial.SetTexture("_FgCocMask", renderTexture5);
+ Graphics.SetRandomWriteTarget(1, cbPoints);
+ Graphics.Blit(renderTexture, renderTexture2, dx11bokehMaterial, 0);
+ Graphics.ClearRandomWriteTargets();
+ RenderTexture.ReleaseTemporary(renderTexture3);
+ RenderTexture.ReleaseTemporary(renderTexture4);
+ if (nearBlur)
+ {
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, num2, 0f, num2));
+ Graphics.Blit(renderTexture5, renderTexture, dofHdrMaterial, 2);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(num2, 0f, 0f, num2));
+ Graphics.Blit(renderTexture, renderTexture5, dofHdrMaterial, 2);
+ Graphics.Blit(renderTexture5, renderTexture2, dofHdrMaterial, 3);
+ }
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(internalBlurWidth, 0f, 0f, internalBlurWidth));
+ Graphics.Blit(renderTexture2, renderTexture, dofHdrMaterial, 5);
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, internalBlurWidth, 0f, internalBlurWidth));
+ Graphics.Blit(renderTexture, renderTexture2, dofHdrMaterial, 5);
+ Graphics.SetRenderTarget(renderTexture2);
+ ComputeBuffer.CopyCount(cbPoints, cbDrawArgs, 0);
+ dx11bokehMaterial.SetBuffer("pointBuffer", cbPoints);
+ dx11bokehMaterial.SetTexture("_MainTex", dx11BokehTexture);
+ dx11bokehMaterial.SetVector("_Screen", new Vector3(1f / (1f * (float)renderTexture2.width), 1f / (1f * (float)renderTexture2.height), internalBlurWidth));
+ dx11bokehMaterial.SetPass(1);
+ Graphics.DrawProceduralIndirectNow(MeshTopology.Points, cbDrawArgs);
+ dofHdrMaterial.SetTexture("_LowRez", renderTexture2);
+ dofHdrMaterial.SetTexture("_FgOverlap", renderTexture5);
+ dofHdrMaterial.SetVector("_Offsets", 1f * (float)source.width / (1f * (float)renderTexture2.width) * internalBlurWidth * Vector4.one);
+ Graphics.Blit(source, destination, dofHdrMaterial, 9);
+ if ((bool)renderTexture5)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture5);
+ }
+ }
+ }
+ else
+ {
+ source.filterMode = FilterMode.Bilinear;
+ if (highResolution)
+ {
+ internalBlurWidth *= 2f;
+ }
+ WriteCoc(source, fgDilate: true);
+ renderTexture = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ renderTexture2 = RenderTexture.GetTemporary(source.width >> 1, source.height >> 1, 0, source.format);
+ int pass = ((blurSampleCount == BlurSampleCount.High || blurSampleCount == BlurSampleCount.Medium) ? 17 : 11);
+ if (highResolution)
+ {
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, internalBlurWidth, 0.025f, internalBlurWidth));
+ Graphics.Blit(source, destination, dofHdrMaterial, pass);
+ }
+ else
+ {
+ dofHdrMaterial.SetVector("_Offsets", new Vector4(0f, internalBlurWidth, 0.1f, internalBlurWidth));
+ Graphics.Blit(source, renderTexture, dofHdrMaterial, 6);
+ Graphics.Blit(renderTexture, renderTexture2, dofHdrMaterial, pass);
+ dofHdrMaterial.SetTexture("_LowRez", renderTexture2);
+ dofHdrMaterial.SetTexture("_FgOverlap", null);
+ dofHdrMaterial.SetVector("_Offsets", Vector4.one * (1f * (float)source.width / (1f * (float)renderTexture2.width)) * internalBlurWidth);
+ Graphics.Blit(source, destination, dofHdrMaterial, (blurSampleCount == BlurSampleCount.High) ? 18 : 12);
+ }
+ }
+ if ((bool)renderTexture)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+ if ((bool)renderTexture2)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture2);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfFieldDeprecated.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfFieldDeprecated.cs
new file mode 100644
index 0000000..9c2dc42
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/DepthOfFieldDeprecated.cs
@@ -0,0 +1,451 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Camera/Depth of Field (deprecated)")]
+public class DepthOfFieldDeprecated : PostEffectsBase
+{
+ public enum Dof34QualitySetting
+ {
+ OnlyBackground = 1,
+ BackgroundAndForeground
+ }
+
+ public enum DofResolution
+ {
+ High = 2,
+ Medium,
+ Low
+ }
+
+ public enum DofBlurriness
+ {
+ Low = 1,
+ High = 2,
+ VeryHigh = 4
+ }
+
+ public enum BokehDestination
+ {
+ Background = 1,
+ Foreground,
+ BackgroundAndForeground
+ }
+
+ private static int SMOOTH_DOWNSAMPLE_PASS = 6;
+
+ private static float BOKEH_EXTRA_BLUR = 2f;
+
+ public Dof34QualitySetting quality = Dof34QualitySetting.OnlyBackground;
+
+ public DofResolution resolution = DofResolution.Low;
+
+ public bool simpleTweakMode = true;
+
+ public float focalPoint = 1f;
+
+ public float smoothness = 0.5f;
+
+ public float focalZDistance;
+
+ public float focalZStartCurve = 1f;
+
+ public float focalZEndCurve = 1f;
+
+ private float focalStartCurve = 2f;
+
+ private float focalEndCurve = 2f;
+
+ private float focalDistance01 = 0.1f;
+
+ public Transform objectFocus;
+
+ public float focalSize;
+
+ public DofBlurriness bluriness = DofBlurriness.High;
+
+ public float maxBlurSpread = 1.75f;
+
+ public float foregroundBlurExtrude = 1.15f;
+
+ public Shader dofBlurShader;
+
+ private Material dofBlurMaterial;
+
+ public Shader dofShader;
+
+ private Material dofMaterial;
+
+ public bool visualize;
+
+ public BokehDestination bokehDestination = BokehDestination.Background;
+
+ private float widthOverHeight = 1.25f;
+
+ private float oneOverBaseSize = 0.001953125f;
+
+ public bool bokeh;
+
+ public bool bokehSupport = true;
+
+ public Shader bokehShader;
+
+ public Texture2D bokehTexture;
+
+ public float bokehScale = 2.4f;
+
+ public float bokehIntensity = 0.15f;
+
+ public float bokehThresholdContrast = 0.1f;
+
+ public float bokehThresholdLuminance = 0.55f;
+
+ public int bokehDownsample = 1;
+
+ private Material bokehMaterial;
+
+ private Camera _camera;
+
+ private RenderTexture foregroundTexture;
+
+ private RenderTexture mediumRezWorkTexture;
+
+ private RenderTexture finalDefocus;
+
+ private RenderTexture lowRezWorkTexture;
+
+ private RenderTexture bokehSource;
+
+ private RenderTexture bokehSource2;
+
+ private void CreateMaterials()
+ {
+ dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial);
+ dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial);
+ bokehSupport = bokehShader.isSupported;
+ if (bokeh && bokehSupport && (bool)bokehShader)
+ {
+ bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial);
+ }
+ }
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial);
+ dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial);
+ bokehSupport = bokehShader.isSupported;
+ if (bokeh && bokehSupport && (bool)bokehShader)
+ {
+ bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial);
+ }
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnDisable()
+ {
+ Quads.Cleanup();
+ }
+
+ private void OnEnable()
+ {
+ _camera = GetComponent<Camera>();
+ _camera.depthTextureMode |= DepthTextureMode.Depth;
+ }
+
+ private float FocalDistance01(float worldDist)
+ {
+ return _camera.WorldToViewportPoint((worldDist - _camera.nearClipPlane) * _camera.transform.forward + _camera.transform.position).z / (_camera.farClipPlane - _camera.nearClipPlane);
+ }
+
+ private int GetDividerBasedOnQuality()
+ {
+ int result = 1;
+ if (resolution == DofResolution.Medium)
+ {
+ result = 2;
+ }
+ else if (resolution == DofResolution.Low)
+ {
+ result = 2;
+ }
+ return result;
+ }
+
+ private int GetLowResolutionDividerBasedOnQuality(int baseDivider)
+ {
+ int num = baseDivider;
+ if (resolution == DofResolution.High)
+ {
+ num *= 2;
+ }
+ if (resolution == DofResolution.Low)
+ {
+ num *= 2;
+ }
+ return num;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ if (smoothness < 0.1f)
+ {
+ smoothness = 0.1f;
+ }
+ bokeh = bokeh && bokehSupport;
+ float num = (bokeh ? BOKEH_EXTRA_BLUR : 1f);
+ bool flag = quality > Dof34QualitySetting.OnlyBackground;
+ float num2 = focalSize / (_camera.farClipPlane - _camera.nearClipPlane);
+ if (simpleTweakMode)
+ {
+ focalDistance01 = (objectFocus ? (_camera.WorldToViewportPoint(objectFocus.position).z / _camera.farClipPlane) : FocalDistance01(focalPoint));
+ focalStartCurve = focalDistance01 * smoothness;
+ focalEndCurve = focalStartCurve;
+ flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon;
+ }
+ else
+ {
+ if ((bool)objectFocus)
+ {
+ Vector3 vector = _camera.WorldToViewportPoint(objectFocus.position);
+ vector.z /= _camera.farClipPlane;
+ focalDistance01 = vector.z;
+ }
+ else
+ {
+ focalDistance01 = FocalDistance01(focalZDistance);
+ }
+ focalStartCurve = focalZStartCurve;
+ focalEndCurve = focalZEndCurve;
+ flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon;
+ }
+ widthOverHeight = 1f * (float)source.width / (1f * (float)source.height);
+ oneOverBaseSize = 0.001953125f;
+ dofMaterial.SetFloat("_ForegroundBlurExtrude", foregroundBlurExtrude);
+ dofMaterial.SetVector("_CurveParams", new Vector4(simpleTweakMode ? (1f / focalStartCurve) : focalStartCurve, simpleTweakMode ? (1f / focalEndCurve) : focalEndCurve, num2 * 0.5f, focalDistance01));
+ dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)source.width), 1f / (1f * (float)source.height), 0f, 0f));
+ int dividerBasedOnQuality = GetDividerBasedOnQuality();
+ int lowResolutionDividerBasedOnQuality = GetLowResolutionDividerBasedOnQuality(dividerBasedOnQuality);
+ AllocateTextures(flag, source, dividerBasedOnQuality, lowResolutionDividerBasedOnQuality);
+ Graphics.Blit(source, source, dofMaterial, 3);
+ Downsample(source, mediumRezWorkTexture);
+ Blur(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 4, maxBlurSpread);
+ if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
+ {
+ dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast, bokehThresholdLuminance, 0.95f, 0f));
+ Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
+ Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture);
+ Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread * num);
+ }
+ else
+ {
+ Downsample(mediumRezWorkTexture, lowRezWorkTexture);
+ Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread);
+ }
+ dofBlurMaterial.SetTexture("_TapLow", lowRezWorkTexture);
+ dofBlurMaterial.SetTexture("_TapMedium", mediumRezWorkTexture);
+ Graphics.Blit(null, finalDefocus, dofBlurMaterial, 3);
+ if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
+ {
+ AddBokeh(bokehSource2, bokehSource, finalDefocus);
+ }
+ dofMaterial.SetTexture("_TapLowBackground", finalDefocus);
+ dofMaterial.SetTexture("_TapMedium", mediumRezWorkTexture);
+ Graphics.Blit(source, flag ? foregroundTexture : destination, dofMaterial, visualize ? 2 : 0);
+ if (flag)
+ {
+ Graphics.Blit(foregroundTexture, source, dofMaterial, 5);
+ Downsample(source, mediumRezWorkTexture);
+ BlurFg(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 2, maxBlurSpread);
+ if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
+ {
+ dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast * 0.5f, bokehThresholdLuminance, 0f, 0f));
+ Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
+ Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture);
+ BlurFg(lowRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread * num);
+ }
+ else
+ {
+ BlurFg(mediumRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread);
+ }
+ Graphics.Blit(lowRezWorkTexture, finalDefocus);
+ dofMaterial.SetTexture("_TapLowForeground", finalDefocus);
+ Graphics.Blit(source, destination, dofMaterial, visualize ? 1 : 4);
+ if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
+ {
+ AddBokeh(bokehSource2, bokehSource, destination);
+ }
+ }
+ ReleaseTextures();
+ }
+
+ private void Blur(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height);
+ if (iterations > DofBlurriness.Low)
+ {
+ BlurHex(from, to, blurPass, spread, temporary);
+ if (iterations > DofBlurriness.High)
+ {
+ dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(to, temporary, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
+ Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
+ }
+ }
+ else
+ {
+ dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(from, temporary, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
+ Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
+ }
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+
+ private void BlurFg(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
+ {
+ dofBlurMaterial.SetTexture("_TapHigh", from);
+ RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height);
+ if (iterations > DofBlurriness.Low)
+ {
+ BlurHex(from, to, blurPass, spread, temporary);
+ if (iterations > DofBlurriness.High)
+ {
+ dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(to, temporary, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
+ Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
+ }
+ }
+ else
+ {
+ dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(from, temporary, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
+ Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
+ }
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+
+ private void BlurHex(RenderTexture from, RenderTexture to, int blurPass, float spread, RenderTexture tmp)
+ {
+ dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(from, tmp, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
+ Graphics.Blit(tmp, to, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, spread * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(to, tmp, dofBlurMaterial, blurPass);
+ dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, (0f - spread) * oneOverBaseSize, 0f, 0f));
+ Graphics.Blit(tmp, to, dofBlurMaterial, blurPass);
+ }
+
+ private void Downsample(RenderTexture from, RenderTexture to)
+ {
+ dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)to.width), 1f / (1f * (float)to.height), 0f, 0f));
+ Graphics.Blit(from, to, dofMaterial, SMOOTH_DOWNSAMPLE_PASS);
+ }
+
+ private void AddBokeh(RenderTexture bokehInfo, RenderTexture tempTex, RenderTexture finalTarget)
+ {
+ if (!bokehMaterial)
+ {
+ return;
+ }
+ Mesh[] meshes = Quads.GetMeshes(tempTex.width, tempTex.height);
+ RenderTexture.active = tempTex;
+ GL.Clear(clearDepth: false, clearColor: true, new Color(0f, 0f, 0f, 0f));
+ GL.PushMatrix();
+ GL.LoadIdentity();
+ bokehInfo.filterMode = FilterMode.Point;
+ float num = (float)bokehInfo.width * 1f / ((float)bokehInfo.height * 1f);
+ float num2 = 2f / (1f * (float)bokehInfo.width);
+ num2 += bokehScale * maxBlurSpread * BOKEH_EXTRA_BLUR * oneOverBaseSize;
+ bokehMaterial.SetTexture("_Source", bokehInfo);
+ bokehMaterial.SetTexture("_MainTex", bokehTexture);
+ bokehMaterial.SetVector("_ArScale", new Vector4(num2, num2 * num, 0.5f, 0.5f * num));
+ bokehMaterial.SetFloat("_Intensity", bokehIntensity);
+ bokehMaterial.SetPass(0);
+ Mesh[] array = meshes;
+ foreach (Mesh mesh in array)
+ {
+ if ((bool)mesh)
+ {
+ Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
+ }
+ }
+ GL.PopMatrix();
+ Graphics.Blit(tempTex, finalTarget, dofMaterial, 8);
+ bokehInfo.filterMode = FilterMode.Bilinear;
+ }
+
+ private void ReleaseTextures()
+ {
+ if ((bool)foregroundTexture)
+ {
+ RenderTexture.ReleaseTemporary(foregroundTexture);
+ }
+ if ((bool)finalDefocus)
+ {
+ RenderTexture.ReleaseTemporary(finalDefocus);
+ }
+ if ((bool)mediumRezWorkTexture)
+ {
+ RenderTexture.ReleaseTemporary(mediumRezWorkTexture);
+ }
+ if ((bool)lowRezWorkTexture)
+ {
+ RenderTexture.ReleaseTemporary(lowRezWorkTexture);
+ }
+ if ((bool)bokehSource)
+ {
+ RenderTexture.ReleaseTemporary(bokehSource);
+ }
+ if ((bool)bokehSource2)
+ {
+ RenderTexture.ReleaseTemporary(bokehSource2);
+ }
+ }
+
+ private void AllocateTextures(bool blurForeground, RenderTexture source, int divider, int lowTexDivider)
+ {
+ foregroundTexture = null;
+ if (blurForeground)
+ {
+ foregroundTexture = RenderTexture.GetTemporary(source.width, source.height, 0);
+ }
+ mediumRezWorkTexture = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0);
+ finalDefocus = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0);
+ lowRezWorkTexture = RenderTexture.GetTemporary(source.width / lowTexDivider, source.height / lowTexDivider, 0);
+ bokehSource = null;
+ bokehSource2 = null;
+ if (bokeh)
+ {
+ bokehSource = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
+ bokehSource2 = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
+ bokehSource.filterMode = FilterMode.Bilinear;
+ bokehSource2.filterMode = FilterMode.Bilinear;
+ RenderTexture.active = bokehSource2;
+ GL.Clear(clearDepth: false, clearColor: true, new Color(0f, 0f, 0f, 0f));
+ }
+ source.filterMode = FilterMode.Bilinear;
+ finalDefocus.filterMode = FilterMode.Bilinear;
+ mediumRezWorkTexture.filterMode = FilterMode.Bilinear;
+ lowRezWorkTexture.filterMode = FilterMode.Bilinear;
+ if ((bool)foregroundTexture)
+ {
+ foregroundTexture.filterMode = FilterMode.Bilinear;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/EdgeDetection.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/EdgeDetection.cs
new file mode 100644
index 0000000..13e9140
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/EdgeDetection.cs
@@ -0,0 +1,96 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Edge Detection/Edge Detection")]
+public class EdgeDetection : PostEffectsBase
+{
+ public enum EdgeDetectMode
+ {
+ TriangleDepthNormals,
+ RobertsCrossDepthNormals,
+ SobelDepth,
+ SobelDepthThin,
+ TriangleLuminance
+ }
+
+ public EdgeDetectMode mode = EdgeDetectMode.SobelDepthThin;
+
+ public float sensitivityDepth = 1f;
+
+ public float sensitivityNormals = 1f;
+
+ public float lumThreshold = 0.2f;
+
+ public float edgeExp = 1f;
+
+ public float sampleDist = 1f;
+
+ public float edgesOnly;
+
+ public Color edgesOnlyBgColor = Color.white;
+
+ public Shader edgeDetectShader;
+
+ private Material edgeDetectMaterial;
+
+ private EdgeDetectMode oldMode = EdgeDetectMode.SobelDepthThin;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
+ if (mode != oldMode)
+ {
+ SetCameraFlag();
+ }
+ oldMode = mode;
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private new void Start()
+ {
+ oldMode = mode;
+ }
+
+ private void SetCameraFlag()
+ {
+ if (mode == EdgeDetectMode.SobelDepth || mode == EdgeDetectMode.SobelDepthThin)
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+ }
+ else if (mode == EdgeDetectMode.TriangleDepthNormals || mode == EdgeDetectMode.RobertsCrossDepthNormals)
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
+ }
+ }
+
+ private void OnEnable()
+ {
+ SetCameraFlag();
+ }
+
+ [ImageEffectOpaque]
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ Vector2 vector = new Vector2(sensitivityDepth, sensitivityNormals);
+ edgeDetectMaterial.SetVector("_Sensitivity", new Vector4(vector.x, vector.y, 1f, vector.y));
+ edgeDetectMaterial.SetFloat("_BgFade", edgesOnly);
+ edgeDetectMaterial.SetFloat("_SampleDistance", sampleDist);
+ edgeDetectMaterial.SetVector("_BgColor", edgesOnlyBgColor);
+ edgeDetectMaterial.SetFloat("_Exponent", edgeExp);
+ edgeDetectMaterial.SetFloat("_Threshold", lumThreshold);
+ Graphics.Blit(source, destination, edgeDetectMaterial, (int)mode);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Fisheye.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Fisheye.cs
new file mode 100644
index 0000000..77c1663
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Fisheye.cs
@@ -0,0 +1,43 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Displacement/Fisheye")]
+public class Fisheye : PostEffectsBase
+{
+ [Range(0f, 1.5f)]
+ public float strengthX = 0.05f;
+
+ [Range(0f, 1.5f)]
+ public float strengthY = 0.05f;
+
+ public Shader fishEyeShader;
+
+ private Material fisheyeMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ fisheyeMaterial = CheckShaderAndCreateMaterial(fishEyeShader, fisheyeMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ float num = 5f / 32f;
+ float num2 = (float)source.width * 1f / ((float)source.height * 1f);
+ fisheyeMaterial.SetVector("intensity", new Vector4(strengthX * num2 * num, strengthY * num, strengthX * num2 * num, strengthY * num));
+ Graphics.Blit(source, destination, fisheyeMaterial);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/GlobalFog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/GlobalFog.cs
new file mode 100644
index 0000000..72743ac
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/GlobalFog.cs
@@ -0,0 +1,92 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Rendering/Global Fog")]
+internal class GlobalFog : PostEffectsBase
+{
+ [Tooltip("Apply distance-based fog?")]
+ public bool distanceFog = true;
+
+ [Tooltip("Exclude far plane pixels from distance-based fog? (Skybox or clear color)")]
+ public bool excludeFarPixels = true;
+
+ [Tooltip("Distance fog is based on radial distance from camera when checked")]
+ public bool useRadialDistance;
+
+ [Tooltip("Apply height-based fog?")]
+ public bool heightFog = true;
+
+ [Tooltip("Fog top Y coordinate")]
+ public float height = 1f;
+
+ [Range(0.001f, 10f)]
+ public float heightDensity = 2f;
+
+ [Tooltip("Push fog away from the camera by this amount")]
+ public float startDistance;
+
+ public Shader fogShader;
+
+ private Material fogMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ fogMaterial = CheckShaderAndCreateMaterial(fogShader, fogMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ [ImageEffectOpaque]
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources() || (!distanceFog && !heightFog))
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ Camera component = GetComponent<Camera>();
+ Transform obj = component.transform;
+ Vector3[] array = new Vector3[4];
+ component.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), component.farClipPlane, component.stereoActiveEye, array);
+ Vector3 vector = obj.TransformVector(array[0]);
+ Vector3 vector2 = obj.TransformVector(array[1]);
+ Vector3 vector3 = obj.TransformVector(array[2]);
+ Vector3 vector4 = obj.TransformVector(array[3]);
+ Matrix4x4 identity = Matrix4x4.identity;
+ identity.SetRow(0, vector);
+ identity.SetRow(1, vector4);
+ identity.SetRow(2, vector2);
+ identity.SetRow(3, vector3);
+ Vector3 position = obj.position;
+ float num = position.y - height;
+ float z = ((num <= 0f) ? 1f : 0f);
+ float y = (excludeFarPixels ? 1f : 2f);
+ fogMaterial.SetMatrix("_FrustumCornersWS", identity);
+ fogMaterial.SetVector("_CameraWS", position);
+ fogMaterial.SetVector("_HeightParams", new Vector4(height, num, z, heightDensity * 0.5f));
+ fogMaterial.SetVector("_DistanceParams", new Vector4(0f - Mathf.Max(startDistance, 0f), y, 0f, 0f));
+ FogMode fogMode = RenderSettings.fogMode;
+ float fogDensity = RenderSettings.fogDensity;
+ float fogStartDistance = RenderSettings.fogStartDistance;
+ float fogEndDistance = RenderSettings.fogEndDistance;
+ bool flag = fogMode == FogMode.Linear;
+ float num2 = (flag ? (fogEndDistance - fogStartDistance) : 0f);
+ float num3 = ((Mathf.Abs(num2) > 0.0001f) ? (1f / num2) : 0f);
+ Vector4 value = default(Vector4);
+ value.x = fogDensity * 1.2011224f;
+ value.y = fogDensity * 1.442695f;
+ value.z = (flag ? (0f - num3) : 0f);
+ value.w = (flag ? (fogEndDistance * num3) : 0f);
+ fogMaterial.SetVector("_SceneFogParams", value);
+ fogMaterial.SetVector("_SceneFogMode", new Vector4((float)fogMode, useRadialDistance ? 1 : 0, 0f, 0f));
+ int num4 = 0;
+ Graphics.Blit(pass: (!distanceFog || !heightFog) ? (distanceFog ? 1 : 2) : 0, source: source, dest: destination, mat: fogMaterial);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Grayscale.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Grayscale.cs
new file mode 100644
index 0000000..289eddc
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Grayscale.cs
@@ -0,0 +1,20 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Grayscale")]
+public class Grayscale : ImageEffectBase
+{
+ public Texture textureRamp;
+
+ [Range(-1f, 1f)]
+ public float rampOffset;
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ base.material.SetTexture("_RampTex", textureRamp);
+ base.material.SetFloat("_RampOffset", rampOffset);
+ Graphics.Blit(source, destination, base.material);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/HDRBloomMode.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/HDRBloomMode.cs
new file mode 100644
index 0000000..b26d1e5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/HDRBloomMode.cs
@@ -0,0 +1,8 @@
+namespace UnityStandardAssets.ImageEffects;
+
+public enum HDRBloomMode
+{
+ Auto,
+ On,
+ Off
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffectBase.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffectBase.cs
new file mode 100644
index 0000000..19b4215
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffectBase.cs
@@ -0,0 +1,45 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("")]
+public class ImageEffectBase : MonoBehaviour
+{
+ public Shader shader;
+
+ private Material m_Material;
+
+ protected Material material
+ {
+ get
+ {
+ if (m_Material == null)
+ {
+ m_Material = new Material(shader);
+ m_Material.hideFlags = HideFlags.HideAndDontSave;
+ }
+ return m_Material;
+ }
+ }
+
+ protected virtual void Start()
+ {
+ if (!SystemInfo.supportsImageEffects)
+ {
+ base.enabled = false;
+ }
+ else if (!shader || !shader.isSupported)
+ {
+ base.enabled = false;
+ }
+ }
+
+ protected virtual void OnDisable()
+ {
+ if ((bool)m_Material)
+ {
+ Object.DestroyImmediate(m_Material);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffects.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffects.cs
new file mode 100644
index 0000000..43121e4
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ImageEffects.cs
@@ -0,0 +1,34 @@
+using System;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[AddComponentMenu("")]
+public class ImageEffects
+{
+ public static void RenderDistortion(Material material, RenderTexture source, RenderTexture destination, float angle, Vector2 center, Vector2 radius)
+ {
+ if (source.texelSize.y < 0f)
+ {
+ center.y = 1f - center.y;
+ angle = 0f - angle;
+ }
+ Matrix4x4 value = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, angle), Vector3.one);
+ material.SetMatrix("_RotationMatrix", value);
+ material.SetVector("_CenterRadius", new Vector4(center.x, center.y, radius.x, radius.y));
+ material.SetFloat("_Angle", angle * ((float)Math.PI / 180f));
+ Graphics.Blit(source, destination, material);
+ }
+
+ [Obsolete("Use Graphics.Blit(source,dest) instead")]
+ public static void Blit(RenderTexture source, RenderTexture dest)
+ {
+ Graphics.Blit(source, dest);
+ }
+
+ [Obsolete("Use Graphics.Blit(source, destination, material) instead")]
+ public static void BlitWithMaterial(Material material, RenderTexture source, RenderTexture dest)
+ {
+ Graphics.Blit(source, dest, material);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/LensflareStyle34.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/LensflareStyle34.cs
new file mode 100644
index 0000000..a324696
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/LensflareStyle34.cs
@@ -0,0 +1,8 @@
+namespace UnityStandardAssets.ImageEffects;
+
+public enum LensflareStyle34
+{
+ Ghosting,
+ Anamorphic,
+ Combined
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/MotionBlur.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/MotionBlur.cs
new file mode 100644
index 0000000..4f34fc8
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/MotionBlur.cs
@@ -0,0 +1,52 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Blur/Motion Blur (Color Accumulation)")]
+[RequireComponent(typeof(Camera))]
+public class MotionBlur : ImageEffectBase
+{
+ [Range(0f, 0.92f)]
+ public float blurAmount = 0.8f;
+
+ public bool extraBlur;
+
+ private RenderTexture accumTexture;
+
+ protected override void Start()
+ {
+ base.Start();
+ }
+
+ protected override void OnDisable()
+ {
+ base.OnDisable();
+ Object.DestroyImmediate(accumTexture);
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (accumTexture == null || accumTexture.width != source.width || accumTexture.height != source.height)
+ {
+ Object.DestroyImmediate(accumTexture);
+ accumTexture = new RenderTexture(source.width, source.height, 0);
+ accumTexture.hideFlags = HideFlags.HideAndDontSave;
+ Graphics.Blit(source, accumTexture);
+ }
+ if (extraBlur)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width / 4, source.height / 4, 0);
+ accumTexture.MarkRestoreExpected();
+ Graphics.Blit(accumTexture, temporary);
+ Graphics.Blit(temporary, accumTexture);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ blurAmount = Mathf.Clamp(blurAmount, 0f, 0.92f);
+ base.material.SetTexture("_MainTex", accumTexture);
+ base.material.SetFloat("_AccumOrig", 1f - blurAmount);
+ accumTexture.MarkRestoreExpected();
+ Graphics.Blit(source, accumTexture, base.material);
+ Graphics.Blit(accumTexture, destination);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndGrain.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndGrain.cs
new file mode 100644
index 0000000..a15b96d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndGrain.cs
@@ -0,0 +1,158 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Noise/Noise And Grain (Filmic)")]
+public class NoiseAndGrain : PostEffectsBase
+{
+ public float intensityMultiplier = 0.25f;
+
+ public float generalIntensity = 0.5f;
+
+ public float blackIntensity = 1f;
+
+ public float whiteIntensity = 1f;
+
+ public float midGrey = 0.2f;
+
+ public bool dx11Grain;
+
+ public float softness;
+
+ public bool monochrome;
+
+ public Vector3 intensities = new Vector3(1f, 1f, 1f);
+
+ public Vector3 tiling = new Vector3(64f, 64f, 64f);
+
+ public float monochromeTiling = 64f;
+
+ public FilterMode filterMode = FilterMode.Bilinear;
+
+ public Texture2D noiseTexture;
+
+ public Shader noiseShader;
+
+ private Material noiseMaterial;
+
+ public Shader dx11NoiseShader;
+
+ private Material dx11NoiseMaterial;
+
+ private static float TILE_AMOUNT = 64f;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ noiseMaterial = CheckShaderAndCreateMaterial(noiseShader, noiseMaterial);
+ if (dx11Grain && supportDX11)
+ {
+ dx11NoiseMaterial = CheckShaderAndCreateMaterial(dx11NoiseShader, dx11NoiseMaterial);
+ }
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources() || null == noiseTexture)
+ {
+ Graphics.Blit(source, destination);
+ if (null == noiseTexture)
+ {
+ Debug.LogWarning("Noise & Grain effect failing as noise texture is not assigned. please assign.", base.transform);
+ }
+ return;
+ }
+ softness = Mathf.Clamp(softness, 0f, 0.99f);
+ if (dx11Grain && supportDX11)
+ {
+ dx11NoiseMaterial.SetFloat("_DX11NoiseTime", Time.frameCount);
+ dx11NoiseMaterial.SetTexture("_NoiseTex", noiseTexture);
+ dx11NoiseMaterial.SetVector("_NoisePerChannel", monochrome ? Vector3.one : intensities);
+ dx11NoiseMaterial.SetVector("_MidGrey", new Vector3(midGrey, 1f / (1f - midGrey), -1f / midGrey));
+ dx11NoiseMaterial.SetVector("_NoiseAmount", new Vector3(generalIntensity, blackIntensity, whiteIntensity) * intensityMultiplier);
+ if (softness > Mathf.Epsilon)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary((int)((float)source.width * (1f - softness)), (int)((float)source.height * (1f - softness)));
+ DrawNoiseQuadGrid(source, temporary, dx11NoiseMaterial, noiseTexture, monochrome ? 3 : 2);
+ dx11NoiseMaterial.SetTexture("_NoiseTex", temporary);
+ Graphics.Blit(source, destination, dx11NoiseMaterial, 4);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ else
+ {
+ DrawNoiseQuadGrid(source, destination, dx11NoiseMaterial, noiseTexture, monochrome ? 1 : 0);
+ }
+ return;
+ }
+ if ((bool)noiseTexture)
+ {
+ noiseTexture.wrapMode = TextureWrapMode.Repeat;
+ noiseTexture.filterMode = filterMode;
+ }
+ noiseMaterial.SetTexture("_NoiseTex", noiseTexture);
+ noiseMaterial.SetVector("_NoisePerChannel", monochrome ? Vector3.one : intensities);
+ noiseMaterial.SetVector("_NoiseTilingPerChannel", monochrome ? (Vector3.one * monochromeTiling) : tiling);
+ noiseMaterial.SetVector("_MidGrey", new Vector3(midGrey, 1f / (1f - midGrey), -1f / midGrey));
+ noiseMaterial.SetVector("_NoiseAmount", new Vector3(generalIntensity, blackIntensity, whiteIntensity) * intensityMultiplier);
+ if (softness > Mathf.Epsilon)
+ {
+ RenderTexture temporary2 = RenderTexture.GetTemporary((int)((float)source.width * (1f - softness)), (int)((float)source.height * (1f - softness)));
+ DrawNoiseQuadGrid(source, temporary2, noiseMaterial, noiseTexture, 2);
+ noiseMaterial.SetTexture("_NoiseTex", temporary2);
+ Graphics.Blit(source, destination, noiseMaterial, 1);
+ RenderTexture.ReleaseTemporary(temporary2);
+ }
+ else
+ {
+ DrawNoiseQuadGrid(source, destination, noiseMaterial, noiseTexture, 0);
+ }
+ }
+
+ private static void DrawNoiseQuadGrid(RenderTexture source, RenderTexture dest, Material fxMaterial, Texture2D noise, int passNr)
+ {
+ RenderTexture.active = dest;
+ float num = (float)noise.width * 1f;
+ float num2 = 1f * (float)source.width / TILE_AMOUNT;
+ fxMaterial.SetTexture("_MainTex", source);
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ float num3 = 1f * (float)source.width / (1f * (float)source.height);
+ float num4 = 1f / num2;
+ float num5 = num4 * num3;
+ float num6 = num / ((float)noise.width * 1f);
+ fxMaterial.SetPass(passNr);
+ GL.Begin(7);
+ for (float num7 = 0f; num7 < 1f; num7 += num4)
+ {
+ for (float num8 = 0f; num8 < 1f; num8 += num5)
+ {
+ float num9 = Random.Range(0f, 1f);
+ float num10 = Random.Range(0f, 1f);
+ num9 = Mathf.Floor(num9 * num) / num;
+ num10 = Mathf.Floor(num10 * num) / num;
+ float num11 = 1f / num;
+ GL.MultiTexCoord2(0, num9, num10);
+ GL.MultiTexCoord2(1, 0f, 0f);
+ GL.Vertex3(num7, num8, 0.1f);
+ GL.MultiTexCoord2(0, num9 + num6 * num11, num10);
+ GL.MultiTexCoord2(1, 1f, 0f);
+ GL.Vertex3(num7 + num4, num8, 0.1f);
+ GL.MultiTexCoord2(0, num9 + num6 * num11, num10 + num6 * num11);
+ GL.MultiTexCoord2(1, 1f, 1f);
+ GL.Vertex3(num7 + num4, num8 + num5, 0.1f);
+ GL.MultiTexCoord2(0, num9, num10 + num6 * num11);
+ GL.MultiTexCoord2(1, 0f, 1f);
+ GL.Vertex3(num7, num8 + num5, 0.1f);
+ }
+ }
+ GL.End();
+ GL.PopMatrix();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndScratches.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndScratches.cs
new file mode 100644
index 0000000..256a981
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/NoiseAndScratches.cs
@@ -0,0 +1,138 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Noise/Noise and Scratches")]
+public class NoiseAndScratches : MonoBehaviour
+{
+ public bool monochrome = true;
+
+ private bool rgbFallback;
+
+ [Range(0f, 5f)]
+ public float grainIntensityMin = 0.1f;
+
+ [Range(0f, 5f)]
+ public float grainIntensityMax = 0.2f;
+
+ [Range(0.1f, 50f)]
+ public float grainSize = 2f;
+
+ [Range(0f, 5f)]
+ public float scratchIntensityMin = 0.05f;
+
+ [Range(0f, 5f)]
+ public float scratchIntensityMax = 0.25f;
+
+ [Range(1f, 30f)]
+ public float scratchFPS = 10f;
+
+ [Range(0f, 1f)]
+ public float scratchJitter = 0.01f;
+
+ public Texture grainTexture;
+
+ public Texture scratchTexture;
+
+ public Shader shaderRGB;
+
+ public Shader shaderYUV;
+
+ private Material m_MaterialRGB;
+
+ private Material m_MaterialYUV;
+
+ private float scratchTimeLeft;
+
+ private float scratchX;
+
+ private float scratchY;
+
+ protected Material material
+ {
+ get
+ {
+ if (m_MaterialRGB == null)
+ {
+ m_MaterialRGB = new Material(shaderRGB);
+ m_MaterialRGB.hideFlags = HideFlags.HideAndDontSave;
+ }
+ if (m_MaterialYUV == null && !rgbFallback)
+ {
+ m_MaterialYUV = new Material(shaderYUV);
+ m_MaterialYUV.hideFlags = HideFlags.HideAndDontSave;
+ }
+ if (rgbFallback || monochrome)
+ {
+ return m_MaterialRGB;
+ }
+ return m_MaterialYUV;
+ }
+ }
+
+ protected void Start()
+ {
+ if (!SystemInfo.supportsImageEffects)
+ {
+ base.enabled = false;
+ }
+ else if (shaderRGB == null || shaderYUV == null)
+ {
+ Debug.Log("Noise shaders are not set up! Disabling noise effect.");
+ base.enabled = false;
+ }
+ else if (!shaderRGB.isSupported)
+ {
+ base.enabled = false;
+ }
+ else if (!shaderYUV.isSupported)
+ {
+ rgbFallback = true;
+ }
+ }
+
+ protected void OnDisable()
+ {
+ if ((bool)m_MaterialRGB)
+ {
+ Object.DestroyImmediate(m_MaterialRGB);
+ }
+ if ((bool)m_MaterialYUV)
+ {
+ Object.DestroyImmediate(m_MaterialYUV);
+ }
+ }
+
+ private void SanitizeParameters()
+ {
+ grainIntensityMin = Mathf.Clamp(grainIntensityMin, 0f, 5f);
+ grainIntensityMax = Mathf.Clamp(grainIntensityMax, 0f, 5f);
+ scratchIntensityMin = Mathf.Clamp(scratchIntensityMin, 0f, 5f);
+ scratchIntensityMax = Mathf.Clamp(scratchIntensityMax, 0f, 5f);
+ scratchFPS = Mathf.Clamp(scratchFPS, 1f, 30f);
+ scratchJitter = Mathf.Clamp(scratchJitter, 0f, 1f);
+ grainSize = Mathf.Clamp(grainSize, 0.1f, 50f);
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ SanitizeParameters();
+ if (scratchTimeLeft <= 0f)
+ {
+ scratchTimeLeft = Random.value * 2f / scratchFPS;
+ scratchX = Random.value;
+ scratchY = Random.value;
+ }
+ scratchTimeLeft -= Time.deltaTime;
+ Material material = this.material;
+ material.SetTexture("_GrainTex", grainTexture);
+ material.SetTexture("_ScratchTex", scratchTexture);
+ float num = 1f / grainSize;
+ material.SetVector("_GrainOffsetScale", new Vector4(Random.value, Random.value, (float)Screen.width / (float)grainTexture.width * num, (float)Screen.height / (float)grainTexture.height * num));
+ material.SetVector("_ScratchOffsetScale", new Vector4(scratchX + Random.value * scratchJitter, scratchY + Random.value * scratchJitter, (float)Screen.width / (float)scratchTexture.width, (float)Screen.height / (float)scratchTexture.height));
+ material.SetVector("_Intensity", new Vector4(Random.Range(grainIntensityMin, grainIntensityMax), Random.Range(scratchIntensityMin, scratchIntensityMax), 0f, 0f));
+ Graphics.Blit(source, destination, material);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsBase.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsBase.cs
new file mode 100644
index 0000000..1296bab
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsBase.cs
@@ -0,0 +1,233 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+public class PostEffectsBase : MonoBehaviour
+{
+ protected bool supportHDRTextures = true;
+
+ protected bool supportDX11;
+
+ protected bool isSupported = true;
+
+ private List<Material> createdMaterials = new List<Material>();
+
+ protected Material CheckShaderAndCreateMaterial(Shader s, Material m2Create)
+ {
+ if (!s)
+ {
+ Debug.Log("Missing shader in " + ToString());
+ base.enabled = false;
+ return null;
+ }
+ if (s.isSupported && (bool)m2Create && m2Create.shader == s)
+ {
+ return m2Create;
+ }
+ if (!s.isSupported)
+ {
+ NotSupported();
+ Debug.Log("The shader " + s.ToString() + " on effect " + ToString() + " is not supported on this platform!");
+ return null;
+ }
+ m2Create = new Material(s);
+ createdMaterials.Add(m2Create);
+ m2Create.hideFlags = HideFlags.DontSave;
+ return m2Create;
+ }
+
+ protected Material CreateMaterial(Shader s, Material m2Create)
+ {
+ if (!s)
+ {
+ Debug.Log("Missing shader in " + ToString());
+ return null;
+ }
+ if ((bool)m2Create && m2Create.shader == s && s.isSupported)
+ {
+ return m2Create;
+ }
+ if (!s.isSupported)
+ {
+ return null;
+ }
+ m2Create = new Material(s);
+ createdMaterials.Add(m2Create);
+ m2Create.hideFlags = HideFlags.DontSave;
+ return m2Create;
+ }
+
+ private void OnEnable()
+ {
+ isSupported = true;
+ }
+
+ private void OnDestroy()
+ {
+ RemoveCreatedMaterials();
+ }
+
+ private void RemoveCreatedMaterials()
+ {
+ while (createdMaterials.Count > 0)
+ {
+ Material obj = createdMaterials[0];
+ createdMaterials.RemoveAt(0);
+ Object.Destroy(obj);
+ }
+ }
+
+ protected bool CheckSupport()
+ {
+ return CheckSupport(needDepth: false);
+ }
+
+ public virtual bool CheckResources()
+ {
+ Debug.LogWarning("CheckResources () for " + ToString() + " should be overwritten.");
+ return isSupported;
+ }
+
+ protected void Start()
+ {
+ CheckResources();
+ }
+
+ protected bool CheckSupport(bool needDepth)
+ {
+ isSupported = true;
+ supportHDRTextures = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf);
+ supportDX11 = SystemInfo.graphicsShaderLevel >= 50 && SystemInfo.supportsComputeShaders;
+ if (!SystemInfo.supportsImageEffects)
+ {
+ NotSupported();
+ return false;
+ }
+ if (needDepth && !SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.Depth))
+ {
+ NotSupported();
+ return false;
+ }
+ if (needDepth)
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+ }
+ return true;
+ }
+
+ protected bool CheckSupport(bool needDepth, bool needHdr)
+ {
+ if (!CheckSupport(needDepth))
+ {
+ return false;
+ }
+ if (needHdr && !supportHDRTextures)
+ {
+ NotSupported();
+ return false;
+ }
+ return true;
+ }
+
+ public bool Dx11Support()
+ {
+ return supportDX11;
+ }
+
+ protected void ReportAutoDisable()
+ {
+ Debug.LogWarning("The image effect " + ToString() + " has been disabled as it's not supported on the current platform.");
+ }
+
+ private bool CheckShader(Shader s)
+ {
+ Debug.Log("The shader " + s.ToString() + " on effect " + ToString() + " is not part of the Unity 3.2+ effects suite anymore. For best performance and quality, please ensure you are using the latest Standard Assets Image Effects (Pro only) package.");
+ if (!s.isSupported)
+ {
+ NotSupported();
+ return false;
+ }
+ return false;
+ }
+
+ protected void NotSupported()
+ {
+ base.enabled = false;
+ isSupported = false;
+ }
+
+ protected void DrawBorder(RenderTexture dest, Material material)
+ {
+ RenderTexture.active = dest;
+ bool flag = true;
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ for (int i = 0; i < material.passCount; i++)
+ {
+ material.SetPass(i);
+ float y;
+ float y2;
+ if (flag)
+ {
+ y = 1f;
+ y2 = 0f;
+ }
+ else
+ {
+ y = 0f;
+ y2 = 1f;
+ }
+ float x = 0f + 1f / ((float)dest.width * 1f);
+ float y3 = 0f;
+ float y4 = 1f;
+ GL.Begin(7);
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ float x2 = 1f - 1f / ((float)dest.width * 1f);
+ x = 1f;
+ y3 = 0f;
+ y4 = 1f;
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(x2, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(x2, y4, 0.1f);
+ x = 1f;
+ y3 = 0f;
+ y4 = 0f + 1f / ((float)dest.height * 1f);
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ x = 1f;
+ y3 = 1f - 1f / ((float)dest.height * 1f);
+ y4 = 1f;
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ GL.End();
+ }
+ GL.PopMatrix();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsHelper.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsHelper.cs
new file mode 100644
index 0000000..0558551
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/PostEffectsHelper.cs
@@ -0,0 +1,172 @@
+using System;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+internal class PostEffectsHelper : MonoBehaviour
+{
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ Debug.Log("OnRenderImage in Helper called ...");
+ }
+
+ private static void DrawLowLevelPlaneAlignedWithCamera(float dist, RenderTexture source, RenderTexture dest, Material material, Camera cameraForProjectionMatrix)
+ {
+ RenderTexture.active = dest;
+ material.SetTexture("_MainTex", source);
+ bool flag = true;
+ GL.PushMatrix();
+ GL.LoadIdentity();
+ GL.LoadProjectionMatrix(cameraForProjectionMatrix.projectionMatrix);
+ float f = cameraForProjectionMatrix.fieldOfView * 0.5f * ((float)Math.PI / 180f);
+ float num = Mathf.Cos(f) / Mathf.Sin(f);
+ float aspect = cameraForProjectionMatrix.aspect;
+ float num2 = aspect / (0f - num);
+ float num3 = aspect / num;
+ float num4 = 1f / (0f - num);
+ float num5 = 1f / num;
+ float num6 = 1f;
+ num2 *= dist * num6;
+ num3 *= dist * num6;
+ num4 *= dist * num6;
+ num5 *= dist * num6;
+ float z = 0f - dist;
+ for (int i = 0; i < material.passCount; i++)
+ {
+ material.SetPass(i);
+ GL.Begin(7);
+ float y;
+ float y2;
+ if (flag)
+ {
+ y = 1f;
+ y2 = 0f;
+ }
+ else
+ {
+ y = 0f;
+ y2 = 1f;
+ }
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(num2, num4, z);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(num3, num4, z);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(num3, num5, z);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(num2, num5, z);
+ GL.End();
+ }
+ GL.PopMatrix();
+ }
+
+ private static void DrawBorder(RenderTexture dest, Material material)
+ {
+ RenderTexture.active = dest;
+ bool flag = true;
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ for (int i = 0; i < material.passCount; i++)
+ {
+ material.SetPass(i);
+ float y;
+ float y2;
+ if (flag)
+ {
+ y = 1f;
+ y2 = 0f;
+ }
+ else
+ {
+ y = 0f;
+ y2 = 1f;
+ }
+ float x = 0f + 1f / ((float)dest.width * 1f);
+ float y3 = 0f;
+ float y4 = 1f;
+ GL.Begin(7);
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ float x2 = 1f - 1f / ((float)dest.width * 1f);
+ x = 1f;
+ y3 = 0f;
+ y4 = 1f;
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(x2, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(x2, y4, 0.1f);
+ x = 1f;
+ y3 = 0f;
+ y4 = 0f + 1f / ((float)dest.height * 1f);
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ x = 1f;
+ y3 = 1f - 1f / ((float)dest.height * 1f);
+ y4 = 1f;
+ GL.TexCoord2(0f, y);
+ GL.Vertex3(0f, y3, 0.1f);
+ GL.TexCoord2(1f, y);
+ GL.Vertex3(x, y3, 0.1f);
+ GL.TexCoord2(1f, y2);
+ GL.Vertex3(x, y4, 0.1f);
+ GL.TexCoord2(0f, y2);
+ GL.Vertex3(0f, y4, 0.1f);
+ GL.End();
+ }
+ GL.PopMatrix();
+ }
+
+ private static void DrawLowLevelQuad(float x1, float x2, float y1, float y2, RenderTexture source, RenderTexture dest, Material material)
+ {
+ RenderTexture.active = dest;
+ material.SetTexture("_MainTex", source);
+ bool flag = true;
+ GL.PushMatrix();
+ GL.LoadOrtho();
+ for (int i = 0; i < material.passCount; i++)
+ {
+ material.SetPass(i);
+ GL.Begin(7);
+ float y3;
+ float y4;
+ if (flag)
+ {
+ y3 = 1f;
+ y4 = 0f;
+ }
+ else
+ {
+ y3 = 0f;
+ y4 = 1f;
+ }
+ GL.TexCoord2(0f, y3);
+ GL.Vertex3(x1, y1, 0.1f);
+ GL.TexCoord2(1f, y3);
+ GL.Vertex3(x2, y1, 0.1f);
+ GL.TexCoord2(1f, y4);
+ GL.Vertex3(x2, y2, 0.1f);
+ GL.TexCoord2(0f, y4);
+ GL.Vertex3(x1, y2, 0.1f);
+ GL.End();
+ }
+ GL.PopMatrix();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Quads.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Quads.cs
new file mode 100644
index 0000000..f8b01d9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Quads.cs
@@ -0,0 +1,102 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+internal class Quads
+{
+ private static Mesh[] meshes;
+
+ private static int currentQuads;
+
+ private static bool HasMeshes()
+ {
+ if (meshes == null)
+ {
+ return false;
+ }
+ Mesh[] array = meshes;
+ foreach (Mesh mesh in array)
+ {
+ if (null == mesh)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void Cleanup()
+ {
+ if (meshes == null)
+ {
+ return;
+ }
+ for (int i = 0; i < meshes.Length; i++)
+ {
+ if (null != meshes[i])
+ {
+ Object.DestroyImmediate(meshes[i]);
+ meshes[i] = null;
+ }
+ }
+ meshes = null;
+ }
+
+ public static Mesh[] GetMeshes(int totalWidth, int totalHeight)
+ {
+ if (HasMeshes() && currentQuads == totalWidth * totalHeight)
+ {
+ return meshes;
+ }
+ int num = 10833;
+ int num2 = (currentQuads = totalWidth * totalHeight);
+ meshes = new Mesh[Mathf.CeilToInt(1f * (float)num2 / (1f * (float)num))];
+ int num3 = 0;
+ int num4 = 0;
+ for (num3 = 0; num3 < num2; num3 += num)
+ {
+ int triCount = Mathf.FloorToInt(Mathf.Clamp(num2 - num3, 0, num));
+ meshes[num4] = GetMesh(triCount, num3, totalWidth, totalHeight);
+ num4++;
+ }
+ return meshes;
+ }
+
+ private static Mesh GetMesh(int triCount, int triOffset, int totalWidth, int totalHeight)
+ {
+ Mesh mesh = new Mesh();
+ mesh.hideFlags = HideFlags.DontSave;
+ Vector3[] array = new Vector3[triCount * 4];
+ Vector2[] array2 = new Vector2[triCount * 4];
+ Vector2[] array3 = new Vector2[triCount * 4];
+ int[] array4 = new int[triCount * 6];
+ for (int i = 0; i < triCount; i++)
+ {
+ int num = i * 4;
+ int num2 = i * 6;
+ int num3 = triOffset + i;
+ float num4 = Mathf.Floor(num3 % totalWidth) / (float)totalWidth;
+ float num5 = Mathf.Floor(num3 / totalWidth) / (float)totalHeight;
+ array[num + 3] = (array[num + 2] = (array[num + 1] = (array[num] = new Vector3(num4 * 2f - 1f, num5 * 2f - 1f, 1f))));
+ array2[num] = new Vector2(0f, 0f);
+ array2[num + 1] = new Vector2(1f, 0f);
+ array2[num + 2] = new Vector2(0f, 1f);
+ array2[num + 3] = new Vector2(1f, 1f);
+ array3[num] = new Vector2(num4, num5);
+ array3[num + 1] = new Vector2(num4, num5);
+ array3[num + 2] = new Vector2(num4, num5);
+ array3[num + 3] = new Vector2(num4, num5);
+ array4[num2] = num;
+ array4[num2 + 1] = num + 1;
+ array4[num2 + 2] = num + 2;
+ array4[num2 + 3] = num + 1;
+ array4[num2 + 4] = num + 2;
+ array4[num2 + 5] = num + 3;
+ }
+ mesh.vertices = array;
+ mesh.triangles = array4;
+ mesh.uv = array2;
+ mesh.uv2 = array3;
+ return mesh;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenOverlay.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenOverlay.cs
new file mode 100644
index 0000000..5136a5e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenOverlay.cs
@@ -0,0 +1,53 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Other/Screen Overlay")]
+public class ScreenOverlay : PostEffectsBase
+{
+ public enum OverlayBlendMode
+ {
+ Additive,
+ ScreenBlend,
+ Multiply,
+ Overlay,
+ AlphaBlend
+ }
+
+ public OverlayBlendMode blendMode = OverlayBlendMode.Overlay;
+
+ public float intensity = 1f;
+
+ public Texture2D texture;
+
+ public Shader overlayShader;
+
+ private Material overlayMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ overlayMaterial = CheckShaderAndCreateMaterial(overlayShader, overlayMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ Vector4 value = new Vector4(1f, 0f, 0f, 1f);
+ overlayMaterial.SetVector("_UV_Transform", value);
+ overlayMaterial.SetFloat("_Intensity", intensity);
+ overlayMaterial.SetTexture("_Overlay", texture);
+ Graphics.Blit(source, destination, overlayMaterial, (int)blendMode);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientObscurance.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientObscurance.cs
new file mode 100644
index 0000000..b59c32e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientObscurance.cs
@@ -0,0 +1,105 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Rendering/Screen Space Ambient Obscurance")]
+internal class ScreenSpaceAmbientObscurance : PostEffectsBase
+{
+ [Range(0f, 3f)]
+ public float intensity = 0.5f;
+
+ [Range(0.1f, 3f)]
+ public float radius = 0.2f;
+
+ [Range(0f, 3f)]
+ public int blurIterations = 1;
+
+ [Range(0f, 5f)]
+ public float blurFilterDistance = 1.25f;
+
+ [Range(0f, 1f)]
+ public int downsample;
+
+ public Texture2D rand;
+
+ public Shader aoShader;
+
+ private Material aoMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: true);
+ aoMaterial = CheckShaderAndCreateMaterial(aoShader, aoMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnDisable()
+ {
+ if ((bool)aoMaterial)
+ {
+ Object.DestroyImmediate(aoMaterial);
+ }
+ aoMaterial = null;
+ }
+
+ [ImageEffectOpaque]
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ Camera component = GetComponent<Camera>();
+ Matrix4x4 projectionMatrix = component.projectionMatrix;
+ Matrix4x4 inverse = projectionMatrix.inverse;
+ Vector4 value = new Vector4(-2f / projectionMatrix[0, 0], -2f / projectionMatrix[1, 1], (1f - projectionMatrix[0, 2]) / projectionMatrix[0, 0], (1f + projectionMatrix[1, 2]) / projectionMatrix[1, 1]);
+ if (component.stereoEnabled)
+ {
+ Matrix4x4 stereoProjectionMatrix = component.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
+ Matrix4x4 stereoProjectionMatrix2 = component.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
+ Vector4 value2 = new Vector4(-2f / stereoProjectionMatrix[0, 0], -2f / stereoProjectionMatrix[1, 1], (1f - stereoProjectionMatrix[0, 2]) / stereoProjectionMatrix[0, 0], (1f + stereoProjectionMatrix[1, 2]) / stereoProjectionMatrix[1, 1]);
+ Vector4 value3 = new Vector4(-2f / stereoProjectionMatrix2[0, 0], -2f / stereoProjectionMatrix2[1, 1], (1f - stereoProjectionMatrix2[0, 2]) / stereoProjectionMatrix2[0, 0], (1f + stereoProjectionMatrix2[1, 2]) / stereoProjectionMatrix2[1, 1]);
+ aoMaterial.SetVector("_ProjInfoLeft", value2);
+ aoMaterial.SetVector("_ProjInfoRight", value3);
+ }
+ aoMaterial.SetVector("_ProjInfo", value);
+ aoMaterial.SetMatrix("_ProjectionInv", inverse);
+ aoMaterial.SetTexture("_Rand", rand);
+ aoMaterial.SetFloat("_Radius", radius);
+ aoMaterial.SetFloat("_Radius2", radius * radius);
+ aoMaterial.SetFloat("_Intensity", intensity);
+ aoMaterial.SetFloat("_BlurFilterDistance", blurFilterDistance);
+ int width = source.width;
+ int height = source.height;
+ RenderTexture renderTexture = RenderTexture.GetTemporary(width >> downsample, height >> downsample);
+ Graphics.Blit(source, renderTexture, aoMaterial, 0);
+ if (downsample > 0)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height);
+ Graphics.Blit(renderTexture, temporary, aoMaterial, 4);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ renderTexture = temporary;
+ }
+ for (int i = 0; i < blurIterations; i++)
+ {
+ aoMaterial.SetVector("_Axis", new Vector2(1f, 0f));
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height);
+ Graphics.Blit(renderTexture, temporary, aoMaterial, 1);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ aoMaterial.SetVector("_Axis", new Vector2(0f, 1f));
+ renderTexture = RenderTexture.GetTemporary(width, height);
+ Graphics.Blit(temporary, renderTexture, aoMaterial, 1);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ aoMaterial.SetTexture("_AOTex", renderTexture);
+ Graphics.Blit(source, destination, aoMaterial, 2);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientOcclusion.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientOcclusion.cs
new file mode 100644
index 0000000..108bd0e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/ScreenSpaceAmbientOcclusion.cs
@@ -0,0 +1,161 @@
+using System;
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Rendering/Screen Space Ambient Occlusion")]
+public class ScreenSpaceAmbientOcclusion : MonoBehaviour
+{
+ public enum SSAOSamples
+ {
+ Low,
+ Medium,
+ High
+ }
+
+ [Range(0.05f, 1f)]
+ public float m_Radius = 0.4f;
+
+ public SSAOSamples m_SampleCount = SSAOSamples.Medium;
+
+ [Range(0.5f, 4f)]
+ public float m_OcclusionIntensity = 1.5f;
+
+ [Range(0f, 4f)]
+ public int m_Blur = 2;
+
+ [Range(1f, 6f)]
+ public int m_Downsampling = 2;
+
+ [Range(0.2f, 2f)]
+ public float m_OcclusionAttenuation = 1f;
+
+ [Range(1E-05f, 0.5f)]
+ public float m_MinZ = 0.01f;
+
+ public Shader m_SSAOShader;
+
+ private Material m_SSAOMaterial;
+
+ public Texture2D m_RandomTexture;
+
+ private bool m_Supported;
+
+ private static Material CreateMaterial(Shader shader)
+ {
+ if (!shader)
+ {
+ return null;
+ }
+ return new Material(shader)
+ {
+ hideFlags = HideFlags.HideAndDontSave
+ };
+ }
+
+ private static void DestroyMaterial(Material mat)
+ {
+ if ((bool)mat)
+ {
+ UnityEngine.Object.DestroyImmediate(mat);
+ mat = null;
+ }
+ }
+
+ private void OnDisable()
+ {
+ DestroyMaterial(m_SSAOMaterial);
+ }
+
+ private void Start()
+ {
+ if (!SystemInfo.supportsImageEffects || !SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.Depth))
+ {
+ m_Supported = false;
+ base.enabled = false;
+ return;
+ }
+ CreateMaterials();
+ if (!m_SSAOMaterial || m_SSAOMaterial.passCount != 5)
+ {
+ m_Supported = false;
+ base.enabled = false;
+ }
+ else
+ {
+ m_Supported = true;
+ }
+ }
+
+ private void OnEnable()
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
+ }
+
+ private void CreateMaterials()
+ {
+ if (!m_SSAOMaterial && m_SSAOShader.isSupported)
+ {
+ m_SSAOMaterial = CreateMaterial(m_SSAOShader);
+ m_SSAOMaterial.SetTexture("_RandomTexture", m_RandomTexture);
+ }
+ }
+
+ [ImageEffectOpaque]
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!m_Supported || !m_SSAOShader.isSupported)
+ {
+ base.enabled = false;
+ return;
+ }
+ CreateMaterials();
+ m_Downsampling = Mathf.Clamp(m_Downsampling, 1, 6);
+ m_Radius = Mathf.Clamp(m_Radius, 0.05f, 1f);
+ m_MinZ = Mathf.Clamp(m_MinZ, 1E-05f, 0.5f);
+ m_OcclusionIntensity = Mathf.Clamp(m_OcclusionIntensity, 0.5f, 4f);
+ m_OcclusionAttenuation = Mathf.Clamp(m_OcclusionAttenuation, 0.2f, 2f);
+ m_Blur = Mathf.Clamp(m_Blur, 0, 4);
+ RenderTexture renderTexture = RenderTexture.GetTemporary(source.width / m_Downsampling, source.height / m_Downsampling, 0);
+ float fieldOfView = GetComponent<Camera>().fieldOfView;
+ float farClipPlane = GetComponent<Camera>().farClipPlane;
+ float num = Mathf.Tan(fieldOfView * ((float)Math.PI / 180f) * 0.5f) * farClipPlane;
+ float x = num * GetComponent<Camera>().aspect;
+ m_SSAOMaterial.SetVector("_FarCorner", new Vector3(x, num, farClipPlane));
+ int num2;
+ int num3;
+ if ((bool)m_RandomTexture)
+ {
+ num2 = m_RandomTexture.width;
+ num3 = m_RandomTexture.height;
+ }
+ else
+ {
+ num2 = 1;
+ num3 = 1;
+ }
+ m_SSAOMaterial.SetVector("_NoiseScale", new Vector3((float)renderTexture.width / (float)num2, (float)renderTexture.height / (float)num3, 0f));
+ m_SSAOMaterial.SetVector("_Params", new Vector4(m_Radius, m_MinZ, 1f / m_OcclusionAttenuation, m_OcclusionIntensity));
+ bool num4 = m_Blur > 0;
+ Graphics.Blit(num4 ? null : source, renderTexture, m_SSAOMaterial, (int)m_SampleCount);
+ if (num4)
+ {
+ RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0);
+ m_SSAOMaterial.SetVector("_TexelOffsetScale", new Vector4((float)m_Blur / (float)source.width, 0f, 0f, 0f));
+ m_SSAOMaterial.SetTexture("_SSAO", renderTexture);
+ Graphics.Blit(null, temporary, m_SSAOMaterial, 3);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ RenderTexture temporary2 = RenderTexture.GetTemporary(source.width, source.height, 0);
+ m_SSAOMaterial.SetVector("_TexelOffsetScale", new Vector4(0f, (float)m_Blur / (float)source.height, 0f, 0f));
+ m_SSAOMaterial.SetTexture("_SSAO", temporary);
+ Graphics.Blit(source, temporary2, m_SSAOMaterial, 3);
+ RenderTexture.ReleaseTemporary(temporary);
+ renderTexture = temporary2;
+ }
+ m_SSAOMaterial.SetTexture("_SSAO", renderTexture);
+ Graphics.Blit(source, destination, m_SSAOMaterial, 4);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SepiaTone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SepiaTone.cs
new file mode 100644
index 0000000..ff006e5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SepiaTone.cs
@@ -0,0 +1,13 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Color Adjustments/Sepia Tone")]
+public class SepiaTone : ImageEffectBase
+{
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ Graphics.Blit(source, destination, base.material);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SunShafts.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SunShafts.cs
new file mode 100644
index 0000000..b4a8006
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/SunShafts.cs
@@ -0,0 +1,134 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Rendering/Sun Shafts")]
+public class SunShafts : PostEffectsBase
+{
+ public enum SunShaftsResolution
+ {
+ Low,
+ Normal,
+ High
+ }
+
+ public enum ShaftsScreenBlendMode
+ {
+ Screen,
+ Add
+ }
+
+ public SunShaftsResolution resolution = SunShaftsResolution.Normal;
+
+ public ShaftsScreenBlendMode screenBlendMode;
+
+ public Transform sunTransform;
+
+ public int radialBlurIterations = 2;
+
+ public Color sunColor = Color.white;
+
+ public Color sunThreshold = new Color(0.87f, 0.74f, 0.65f);
+
+ public float sunShaftBlurRadius = 2.5f;
+
+ public float sunShaftIntensity = 1.15f;
+
+ public float maxRadius = 0.75f;
+
+ public bool useDepthTexture = true;
+
+ public Shader sunShaftsShader;
+
+ private Material sunShaftsMaterial;
+
+ public Shader simpleClearShader;
+
+ private Material simpleClearMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(useDepthTexture);
+ sunShaftsMaterial = CheckShaderAndCreateMaterial(sunShaftsShader, sunShaftsMaterial);
+ simpleClearMaterial = CheckShaderAndCreateMaterial(simpleClearShader, simpleClearMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ if (useDepthTexture)
+ {
+ GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
+ }
+ int num = 4;
+ if (resolution == SunShaftsResolution.Normal)
+ {
+ num = 2;
+ }
+ else if (resolution == SunShaftsResolution.High)
+ {
+ num = 1;
+ }
+ Vector3 vector = Vector3.one * 0.5f;
+ vector = ((!sunTransform) ? new Vector3(0.5f, 0.5f, 0f) : GetComponent<Camera>().WorldToViewportPoint(sunTransform.position));
+ int width = source.width / num;
+ int height = source.height / num;
+ RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0);
+ sunShaftsMaterial.SetVector("_BlurRadius4", new Vector4(1f, 1f, 0f, 0f) * sunShaftBlurRadius);
+ sunShaftsMaterial.SetVector("_SunPosition", new Vector4(vector.x, vector.y, vector.z, maxRadius));
+ sunShaftsMaterial.SetVector("_SunThreshold", sunThreshold);
+ if (!useDepthTexture)
+ {
+ RenderTextureFormat format = (GetComponent<Camera>().allowHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);
+ RenderTexture renderTexture = (RenderTexture.active = RenderTexture.GetTemporary(source.width, source.height, 0, format));
+ GL.ClearWithSkybox(clearDepth: false, GetComponent<Camera>());
+ sunShaftsMaterial.SetTexture("_Skybox", renderTexture);
+ Graphics.Blit(source, temporary, sunShaftsMaterial, 3);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+ else
+ {
+ Graphics.Blit(source, temporary, sunShaftsMaterial, 2);
+ }
+ DrawBorder(temporary, simpleClearMaterial);
+ radialBlurIterations = Mathf.Clamp(radialBlurIterations, 1, 4);
+ float num2 = sunShaftBlurRadius * 0.0013020834f;
+ sunShaftsMaterial.SetVector("_BlurRadius4", new Vector4(num2, num2, 0f, 0f));
+ sunShaftsMaterial.SetVector("_SunPosition", new Vector4(vector.x, vector.y, vector.z, maxRadius));
+ for (int i = 0; i < radialBlurIterations; i++)
+ {
+ RenderTexture temporary3 = RenderTexture.GetTemporary(width, height, 0);
+ Graphics.Blit(temporary, temporary3, sunShaftsMaterial, 1);
+ RenderTexture.ReleaseTemporary(temporary);
+ num2 = sunShaftBlurRadius * (((float)i * 2f + 1f) * 6f) / 768f;
+ sunShaftsMaterial.SetVector("_BlurRadius4", new Vector4(num2, num2, 0f, 0f));
+ temporary = RenderTexture.GetTemporary(width, height, 0);
+ Graphics.Blit(temporary3, temporary, sunShaftsMaterial, 1);
+ RenderTexture.ReleaseTemporary(temporary3);
+ num2 = sunShaftBlurRadius * (((float)i * 2f + 2f) * 6f) / 768f;
+ sunShaftsMaterial.SetVector("_BlurRadius4", new Vector4(num2, num2, 0f, 0f));
+ }
+ if (vector.z >= 0f)
+ {
+ sunShaftsMaterial.SetVector("_SunColor", new Vector4(sunColor.r, sunColor.g, sunColor.b, sunColor.a) * sunShaftIntensity);
+ }
+ else
+ {
+ sunShaftsMaterial.SetVector("_SunColor", Vector4.zero);
+ }
+ sunShaftsMaterial.SetTexture("_ColorBuffer", temporary);
+ Graphics.Blit(source, destination, sunShaftsMaterial, (screenBlendMode != 0) ? 4 : 0);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TiltShift.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TiltShift.cs
new file mode 100644
index 0000000..9258c81
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TiltShift.cs
@@ -0,0 +1,80 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Camera/Tilt Shift (Lens Blur)")]
+internal class TiltShift : PostEffectsBase
+{
+ public enum TiltShiftMode
+ {
+ TiltShiftMode,
+ IrisMode
+ }
+
+ public enum TiltShiftQuality
+ {
+ Preview,
+ Low,
+ Normal,
+ High
+ }
+
+ public TiltShiftMode mode;
+
+ public TiltShiftQuality quality = TiltShiftQuality.Normal;
+
+ [Range(0f, 15f)]
+ public float blurArea = 1f;
+
+ [Range(0f, 25f)]
+ public float maxBlurSize = 5f;
+
+ [Range(0f, 1f)]
+ public int downsample;
+
+ public Shader tiltShiftShader;
+
+ private Material tiltShiftMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ tiltShiftMaterial = CheckShaderAndCreateMaterial(tiltShiftShader, tiltShiftMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ tiltShiftMaterial.SetFloat("_BlurSize", (maxBlurSize < 0f) ? 0f : maxBlurSize);
+ tiltShiftMaterial.SetFloat("_BlurArea", blurArea);
+ source.filterMode = FilterMode.Bilinear;
+ RenderTexture renderTexture = destination;
+ if ((float)downsample > 0f)
+ {
+ renderTexture = RenderTexture.GetTemporary(source.width >> downsample, source.height >> downsample, 0, source.format);
+ renderTexture.filterMode = FilterMode.Bilinear;
+ }
+ int num = (int)quality;
+ num *= 2;
+ Graphics.Blit(source, renderTexture, tiltShiftMaterial, (mode == TiltShiftMode.TiltShiftMode) ? num : (num + 1));
+ if (downsample > 0)
+ {
+ tiltShiftMaterial.SetTexture("_Blurred", renderTexture);
+ Graphics.Blit(source, destination, tiltShiftMaterial, 8);
+ }
+ if (renderTexture != destination)
+ {
+ RenderTexture.ReleaseTemporary(renderTexture);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Tonemapping.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Tonemapping.cs
new file mode 100644
index 0000000..bd41109
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Tonemapping.cs
@@ -0,0 +1,226 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Color Adjustments/Tonemapping")]
+public class Tonemapping : PostEffectsBase
+{
+ public enum TonemapperType
+ {
+ SimpleReinhard,
+ UserCurve,
+ Hable,
+ Photographic,
+ OptimizedHejiDawson,
+ AdaptiveReinhard,
+ AdaptiveReinhardAutoWhite
+ }
+
+ public enum AdaptiveTexSize
+ {
+ Square16 = 0x10,
+ Square32 = 0x20,
+ Square64 = 0x40,
+ Square128 = 0x80,
+ Square256 = 0x100,
+ Square512 = 0x200,
+ Square1024 = 0x400
+ }
+
+ public TonemapperType type = TonemapperType.Photographic;
+
+ public AdaptiveTexSize adaptiveTextureSize = AdaptiveTexSize.Square256;
+
+ public AnimationCurve remapCurve;
+
+ private Texture2D curveTex;
+
+ public float exposureAdjustment = 1.5f;
+
+ public float middleGrey = 0.4f;
+
+ public float white = 2f;
+
+ public float adaptionSpeed = 1.5f;
+
+ public Shader tonemapper;
+
+ public bool validRenderTextureFormat = true;
+
+ private Material tonemapMaterial;
+
+ private RenderTexture rt;
+
+ private RenderTextureFormat rtFormat = RenderTextureFormat.ARGBHalf;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false, needHdr: true);
+ tonemapMaterial = CheckShaderAndCreateMaterial(tonemapper, tonemapMaterial);
+ if (!curveTex && type == TonemapperType.UserCurve)
+ {
+ curveTex = new Texture2D(256, 1, TextureFormat.ARGB32, mipChain: false, linear: true);
+ curveTex.filterMode = FilterMode.Bilinear;
+ curveTex.wrapMode = TextureWrapMode.Clamp;
+ curveTex.hideFlags = HideFlags.DontSave;
+ }
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ public float UpdateCurve()
+ {
+ float num = 1f;
+ if (remapCurve.keys.Length < 1)
+ {
+ remapCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(2f, 1f));
+ }
+ if (remapCurve != null)
+ {
+ if (remapCurve.length > 0)
+ {
+ num = remapCurve[remapCurve.length - 1].time;
+ }
+ for (float num2 = 0f; num2 <= 1f; num2 += 0.003921569f)
+ {
+ float num3 = remapCurve.Evaluate(num2 * 1f * num);
+ curveTex.SetPixel((int)Mathf.Floor(num2 * 255f), 0, new Color(num3, num3, num3));
+ }
+ curveTex.Apply();
+ }
+ return 1f / num;
+ }
+
+ private void OnDisable()
+ {
+ if ((bool)rt)
+ {
+ Object.DestroyImmediate(rt);
+ rt = null;
+ }
+ if ((bool)tonemapMaterial)
+ {
+ Object.DestroyImmediate(tonemapMaterial);
+ tonemapMaterial = null;
+ }
+ if ((bool)curveTex)
+ {
+ Object.DestroyImmediate(curveTex);
+ curveTex = null;
+ }
+ }
+
+ private bool CreateInternalRenderTexture()
+ {
+ if ((bool)rt)
+ {
+ return false;
+ }
+ rtFormat = (SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf) ? RenderTextureFormat.RGHalf : RenderTextureFormat.ARGBHalf);
+ rt = new RenderTexture(1, 1, 0, rtFormat);
+ rt.hideFlags = HideFlags.DontSave;
+ return true;
+ }
+
+ [ImageEffectTransformsToLDR]
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ exposureAdjustment = ((exposureAdjustment < 0.001f) ? 0.001f : exposureAdjustment);
+ if (type == TonemapperType.UserCurve)
+ {
+ float value = UpdateCurve();
+ tonemapMaterial.SetFloat("_RangeScale", value);
+ tonemapMaterial.SetTexture("_Curve", curveTex);
+ Graphics.Blit(source, destination, tonemapMaterial, 4);
+ return;
+ }
+ if (type == TonemapperType.SimpleReinhard)
+ {
+ tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
+ Graphics.Blit(source, destination, tonemapMaterial, 6);
+ return;
+ }
+ if (type == TonemapperType.Hable)
+ {
+ tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
+ Graphics.Blit(source, destination, tonemapMaterial, 5);
+ return;
+ }
+ if (type == TonemapperType.Photographic)
+ {
+ tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
+ Graphics.Blit(source, destination, tonemapMaterial, 8);
+ return;
+ }
+ if (type == TonemapperType.OptimizedHejiDawson)
+ {
+ tonemapMaterial.SetFloat("_ExposureAdjustment", 0.5f * exposureAdjustment);
+ Graphics.Blit(source, destination, tonemapMaterial, 7);
+ return;
+ }
+ bool flag = CreateInternalRenderTexture();
+ RenderTexture temporary = RenderTexture.GetTemporary((int)adaptiveTextureSize, (int)adaptiveTextureSize, 0, rtFormat);
+ Graphics.Blit(source, temporary);
+ int num = (int)Mathf.Log((float)temporary.width * 1f, 2f);
+ int num2 = 2;
+ RenderTexture[] array = new RenderTexture[num];
+ for (int i = 0; i < num; i++)
+ {
+ array[i] = RenderTexture.GetTemporary(temporary.width / num2, temporary.width / num2, 0, rtFormat);
+ num2 *= 2;
+ }
+ RenderTexture source2 = array[num - 1];
+ Graphics.Blit(temporary, array[0], tonemapMaterial, 1);
+ if (type == TonemapperType.AdaptiveReinhardAutoWhite)
+ {
+ for (int j = 0; j < num - 1; j++)
+ {
+ Graphics.Blit(array[j], array[j + 1], tonemapMaterial, 9);
+ source2 = array[j + 1];
+ }
+ }
+ else if (type == TonemapperType.AdaptiveReinhard)
+ {
+ for (int k = 0; k < num - 1; k++)
+ {
+ Graphics.Blit(array[k], array[k + 1]);
+ source2 = array[k + 1];
+ }
+ }
+ adaptionSpeed = ((adaptionSpeed < 0.001f) ? 0.001f : adaptionSpeed);
+ tonemapMaterial.SetFloat("_AdaptionSpeed", adaptionSpeed);
+ rt.MarkRestoreExpected();
+ Graphics.Blit(source2, rt, tonemapMaterial, flag ? 3 : 2);
+ middleGrey = ((middleGrey < 0.001f) ? 0.001f : middleGrey);
+ tonemapMaterial.SetVector("_HdrParams", new Vector4(middleGrey, middleGrey, middleGrey, white * white));
+ tonemapMaterial.SetTexture("_SmallTex", rt);
+ if (type == TonemapperType.AdaptiveReinhard)
+ {
+ Graphics.Blit(source, destination, tonemapMaterial, 0);
+ }
+ else if (type == TonemapperType.AdaptiveReinhardAutoWhite)
+ {
+ Graphics.Blit(source, destination, tonemapMaterial, 10);
+ }
+ else
+ {
+ Debug.LogError("No valid adaptive tonemapper type found!");
+ Graphics.Blit(source, destination);
+ }
+ for (int l = 0; l < num; l++)
+ {
+ RenderTexture.ReleaseTemporary(array[l]);
+ }
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Triangles.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Triangles.cs
new file mode 100644
index 0000000..3a79391
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Triangles.cs
@@ -0,0 +1,95 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+internal class Triangles
+{
+ private static Mesh[] meshes;
+
+ private static int currentTris;
+
+ private static bool HasMeshes()
+ {
+ if (meshes == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < meshes.Length; i++)
+ {
+ if (null == meshes[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void Cleanup()
+ {
+ if (meshes == null)
+ {
+ return;
+ }
+ for (int i = 0; i < meshes.Length; i++)
+ {
+ if (null != meshes[i])
+ {
+ Object.DestroyImmediate(meshes[i]);
+ meshes[i] = null;
+ }
+ }
+ meshes = null;
+ }
+
+ private static Mesh[] GetMeshes(int totalWidth, int totalHeight)
+ {
+ if (HasMeshes() && currentTris == totalWidth * totalHeight)
+ {
+ return meshes;
+ }
+ int num = 21666;
+ int num2 = (currentTris = totalWidth * totalHeight);
+ meshes = new Mesh[Mathf.CeilToInt(1f * (float)num2 / (1f * (float)num))];
+ int num3 = 0;
+ int num4 = 0;
+ for (num3 = 0; num3 < num2; num3 += num)
+ {
+ int triCount = Mathf.FloorToInt(Mathf.Clamp(num2 - num3, 0, num));
+ meshes[num4] = GetMesh(triCount, num3, totalWidth, totalHeight);
+ num4++;
+ }
+ return meshes;
+ }
+
+ private static Mesh GetMesh(int triCount, int triOffset, int totalWidth, int totalHeight)
+ {
+ Mesh mesh = new Mesh();
+ mesh.hideFlags = HideFlags.DontSave;
+ Vector3[] array = new Vector3[triCount * 3];
+ Vector2[] array2 = new Vector2[triCount * 3];
+ Vector2[] array3 = new Vector2[triCount * 3];
+ int[] array4 = new int[triCount * 3];
+ for (int i = 0; i < triCount; i++)
+ {
+ int num = i * 3;
+ int num2 = triOffset + i;
+ float num3 = Mathf.Floor(num2 % totalWidth) / (float)totalWidth;
+ float num4 = Mathf.Floor(num2 / totalWidth) / (float)totalHeight;
+ array[num + 2] = (array[num + 1] = (array[num] = new Vector3(num3 * 2f - 1f, num4 * 2f - 1f, 1f)));
+ array2[num] = new Vector2(0f, 0f);
+ array2[num + 1] = new Vector2(1f, 0f);
+ array2[num + 2] = new Vector2(0f, 1f);
+ array3[num] = new Vector2(num3, num4);
+ array3[num + 1] = new Vector2(num3, num4);
+ array3[num + 2] = new Vector2(num3, num4);
+ array4[num] = num;
+ array4[num + 1] = num + 1;
+ array4[num + 2] = num + 2;
+ }
+ mesh.vertices = array;
+ mesh.triangles = array4;
+ mesh.uv = array2;
+ mesh.uv2 = array3;
+ return mesh;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TweakMode34.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TweakMode34.cs
new file mode 100644
index 0000000..6d04716
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/TweakMode34.cs
@@ -0,0 +1,7 @@
+namespace UnityStandardAssets.ImageEffects;
+
+public enum TweakMode34
+{
+ Basic,
+ Complex
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Twirl.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Twirl.cs
new file mode 100644
index 0000000..2e660ec
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Twirl.cs
@@ -0,0 +1,20 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Displacement/Twirl")]
+public class Twirl : ImageEffectBase
+{
+ public Vector2 radius = new Vector2(0.3f, 0.3f);
+
+ [Range(0f, 360f)]
+ public float angle = 50f;
+
+ public Vector2 center = new Vector2(0.5f, 0.5f);
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ ImageEffects.RenderDistortion(base.material, source, destination, angle, center, radius);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/VignetteAndChromaticAberration.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/VignetteAndChromaticAberration.cs
new file mode 100644
index 0000000..df2e56c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/VignetteAndChromaticAberration.cs
@@ -0,0 +1,110 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[RequireComponent(typeof(Camera))]
+[AddComponentMenu("Image Effects/Camera/Vignette and Chromatic Aberration")]
+public class VignetteAndChromaticAberration : PostEffectsBase
+{
+ public enum AberrationMode
+ {
+ Simple,
+ Advanced
+ }
+
+ public AberrationMode mode;
+
+ public float intensity = 0.036f;
+
+ public float chromaticAberration = 0.2f;
+
+ public float axialAberration = 0.5f;
+
+ public float blur;
+
+ public float blurSpread = 0.75f;
+
+ public float luminanceDependency = 0.25f;
+
+ public float blurDistance = 2.5f;
+
+ public Shader vignetteShader;
+
+ public Shader separableBlurShader;
+
+ public Shader chromAberrationShader;
+
+ private Material m_VignetteMaterial;
+
+ private Material m_SeparableBlurMaterial;
+
+ private Material m_ChromAberrationMaterial;
+
+ public override bool CheckResources()
+ {
+ CheckSupport(needDepth: false);
+ m_VignetteMaterial = CheckShaderAndCreateMaterial(vignetteShader, m_VignetteMaterial);
+ m_SeparableBlurMaterial = CheckShaderAndCreateMaterial(separableBlurShader, m_SeparableBlurMaterial);
+ m_ChromAberrationMaterial = CheckShaderAndCreateMaterial(chromAberrationShader, m_ChromAberrationMaterial);
+ if (!isSupported)
+ {
+ ReportAutoDisable();
+ }
+ return isSupported;
+ }
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ if (!CheckResources())
+ {
+ Graphics.Blit(source, destination);
+ return;
+ }
+ int width = source.width;
+ int height = source.height;
+ bool flag = Mathf.Abs(blur) > 0f || Mathf.Abs(intensity) > 0f;
+ float num = 1f * (float)width / (1f * (float)height);
+ RenderTexture renderTexture = null;
+ RenderTexture renderTexture2 = null;
+ if (flag)
+ {
+ renderTexture = RenderTexture.GetTemporary(width, height, 0, source.format);
+ if (Mathf.Abs(blur) > 0f)
+ {
+ renderTexture2 = RenderTexture.GetTemporary(width / 2, height / 2, 0, source.format);
+ Graphics.Blit(source, renderTexture2, m_ChromAberrationMaterial, 0);
+ for (int i = 0; i < 2; i++)
+ {
+ m_SeparableBlurMaterial.SetVector("offsets", new Vector4(0f, blurSpread * 0.001953125f, 0f, 0f));
+ RenderTexture temporary = RenderTexture.GetTemporary(width / 2, height / 2, 0, source.format);
+ Graphics.Blit(renderTexture2, temporary, m_SeparableBlurMaterial);
+ RenderTexture.ReleaseTemporary(renderTexture2);
+ m_SeparableBlurMaterial.SetVector("offsets", new Vector4(blurSpread * 0.001953125f / num, 0f, 0f, 0f));
+ renderTexture2 = RenderTexture.GetTemporary(width / 2, height / 2, 0, source.format);
+ Graphics.Blit(temporary, renderTexture2, m_SeparableBlurMaterial);
+ RenderTexture.ReleaseTemporary(temporary);
+ }
+ }
+ m_VignetteMaterial.SetFloat("_Intensity", 1f / (1f - intensity) - 1f);
+ m_VignetteMaterial.SetFloat("_Blur", 1f / (1f - blur) - 1f);
+ m_VignetteMaterial.SetTexture("_VignetteTex", renderTexture2);
+ Graphics.Blit(source, renderTexture, m_VignetteMaterial, 0);
+ }
+ m_ChromAberrationMaterial.SetFloat("_ChromaticAberration", chromaticAberration);
+ m_ChromAberrationMaterial.SetFloat("_AxialAberration", axialAberration);
+ m_ChromAberrationMaterial.SetVector("_BlurDistance", new Vector2(0f - blurDistance, blurDistance));
+ m_ChromAberrationMaterial.SetFloat("_Luminance", 1f / Mathf.Max(Mathf.Epsilon, luminanceDependency));
+ if (flag)
+ {
+ renderTexture.wrapMode = TextureWrapMode.Clamp;
+ }
+ else
+ {
+ source.wrapMode = TextureWrapMode.Clamp;
+ }
+ Graphics.Blit(flag ? renderTexture : source, destination, m_ChromAberrationMaterial, (mode != AberrationMode.Advanced) ? 1 : 2);
+ RenderTexture.ReleaseTemporary(renderTexture);
+ RenderTexture.ReleaseTemporary(renderTexture2);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Vortex.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Vortex.cs
new file mode 100644
index 0000000..17ac440
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/UnityStandardAssets.ImageEffects/Vortex.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+namespace UnityStandardAssets.ImageEffects;
+
+[ExecuteInEditMode]
+[AddComponentMenu("Image Effects/Displacement/Vortex")]
+public class Vortex : ImageEffectBase
+{
+ public Vector2 radius = new Vector2(0.4f, 0.4f);
+
+ public float angle = 50f;
+
+ public Vector2 center = new Vector2(0.5f, 0.5f);
+
+ private void OnRenderImage(RenderTexture source, RenderTexture destination)
+ {
+ ImageEffects.RenderDistortion(base.material, source, destination, angle, center, radius);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/assembly_sunshafts.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/assembly_sunshafts.csproj
new file mode 100644
index 0000000..5b6a839
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_sunshafts/assembly_sunshafts.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_sunshafts</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/BitMaskAttribute.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/BitMaskAttribute.cs
new file mode 100644
index 0000000..fce668b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/BitMaskAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+using UnityEngine;
+
+public class BitMaskAttribute : PropertyAttribute
+{
+ public Type propType;
+
+ public BitMaskAttribute(Type aType)
+ {
+ propType = aType;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Cover.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Cover.cs
new file mode 100644
index 0000000..73e7288
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Cover.cs
@@ -0,0 +1,82 @@
+using UnityEngine;
+
+public class Cover
+{
+ private const float m_coverRayDistance = 30f;
+
+ private static int m_coverRayMask = 0;
+
+ private static Vector3[] m_coverRays = null;
+
+ private static RaycastHit[] m_raycastHits = new RaycastHit[128];
+
+ public static void GetCoverForPoint(Vector3 startPos, out float coverPercentage, out bool underRoof)
+ {
+ Setup();
+ float num = 0.5f;
+ float num2 = 0f;
+ underRoof = IsUnderRoof(startPos);
+ Vector3[] coverRays = m_coverRays;
+ foreach (Vector3 vector in coverRays)
+ {
+ if (Physics.Raycast(startPos + vector * num, vector, out var _, 30f - num, m_coverRayMask))
+ {
+ num2 += 1f;
+ }
+ }
+ coverPercentage = num2 / (float)m_coverRays.Length;
+ }
+
+ public static bool IsUnderRoof(Vector3 startPos)
+ {
+ Setup();
+ int num = Physics.SphereCastNonAlloc(startPos, 0.1f, Vector3.up, m_raycastHits, 100f, m_coverRayMask);
+ for (int i = 0; i < num; i++)
+ {
+ RaycastHit raycastHit = m_raycastHits[i];
+ if (!raycastHit.collider.gameObject.CompareTag("leaky"))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void Setup()
+ {
+ if (m_coverRays == null)
+ {
+ m_coverRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain", "vehicle");
+ CreateCoverRays();
+ }
+ }
+
+ private static void CreateCoverRays()
+ {
+ m_coverRays = new Vector3[17]
+ {
+ new Vector3(0f, 1f, 0f),
+ new Vector3(1f, 0f, 0f),
+ new Vector3(-1f, 0f, 0f),
+ new Vector3(0f, 0f, 1f),
+ new Vector3(0f, 0f, -1f),
+ new Vector3(-1f, 0f, -1f),
+ new Vector3(1f, 0f, -1f),
+ new Vector3(-1f, 0f, 1f),
+ new Vector3(1f, 0f, 1f),
+ new Vector3(-1f, 1f, 0f),
+ new Vector3(1f, 1f, 0f),
+ new Vector3(0f, 1f, 1f),
+ new Vector3(0f, 1f, -1f),
+ new Vector3(-1f, 1f, -1f),
+ new Vector3(1f, 1f, -1f),
+ new Vector3(-1f, 1f, 1f),
+ new Vector3(1f, 1f, 1f)
+ };
+ Vector3[] coverRays = m_coverRays;
+ foreach (Vector3 vector in coverRays)
+ {
+ vector.Normalize();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DictionaryExt.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DictionaryExt.cs
new file mode 100644
index 0000000..91db22f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DictionaryExt.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+public static class DictionaryExt
+{
+ public static void Copy<TKey, TValue>(this Dictionary<TKey, TValue> target, Dictionary<TKey, TValue> other)
+ {
+ foreach (KeyValuePair<TKey, TValue> item in other)
+ {
+ target.Add(item.Key, item.Value);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DrawBounds.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DrawBounds.cs
new file mode 100644
index 0000000..a30a2da
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/DrawBounds.cs
@@ -0,0 +1,16 @@
+using UnityEngine;
+
+public class DrawBounds : MonoBehaviour
+{
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.magenta;
+ MeshFilter[] componentsInChildren = GetComponentsInChildren<MeshFilter>();
+ foreach (MeshFilter obj in componentsInChildren)
+ {
+ Gizmos.matrix = obj.transform.localToWorldMatrix;
+ Mesh sharedMesh = obj.sharedMesh;
+ Gizmos.DrawWireCube(sharedMesh.bounds.center, sharedMesh.bounds.size);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/HideWhenRunning.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/HideWhenRunning.cs
new file mode 100644
index 0000000..7046876
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/HideWhenRunning.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+
+public class HideWhenRunning : MonoBehaviour
+{
+ private void Awake()
+ {
+ if (Application.isPlaying)
+ {
+ base.gameObject.SetActive(value: false);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ListExtra.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ListExtra.cs
new file mode 100644
index 0000000..d74fb9d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ListExtra.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Linq;
+
+public static class ListExtra
+{
+ public static void Resize<T>(this List<T> list, int sz, T c)
+ {
+ int count = list.Count;
+ if (sz < count)
+ {
+ list.RemoveRange(sz, count - sz);
+ }
+ else if (sz > count)
+ {
+ if (sz > list.Capacity)
+ {
+ list.Capacity = sz;
+ }
+ list.AddRange(Enumerable.Repeat(c, sz - count));
+ }
+ }
+
+ public static void Resize<T>(this List<T> list, int sz) where T : new()
+ {
+ list.Resize(sz, new T());
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/LookAt.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/LookAt.cs
new file mode 100644
index 0000000..7e4a065
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/LookAt.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+
+public class LookAt : MonoBehaviour
+{
+ private Vector3 m_lookAtTarget = Vector3.zero;
+
+ private float m_weight;
+
+ private float m_targetWeight;
+
+ private Animator m_animator;
+
+ private void Awake()
+ {
+ m_animator = GetComponent<Animator>();
+ }
+
+ private void OnAnimatorIK(int layerIndex)
+ {
+ m_weight = Mathf.MoveTowards(m_weight, m_targetWeight, Time.deltaTime);
+ m_animator.SetLookAtPosition(m_lookAtTarget);
+ m_animator.SetLookAtWeight(m_weight, 0.5f, 1f, 0f);
+ }
+
+ public void SetLoockAtTarget(Vector3 target)
+ {
+ m_lookAtTarget = target;
+ m_targetWeight = 1f;
+ }
+
+ public void ResetTarget()
+ {
+ m_targetWeight = 0f;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Pool.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Pool.cs
new file mode 100644
index 0000000..9d99e7f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Pool.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+public class Pool<T> where T : new()
+{
+ private static Stack<T> _available = new Stack<T>();
+
+ public static T Create()
+ {
+ lock (_available)
+ {
+ if (_available.Count > 0)
+ {
+ return _available.Pop();
+ }
+ return new T();
+ }
+ }
+
+ public static void Release(T obj)
+ {
+ if (obj == null)
+ {
+ return;
+ }
+ lock (_available)
+ {
+ _available.Push(obj);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/QuaternionExt.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/QuaternionExt.cs
new file mode 100644
index 0000000..f6ecdee
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/QuaternionExt.cs
@@ -0,0 +1,10 @@
+using UnityEngine;
+
+public static class QuaternionExt
+{
+ public static Quaternion GetNormalized(this Quaternion q)
+ {
+ float num = 1f / Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
+ return new Quaternion(q.x * num, q.y * num, q.z * num, q.w * num);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/StringExtensionMethods.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/StringExtensionMethods.cs
new file mode 100644
index 0000000..9bd7e45
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/StringExtensionMethods.cs
@@ -0,0 +1,18 @@
+public static class StringExtensionMethods
+{
+ public static int GetStableHashCode(this string str)
+ {
+ int num = 5381;
+ int num2 = num;
+ for (int i = 0; i < str.Length && str[i] != 0; i += 2)
+ {
+ num = ((num << 5) + num) ^ str[i];
+ if (i == str.Length - 1 || str[i + 1] == '\0')
+ {
+ break;
+ }
+ num2 = ((num2 << 5) + num2) ^ str[i + 1];
+ }
+ return num + num2 * 1566083941;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/SyncedList.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/SyncedList.cs
new file mode 100644
index 0000000..0dfb10b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/SyncedList.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public class SyncedList
+{
+ private const float m_loadInterval = 10f;
+
+ private float m_lastLoadCheckTime;
+
+ private List<string> m_comments = new List<string>();
+
+ private List<string> m_list = new List<string>();
+
+ private string m_fileName;
+
+ private DateTime m_lastLoadDate = DateTime.MinValue;
+
+ public SyncedList(string fileName, string defaultFileComment)
+ {
+ m_fileName = fileName;
+ if (!File.Exists(m_fileName))
+ {
+ m_comments.Add("// " + defaultFileComment);
+ Save();
+ }
+ else
+ {
+ Load();
+ }
+ }
+
+ public List<string> GetList()
+ {
+ CheckLoad();
+ return m_list;
+ }
+
+ public int Count()
+ {
+ CheckLoad();
+ return m_list.Count;
+ }
+
+ public bool Contains(string s)
+ {
+ CheckLoad();
+ return m_list.Contains(s);
+ }
+
+ public void Add(string s)
+ {
+ Load();
+ if (!m_list.Contains(s))
+ {
+ m_list.Add(s);
+ Save();
+ }
+ }
+
+ public void Remove(string s)
+ {
+ Load();
+ if (m_list.Remove(s))
+ {
+ Save();
+ }
+ }
+
+ private void Save()
+ {
+ using (StreamWriter streamWriter = new StreamWriter(m_fileName))
+ {
+ foreach (string comment in m_comments)
+ {
+ streamWriter.WriteLine(comment);
+ }
+ foreach (string item in m_list)
+ {
+ streamWriter.WriteLine(item);
+ }
+ }
+ m_lastLoadDate = File.GetLastWriteTime(m_fileName);
+ }
+
+ private void CheckLoad()
+ {
+ if (Time.realtimeSinceStartup - m_lastLoadCheckTime > 10f)
+ {
+ Load();
+ m_lastLoadCheckTime = Time.realtimeSinceStartup;
+ }
+ }
+
+ private void Load()
+ {
+ try
+ {
+ DateTime lastWriteTime = File.GetLastWriteTime(m_fileName);
+ if (lastWriteTime <= m_lastLoadDate)
+ {
+ return;
+ }
+ m_lastLoadDate = lastWriteTime;
+ m_comments.Clear();
+ m_list.Clear();
+ using StreamReader streamReader = new StreamReader(m_fileName);
+ string text;
+ while ((text = streamReader.ReadLine()) != null)
+ {
+ if (text.Length > 0)
+ {
+ if (text.StartsWith("//"))
+ {
+ m_comments.Add(text);
+ }
+ else
+ {
+ m_list.Add(text);
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Timer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Timer.cs
new file mode 100644
index 0000000..3f2fdec
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Timer.cs
@@ -0,0 +1,51 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public class Timer
+{
+ public float m_interval;
+
+ private float m_startTime = -1f;
+
+ private bool m_started;
+
+ public Timer(float interval)
+ {
+ m_interval = interval;
+ }
+
+ public Timer()
+ {
+ }
+
+ public void SetInerval(float i)
+ {
+ m_interval = i;
+ }
+
+ public void Start()
+ {
+ m_startTime = Time.time;
+ m_started = true;
+ }
+
+ public void Stop()
+ {
+ m_started = false;
+ }
+
+ public bool IsStarted()
+ {
+ return m_started;
+ }
+
+ public bool IsDue()
+ {
+ if (m_started)
+ {
+ return Time.time >= m_startTime + m_interval;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/TriggerTracker.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/TriggerTracker.cs
new file mode 100644
index 0000000..d6a2fb0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/TriggerTracker.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class TriggerTracker : MonoBehaviour
+{
+ public Action m_changed;
+
+ private List<Collider> m_colliders = new List<Collider>();
+
+ private void OnTriggerEnter(Collider other)
+ {
+ if (!m_colliders.Contains(other))
+ {
+ m_colliders.Add(other);
+ }
+ m_changed();
+ }
+
+ private void OnTriggerExit(Collider other)
+ {
+ m_colliders.Remove(other);
+ m_changed();
+ }
+
+ public bool IsColliding()
+ {
+ return m_colliders.Count > 0;
+ }
+
+ public List<Collider> GetColliders()
+ {
+ return m_colliders;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Utils.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Utils.cs
new file mode 100644
index 0000000..969742d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Utils.cs
@@ -0,0 +1,504 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.NetworkInformation;
+using UnityEngine;
+
+public static class Utils
+{
+ private static Plane[] mainPlanes;
+
+ private static int lastPlaneFrame = -1;
+
+ private static int lastFrameCheck = 0;
+
+ private static Camera lastMainCamera = null;
+
+ public static bool InsideMainCamera(Bounds bounds)
+ {
+ Plane[] mainCameraFrustumPlanes = GetMainCameraFrustumPlanes();
+ if (mainCameraFrustumPlanes == null)
+ {
+ return false;
+ }
+ return GeometryUtility.TestPlanesAABB(mainCameraFrustumPlanes, bounds);
+ }
+
+ public static bool InsideMainCamera(BoundingSphere bounds)
+ {
+ Plane[] mainCameraFrustumPlanes = GetMainCameraFrustumPlanes();
+ if (mainCameraFrustumPlanes == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < mainCameraFrustumPlanes.Length; i++)
+ {
+ if (mainCameraFrustumPlanes[i].GetDistanceToPoint(bounds.position) < 0f - bounds.radius)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static Plane[] GetMainCameraFrustumPlanes()
+ {
+ Camera mainCamera = GetMainCamera();
+ if ((bool)mainCamera)
+ {
+ if (Time.frameCount != lastPlaneFrame)
+ {
+ mainPlanes = GeometryUtility.CalculateFrustumPlanes(mainCamera);
+ lastPlaneFrame = Time.frameCount;
+ }
+ return mainPlanes;
+ }
+ return null;
+ }
+
+ public static Camera GetMainCamera()
+ {
+ int frameCount = Time.frameCount;
+ if (lastFrameCheck == frameCount)
+ {
+ return lastMainCamera;
+ }
+ lastMainCamera = Camera.main;
+ lastFrameCheck = frameCount;
+ return lastMainCamera;
+ }
+
+ public static Color Vec3ToColor(Vector3 c)
+ {
+ return new Color(c.x, c.y, c.z);
+ }
+
+ public static Vector3 ColorToVec3(Color c)
+ {
+ return new Vector3(c.r, c.g, c.b);
+ }
+
+ public static float LerpStep(float l, float h, float v)
+ {
+ return Mathf.Clamp01((v - l) / (h - l));
+ }
+
+ public static float SmoothStep(float p_Min, float p_Max, float p_X)
+ {
+ float num = Mathf.Clamp01((p_X - p_Min) / (p_Max - p_Min));
+ return num * num * (3f - 2f * num);
+ }
+
+ public static double LerpStep(double l, double h, double v)
+ {
+ return Clamp01((v - l) / (h - l));
+ }
+
+ public static double Clamp01(double v)
+ {
+ if (v > 1.0)
+ {
+ return 1.0;
+ }
+ if (v < 0.0)
+ {
+ return 0.0;
+ }
+ return v;
+ }
+
+ public static float Fbm(Vector3 p, int octaves, float lacunarity, float gain)
+ {
+ return Fbm(new Vector2(p.x, p.z), octaves, lacunarity, gain);
+ }
+
+ public static float FbmMaxValue(int octaves, float gain)
+ {
+ float num = 0f;
+ float num2 = 1f;
+ for (int i = 0; i < octaves; i++)
+ {
+ num += num2;
+ num2 *= gain;
+ }
+ return num;
+ }
+
+ public static float Fbm(Vector2 p, int octaves, float lacunarity, float gain)
+ {
+ float num = 0f;
+ float num2 = 1f;
+ Vector2 vector = p;
+ for (int i = 0; i < octaves; i++)
+ {
+ num += num2 * Mathf.PerlinNoise(vector.x, vector.y);
+ num2 *= gain;
+ vector *= lacunarity;
+ }
+ return num;
+ }
+
+ public static Quaternion SmoothDamp(Quaternion rot, Quaternion target, ref Quaternion deriv, float smoothTime, float maxSpeed, float deltaTime)
+ {
+ float num = ((Quaternion.Dot(rot, target) > 0f) ? 1f : (-1f));
+ target.x *= num;
+ target.y *= num;
+ target.z *= num;
+ target.w *= num;
+ Vector4 normalized = new Vector4(Mathf.SmoothDamp(rot.x, target.x, ref deriv.x, smoothTime, maxSpeed, deltaTime), Mathf.SmoothDamp(rot.y, target.y, ref deriv.y, smoothTime, maxSpeed, deltaTime), Mathf.SmoothDamp(rot.z, target.z, ref deriv.z, smoothTime, maxSpeed, deltaTime), Mathf.SmoothDamp(rot.w, target.w, ref deriv.w, smoothTime, maxSpeed, deltaTime)).normalized;
+ float num2 = 1f / Time.deltaTime;
+ deriv.x = (normalized.x - rot.x) * num2;
+ deriv.y = (normalized.y - rot.y) * num2;
+ deriv.z = (normalized.z - rot.z) * num2;
+ deriv.w = (normalized.w - rot.w) * num2;
+ return new Quaternion(normalized.x, normalized.y, normalized.z, normalized.w);
+ }
+
+ public static long GenerateUID()
+ {
+ IPGlobalProperties iPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
+ string obj = ((iPGlobalProperties != null && iPGlobalProperties.HostName != null) ? iPGlobalProperties.HostName : "unkown");
+ string text = ((iPGlobalProperties != null && iPGlobalProperties.DomainName != null) ? iPGlobalProperties.DomainName : "domain");
+ return (long)(obj + ":" + text).GetHashCode() + (long)UnityEngine.Random.Range(1, int.MaxValue);
+ }
+
+ public static bool TestPointInViewFrustum(Camera camera, Vector3 worldPos)
+ {
+ Vector3 vector = camera.WorldToViewportPoint(worldPos);
+ if (vector.x >= 0f && vector.x <= 1f && vector.y >= 0f)
+ {
+ return vector.y <= 1f;
+ }
+ return false;
+ }
+
+ public static Vector3 ParseVector3(string rString)
+ {
+ string[] array = rString.Substring(1, rString.Length - 2).Split(',');
+ float x = float.Parse(array[0]);
+ float y = float.Parse(array[1]);
+ float z = float.Parse(array[2]);
+ return new Vector3(x, y, z);
+ }
+
+ public static int GetMinPow2(int val)
+ {
+ if (val <= 1)
+ {
+ return 1;
+ }
+ if (val <= 2)
+ {
+ return 2;
+ }
+ if (val <= 4)
+ {
+ return 4;
+ }
+ if (val <= 8)
+ {
+ return 8;
+ }
+ if (val <= 16)
+ {
+ return 16;
+ }
+ if (val <= 32)
+ {
+ return 32;
+ }
+ if (val <= 64)
+ {
+ return 64;
+ }
+ if (val <= 128)
+ {
+ return 128;
+ }
+ if (val <= 256)
+ {
+ return 256;
+ }
+ if (val <= 512)
+ {
+ return 512;
+ }
+ if (val <= 1024)
+ {
+ return 1024;
+ }
+ if (val <= 2048)
+ {
+ return 2048;
+ }
+ if (val <= 4096)
+ {
+ return 4096;
+ }
+ return 1;
+ }
+
+ public static void NormalizeQuaternion(ref Quaternion q)
+ {
+ float num = 0f;
+ for (int i = 0; i < 4; i++)
+ {
+ num += q[i] * q[i];
+ }
+ float num2 = 1f / Mathf.Sqrt(num);
+ for (int j = 0; j < 4; j++)
+ {
+ q[j] *= num2;
+ }
+ }
+
+ public static Vector3 Project(Vector3 v, Vector3 onTo)
+ {
+ float num = Vector3.Dot(onTo, v);
+ return onTo * num;
+ }
+
+ public static float Length(float x, float y)
+ {
+ return Mathf.Sqrt(x * x + y * y);
+ }
+
+ public static float DistanceSqr(Vector3 v0, Vector3 v1)
+ {
+ float num = v1.x - v0.x;
+ float num2 = v1.y - v0.y;
+ float num3 = v1.z - v0.z;
+ return num * num + num2 * num2 + num3 * num3;
+ }
+
+ public static float DistanceXZ(Vector3 v0, Vector3 v1)
+ {
+ float num = v1.x - v0.x;
+ float num2 = v1.z - v0.z;
+ return Mathf.Sqrt(num * num + num2 * num2);
+ }
+
+ public static float LengthXZ(Vector3 v)
+ {
+ return Mathf.Sqrt(v.x * v.x + v.z * v.z);
+ }
+
+ public static Vector3 DirectionXZ(Vector3 dir)
+ {
+ dir.y = 0f;
+ dir.Normalize();
+ return dir;
+ }
+
+ public static Vector3 Bezier2(Vector3 Start, Vector3 Control, Vector3 End, float delta)
+ {
+ return (1f - delta) * (1f - delta) * Start + 2f * delta * (1f - delta) * Control + delta * delta * End;
+ }
+
+ public static float FixDegAngle(float p_Angle)
+ {
+ while (p_Angle >= 360f)
+ {
+ p_Angle -= 360f;
+ }
+ while (p_Angle < 0f)
+ {
+ p_Angle += 360f;
+ }
+ return p_Angle;
+ }
+
+ public static float DegDistance(float p_a, float p_b)
+ {
+ if (p_a == p_b)
+ {
+ return 0f;
+ }
+ p_a = FixDegAngle(p_a);
+ p_b = FixDegAngle(p_b);
+ float num = Mathf.Abs(p_b - p_a);
+ if (num > 180f)
+ {
+ num = Mathf.Abs(num - 360f);
+ }
+ return num;
+ }
+
+ public static float GetYawDeltaAngle(Quaternion q1, Quaternion q2)
+ {
+ float y = q1.eulerAngles.y;
+ float y2 = q2.eulerAngles.y;
+ return Mathf.DeltaAngle(y, y2);
+ }
+
+ public static float YawFromDirection(Vector3 dir)
+ {
+ float num = Mathf.Atan2(dir.x, dir.z);
+ return FixDegAngle(57.29578f * num);
+ }
+
+ public static float DegDirection(float p_a, float p_b)
+ {
+ if (p_a == p_b)
+ {
+ return 0f;
+ }
+ p_a = FixDegAngle(p_a);
+ p_b = FixDegAngle(p_b);
+ float num = p_a - p_b;
+ float num2 = ((num > 0f) ? 1f : (-1f));
+ if (Mathf.Abs(num) > 180f)
+ {
+ num2 *= -1f;
+ }
+ return num2;
+ }
+
+ public static void RotateBodyTo(Rigidbody body, Quaternion rot, float alpha)
+ {
+ }
+
+ public static string DownloadString(string downloadUrl, int timeoutMS = 5000)
+ {
+ HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(downloadUrl);
+ httpWebRequest.Timeout = timeoutMS;
+ httpWebRequest.ReadWriteTimeout = timeoutMS;
+ try
+ {
+ return new StreamReader(((HttpWebResponse)httpWebRequest.GetResponse()).GetResponseStream()).ReadToEnd();
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Exception while waiting for respons from " + downloadUrl + " -> " + ex.ToString());
+ return "";
+ }
+ }
+
+ public static bool IsEnabledInheirarcy(GameObject go, GameObject root)
+ {
+ do
+ {
+ if (!go.activeSelf)
+ {
+ return false;
+ }
+ if (go == root)
+ {
+ return true;
+ }
+ go = go.transform.parent.gameObject;
+ }
+ while (go != null);
+ return true;
+ }
+
+ public static bool IsParent(Transform go, Transform parent)
+ {
+ do
+ {
+ if (go == parent)
+ {
+ return true;
+ }
+ go = go.parent;
+ }
+ while (go != null);
+ return false;
+ }
+
+ public static Transform FindChild(Transform aParent, string aName)
+ {
+ foreach (Transform item in aParent)
+ {
+ if (item.name == aName)
+ {
+ return item;
+ }
+ Transform transform2 = FindChild(item, aName);
+ if (transform2 != null)
+ {
+ return transform2;
+ }
+ }
+ return null;
+ }
+
+ public static void AddToLodgroup(LODGroup lg, GameObject toAdd)
+ {
+ List<Renderer> list = new List<Renderer>(lg.GetLODs()[0].renderers);
+ Renderer[] componentsInChildren = toAdd.GetComponentsInChildren<Renderer>();
+ list.AddRange(componentsInChildren);
+ lg.GetLODs()[0].renderers = list.ToArray();
+ }
+
+ public static void RemoveFromLodgroup(LODGroup lg, GameObject toRemove)
+ {
+ List<Renderer> list = new List<Renderer>(lg.GetLODs()[0].renderers);
+ Renderer[] componentsInChildren = toRemove.GetComponentsInChildren<Renderer>();
+ foreach (Renderer item in componentsInChildren)
+ {
+ list.Remove(item);
+ }
+ lg.GetLODs()[0].renderers = list.ToArray();
+ }
+
+ public static void DrawGizmoCircle(Vector3 center, float radius, int steps)
+ {
+ float num = (float)Math.PI * 2f / (float)steps;
+ Vector3 vector = center + new Vector3(Mathf.Cos(0f) * radius, 0f, Mathf.Sin(0f) * radius);
+ Vector3 vector2 = vector;
+ for (float num2 = num; num2 <= (float)Math.PI * 2f; num2 += num)
+ {
+ Vector3 vector3 = center + new Vector3(Mathf.Cos(num2) * radius, 0f, Mathf.Sin(num2) * radius);
+ Gizmos.DrawLine(vector3, vector2);
+ vector2 = vector3;
+ }
+ Gizmos.DrawLine(vector2, vector);
+ }
+
+ public static void ClampUIToScreen(RectTransform transform)
+ {
+ Vector3[] array = new Vector3[4];
+ transform.GetWorldCorners(array);
+ if (!(GetMainCamera() == null))
+ {
+ float num = 0f;
+ float num2 = 0f;
+ if (array[2].x > (float)Screen.width)
+ {
+ num -= array[2].x - (float)Screen.width;
+ }
+ if (array[0].x < 0f)
+ {
+ num -= array[0].x;
+ }
+ if (array[2].y > (float)Screen.height)
+ {
+ num2 -= array[2].y - (float)Screen.height;
+ }
+ if (array[0].y < 0f)
+ {
+ num2 -= array[0].y;
+ }
+ Vector3 position = transform.position;
+ position.x += num;
+ position.y += num2;
+ transform.position = position;
+ }
+ }
+
+ public static void Pull(Rigidbody body, Vector3 target, float targetDistance, float speed, float force, float smoothDistance)
+ {
+ Vector3 vector = target - body.position;
+ float magnitude = vector.magnitude;
+ if (!(magnitude < targetDistance))
+ {
+ Vector3 normalized = vector.normalized;
+ float num = Mathf.Clamp01((magnitude - targetDistance) / smoothDistance);
+ Vector3 vector2 = Vector3.Project(body.velocity, normalized.normalized);
+ Vector3 vector3 = normalized.normalized * speed - vector2;
+ body.AddForce(vector3 * num * force, ForceMode.VelocityChange);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Vector2i.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Vector2i.cs
new file mode 100644
index 0000000..3a10e66
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/Vector2i.cs
@@ -0,0 +1,104 @@
+using UnityEngine;
+
+public struct Vector2i
+{
+ public static Vector2i zero = new Vector2i(0, 0);
+
+ public int x;
+
+ public int y;
+
+ public Vector2i(Vector2 v)
+ {
+ x = (int)v.x;
+ y = (int)v.y;
+ }
+
+ public Vector2i(Vector3 v)
+ {
+ x = (int)v.x;
+ y = (int)v.y;
+ }
+
+ public Vector2i(Vector2i v)
+ {
+ x = v.x;
+ y = v.y;
+ }
+
+ public Vector2i(int _x, int _y)
+ {
+ x = _x;
+ y = _y;
+ }
+
+ public static Vector2i operator +(Vector2i v0, Vector2i v1)
+ {
+ return new Vector2i(v0.x + v1.x, v0.y + v1.y);
+ }
+
+ public static Vector2i operator -(Vector2i v0, Vector2i v1)
+ {
+ return new Vector2i(v0.x - v1.x, v0.y - v1.y);
+ }
+
+ public static bool operator ==(Vector2i v0, Vector2i v1)
+ {
+ if (v0.x == v1.x)
+ {
+ return v0.y == v1.y;
+ }
+ return false;
+ }
+
+ public static bool operator !=(Vector2i v0, Vector2i v1)
+ {
+ if (v0.x == v1.x)
+ {
+ return v0.y != v1.y;
+ }
+ return true;
+ }
+
+ public int Magnitude()
+ {
+ return Mathf.Abs(x) + Mathf.Abs(y);
+ }
+
+ public static int Distance(Vector2i a, Vector2i b)
+ {
+ return (a - b).Magnitude();
+ }
+
+ public Vector2 ToVector2()
+ {
+ return new Vector2(x, y);
+ }
+
+ public override string ToString()
+ {
+ return x + "," + y;
+ }
+
+ public override int GetHashCode()
+ {
+ return x.GetHashCode() ^ y.GetHashCode();
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj is Vector2i vector2i)
+ {
+ if (vector2i.x == x)
+ {
+ return vector2i.y == y;
+ }
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZInput.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZInput.cs
new file mode 100644
index 0000000..116b43f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZInput.cs
@@ -0,0 +1,522 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ZInput
+{
+ public class ButtonDef
+ {
+ public string m_name;
+
+ public bool m_gamepad;
+
+ public bool m_save = true;
+
+ public KeyCode m_key;
+
+ public string m_axis;
+
+ public bool m_inverted;
+
+ public bool m_pressed;
+
+ public bool m_wasPressed;
+
+ public bool m_down;
+
+ public bool m_up;
+
+ public bool m_pressedFixed;
+
+ public bool m_wasPressedFixed;
+
+ public bool m_downFixed;
+
+ public bool m_upFixed;
+
+ public float m_pressedTimer;
+
+ public float m_repeatDelay;
+
+ public float m_repeatInterval;
+ }
+
+ private static ZInput m_instance;
+
+ private const float m_stickDeadZone = 0.2f;
+
+ private const float m_gamepadInactiveTimeout = 60f;
+
+ private bool m_gamepadActive;
+
+ private bool m_mouseActive = true;
+
+ private bool m_gamepadEnabled;
+
+ private Dictionary<string, ButtonDef> m_buttons = new Dictionary<string, ButtonDef>();
+
+ private static ButtonDef m_binding;
+
+ public static ZInput instance => m_instance;
+
+ public static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new ZInput();
+ }
+ }
+
+ private ZInput()
+ {
+ Reset();
+ Load();
+ }
+
+ public static void Update(float dt)
+ {
+ if (m_instance != null)
+ {
+ m_instance.InternalUpdate(dt);
+ }
+ }
+
+ public static void FixedUpdate(float dt)
+ {
+ if (m_instance != null)
+ {
+ m_instance.InternalUpdateFixed(dt);
+ }
+ }
+
+ private void InternalUpdate(float dt)
+ {
+ CheckMouseInput();
+ foreach (ButtonDef value in m_buttons.Values)
+ {
+ if (!m_gamepadEnabled && value.m_gamepad)
+ {
+ continue;
+ }
+ value.m_wasPressed = value.m_pressed;
+ if (!string.IsNullOrEmpty(value.m_axis))
+ {
+ float num = (value.m_inverted ? (0f - Input.GetAxis(value.m_axis)) : Input.GetAxis(value.m_axis));
+ value.m_pressed = num > 0.4f;
+ }
+ else
+ {
+ value.m_pressed = Input.GetKey(value.m_key);
+ }
+ value.m_down = value.m_pressed && !value.m_wasPressed;
+ value.m_up = !value.m_pressed && value.m_wasPressed;
+ if (value.m_repeatDelay > 0f)
+ {
+ if (value.m_pressed)
+ {
+ value.m_pressedTimer += dt;
+ if (value.m_pressedTimer > value.m_repeatDelay)
+ {
+ value.m_down = true;
+ value.m_downFixed = true;
+ value.m_pressedTimer -= value.m_repeatInterval;
+ }
+ }
+ else
+ {
+ value.m_pressedTimer = 0f;
+ }
+ }
+ if (value.m_gamepad && value.m_down)
+ {
+ OnGamepadInput();
+ }
+ }
+ }
+
+ private void CheckMouseInput()
+ {
+ if (Input.GetAxis("Mouse X") != 0f || Input.GetAxis("Mouse Y") != 0f)
+ {
+ OnMouseInput();
+ }
+ }
+
+ private void OnMouseInput()
+ {
+ m_gamepadActive = false;
+ m_mouseActive = true;
+ }
+
+ private void OnGamepadInput()
+ {
+ m_gamepadActive = true;
+ m_mouseActive = false;
+ }
+
+ private void InternalUpdateFixed(float dt)
+ {
+ foreach (ButtonDef value in m_buttons.Values)
+ {
+ value.m_wasPressedFixed = value.m_pressedFixed;
+ value.m_pressedFixed = value.m_pressed;
+ value.m_downFixed = value.m_pressedFixed && !value.m_wasPressedFixed;
+ value.m_upFixed = !value.m_pressedFixed && value.m_wasPressedFixed;
+ }
+ }
+
+ public void Reset()
+ {
+ m_buttons.Clear();
+ float repeatDelay = 0.3f;
+ float repeatInterval = 0.1f;
+ AddButton("Attack", KeyCode.Mouse0);
+ AddButton("SecondAttack", KeyCode.Mouse2);
+ AddButton("Block", KeyCode.Mouse1);
+ AddButton("Use", KeyCode.E);
+ AddButton("Hide", KeyCode.R);
+ AddButton("Jump", KeyCode.Space);
+ AddButton("Crouch", KeyCode.LeftControl);
+ AddButton("Run", KeyCode.LeftShift);
+ AddButton("ToggleWalk", KeyCode.C);
+ AddButton("AutoRun", KeyCode.Q);
+ AddButton("Sit", KeyCode.X);
+ AddButton("GPower", KeyCode.F);
+ AddButton("AltPlace", KeyCode.LeftShift);
+ AddButton("Forward", KeyCode.W, repeatDelay, repeatInterval);
+ AddButton("Left", KeyCode.A, repeatDelay, repeatInterval);
+ AddButton("Backward", KeyCode.S, repeatDelay, repeatInterval);
+ AddButton("Right", KeyCode.D, repeatDelay, repeatInterval);
+ AddButton("Inventory", KeyCode.Tab);
+ AddButton("Map", KeyCode.M);
+ AddButton("MapZoomOut", KeyCode.Comma);
+ AddButton("MapZoomIn", KeyCode.Period);
+ AddButton("BuildPrev", KeyCode.Q);
+ AddButton("BuildNext", KeyCode.E);
+ AddButton("BuildMenu", KeyCode.Mouse1);
+ AddButton("Remove", KeyCode.Mouse2);
+ AddButton("JoyUse", KeyCode.JoystickButton0);
+ AddButton("JoyHide", KeyCode.JoystickButton9);
+ AddButton("JoyJump", KeyCode.JoystickButton1);
+ AddButton("JoySit", KeyCode.JoystickButton2);
+ AddButton("JoyGPower", "JoyAxis 7", inverted: true);
+ AddButton("JoyInventory", KeyCode.JoystickButton3);
+ AddButton("JoyRun", KeyCode.JoystickButton4);
+ AddButton("JoyCrouch", KeyCode.JoystickButton8);
+ AddButton("JoyMap", KeyCode.JoystickButton6);
+ AddButton("JoyMenu", KeyCode.JoystickButton7);
+ AddButton("JoyBlock", "JoyAxis 3", inverted: true);
+ AddButton("JoyAttack", "JoyAxis 3");
+ AddButton("JoySecondAttack", KeyCode.JoystickButton5);
+ AddButton("JoyAltPlace", KeyCode.JoystickButton4);
+ AddButton("JoyRotate", "JoyAxis 3", inverted: true);
+ AddButton("JoyPlace", "JoyAxis 10");
+ AddButton("JoyRemove", KeyCode.JoystickButton5);
+ AddButton("JoyTabLeft", KeyCode.JoystickButton4);
+ AddButton("JoyTabRight", KeyCode.JoystickButton5);
+ AddButton("JoyLStickLeft", "JoyAxis 1", inverted: true, repeatDelay, repeatInterval);
+ AddButton("JoyLStickRight", "JoyAxis 1", inverted: false, repeatDelay, repeatInterval);
+ AddButton("JoyLStickUp", "JoyAxis 2", inverted: true, repeatDelay, repeatInterval);
+ AddButton("JoyLStickDown", "JoyAxis 2", inverted: false, repeatDelay, repeatInterval);
+ AddButton("JoyButtonA", KeyCode.JoystickButton0);
+ AddButton("JoyButtonB", KeyCode.JoystickButton1);
+ AddButton("JoyButtonX", KeyCode.JoystickButton2);
+ AddButton("JoyButtonY", KeyCode.JoystickButton3);
+ AddButton("JoyDPadLeft", "JoyAxis 6", inverted: true, repeatDelay, repeatInterval);
+ AddButton("JoyDPadRight", "JoyAxis 6", inverted: false, repeatDelay, repeatInterval);
+ AddButton("JoyDPadUp", "JoyAxis 7", inverted: false, repeatDelay, repeatInterval);
+ AddButton("JoyDPadDown", "JoyAxis 7", inverted: true, repeatDelay, repeatInterval);
+ AddButton("JoyLTrigger", "JoyAxis 3", inverted: true);
+ AddButton("JoyRTrigger", "JoyAxis 3");
+ AddButton("JoyLStick", KeyCode.JoystickButton8);
+ AddButton("JoyRStick", KeyCode.JoystickButton9);
+ }
+
+ public static bool IsGamepadEnabled()
+ {
+ return m_instance.m_gamepadEnabled;
+ }
+
+ public static void SetGamepadEnabled(bool enabled)
+ {
+ m_instance.m_gamepadEnabled = enabled;
+ }
+
+ public static bool IsGamepadActive()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return false;
+ }
+ return m_instance.m_gamepadActive;
+ }
+
+ public static bool IsMouseActive()
+ {
+ return m_instance.m_mouseActive;
+ }
+
+ public void Save()
+ {
+ PlayerPrefs.SetInt("gamepad_enabled", m_gamepadEnabled ? 1 : 0);
+ foreach (ButtonDef value in m_buttons.Values)
+ {
+ if (value.m_save)
+ {
+ PlayerPrefs.SetInt("key_" + value.m_name, (int)value.m_key);
+ }
+ }
+ }
+
+ public void Load()
+ {
+ Reset();
+ m_gamepadEnabled = PlayerPrefs.GetInt("gamepad_enabled", 1) == 1;
+ foreach (ButtonDef value in m_buttons.Values)
+ {
+ if (value.m_save)
+ {
+ KeyCode @int = (KeyCode)PlayerPrefs.GetInt("key_" + value.m_name, (int)value.m_key);
+ value.m_key = @int;
+ }
+ }
+ }
+
+ public ButtonDef AddButton(string name, KeyCode key, float repeatDelay = 0f, float repeatInterval = 0f)
+ {
+ ButtonDef buttonDef = new ButtonDef();
+ buttonDef.m_name = name;
+ buttonDef.m_key = key;
+ buttonDef.m_gamepad = name.StartsWith("Joy");
+ buttonDef.m_save = !buttonDef.m_gamepad;
+ buttonDef.m_repeatDelay = repeatDelay;
+ buttonDef.m_repeatInterval = repeatInterval;
+ m_buttons.Add(name, buttonDef);
+ return buttonDef;
+ }
+
+ public ButtonDef AddButton(string name, string axis, bool inverted = false, float repeatDelay = 0f, float repeatInterval = 0f)
+ {
+ ButtonDef buttonDef = new ButtonDef();
+ buttonDef.m_name = name;
+ buttonDef.m_axis = axis;
+ buttonDef.m_inverted = inverted;
+ buttonDef.m_gamepad = name.StartsWith("Joy");
+ buttonDef.m_save = !buttonDef.m_gamepad;
+ buttonDef.m_repeatDelay = repeatDelay;
+ buttonDef.m_repeatInterval = repeatInterval;
+ m_buttons.Add(name, buttonDef);
+ return buttonDef;
+ }
+
+ public void Setbutton(string name, KeyCode key)
+ {
+ m_buttons[name].m_key = key;
+ }
+
+ public string GetBoundKeyString(string name)
+ {
+ if (m_buttons.TryGetValue(name, out var value))
+ {
+ return value.m_key switch
+ {
+ KeyCode.Comma => ",",
+ KeyCode.Period => ".",
+ KeyCode.Mouse0 => "$button_mouse0",
+ KeyCode.Mouse1 => "$button_mouse1",
+ KeyCode.Mouse2 => "$button_mouse2",
+ KeyCode.Space => "$button_space",
+ KeyCode.LeftShift => "$button_lshift",
+ KeyCode.RightShift => "$button_rshift",
+ KeyCode.LeftAlt => "$button_lalt",
+ KeyCode.RightAlt => "$button_ralt",
+ KeyCode.LeftControl => "$button_lctrl",
+ KeyCode.RightControl => "$button_rctrl",
+ KeyCode.Return => "$button_return",
+ _ => value.m_key.ToString(),
+ };
+ }
+ return "MISSING KEY BINDING \"" + name + "\"";
+ }
+
+ public static void ResetButtonStatus(string name)
+ {
+ if (m_instance.m_buttons.TryGetValue(name, out var value))
+ {
+ value.m_down = false;
+ value.m_up = false;
+ value.m_downFixed = false;
+ value.m_upFixed = false;
+ }
+ }
+
+ public static bool GetButtonDown(string name)
+ {
+ if (m_instance.m_buttons.TryGetValue(name, out var value))
+ {
+ if (!instance.m_gamepadEnabled && value.m_gamepad)
+ {
+ return false;
+ }
+ if (Time.inFixedTimeStep)
+ {
+ return value.m_downFixed;
+ }
+ return value.m_down;
+ }
+ return false;
+ }
+
+ public static bool GetButtonUp(string name)
+ {
+ if (m_instance.m_buttons.TryGetValue(name, out var value))
+ {
+ if (!instance.m_gamepadEnabled && value.m_gamepad)
+ {
+ return false;
+ }
+ if (Time.inFixedTimeStep)
+ {
+ return value.m_upFixed;
+ }
+ return value.m_up;
+ }
+ return false;
+ }
+
+ public static bool GetButton(string name)
+ {
+ if (m_instance.m_buttons.TryGetValue(name, out var value))
+ {
+ if (!instance.m_gamepadEnabled && value.m_gamepad)
+ {
+ return false;
+ }
+ return value.m_pressed;
+ }
+ return false;
+ }
+
+ private KeyCode GetPressedKey()
+ {
+ foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
+ {
+ if (Input.GetKey(value))
+ {
+ return value;
+ }
+ }
+ return KeyCode.None;
+ }
+
+ public void StartBindKey(string name)
+ {
+ if (m_buttons.TryGetValue(name, out var value))
+ {
+ m_binding = value;
+ }
+ }
+
+ public bool EndBindKey()
+ {
+ if (m_binding == null)
+ {
+ return true;
+ }
+ KeyCode pressedKey = GetPressedKey();
+ if (pressedKey != 0)
+ {
+ m_binding.m_key = pressedKey;
+ return true;
+ }
+ return false;
+ }
+
+ private static float ApplyDeadzone(float v, bool soften)
+ {
+ float num = Mathf.Sign(v);
+ v = Mathf.Abs(v);
+ v = Mathf.Clamp01(v - 0.2f);
+ v *= 1.25f;
+ if (soften)
+ {
+ v *= v;
+ }
+ v *= num;
+ return v;
+ }
+
+ public static float GetJoyLeftStickX()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ float num = ApplyDeadzone(Input.GetAxis("JoyAxis 1"), soften: false);
+ if (num != 0f)
+ {
+ m_instance.OnGamepadInput();
+ }
+ return num;
+ }
+
+ public static float GetJoyLeftStickY()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ float num = ApplyDeadzone(Input.GetAxis("JoyAxis 2"), soften: false);
+ if (num != 0f)
+ {
+ m_instance.OnGamepadInput();
+ }
+ return num;
+ }
+
+ public static float GetJoyRightStickX()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ float num = ApplyDeadzone(Input.GetAxis("JoyAxis 4"), soften: true);
+ if (num != 0f)
+ {
+ m_instance.OnGamepadInput();
+ }
+ return num;
+ }
+
+ public static float GetJoyRightStickY()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ float num = ApplyDeadzone(Input.GetAxis("JoyAxis 5"), soften: true);
+ if (num != 0f)
+ {
+ m_instance.OnGamepadInput();
+ }
+ return num;
+ }
+
+ public static float GetJoyLTrigger()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ return Input.GetAxis("JoyAxis 3");
+ }
+
+ public static float GetJoyRTrigger()
+ {
+ if (!m_instance.m_gamepadEnabled)
+ {
+ return 0f;
+ }
+ return Input.GetAxis("JoyAxis 6");
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZLog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZLog.cs
new file mode 100644
index 0000000..5a0b187
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/ZLog.cs
@@ -0,0 +1,28 @@
+using System;
+using UnityEngine;
+
+public class ZLog
+{
+ public static void Log(object o)
+ {
+ Debug.Log(string.Concat(DateTime.Now.ToString(), ": ", o, "\n"));
+ }
+
+ public static void DevLog(object o)
+ {
+ if (Debug.isDebugBuild)
+ {
+ Debug.Log(string.Concat(DateTime.Now.ToString(), ": ", o, "\n"));
+ }
+ }
+
+ public static void LogError(object o)
+ {
+ Debug.LogError(string.Concat(DateTime.Now.ToString(), ": ", o, "\n"));
+ }
+
+ public static void LogWarning(object o)
+ {
+ Debug.LogWarning(string.Concat(DateTime.Now.ToString(), ": ", o, "\n"));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_utils/assembly_utils.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/assembly_utils.csproj
new file mode 100644
index 0000000..aca9a06
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_utils/assembly_utils.csproj
@@ -0,0 +1,28 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_utils</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup />
+ <ItemGroup>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PhysicsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AnimationModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Core" />
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/.gitignore b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/.gitignore
@@ -0,0 +1,399 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.vs
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimalAI.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimalAI.cs
new file mode 100644
index 0000000..8f747b4
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimalAI.cs
@@ -0,0 +1,80 @@
+using UnityEngine;
+
+public class AnimalAI : BaseAI
+{
+ private const float m_updateTargetFarRange = 32f;
+
+ private const float m_updateTargetIntervalNear = 2f;
+
+ private const float m_updateTargetIntervalFar = 10f;
+
+ public float m_timeToSafe = 4f;
+
+ private Character m_target;
+
+ private float m_inDangerTimer;
+
+ private float m_updateTargetTimer;
+
+ protected override void Awake()
+ {
+ base.Awake();
+ m_updateTargetTimer = Random.Range(0f, 2f);
+ }
+
+ protected override void OnDamaged(float damage, Character attacker)
+ {
+ base.OnDamaged(damage, attacker);
+ SetAlerted(alert: true);
+ }
+
+ protected override void UpdateAI(float dt)
+ {
+ base.UpdateAI(dt);
+ if (!m_nview.IsOwner() || (m_afraidOfFire && AvoidFire(dt, null, superAfraid: true)))
+ {
+ return;
+ }
+ m_updateTargetTimer -= dt;
+ if (m_updateTargetTimer <= 0f)
+ {
+ m_updateTargetTimer = (Character.IsCharacterInRange(base.transform.position, 32f) ? 2f : 10f);
+ Character character = FindEnemy();
+ if ((bool)character)
+ {
+ m_target = character;
+ }
+ }
+ if ((bool)m_target && !m_target.IsDead() && CanSenseTarget(m_target))
+ {
+ SetAlerted(alert: true);
+ }
+ if (IsAlerted())
+ {
+ m_inDangerTimer += dt;
+ if (m_inDangerTimer > m_timeToSafe)
+ {
+ m_target = null;
+ SetAlerted(alert: false);
+ }
+ }
+ if ((bool)m_target)
+ {
+ Flee(dt, m_target.transform.position);
+ m_target.OnTargeted(sensed: false, alerted: false);
+ }
+ else
+ {
+ IdleMovement(dt);
+ }
+ }
+
+ protected override void SetAlerted(bool alert)
+ {
+ if (alert)
+ {
+ m_inDangerTimer = 0f;
+ }
+ base.SetAlerted(alert);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimationEffect.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimationEffect.cs
new file mode 100644
index 0000000..f77f3b2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AnimationEffect.cs
@@ -0,0 +1,102 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class AnimationEffect : MonoBehaviour
+{
+ public Transform m_effectRoot;
+
+ private Animator m_animator;
+
+ private List<GameObject> m_attachments;
+
+ private int m_attachStateHash;
+
+ private void Start()
+ {
+ m_animator = GetComponent<Animator>();
+ }
+
+ public void Effect(AnimationEvent e)
+ {
+ string stringParameter = e.stringParameter;
+ GameObject original = e.objectReferenceParameter as GameObject;
+ Transform transform = null;
+ if (stringParameter.Length > 0)
+ {
+ transform = Utils.FindChild(base.transform, stringParameter);
+ }
+ if (transform == null)
+ {
+ transform = (m_effectRoot ? m_effectRoot : base.transform);
+ }
+ Object.Instantiate(original, transform.position, transform.rotation);
+ }
+
+ public void Attach(AnimationEvent e)
+ {
+ string stringParameter = e.stringParameter;
+ GameObject original = e.objectReferenceParameter as GameObject;
+ Transform transform = Utils.FindChild(base.transform, stringParameter);
+ if (transform == null)
+ {
+ ZLog.LogWarning("Failed to find attach joint " + stringParameter);
+ return;
+ }
+ ClearAttachment(transform);
+ GameObject gameObject = Object.Instantiate(original, transform.position, transform.rotation);
+ gameObject.transform.SetParent(transform, worldPositionStays: true);
+ if (m_attachments == null)
+ {
+ m_attachments = new List<GameObject>();
+ }
+ m_attachments.Add(gameObject);
+ m_attachStateHash = e.animatorStateInfo.fullPathHash;
+ CancelInvoke("UpdateAttachments");
+ InvokeRepeating("UpdateAttachments", 0.1f, 0.1f);
+ }
+
+ private void ClearAttachment(Transform parent)
+ {
+ if (m_attachments == null)
+ {
+ return;
+ }
+ foreach (GameObject attachment in m_attachments)
+ {
+ if ((bool)attachment && attachment.transform.parent == parent)
+ {
+ m_attachments.Remove(attachment);
+ Object.Destroy(attachment);
+ break;
+ }
+ }
+ }
+
+ public void RemoveAttachments()
+ {
+ if (m_attachments == null)
+ {
+ return;
+ }
+ foreach (GameObject attachment in m_attachments)
+ {
+ Object.Destroy(attachment);
+ }
+ m_attachments.Clear();
+ }
+
+ private void UpdateAttachments()
+ {
+ if (m_attachments != null && m_attachments.Count > 0)
+ {
+ if (m_attachStateHash != m_animator.GetCurrentAnimatorStateInfo(0).fullPathHash && m_attachStateHash != m_animator.GetNextAnimatorStateInfo(0).fullPathHash)
+ {
+ RemoveAttachments();
+ }
+ }
+ else
+ {
+ CancelInvoke("UpdateAttachments");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Aoe.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Aoe.cs
new file mode 100644
index 0000000..4f657e9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Aoe.cs
@@ -0,0 +1,331 @@
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+
+public class Aoe : MonoBehaviour, IProjectile
+{
+ [Header("Attack (overridden by item )")]
+ public bool m_useAttackSettings = true;
+
+ public HitData.DamageTypes m_damage;
+
+ public bool m_dodgeable;
+
+ public bool m_blockable;
+
+ public int m_toolTier;
+
+ public float m_attackForce;
+
+ public float m_backstabBonus = 4f;
+
+ public string m_statusEffect = "";
+
+ [Header("Attack (other)")]
+ public HitData.DamageTypes m_damagePerLevel;
+
+ public bool m_attackForceForward;
+
+ [Header("Damage self")]
+ public float m_damageSelf;
+
+ [Header("Ignore targets")]
+ public bool m_hitOwner;
+
+ public bool m_hitSame;
+
+ public bool m_hitFriendly = true;
+
+ public bool m_hitEnemy = true;
+
+ public bool m_hitCharacters = true;
+
+ public bool m_hitProps = true;
+
+ [Header("Other")]
+ public Skills.SkillType m_skill;
+
+ public bool m_useTriggers;
+
+ public bool m_triggerEnterOnly;
+
+ public float m_radius = 4f;
+
+ public float m_ttl = 4f;
+
+ public float m_hitInterval = 1f;
+
+ public EffectList m_hitEffects = new EffectList();
+
+ public bool m_attachToCaster;
+
+ private ZNetView m_nview;
+
+ private Character m_owner;
+
+ private List<GameObject> m_hitList = new List<GameObject>();
+
+ private float m_hitTimer;
+
+ private Vector3 m_offset = Vector3.zero;
+
+ private Quaternion m_localRot = Quaternion.identity;
+
+ private int m_level;
+
+ private int m_rayMask;
+
+ private void Awake()
+ {
+ m_nview = GetComponentInParent<ZNetView>();
+ m_rayMask = 0;
+ if (m_hitCharacters)
+ {
+ m_rayMask |= LayerMask.GetMask("character", "character_net", "character_ghost");
+ }
+ if (m_hitProps)
+ {
+ m_rayMask |= LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "hitbox", "character_noenv", "vehicle");
+ }
+ }
+
+ public HitData.DamageTypes GetDamage()
+ {
+ return GetDamage(m_level);
+ }
+
+ public HitData.DamageTypes GetDamage(int itemQuality)
+ {
+ if (itemQuality <= 1)
+ {
+ return m_damage;
+ }
+ HitData.DamageTypes damage = m_damage;
+ damage.Add(m_damagePerLevel, itemQuality - 1);
+ return damage;
+ }
+
+ public string GetTooltipString(int itemQuality)
+ {
+ StringBuilder stringBuilder = new StringBuilder(256);
+ stringBuilder.Append("AOE");
+ stringBuilder.Append(GetDamage(itemQuality).GetTooltipString());
+ stringBuilder.AppendFormat("\n$item_knockback: <color=orange>{0}</color>", m_attackForce);
+ stringBuilder.AppendFormat("\n$item_backstab: <color=orange>{0}x</color>", m_backstabBonus);
+ return stringBuilder.ToString();
+ }
+
+ private void Start()
+ {
+ if ((!(m_nview != null) || (m_nview.IsValid() && m_nview.IsOwner())) && !m_useTriggers && m_hitInterval <= 0f)
+ {
+ CheckHits();
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview != null && (!m_nview.IsValid() || !m_nview.IsOwner()))
+ {
+ return;
+ }
+ if (m_hitInterval > 0f)
+ {
+ m_hitTimer -= Time.fixedDeltaTime;
+ if (m_hitTimer <= 0f)
+ {
+ m_hitTimer = m_hitInterval;
+ if (m_useTriggers)
+ {
+ m_hitList.Clear();
+ }
+ else
+ {
+ CheckHits();
+ }
+ }
+ }
+ if (m_owner != null && m_attachToCaster)
+ {
+ base.transform.position = m_owner.transform.TransformPoint(m_offset);
+ base.transform.rotation = m_owner.transform.rotation * m_localRot;
+ }
+ if (m_ttl > 0f)
+ {
+ m_ttl -= Time.fixedDeltaTime;
+ if (m_ttl <= 0f)
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ }
+ }
+
+ private void CheckHits()
+ {
+ m_hitList.Clear();
+ Collider[] array = Physics.OverlapSphere(base.transform.position, m_radius, m_rayMask);
+ bool flag = false;
+ Collider[] array2 = array;
+ foreach (Collider collider in array2)
+ {
+ if (OnHit(collider, collider.transform.position))
+ {
+ flag = true;
+ }
+ }
+ if (flag && (bool)m_owner && m_owner.IsPlayer() && m_skill != 0)
+ {
+ m_owner.RaiseSkill(m_skill);
+ }
+ }
+
+ public void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemDrop.ItemData item)
+ {
+ m_owner = owner;
+ if (item != null)
+ {
+ m_level = item.m_quality;
+ }
+ if (m_attachToCaster && owner != null)
+ {
+ m_offset = owner.transform.InverseTransformPoint(base.transform.position);
+ m_localRot = Quaternion.Inverse(owner.transform.rotation) * base.transform.rotation;
+ }
+ if (hitData != null && m_useAttackSettings)
+ {
+ m_damage = hitData.m_damage;
+ m_blockable = hitData.m_blockable;
+ m_dodgeable = hitData.m_dodgeable;
+ m_attackForce = hitData.m_pushForce;
+ m_backstabBonus = hitData.m_backstabBonus;
+ m_statusEffect = hitData.m_statusEffect;
+ m_toolTier = hitData.m_toolTier;
+ }
+ }
+
+ private void OnTriggerEnter(Collider collider)
+ {
+ if (m_triggerEnterOnly)
+ {
+ if (!m_useTriggers)
+ {
+ ZLog.LogWarning("AOE got OnTriggerStay but trigger damage is disabled in " + base.gameObject.name);
+ }
+ else if (!(m_nview != null) || (m_nview.IsValid() && m_nview.IsOwner()))
+ {
+ OnHit(collider, collider.transform.position);
+ }
+ }
+ }
+
+ private void OnTriggerStay(Collider collider)
+ {
+ if (!m_triggerEnterOnly)
+ {
+ if (!m_useTriggers)
+ {
+ ZLog.LogWarning("AOE got OnTriggerStay but trigger damage is disabled in " + base.gameObject.name);
+ }
+ else if (!(m_nview != null) || (m_nview.IsValid() && m_nview.IsOwner()))
+ {
+ OnHit(collider, collider.transform.position);
+ }
+ }
+ }
+
+ private bool OnHit(Collider collider, Vector3 hitPoint)
+ {
+ GameObject gameObject = Projectile.FindHitObject(collider);
+ if (m_hitList.Contains(gameObject))
+ {
+ return false;
+ }
+ m_hitList.Add(gameObject);
+ float num = 1f;
+ if ((bool)m_owner && m_owner.IsPlayer() && m_skill != 0)
+ {
+ num = m_owner.GetRandomSkillFactor(m_skill);
+ }
+ bool result = false;
+ IDestructible component = gameObject.GetComponent<IDestructible>();
+ if (component != null)
+ {
+ Character character = component as Character;
+ if ((bool)character)
+ {
+ if (m_nview == null && !character.IsOwner())
+ {
+ return false;
+ }
+ if (m_owner != null)
+ {
+ if (!m_hitOwner && character == m_owner)
+ {
+ return false;
+ }
+ if (!m_hitSame && character.m_name == m_owner.m_name)
+ {
+ return false;
+ }
+ bool flag = BaseAI.IsEnemy(m_owner, character);
+ if (!m_hitFriendly && !flag)
+ {
+ return false;
+ }
+ if (!m_hitEnemy && flag)
+ {
+ return false;
+ }
+ }
+ if (!m_hitCharacters)
+ {
+ return false;
+ }
+ if (m_dodgeable && character.IsDodgeInvincible())
+ {
+ return false;
+ }
+ }
+ else if (!m_hitProps)
+ {
+ return false;
+ }
+ Vector3 dir = (m_attackForceForward ? base.transform.forward : (hitPoint - base.transform.position).normalized);
+ HitData hitData = new HitData();
+ hitData.m_hitCollider = collider;
+ hitData.m_damage = GetDamage();
+ hitData.m_pushForce = m_attackForce * num;
+ hitData.m_backstabBonus = m_backstabBonus;
+ hitData.m_point = hitPoint;
+ hitData.m_dir = dir;
+ hitData.m_statusEffect = m_statusEffect;
+ hitData.m_dodgeable = m_dodgeable;
+ hitData.m_blockable = m_blockable;
+ hitData.m_toolTier = m_toolTier;
+ hitData.SetAttacker(m_owner);
+ hitData.m_damage.Modify(num);
+ component.Damage(hitData);
+ if (m_damageSelf > 0f)
+ {
+ IDestructible componentInParent = GetComponentInParent<IDestructible>();
+ if (componentInParent != null)
+ {
+ HitData hitData2 = new HitData();
+ hitData2.m_damage.m_damage = m_damageSelf;
+ hitData2.m_point = base.transform.position;
+ hitData2.m_blockable = false;
+ hitData2.m_dodgeable = false;
+ componentInParent.Damage(hitData2);
+ }
+ }
+ result = true;
+ }
+ m_hitEffects.Create(hitPoint, Quaternion.identity);
+ return result;
+ }
+
+ private void OnDrawGizmos()
+ {
+ _ = m_useTriggers;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Attack.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Attack.cs
new file mode 100644
index 0000000..fe7c100
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Attack.cs
@@ -0,0 +1,988 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+[Serializable]
+public class Attack
+{
+ private class HitPoint
+ {
+ public GameObject go;
+
+ public Vector3 avgPoint = Vector3.zero;
+
+ public int count;
+
+ public Vector3 firstPoint;
+
+ public Collider collider;
+
+ public Vector3 closestPoint;
+
+ public float closestDistance = 999999f;
+ }
+
+ public enum AttackType
+ {
+ Horizontal,
+ Vertical,
+ Projectile,
+ None,
+ Area,
+ TriggerProjectile
+ }
+
+ public enum HitPointType
+ {
+ Closest,
+ Average,
+ First
+ }
+
+ [Header("Common")]
+ public AttackType m_attackType;
+
+ public string m_attackAnimation = "";
+
+ public int m_attackRandomAnimations;
+
+ public int m_attackChainLevels;
+
+ public bool m_consumeItem;
+
+ public bool m_hitTerrain = true;
+
+ public float m_attackStamina = 20f;
+
+ public float m_speedFactor = 0.2f;
+
+ public float m_speedFactorRotation = 0.2f;
+
+ public float m_attackStartNoise = 10f;
+
+ public float m_attackHitNoise = 30f;
+
+ public float m_damageMultiplier = 1f;
+
+ public float m_forceMultiplier = 1f;
+
+ public float m_staggerMultiplier = 1f;
+
+ [Header("Misc")]
+ public string m_attackOriginJoint = "";
+
+ public float m_attackRange = 1.5f;
+
+ public float m_attackHeight = 0.6f;
+
+ public float m_attackOffset;
+
+ public GameObject m_spawnOnTrigger;
+
+ [Header("Melee/AOE")]
+ public float m_attackAngle = 90f;
+
+ public float m_attackRayWidth;
+
+ public float m_maxYAngle;
+
+ public bool m_lowerDamagePerHit = true;
+
+ public HitPointType m_hitPointtype;
+
+ public bool m_hitThroughWalls;
+
+ public bool m_multiHit = true;
+
+ public float m_lastChainDamageMultiplier = 2f;
+
+ [BitMask(typeof(DestructibleType))]
+ public DestructibleType m_resetChainIfHit;
+
+ [Header("Melee special-skill")]
+ public Skills.SkillType m_specialHitSkill;
+
+ [BitMask(typeof(DestructibleType))]
+ public DestructibleType m_specialHitType;
+
+ [Header("Projectile")]
+ public GameObject m_attackProjectile;
+
+ public float m_projectileVel = 10f;
+
+ public float m_projectileVelMin = 2f;
+
+ public float m_projectileAccuracy = 10f;
+
+ public float m_projectileAccuracyMin = 20f;
+
+ public bool m_useCharacterFacing;
+
+ public bool m_useCharacterFacingYAim;
+
+ [FormerlySerializedAs("m_useCharacterFacingAngle")]
+ public float m_launchAngle;
+
+ public int m_projectiles = 1;
+
+ public int m_projectileBursts = 1;
+
+ public float m_burstInterval;
+
+ public bool m_destroyPreviousProjectile;
+
+ [Header("Attack-Effects")]
+ public EffectList m_hitEffect = new EffectList();
+
+ public EffectList m_hitTerrainEffect = new EffectList();
+
+ public EffectList m_startEffect = new EffectList();
+
+ public EffectList m_triggerEffect = new EffectList();
+
+ public EffectList m_trailStartEffect = new EffectList();
+
+ protected static int m_attackMask;
+
+ protected static int m_attackMaskTerrain;
+
+ private Humanoid m_character;
+
+ private BaseAI m_baseAI;
+
+ private Rigidbody m_body;
+
+ private ZSyncAnimation m_zanim;
+
+ private CharacterAnimEvent m_animEvent;
+
+ [NonSerialized]
+ private ItemDrop.ItemData m_weapon;
+
+ private VisEquipment m_visEquipment;
+
+ private float m_attackDrawPercentage;
+
+ private const float m_freezeFrameDuration = 0.15f;
+
+ private const float m_chainAttackMaxTime = 0.2f;
+
+ private int m_nextAttackChainLevel;
+
+ private int m_currentAttackCainLevel;
+
+ private bool m_wasInAttack;
+
+ private float m_time;
+
+ private bool m_projectileAttackStarted;
+
+ private float m_projectileFireTimer = -1f;
+
+ private int m_projectileBurstsFired;
+
+ [NonSerialized]
+ private ItemDrop.ItemData m_ammoItem;
+
+ public bool StartDraw(Humanoid character, ItemDrop.ItemData weapon)
+ {
+ if (!HaveAmmo(character, weapon))
+ {
+ return false;
+ }
+ EquipAmmoItem(character, weapon);
+ return true;
+ }
+
+ public bool Start(Humanoid character, Rigidbody body, ZSyncAnimation zanim, CharacterAnimEvent animEvent, VisEquipment visEquipment, ItemDrop.ItemData weapon, Attack previousAttack, float timeSinceLastAttack, float attackDrawPercentage)
+ {
+ if (m_attackAnimation == "")
+ {
+ return false;
+ }
+ m_character = character;
+ m_baseAI = m_character.GetComponent<BaseAI>();
+ m_body = body;
+ m_zanim = zanim;
+ m_animEvent = animEvent;
+ m_visEquipment = visEquipment;
+ m_weapon = weapon;
+ m_attackDrawPercentage = attackDrawPercentage;
+ if (m_attackMask == 0)
+ {
+ m_attackMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle");
+ m_attackMaskTerrain = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle");
+ }
+ float staminaUsage = GetStaminaUsage();
+ if (staminaUsage > 0f && !character.HaveStamina(staminaUsage + 0.1f))
+ {
+ if (character.IsPlayer())
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ return false;
+ }
+ if (!HaveAmmo(character, m_weapon))
+ {
+ return false;
+ }
+ EquipAmmoItem(character, m_weapon);
+ if (m_attackChainLevels > 1)
+ {
+ if (previousAttack != null && previousAttack.m_attackAnimation == m_attackAnimation)
+ {
+ m_currentAttackCainLevel = previousAttack.m_nextAttackChainLevel;
+ }
+ if (m_currentAttackCainLevel >= m_attackChainLevels || timeSinceLastAttack > 0.2f)
+ {
+ m_currentAttackCainLevel = 0;
+ }
+ m_zanim.SetTrigger(m_attackAnimation + m_currentAttackCainLevel);
+ }
+ else if (m_attackRandomAnimations >= 2)
+ {
+ int num = UnityEngine.Random.Range(0, m_attackRandomAnimations);
+ m_zanim.SetTrigger(m_attackAnimation + num);
+ }
+ else
+ {
+ m_zanim.SetTrigger(m_attackAnimation);
+ }
+ if (character.IsPlayer() && m_attackType != AttackType.None && m_currentAttackCainLevel == 0)
+ {
+ if (ZInput.IsMouseActive() || m_attackType == AttackType.Projectile)
+ {
+ character.transform.rotation = character.GetLookYaw();
+ m_body.rotation = character.transform.rotation;
+ }
+ else if (ZInput.IsGamepadActive() && !character.IsBlocking() && character.GetMoveDir().magnitude > 0.3f)
+ {
+ character.transform.rotation = Quaternion.LookRotation(character.GetMoveDir());
+ m_body.rotation = character.transform.rotation;
+ }
+ }
+ weapon.m_lastAttackTime = Time.time;
+ m_animEvent.ResetChain();
+ return true;
+ }
+
+ private float GetStaminaUsage()
+ {
+ if (m_attackStamina <= 0f)
+ {
+ return 0f;
+ }
+ float attackStamina = m_attackStamina;
+ float skillFactor = m_character.GetSkillFactor(m_weapon.m_shared.m_skillType);
+ return attackStamina - attackStamina * 0.33f * skillFactor;
+ }
+
+ public void Update(float dt)
+ {
+ m_time += dt;
+ if (m_character.InAttack())
+ {
+ if (!m_wasInAttack)
+ {
+ m_character.UseStamina(GetStaminaUsage());
+ Transform attackOrigin = GetAttackOrigin();
+ m_weapon.m_shared.m_startEffect.Create(attackOrigin.position, m_character.transform.rotation, attackOrigin);
+ m_startEffect.Create(attackOrigin.position, m_character.transform.rotation, attackOrigin);
+ m_character.AddNoise(m_attackStartNoise);
+ m_nextAttackChainLevel = m_currentAttackCainLevel + 1;
+ if (m_nextAttackChainLevel >= m_attackChainLevels)
+ {
+ m_nextAttackChainLevel = 0;
+ }
+ }
+ m_wasInAttack = true;
+ }
+ else if (m_wasInAttack)
+ {
+ OnAttackDone();
+ m_wasInAttack = false;
+ }
+ UpdateProjectile(dt);
+ }
+
+ private void OnAttackDone()
+ {
+ if ((bool)m_visEquipment)
+ {
+ m_visEquipment.SetWeaponTrails(enabled: false);
+ }
+ }
+
+ public void Stop()
+ {
+ if (m_wasInAttack)
+ {
+ OnAttackDone();
+ m_wasInAttack = false;
+ }
+ }
+
+ public void OnAttackTrigger()
+ {
+ if (UseAmmo())
+ {
+ switch (m_attackType)
+ {
+ case AttackType.Horizontal:
+ case AttackType.Vertical:
+ DoMeleeAttack();
+ break;
+ case AttackType.Area:
+ DoAreaAttack();
+ break;
+ case AttackType.Projectile:
+ ProjectileAttackTriggered();
+ break;
+ case AttackType.None:
+ DoNonAttack();
+ break;
+ }
+ if (m_consumeItem)
+ {
+ ConsumeItem();
+ }
+ }
+ }
+
+ private void ConsumeItem()
+ {
+ if (m_weapon.m_shared.m_maxStackSize > 1 && m_weapon.m_stack > 1)
+ {
+ m_weapon.m_stack--;
+ return;
+ }
+ m_character.UnequipItem(m_weapon, triggerEquipEffects: false);
+ m_character.GetInventory().RemoveItem(m_weapon);
+ }
+
+ private static bool EquipAmmoItem(Humanoid character, ItemDrop.ItemData weapon)
+ {
+ if (!string.IsNullOrEmpty(weapon.m_shared.m_ammoType))
+ {
+ ItemDrop.ItemData ammoItem = character.GetAmmoItem();
+ if (ammoItem != null && character.GetInventory().ContainsItem(ammoItem) && ammoItem.m_shared.m_ammoType == weapon.m_shared.m_ammoType)
+ {
+ return true;
+ }
+ ItemDrop.ItemData ammoItem2 = character.GetInventory().GetAmmoItem(weapon.m_shared.m_ammoType);
+ if (ammoItem2.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Ammo)
+ {
+ return character.EquipItem(ammoItem2);
+ }
+ }
+ return true;
+ }
+
+ private static bool HaveAmmo(Humanoid character, ItemDrop.ItemData weapon)
+ {
+ if (!string.IsNullOrEmpty(weapon.m_shared.m_ammoType))
+ {
+ ItemDrop.ItemData itemData = character.GetAmmoItem();
+ if (itemData != null && (!character.GetInventory().ContainsItem(itemData) || itemData.m_shared.m_ammoType != weapon.m_shared.m_ammoType))
+ {
+ itemData = null;
+ }
+ if (itemData == null)
+ {
+ itemData = character.GetInventory().GetAmmoItem(weapon.m_shared.m_ammoType);
+ }
+ if (itemData == null)
+ {
+ character.Message(MessageHud.MessageType.Center, "$msg_outof " + weapon.m_shared.m_ammoType);
+ return false;
+ }
+ if (itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Consumable)
+ {
+ return character.CanConsumeItem(itemData);
+ }
+ return true;
+ }
+ return true;
+ }
+
+ private bool UseAmmo()
+ {
+ m_ammoItem = null;
+ ItemDrop.ItemData itemData = null;
+ if (!string.IsNullOrEmpty(m_weapon.m_shared.m_ammoType))
+ {
+ itemData = m_character.GetAmmoItem();
+ if (itemData != null && (!m_character.GetInventory().ContainsItem(itemData) || itemData.m_shared.m_ammoType != m_weapon.m_shared.m_ammoType))
+ {
+ itemData = null;
+ }
+ if (itemData == null)
+ {
+ itemData = m_character.GetInventory().GetAmmoItem(m_weapon.m_shared.m_ammoType);
+ }
+ if (itemData == null)
+ {
+ m_character.Message(MessageHud.MessageType.Center, "$msg_outof " + m_weapon.m_shared.m_ammoType);
+ return false;
+ }
+ if (itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Consumable)
+ {
+ bool num = m_character.ConsumeItem(m_character.GetInventory(), itemData);
+ if (num)
+ {
+ m_ammoItem = itemData;
+ }
+ return num;
+ }
+ m_character.GetInventory().RemoveItem(itemData, 1);
+ m_ammoItem = itemData;
+ return true;
+ }
+ return true;
+ }
+
+ private void ProjectileAttackTriggered()
+ {
+ GetProjectileSpawnPoint(out var spawnPoint, out var aimDir);
+ m_weapon.m_shared.m_triggerEffect.Create(spawnPoint, Quaternion.LookRotation(aimDir));
+ m_triggerEffect.Create(spawnPoint, Quaternion.LookRotation(aimDir));
+ if (m_weapon.m_shared.m_useDurability && m_character.IsPlayer())
+ {
+ m_weapon.m_durability -= m_weapon.m_shared.m_useDurabilityDrain;
+ }
+ if (m_projectileBursts == 1)
+ {
+ FireProjectileBurst();
+ }
+ else
+ {
+ m_projectileAttackStarted = true;
+ }
+ }
+
+ private void UpdateProjectile(float dt)
+ {
+ if (m_projectileAttackStarted && m_projectileBurstsFired < m_projectileBursts)
+ {
+ m_projectileFireTimer -= dt;
+ if (m_projectileFireTimer <= 0f)
+ {
+ m_projectileFireTimer = m_burstInterval;
+ FireProjectileBurst();
+ m_projectileBurstsFired++;
+ }
+ }
+ }
+
+ private Transform GetAttackOrigin()
+ {
+ if (m_attackOriginJoint.Length > 0)
+ {
+ return Utils.FindChild(m_character.GetVisual().transform, m_attackOriginJoint);
+ }
+ return m_character.transform;
+ }
+
+ private void GetProjectileSpawnPoint(out Vector3 spawnPoint, out Vector3 aimDir)
+ {
+ Transform attackOrigin = GetAttackOrigin();
+ Transform transform = m_character.transform;
+ spawnPoint = attackOrigin.position + transform.up * m_attackHeight + transform.forward * m_attackRange + transform.right * m_attackOffset;
+ aimDir = m_character.GetAimDir(spawnPoint);
+ if ((bool)m_baseAI)
+ {
+ Character targetCreature = m_baseAI.GetTargetCreature();
+ if ((bool)targetCreature)
+ {
+ Vector3 normalized = (targetCreature.GetCenterPoint() - spawnPoint).normalized;
+ aimDir = Vector3.RotateTowards(m_character.transform.forward, normalized, (float)Math.PI / 2f, 1f);
+ }
+ }
+ }
+
+ private void FireProjectileBurst()
+ {
+ ItemDrop.ItemData ammoItem = m_ammoItem;
+ GameObject attackProjectile = m_attackProjectile;
+ float num = m_projectileVel;
+ float num2 = m_projectileVelMin;
+ float num3 = m_projectileAccuracy;
+ float num4 = m_projectileAccuracyMin;
+ float num5 = m_attackHitNoise;
+ if (ammoItem != null && (bool)ammoItem.m_shared.m_attack.m_attackProjectile)
+ {
+ attackProjectile = ammoItem.m_shared.m_attack.m_attackProjectile;
+ num += ammoItem.m_shared.m_attack.m_projectileVel;
+ num2 += ammoItem.m_shared.m_attack.m_projectileVelMin;
+ num3 += ammoItem.m_shared.m_attack.m_projectileAccuracy;
+ num4 += ammoItem.m_shared.m_attack.m_projectileAccuracyMin;
+ num5 += ammoItem.m_shared.m_attack.m_attackHitNoise;
+ }
+ float num6 = m_character.GetRandomSkillFactor(m_weapon.m_shared.m_skillType);
+ if (m_weapon.m_shared.m_holdDurationMin > 0f)
+ {
+ num3 = Mathf.Lerp(num4, num3, Mathf.Pow(m_attackDrawPercentage, 0.5f));
+ num6 *= m_attackDrawPercentage;
+ num = Mathf.Lerp(num2, num, m_attackDrawPercentage);
+ }
+ GetProjectileSpawnPoint(out var spawnPoint, out var aimDir);
+ Transform transform = m_character.transform;
+ if (m_useCharacterFacing)
+ {
+ Vector3 forward = Vector3.forward;
+ if (m_useCharacterFacingYAim)
+ {
+ forward.y = aimDir.y;
+ }
+ aimDir = transform.TransformDirection(forward);
+ }
+ if (m_launchAngle != 0f)
+ {
+ Vector3 axis = Vector3.Cross(Vector3.up, aimDir);
+ aimDir = Quaternion.AngleAxis(m_launchAngle, axis) * aimDir;
+ }
+ for (int i = 0; i < m_projectiles; i++)
+ {
+ if (m_destroyPreviousProjectile && (bool)m_weapon.m_lastProjectile)
+ {
+ ZNetScene.instance.Destroy(m_weapon.m_lastProjectile);
+ m_weapon.m_lastProjectile = null;
+ }
+ Vector3 vector = aimDir;
+ Vector3 axis2 = Vector3.Cross(vector, Vector3.up);
+ Quaternion quaternion = Quaternion.AngleAxis(UnityEngine.Random.Range(0f - num3, num3), Vector3.up);
+ vector = Quaternion.AngleAxis(UnityEngine.Random.Range(0f - num3, num3), axis2) * vector;
+ vector = quaternion * vector;
+ GameObject gameObject = UnityEngine.Object.Instantiate(attackProjectile, spawnPoint, Quaternion.LookRotation(vector));
+ HitData hitData = new HitData();
+ hitData.m_toolTier = m_weapon.m_shared.m_toolTier;
+ hitData.m_pushForce = m_weapon.m_shared.m_attackForce * m_forceMultiplier;
+ hitData.m_backstabBonus = m_weapon.m_shared.m_backstabBonus;
+ hitData.m_staggerMultiplier = m_staggerMultiplier;
+ hitData.m_damage.Add(m_weapon.GetDamage());
+ hitData.m_statusEffect = (m_weapon.m_shared.m_attackStatusEffect ? m_weapon.m_shared.m_attackStatusEffect.name : "");
+ hitData.m_blockable = m_weapon.m_shared.m_blockable;
+ hitData.m_dodgeable = m_weapon.m_shared.m_dodgeable;
+ hitData.m_skill = m_weapon.m_shared.m_skillType;
+ hitData.SetAttacker(m_character);
+ if (ammoItem != null)
+ {
+ hitData.m_damage.Add(ammoItem.GetDamage());
+ hitData.m_pushForce += ammoItem.m_shared.m_attackForce;
+ if (ammoItem.m_shared.m_attackStatusEffect != null)
+ {
+ hitData.m_statusEffect = ammoItem.m_shared.m_attackStatusEffect.name;
+ }
+ if (!ammoItem.m_shared.m_blockable)
+ {
+ hitData.m_blockable = false;
+ }
+ if (!ammoItem.m_shared.m_dodgeable)
+ {
+ hitData.m_dodgeable = false;
+ }
+ }
+ hitData.m_pushForce *= num6;
+ hitData.m_damage.Modify(m_damageMultiplier);
+ hitData.m_damage.Modify(num6);
+ hitData.m_damage.Modify(GetLevelDamageFactor());
+ m_character.GetSEMan().ModifyAttack(m_weapon.m_shared.m_skillType, ref hitData);
+ gameObject.GetComponent<IProjectile>()?.Setup(m_character, vector * num, num5, hitData, m_weapon);
+ m_weapon.m_lastProjectile = gameObject;
+ }
+ }
+
+ private void DoNonAttack()
+ {
+ if (m_weapon.m_shared.m_useDurability && m_character.IsPlayer())
+ {
+ m_weapon.m_durability -= m_weapon.m_shared.m_useDurabilityDrain;
+ }
+ Transform attackOrigin = GetAttackOrigin();
+ m_weapon.m_shared.m_triggerEffect.Create(attackOrigin.position, m_character.transform.rotation, attackOrigin);
+ m_triggerEffect.Create(attackOrigin.position, m_character.transform.rotation, attackOrigin);
+ if ((bool)m_weapon.m_shared.m_consumeStatusEffect)
+ {
+ m_character.GetSEMan().AddStatusEffect(m_weapon.m_shared.m_consumeStatusEffect, resetTime: true);
+ }
+ m_character.AddNoise(m_attackHitNoise);
+ }
+
+ private float GetLevelDamageFactor()
+ {
+ return 1f + (float)Mathf.Max(0, m_character.GetLevel() - 1) * 0.5f;
+ }
+
+ private void DoAreaAttack()
+ {
+ Transform transform = m_character.transform;
+ Transform attackOrigin = GetAttackOrigin();
+ Vector3 vector = attackOrigin.position + Vector3.up * m_attackHeight + transform.forward * m_attackRange + transform.right * m_attackOffset;
+ m_weapon.m_shared.m_triggerEffect.Create(vector, transform.rotation, attackOrigin);
+ m_triggerEffect.Create(vector, transform.rotation, attackOrigin);
+ Vector3 vector2 = vector - transform.position;
+ vector2.y = 0f;
+ vector2.Normalize();
+ int num = 0;
+ Vector3 zero = Vector3.zero;
+ bool flag = false;
+ bool flag2 = false;
+ float randomSkillFactor = m_character.GetRandomSkillFactor(m_weapon.m_shared.m_skillType);
+ int layerMask = (m_hitTerrain ? m_attackMaskTerrain : m_attackMask);
+ Collider[] array = Physics.OverlapSphere(vector, m_attackRayWidth, layerMask, QueryTriggerInteraction.UseGlobal);
+ HashSet<GameObject> hashSet = new HashSet<GameObject>();
+ Collider[] array2 = array;
+ foreach (Collider collider in array2)
+ {
+ if (collider.gameObject == m_character.gameObject)
+ {
+ continue;
+ }
+ GameObject gameObject = Projectile.FindHitObject(collider);
+ if (gameObject == m_character.gameObject || hashSet.Contains(gameObject))
+ {
+ continue;
+ }
+ hashSet.Add(gameObject);
+ Vector3 vector3 = ((!(collider is MeshCollider)) ? collider.ClosestPoint(vector) : collider.ClosestPointOnBounds(vector));
+ IDestructible component = gameObject.GetComponent<IDestructible>();
+ if (component != null)
+ {
+ Vector3 vector4 = vector3 - vector;
+ vector4.y = 0f;
+ float num2 = Vector3.Dot(vector2, vector4);
+ if (num2 < 0f)
+ {
+ vector4 += vector2 * (0f - num2);
+ }
+ vector4.Normalize();
+ HitData hitData = new HitData();
+ hitData.m_toolTier = m_weapon.m_shared.m_toolTier;
+ hitData.m_statusEffect = (m_weapon.m_shared.m_attackStatusEffect ? m_weapon.m_shared.m_attackStatusEffect.name : "");
+ hitData.m_pushForce = m_weapon.m_shared.m_attackForce * randomSkillFactor * m_forceMultiplier;
+ hitData.m_backstabBonus = m_weapon.m_shared.m_backstabBonus;
+ hitData.m_staggerMultiplier = m_staggerMultiplier;
+ hitData.m_dodgeable = m_weapon.m_shared.m_dodgeable;
+ hitData.m_blockable = m_weapon.m_shared.m_blockable;
+ hitData.m_skill = m_weapon.m_shared.m_skillType;
+ hitData.m_damage.Add(m_weapon.GetDamage());
+ hitData.m_point = vector3;
+ hitData.m_dir = vector4;
+ hitData.m_hitCollider = collider;
+ hitData.SetAttacker(m_character);
+ hitData.m_damage.Modify(m_damageMultiplier);
+ hitData.m_damage.Modify(randomSkillFactor);
+ hitData.m_damage.Modify(GetLevelDamageFactor());
+ if (m_attackChainLevels > 1 && m_currentAttackCainLevel == m_attackChainLevels - 1 && m_lastChainDamageMultiplier > 1f)
+ {
+ hitData.m_damage.Modify(m_lastChainDamageMultiplier);
+ hitData.m_pushForce *= 1.2f;
+ }
+ m_character.GetSEMan().ModifyAttack(m_weapon.m_shared.m_skillType, ref hitData);
+ Character character = component as Character;
+ if ((bool)character)
+ {
+ if ((!m_character.IsPlayer() && !BaseAI.IsEnemy(m_character, character)) || (hitData.m_dodgeable && character.IsDodgeInvincible()))
+ {
+ continue;
+ }
+ flag2 = true;
+ }
+ component.Damage(hitData);
+ flag = true;
+ }
+ num++;
+ zero += vector3;
+ }
+ if (num > 0)
+ {
+ zero /= (float)num;
+ m_weapon.m_shared.m_hitEffect.Create(zero, Quaternion.identity);
+ m_hitEffect.Create(zero, Quaternion.identity);
+ if (m_weapon.m_shared.m_useDurability && m_character.IsPlayer())
+ {
+ m_weapon.m_durability -= 1f;
+ }
+ m_character.AddNoise(m_attackHitNoise);
+ if (flag)
+ {
+ m_character.RaiseSkill(m_weapon.m_shared.m_skillType, flag2 ? 1.5f : 1f);
+ }
+ }
+ if ((bool)m_spawnOnTrigger)
+ {
+ UnityEngine.Object.Instantiate(m_spawnOnTrigger, vector, Quaternion.identity).GetComponent<IProjectile>()?.Setup(m_character, m_character.transform.forward, -1f, null, null);
+ }
+ }
+
+ private void GetMeleeAttackDir(out Transform originJoint, out Vector3 attackDir)
+ {
+ originJoint = GetAttackOrigin();
+ Vector3 forward = m_character.transform.forward;
+ Vector3 aimDir = m_character.GetAimDir(originJoint.position);
+ aimDir.x = forward.x;
+ aimDir.z = forward.z;
+ aimDir.Normalize();
+ attackDir = Vector3.RotateTowards(m_character.transform.forward, aimDir, (float)Math.PI / 180f * m_maxYAngle, 10f);
+ }
+
+ private void AddHitPoint(List<HitPoint> list, GameObject go, Collider collider, Vector3 point, float distance)
+ {
+ HitPoint hitPoint = null;
+ for (int num = list.Count - 1; num >= 0; num--)
+ {
+ if (list[num].go == go)
+ {
+ hitPoint = list[num];
+ break;
+ }
+ }
+ if (hitPoint == null)
+ {
+ hitPoint = new HitPoint();
+ hitPoint.go = go;
+ hitPoint.collider = collider;
+ hitPoint.firstPoint = point;
+ list.Add(hitPoint);
+ }
+ hitPoint.avgPoint += point;
+ hitPoint.count++;
+ if (distance < hitPoint.closestDistance)
+ {
+ hitPoint.closestPoint = point;
+ hitPoint.closestDistance = distance;
+ }
+ }
+
+ private void DoMeleeAttack()
+ {
+ GetMeleeAttackDir(out var originJoint, out var attackDir);
+ Vector3 vector = m_character.transform.InverseTransformDirection(attackDir);
+ Quaternion quaternion = Quaternion.LookRotation(attackDir, Vector3.up);
+ m_weapon.m_shared.m_triggerEffect.Create(originJoint.position, quaternion, originJoint);
+ m_triggerEffect.Create(originJoint.position, quaternion, originJoint);
+ Vector3 vector2 = originJoint.position + Vector3.up * m_attackHeight + m_character.transform.right * m_attackOffset;
+ float num = m_attackAngle / 2f;
+ float num2 = 4f;
+ float attackRange = m_attackRange;
+ List<HitPoint> list = new List<HitPoint>();
+ HashSet<Skills.SkillType> hashSet = new HashSet<Skills.SkillType>();
+ int layerMask = (m_hitTerrain ? m_attackMaskTerrain : m_attackMask);
+ for (float num3 = 0f - num; num3 <= num; num3 += num2)
+ {
+ Quaternion quaternion2 = Quaternion.identity;
+ if (m_attackType == AttackType.Horizontal)
+ {
+ quaternion2 = Quaternion.Euler(0f, 0f - num3, 0f);
+ }
+ else if (m_attackType == AttackType.Vertical)
+ {
+ quaternion2 = Quaternion.Euler(num3, 0f, 0f);
+ }
+ Vector3 vector3 = m_character.transform.TransformDirection(quaternion2 * vector);
+ Debug.DrawLine(vector2, vector2 + vector3 * attackRange);
+ RaycastHit[] array = ((!(m_attackRayWidth > 0f)) ? Physics.RaycastAll(vector2, vector3, attackRange, layerMask, QueryTriggerInteraction.Ignore) : Physics.SphereCastAll(vector2, m_attackRayWidth, vector3, Mathf.Max(0f, attackRange - m_attackRayWidth), layerMask, QueryTriggerInteraction.Ignore));
+ Array.Sort(array, (RaycastHit x, RaycastHit y) => x.distance.CompareTo(y.distance));
+ RaycastHit[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ RaycastHit raycastHit = array2[i];
+ if (raycastHit.collider.gameObject == m_character.gameObject)
+ {
+ continue;
+ }
+ Vector3 vector4 = raycastHit.point;
+ if (raycastHit.distance < float.Epsilon)
+ {
+ vector4 = ((!(raycastHit.collider is MeshCollider)) ? raycastHit.collider.ClosestPoint(vector2) : (vector2 + vector3 * attackRange));
+ }
+ if (m_attackAngle < 180f && Vector3.Dot(vector4 - vector2, attackDir) <= 0f)
+ {
+ continue;
+ }
+ GameObject gameObject = Projectile.FindHitObject(raycastHit.collider);
+ if (gameObject == m_character.gameObject)
+ {
+ continue;
+ }
+ Vagon component = gameObject.GetComponent<Vagon>();
+ if ((bool)component && component.IsAttached(m_character))
+ {
+ continue;
+ }
+ Character component2 = gameObject.GetComponent<Character>();
+ if (!(component2 != null) || ((m_character.IsPlayer() || BaseAI.IsEnemy(m_character, component2)) && (!m_weapon.m_shared.m_dodgeable || !component2.IsDodgeInvincible())))
+ {
+ AddHitPoint(list, gameObject, raycastHit.collider, vector4, raycastHit.distance);
+ if (!m_hitThroughWalls)
+ {
+ break;
+ }
+ }
+ }
+ }
+ int num4 = 0;
+ Vector3 zero = Vector3.zero;
+ bool flag = false;
+ bool flag2 = false;
+ foreach (HitPoint item in list)
+ {
+ GameObject go = item.go;
+ Vector3 vector5 = item.avgPoint / item.count;
+ Vector3 vector6 = vector5;
+ switch (m_hitPointtype)
+ {
+ case HitPointType.Average:
+ vector6 = vector5;
+ break;
+ case HitPointType.First:
+ vector6 = item.firstPoint;
+ break;
+ case HitPointType.Closest:
+ vector6 = item.closestPoint;
+ break;
+ }
+ num4++;
+ zero += vector5;
+ m_weapon.m_shared.m_hitEffect.Create(vector6, Quaternion.identity);
+ m_hitEffect.Create(vector6, Quaternion.identity);
+ IDestructible component3 = go.GetComponent<IDestructible>();
+ if (component3 != null)
+ {
+ DestructibleType destructibleType = component3.GetDestructibleType();
+ Skills.SkillType skillType = m_weapon.m_shared.m_skillType;
+ if (m_specialHitSkill != 0 && (destructibleType & m_specialHitType) != 0)
+ {
+ skillType = m_specialHitSkill;
+ }
+ float num5 = m_character.GetRandomSkillFactor(skillType);
+ if (m_lowerDamagePerHit && list.Count > 1)
+ {
+ num5 /= (float)list.Count * 0.75f;
+ }
+ HitData hitData = new HitData();
+ hitData.m_toolTier = m_weapon.m_shared.m_toolTier;
+ hitData.m_statusEffect = (m_weapon.m_shared.m_attackStatusEffect ? m_weapon.m_shared.m_attackStatusEffect.name : "");
+ hitData.m_pushForce = m_weapon.m_shared.m_attackForce * num5 * m_forceMultiplier;
+ hitData.m_backstabBonus = m_weapon.m_shared.m_backstabBonus;
+ hitData.m_staggerMultiplier = m_staggerMultiplier;
+ hitData.m_dodgeable = m_weapon.m_shared.m_dodgeable;
+ hitData.m_blockable = m_weapon.m_shared.m_blockable;
+ hitData.m_skill = skillType;
+ hitData.m_damage = m_weapon.GetDamage();
+ hitData.m_point = vector6;
+ hitData.m_dir = (vector6 - vector2).normalized;
+ hitData.m_hitCollider = item.collider;
+ hitData.SetAttacker(m_character);
+ hitData.m_damage.Modify(m_damageMultiplier);
+ hitData.m_damage.Modify(num5);
+ hitData.m_damage.Modify(GetLevelDamageFactor());
+ if (m_attackChainLevels > 1 && m_currentAttackCainLevel == m_attackChainLevels - 1)
+ {
+ hitData.m_damage.Modify(2f);
+ hitData.m_pushForce *= 1.2f;
+ }
+ m_character.GetSEMan().ModifyAttack(skillType, ref hitData);
+ if (component3 is Character)
+ {
+ flag2 = true;
+ }
+ component3.Damage(hitData);
+ if ((destructibleType & m_resetChainIfHit) != 0)
+ {
+ m_nextAttackChainLevel = 0;
+ }
+ hashSet.Add(skillType);
+ if (!m_multiHit)
+ {
+ break;
+ }
+ }
+ if (go.GetComponent<Heightmap>() != null && !flag)
+ {
+ flag = true;
+ m_weapon.m_shared.m_hitTerrainEffect.Create(vector5, quaternion);
+ m_hitTerrainEffect.Create(vector5, quaternion);
+ if ((bool)m_weapon.m_shared.m_spawnOnHitTerrain)
+ {
+ SpawnOnHitTerrain(vector5, m_weapon.m_shared.m_spawnOnHitTerrain);
+ }
+ if (!m_multiHit)
+ {
+ break;
+ }
+ }
+ }
+ if (num4 > 0)
+ {
+ zero /= (float)num4;
+ if (m_weapon.m_shared.m_useDurability && m_character.IsPlayer())
+ {
+ m_weapon.m_durability -= m_weapon.m_shared.m_useDurabilityDrain;
+ }
+ m_character.AddNoise(m_attackHitNoise);
+ m_animEvent.FreezeFrame(0.15f);
+ if ((bool)m_weapon.m_shared.m_spawnOnHit)
+ {
+ UnityEngine.Object.Instantiate(m_weapon.m_shared.m_spawnOnHit, zero, quaternion).GetComponent<IProjectile>()?.Setup(m_character, Vector3.zero, m_attackHitNoise, null, m_weapon);
+ }
+ foreach (Skills.SkillType item2 in hashSet)
+ {
+ m_character.RaiseSkill(item2, flag2 ? 1.5f : 1f);
+ }
+ }
+ if ((bool)m_spawnOnTrigger)
+ {
+ UnityEngine.Object.Instantiate(m_spawnOnTrigger, vector2, Quaternion.identity).GetComponent<IProjectile>()?.Setup(m_character, m_character.transform.forward, -1f, null, m_weapon);
+ }
+ }
+
+ private void SpawnOnHitTerrain(Vector3 hitPoint, GameObject prefab)
+ {
+ TerrainModifier componentInChildren = prefab.GetComponentInChildren<TerrainModifier>();
+ if (!componentInChildren || (PrivateArea.CheckAccess(hitPoint, componentInChildren.GetRadius()) && !Location.IsInsideNoBuildLocation(hitPoint)))
+ {
+ TerrainModifier.SetTriggerOnPlaced(trigger: true);
+ GameObject gameObject = UnityEngine.Object.Instantiate(prefab, hitPoint, Quaternion.LookRotation(m_character.transform.forward));
+ TerrainModifier.SetTriggerOnPlaced(trigger: false);
+ gameObject.GetComponent<IProjectile>()?.Setup(m_character, Vector3.zero, m_attackHitNoise, null, m_weapon);
+ }
+ }
+
+ public Attack Clone()
+ {
+ return MemberwiseClone() as Attack;
+ }
+
+ public ItemDrop.ItemData GetWeapon()
+ {
+ return m_weapon;
+ }
+
+ public bool CanStartChainAttack()
+ {
+ if (m_nextAttackChainLevel > 0)
+ {
+ return m_animEvent.CanChain();
+ }
+ return false;
+ }
+
+ public void OnTrailStart()
+ {
+ if (m_attackType == AttackType.Projectile)
+ {
+ Transform attackOrigin = GetAttackOrigin();
+ m_weapon.m_shared.m_trailStartEffect.Create(attackOrigin.position, m_character.transform.rotation);
+ m_trailStartEffect.Create(attackOrigin.position, m_character.transform.rotation);
+ }
+ else
+ {
+ GetMeleeAttackDir(out var originJoint, out var attackDir);
+ Quaternion rot = Quaternion.LookRotation(attackDir, Vector3.up);
+ m_weapon.m_shared.m_trailStartEffect.Create(originJoint.position, rot);
+ m_trailStartEffect.Create(originJoint.position, rot);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AudioMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AudioMan.cs
new file mode 100644
index 0000000..3c4d300
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AudioMan.cs
@@ -0,0 +1,496 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Audio;
+using UnityEngine.Rendering;
+
+public class AudioMan : MonoBehaviour
+{
+ [Serializable]
+ public class BiomeAmbients
+ {
+ public string m_name = "";
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ public List<AudioClip> m_randomAmbientClips = new List<AudioClip>();
+
+ public List<AudioClip> m_randomAmbientClipsDay = new List<AudioClip>();
+
+ public List<AudioClip> m_randomAmbientClipsNight = new List<AudioClip>();
+ }
+
+ private enum Snapshot
+ {
+ Default,
+ Menu,
+ Indoor
+ }
+
+ private static AudioMan m_instance;
+
+ [Header("Mixers")]
+ public AudioMixerGroup m_ambientMixer;
+
+ public AudioMixer m_masterMixer;
+
+ public float m_snapshotTransitionTime = 2f;
+
+ [Header("Wind")]
+ public AudioClip m_windAudio;
+
+ public float m_windMinVol;
+
+ public float m_windMaxVol = 1f;
+
+ public float m_windMinPitch = 0.5f;
+
+ public float m_windMaxPitch = 1.5f;
+
+ public float m_windVariation = 0.2f;
+
+ public float m_windIntensityPower = 1.5f;
+
+ [Header("Ocean")]
+ public AudioClip m_oceanAudio;
+
+ public float m_oceanVolumeMax = 1f;
+
+ public float m_oceanVolumeMin = 1f;
+
+ public float m_oceanFadeSpeed = 0.1f;
+
+ public float m_oceanMoveSpeed = 0.1f;
+
+ public float m_oceanDepthTreshold = 10f;
+
+ [Header("Random ambients")]
+ public float m_ambientFadeTime = 2f;
+
+ public float m_randomAmbientInterval = 5f;
+
+ public float m_randomAmbientChance = 0.5f;
+
+ public float m_randomMinPitch = 0.9f;
+
+ public float m_randomMaxPitch = 1.1f;
+
+ public float m_randomMinVol = 0.2f;
+
+ public float m_randomMaxVol = 0.4f;
+
+ public float m_randomPan = 0.2f;
+
+ public float m_randomFadeIn = 0.2f;
+
+ public float m_randomFadeOut = 2f;
+
+ public float m_randomMinDistance = 5f;
+
+ public float m_randomMaxDistance = 20f;
+
+ public List<BiomeAmbients> m_randomAmbients = new List<BiomeAmbients>();
+
+ public GameObject m_randomAmbientPrefab;
+
+ private AudioSource m_oceanAmbientSource;
+
+ private AudioSource m_ambientLoopSource;
+
+ private AudioSource m_windLoopSource;
+
+ private AudioClip m_queuedAmbientLoop;
+
+ private float m_queuedAmbientVol;
+
+ private float m_ambientVol;
+
+ private float m_randomAmbientTimer;
+
+ private bool m_stopAmbientLoop;
+
+ private bool m_indoor;
+
+ private float m_oceanUpdateTimer;
+
+ private bool m_haveOcean;
+
+ private Vector3 m_avgOceanPoint = Vector3.zero;
+
+ private Snapshot m_currentSnapshot;
+
+ public static AudioMan instance => m_instance;
+
+ private void Awake()
+ {
+ if (m_instance != null)
+ {
+ ZLog.Log("Audioman already exist, destroying self");
+ UnityEngine.Object.DestroyImmediate(base.gameObject);
+ return;
+ }
+ m_instance = this;
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ GameObject gameObject = new GameObject("ocean_ambient_loop");
+ gameObject.transform.SetParent(base.transform);
+ m_oceanAmbientSource = gameObject.AddComponent<AudioSource>();
+ m_oceanAmbientSource.loop = true;
+ m_oceanAmbientSource.spatialBlend = 0.75f;
+ m_oceanAmbientSource.outputAudioMixerGroup = m_ambientMixer;
+ m_oceanAmbientSource.maxDistance = 128f;
+ m_oceanAmbientSource.minDistance = 40f;
+ m_oceanAmbientSource.spread = 90f;
+ m_oceanAmbientSource.rolloffMode = AudioRolloffMode.Linear;
+ m_oceanAmbientSource.clip = m_oceanAudio;
+ m_oceanAmbientSource.bypassReverbZones = true;
+ m_oceanAmbientSource.dopplerLevel = 0f;
+ m_oceanAmbientSource.volume = 0f;
+ m_oceanAmbientSource.Play();
+ GameObject gameObject2 = new GameObject("ambient_loop");
+ gameObject2.transform.SetParent(base.transform);
+ m_ambientLoopSource = gameObject2.AddComponent<AudioSource>();
+ m_ambientLoopSource.loop = true;
+ m_ambientLoopSource.spatialBlend = 0f;
+ m_ambientLoopSource.outputAudioMixerGroup = m_ambientMixer;
+ m_ambientLoopSource.bypassReverbZones = true;
+ m_ambientLoopSource.volume = 0f;
+ GameObject gameObject3 = new GameObject("wind_loop");
+ gameObject3.transform.SetParent(base.transform);
+ m_windLoopSource = gameObject3.AddComponent<AudioSource>();
+ m_windLoopSource.loop = true;
+ m_windLoopSource.spatialBlend = 0f;
+ m_windLoopSource.outputAudioMixerGroup = m_ambientMixer;
+ m_windLoopSource.bypassReverbZones = true;
+ m_windLoopSource.clip = m_windAudio;
+ m_windLoopSource.volume = 0f;
+ m_windLoopSource.Play();
+ if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null)
+ {
+ AudioListener.volume = 0f;
+ return;
+ }
+ AudioListener.volume = PlayerPrefs.GetFloat("MasterVolume", AudioListener.volume);
+ SetSFXVolume(PlayerPrefs.GetFloat("SfxVolume", GetSFXVolume()));
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ private void Update()
+ {
+ float deltaTime = Time.deltaTime;
+ UpdateAmbientLoop(deltaTime);
+ UpdateRandomAmbient(deltaTime);
+ UpdateSnapshots(deltaTime);
+ }
+
+ private void FixedUpdate()
+ {
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ UpdateOceanAmbiance(fixedDeltaTime);
+ UpdateWindAmbience(fixedDeltaTime);
+ }
+
+ public static float GetSFXVolume()
+ {
+ if (m_instance == null)
+ {
+ return 1f;
+ }
+ m_instance.m_masterMixer.GetFloat("SfxVol", out var value);
+ return Mathf.Pow(10f, value / 20f);
+ }
+
+ public static void SetSFXVolume(float vol)
+ {
+ if (!(m_instance == null))
+ {
+ float value = Mathf.Log(Mathf.Clamp(vol, 0.001f, 1f)) * 10f;
+ m_instance.m_masterMixer.SetFloat("SfxVol", value);
+ }
+ }
+
+ private void UpdateRandomAmbient(float dt)
+ {
+ if (InMenu())
+ {
+ return;
+ }
+ m_randomAmbientTimer += dt;
+ if (!(m_randomAmbientTimer > m_randomAmbientInterval))
+ {
+ return;
+ }
+ m_randomAmbientTimer = 0f;
+ if (UnityEngine.Random.value <= m_randomAmbientChance)
+ {
+ AudioClip audioClip = SelectRandomAmbientClip();
+ if ((bool)audioClip)
+ {
+ Vector3 randomAmbiencePoint = GetRandomAmbiencePoint();
+ GameObject obj = UnityEngine.Object.Instantiate(m_randomAmbientPrefab, randomAmbiencePoint, Quaternion.identity, base.transform);
+ obj.GetComponent<AudioSource>().pitch = UnityEngine.Random.Range(m_randomMinPitch, m_randomMaxPitch);
+ ZSFX component = obj.GetComponent<ZSFX>();
+ component.m_audioClips = new AudioClip[1] { audioClip };
+ component.Play();
+ component.FadeOut();
+ }
+ }
+ }
+
+ private Vector3 GetRandomAmbiencePoint()
+ {
+ Vector3 vector = Vector3.zero;
+ Camera mainCamera = Utils.GetMainCamera();
+ if ((bool)Player.m_localPlayer)
+ {
+ vector = Player.m_localPlayer.transform.position;
+ }
+ else if ((bool)mainCamera)
+ {
+ vector = mainCamera.transform.position;
+ }
+ float f = UnityEngine.Random.value * (float)Math.PI * 2f;
+ float num = UnityEngine.Random.Range(m_randomMinDistance, m_randomMaxDistance);
+ return vector + new Vector3(Mathf.Sin(f) * num, 0f, Mathf.Cos(f) * num);
+ }
+
+ private AudioClip SelectRandomAmbientClip()
+ {
+ if (EnvMan.instance == null)
+ {
+ return null;
+ }
+ EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment();
+ BiomeAmbients biomeAmbients = null;
+ biomeAmbients = ((currentEnvironment == null || string.IsNullOrEmpty(currentEnvironment.m_ambientList)) ? GetBiomeAmbients(EnvMan.instance.GetCurrentBiome()) : GetAmbients(currentEnvironment.m_ambientList));
+ if (biomeAmbients == null)
+ {
+ return null;
+ }
+ List<AudioClip> list = new List<AudioClip>(biomeAmbients.m_randomAmbientClips);
+ List<AudioClip> collection = (EnvMan.instance.IsDaylight() ? biomeAmbients.m_randomAmbientClipsDay : biomeAmbients.m_randomAmbientClipsNight);
+ list.AddRange(collection);
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ private void UpdateAmbientLoop(float dt)
+ {
+ if (EnvMan.instance == null)
+ {
+ m_ambientLoopSource.Stop();
+ }
+ else if ((bool)m_queuedAmbientLoop || m_stopAmbientLoop)
+ {
+ if (!m_ambientLoopSource.isPlaying || m_ambientLoopSource.volume <= 0f)
+ {
+ m_ambientLoopSource.Stop();
+ m_stopAmbientLoop = false;
+ if ((bool)m_queuedAmbientLoop)
+ {
+ m_ambientLoopSource.clip = m_queuedAmbientLoop;
+ m_ambientLoopSource.volume = 0f;
+ m_ambientLoopSource.Play();
+ m_ambientVol = m_queuedAmbientVol;
+ m_queuedAmbientLoop = null;
+ }
+ }
+ else
+ {
+ m_ambientLoopSource.volume = Mathf.MoveTowards(m_ambientLoopSource.volume, 0f, dt / m_ambientFadeTime);
+ }
+ }
+ else if (m_ambientLoopSource.isPlaying)
+ {
+ m_ambientLoopSource.volume = Mathf.MoveTowards(m_ambientLoopSource.volume, m_ambientVol, dt / m_ambientFadeTime);
+ }
+ }
+
+ public void SetIndoor(bool indoor)
+ {
+ m_indoor = indoor;
+ }
+
+ private bool InMenu()
+ {
+ if (!(FejdStartup.instance != null) && !Menu.IsVisible() && (!Game.instance || !Game.instance.WaitingForRespawn()))
+ {
+ return TextViewer.IsShowingIntro();
+ }
+ return true;
+ }
+
+ private void UpdateSnapshots(float dt)
+ {
+ if (InMenu())
+ {
+ SetSnapshot(Snapshot.Menu);
+ }
+ else if (m_indoor)
+ {
+ SetSnapshot(Snapshot.Indoor);
+ }
+ else
+ {
+ SetSnapshot(Snapshot.Default);
+ }
+ }
+
+ private void SetSnapshot(Snapshot snapshot)
+ {
+ if (m_currentSnapshot != snapshot)
+ {
+ m_currentSnapshot = snapshot;
+ switch (snapshot)
+ {
+ case Snapshot.Default:
+ m_masterMixer.FindSnapshot("Default").TransitionTo(m_snapshotTransitionTime);
+ break;
+ case Snapshot.Indoor:
+ m_masterMixer.FindSnapshot("Indoor").TransitionTo(m_snapshotTransitionTime);
+ break;
+ case Snapshot.Menu:
+ m_masterMixer.FindSnapshot("Menu").TransitionTo(m_snapshotTransitionTime);
+ break;
+ }
+ }
+ }
+
+ public void StopAmbientLoop()
+ {
+ m_queuedAmbientLoop = null;
+ m_stopAmbientLoop = true;
+ }
+
+ public void QueueAmbientLoop(AudioClip clip, float vol)
+ {
+ if ((!(m_queuedAmbientLoop == clip) || m_queuedAmbientVol != vol) && (!(m_queuedAmbientLoop == null) || !(m_ambientLoopSource.clip == clip) || m_ambientVol != vol))
+ {
+ m_queuedAmbientLoop = clip;
+ m_queuedAmbientVol = vol;
+ m_stopAmbientLoop = false;
+ }
+ }
+
+ private void UpdateWindAmbience(float dt)
+ {
+ if (ZoneSystem.instance == null)
+ {
+ m_windLoopSource.volume = 0f;
+ return;
+ }
+ float windIntensity = EnvMan.instance.GetWindIntensity();
+ windIntensity = Mathf.Pow(windIntensity, m_windIntensityPower);
+ windIntensity += windIntensity * Mathf.Sin(Time.time) * Mathf.Sin(Time.time * 1.54323f) * Mathf.Sin(Time.time * 2.31237f) * m_windVariation;
+ m_windLoopSource.volume = Mathf.Lerp(m_windMinVol, m_windMaxVol, windIntensity);
+ m_windLoopSource.pitch = Mathf.Lerp(m_windMinPitch, m_windMaxPitch, windIntensity);
+ }
+
+ private void UpdateOceanAmbiance(float dt)
+ {
+ if (ZoneSystem.instance == null)
+ {
+ m_oceanAmbientSource.volume = 0f;
+ return;
+ }
+ m_oceanUpdateTimer += dt;
+ if (m_oceanUpdateTimer > 2f)
+ {
+ m_oceanUpdateTimer = 0f;
+ m_haveOcean = FindAverageOceanPoint(out m_avgOceanPoint);
+ }
+ if (m_haveOcean)
+ {
+ float windIntensity = EnvMan.instance.GetWindIntensity();
+ float target = Mathf.Lerp(m_oceanVolumeMin, m_oceanVolumeMax, windIntensity);
+ m_oceanAmbientSource.volume = Mathf.MoveTowards(m_oceanAmbientSource.volume, target, m_oceanFadeSpeed * dt);
+ m_oceanAmbientSource.transform.position = Vector3.Lerp(m_oceanAmbientSource.transform.position, m_avgOceanPoint, m_oceanMoveSpeed);
+ }
+ else
+ {
+ m_oceanAmbientSource.volume = Mathf.MoveTowards(m_oceanAmbientSource.volume, 0f, m_oceanFadeSpeed * dt);
+ }
+ }
+
+ private bool FindAverageOceanPoint(out Vector3 point)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ point = Vector3.zero;
+ return false;
+ }
+ Vector3 zero = Vector3.zero;
+ int num = 0;
+ Vector3 position = mainCamera.transform.position;
+ Vector2i zone = ZoneSystem.instance.GetZone(position);
+ for (int i = -1; i <= 1; i++)
+ {
+ for (int j = -1; j <= 1; j++)
+ {
+ Vector2i id = zone;
+ id.x += j;
+ id.y += i;
+ Vector3 zonePos = ZoneSystem.instance.GetZonePos(id);
+ if (IsOceanZone(zonePos))
+ {
+ num++;
+ zero += zonePos;
+ }
+ }
+ }
+ if (num > 0)
+ {
+ zero /= (float)num;
+ point = zero;
+ point.y = ZoneSystem.instance.m_waterLevel;
+ return true;
+ }
+ point = Vector3.zero;
+ return false;
+ }
+
+ private bool IsOceanZone(Vector3 centerPos)
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(centerPos);
+ if (ZoneSystem.instance.m_waterLevel - groundHeight > m_oceanDepthTreshold)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private BiomeAmbients GetAmbients(string name)
+ {
+ foreach (BiomeAmbients randomAmbient in m_randomAmbients)
+ {
+ if (randomAmbient.m_name == name)
+ {
+ return randomAmbient;
+ }
+ }
+ return null;
+ }
+
+ private BiomeAmbients GetBiomeAmbients(Heightmap.Biome biome)
+ {
+ foreach (BiomeAmbients randomAmbient in m_randomAmbients)
+ {
+ if ((randomAmbient.m_biome & biome) != 0)
+ {
+ return randomAmbient;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AutoJumpLedge.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AutoJumpLedge.cs
new file mode 100644
index 0000000..d39ae81
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/AutoJumpLedge.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+public class AutoJumpLedge : MonoBehaviour
+{
+ public bool m_forwardOnly = true;
+
+ public float m_upVel = 1f;
+
+ public float m_forwardVel = 1f;
+
+ private void OnTriggerStay(Collider collider)
+ {
+ Character component = collider.GetComponent<Character>();
+ if ((bool)component)
+ {
+ component.OnAutoJump(base.transform.forward, m_upVel, m_forwardVel);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BaseAI.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BaseAI.cs
new file mode 100644
index 0000000..7e9d3dd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BaseAI.cs
@@ -0,0 +1,1461 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class BaseAI : MonoBehaviour
+{
+ private float m_lastMoveToWaterUpdate;
+
+ private bool m_haveWaterPosition;
+
+ private Vector3 m_moveToWaterPosition = Vector3.zero;
+
+ private float m_fleeTargetUpdateTime;
+
+ private Vector3 m_fleeTarget = Vector3.zero;
+
+ private float m_nearFireTime;
+
+ private EffectArea m_nearFireArea;
+
+ private float aroundPointUpdateTime;
+
+ private Vector3 arroundPointTarget = Vector3.zero;
+
+ private const bool m_debugDraw = false;
+
+ public float m_viewRange = 50f;
+
+ public float m_viewAngle = 90f;
+
+ public float m_hearRange = 9999f;
+
+ private const float m_interiorMaxHearRange = 8f;
+
+ private const float m_despawnDistance = 80f;
+
+ private const float m_regenAllHPTime = 3600f;
+
+ public EffectList m_alertedEffects = new EffectList();
+
+ public EffectList m_idleSound = new EffectList();
+
+ public float m_idleSoundInterval = 5f;
+
+ public float m_idleSoundChance = 0.5f;
+
+ public Pathfinding.AgentType m_pathAgentType = Pathfinding.AgentType.Humanoid;
+
+ public float m_moveMinAngle = 10f;
+
+ public bool m_smoothMovement = true;
+
+ public bool m_serpentMovement;
+
+ public float m_serpentTurnRadius = 20f;
+
+ public float m_jumpInterval;
+
+ [Header("Random circle")]
+ public float m_randomCircleInterval = 2f;
+
+ [Header("Random movement")]
+ public float m_randomMoveInterval = 5f;
+
+ public float m_randomMoveRange = 4f;
+
+ [Header("Fly behaviour")]
+ public bool m_randomFly;
+
+ public float m_chanceToTakeoff = 1f;
+
+ public float m_chanceToLand = 1f;
+
+ public float m_groundDuration = 10f;
+
+ public float m_airDuration = 10f;
+
+ public float m_maxLandAltitude = 5f;
+
+ public float m_flyAltitudeMin = 3f;
+
+ public float m_flyAltitudeMax = 10f;
+
+ public float m_takeoffTime = 5f;
+
+ [Header("Other")]
+ public bool m_avoidFire;
+
+ public bool m_afraidOfFire;
+
+ public bool m_avoidWater = true;
+
+ public string m_spawnMessage = "";
+
+ public string m_deathMessage = "";
+
+ private bool m_patrol;
+
+ private Vector3 m_patrolPoint = Vector3.zero;
+
+ private float m_patrolPointUpdateTime;
+
+ protected ZNetView m_nview;
+
+ protected Character m_character;
+
+ protected ZSyncAnimation m_animator;
+
+ protected Rigidbody m_body;
+
+ private float m_updateTimer;
+
+ private int m_solidRayMask;
+
+ private int m_viewBlockMask;
+
+ private int m_monsterTargetRayMask;
+
+ private Vector3 m_randomMoveTarget = Vector3.zero;
+
+ private float m_randomMoveUpdateTimer;
+
+ private float m_jumpTimer;
+
+ private float m_randomFlyTimer;
+
+ private float m_regenTimer;
+
+ protected bool m_alerted;
+
+ protected bool m_huntPlayer;
+
+ protected Vector3 m_spawnPoint = Vector3.zero;
+
+ private const float m_getOfOfCornerMaxAngle = 20f;
+
+ private float m_getOutOfCornerTimer;
+
+ private float m_getOutOfCornerAngle;
+
+ private Vector3 m_lastPosition = Vector3.zero;
+
+ private float m_stuckTimer;
+
+ protected float m_timeSinceHurt = 99999f;
+
+ private Vector3 m_havePathTarget = new Vector3(-999999f, -999999f, -999999f);
+
+ private Vector3 m_havePathFrom = new Vector3(-999999f, -999999f, -999999f);
+
+ private float m_lastHavePathTime;
+
+ private bool m_lastHavePathResult;
+
+ private Vector3 m_lastFindPathTarget = new Vector3(-999999f, -999999f, -999999f);
+
+ private float m_lastFindPathTime;
+
+ private bool m_lastFindPathResult;
+
+ private List<Vector3> m_path = new List<Vector3>();
+
+ private static RaycastHit[] m_tempRaycastHits = new RaycastHit[128];
+
+ private static List<BaseAI> m_instances = new List<BaseAI>();
+
+ private static int worldTimeHash = "lastWorldTime".GetStableHashCode();
+
+ private static int spawnTimeHash = "spawntime".GetStableHashCode();
+
+ protected virtual void Awake()
+ {
+ m_instances.Add(this);
+ m_nview = GetComponent<ZNetView>();
+ m_character = GetComponent<Character>();
+ m_animator = GetComponent<ZSyncAnimation>();
+ m_body = GetComponent<Rigidbody>();
+ m_solidRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain", "vehicle");
+ m_viewBlockMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain", "viewblock", "vehicle");
+ m_monsterTargetRayMask = LayerMask.GetMask("piece", "piece_nonsolid", "Default", "static_solid", "Default_small", "vehicle");
+ Character character = m_character;
+ character.m_onDamaged = (Action<float, Character>)Delegate.Combine(character.m_onDamaged, new Action<float, Character>(OnDamaged));
+ Character character2 = m_character;
+ character2.m_onDeath = (Action)Delegate.Combine(character2.m_onDeath, new Action(OnDeath));
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong(spawnTimeHash, 0L) == 0L)
+ {
+ m_nview.GetZDO().Set(spawnTimeHash, ZNet.instance.GetTime().Ticks);
+ if (!string.IsNullOrEmpty(m_spawnMessage))
+ {
+ MessageHud.instance.MessageAll(MessageHud.MessageType.Center, m_spawnMessage);
+ }
+ }
+ m_randomMoveUpdateTimer = UnityEngine.Random.Range(0f, m_randomMoveInterval);
+ m_nview.Register("Alert", RPC_Alert);
+ m_huntPlayer = m_nview.GetZDO().GetBool("huntplayer", m_huntPlayer);
+ m_spawnPoint = m_nview.GetZDO().GetVec3("spawnpoint", base.transform.position);
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("spawnpoint", m_spawnPoint);
+ }
+ InvokeRepeating("DoIdleSound", m_idleSoundInterval, m_idleSoundInterval);
+ }
+
+ private void OnDestroy()
+ {
+ m_instances.Remove(this);
+ }
+
+ public void SetPatrolPoint()
+ {
+ SetPatrolPoint(base.transform.position);
+ }
+
+ public void SetPatrolPoint(Vector3 point)
+ {
+ m_patrol = true;
+ m_patrolPoint = point;
+ m_nview.GetZDO().Set("patrolPoint", point);
+ m_nview.GetZDO().Set("patrol", value: true);
+ }
+
+ public void ResetPatrolPoint()
+ {
+ m_patrol = false;
+ m_nview.GetZDO().Set("patrol", value: false);
+ }
+
+ public bool GetPatrolPoint(out Vector3 point)
+ {
+ if (Time.time - m_patrolPointUpdateTime > 1f)
+ {
+ m_patrolPointUpdateTime = Time.time;
+ m_patrol = m_nview.GetZDO().GetBool("patrol");
+ if (m_patrol)
+ {
+ m_patrolPoint = m_nview.GetZDO().GetVec3("patrolPoint", m_patrolPoint);
+ }
+ }
+ point = m_patrolPoint;
+ return m_patrol;
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ m_updateTimer += Time.fixedDeltaTime;
+ if (m_updateTimer >= 0.05f)
+ {
+ UpdateAI(0.05f);
+ m_updateTimer -= 0.05f;
+ }
+ }
+ }
+
+ protected virtual void UpdateAI(float dt)
+ {
+ if (m_nview.IsOwner())
+ {
+ UpdateTakeoffLanding(dt);
+ if (m_jumpInterval > 0f)
+ {
+ m_jumpTimer += dt;
+ }
+ if (m_randomMoveUpdateTimer > 0f)
+ {
+ m_randomMoveUpdateTimer -= dt;
+ }
+ UpdateRegeneration(dt);
+ m_timeSinceHurt += dt;
+ }
+ else
+ {
+ m_alerted = m_nview.GetZDO().GetBool("alert");
+ }
+ }
+
+ private void UpdateRegeneration(float dt)
+ {
+ m_regenTimer += dt;
+ if (m_regenTimer > 1f)
+ {
+ m_regenTimer = 0f;
+ float num = m_character.GetMaxHealth() / 3600f;
+ float worldTimeDelta = GetWorldTimeDelta();
+ m_character.Heal(num * worldTimeDelta, showText: false);
+ }
+ }
+
+ public bool IsTakingOff()
+ {
+ if (m_randomFly && m_character.IsFlying() && m_randomFlyTimer < m_takeoffTime)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public void UpdateTakeoffLanding(float dt)
+ {
+ if (!m_randomFly)
+ {
+ return;
+ }
+ m_randomFlyTimer += dt;
+ if (m_character.InAttack() || m_character.IsStaggering())
+ {
+ return;
+ }
+ if (m_character.IsFlying())
+ {
+ if (m_randomFlyTimer > m_airDuration && GetAltitude() < m_maxLandAltitude)
+ {
+ m_randomFlyTimer = 0f;
+ if (UnityEngine.Random.value <= m_chanceToLand)
+ {
+ m_character.m_flying = false;
+ m_animator.SetTrigger("fly_land");
+ }
+ }
+ }
+ else if (m_randomFlyTimer > m_groundDuration)
+ {
+ m_randomFlyTimer = 0f;
+ if (UnityEngine.Random.value <= m_chanceToTakeoff)
+ {
+ m_character.m_flying = true;
+ m_character.m_jumpEffects.Create(m_character.transform.position, Quaternion.identity);
+ m_animator.SetTrigger("fly_takeoff");
+ }
+ }
+ }
+
+ private float GetWorldTimeDelta()
+ {
+ DateTime time = ZNet.instance.GetTime();
+ long @long = m_nview.GetZDO().GetLong(worldTimeHash, 0L);
+ if (@long == 0L)
+ {
+ m_nview.GetZDO().Set(worldTimeHash, time.Ticks);
+ return 0f;
+ }
+ DateTime dateTime = new DateTime(@long);
+ TimeSpan timeSpan = time - dateTime;
+ m_nview.GetZDO().Set(worldTimeHash, time.Ticks);
+ return (float)timeSpan.TotalSeconds;
+ }
+
+ public TimeSpan GetTimeSinceSpawned()
+ {
+ long num = m_nview.GetZDO().GetLong("spawntime", 0L);
+ if (num == 0L)
+ {
+ num = ZNet.instance.GetTime().Ticks;
+ m_nview.GetZDO().Set("spawntime", num);
+ }
+ DateTime dateTime = new DateTime(num);
+ return ZNet.instance.GetTime() - dateTime;
+ }
+
+ private void DoIdleSound()
+ {
+ if (!IsSleeping() && !(UnityEngine.Random.value > m_idleSoundChance))
+ {
+ m_idleSound.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+
+ protected void Follow(GameObject go, float dt)
+ {
+ float num = Vector3.Distance(go.transform.position, base.transform.position);
+ bool run = num > 10f;
+ if (num < 3f)
+ {
+ StopMoving();
+ }
+ else
+ {
+ MoveTo(dt, go.transform.position, 0f, run);
+ }
+ }
+
+ protected void MoveToWater(float dt, float maxRange)
+ {
+ float num = (m_haveWaterPosition ? 2f : 0.5f);
+ if (Time.time - m_lastMoveToWaterUpdate > num)
+ {
+ m_lastMoveToWaterUpdate = Time.time;
+ Vector3 moveToWaterPosition = base.transform.position;
+ for (int i = 0; i < 10; i++)
+ {
+ Vector3 vector = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward * UnityEngine.Random.Range(4f, maxRange);
+ Vector3 vector2 = base.transform.position + vector;
+ vector2.y = ZoneSystem.instance.GetSolidHeight(vector2);
+ if (vector2.y < moveToWaterPosition.y)
+ {
+ moveToWaterPosition = vector2;
+ }
+ }
+ if (moveToWaterPosition.y < ZoneSystem.instance.m_waterLevel)
+ {
+ m_moveToWaterPosition = moveToWaterPosition;
+ m_haveWaterPosition = true;
+ }
+ else
+ {
+ m_haveWaterPosition = false;
+ }
+ }
+ if (m_haveWaterPosition)
+ {
+ MoveTowards(m_moveToWaterPosition - base.transform.position, run: true);
+ }
+ }
+
+ protected void MoveAwayAndDespawn(float dt, bool run)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 40f);
+ if (closestPlayer != null)
+ {
+ Vector3 normalized = (closestPlayer.transform.position - base.transform.position).normalized;
+ MoveTo(dt, base.transform.position - normalized * 5f, 0f, run);
+ }
+ else
+ {
+ m_nview.Destroy();
+ }
+ }
+
+ protected void IdleMovement(float dt)
+ {
+ Vector3 centerPoint = (m_character.IsTamed() ? base.transform.position : m_spawnPoint);
+ if (GetPatrolPoint(out var point))
+ {
+ centerPoint = point;
+ }
+ RandomMovement(dt, centerPoint);
+ }
+
+ protected void RandomMovement(float dt, Vector3 centerPoint)
+ {
+ if (m_randomMoveUpdateTimer <= 0f)
+ {
+ if (Utils.DistanceXZ(centerPoint, base.transform.position) > m_randomMoveRange * 2f)
+ {
+ Vector3 vector = centerPoint - base.transform.position;
+ vector.y = 0f;
+ vector.Normalize();
+ vector = Quaternion.Euler(0f, UnityEngine.Random.Range(-30, 30), 0f) * vector;
+ m_randomMoveTarget = base.transform.position + vector * m_randomMoveRange * 2f;
+ }
+ else
+ {
+ Vector3 vector2 = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * base.transform.forward * UnityEngine.Random.Range(m_randomMoveRange * 0.7f, m_randomMoveRange);
+ m_randomMoveTarget = centerPoint + vector2;
+ }
+ if (m_character.IsFlying() && ZoneSystem.instance.GetSolidHeight(m_randomMoveTarget, out var height))
+ {
+ if (height < ZoneSystem.instance.m_waterLevel)
+ {
+ height = ZoneSystem.instance.m_waterLevel;
+ }
+ m_randomMoveTarget.y = height + UnityEngine.Random.Range(m_flyAltitudeMin, m_flyAltitudeMax);
+ }
+ if (!IsValidRandomMovePoint(m_randomMoveTarget))
+ {
+ return;
+ }
+ m_randomMoveUpdateTimer = UnityEngine.Random.Range(m_randomMoveInterval, m_randomMoveInterval + m_randomMoveInterval / 2f);
+ if (m_avoidWater && m_character.IsSwiming())
+ {
+ m_randomMoveUpdateTimer /= 4f;
+ }
+ }
+ bool flag = IsAlerted() || Utils.DistanceXZ(base.transform.position, centerPoint) > m_randomMoveRange * 2f;
+ if (MoveTo(dt, m_randomMoveTarget, 0f, flag) && flag)
+ {
+ m_randomMoveUpdateTimer = 0f;
+ }
+ }
+
+ protected void Flee(float dt, Vector3 from)
+ {
+ float time = Time.time;
+ if (time - m_fleeTargetUpdateTime > 2f)
+ {
+ m_fleeTargetUpdateTime = time;
+ Vector3 vector = -(from - base.transform.position);
+ vector.y = 0f;
+ vector.Normalize();
+ bool flag = false;
+ for (int i = 0; i < 4; i++)
+ {
+ m_fleeTarget = base.transform.position + Quaternion.Euler(0f, UnityEngine.Random.Range(-45f, 45f), 0f) * vector * 25f;
+ if (HavePath(m_fleeTarget) && (!m_avoidWater || m_character.IsSwiming() || !(ZoneSystem.instance.GetSolidHeight(m_fleeTarget) < ZoneSystem.instance.m_waterLevel)))
+ {
+ flag = true;
+ break;
+ }
+ }
+ if (!flag)
+ {
+ m_fleeTarget = base.transform.position + Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward * 25f;
+ }
+ }
+ MoveTo(dt, m_fleeTarget, 0f, IsAlerted());
+ }
+
+ protected bool AvoidFire(float dt, Character moveToTarget, bool superAfraid)
+ {
+ if (superAfraid)
+ {
+ EffectArea effectArea = EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.Fire, 3f);
+ if ((bool)effectArea)
+ {
+ m_nearFireTime = Time.time;
+ m_nearFireArea = effectArea;
+ }
+ if (Time.time - m_nearFireTime < 6f && (bool)m_nearFireArea)
+ {
+ SetAlerted(alert: true);
+ Flee(dt, m_nearFireArea.transform.position);
+ return true;
+ }
+ }
+ else
+ {
+ EffectArea effectArea2 = EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.Fire, 3f);
+ if ((bool)effectArea2)
+ {
+ if (moveToTarget != null && (bool)EffectArea.IsPointInsideArea(moveToTarget.transform.position, EffectArea.Type.Fire))
+ {
+ RandomMovementArroundPoint(dt, effectArea2.transform.position, effectArea2.GetRadius() + 3f + 1f, IsAlerted());
+ return true;
+ }
+ RandomMovementArroundPoint(dt, effectArea2.transform.position, (effectArea2.GetRadius() + 3f) * 1.5f, IsAlerted());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected void RandomMovementArroundPoint(float dt, Vector3 point, float distance, bool run)
+ {
+ float time = Time.time;
+ if (time - aroundPointUpdateTime > m_randomCircleInterval)
+ {
+ aroundPointUpdateTime = time;
+ Vector3 vector = base.transform.position - point;
+ vector.y = 0f;
+ vector.Normalize();
+ float num = ((!(Vector3.Distance(base.transform.position, point) < distance / 2f)) ? ((float)(((double)UnityEngine.Random.value > 0.5) ? 40 : (-40))) : ((float)(((double)UnityEngine.Random.value > 0.5) ? 90 : (-90))));
+ Vector3 vector2 = Quaternion.Euler(0f, num, 0f) * vector;
+ arroundPointTarget = point + vector2 * distance;
+ if (Vector3.Dot(base.transform.forward, arroundPointTarget - base.transform.position) < 0f)
+ {
+ vector2 = Quaternion.Euler(0f, 0f - num, 0f) * vector;
+ arroundPointTarget = point + vector2 * distance;
+ if (m_serpentMovement && Vector3.Distance(point, base.transform.position) > distance / 2f && Vector3.Dot(base.transform.forward, arroundPointTarget - base.transform.position) < 0f)
+ {
+ arroundPointTarget = point - vector2 * distance;
+ }
+ }
+ if (m_character.IsFlying())
+ {
+ arroundPointTarget.y += UnityEngine.Random.Range(m_flyAltitudeMin, m_flyAltitudeMax);
+ }
+ }
+ if (MoveTo(dt, arroundPointTarget, 0f, run))
+ {
+ if (run)
+ {
+ aroundPointUpdateTime = 0f;
+ }
+ if (!m_serpentMovement && !run)
+ {
+ LookAt(point);
+ }
+ }
+ }
+
+ private bool GetSolidHeight(Vector3 p, out float height, float maxYDistance)
+ {
+ if (Physics.Raycast(p + Vector3.up * maxYDistance, Vector3.down, out var hitInfo, maxYDistance * 2f, m_solidRayMask))
+ {
+ height = hitInfo.point.y;
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ protected bool IsValidRandomMovePoint(Vector3 point)
+ {
+ if (m_character.IsFlying())
+ {
+ return true;
+ }
+ if (m_avoidWater && GetSolidHeight(point, out var height, 50f))
+ {
+ if (m_character.IsSwiming())
+ {
+ if (GetSolidHeight(base.transform.position, out var height2, 50f) && height < height2)
+ {
+ return false;
+ }
+ }
+ else if (height < ZoneSystem.instance.m_waterLevel)
+ {
+ return false;
+ }
+ }
+ if ((m_afraidOfFire || m_avoidFire) && (bool)EffectArea.IsPointInsideArea(point, EffectArea.Type.Fire))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ protected virtual void OnDamaged(float damage, Character attacker)
+ {
+ m_timeSinceHurt = 0f;
+ }
+
+ protected virtual void OnDeath()
+ {
+ if (!string.IsNullOrEmpty(m_deathMessage))
+ {
+ MessageHud.instance.MessageAll(MessageHud.MessageType.Center, m_deathMessage);
+ }
+ }
+
+ public bool CanSenseTarget(Character target)
+ {
+ if (CanHearTarget(target))
+ {
+ return true;
+ }
+ if (CanSeeTarget(target))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool CanHearTarget(Character target)
+ {
+ if (target.IsPlayer())
+ {
+ Player player = target as Player;
+ if (player.InDebugFlyMode() || player.InGhostMode())
+ {
+ return false;
+ }
+ }
+ float num = Vector3.Distance(target.transform.position, base.transform.position);
+ float num2 = m_hearRange;
+ if (m_character.InInterior())
+ {
+ num2 = Mathf.Min(8f, num2);
+ }
+ if (num > num2)
+ {
+ return false;
+ }
+ if (num < target.GetNoiseRange())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool CanSeeTarget(Character target)
+ {
+ if (target.IsPlayer())
+ {
+ Player player = target as Player;
+ if (player.InDebugFlyMode() || player.InGhostMode())
+ {
+ return false;
+ }
+ }
+ float num = Vector3.Distance(target.transform.position, base.transform.position);
+ if (num > m_viewRange)
+ {
+ return false;
+ }
+ float factor = 1f - num / m_viewRange;
+ float stealthFactor = target.GetStealthFactor();
+ float num2 = m_viewRange * stealthFactor;
+ if (num > num2)
+ {
+ target.OnStealthSuccess(m_character, factor);
+ return false;
+ }
+ if (!IsAlerted() && Vector3.Angle(target.transform.position - m_character.transform.position, base.transform.forward) > m_viewAngle)
+ {
+ target.OnStealthSuccess(m_character, factor);
+ return false;
+ }
+ Vector3 vector = (target.IsCrouching() ? target.GetCenterPoint() : target.m_eye.position) - m_character.m_eye.position;
+ if (Physics.Raycast(m_character.m_eye.position, vector.normalized, vector.magnitude, m_viewBlockMask))
+ {
+ target.OnStealthSuccess(m_character, factor);
+ return false;
+ }
+ return true;
+ }
+
+ public bool CanSeeTarget(StaticTarget target)
+ {
+ Vector3 center = target.GetCenter();
+ if (Vector3.Distance(center, base.transform.position) > m_viewRange)
+ {
+ return false;
+ }
+ Vector3 rhs = center - m_character.m_eye.position;
+ if (!IsAlerted() && Vector3.Dot(base.transform.forward, rhs) < 0f)
+ {
+ return false;
+ }
+ List<Collider> allColliders = target.GetAllColliders();
+ int num = Physics.RaycastNonAlloc(m_character.m_eye.position, rhs.normalized, m_tempRaycastHits, rhs.magnitude, m_viewBlockMask);
+ for (int i = 0; i < num; i++)
+ {
+ RaycastHit raycastHit = m_tempRaycastHits[i];
+ if (!allColliders.Contains(raycastHit.collider))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected void MoveTowardsSwoop(Vector3 dir, bool run, float distance)
+ {
+ dir = dir.normalized;
+ float num = Mathf.Clamp01(Vector3.Dot(dir, m_character.transform.forward));
+ num *= num;
+ float num2 = Mathf.Clamp01(distance / m_serpentTurnRadius);
+ float num3 = 1f - (1f - num2) * (1f - num);
+ num3 = num3 * 0.9f + 0.1f;
+ Vector3 moveDir = base.transform.forward * num3;
+ LookTowards(dir);
+ m_character.SetMoveDir(moveDir);
+ m_character.SetRun(run);
+ }
+
+ protected void MoveTowards(Vector3 dir, bool run)
+ {
+ dir = dir.normalized;
+ LookTowards(dir);
+ if (m_smoothMovement)
+ {
+ float num = Vector3.Angle(dir, base.transform.forward);
+ float num2 = 1f - Mathf.Clamp01(num / m_moveMinAngle);
+ Vector3 moveDir = base.transform.forward * num2;
+ moveDir.y = dir.y;
+ m_character.SetMoveDir(moveDir);
+ m_character.SetRun(run);
+ if (m_jumpInterval > 0f && m_jumpTimer >= m_jumpInterval)
+ {
+ m_jumpTimer = 0f;
+ m_character.Jump();
+ }
+ }
+ else if (IsLookingTowards(dir, m_moveMinAngle))
+ {
+ m_character.SetMoveDir(dir);
+ m_character.SetRun(run);
+ if (m_jumpInterval > 0f && m_jumpTimer >= m_jumpInterval)
+ {
+ m_jumpTimer = 0f;
+ m_character.Jump();
+ }
+ }
+ else
+ {
+ StopMoving();
+ }
+ }
+
+ protected void LookAt(Vector3 point)
+ {
+ Vector3 vector = point - m_character.m_eye.position;
+ if (!(Utils.LengthXZ(vector) < 0.01f))
+ {
+ vector.Normalize();
+ LookTowards(vector);
+ }
+ }
+
+ protected void LookTowards(Vector3 dir)
+ {
+ m_character.SetLookDir(dir);
+ }
+
+ protected bool IsLookingAt(Vector3 point, float minAngle)
+ {
+ return IsLookingTowards((point - base.transform.position).normalized, minAngle);
+ }
+
+ protected bool IsLookingTowards(Vector3 dir, float minAngle)
+ {
+ dir.y = 0f;
+ Vector3 forward = base.transform.forward;
+ forward.y = 0f;
+ return Vector3.Angle(dir, forward) < minAngle;
+ }
+
+ protected void StopMoving()
+ {
+ m_character.SetMoveDir(Vector3.zero);
+ }
+
+ // жǷеĿ㣨Vector3·
+ protected bool HavePath(Vector3 target)
+ {
+ if (m_character.IsFlying())
+ {
+ return true;
+ }
+ float time = Time.time;
+ float num = time - m_lastHavePathTime;
+ Vector3 position = base.transform.position;
+ if (Vector3.Distance(position, m_havePathFrom) > 2f || Vector3.Distance(target, m_havePathTarget) > 1f || num > 5f)
+ {
+ m_havePathFrom = position;
+ m_havePathTarget = target;
+ m_lastHavePathTime = time;
+ m_lastHavePathResult = Pathfinding.instance.HavePath(position, target, m_pathAgentType);
+ }
+ return m_lastHavePathResult;
+ }
+
+ // ѰҵĿ㣨Vector3·List<Vector3>)
+ protected bool FindPath(Vector3 target)
+ {
+ float time = Time.time;
+ float num = time - m_lastFindPathTime;
+ if (num < 1f)
+ {
+ return m_lastFindPathResult;
+ }
+ if (Vector3.Distance(target, m_lastFindPathTarget) < 1f && num < 5f)
+ {
+ return m_lastFindPathResult;
+ }
+ m_lastFindPathTarget = target;
+ m_lastFindPathTime = time;
+ m_lastFindPathResult = Pathfinding.instance.GetPath(base.transform.position, target, m_path, m_pathAgentType);
+ return m_lastFindPathResult;
+ }
+
+ protected bool FoundPath()
+ {
+ return m_lastFindPathResult;
+ }
+
+ protected bool MoveTo(float dt, Vector3 point, float dist, bool run)
+ {
+ if (m_character.m_flying)
+ {
+ dist = Mathf.Max(dist, 1f);
+ if (ZoneSystem.instance.GetSolidHeight(point, out var height))
+ {
+ point.y = Mathf.Max(point.y, height + m_flyAltitudeMin);
+ }
+ return MoveAndAvoid(dt, point, dist, run);
+ }
+ float num = (run ? 1f : 0.5f);
+ if (m_serpentMovement)
+ {
+ num = 3f;
+ }
+ if (Utils.DistanceXZ(point, base.transform.position) < Mathf.Max(dist, num))
+ {
+ StopMoving();
+ return true;
+ }
+ if (!FindPath(point))
+ {
+ StopMoving();
+ return true;
+ }
+ if (m_path.Count == 0)
+ {
+ StopMoving();
+ return true;
+ }
+ Vector3 vector = m_path[0];
+ if (Utils.DistanceXZ(vector, base.transform.position) < num)
+ {
+ m_path.RemoveAt(0);
+ if (m_path.Count == 0)
+ {
+ StopMoving();
+ return true;
+ }
+ }
+ else if (m_serpentMovement)
+ {
+ float distance = Vector3.Distance(vector, base.transform.position);
+ Vector3 normalized = (vector - base.transform.position).normalized;
+ MoveTowardsSwoop(normalized, run, distance);
+ }
+ else
+ {
+ Vector3 normalized2 = (vector - base.transform.position).normalized;
+ MoveTowards(normalized2, run);
+ }
+ return false;
+ }
+
+ protected bool MoveAndAvoid(float dt, Vector3 point, float dist, bool run)
+ {
+ Vector3 vector = point - base.transform.position;
+ if (m_character.IsFlying())
+ {
+ if (vector.magnitude < dist)
+ {
+ StopMoving();
+ return true;
+ }
+ }
+ else
+ {
+ vector.y = 0f;
+ if (vector.magnitude < dist)
+ {
+ StopMoving();
+ return true;
+ }
+ }
+ vector.Normalize();
+ float radius = m_character.GetRadius();
+ float num = radius + 1f;
+ if (!m_character.InAttack())
+ {
+ m_getOutOfCornerTimer -= dt;
+ if (m_getOutOfCornerTimer > 0f)
+ {
+ Vector3 dir = Quaternion.Euler(0f, m_getOutOfCornerAngle, 0f) * -vector;
+ MoveTowards(dir, run);
+ return false;
+ }
+ m_stuckTimer += Time.fixedDeltaTime;
+ if (m_stuckTimer > 1.5f)
+ {
+ if (Vector3.Distance(base.transform.position, m_lastPosition) < 0.2f)
+ {
+ m_getOutOfCornerTimer = 4f;
+ m_getOutOfCornerAngle = UnityEngine.Random.Range(-20f, 20f);
+ m_stuckTimer = 0f;
+ return false;
+ }
+ m_stuckTimer = 0f;
+ m_lastPosition = base.transform.position;
+ }
+ }
+ if (CanMove(vector, radius, num))
+ {
+ MoveTowards(vector, run);
+ }
+ else
+ {
+ Vector3 forward = base.transform.forward;
+ if (m_character.IsFlying())
+ {
+ forward.y = 0.2f;
+ forward.Normalize();
+ }
+ Vector3 vector2 = base.transform.right * radius * 0.75f;
+ float num2 = num * 1.5f;
+ Vector3 centerPoint = m_character.GetCenterPoint();
+ float num3 = Raycast(centerPoint - vector2, forward, num2, 0.1f);
+ float num4 = Raycast(centerPoint + vector2, forward, num2, 0.1f);
+ if (num3 >= num2 && num4 >= num2)
+ {
+ MoveTowards(forward, run);
+ }
+ else
+ {
+ Vector3 dir2 = Quaternion.Euler(0f, -20f, 0f) * forward;
+ Vector3 dir3 = Quaternion.Euler(0f, 20f, 0f) * forward;
+ if (num3 > num4)
+ {
+ MoveTowards(dir2, run);
+ }
+ else
+ {
+ MoveTowards(dir3, run);
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool CanMove(Vector3 dir, float checkRadius, float distance)
+ {
+ Vector3 centerPoint = m_character.GetCenterPoint();
+ Vector3 right = base.transform.right;
+ if (Raycast(centerPoint, dir, distance, 0.1f) < distance)
+ {
+ return false;
+ }
+ if (Raycast(centerPoint - right * (checkRadius - 0.1f), dir, distance, 0.1f) < distance)
+ {
+ return false;
+ }
+ if (Raycast(centerPoint + right * (checkRadius - 0.1f), dir, distance, 0.1f) < distance)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public float Raycast(Vector3 p, Vector3 dir, float distance, float radius)
+ {
+ if (radius == 0f)
+ {
+ if (Physics.Raycast(p, dir, out var hitInfo, distance, m_solidRayMask))
+ {
+ return hitInfo.distance;
+ }
+ return distance;
+ }
+ if (Physics.SphereCast(p, radius, dir, out var hitInfo2, distance, m_solidRayMask))
+ {
+ return hitInfo2.distance;
+ }
+ return distance;
+ }
+
+ public bool IsEnemey(Character other)
+ {
+ return IsEnemy(m_character, other);
+ }
+
+ public static bool IsEnemy(Character a, Character b)
+ {
+ if (a == b)
+ {
+ return false;
+ }
+ Character.Faction faction = a.GetFaction();
+ Character.Faction faction2 = b.GetFaction();
+ if (faction == faction2)
+ {
+ return false;
+ }
+ bool flag = a.IsTamed();
+ bool flag2 = b.IsTamed();
+ if (flag || flag2)
+ {
+ if ((flag && flag2) || (flag && faction2 == Character.Faction.Players) || (flag2 && faction == Character.Faction.Players))
+ {
+ return false;
+ }
+ return true;
+ }
+ switch (faction)
+ {
+ case Character.Faction.AnimalsVeg:
+ return true;
+ case Character.Faction.Players:
+ return true;
+ case Character.Faction.ForestMonsters:
+ if (faction2 != Character.Faction.AnimalsVeg)
+ {
+ return faction2 != Character.Faction.Boss;
+ }
+ return false;
+ case Character.Faction.Undead:
+ if (faction2 != Character.Faction.Demon)
+ {
+ return faction2 != Character.Faction.Boss;
+ }
+ return false;
+ case Character.Faction.Demon:
+ if (faction2 != Character.Faction.Undead)
+ {
+ return faction2 != Character.Faction.Boss;
+ }
+ return false;
+ case Character.Faction.MountainMonsters:
+ return faction2 != Character.Faction.Boss;
+ case Character.Faction.SeaMonsters:
+ return faction2 != Character.Faction.Boss;
+ case Character.Faction.PlainsMonsters:
+ return faction2 != Character.Faction.Boss;
+ case Character.Faction.Boss:
+ return faction2 == Character.Faction.Players;
+ default:
+ return false;
+ }
+ }
+
+ protected StaticTarget FindRandomStaticTarget(float maxDistance, bool priorityTargetsOnly)
+ {
+ float radius = m_character.GetRadius();
+ Collider[] array = Physics.OverlapSphere(base.transform.position, radius + maxDistance, m_monsterTargetRayMask);
+ if (array.Length == 0)
+ {
+ return null;
+ }
+ List<StaticTarget> list = new List<StaticTarget>();
+ Collider[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ StaticTarget componentInParent = array2[i].GetComponentInParent<StaticTarget>();
+ if (componentInParent == null || !componentInParent.IsValidMonsterTarget())
+ {
+ continue;
+ }
+ if (priorityTargetsOnly)
+ {
+ if (!componentInParent.m_primaryTarget)
+ {
+ continue;
+ }
+ }
+ else if (!componentInParent.m_randomTarget)
+ {
+ continue;
+ }
+ if (CanSeeTarget(componentInParent))
+ {
+ list.Add(componentInParent);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ protected StaticTarget FindClosestStaticPriorityTarget(float maxDistance)
+ {
+ float num = Mathf.Min(maxDistance, m_viewRange);
+ Collider[] array = Physics.OverlapSphere(base.transform.position, num, m_monsterTargetRayMask);
+ if (array.Length == 0)
+ {
+ return null;
+ }
+ StaticTarget result = null;
+ float num2 = num;
+ Collider[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ StaticTarget componentInParent = array2[i].GetComponentInParent<StaticTarget>();
+ if (!(componentInParent == null) && componentInParent.IsValidMonsterTarget() && componentInParent.m_primaryTarget)
+ {
+ float num3 = Vector3.Distance(base.transform.position, componentInParent.GetCenter());
+ if (num3 < num2 && CanSeeTarget(componentInParent))
+ {
+ result = componentInParent;
+ num2 = num3;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected void HaveFriendsInRange(float range, out Character hurtFriend, out Character friend)
+ {
+ List<Character> allCharacters = Character.GetAllCharacters();
+ friend = HaveFriendInRange(allCharacters, range);
+ hurtFriend = HaveHurtFriendInRange(allCharacters, range);
+ }
+
+ private Character HaveFriendInRange(List<Character> characters, float range)
+ {
+ foreach (Character character in characters)
+ {
+ if (!(character == m_character) && !IsEnemy(m_character, character) && !(Vector3.Distance(character.transform.position, base.transform.position) > range))
+ {
+ return character;
+ }
+ }
+ return null;
+ }
+
+ protected Character HaveFriendInRange(float range)
+ {
+ List<Character> allCharacters = Character.GetAllCharacters();
+ return HaveFriendInRange(allCharacters, range);
+ }
+
+ private Character HaveHurtFriendInRange(List<Character> characters, float range)
+ {
+ foreach (Character character in characters)
+ {
+ if (!IsEnemy(m_character, character) && !(Vector3.Distance(character.transform.position, base.transform.position) > range) && character.GetHealth() < character.GetMaxHealth())
+ {
+ return character;
+ }
+ }
+ return null;
+ }
+
+ protected Character HaveHurtFriendInRange(float range)
+ {
+ List<Character> allCharacters = Character.GetAllCharacters();
+ return HaveHurtFriendInRange(allCharacters, range);
+ }
+
+ protected Character FindEnemy()
+ {
+ List<Character> allCharacters = Character.GetAllCharacters();
+ Character character = null;
+ float num = 99999f;
+ foreach (Character item in allCharacters)
+ {
+ if (!IsEnemy(m_character, item) || item.IsDead())
+ {
+ continue;
+ }
+ BaseAI baseAI = item.GetBaseAI();
+ if ((!(baseAI != null) || !baseAI.IsSleeping()) && CanSenseTarget(item))
+ {
+ float num2 = Vector3.Distance(item.transform.position, base.transform.position);
+ if (num2 < num || character == null)
+ {
+ character = item;
+ num = num2;
+ }
+ }
+ }
+ if (character == null && HuntPlayer())
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 200f);
+ if ((bool)closestPlayer && (closestPlayer.InDebugFlyMode() || closestPlayer.InGhostMode()))
+ {
+ return null;
+ }
+ return closestPlayer;
+ }
+ return character;
+ }
+
+ public void SetHuntPlayer(bool hunt)
+ {
+ if (m_huntPlayer != hunt)
+ {
+ m_huntPlayer = hunt;
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("huntplayer", m_huntPlayer);
+ }
+ }
+ }
+
+ public virtual bool HuntPlayer()
+ {
+ return m_huntPlayer;
+ }
+
+ protected bool HaveAlertedCreatureInRange(float range)
+ {
+ foreach (BaseAI instance in m_instances)
+ {
+ if (Vector3.Distance(base.transform.position, instance.transform.position) < range && instance.IsAlerted())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void AlertAllInRange(Vector3 center, float range, Character attacker)
+ {
+ foreach (BaseAI instance in m_instances)
+ {
+ if ((!attacker || instance.IsEnemey(attacker)) && Vector3.Distance(instance.transform.position, center) < range)
+ {
+ instance.Alert();
+ }
+ }
+ }
+
+ public void Alert()
+ {
+ if (m_nview.IsValid() && !IsAlerted())
+ {
+ if (m_nview.IsOwner())
+ {
+ SetAlerted(alert: true);
+ }
+ else
+ {
+ m_nview.InvokeRPC("Alert");
+ }
+ }
+ }
+
+ private void RPC_Alert(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ SetAlerted(alert: true);
+ }
+ }
+
+ protected virtual void SetAlerted(bool alert)
+ {
+ if (m_alerted != alert)
+ {
+ m_alerted = alert;
+ m_animator.SetBool("alert", m_alerted);
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("alert", m_alerted);
+ }
+ if (m_alerted)
+ {
+ m_alertedEffects.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+ }
+
+ public static bool InStealthRange(Character me)
+ {
+ bool result = false;
+ foreach (BaseAI allInstance in GetAllInstances())
+ {
+ if (!IsEnemy(me, allInstance.m_character))
+ {
+ continue;
+ }
+ float num = Vector3.Distance(me.transform.position, allInstance.transform.position);
+ if (num < allInstance.m_viewRange || num < 10f)
+ {
+ if (allInstance.IsAlerted())
+ {
+ return false;
+ }
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public static Character FindClosestEnemy(Character me, Vector3 point, float maxDistance)
+ {
+ Character character = null;
+ float num = maxDistance;
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (IsEnemy(me, allCharacter))
+ {
+ float num2 = Vector3.Distance(allCharacter.transform.position, point);
+ if (character == null || num2 < num)
+ {
+ character = allCharacter;
+ num = num2;
+ }
+ }
+ }
+ return character;
+ }
+
+ public static Character FindRandomEnemy(Character me, Vector3 point, float maxDistance)
+ {
+ List<Character> list = new List<Character>();
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (IsEnemy(me, allCharacter) && Vector3.Distance(allCharacter.transform.position, point) < maxDistance)
+ {
+ list.Add(allCharacter);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ public bool IsAlerted()
+ {
+ return m_alerted;
+ }
+
+ protected float GetAltitude()
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(m_character.transform.position);
+ return m_character.transform.position.y - groundHeight;
+ }
+
+ public static List<BaseAI> GetAllInstances()
+ {
+ return m_instances;
+ }
+
+ protected virtual void OnDrawGizmosSelected()
+ {
+ if (m_lastFindPathResult)
+ {
+ Gizmos.color = Color.yellow;
+ for (int i = 0; i < m_path.Count - 1; i++)
+ {
+ Vector3 vector = m_path[i];
+ Gizmos.DrawLine(to: m_path[i + 1] + Vector3.up * 0.1f, from: vector + Vector3.up * 0.1f);
+ }
+ Gizmos.color = Color.cyan;
+ foreach (Vector3 item in m_path)
+ {
+ Gizmos.DrawSphere(item + Vector3.up * 0.1f, 0.1f);
+ }
+ Gizmos.color = Color.green;
+ Gizmos.DrawLine(base.transform.position, m_lastFindPathTarget);
+ Gizmos.DrawSphere(m_lastFindPathTarget, 0.2f);
+ }
+ else
+ {
+ Gizmos.color = Color.red;
+ Gizmos.DrawLine(base.transform.position, m_lastFindPathTarget);
+ Gizmos.DrawSphere(m_lastFindPathTarget, 0.2f);
+ }
+ }
+
+ public virtual bool IsSleeping()
+ {
+ return false;
+ }
+
+ public bool HasZDOOwner()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().HasOwner();
+ }
+
+ public static bool CanUseAttack(Character character, ItemDrop.ItemData item)
+ {
+ bool flag = character.IsFlying();
+ bool flag2 = character.IsSwiming();
+ if (item.m_shared.m_aiWhenFlying && flag)
+ {
+ return true;
+ }
+ if (item.m_shared.m_aiWhenWalking && !flag && !flag2)
+ {
+ return true;
+ }
+ if (item.m_shared.m_aiWhenSwiming && flag2)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public virtual Character GetTargetCreature()
+ {
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beacon.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beacon.cs
new file mode 100644
index 0000000..8dd7cba
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beacon.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Beacon : MonoBehaviour
+{
+ public float m_range = 20f;
+
+ private static List<Beacon> m_instances = new List<Beacon>();
+
+ private void Awake()
+ {
+ m_instances.Add(this);
+ }
+
+ private void OnDestroy()
+ {
+ m_instances.Remove(this);
+ }
+
+ public static Beacon FindClosestBeaconInRange(Vector3 point)
+ {
+ Beacon beacon = null;
+ float num = 999999f;
+ foreach (Beacon instance in m_instances)
+ {
+ float num2 = Vector3.Distance(point, instance.transform.position);
+ if (num2 < instance.m_range && (beacon == null || num2 < num))
+ {
+ beacon = instance;
+ num = num2;
+ }
+ }
+ return beacon;
+ }
+
+ public static void FindBeaconsInRange(Vector3 point, List<Beacon> becons)
+ {
+ foreach (Beacon instance in m_instances)
+ {
+ if (Vector3.Distance(point, instance.transform.position) < instance.m_range)
+ {
+ becons.Add(instance);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Bed.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Bed.cs
new file mode 100644
index 0000000..2af71df
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Bed.cs
@@ -0,0 +1,201 @@
+using UnityEngine;
+
+public class Bed : MonoBehaviour, Hoverable, Interactable
+{
+ public Transform m_spawnPoint;
+
+ public float m_monsterCheckRadius = 20f;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.Register<long, string>("SetOwner", RPC_SetOwner);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ string ownerName = GetOwnerName();
+ if (ownerName == "")
+ {
+ return Localization.instance.Localize("$piece_bed_unclaimed\n[<color=yellow><b>$KEY_Use</b></color>] $piece_bed_claim");
+ }
+ string text = ownerName + "'s $piece_bed";
+ if (IsMine())
+ {
+ if (IsCurrent())
+ {
+ return Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_bed_sleep");
+ }
+ return Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_bed_setspawn");
+ }
+ return Localization.instance.Localize(text);
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize("$piece_bed");
+ }
+
+ public bool Interact(Humanoid human, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ long owner = GetOwner();
+ Player human2 = human as Player;
+ if (owner == 0L)
+ {
+ ZLog.Log("Has no creator");
+ if (!CheckExposure(human2))
+ {
+ return false;
+ }
+ SetOwner(playerID, Game.instance.GetPlayerProfile().GetName());
+ Game.instance.GetPlayerProfile().SetCustomSpawnPoint(GetSpawnPoint());
+ human.Message(MessageHud.MessageType.Center, "$msg_spawnpointset");
+ }
+ else if (IsMine())
+ {
+ ZLog.Log("Is mine");
+ if (IsCurrent())
+ {
+ ZLog.Log("is current spawnpoint");
+ if (!EnvMan.instance.IsAfternoon() && !EnvMan.instance.IsNight())
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_cantsleep");
+ return false;
+ }
+ if (!CheckEnemies(human2))
+ {
+ return false;
+ }
+ if (!CheckExposure(human2))
+ {
+ return false;
+ }
+ if (!CheckFire(human2))
+ {
+ return false;
+ }
+ if (!CheckWet(human2))
+ {
+ return false;
+ }
+ human.AttachStart(m_spawnPoint, hideWeapons: true, isBed: true, "attach_bed", new Vector3(0f, 0.5f, 0f));
+ return false;
+ }
+ ZLog.Log("Not current spawn point");
+ if (!CheckExposure(human2))
+ {
+ return false;
+ }
+ Game.instance.GetPlayerProfile().SetCustomSpawnPoint(GetSpawnPoint());
+ human.Message(MessageHud.MessageType.Center, "$msg_spawnpointset");
+ }
+ return false;
+ }
+
+ private bool CheckWet(Player human)
+ {
+ if (human.GetSEMan().HaveStatusEffect("Wet"))
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_bedwet");
+ return false;
+ }
+ return true;
+ }
+
+ private bool CheckEnemies(Player human)
+ {
+ if (human.IsSensed())
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_bedenemiesnearby");
+ return false;
+ }
+ return true;
+ }
+
+ private bool CheckExposure(Player human)
+ {
+ Cover.GetCoverForPoint(GetSpawnPoint(), out var coverPercentage, out var underRoof);
+ if (!underRoof)
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_bedneedroof");
+ return false;
+ }
+ if (coverPercentage < 0.8f)
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_bedtooexposed");
+ return false;
+ }
+ ZLog.Log("exporeusre check " + coverPercentage + " " + underRoof.ToString());
+ return true;
+ }
+
+ private bool CheckFire(Player human)
+ {
+ if (!EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.Heat))
+ {
+ human.Message(MessageHud.MessageType.Center, "$msg_bednofire");
+ return false;
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public bool IsCurrent()
+ {
+ if (!IsMine())
+ {
+ return false;
+ }
+ return Vector3.Distance(GetSpawnPoint(), Game.instance.GetPlayerProfile().GetCustomSpawnPoint()) < 1f;
+ }
+
+ public Vector3 GetSpawnPoint()
+ {
+ return m_spawnPoint.position;
+ }
+
+ private bool IsMine()
+ {
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ long owner = GetOwner();
+ return playerID == owner;
+ }
+
+ private void SetOwner(long uid, string name)
+ {
+ m_nview.InvokeRPC("SetOwner", uid, name);
+ }
+
+ private void RPC_SetOwner(long sender, long uid, string name)
+ {
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("owner", uid);
+ m_nview.GetZDO().Set("ownerName", name);
+ }
+ }
+
+ private long GetOwner()
+ {
+ return m_nview.GetZDO().GetLong("owner", 0L);
+ }
+
+ private string GetOwnerName()
+ {
+ return m_nview.GetZDO().GetString("ownerName");
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beehive.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beehive.cs
new file mode 100644
index 0000000..0e92ae1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Beehive.cs
@@ -0,0 +1,186 @@
+using System;
+using UnityEngine;
+
+public class Beehive : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "";
+
+ public Transform m_coverPoint;
+
+ public Transform m_spawnPoint;
+
+ public GameObject m_beeEffect;
+
+ public float m_maxCover = 0.25f;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ public float m_secPerUnit = 10f;
+
+ public int m_maxHoney = 4;
+
+ public ItemDrop m_honeyItem;
+
+ public EffectList m_spawnEffect = new EffectList();
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong("lastTime", 0L) == 0L)
+ {
+ m_nview.GetZDO().Set("lastTime", ZNet.instance.GetTime().Ticks);
+ }
+ m_nview.Register("Extract", RPC_Extract);
+ InvokeRepeating("UpdateBees", 0f, 10f);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (!PrivateArea.CheckAccess(base.transform.position, 0f, flash: false))
+ {
+ return Localization.instance.Localize(m_name + "\n$piece_noaccess");
+ }
+ int honeyLevel = GetHoneyLevel();
+ if (honeyLevel > 0)
+ {
+ return Localization.instance.Localize(m_name + " ( " + m_honeyItem.m_itemData.m_shared.m_name + " x " + honeyLevel + " )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_beehive_extract");
+ }
+ return Localization.instance.Localize(m_name + " ( $piece_container_empty )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_beehive_check");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ return true;
+ }
+ if (GetHoneyLevel() > 0)
+ {
+ Extract();
+ }
+ else
+ {
+ if (!CheckBiome())
+ {
+ character.Message(MessageHud.MessageType.Center, "$piece_beehive_area");
+ return true;
+ }
+ if (!HaveFreeSpace())
+ {
+ character.Message(MessageHud.MessageType.Center, "$piece_beehive_freespace");
+ return true;
+ }
+ if (!EnvMan.instance.IsDaylight())
+ {
+ character.Message(MessageHud.MessageType.Center, "$piece_beehive_sleep");
+ return true;
+ }
+ character.Message(MessageHud.MessageType.Center, "$piece_beehive_happy");
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void Extract()
+ {
+ m_nview.InvokeRPC("Extract");
+ }
+
+ private void RPC_Extract(long caller)
+ {
+ int honeyLevel = GetHoneyLevel();
+ if (honeyLevel > 0)
+ {
+ m_spawnEffect.Create(m_spawnPoint.position, Quaternion.identity);
+ for (int i = 0; i < honeyLevel; i++)
+ {
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * 0.5f;
+ Vector3 position = m_spawnPoint.position + new Vector3(vector.x, 0.25f * (float)i, vector.y);
+ UnityEngine.Object.Instantiate(m_honeyItem, position, Quaternion.identity);
+ }
+ ResetLevel();
+ }
+ }
+
+ private float GetTimeSinceLastUpdate()
+ {
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("lastTime", ZNet.instance.GetTime().Ticks));
+ DateTime time = ZNet.instance.GetTime();
+ TimeSpan timeSpan = time - dateTime;
+ m_nview.GetZDO().Set("lastTime", time.Ticks);
+ double num = timeSpan.TotalSeconds;
+ if (num < 0.0)
+ {
+ num = 0.0;
+ }
+ return (float)num;
+ }
+
+ private void ResetLevel()
+ {
+ m_nview.GetZDO().Set("level", 0);
+ }
+
+ private void IncreseLevel(int i)
+ {
+ int honeyLevel = GetHoneyLevel();
+ honeyLevel += i;
+ honeyLevel = Mathf.Clamp(honeyLevel, 0, m_maxHoney);
+ m_nview.GetZDO().Set("level", honeyLevel);
+ }
+
+ private int GetHoneyLevel()
+ {
+ return m_nview.GetZDO().GetInt("level");
+ }
+
+ private void UpdateBees()
+ {
+ bool flag = CheckBiome() && HaveFreeSpace();
+ bool active = flag && EnvMan.instance.IsDaylight();
+ m_beeEffect.SetActive(active);
+ if (m_nview.IsOwner() && flag)
+ {
+ float timeSinceLastUpdate = GetTimeSinceLastUpdate();
+ float @float = m_nview.GetZDO().GetFloat("product");
+ @float += timeSinceLastUpdate;
+ if (@float > m_secPerUnit)
+ {
+ int i = (int)(@float / m_secPerUnit);
+ IncreseLevel(i);
+ @float = 0f;
+ }
+ m_nview.GetZDO().Set("product", @float);
+ }
+ }
+
+ private bool HaveFreeSpace()
+ {
+ Cover.GetCoverForPoint(m_coverPoint.position, out var coverPercentage, out var _);
+ return coverPercentage < m_maxCover;
+ }
+
+ private bool CheckBiome()
+ {
+ return (Heightmap.FindBiome(base.transform.position) & m_biome) != 0;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Billboard.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Billboard.cs
new file mode 100644
index 0000000..108afa6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Billboard.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+
+public class Billboard : MonoBehaviour
+{
+ public bool m_vertical = true;
+
+ public bool m_invert;
+
+ private Vector3 m_normal;
+
+ private void Awake()
+ {
+ m_normal = base.transform.up;
+ }
+
+ private void LateUpdate()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null))
+ {
+ Vector3 vector = mainCamera.transform.position;
+ if (m_invert)
+ {
+ vector = base.transform.position - (vector - base.transform.position);
+ }
+ if (m_vertical)
+ {
+ vector.y = base.transform.position.y;
+ base.transform.LookAt(vector, m_normal);
+ }
+ else
+ {
+ base.transform.LookAt(vector);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BiomeEnvSetup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BiomeEnvSetup.cs
new file mode 100644
index 0000000..4ff8e60
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BiomeEnvSetup.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Serialization;
+
+[Serializable]
+public class BiomeEnvSetup
+{
+ public string m_name = "";
+
+ public Heightmap.Biome m_biome = Heightmap.Biome.Meadows;
+
+ public List<EnvEntry> m_environments = new List<EnvEntry>();
+
+ public string m_musicMorning = "morning";
+
+ public string m_musicEvening = "evening";
+
+ [FormerlySerializedAs("m_musicRandomDay")]
+ public string m_musicDay = "";
+
+ [FormerlySerializedAs("m_musicRandomNight")]
+ public string m_musicNight = "";
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BossStone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BossStone.cs
new file mode 100644
index 0000000..67aa52f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/BossStone.cs
@@ -0,0 +1,111 @@
+using System.Collections;
+using UnityEngine;
+
+public class BossStone : MonoBehaviour
+{
+ public ItemStand m_itemStand;
+
+ public GameObject m_activeEffect;
+
+ public EffectList m_activateStep1 = new EffectList();
+
+ public EffectList m_activateStep2 = new EffectList();
+
+ public EffectList m_activateStep3 = new EffectList();
+
+ public string m_completedMessage = "";
+
+ public MeshRenderer m_mesh;
+
+ public int m_emissiveMaterialIndex;
+
+ public Color m_activeEmissiveColor = Color.white;
+
+ private bool m_active;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ if (m_mesh.material.HasProperty("_EmissionColor"))
+ {
+ m_mesh.materials[m_emissiveMaterialIndex].SetColor("_EmissionColor", Color.black);
+ }
+ if ((bool)m_activeEffect)
+ {
+ m_activeEffect.SetActive(value: false);
+ }
+ SetActivated(m_itemStand.HaveAttachment(), triggerEffect: false);
+ InvokeRepeating("UpdateVisual", 1f, 1f);
+ }
+
+ private void UpdateVisual()
+ {
+ SetActivated(m_itemStand.HaveAttachment(), triggerEffect: true);
+ }
+
+ private void SetActivated(bool active, bool triggerEffect)
+ {
+ if (active == m_active)
+ {
+ return;
+ }
+ m_active = active;
+ if (triggerEffect && active)
+ {
+ Invoke("DelayedAttachEffects_Step1", 1f);
+ Invoke("DelayedAttachEffects_Step2", 5f);
+ Invoke("DelayedAttachEffects_Step3", 11f);
+ return;
+ }
+ if ((bool)m_activeEffect)
+ {
+ m_activeEffect.SetActive(active);
+ }
+ StopCoroutine("FadeEmission");
+ StartCoroutine("FadeEmission");
+ }
+
+ private void DelayedAttachEffects_Step1()
+ {
+ m_activateStep1.Create(m_itemStand.transform.position, base.transform.rotation);
+ }
+
+ private void DelayedAttachEffects_Step2()
+ {
+ m_activateStep2.Create(base.transform.position, base.transform.rotation);
+ }
+
+ private void DelayedAttachEffects_Step3()
+ {
+ if ((bool)m_activeEffect)
+ {
+ m_activeEffect.SetActive(value: true);
+ }
+ m_activateStep3.Create(base.transform.position, base.transform.rotation);
+ StopCoroutine("FadeEmission");
+ StartCoroutine("FadeEmission");
+ Player.MessageAllInRange(base.transform.position, 20f, MessageHud.MessageType.Center, m_completedMessage);
+ }
+
+ private IEnumerator FadeEmission()
+ {
+ if ((bool)m_mesh && m_mesh.materials[m_emissiveMaterialIndex].HasProperty("_EmissionColor"))
+ {
+ Color startColor = m_mesh.materials[m_emissiveMaterialIndex].GetColor("_EmissionColor");
+ Color targetColor = (m_active ? m_activeEmissiveColor : Color.black);
+ for (float t = 0f; t < 1f; t += Time.deltaTime)
+ {
+ Color value = Color.Lerp(startColor, targetColor, t / 1f);
+ m_mesh.materials[m_emissiveMaterialIndex].SetColor("_EmissionColor", value);
+ yield return null;
+ }
+ }
+ ZLog.Log("Done fading color");
+ }
+
+ public bool IsActivated()
+ {
+ return m_active;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CamShaker.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CamShaker.cs
new file mode 100644
index 0000000..4d661c5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CamShaker.cs
@@ -0,0 +1,65 @@
+using System.Collections;
+using UnityEngine;
+
+public class CamShaker : MonoBehaviour
+{
+ public float m_strength = 1f;
+
+ public float m_range = 50f;
+
+ public float m_delay;
+
+ public bool m_continous;
+
+ public float m_continousDuration;
+
+ public bool m_localOnly;
+
+ private void Start()
+ {
+ if (m_continous)
+ {
+ StartCoroutine("TriggerContinous");
+ }
+ else if (m_delay <= 0f)
+ {
+ Trigger();
+ }
+ else
+ {
+ Invoke("Trigger", m_delay);
+ }
+ }
+
+ private IEnumerator TriggerContinous()
+ {
+ float t = 0f;
+ while (true)
+ {
+ Trigger();
+ t += Time.deltaTime;
+ if (m_continousDuration > 0f && t > m_continousDuration)
+ {
+ break;
+ }
+ yield return null;
+ }
+ }
+
+ private void Trigger()
+ {
+ if (!GameCamera.instance)
+ {
+ return;
+ }
+ if (m_localOnly)
+ {
+ ZNetView component = GetComponent<ZNetView>();
+ if ((bool)component && !component.IsOwner())
+ {
+ return;
+ }
+ }
+ GameCamera.instance.AddShake(base.transform.position, m_range, m_strength, m_continous);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CameraEffects.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CameraEffects.cs
new file mode 100644
index 0000000..7aa1f95
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CameraEffects.cs
@@ -0,0 +1,127 @@
+using UnityEngine;
+using UnityEngine.PostProcessing;
+using UnityStandardAssets.ImageEffects;
+
+public class CameraEffects : MonoBehaviour
+{
+ private static CameraEffects m_instance;
+
+ public bool m_forceDof;
+
+ public LayerMask m_dofRayMask;
+
+ public bool m_dofAutoFocus;
+
+ public float m_dofMinDistance = 50f;
+
+ public float m_dofMinDistanceShip = 50f;
+
+ public float m_dofMaxDistance = 3000f;
+
+ private PostProcessingBehaviour m_postProcessing;
+
+ private DepthOfField m_dof;
+
+ public static CameraEffects instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_postProcessing = GetComponent<PostProcessingBehaviour>();
+ m_dof = GetComponent<DepthOfField>();
+ ApplySettings();
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void ApplySettings()
+ {
+ SetDof(PlayerPrefs.GetInt("DOF", 1) == 1);
+ SetBloom(PlayerPrefs.GetInt("Bloom", 1) == 1);
+ SetSSAO(PlayerPrefs.GetInt("SSAO", 1) == 1);
+ SetSunShafts(PlayerPrefs.GetInt("SunShafts", 1) == 1);
+ SetAntiAliasing(PlayerPrefs.GetInt("AntiAliasing", 1) == 1);
+ SetCA(PlayerPrefs.GetInt("ChromaticAberration", 1) == 1);
+ SetMotionBlur(PlayerPrefs.GetInt("MotionBlur", 1) == 1);
+ }
+
+ public void SetSunShafts(bool enabled)
+ {
+ SunShafts component = GetComponent<SunShafts>();
+ if (component != null)
+ {
+ component.enabled = enabled;
+ }
+ }
+
+ private void SetBloom(bool enabled)
+ {
+ m_postProcessing.profile.bloom.enabled = enabled;
+ }
+
+ private void SetSSAO(bool enabled)
+ {
+ m_postProcessing.profile.ambientOcclusion.enabled = enabled;
+ }
+
+ private void SetMotionBlur(bool enabled)
+ {
+ m_postProcessing.profile.motionBlur.enabled = enabled;
+ }
+
+ private void SetAntiAliasing(bool enabled)
+ {
+ m_postProcessing.profile.antialiasing.enabled = enabled;
+ }
+
+ private void SetCA(bool enabled)
+ {
+ m_postProcessing.profile.chromaticAberration.enabled = enabled;
+ }
+
+ private void SetDof(bool enabled)
+ {
+ m_dof.enabled = enabled || m_forceDof;
+ }
+
+ private void LateUpdate()
+ {
+ UpdateDOF();
+ }
+
+ private bool ControllingShip()
+ {
+ if (Player.m_localPlayer == null || Player.m_localPlayer.GetControlledShip() != null)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void UpdateDOF()
+ {
+ if (m_dof.enabled && m_dofAutoFocus)
+ {
+ float num = m_dofMaxDistance;
+ if (Physics.Raycast(base.transform.position, base.transform.forward, out var hitInfo, m_dofMaxDistance, m_dofRayMask))
+ {
+ num = hitInfo.distance;
+ }
+ if (ControllingShip() && num < m_dofMinDistanceShip)
+ {
+ num = m_dofMinDistanceShip;
+ }
+ if (num < m_dofMinDistance)
+ {
+ num = m_dofMinDistance;
+ }
+ m_dof.focalLength = Mathf.Lerp(m_dof.focalLength, num, 0.2f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chair.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chair.cs
new file mode 100644
index 0000000..09c5277
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chair.cs
@@ -0,0 +1,73 @@
+using UnityEngine;
+
+public class Chair : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "Chair";
+
+ public float m_useDistance = 2f;
+
+ public Transform m_attachPoint;
+
+ public Vector3 m_detachOffset = new Vector3(0f, 0.5f, 0f);
+
+ public string m_attachAnimation = "attach_chair";
+
+ private const float m_minSitDelay = 2f;
+
+ private static float m_lastSitTime;
+
+ public string GetHoverText()
+ {
+ if (Time.time - m_lastSitTime < 2f)
+ {
+ return "";
+ }
+ if (!InUseDistance(Player.m_localPlayer))
+ {
+ return Localization.instance.Localize("<color=grey>$piece_toofar</color>");
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid human, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ Player player = human as Player;
+ if (!InUseDistance(player))
+ {
+ return false;
+ }
+ if (Time.time - m_lastSitTime < 2f)
+ {
+ return false;
+ }
+ if ((bool)player)
+ {
+ if (player.IsEncumbered())
+ {
+ return false;
+ }
+ player.AttachStart(m_attachPoint, hideWeapons: false, isBed: false, m_attachAnimation, m_detachOffset);
+ m_lastSitTime = Time.time;
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private bool InUseDistance(Humanoid human)
+ {
+ return Vector3.Distance(human.transform.position, m_attachPoint.position) < m_useDistance;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ChangeLog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ChangeLog.cs
new file mode 100644
index 0000000..ff4874f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ChangeLog.cs
@@ -0,0 +1,15 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ChangeLog : MonoBehaviour
+{
+ public Text m_textField;
+
+ public TextAsset m_changeLog;
+
+ private void Start()
+ {
+ string text = m_changeLog.text;
+ m_textField.text = text;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Character.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Character.cs
new file mode 100644
index 0000000..7807218
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Character.cs
@@ -0,0 +1,2567 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Character : MonoBehaviour, IDestructible, Hoverable, IWaterInteractable
+{
+ public enum Faction
+ {
+ Players,
+ AnimalsVeg,
+ ForestMonsters,
+ Undead,
+ Demon,
+ MountainMonsters,
+ SeaMonsters,
+ PlainsMonsters,
+ Boss
+ }
+
+ public enum GroundTiltType
+ {
+ None,
+ Pitch,
+ Full,
+ PitchRaycast,
+ FullRaycast
+ }
+
+ private float m_underWorldCheckTimer;
+
+ private Collider m_lowestContactCollider;
+
+ private bool m_groundContact;
+
+ private Vector3 m_groundContactPoint = Vector3.zero;
+
+ private Vector3 m_groundContactNormal = Vector3.zero;
+
+ public Action<float, Character> m_onDamaged;
+
+ public Action m_onDeath;
+
+ public Action<int> m_onLevelSet;
+
+ public Action<Vector3> m_onLand;
+
+ [Header("Character")]
+ public string m_name = "";
+
+ public Faction m_faction = Faction.AnimalsVeg;
+
+ public bool m_boss;
+
+ public string m_bossEvent = "";
+
+ public string m_defeatSetGlobalKey = "";
+
+ [Header("Movement & Physics")]
+ public float m_crouchSpeed = 2f;
+
+ public float m_walkSpeed = 5f;
+
+ public float m_speed = 10f;
+
+ public float m_turnSpeed = 300f;
+
+ public float m_runSpeed = 20f;
+
+ public float m_runTurnSpeed = 300f;
+
+ public float m_flySlowSpeed = 5f;
+
+ public float m_flyFastSpeed = 12f;
+
+ public float m_flyTurnSpeed = 12f;
+
+ public float m_acceleration = 1f;
+
+ public float m_jumpForce = 10f;
+
+ public float m_jumpForceForward;
+
+ public float m_jumpForceTiredFactor = 0.7f;
+
+ public float m_airControl = 0.1f;
+
+ private const float m_slopeStaminaDrain = 10f;
+
+ public const float m_minSlideDegreesPlayer = 38f;
+
+ public const float m_minSlideDegreesMonster = 90f;
+
+ private const float m_rootMotionMultiplier = 55f;
+
+ private const float m_continousPushForce = 10f;
+
+ private const float m_pushForcedissipation = 100f;
+
+ private const float m_maxMoveForce = 20f;
+
+ public bool m_canSwim = true;
+
+ public float m_swimDepth = 2f;
+
+ public float m_swimSpeed = 2f;
+
+ public float m_swimTurnSpeed = 100f;
+
+ public float m_swimAcceleration = 0.05f;
+
+ public GroundTiltType m_groundTilt;
+
+ public bool m_flying;
+
+ public float m_jumpStaminaUsage = 10f;
+
+ [Header("Bodyparts")]
+ public Transform m_eye;
+
+ protected Transform m_head;
+
+ [Header("Effects")]
+ public EffectList m_hitEffects = new EffectList();
+
+ public EffectList m_critHitEffects = new EffectList();
+
+ public EffectList m_backstabHitEffects = new EffectList();
+
+ public EffectList m_deathEffects = new EffectList();
+
+ public EffectList m_waterEffects = new EffectList();
+
+ public EffectList m_slideEffects = new EffectList();
+
+ public EffectList m_jumpEffects = new EffectList();
+
+ [Header("Health & Damage")]
+ public bool m_tolerateWater = true;
+
+ public bool m_tolerateFire;
+
+ public bool m_tolerateSmoke = true;
+
+ public float m_health = 10f;
+
+ public HitData.DamageModifiers m_damageModifiers;
+
+ public bool m_staggerWhenBlocked = true;
+
+ public float m_staggerDamageFactor;
+
+ private const float m_staggerResetTime = 3f;
+
+ private float m_staggerDamage;
+
+ private float m_staggerTimer;
+
+ private float m_backstabTime = -99999f;
+
+ private const float m_backstabResetTime = 300f;
+
+ private GameObject[] m_waterEffects_instances;
+
+ private GameObject[] m_slideEffects_instances;
+
+ protected Vector3 m_moveDir = Vector3.zero;
+
+ protected Vector3 m_lookDir = Vector3.forward;
+
+ protected Quaternion m_lookYaw = Quaternion.identity;
+
+ protected bool m_run;
+
+ protected bool m_walk;
+
+ protected bool m_attack;
+
+ protected bool m_attackDraw;
+
+ protected bool m_secondaryAttack;
+
+ protected bool m_blocking;
+
+ protected GameObject m_visual;
+
+ protected LODGroup m_lodGroup;
+
+ protected Rigidbody m_body;
+
+ protected CapsuleCollider m_collider;
+
+ protected ZNetView m_nview;
+
+ protected ZSyncAnimation m_zanim;
+
+ protected Animator m_animator;
+
+ protected CharacterAnimEvent m_animEvent;
+
+ protected BaseAI m_baseAI;
+
+ private const float m_maxFallHeight = 20f;
+
+ private const float m_minFallHeight = 4f;
+
+ private const float m_maxFallDamage = 100f;
+
+ private const float m_staggerDamageBonus = 2f;
+
+ private const float m_baseVisualRange = 30f;
+
+ private const float m_autoJumpInterval = 0.5f;
+
+ private float m_jumpTimer;
+
+ private float m_lastAutoJumpTime;
+
+ private float m_lastGroundTouch;
+
+ private Vector3 m_lastGroundNormal = Vector3.up;
+
+ private Vector3 m_lastGroundPoint = Vector3.up;
+
+ private Collider m_lastGroundCollider;
+
+ private Rigidbody m_lastGroundBody;
+
+ private Vector3 m_lastAttachPos = Vector3.zero;
+
+ private Rigidbody m_lastAttachBody;
+
+ protected float m_maxAirAltitude = -10000f;
+
+ private float m_waterLevel = -10000f;
+
+ private float m_swimTimer = 999f;
+
+ protected SEMan m_seman;
+
+ private float m_noiseRange;
+
+ private float m_syncNoiseTimer;
+
+ private bool m_tamed;
+
+ private float m_lastTamedCheck;
+
+ private int m_level = 1;
+
+ private Vector3 m_currentVel = Vector3.zero;
+
+ private float m_currentTurnVel;
+
+ private float m_currentTurnVelChange;
+
+ private Vector3 m_groundTiltNormal = Vector3.up;
+
+ protected Vector3 m_pushForce = Vector3.zero;
+
+ private Vector3 m_rootMotion = Vector3.zero;
+
+ private static int forward_speed = 0;
+
+ private static int sideway_speed = 0;
+
+ private static int turn_speed = 0;
+
+ private static int inWater = 0;
+
+ private static int onGround = 0;
+
+ private static int encumbered = 0;
+
+ private static int flying = 0;
+
+ private float m_slippage;
+
+ protected bool m_wallRunning;
+
+ protected bool m_sliding;
+
+ protected bool m_running;
+
+ private Vector3 m_originalLocalRef;
+
+ private bool m_lodVisible = true;
+
+ private static int m_smokeRayMask = 0;
+
+ private float m_smokeCheckTimer;
+
+ private static bool m_dpsDebugEnabled = false;
+
+ private static List<KeyValuePair<float, float>> m_enemyDamage = new List<KeyValuePair<float, float>>();
+
+ private static List<KeyValuePair<float, float>> m_playerDamage = new List<KeyValuePair<float, float>>();
+
+ private static List<Character> m_characters = new List<Character>();
+
+ protected static int m_characterLayer = 0;
+
+ protected static int m_characterNetLayer = 0;
+
+ protected static int m_characterGhostLayer = 0;
+
+ protected static int m_animatorTagFreeze = Animator.StringToHash("freeze");
+
+ protected static int m_animatorTagStagger = Animator.StringToHash("stagger");
+
+ protected static int m_animatorTagSitting = Animator.StringToHash("sitting");
+
+ protected virtual void Awake()
+ {
+ m_characters.Add(this);
+ m_collider = GetComponent<CapsuleCollider>();
+ m_body = GetComponent<Rigidbody>();
+ m_zanim = GetComponent<ZSyncAnimation>();
+ m_nview = GetComponent<ZNetView>();
+ m_animator = GetComponentInChildren<Animator>();
+ m_animEvent = m_animator.GetComponent<CharacterAnimEvent>();
+ m_baseAI = GetComponent<BaseAI>();
+ m_animator.logWarnings = false;
+ m_visual = base.transform.Find("Visual").gameObject;
+ m_lodGroup = m_visual.GetComponent<LODGroup>();
+ m_head = m_animator.GetBoneTransform(HumanBodyBones.Head);
+ m_body.maxDepenetrationVelocity = 2f;
+ if (m_smokeRayMask == 0)
+ {
+ m_smokeRayMask = LayerMask.GetMask("smoke");
+ m_characterLayer = LayerMask.NameToLayer("character");
+ m_characterNetLayer = LayerMask.NameToLayer("character_net");
+ m_characterGhostLayer = LayerMask.NameToLayer("character_ghost");
+ }
+ if (forward_speed == 0)
+ {
+ forward_speed = ZSyncAnimation.GetHash("forward_speed");
+ sideway_speed = ZSyncAnimation.GetHash("sideway_speed");
+ turn_speed = ZSyncAnimation.GetHash("turn_speed");
+ inWater = ZSyncAnimation.GetHash("inWater");
+ onGround = ZSyncAnimation.GetHash("onGround");
+ encumbered = ZSyncAnimation.GetHash("encumbered");
+ flying = ZSyncAnimation.GetHash("flying");
+ }
+ if ((bool)m_lodGroup)
+ {
+ m_originalLocalRef = m_lodGroup.localReferencePoint;
+ }
+ m_seman = new SEMan(this, m_nview);
+ if (m_nview.GetZDO() == null)
+ {
+ return;
+ }
+ if (!IsPlayer())
+ {
+ if (m_nview.IsOwner() && GetHealth() == GetMaxHealth())
+ {
+ SetupMaxHealth();
+ }
+ m_tamed = m_nview.GetZDO().GetBool("tamed", m_tamed);
+ m_level = m_nview.GetZDO().GetInt("level", 1);
+ }
+ m_nview.Register<HitData>("Damage", RPC_Damage);
+ m_nview.Register<float, bool>("Heal", RPC_Heal);
+ m_nview.Register<float>("AddNoise", RPC_AddNoise);
+ m_nview.Register<Vector3>("Stagger", RPC_Stagger);
+ m_nview.Register("ResetCloth", RPC_ResetCloth);
+ m_nview.Register<bool>("SetTamed", RPC_SetTamed);
+ }
+
+ private void SetupMaxHealth()
+ {
+ int level = GetLevel();
+ float difficultyHealthScale = Game.instance.GetDifficultyHealthScale(base.transform.position);
+ SetMaxHealth(m_health * difficultyHealthScale * (float)level);
+ }
+
+ protected virtual void Start()
+ {
+ m_nview.GetZDO();
+ }
+
+ public virtual void OnDestroy()
+ {
+ m_seman.OnDestroy();
+ m_characters.Remove(this);
+ }
+
+ public void SetLevel(int level)
+ {
+ if (level >= 1)
+ {
+ m_level = level;
+ m_nview.GetZDO().Set("level", level);
+ SetupMaxHealth();
+ if (m_onLevelSet != null)
+ {
+ m_onLevelSet(m_level);
+ }
+ }
+ }
+
+ public int GetLevel()
+ {
+ return m_level;
+ }
+
+ public virtual bool IsPlayer()
+ {
+ return false;
+ }
+
+ public Faction GetFaction()
+ {
+ return m_faction;
+ }
+
+ protected virtual void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ UpdateLayer();
+ UpdateContinousEffects();
+ UpdateWater(fixedDeltaTime);
+ UpdateGroundTilt(fixedDeltaTime);
+ SetVisible(m_nview.HasOwner());
+ if (m_nview.IsOwner())
+ {
+ UpdateGroundContact(fixedDeltaTime);
+ UpdateNoise(fixedDeltaTime);
+ m_seman.Update(fixedDeltaTime);
+ UpdateStagger(fixedDeltaTime);
+ UpdatePushback(fixedDeltaTime);
+ UpdateMotion(fixedDeltaTime);
+ UpdateSmoke(fixedDeltaTime);
+ UnderWorldCheck(fixedDeltaTime);
+ SyncVelocity();
+ CheckDeath();
+ }
+ }
+ }
+
+ private void UpdateLayer()
+ {
+ if (m_collider.gameObject.layer == m_characterLayer || m_collider.gameObject.layer == m_characterNetLayer)
+ {
+ if (m_nview.IsOwner())
+ {
+ m_collider.gameObject.layer = (IsAttached() ? m_characterNetLayer : m_characterLayer);
+ }
+ else
+ {
+ m_collider.gameObject.layer = m_characterNetLayer;
+ }
+ }
+ }
+
+ private void UnderWorldCheck(float dt)
+ {
+ if (IsDead())
+ {
+ return;
+ }
+ m_underWorldCheckTimer += dt;
+ if (m_underWorldCheckTimer > 5f || IsPlayer())
+ {
+ m_underWorldCheckTimer = 0f;
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ if (base.transform.position.y < groundHeight - 1f)
+ {
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + 0.5f;
+ base.transform.position = position;
+ m_body.position = position;
+ m_body.velocity = Vector3.zero;
+ }
+ }
+ }
+
+ private void UpdateSmoke(float dt)
+ {
+ if (m_tolerateSmoke)
+ {
+ return;
+ }
+ m_smokeCheckTimer += dt;
+ if (m_smokeCheckTimer > 2f)
+ {
+ m_smokeCheckTimer = 0f;
+ if (Physics.CheckSphere(GetTopPoint() + Vector3.up * 0.1f, 0.5f, m_smokeRayMask))
+ {
+ m_seman.AddStatusEffect("Smoked", resetTime: true);
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("Smoked", quiet: true);
+ }
+ }
+ }
+
+ private void UpdateContinousEffects()
+ {
+ SetupContinousEffect(base.transform.position, m_sliding, m_slideEffects, ref m_slideEffects_instances);
+ Vector3 position = base.transform.position;
+ position.y = m_waterLevel + 0.05f;
+ SetupContinousEffect(position, InWater(), m_waterEffects, ref m_waterEffects_instances);
+ }
+
+ private void SetupContinousEffect(Vector3 point, bool enabled, EffectList effects, ref GameObject[] instances)
+ {
+ if (!effects.HasEffects())
+ {
+ return;
+ }
+ if (enabled)
+ {
+ if (instances == null)
+ {
+ instances = effects.Create(point, Quaternion.identity, base.transform);
+ return;
+ }
+ GameObject[] array = instances;
+ foreach (GameObject gameObject in array)
+ {
+ if ((bool)gameObject)
+ {
+ gameObject.transform.position = point;
+ }
+ }
+ }
+ else
+ {
+ if (instances == null)
+ {
+ return;
+ }
+ GameObject[] array = instances;
+ foreach (GameObject gameObject2 in array)
+ {
+ if ((bool)gameObject2)
+ {
+ ParticleSystem[] componentsInChildren = gameObject2.GetComponentsInChildren<ParticleSystem>();
+ foreach (ParticleSystem obj in componentsInChildren)
+ {
+ ParticleSystem.EmissionModule emission = obj.emission;
+ emission.enabled = false;
+ obj.Stop();
+ }
+ CamShaker componentInChildren = gameObject2.GetComponentInChildren<CamShaker>();
+ if ((bool)componentInChildren)
+ {
+ UnityEngine.Object.Destroy(componentInChildren);
+ }
+ ZSFX componentInChildren2 = gameObject2.GetComponentInChildren<ZSFX>();
+ if ((bool)componentInChildren2)
+ {
+ componentInChildren2.FadeOut();
+ }
+ TimedDestruction component = gameObject2.GetComponent<TimedDestruction>();
+ if ((bool)component)
+ {
+ component.Trigger();
+ }
+ else
+ {
+ UnityEngine.Object.Destroy(gameObject2);
+ }
+ }
+ }
+ instances = null;
+ }
+ }
+
+ protected virtual void OnSwiming(Vector3 targetVel, float dt)
+ {
+ }
+
+ protected virtual void OnSneaking(float dt)
+ {
+ }
+
+ protected virtual void OnJump()
+ {
+ }
+
+ protected virtual bool TakeInput()
+ {
+ return true;
+ }
+
+ private float GetSlideAngle()
+ {
+ if (!IsPlayer())
+ {
+ return 90f;
+ }
+ return 38f;
+ }
+
+ private void ApplySlide(float dt, ref Vector3 currentVel, Vector3 bodyVel, bool running)
+ {
+ bool flag = CanWallRun();
+ float num = Mathf.Acos(Mathf.Clamp01(m_lastGroundNormal.y)) * 57.29578f;
+ Vector3 lastGroundNormal = m_lastGroundNormal;
+ lastGroundNormal.y = 0f;
+ lastGroundNormal.Normalize();
+ _ = m_body.velocity;
+ Vector3 vector = Vector3.Cross(rhs: Vector3.Cross(m_lastGroundNormal, Vector3.up), lhs: m_lastGroundNormal);
+ bool flag2 = currentVel.magnitude > 0.1f;
+ if (num > GetSlideAngle())
+ {
+ if (running && flag && flag2)
+ {
+ UseStamina(10f * dt);
+ m_slippage = 0f;
+ m_wallRunning = true;
+ }
+ else
+ {
+ m_slippage = Mathf.MoveTowards(m_slippage, 1f, 1f * dt);
+ }
+ Vector3 b = vector * 5f;
+ currentVel = Vector3.Lerp(currentVel, b, m_slippage);
+ m_sliding = m_slippage > 0.5f;
+ }
+ else
+ {
+ m_slippage = 0f;
+ }
+ }
+
+ private void UpdateMotion(float dt)
+ {
+ UpdateBodyFriction();
+ m_sliding = false;
+ m_wallRunning = false;
+ m_running = false;
+ if (IsDead())
+ {
+ return;
+ }
+ if (IsDebugFlying())
+ {
+ UpdateDebugFly(dt);
+ return;
+ }
+ if (InIntro())
+ {
+ m_maxAirAltitude = base.transform.position.y;
+ m_body.velocity = Vector3.zero;
+ m_body.angularVelocity = Vector3.zero;
+ }
+ if (!InWaterSwimDepth() && !IsOnGround())
+ {
+ float y = base.transform.position.y;
+ m_maxAirAltitude = Mathf.Max(m_maxAirAltitude, y);
+ }
+ if (IsSwiming())
+ {
+ UpdateSwiming(dt);
+ }
+ else if (m_flying)
+ {
+ UpdateFlying(dt);
+ }
+ else
+ {
+ UpdateWalking(dt);
+ }
+ m_lastGroundTouch += Time.fixedDeltaTime;
+ m_jumpTimer += Time.fixedDeltaTime;
+ }
+
+ private void UpdateDebugFly(float dt)
+ {
+ float num = (m_run ? 50 : 20);
+ Vector3 b = m_moveDir * num;
+ if (TakeInput())
+ {
+ if (ZInput.GetButton("Jump"))
+ {
+ b.y = num;
+ }
+ else if (Input.GetKey(KeyCode.LeftControl))
+ {
+ b.y = 0f - num;
+ }
+ }
+ m_currentVel = Vector3.Lerp(m_currentVel, b, 0.5f);
+ m_body.velocity = m_currentVel;
+ m_body.useGravity = false;
+ m_lastGroundTouch = 0f;
+ m_maxAirAltitude = base.transform.position.y;
+ m_body.rotation = Quaternion.RotateTowards(base.transform.rotation, m_lookYaw, m_turnSpeed * dt);
+ m_body.angularVelocity = Vector3.zero;
+ UpdateEyeRotation();
+ }
+
+ private void UpdateSwiming(float dt)
+ {
+ bool flag = IsOnGround();
+ if (Mathf.Max(0f, m_maxAirAltitude - base.transform.position.y) > 0.5f && m_onLand != null)
+ {
+ m_onLand(new Vector3(base.transform.position.x, m_waterLevel, base.transform.position.z));
+ }
+ m_maxAirAltitude = base.transform.position.y;
+ float speed = m_swimSpeed * GetAttackSpeedFactorMovement();
+ if (InMinorAction())
+ {
+ speed = 0f;
+ }
+ m_seman.ApplyStatusEffectSpeedMods(ref speed);
+ Vector3 vector = m_moveDir * speed;
+ if (vector.magnitude > 0f && IsOnGround())
+ {
+ vector = Vector3.ProjectOnPlane(vector, m_lastGroundNormal).normalized * vector.magnitude;
+ }
+ if (IsPlayer())
+ {
+ m_currentVel = Vector3.Lerp(m_currentVel, vector, m_swimAcceleration);
+ }
+ else
+ {
+ float magnitude = vector.magnitude;
+ float magnitude2 = m_currentVel.magnitude;
+ if (magnitude > magnitude2)
+ {
+ magnitude = Mathf.MoveTowards(magnitude2, magnitude, m_swimAcceleration);
+ vector = vector.normalized * magnitude;
+ }
+ m_currentVel = Vector3.Lerp(m_currentVel, vector, 0.5f);
+ }
+ if (vector.magnitude > 0.1f)
+ {
+ AddNoise(15f);
+ }
+ AddPushbackForce(ref m_currentVel);
+ Vector3 force = m_currentVel - m_body.velocity;
+ force.y = 0f;
+ if (force.magnitude > 20f)
+ {
+ force = force.normalized * 20f;
+ }
+ m_body.AddForce(force, ForceMode.VelocityChange);
+ float num = m_waterLevel - m_swimDepth;
+ if (base.transform.position.y < num)
+ {
+ float t = Mathf.Clamp01((num - base.transform.position.y) / 2f);
+ float target = Mathf.Lerp(0f, 10f, t);
+ Vector3 velocity = m_body.velocity;
+ velocity.y = Mathf.MoveTowards(velocity.y, target, 50f * dt);
+ m_body.velocity = velocity;
+ }
+ else
+ {
+ float t2 = Mathf.Clamp01((0f - (num - base.transform.position.y)) / 1f);
+ float num2 = Mathf.Lerp(0f, 10f, t2);
+ Vector3 velocity2 = m_body.velocity;
+ velocity2.y = Mathf.MoveTowards(velocity2.y, 0f - num2, 30f * dt);
+ m_body.velocity = velocity2;
+ }
+ float target2 = 0f;
+ if (m_moveDir.magnitude > 0.1f || AlwaysRotateCamera())
+ {
+ float speed2 = m_swimTurnSpeed;
+ m_seman.ApplyStatusEffectSpeedMods(ref speed2);
+ target2 = UpdateRotation(speed2, dt);
+ }
+ m_body.angularVelocity = Vector3.zero;
+ UpdateEyeRotation();
+ m_body.useGravity = true;
+ float num3 = Vector3.Dot(m_currentVel, base.transform.forward);
+ float value = Vector3.Dot(m_currentVel, base.transform.right);
+ float num4 = Vector3.Dot(m_body.velocity, base.transform.forward);
+ m_currentTurnVel = Mathf.SmoothDamp(m_currentTurnVel, target2, ref m_currentTurnVelChange, 0.5f, 99f);
+ m_zanim.SetFloat(forward_speed, IsPlayer() ? num3 : num4);
+ m_zanim.SetFloat(sideway_speed, value);
+ m_zanim.SetFloat(turn_speed, m_currentTurnVel);
+ m_zanim.SetBool(inWater, !flag);
+ m_zanim.SetBool(onGround, value: false);
+ m_zanim.SetBool(encumbered, value: false);
+ m_zanim.SetBool(flying, value: false);
+ if (!flag)
+ {
+ OnSwiming(vector, dt);
+ }
+ }
+
+ private void UpdateFlying(float dt)
+ {
+ float num = (m_run ? m_flyFastSpeed : m_flySlowSpeed) * GetAttackSpeedFactorMovement();
+ Vector3 b = (CanMove() ? (m_moveDir * num) : Vector3.zero);
+ m_currentVel = Vector3.Lerp(m_currentVel, b, m_acceleration);
+ m_maxAirAltitude = base.transform.position.y;
+ ApplyRootMotion(ref m_currentVel);
+ AddPushbackForce(ref m_currentVel);
+ Vector3 force = m_currentVel - m_body.velocity;
+ if (force.magnitude > 20f)
+ {
+ force = force.normalized * 20f;
+ }
+ m_body.AddForce(force, ForceMode.VelocityChange);
+ float target = 0f;
+ if ((m_moveDir.magnitude > 0.1f || AlwaysRotateCamera()) && !InDodge() && CanMove())
+ {
+ float speed = m_flyTurnSpeed;
+ m_seman.ApplyStatusEffectSpeedMods(ref speed);
+ target = UpdateRotation(speed, dt);
+ }
+ m_body.angularVelocity = Vector3.zero;
+ UpdateEyeRotation();
+ m_body.useGravity = false;
+ float num2 = Vector3.Dot(m_currentVel, base.transform.forward);
+ float value = Vector3.Dot(m_currentVel, base.transform.right);
+ float num3 = Vector3.Dot(m_body.velocity, base.transform.forward);
+ m_currentTurnVel = Mathf.SmoothDamp(m_currentTurnVel, target, ref m_currentTurnVelChange, 0.5f, 99f);
+ m_zanim.SetFloat(forward_speed, IsPlayer() ? num2 : num3);
+ m_zanim.SetFloat(sideway_speed, value);
+ m_zanim.SetFloat(turn_speed, m_currentTurnVel);
+ m_zanim.SetBool(inWater, value: false);
+ m_zanim.SetBool(onGround, value: false);
+ m_zanim.SetBool(encumbered, value: false);
+ m_zanim.SetBool(flying, value: true);
+ }
+
+ private void UpdateWalking(float dt)
+ {
+ Vector3 moveDir = m_moveDir;
+ bool flag = IsCrouching();
+ m_running = CheckRun(moveDir, dt);
+ float num = m_speed * GetJogSpeedFactor();
+ if ((m_walk || InMinorAction()) && !flag)
+ {
+ num = m_walkSpeed;
+ }
+ else if (m_running)
+ {
+ bool num2 = InWaterDepth() > 0.4f;
+ float num3 = m_runSpeed * GetRunSpeedFactor();
+ num = (num2 ? Mathf.Lerp(num, num3, 0.33f) : num3);
+ if (IsPlayer() && moveDir.magnitude > 0f)
+ {
+ moveDir.Normalize();
+ }
+ }
+ else if (flag || IsEncumbered())
+ {
+ num = m_crouchSpeed;
+ }
+ num *= GetAttackSpeedFactorMovement();
+ m_seman.ApplyStatusEffectSpeedMods(ref num);
+ Vector3 vector = (CanMove() ? (moveDir * num) : Vector3.zero);
+ if (vector.magnitude > 0f && IsOnGround())
+ {
+ vector = Vector3.ProjectOnPlane(vector, m_lastGroundNormal).normalized * vector.magnitude;
+ }
+ float magnitude = vector.magnitude;
+ float magnitude2 = m_currentVel.magnitude;
+ if (magnitude > magnitude2)
+ {
+ magnitude = Mathf.MoveTowards(magnitude2, magnitude, m_acceleration);
+ vector = vector.normalized * magnitude;
+ }
+ else if (IsPlayer())
+ {
+ magnitude = Mathf.MoveTowards(magnitude2, magnitude, m_acceleration * 2f);
+ vector = ((vector.magnitude > 0f) ? (vector.normalized * magnitude) : (m_currentVel.normalized * magnitude));
+ }
+ m_currentVel = Vector3.Lerp(m_currentVel, vector, 0.5f);
+ Vector3 velocity = m_body.velocity;
+ Vector3 vel = m_currentVel;
+ vel.y = velocity.y;
+ if (IsOnGround() && m_lastAttachBody == null)
+ {
+ ApplySlide(dt, ref vel, velocity, m_running);
+ }
+ ApplyRootMotion(ref vel);
+ AddPushbackForce(ref vel);
+ ApplyGroundForce(ref vel, vector);
+ Vector3 vector2 = vel - velocity;
+ if (!IsOnGround())
+ {
+ if (vector.magnitude > 0.1f)
+ {
+ vector2 *= m_airControl;
+ }
+ else
+ {
+ vector2 = Vector3.zero;
+ }
+ }
+ if (IsAttached())
+ {
+ vector2 = Vector3.zero;
+ }
+ if (IsSneaking())
+ {
+ OnSneaking(dt);
+ }
+ if (vector2.magnitude > 20f)
+ {
+ vector2 = vector2.normalized * 20f;
+ }
+ if (vector2.magnitude > 0.01f)
+ {
+ m_body.AddForce(vector2, ForceMode.VelocityChange);
+ }
+ if ((bool)m_lastGroundBody && m_lastGroundBody.gameObject.layer != base.gameObject.layer && m_lastGroundBody.mass > m_body.mass)
+ {
+ float num4 = m_body.mass / m_lastGroundBody.mass;
+ m_lastGroundBody.AddForceAtPosition(-vector2 * num4, base.transform.position, ForceMode.VelocityChange);
+ }
+ float target = 0f;
+ if ((moveDir.magnitude > 0.1f || AlwaysRotateCamera()) && !InDodge() && CanMove())
+ {
+ float speed = (m_run ? m_runTurnSpeed : m_turnSpeed);
+ m_seman.ApplyStatusEffectSpeedMods(ref speed);
+ target = UpdateRotation(speed, dt);
+ }
+ UpdateEyeRotation();
+ m_body.useGravity = true;
+ float num5 = Vector3.Dot(m_currentVel, Vector3.ProjectOnPlane(base.transform.forward, m_lastGroundNormal).normalized);
+ float value = Vector3.Dot(m_currentVel, Vector3.ProjectOnPlane(base.transform.right, m_lastGroundNormal).normalized);
+ float num6 = Vector3.Dot(m_body.velocity, base.transform.forward);
+ m_currentTurnVel = Mathf.SmoothDamp(m_currentTurnVel, target, ref m_currentTurnVelChange, 0.5f, 99f);
+ m_zanim.SetFloat(forward_speed, IsPlayer() ? num5 : num6);
+ m_zanim.SetFloat(sideway_speed, value);
+ m_zanim.SetFloat(turn_speed, m_currentTurnVel);
+ m_zanim.SetBool(inWater, value: false);
+ m_zanim.SetBool(onGround, IsOnGround());
+ m_zanim.SetBool(encumbered, IsEncumbered());
+ m_zanim.SetBool(flying, value: false);
+ if (m_currentVel.magnitude > 0.1f)
+ {
+ if (m_running)
+ {
+ AddNoise(30f);
+ }
+ else if (!flag)
+ {
+ AddNoise(15f);
+ }
+ }
+ }
+
+ public bool IsSneaking()
+ {
+ if (IsCrouching() && m_currentVel.magnitude > 0.1f)
+ {
+ return IsOnGround();
+ }
+ return false;
+ }
+
+ private float GetSlopeAngle()
+ {
+ if (!IsOnGround())
+ {
+ return 0f;
+ }
+ float num = Vector3.SignedAngle(base.transform.forward, m_lastGroundNormal, base.transform.right);
+ return 0f - (90f - (0f - num));
+ }
+
+ protected void AddPushbackForce(ref Vector3 velocity)
+ {
+ if (m_pushForce != Vector3.zero)
+ {
+ Vector3 normalized = m_pushForce.normalized;
+ float num = Vector3.Dot(normalized, velocity);
+ if (num < 10f)
+ {
+ velocity += normalized * (10f - num);
+ }
+ if (IsSwiming() || m_flying)
+ {
+ velocity *= 0.5f;
+ }
+ }
+ }
+
+ private void ApplyPushback(HitData hit)
+ {
+ if (hit.m_pushForce != 0f)
+ {
+ float num = Mathf.Min(40f, hit.m_pushForce / m_body.mass * 5f);
+ Vector3 pushForce = hit.m_dir * num;
+ pushForce.y = 0f;
+ if (m_pushForce.magnitude < pushForce.magnitude)
+ {
+ m_pushForce = pushForce;
+ }
+ }
+ }
+
+ private void UpdatePushback(float dt)
+ {
+ m_pushForce = Vector3.MoveTowards(m_pushForce, Vector3.zero, 100f * dt);
+ }
+
+ private void ApplyGroundForce(ref Vector3 vel, Vector3 targetVel)
+ {
+ Vector3 vector = Vector3.zero;
+ if (IsOnGround() && (bool)m_lastGroundBody)
+ {
+ vector = m_lastGroundBody.GetPointVelocity(base.transform.position);
+ vector.y = 0f;
+ }
+ Ship standingOnShip = GetStandingOnShip();
+ if (standingOnShip != null)
+ {
+ if (targetVel.magnitude > 0.01f)
+ {
+ m_lastAttachBody = null;
+ }
+ else if (m_lastAttachBody != m_lastGroundBody)
+ {
+ m_lastAttachBody = m_lastGroundBody;
+ m_lastAttachPos = m_lastAttachBody.transform.InverseTransformPoint(m_body.position);
+ }
+ if ((bool)m_lastAttachBody)
+ {
+ Vector3 vector2 = m_lastAttachBody.transform.TransformPoint(m_lastAttachPos);
+ Vector3 vector3 = vector2 - m_body.position;
+ if (vector3.magnitude < 4f)
+ {
+ Vector3 position = vector2;
+ position.y = m_body.position.y;
+ if (standingOnShip.IsOwner())
+ {
+ vector3.y = 0f;
+ vector += vector3 * 10f;
+ }
+ else
+ {
+ m_body.position = position;
+ }
+ }
+ else
+ {
+ m_lastAttachBody = null;
+ }
+ }
+ }
+ else
+ {
+ m_lastAttachBody = null;
+ }
+ vel += vector;
+ }
+
+ private float UpdateRotation(float turnSpeed, float dt)
+ {
+ Quaternion quaternion = (AlwaysRotateCamera() ? m_lookYaw : Quaternion.LookRotation(m_moveDir));
+ float yawDeltaAngle = Utils.GetYawDeltaAngle(base.transform.rotation, quaternion);
+ float num = 1f;
+ if (!IsPlayer())
+ {
+ num = Mathf.Clamp01(Mathf.Abs(yawDeltaAngle) / 90f);
+ num = Mathf.Pow(num, 0.5f);
+ }
+ float num2 = turnSpeed * GetAttackSpeedFactorRotation() * num;
+ Quaternion rotation = Quaternion.RotateTowards(base.transform.rotation, quaternion, num2 * dt);
+ if (Mathf.Abs(yawDeltaAngle) > 0.001f)
+ {
+ base.transform.rotation = rotation;
+ }
+ return num2 * Mathf.Sign(yawDeltaAngle) * ((float)Math.PI / 180f);
+ }
+
+ private void UpdateGroundTilt(float dt)
+ {
+ if (m_visual == null)
+ {
+ return;
+ }
+ if (m_nview.IsOwner())
+ {
+ if (m_groundTilt != 0)
+ {
+ if (!IsFlying() && IsOnGround())
+ {
+ Vector3 vector = m_lastGroundNormal;
+ if (m_groundTilt == GroundTiltType.PitchRaycast || m_groundTilt == GroundTiltType.FullRaycast)
+ {
+ Vector3 p = base.transform.position + base.transform.forward * m_collider.radius;
+ Vector3 p2 = base.transform.position - base.transform.forward * m_collider.radius;
+ ZoneSystem.instance.GetSolidHeight(p, out var _, out var normal);
+ ZoneSystem.instance.GetSolidHeight(p2, out var _, out var normal2);
+ vector = (vector + normal + normal2).normalized;
+ }
+ Vector3 target = base.transform.InverseTransformVector(vector);
+ target = Vector3.RotateTowards(Vector3.up, target, 0.87266463f, 1f);
+ m_groundTiltNormal = Vector3.Lerp(m_groundTiltNormal, target, 0.05f);
+ Vector3 vector3;
+ if (m_groundTilt == GroundTiltType.Pitch || m_groundTilt == GroundTiltType.PitchRaycast)
+ {
+ Vector3 vector2 = Vector3.Project(m_groundTiltNormal, Vector3.right);
+ vector3 = m_groundTiltNormal - vector2;
+ }
+ else
+ {
+ vector3 = m_groundTiltNormal;
+ }
+ Vector3 forward = Vector3.Cross(vector3, Vector3.left);
+ m_visual.transform.localRotation = Quaternion.LookRotation(forward, vector3);
+ }
+ else
+ {
+ m_visual.transform.localRotation = Quaternion.RotateTowards(m_visual.transform.localRotation, Quaternion.identity, dt * 200f);
+ }
+ m_nview.GetZDO().Set("tiltrot", m_visual.transform.localRotation);
+ }
+ else if (CanWallRun())
+ {
+ if (m_wallRunning)
+ {
+ Vector3 vector4 = Vector3.Lerp(Vector3.up, m_lastGroundNormal, 0.65f);
+ Vector3 forward2 = Vector3.ProjectOnPlane(base.transform.forward, vector4);
+ forward2.Normalize();
+ Quaternion to = Quaternion.LookRotation(forward2, vector4);
+ m_visual.transform.rotation = Quaternion.RotateTowards(m_visual.transform.rotation, to, 30f * dt);
+ }
+ else
+ {
+ m_visual.transform.localRotation = Quaternion.RotateTowards(m_visual.transform.localRotation, Quaternion.identity, 100f * dt);
+ }
+ m_nview.GetZDO().Set("tiltrot", m_visual.transform.localRotation);
+ }
+ }
+ else if (m_groundTilt != 0 || CanWallRun())
+ {
+ Quaternion quaternion = m_nview.GetZDO().GetQuaternion("tiltrot", Quaternion.identity);
+ m_visual.transform.localRotation = quaternion;
+ }
+ }
+
+ public bool IsWallRunning()
+ {
+ return m_wallRunning;
+ }
+
+ private bool IsOnSnow()
+ {
+ return false;
+ }
+
+ public void Heal(float hp, bool showText = true)
+ {
+ if (!(hp <= 0f))
+ {
+ if (m_nview.IsOwner())
+ {
+ RPC_Heal(0L, hp, showText);
+ return;
+ }
+ m_nview.InvokeRPC("Heal", hp, showText);
+ }
+ }
+
+ private void RPC_Heal(long sender, float hp, bool showText)
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ float health = GetHealth();
+ if (health <= 0f || IsDead())
+ {
+ return;
+ }
+ float num = Mathf.Min(health + hp, GetMaxHealth());
+ if (num > health)
+ {
+ SetHealth(num);
+ if (showText)
+ {
+ Vector3 topPoint = GetTopPoint();
+ DamageText.instance.ShowText(DamageText.TextType.Heal, topPoint, hp, IsPlayer());
+ }
+ }
+ }
+
+ public Vector3 GetTopPoint()
+ {
+ Vector3 center = m_collider.bounds.center;
+ center.y = m_collider.bounds.max.y;
+ return center;
+ }
+
+ public float GetRadius()
+ {
+ return m_collider.radius;
+ }
+
+ public Vector3 GetHeadPoint()
+ {
+ return m_head.position;
+ }
+
+ public Vector3 GetEyePoint()
+ {
+ return m_eye.position;
+ }
+
+ public Vector3 GetCenterPoint()
+ {
+ return m_collider.bounds.center;
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Character;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("Damage", hit);
+ }
+ }
+
+ private void RPC_Damage(long sender, HitData hit)
+ {
+ if (IsDebugFlying() || !m_nview.IsOwner() || GetHealth() <= 0f || IsDead() || IsTeleporting() || InCutscene() || (hit.m_dodgeable && IsDodgeInvincible()))
+ {
+ return;
+ }
+ Character attacker = hit.GetAttacker();
+ if ((hit.HaveAttacker() && attacker == null) || (IsPlayer() && !IsPVPEnabled() && attacker != null && attacker.IsPlayer()))
+ {
+ return;
+ }
+ if (attacker != null && !attacker.IsPlayer())
+ {
+ float difficultyDamageScale = Game.instance.GetDifficultyDamageScale(base.transform.position);
+ hit.ApplyModifier(difficultyDamageScale);
+ }
+ m_seman.OnDamaged(hit, attacker);
+ if (m_baseAI != null && !m_baseAI.IsAlerted() && hit.m_backstabBonus > 1f && Time.time - m_backstabTime > 300f)
+ {
+ m_backstabTime = Time.time;
+ hit.ApplyModifier(hit.m_backstabBonus);
+ m_backstabHitEffects.Create(hit.m_point, Quaternion.identity, base.transform);
+ }
+ if (IsStaggering() && !IsPlayer())
+ {
+ hit.ApplyModifier(2f);
+ m_critHitEffects.Create(hit.m_point, Quaternion.identity, base.transform);
+ }
+ if (hit.m_blockable && IsBlocking())
+ {
+ BlockAttack(hit, attacker);
+ }
+ ApplyPushback(hit);
+ if (!string.IsNullOrEmpty(hit.m_statusEffect))
+ {
+ StatusEffect statusEffect = m_seman.GetStatusEffect(hit.m_statusEffect);
+ if (statusEffect == null)
+ {
+ statusEffect = m_seman.AddStatusEffect(hit.m_statusEffect);
+ }
+ if (statusEffect != null && attacker != null)
+ {
+ statusEffect.SetAttacker(attacker);
+ }
+ }
+ HitData.DamageModifiers damageModifiers = GetDamageModifiers();
+ hit.ApplyResistance(damageModifiers, out var significantModifier);
+ if (IsPlayer())
+ {
+ float bodyArmor = GetBodyArmor();
+ hit.ApplyArmor(bodyArmor);
+ DamageArmorDurability(hit);
+ }
+ float poison = hit.m_damage.m_poison;
+ float fire = hit.m_damage.m_fire;
+ float spirit = hit.m_damage.m_spirit;
+ hit.m_damage.m_poison = 0f;
+ hit.m_damage.m_fire = 0f;
+ hit.m_damage.m_spirit = 0f;
+ ApplyDamage(hit, showDamageText: true, triggerEffects: true, significantModifier);
+ AddFireDamage(fire);
+ AddSpiritDamage(spirit);
+ AddPoisonDamage(poison);
+ AddFrostDamage(hit.m_damage.m_frost);
+ AddLightningDamage(hit.m_damage.m_lightning);
+ }
+
+ protected HitData.DamageModifier GetDamageModifier(HitData.DamageType damageType)
+ {
+ return GetDamageModifiers().GetModifier(damageType);
+ }
+
+ protected HitData.DamageModifiers GetDamageModifiers()
+ {
+ HitData.DamageModifiers mods = m_damageModifiers.Clone();
+ ApplyArmorDamageMods(ref mods);
+ m_seman.ApplyDamageMods(ref mods);
+ return mods;
+ }
+
+ public void ApplyDamage(HitData hit, bool showDamageText, bool triggerEffects, HitData.DamageModifier mod = HitData.DamageModifier.Normal)
+ {
+ if (IsDebugFlying() || IsDead() || IsTeleporting() || InCutscene())
+ {
+ return;
+ }
+ float totalDamage = hit.GetTotalDamage();
+ if (showDamageText && (totalDamage > 0f || !IsPlayer()))
+ {
+ DamageText.instance.ShowText(mod, hit.m_point, totalDamage, IsPlayer());
+ }
+ if (!(totalDamage <= 0f))
+ {
+ if (!InGodMode() && !InGhostMode())
+ {
+ float health = GetHealth();
+ health -= totalDamage;
+ SetHealth(health);
+ }
+ AddStaggerDamage(totalDamage * hit.m_staggerMultiplier, hit.m_dir);
+ if (triggerEffects && totalDamage > 2f)
+ {
+ DoDamageCameraShake(hit);
+ m_hitEffects.Create(hit.m_point, Quaternion.identity, base.transform);
+ }
+ OnDamaged(hit);
+ if (m_onDamaged != null)
+ {
+ m_onDamaged(totalDamage, hit.GetAttacker());
+ }
+ if (m_dpsDebugEnabled)
+ {
+ AddDPS(totalDamage, this);
+ }
+ }
+ }
+
+ protected virtual void DoDamageCameraShake(HitData hit)
+ {
+ }
+
+ protected virtual void DamageArmorDurability(HitData hit)
+ {
+ }
+
+ private void AddFireDamage(float damage)
+ {
+ if (!(damage <= 0f))
+ {
+ SE_Burning sE_Burning = m_seman.GetStatusEffect("Burning") as SE_Burning;
+ if (sE_Burning == null)
+ {
+ sE_Burning = m_seman.AddStatusEffect("Burning") as SE_Burning;
+ }
+ sE_Burning.AddFireDamage(damage);
+ }
+ }
+
+ private void AddSpiritDamage(float damage)
+ {
+ if (!(damage <= 0f))
+ {
+ SE_Burning sE_Burning = m_seman.GetStatusEffect("Spirit") as SE_Burning;
+ if (sE_Burning == null)
+ {
+ sE_Burning = m_seman.AddStatusEffect("Spirit") as SE_Burning;
+ }
+ sE_Burning.AddSpiritDamage(damage);
+ }
+ }
+
+ private void AddPoisonDamage(float damage)
+ {
+ if (!(damage <= 0f))
+ {
+ SE_Poison sE_Poison = m_seman.GetStatusEffect("Poison") as SE_Poison;
+ if (sE_Poison == null)
+ {
+ sE_Poison = m_seman.AddStatusEffect("Poison") as SE_Poison;
+ }
+ sE_Poison.AddDamage(damage);
+ }
+ }
+
+ private void AddFrostDamage(float damage)
+ {
+ if (!(damage <= 0f))
+ {
+ SE_Frost sE_Frost = m_seman.GetStatusEffect("Frost") as SE_Frost;
+ if (sE_Frost == null)
+ {
+ sE_Frost = m_seman.AddStatusEffect("Frost") as SE_Frost;
+ }
+ sE_Frost.AddDamage(damage);
+ }
+ }
+
+ private void AddLightningDamage(float damage)
+ {
+ if (!(damage <= 0f))
+ {
+ m_seman.AddStatusEffect("Lightning", resetTime: true);
+ }
+ }
+
+ private void AddStaggerDamage(float damage, Vector3 forceDirection)
+ {
+ if (!(m_staggerDamageFactor <= 0f) || IsPlayer())
+ {
+ m_staggerDamage += damage;
+ m_staggerTimer = 0f;
+ float maxHealth = GetMaxHealth();
+ float num = (IsPlayer() ? (maxHealth / 2f) : (maxHealth * m_staggerDamageFactor));
+ if (m_staggerDamage >= num)
+ {
+ m_staggerDamage = 0f;
+ Stagger(forceDirection);
+ }
+ }
+ }
+
+ private static void AddDPS(float damage, Character me)
+ {
+ if (me == Player.m_localPlayer)
+ {
+ CalculateDPS("To-you ", m_playerDamage, damage);
+ }
+ else
+ {
+ CalculateDPS("To-others ", m_enemyDamage, damage);
+ }
+ }
+
+ private static void CalculateDPS(string name, List<KeyValuePair<float, float>> damages, float damage)
+ {
+ float time = Time.time;
+ if (damages.Count > 0 && Time.time - damages[damages.Count - 1].Key > 5f)
+ {
+ damages.Clear();
+ }
+ damages.Add(new KeyValuePair<float, float>(time, damage));
+ float num = Time.time - damages[0].Key;
+ if (num < 0.01f)
+ {
+ return;
+ }
+ float num2 = 0f;
+ foreach (KeyValuePair<float, float> damage2 in damages)
+ {
+ num2 += damage2.Value;
+ }
+ float num3 = num2 / num;
+ string text = "DPS " + name + " (" + damages.Count + " attacks): " + num3.ToString("0.0");
+ ZLog.Log(text);
+ MessageHud.instance.ShowMessage(MessageHud.MessageType.Center, text);
+ }
+
+ private void UpdateStagger(float dt)
+ {
+ if (!(m_staggerDamageFactor <= 0f) || IsPlayer())
+ {
+ m_staggerTimer += dt;
+ if (m_staggerTimer > 3f)
+ {
+ m_staggerDamage = 0f;
+ }
+ }
+ }
+
+ public void Stagger(Vector3 forceDirection)
+ {
+ if (m_nview.IsOwner())
+ {
+ RPC_Stagger(0L, forceDirection);
+ return;
+ }
+ m_nview.InvokeRPC("Stagger", forceDirection);
+ }
+
+ private void RPC_Stagger(long sender, Vector3 forceDirection)
+ {
+ if (!IsStaggering())
+ {
+ if (forceDirection.magnitude > 0.01f)
+ {
+ forceDirection.y = 0f;
+ base.transform.rotation = Quaternion.LookRotation(-forceDirection);
+ }
+ m_zanim.SetTrigger("stagger");
+ }
+ }
+
+ protected virtual void ApplyArmorDamageMods(ref HitData.DamageModifiers mods)
+ {
+ }
+
+ public virtual float GetBodyArmor()
+ {
+ return 0f;
+ }
+
+ protected virtual bool BlockAttack(HitData hit, Character attacker)
+ {
+ return false;
+ }
+
+ protected virtual void OnDamaged(HitData hit)
+ {
+ }
+
+ private void OnCollisionStay(Collision collision)
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner() || m_jumpTimer < 0.1f)
+ {
+ return;
+ }
+ ContactPoint[] contacts = collision.contacts;
+ for (int i = 0; i < contacts.Length; i++)
+ {
+ ContactPoint contactPoint = contacts[i];
+ float num = contactPoint.point.y - base.transform.position.y;
+ if (!(contactPoint.normal.y > 0.1f) || !(num < m_collider.radius))
+ {
+ continue;
+ }
+ if (contactPoint.normal.y > m_groundContactNormal.y || !m_groundContact)
+ {
+ m_groundContact = true;
+ m_groundContactNormal = contactPoint.normal;
+ m_groundContactPoint = contactPoint.point;
+ m_lowestContactCollider = collision.collider;
+ continue;
+ }
+ Vector3 groundContactNormal = Vector3.Normalize(m_groundContactNormal + contactPoint.normal);
+ if (groundContactNormal.y > m_groundContactNormal.y)
+ {
+ m_groundContactNormal = groundContactNormal;
+ m_groundContactPoint = (m_groundContactPoint + contactPoint.point) * 0.5f;
+ }
+ }
+ }
+
+ private void UpdateGroundContact(float dt)
+ {
+ if (!m_groundContact)
+ {
+ return;
+ }
+ m_lastGroundCollider = m_lowestContactCollider;
+ m_lastGroundNormal = m_groundContactNormal;
+ m_lastGroundPoint = m_groundContactPoint;
+ m_lastGroundBody = (m_lastGroundCollider ? m_lastGroundCollider.attachedRigidbody : null);
+ if (!IsPlayer() && m_lastGroundBody != null && m_lastGroundBody.gameObject.layer == base.gameObject.layer)
+ {
+ m_lastGroundCollider = null;
+ m_lastGroundBody = null;
+ }
+ float num = Mathf.Max(0f, m_maxAirAltitude - base.transform.position.y);
+ if (num > 0.8f)
+ {
+ if (m_onLand != null)
+ {
+ Vector3 lastGroundPoint = m_lastGroundPoint;
+ if (InWater())
+ {
+ lastGroundPoint.y = m_waterLevel;
+ }
+ m_onLand(m_lastGroundPoint);
+ }
+ ResetCloth();
+ }
+ if (IsPlayer() && num > 4f)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = Mathf.Clamp01((num - 4f) / 16f) * 100f;
+ hitData.m_point = m_lastGroundPoint;
+ hitData.m_dir = m_lastGroundNormal;
+ Damage(hitData);
+ }
+ ResetGroundContact();
+ m_lastGroundTouch = 0f;
+ m_maxAirAltitude = base.transform.position.y;
+ }
+
+ private void ResetGroundContact()
+ {
+ m_lowestContactCollider = null;
+ m_groundContact = false;
+ m_groundContactNormal = Vector3.zero;
+ m_groundContactPoint = Vector3.zero;
+ }
+
+ public Ship GetStandingOnShip()
+ {
+ if (!IsOnGround())
+ {
+ return null;
+ }
+ if ((bool)m_lastGroundBody)
+ {
+ return m_lastGroundBody.GetComponent<Ship>();
+ }
+ return null;
+ }
+
+ public bool IsOnGround()
+ {
+ if (!(m_lastGroundTouch < 0.2f))
+ {
+ return m_body.IsSleeping();
+ }
+ return true;
+ }
+
+ private void CheckDeath()
+ {
+ if (!IsDead() && GetHealth() <= 0f)
+ {
+ OnDeath();
+ if (m_onDeath != null)
+ {
+ m_onDeath();
+ }
+ }
+ }
+
+ protected virtual void OnRagdollCreated(Ragdoll ragdoll)
+ {
+ }
+
+ protected virtual void OnDeath()
+ {
+ GameObject[] array = m_deathEffects.Create(base.transform.position, base.transform.rotation, base.transform);
+ for (int i = 0; i < array.Length; i++)
+ {
+ Ragdoll component = array[i].GetComponent<Ragdoll>();
+ if ((bool)component)
+ {
+ CharacterDrop component2 = GetComponent<CharacterDrop>();
+ LevelEffects componentInChildren = GetComponentInChildren<LevelEffects>();
+ Vector3 velocity = m_body.velocity;
+ if (m_pushForce.magnitude * 0.5f > velocity.magnitude)
+ {
+ velocity = m_pushForce * 0.5f;
+ }
+ float hue = 0f;
+ float saturation = 0f;
+ float value = 0f;
+ if ((bool)componentInChildren)
+ {
+ componentInChildren.GetColorChanges(out hue, out saturation, out value);
+ }
+ component.Setup(velocity, hue, saturation, value, component2);
+ OnRagdollCreated(component);
+ if ((bool)component2)
+ {
+ component2.SetDropsEnabled(enabled: false);
+ }
+ }
+ }
+ if (!string.IsNullOrEmpty(m_defeatSetGlobalKey))
+ {
+ ZoneSystem.instance.SetGlobalKey(m_defeatSetGlobalKey);
+ }
+ ZNetScene.instance.Destroy(base.gameObject);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Killed", m_name, 0L);
+ }
+
+ public float GetHealth()
+ {
+ return m_nview.GetZDO()?.GetFloat("health", GetMaxHealth()) ?? GetMaxHealth();
+ }
+
+ public void SetHealth(float health)
+ {
+ ZDO zDO = m_nview.GetZDO();
+ if (zDO != null && m_nview.IsOwner())
+ {
+ if (health < 0f)
+ {
+ health = 0f;
+ }
+ zDO.Set("health", health);
+ }
+ }
+
+ public float GetHealthPercentage()
+ {
+ return GetHealth() / GetMaxHealth();
+ }
+
+ public virtual bool IsDead()
+ {
+ return false;
+ }
+
+ public void SetMaxHealth(float health)
+ {
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("max_health", health);
+ }
+ if (GetHealth() > health)
+ {
+ SetHealth(health);
+ }
+ }
+
+ public float GetMaxHealth()
+ {
+ if (m_nview.GetZDO() != null)
+ {
+ return m_nview.GetZDO().GetFloat("max_health", m_health);
+ }
+ return m_health;
+ }
+
+ public virtual float GetMaxStamina()
+ {
+ return 0f;
+ }
+
+ public virtual float GetStaminaPercentage()
+ {
+ return 1f;
+ }
+
+ public bool IsBoss()
+ {
+ return m_boss;
+ }
+
+ public void SetLookDir(Vector3 dir)
+ {
+ if (dir.magnitude <= Mathf.Epsilon)
+ {
+ dir = base.transform.forward;
+ }
+ else
+ {
+ dir.Normalize();
+ }
+ m_lookDir = dir;
+ dir.y = 0f;
+ m_lookYaw = Quaternion.LookRotation(dir);
+ }
+
+ public Vector3 GetLookDir()
+ {
+ return m_eye.forward;
+ }
+
+ public virtual void OnAttackTrigger()
+ {
+ }
+
+ public virtual void OnStopMoving()
+ {
+ }
+
+ public virtual void OnWeaponTrailStart()
+ {
+ }
+
+ public void SetMoveDir(Vector3 dir)
+ {
+ m_moveDir = dir;
+ }
+
+ public void SetRun(bool run)
+ {
+ m_run = run;
+ }
+
+ public void SetWalk(bool walk)
+ {
+ m_walk = walk;
+ }
+
+ public bool GetWalk()
+ {
+ return m_walk;
+ }
+
+ protected virtual void UpdateEyeRotation()
+ {
+ m_eye.rotation = Quaternion.LookRotation(m_lookDir);
+ }
+
+ public void OnAutoJump(Vector3 dir, float upVel, float forwardVel)
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && IsOnGround() && !IsDead() && !InAttack() && !InDodge() && !IsKnockedBack() && !(Time.time - m_lastAutoJumpTime < 0.5f))
+ {
+ m_lastAutoJumpTime = Time.time;
+ if (!(Vector3.Dot(m_moveDir, dir) < 0.5f))
+ {
+ Vector3 zero = Vector3.zero;
+ zero.y = upVel;
+ zero += dir * forwardVel;
+ m_body.velocity = zero;
+ m_lastGroundTouch = 1f;
+ m_jumpTimer = 0f;
+ m_jumpEffects.Create(base.transform.position, base.transform.rotation, base.transform);
+ SetCrouch(crouch: false);
+ UpdateBodyFriction();
+ }
+ }
+ }
+
+ public void Jump()
+ {
+ if (!IsOnGround() || IsDead() || InAttack() || IsEncumbered() || InDodge() || IsKnockedBack())
+ {
+ return;
+ }
+ bool flag = false;
+ if (!HaveStamina(m_jumpStaminaUsage))
+ {
+ if (IsPlayer())
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ flag = true;
+ }
+ float num = 0f;
+ Skills skills = GetSkills();
+ if (skills != null)
+ {
+ num = skills.GetSkillFactor(Skills.SkillType.Jump);
+ if (!flag)
+ {
+ RaiseSkill(Skills.SkillType.Jump);
+ }
+ }
+ Vector3 velocity = m_body.velocity;
+ Mathf.Acos(Mathf.Clamp01(m_lastGroundNormal.y));
+ Vector3 normalized = (m_lastGroundNormal + Vector3.up).normalized;
+ float num2 = 1f + num * 0.4f;
+ float num3 = m_jumpForce * num2;
+ float num4 = Vector3.Dot(normalized, velocity);
+ if (num4 < num3)
+ {
+ velocity += normalized * (num3 - num4);
+ }
+ velocity += m_moveDir * m_jumpForceForward * num2;
+ if (flag)
+ {
+ velocity *= m_jumpForceTiredFactor;
+ }
+ m_body.WakeUp();
+ m_body.velocity = velocity;
+ ResetGroundContact();
+ m_lastGroundTouch = 1f;
+ m_jumpTimer = 0f;
+ m_zanim.SetTrigger("jump");
+ AddNoise(30f);
+ m_jumpEffects.Create(base.transform.position, base.transform.rotation, base.transform);
+ OnJump();
+ SetCrouch(crouch: false);
+ UpdateBodyFriction();
+ }
+
+ private void UpdateBodyFriction()
+ {
+ m_collider.material.frictionCombine = PhysicMaterialCombine.Multiply;
+ if (IsDead())
+ {
+ m_collider.material.staticFriction = 1f;
+ m_collider.material.dynamicFriction = 1f;
+ m_collider.material.frictionCombine = PhysicMaterialCombine.Maximum;
+ }
+ else if (IsSwiming())
+ {
+ m_collider.material.staticFriction = 0.2f;
+ m_collider.material.dynamicFriction = 0.2f;
+ }
+ else if (!IsOnGround())
+ {
+ m_collider.material.staticFriction = 0f;
+ m_collider.material.dynamicFriction = 0f;
+ }
+ else if (IsFlying())
+ {
+ m_collider.material.staticFriction = 0f;
+ m_collider.material.dynamicFriction = 0f;
+ }
+ else if (m_moveDir.magnitude < 0.1f)
+ {
+ m_collider.material.staticFriction = 0.8f * (1f - m_slippage);
+ m_collider.material.dynamicFriction = 0.8f * (1f - m_slippage);
+ m_collider.material.frictionCombine = PhysicMaterialCombine.Maximum;
+ }
+ else
+ {
+ m_collider.material.staticFriction = 0.4f * (1f - m_slippage);
+ m_collider.material.dynamicFriction = 0.4f * (1f - m_slippage);
+ }
+ }
+
+ public virtual bool StartAttack(Character target, bool charge)
+ {
+ return false;
+ }
+
+ public virtual void OnNearFire(Vector3 point)
+ {
+ }
+
+ public ZDOID GetZDOID()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.GetZDO().m_uid;
+ }
+ return ZDOID.None;
+ }
+
+ public bool IsOwner()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.IsOwner();
+ }
+ return false;
+ }
+
+ public long GetOwner()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.GetZDO().m_owner;
+ }
+ return 0L;
+ }
+
+ public virtual bool UseMeleeCamera()
+ {
+ return false;
+ }
+
+ public virtual bool AlwaysRotateCamera()
+ {
+ return true;
+ }
+
+ public void SetInWater(float depth)
+ {
+ m_waterLevel = depth;
+ }
+
+ public virtual bool IsPVPEnabled()
+ {
+ return false;
+ }
+
+ public virtual bool InIntro()
+ {
+ return false;
+ }
+
+ public virtual bool InCutscene()
+ {
+ return false;
+ }
+
+ public virtual bool IsCrouching()
+ {
+ return false;
+ }
+
+ public virtual bool InBed()
+ {
+ return false;
+ }
+
+ public virtual bool IsAttached()
+ {
+ return false;
+ }
+
+ protected virtual void SetCrouch(bool crouch)
+ {
+ }
+
+ public virtual void AttachStart(Transform attachPoint, bool hideWeapons, bool isBed, string attachAnimation, Vector3 detachOffset)
+ {
+ }
+
+ public virtual void AttachStop()
+ {
+ }
+
+ private void UpdateWater(float dt)
+ {
+ m_swimTimer += dt;
+ if (InWaterSwimDepth())
+ {
+ if (m_nview.IsOwner())
+ {
+ m_seman.AddStatusEffect("Wet", resetTime: true);
+ }
+ if (m_canSwim)
+ {
+ m_swimTimer = 0f;
+ }
+ }
+ }
+
+ public bool IsSwiming()
+ {
+ return m_swimTimer < 0.5f;
+ }
+
+ public bool InWaterSwimDepth()
+ {
+ return InWaterDepth() > Mathf.Max(0f, m_swimDepth - 0.4f);
+ }
+
+ private float InWaterDepth()
+ {
+ if (GetStandingOnShip() != null)
+ {
+ return 0f;
+ }
+ return Mathf.Max(0f, m_waterLevel - base.transform.position.y);
+ }
+
+ public bool InWater()
+ {
+ return InWaterDepth() > 0f;
+ }
+
+ protected virtual bool CheckRun(Vector3 moveDir, float dt)
+ {
+ if (!m_run)
+ {
+ return false;
+ }
+ if (moveDir.magnitude < 0.1f)
+ {
+ return false;
+ }
+ if (IsCrouching() || IsEncumbered())
+ {
+ return false;
+ }
+ if (InDodge())
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool IsRunning()
+ {
+ return m_running;
+ }
+
+ public virtual bool InPlaceMode()
+ {
+ return false;
+ }
+
+ public virtual bool HaveStamina(float amount = 0f)
+ {
+ return true;
+ }
+
+ public virtual void AddStamina(float v)
+ {
+ }
+
+ public virtual void UseStamina(float stamina)
+ {
+ }
+
+ public bool IsStaggering()
+ {
+ return m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagStagger;
+ }
+
+ public virtual bool CanMove()
+ {
+ AnimatorStateInfo animatorStateInfo = (m_animator.IsInTransition(0) ? m_animator.GetNextAnimatorStateInfo(0) : m_animator.GetCurrentAnimatorStateInfo(0));
+ if (animatorStateInfo.tagHash == m_animatorTagFreeze || animatorStateInfo.tagHash == m_animatorTagStagger || animatorStateInfo.tagHash == m_animatorTagSitting)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public virtual bool IsEncumbered()
+ {
+ return false;
+ }
+
+ public virtual bool IsTeleporting()
+ {
+ return false;
+ }
+
+ private bool CanWallRun()
+ {
+ return IsPlayer();
+ }
+
+ public void ShowPickupMessage(ItemDrop.ItemData item, int amount)
+ {
+ Message(MessageHud.MessageType.TopLeft, "$msg_added " + item.m_shared.m_name, amount, item.GetIcon());
+ }
+
+ public void ShowRemovedMessage(ItemDrop.ItemData item, int amount)
+ {
+ Message(MessageHud.MessageType.TopLeft, "$msg_removed " + item.m_shared.m_name, amount, item.GetIcon());
+ }
+
+ public virtual void Message(MessageHud.MessageType type, string msg, int amount = 0, Sprite icon = null)
+ {
+ }
+
+ public CapsuleCollider GetCollider()
+ {
+ return m_collider;
+ }
+
+ public virtual void OnStealthSuccess(Character character, float factor)
+ {
+ }
+
+ public virtual float GetStealthFactor()
+ {
+ return 1f;
+ }
+
+ private void UpdateNoise(float dt)
+ {
+ m_noiseRange = Mathf.Max(0f, m_noiseRange - dt * 4f);
+ m_syncNoiseTimer += dt;
+ if (m_syncNoiseTimer > 0.5f)
+ {
+ m_syncNoiseTimer = 0f;
+ m_nview.GetZDO().Set("noise", m_noiseRange);
+ }
+ }
+
+ public void AddNoise(float range)
+ {
+ if (m_nview.IsValid())
+ {
+ if (m_nview.IsOwner())
+ {
+ RPC_AddNoise(0L, range);
+ return;
+ }
+ m_nview.InvokeRPC("AddNoise", range);
+ }
+ }
+
+ private void RPC_AddNoise(long sender, float range)
+ {
+ if (m_nview.IsOwner() && range > m_noiseRange)
+ {
+ m_noiseRange = range;
+ m_seman.ModifyNoise(m_noiseRange, ref m_noiseRange);
+ }
+ }
+
+ public float GetNoiseRange()
+ {
+ if (!m_nview.IsValid())
+ {
+ return 0f;
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_noiseRange;
+ }
+ return m_nview.GetZDO().GetFloat("noise");
+ }
+
+ public virtual bool InGodMode()
+ {
+ return false;
+ }
+
+ public virtual bool InGhostMode()
+ {
+ return false;
+ }
+
+ public virtual bool IsDebugFlying()
+ {
+ return false;
+ }
+
+ public virtual string GetHoverText()
+ {
+ Tameable component = GetComponent<Tameable>();
+ if ((bool)component)
+ {
+ return component.GetHoverText();
+ }
+ return "";
+ }
+
+ public virtual string GetHoverName()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ public virtual bool IsHoldingAttack()
+ {
+ return false;
+ }
+
+ public virtual bool InAttack()
+ {
+ return false;
+ }
+
+ protected virtual void StopEmote()
+ {
+ }
+
+ public virtual bool InMinorAction()
+ {
+ return false;
+ }
+
+ public virtual bool InDodge()
+ {
+ return false;
+ }
+
+ public virtual bool IsDodgeInvincible()
+ {
+ return false;
+ }
+
+ public virtual bool InEmote()
+ {
+ return false;
+ }
+
+ public virtual bool IsBlocking()
+ {
+ return false;
+ }
+
+ public bool IsFlying()
+ {
+ return m_flying;
+ }
+
+ public bool IsKnockedBack()
+ {
+ return m_pushForce != Vector3.zero;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ if (m_nview != null && m_nview.GetZDO() != null)
+ {
+ float @float = m_nview.GetZDO().GetFloat("noise");
+ Gizmos.DrawWireSphere(base.transform.position, @float);
+ }
+ Gizmos.color = Color.blue;
+ Gizmos.DrawWireCube(base.transform.position + Vector3.up * m_swimDepth, new Vector3(1f, 0.05f, 1f));
+ if (IsOnGround())
+ {
+ Gizmos.color = Color.green;
+ Gizmos.DrawLine(m_lastGroundPoint, m_lastGroundPoint + m_lastGroundNormal);
+ }
+ }
+
+ public virtual bool TeleportTo(Vector3 pos, Quaternion rot, bool distantTeleport)
+ {
+ return false;
+ }
+
+ private void SyncVelocity()
+ {
+ m_nview.GetZDO().Set("BodyVelocity", m_body.velocity);
+ }
+
+ public Vector3 GetVelocity()
+ {
+ if (!m_nview.IsValid())
+ {
+ return Vector3.zero;
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_body.velocity;
+ }
+ return m_nview.GetZDO().GetVec3("BodyVelocity", Vector3.zero);
+ }
+
+ public void AddRootMotion(Vector3 vel)
+ {
+ if (InDodge() || InAttack() || InEmote())
+ {
+ m_rootMotion += vel;
+ }
+ }
+
+ private void ApplyRootMotion(ref Vector3 vel)
+ {
+ Vector3 vector = m_rootMotion * 55f;
+ if (vector.magnitude > vel.magnitude)
+ {
+ vel = vector;
+ }
+ m_rootMotion = Vector3.zero;
+ }
+
+ public static void GetCharactersInRange(Vector3 point, float radius, List<Character> characters)
+ {
+ foreach (Character character in m_characters)
+ {
+ if (Vector3.Distance(character.transform.position, point) < radius)
+ {
+ characters.Add(character);
+ }
+ }
+ }
+
+ public static List<Character> GetAllCharacters()
+ {
+ return m_characters;
+ }
+
+ public static bool IsCharacterInRange(Vector3 point, float range)
+ {
+ foreach (Character character in m_characters)
+ {
+ if (Vector3.Distance(character.transform.position, point) < range)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public virtual void OnTargeted(bool sensed, bool alerted)
+ {
+ }
+
+ public GameObject GetVisual()
+ {
+ return m_visual;
+ }
+
+ protected void UpdateLodgroup()
+ {
+ if (!(m_lodGroup == null))
+ {
+ Renderer[] componentsInChildren = m_visual.GetComponentsInChildren<Renderer>();
+ LOD[] lODs = m_lodGroup.GetLODs();
+ lODs[0].renderers = componentsInChildren;
+ m_lodGroup.SetLODs(lODs);
+ }
+ }
+
+ public virtual float GetEquipmentMovementModifier()
+ {
+ return 0f;
+ }
+
+ protected virtual float GetJogSpeedFactor()
+ {
+ return 1f;
+ }
+
+ protected virtual float GetRunSpeedFactor()
+ {
+ return 1f;
+ }
+
+ protected virtual float GetAttackSpeedFactorMovement()
+ {
+ return 1f;
+ }
+
+ protected virtual float GetAttackSpeedFactorRotation()
+ {
+ return 1f;
+ }
+
+ public virtual void RaiseSkill(Skills.SkillType skill, float value = 1f)
+ {
+ }
+
+ public virtual Skills GetSkills()
+ {
+ return null;
+ }
+
+ public virtual float GetSkillFactor(Skills.SkillType skill)
+ {
+ return 0f;
+ }
+
+ public virtual float GetRandomSkillFactor(Skills.SkillType skill)
+ {
+ return UnityEngine.Random.Range(0.75f, 1f);
+ }
+
+ public bool IsMonsterFaction()
+ {
+ if (IsTamed())
+ {
+ return false;
+ }
+ if (m_faction != Faction.ForestMonsters && m_faction != Faction.Undead && m_faction != Faction.Demon && m_faction != Faction.PlainsMonsters && m_faction != Faction.MountainMonsters)
+ {
+ return m_faction == Faction.SeaMonsters;
+ }
+ return true;
+ }
+
+ public Transform GetTransform()
+ {
+ if (this == null)
+ {
+ return null;
+ }
+ return base.transform;
+ }
+
+ public Collider GetLastGroundCollider()
+ {
+ return m_lastGroundCollider;
+ }
+
+ public Vector3 GetLastGroundNormal()
+ {
+ return m_groundContactNormal;
+ }
+
+ public void ResetCloth()
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "ResetCloth");
+ }
+
+ private void RPC_ResetCloth(long sender)
+ {
+ Cloth[] componentsInChildren = GetComponentsInChildren<Cloth>();
+ foreach (Cloth cloth in componentsInChildren)
+ {
+ if (cloth.enabled)
+ {
+ cloth.enabled = false;
+ cloth.enabled = true;
+ }
+ }
+ }
+
+ public virtual bool GetRelativePosition(out ZDOID parent, out Vector3 relativePos, out Vector3 relativeVel)
+ {
+ relativeVel = Vector3.zero;
+ if (IsOnGround() && (bool)m_lastGroundBody)
+ {
+ ZNetView component = m_lastGroundBody.GetComponent<ZNetView>();
+ if ((bool)component && component.IsValid())
+ {
+ parent = component.GetZDO().m_uid;
+ relativePos = component.transform.InverseTransformPoint(base.transform.position);
+ relativeVel = component.transform.InverseTransformVector(m_body.velocity - m_lastGroundBody.velocity);
+ return true;
+ }
+ }
+ parent = ZDOID.None;
+ relativePos = Vector3.zero;
+ return false;
+ }
+
+ public Quaternion GetLookYaw()
+ {
+ return m_lookYaw;
+ }
+
+ public Vector3 GetMoveDir()
+ {
+ return m_moveDir;
+ }
+
+ public BaseAI GetBaseAI()
+ {
+ return m_baseAI;
+ }
+
+ public float GetMass()
+ {
+ return m_body.mass;
+ }
+
+ protected void SetVisible(bool visible)
+ {
+ if (!(m_lodGroup == null) && m_lodVisible != visible)
+ {
+ m_lodVisible = visible;
+ if (m_lodVisible)
+ {
+ m_lodGroup.localReferencePoint = m_originalLocalRef;
+ }
+ else
+ {
+ m_lodGroup.localReferencePoint = new Vector3(999999f, 999999f, 999999f);
+ }
+ }
+ }
+
+ public void SetTamed(bool tamed)
+ {
+ if (m_nview.IsValid() && m_tamed != tamed)
+ {
+ m_nview.InvokeRPC("SetTamed", tamed);
+ }
+ }
+
+ private void RPC_SetTamed(long sender, bool tamed)
+ {
+ if (m_nview.IsOwner() && m_tamed != tamed)
+ {
+ m_tamed = tamed;
+ m_nview.GetZDO().Set("tamed", m_tamed);
+ }
+ }
+
+ public bool IsTamed()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ if (!m_nview.IsOwner() && Time.time - m_lastTamedCheck > 1f)
+ {
+ m_lastTamedCheck = Time.time;
+ m_tamed = m_nview.GetZDO().GetBool("tamed", m_tamed);
+ }
+ return m_tamed;
+ }
+
+ public SEMan GetSEMan()
+ {
+ return m_seman;
+ }
+
+ public bool InInterior()
+ {
+ return base.transform.position.y > 3000f;
+ }
+
+ public static void SetDPSDebug(bool enabled)
+ {
+ m_dpsDebugEnabled = enabled;
+ }
+
+ public static bool IsDPSDebugEnabled()
+ {
+ return m_dpsDebugEnabled;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterAnimEvent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterAnimEvent.cs
new file mode 100644
index 0000000..8f0db87
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterAnimEvent.cs
@@ -0,0 +1,525 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class CharacterAnimEvent : MonoBehaviour
+{
+ [Serializable]
+ public class Foot
+ {
+ public Transform m_transform;
+
+ public AvatarIKGoal m_ikHandle;
+
+ public float m_footDownMax = 0.4f;
+
+ public float m_footOffset = 0.1f;
+
+ public float m_footStepHeight = 1f;
+
+ public float m_stabalizeDistance;
+
+ [NonSerialized]
+ public float m_ikWeight;
+
+ [NonSerialized]
+ public Vector3 m_plantPosition = Vector3.zero;
+
+ [NonSerialized]
+ public Vector3 m_plantNormal = Vector3.up;
+
+ [NonSerialized]
+ public bool m_isPlanted;
+
+ public Foot(Transform t, AvatarIKGoal handle)
+ {
+ m_transform = t;
+ m_ikHandle = handle;
+ m_ikWeight = 0f;
+ }
+ }
+
+ [Header("Foot IK")]
+ public bool m_footIK;
+
+ public float m_footDownMax = 0.4f;
+
+ public float m_footOffset = 0.1f;
+
+ public float m_footStepHeight = 1f;
+
+ public float m_stabalizeDistance;
+
+ public bool m_useFeetValues;
+
+ public Foot[] m_feets = new Foot[0];
+
+ [Header("Head/eye rotation")]
+ public bool m_headRotation = true;
+
+ public Transform[] m_eyes;
+
+ public float m_lookWeight = 0.5f;
+
+ public float m_bodyLookWeight = 0.1f;
+
+ public float m_headLookWeight = 1f;
+
+ public float m_eyeLookWeight;
+
+ public float m_lookClamp = 0.5f;
+
+ private const float m_headRotationSmoothness = 0.1f;
+
+ public Transform m_lookAt;
+
+ [Header("Player Female hack")]
+ public bool m_femaleHack;
+
+ public Transform m_leftShoulder;
+
+ public Transform m_rightShoulder;
+
+ public float m_femaleOffset = 0.0004f;
+
+ public float m_maleOffset = 0.0007651657f;
+
+ private Character m_character;
+
+ private Animator m_animator;
+
+ private ZNetView m_nview;
+
+ private MonsterAI m_monsterAI;
+
+ private VisEquipment m_visEquipment;
+
+ private FootStep m_footStep;
+
+ private int m_chainID;
+
+ private float m_pauseTimer;
+
+ private float m_pauseSpeed = 1f;
+
+ private float m_sendTimer;
+
+ private Vector3 m_headLookDir;
+
+ private float m_lookAtWeight;
+
+ private Transform m_head;
+
+ private bool m_chain;
+
+ private static int m_ikGroundMask;
+
+ private void Awake()
+ {
+ m_character = GetComponentInParent<Character>();
+ m_nview = m_character.GetComponent<ZNetView>();
+ m_animator = GetComponent<Animator>();
+ m_monsterAI = m_character.GetComponent<MonsterAI>();
+ m_visEquipment = m_character.GetComponent<VisEquipment>();
+ m_footStep = m_character.GetComponent<FootStep>();
+ m_head = m_animator.GetBoneTransform(HumanBodyBones.Head);
+ m_chainID = Animator.StringToHash("chain");
+ m_headLookDir = m_character.transform.forward;
+ if (m_ikGroundMask == 0)
+ {
+ m_ikGroundMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain", "vehicle");
+ }
+ }
+
+ private void OnAnimatorMove()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ m_character.AddRootMotion(m_animator.deltaPosition);
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_character == null || !m_nview.IsValid())
+ {
+ return;
+ }
+ if (!m_character.InAttack() && !m_character.InMinorAction() && !m_character.InEmote() && m_character.CanMove())
+ {
+ m_animator.speed = 1f;
+ }
+ if (m_pauseTimer > 0f)
+ {
+ m_pauseTimer -= Time.fixedDeltaTime;
+ if (m_pauseTimer <= 0f)
+ {
+ m_animator.speed = m_pauseSpeed;
+ }
+ }
+ }
+
+ public bool CanChain()
+ {
+ return m_chain;
+ }
+
+ public void FreezeFrame(float delay)
+ {
+ if (delay <= 0f)
+ {
+ return;
+ }
+ if (m_pauseTimer > 0f)
+ {
+ m_pauseTimer = delay;
+ return;
+ }
+ m_pauseTimer = delay;
+ m_pauseSpeed = m_animator.speed;
+ m_animator.speed = 0.0001f;
+ if (m_pauseSpeed <= 0.01f)
+ {
+ m_pauseSpeed = 1f;
+ }
+ }
+
+ public void Speed(float speedScale)
+ {
+ m_animator.speed = speedScale;
+ }
+
+ public void Chain()
+ {
+ m_chain = true;
+ }
+
+ public void ResetChain()
+ {
+ m_chain = false;
+ }
+
+ public void FootStep(AnimationEvent e)
+ {
+ if (!((double)e.animatorClipInfo.weight < 0.33) && (bool)m_footStep)
+ {
+ if (e.stringParameter.Length > 0)
+ {
+ m_footStep.OnFoot(e.stringParameter);
+ }
+ else
+ {
+ m_footStep.OnFoot();
+ }
+ }
+ }
+
+ public void Hit()
+ {
+ m_character.OnAttackTrigger();
+ }
+
+ public void OnAttackTrigger()
+ {
+ m_character.OnAttackTrigger();
+ }
+
+ public void Stop(AnimationEvent e)
+ {
+ m_character.OnStopMoving();
+ }
+
+ public void DodgeMortal()
+ {
+ Player player = m_character as Player;
+ if ((bool)player)
+ {
+ player.OnDodgeMortal();
+ }
+ }
+
+ public void TrailOn()
+ {
+ if ((bool)m_visEquipment)
+ {
+ m_visEquipment.SetWeaponTrails(enabled: true);
+ }
+ m_character.OnWeaponTrailStart();
+ }
+
+ public void TrailOff()
+ {
+ if ((bool)m_visEquipment)
+ {
+ m_visEquipment.SetWeaponTrails(enabled: false);
+ }
+ }
+
+ public void GPower()
+ {
+ Player player = m_character as Player;
+ if ((bool)player)
+ {
+ player.ActivateGuardianPower();
+ }
+ }
+
+ private void OnAnimatorIK(int layerIndex)
+ {
+ if (m_nview.IsValid())
+ {
+ UpdateLookat();
+ UpdateFootIK();
+ }
+ }
+
+ private void LateUpdate()
+ {
+ UpdateHeadRotation(Time.deltaTime);
+ if (m_femaleHack)
+ {
+ _ = m_character;
+ float num = ((m_visEquipment.GetModelIndex() == 1) ? m_femaleOffset : m_maleOffset);
+ Vector3 localPosition = m_leftShoulder.localPosition;
+ localPosition.x = 0f - num;
+ m_leftShoulder.localPosition = localPosition;
+ Vector3 localPosition2 = m_rightShoulder.localPosition;
+ localPosition2.x = num;
+ m_rightShoulder.localPosition = localPosition2;
+ }
+ }
+
+ private void UpdateLookat()
+ {
+ if (m_headRotation && (bool)m_head)
+ {
+ float target = m_lookWeight;
+ if (m_headLookDir != Vector3.zero)
+ {
+ m_animator.SetLookAtPosition(m_head.position + m_headLookDir * 10f);
+ }
+ if (m_character.InAttack() || (!m_character.IsPlayer() && !m_character.CanMove()))
+ {
+ target = 0f;
+ }
+ m_lookAtWeight = Mathf.MoveTowards(m_lookAtWeight, target, Time.deltaTime);
+ float bodyWeight = (m_character.IsAttached() ? 0f : m_bodyLookWeight);
+ m_animator.SetLookAtWeight(m_lookAtWeight, bodyWeight, m_headLookWeight, m_eyeLookWeight, m_lookClamp);
+ }
+ }
+
+ private void UpdateFootIK()
+ {
+ if (!m_footIK)
+ {
+ return;
+ }
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null || Vector3.Distance(base.transform.position, mainCamera.transform.position) > 64f)
+ {
+ return;
+ }
+ if ((m_character.IsFlying() && !m_character.IsOnGround()) || (m_character.IsSwiming() && !m_character.IsOnGround()))
+ {
+ for (int i = 0; i < m_feets.Length; i++)
+ {
+ Foot foot = m_feets[i];
+ m_animator.SetIKPositionWeight(foot.m_ikHandle, 0f);
+ m_animator.SetIKRotationWeight(foot.m_ikHandle, 0f);
+ }
+ return;
+ }
+ float deltaTime = Time.deltaTime;
+ for (int j = 0; j < m_feets.Length; j++)
+ {
+ Foot foot2 = m_feets[j];
+ Vector3 position = foot2.m_transform.position;
+ AvatarIKGoal ikHandle = foot2.m_ikHandle;
+ float num = (m_useFeetValues ? foot2.m_footDownMax : m_footDownMax);
+ float num2 = (m_useFeetValues ? foot2.m_footOffset : m_footOffset);
+ float num3 = (m_useFeetValues ? foot2.m_footStepHeight : m_footStepHeight);
+ float num4 = (m_useFeetValues ? foot2.m_stabalizeDistance : m_stabalizeDistance);
+ float target = 1f - Mathf.Clamp01(base.transform.InverseTransformPoint(position - base.transform.up * num2).y / num);
+ foot2.m_ikWeight = Mathf.MoveTowards(foot2.m_ikWeight, target, deltaTime * 10f);
+ m_animator.SetIKPositionWeight(ikHandle, foot2.m_ikWeight);
+ m_animator.SetIKRotationWeight(ikHandle, foot2.m_ikWeight * 0.5f);
+ if (!(foot2.m_ikWeight > 0f))
+ {
+ continue;
+ }
+ if (Physics.Raycast(position + Vector3.up * num3, Vector3.down, out var hitInfo, num3 * 4f, m_ikGroundMask))
+ {
+ Vector3 vector = hitInfo.point + Vector3.up * num2;
+ Vector3 normal = hitInfo.normal;
+ if (num4 > 0f)
+ {
+ if (foot2.m_ikWeight >= 1f)
+ {
+ if (!foot2.m_isPlanted)
+ {
+ foot2.m_plantPosition = vector;
+ foot2.m_plantNormal = normal;
+ foot2.m_isPlanted = true;
+ }
+ else if (Vector3.Distance(foot2.m_plantPosition, vector) > num4)
+ {
+ foot2.m_isPlanted = false;
+ }
+ else
+ {
+ vector = foot2.m_plantPosition;
+ normal = foot2.m_plantNormal;
+ }
+ }
+ else
+ {
+ foot2.m_isPlanted = false;
+ }
+ }
+ m_animator.SetIKPosition(ikHandle, vector);
+ Quaternion goalRotation = Quaternion.LookRotation(Vector3.Cross(m_animator.GetIKRotation(ikHandle) * Vector3.right, hitInfo.normal), hitInfo.normal);
+ m_animator.SetIKRotation(ikHandle, goalRotation);
+ }
+ else
+ {
+ foot2.m_ikWeight = Mathf.MoveTowards(foot2.m_ikWeight, 0f, deltaTime * 4f);
+ m_animator.SetIKPositionWeight(ikHandle, foot2.m_ikWeight);
+ m_animator.SetIKRotationWeight(ikHandle, foot2.m_ikWeight * 0.5f);
+ }
+ }
+ }
+
+ private void UpdateHeadRotation(float dt)
+ {
+ if (m_nview == null || !m_nview.IsValid() || !m_headRotation || !m_head)
+ {
+ return;
+ }
+ Vector3 lookFromPos = GetLookFromPos();
+ Vector3 vector = Vector3.zero;
+ if (m_nview.IsOwner())
+ {
+ if (m_monsterAI != null)
+ {
+ Character targetCreature = m_monsterAI.GetTargetCreature();
+ if (targetCreature != null)
+ {
+ vector = targetCreature.GetEyePoint();
+ }
+ }
+ else
+ {
+ vector = lookFromPos + m_character.GetLookDir() * 100f;
+ }
+ if (m_lookAt != null)
+ {
+ vector = m_lookAt.position;
+ }
+ m_sendTimer += Time.deltaTime;
+ if (m_sendTimer > 0.2f)
+ {
+ m_sendTimer = 0f;
+ m_nview.GetZDO().Set("LookTarget", vector);
+ }
+ }
+ else
+ {
+ vector = m_nview.GetZDO().GetVec3("LookTarget", Vector3.zero);
+ }
+ if (vector != Vector3.zero)
+ {
+ Vector3 b = Vector3.Normalize(vector - lookFromPos);
+ m_headLookDir = Vector3.Lerp(m_headLookDir, b, 0.1f);
+ }
+ else
+ {
+ m_headLookDir = m_character.transform.forward;
+ }
+ }
+
+ private Vector3 GetLookFromPos()
+ {
+ if (m_eyes != null && m_eyes.Length != 0)
+ {
+ Vector3 zero = Vector3.zero;
+ Transform[] eyes = m_eyes;
+ foreach (Transform transform in eyes)
+ {
+ zero += transform.position;
+ }
+ return zero / m_eyes.Length;
+ }
+ return m_head.position;
+ }
+
+ public void FindJoints()
+ {
+ ZLog.Log("Finding joints");
+ List<Transform> list = new List<Transform>();
+ Transform transform = Utils.FindChild(base.transform, "LeftEye");
+ Transform transform2 = Utils.FindChild(base.transform, "RightEye");
+ if ((bool)transform)
+ {
+ list.Add(transform);
+ }
+ if ((bool)transform2)
+ {
+ list.Add(transform2);
+ }
+ m_eyes = list.ToArray();
+ Transform transform3 = Utils.FindChild(base.transform, "LeftFootFront");
+ Transform transform4 = Utils.FindChild(base.transform, "RightFootFront");
+ Transform transform5 = Utils.FindChild(base.transform, "LeftFoot");
+ if (transform5 == null)
+ {
+ transform5 = Utils.FindChild(base.transform, "LeftFootBack");
+ }
+ if (transform5 == null)
+ {
+ transform5 = Utils.FindChild(base.transform, "l_foot");
+ }
+ if (transform5 == null)
+ {
+ transform5 = Utils.FindChild(base.transform, "Foot.l");
+ }
+ if (transform5 == null)
+ {
+ transform5 = Utils.FindChild(base.transform, "foot.l");
+ }
+ Transform transform6 = Utils.FindChild(base.transform, "RightFoot");
+ if (transform6 == null)
+ {
+ transform6 = Utils.FindChild(base.transform, "RightFootBack");
+ }
+ if (transform6 == null)
+ {
+ transform6 = Utils.FindChild(base.transform, "r_foot");
+ }
+ if (transform6 == null)
+ {
+ transform6 = Utils.FindChild(base.transform, "Foot.r");
+ }
+ if (transform6 == null)
+ {
+ transform6 = Utils.FindChild(base.transform, "foot.r");
+ }
+ List<Foot> list2 = new List<Foot>();
+ if ((bool)transform3)
+ {
+ list2.Add(new Foot(transform3, AvatarIKGoal.LeftHand));
+ }
+ if ((bool)transform4)
+ {
+ list2.Add(new Foot(transform4, AvatarIKGoal.RightHand));
+ }
+ if ((bool)transform5)
+ {
+ list2.Add(new Foot(transform5, AvatarIKGoal.LeftFoot));
+ }
+ if ((bool)transform6)
+ {
+ list2.Add(new Foot(transform6, AvatarIKGoal.RightFoot));
+ }
+ m_feets = list2.ToArray();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterDrop.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterDrop.cs
new file mode 100644
index 0000000..89dfc87
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterDrop.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[RequireComponent(typeof(Character))]
+public class CharacterDrop : MonoBehaviour
+{
+ [Serializable]
+ public class Drop
+ {
+ public GameObject m_prefab;
+
+ public int m_amountMin = 1;
+
+ public int m_amountMax = 1;
+
+ public float m_chance = 1f;
+
+ public bool m_onePerPlayer;
+
+ public bool m_levelMultiplier = true;
+ }
+
+ public Vector3 m_spawnOffset = Vector3.zero;
+
+ public List<Drop> m_drops = new List<Drop>();
+
+ private const float m_dropArea = 0.5f;
+
+ private const float m_vel = 5f;
+
+ private bool m_dropsEnabled = true;
+
+ private Character m_character;
+
+ private void Start()
+ {
+ m_character = GetComponent<Character>();
+ if ((bool)m_character)
+ {
+ Character character = m_character;
+ character.m_onDeath = (Action)Delegate.Combine(character.m_onDeath, new Action(OnDeath));
+ }
+ }
+
+ public void SetDropsEnabled(bool enabled)
+ {
+ m_dropsEnabled = enabled;
+ }
+
+ private void OnDeath()
+ {
+ if (m_dropsEnabled)
+ {
+ List<KeyValuePair<GameObject, int>> drops = GenerateDropList();
+ Vector3 centerPos = m_character.GetCenterPoint() + base.transform.TransformVector(m_spawnOffset);
+ DropItems(drops, centerPos, 0.5f);
+ }
+ }
+
+ public List<KeyValuePair<GameObject, int>> GenerateDropList()
+ {
+ List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
+ int num = ((!m_character) ? 1 : Mathf.Max(1, (int)Mathf.Pow(2f, m_character.GetLevel() - 1)));
+ foreach (Drop drop in m_drops)
+ {
+ if (drop.m_prefab == null)
+ {
+ continue;
+ }
+ float num2 = drop.m_chance;
+ if (drop.m_levelMultiplier)
+ {
+ num2 *= (float)num;
+ }
+ if (UnityEngine.Random.value <= num2)
+ {
+ int num3 = UnityEngine.Random.Range(drop.m_amountMin, drop.m_amountMax);
+ if (drop.m_levelMultiplier)
+ {
+ num3 *= num;
+ }
+ if (drop.m_onePerPlayer)
+ {
+ num3 = ZNet.instance.GetNrOfPlayers();
+ }
+ if (num3 > 0)
+ {
+ list.Add(new KeyValuePair<GameObject, int>(drop.m_prefab, num3));
+ }
+ }
+ }
+ return list;
+ }
+
+ public static void DropItems(List<KeyValuePair<GameObject, int>> drops, Vector3 centerPos, float dropArea)
+ {
+ foreach (KeyValuePair<GameObject, int> drop in drops)
+ {
+ for (int i = 0; i < drop.Value; i++)
+ {
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ Vector3 vector = UnityEngine.Random.insideUnitSphere * dropArea;
+ GameObject gameObject = UnityEngine.Object.Instantiate(drop.Key, centerPos + vector, rotation);
+ Rigidbody component = gameObject.GetComponent<Rigidbody>();
+ if ((bool)component)
+ {
+ Vector3 insideUnitSphere = UnityEngine.Random.insideUnitSphere;
+ if (insideUnitSphere.y < 0f)
+ {
+ insideUnitSphere.y = 0f - insideUnitSphere.y;
+ }
+ component.AddForce(insideUnitSphere * 5f, ForceMode.VelocityChange);
+ }
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs
new file mode 100644
index 0000000..f4382e2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs
@@ -0,0 +1,48 @@
+using UnityEngine;
+
+public class CharacterTimedDestruction : MonoBehaviour
+{
+ public float m_timeoutMin = 1f;
+
+ public float m_timeoutMax = 1f;
+
+ public bool m_triggerOnAwake;
+
+ private ZNetView m_nview;
+
+ private Character m_character;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_triggerOnAwake)
+ {
+ Trigger();
+ }
+ }
+
+ public void Trigger()
+ {
+ InvokeRepeating("DestroyNow", Random.Range(m_timeoutMin, m_timeoutMax), 1f);
+ }
+
+ public void Trigger(float timeout)
+ {
+ InvokeRepeating("DestroyNow", timeout, 1f);
+ }
+
+ private void DestroyNow()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ GetComponent<Character>().ApplyDamage(new HitData
+ {
+ m_damage =
+ {
+ m_damage = 99999f
+ },
+ m_point = base.transform.position
+ }, showDamageText: false, triggerEffects: true);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chat.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chat.cs
new file mode 100644
index 0000000..4646819
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Chat.cs
@@ -0,0 +1,568 @@
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class Chat : MonoBehaviour
+{
+ public class WorldTextInstance
+ {
+ public long m_talkerID;
+
+ public GameObject m_go;
+
+ public Vector3 m_position;
+
+ public float m_timer;
+
+ public GameObject m_gui;
+
+ public Text m_textField;
+
+ public string m_name = "";
+
+ public Talker.Type m_type;
+
+ public string m_text = "";
+ }
+
+ public class NpcText
+ {
+ public GameObject m_go;
+
+ public Vector3 m_offset = Vector3.zero;
+
+ public float m_cullDistance = 20f;
+
+ public GameObject m_gui;
+
+ public Animator m_animator;
+
+ public Text m_textField;
+
+ public Text m_topicField;
+
+ public float m_ttl;
+
+ public bool m_timeout;
+
+ public void SetVisible(bool visible)
+ {
+ m_animator.SetBool("visible", visible);
+ }
+
+ public bool IsVisible()
+ {
+ if (m_animator.GetCurrentAnimatorStateInfo(0).IsTag("visible"))
+ {
+ return true;
+ }
+ return m_animator.GetBool("visible");
+ }
+ }
+
+ private static Chat m_instance;
+
+ public RectTransform m_chatWindow;
+
+ public Text m_output;
+
+ public InputField m_input;
+
+ public float m_hideDelay = 10f;
+
+ public float m_worldTextTTL = 5f;
+
+ public GameObject m_worldTextBase;
+
+ public GameObject m_npcTextBase;
+
+ public GameObject m_npcTextBaseLarge;
+
+ private List<WorldTextInstance> m_worldTexts = new List<WorldTextInstance>();
+
+ private List<NpcText> m_npcTexts = new List<NpcText>();
+
+ private float m_hideTimer = 9999f;
+
+ private bool m_wasFocused;
+
+ private const int m_maxBufferLength = 15;
+
+ private List<string> m_chatBuffer = new List<string>();
+
+ public static Chat instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ ZRoutedRpc.instance.Register<Vector3, int, string, string>("ChatMessage", RPC_ChatMessage);
+ AddString(Localization.instance.Localize("/w [text] - $chat_whisper"));
+ AddString(Localization.instance.Localize("/s [text] - $chat_shout"));
+ AddString(Localization.instance.Localize("/killme - $chat_kill"));
+ AddString(Localization.instance.Localize("/resetspawn - $chat_resetspawn"));
+ AddString(Localization.instance.Localize("/[emote]"));
+ AddString(Localization.instance.Localize("Emotes: sit,wave,challenge,cheer,nonono,thumbsup,point"));
+ AddString("");
+ m_input.gameObject.SetActive(value: false);
+ m_worldTextBase.SetActive(value: false);
+ }
+
+ public bool HasFocus()
+ {
+ if (m_chatWindow.gameObject.activeInHierarchy)
+ {
+ return m_input.isFocused;
+ }
+ return false;
+ }
+
+ public bool IsChatDialogWindowVisible()
+ {
+ return m_chatWindow.gameObject.activeSelf;
+ }
+
+ private void Update()
+ {
+ m_hideTimer += Time.deltaTime;
+ m_chatWindow.gameObject.SetActive(m_hideTimer < m_hideDelay);
+ if (!m_wasFocused)
+ {
+ if (Input.GetKeyDown(KeyCode.Return) && Player.m_localPlayer != null && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput() && !Menu.IsVisible())
+ {
+ m_hideTimer = 0f;
+ m_chatWindow.gameObject.SetActive(value: true);
+ m_input.gameObject.SetActive(value: true);
+ m_input.ActivateInputField();
+ }
+ }
+ else if (m_wasFocused)
+ {
+ m_hideTimer = 0f;
+ if (Input.GetKeyDown(KeyCode.Return))
+ {
+ if (!string.IsNullOrEmpty(m_input.text))
+ {
+ InputText();
+ m_input.text = "";
+ }
+ EventSystem.current.SetSelectedGameObject(null);
+ m_input.gameObject.SetActive(value: false);
+ }
+ }
+ m_wasFocused = m_input.isFocused;
+ }
+
+ private void LateUpdate()
+ {
+ UpdateWorldTexts(Time.deltaTime);
+ UpdateNpcTexts(Time.deltaTime);
+ }
+
+ private void UpdateChat()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ foreach (string item in m_chatBuffer)
+ {
+ stringBuilder.Append(item);
+ stringBuilder.Append("\n");
+ }
+ m_output.text = stringBuilder.ToString();
+ }
+
+ public void OnNewChatMessage(GameObject go, long senderID, Vector3 pos, Talker.Type type, string user, string text)
+ {
+ text = text.Replace('<', ' ');
+ text = text.Replace('>', ' ');
+ AddString(user, text, type);
+ AddInworldText(go, senderID, pos, type, user, text);
+ }
+
+ private void UpdateWorldTexts(float dt)
+ {
+ WorldTextInstance worldTextInstance = null;
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return;
+ }
+ foreach (WorldTextInstance worldText in m_worldTexts)
+ {
+ worldText.m_timer += dt;
+ if (worldText.m_timer > m_worldTextTTL && worldTextInstance == null)
+ {
+ worldTextInstance = worldText;
+ }
+ worldText.m_position.y += dt * 0.15f;
+ Vector3 zero = Vector3.zero;
+ if ((bool)worldText.m_go)
+ {
+ Character component = worldText.m_go.GetComponent<Character>();
+ zero = ((!component) ? (worldText.m_go.transform.position + Vector3.up * 0.3f) : (component.GetHeadPoint() + Vector3.up * 0.3f));
+ }
+ else
+ {
+ zero = worldText.m_position + Vector3.up * 0.3f;
+ }
+ Vector3 position = mainCamera.WorldToScreenPoint(zero);
+ if (position.x < 0f || position.x > (float)Screen.width || position.y < 0f || position.y > (float)Screen.height || position.z < 0f)
+ {
+ Vector3 vector = zero - mainCamera.transform.position;
+ bool flag = Vector3.Dot(mainCamera.transform.right, vector) < 0f;
+ Vector3 vector2 = vector;
+ vector2.y = 0f;
+ float magnitude = vector2.magnitude;
+ float y = vector.y;
+ Vector3 forward = mainCamera.transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ forward *= magnitude;
+ Vector3 vector3 = forward + Vector3.up * y;
+ position = mainCamera.WorldToScreenPoint(mainCamera.transform.position + vector3);
+ position.x = ((!flag) ? Screen.width : 0);
+ }
+ RectTransform rectTransform = worldText.m_gui.transform as RectTransform;
+ position.x = Mathf.Clamp(position.x, rectTransform.rect.width / 2f, (float)Screen.width - rectTransform.rect.width / 2f);
+ position.y = Mathf.Clamp(position.y, rectTransform.rect.height / 2f, (float)Screen.height - rectTransform.rect.height);
+ position.z = Mathf.Min(position.z, 100f);
+ worldText.m_gui.transform.position = position;
+ }
+ if (worldTextInstance != null)
+ {
+ Object.Destroy(worldTextInstance.m_gui);
+ m_worldTexts.Remove(worldTextInstance);
+ }
+ }
+
+ private void AddInworldText(GameObject go, long senderID, Vector3 position, Talker.Type type, string user, string text)
+ {
+ WorldTextInstance worldTextInstance = FindExistingWorldText(senderID);
+ if (worldTextInstance == null)
+ {
+ worldTextInstance = new WorldTextInstance();
+ worldTextInstance.m_talkerID = senderID;
+ worldTextInstance.m_gui = Object.Instantiate(m_worldTextBase, base.transform);
+ worldTextInstance.m_gui.gameObject.SetActive(value: true);
+ worldTextInstance.m_textField = worldTextInstance.m_gui.transform.Find("Text").GetComponent<Text>();
+ m_worldTexts.Add(worldTextInstance);
+ }
+ worldTextInstance.m_name = user;
+ worldTextInstance.m_type = type;
+ worldTextInstance.m_go = go;
+ worldTextInstance.m_position = position;
+ Color color;
+ switch (type)
+ {
+ case Talker.Type.Shout:
+ color = Color.yellow;
+ text = text.ToUpper();
+ break;
+ case Talker.Type.Whisper:
+ color = new Color(1f, 1f, 1f, 0.75f);
+ text = text.ToLowerInvariant();
+ break;
+ case Talker.Type.Ping:
+ color = new Color(0.6f, 0.7f, 1f, 1f);
+ text = "PING";
+ break;
+ default:
+ color = Color.white;
+ break;
+ }
+ worldTextInstance.m_textField.color = color;
+ worldTextInstance.m_textField.GetComponent<Outline>().enabled = type != Talker.Type.Whisper;
+ worldTextInstance.m_timer = 0f;
+ worldTextInstance.m_text = text;
+ UpdateWorldTextField(worldTextInstance);
+ }
+
+ private void UpdateWorldTextField(WorldTextInstance wt)
+ {
+ string text = "";
+ if (wt.m_type == Talker.Type.Shout || wt.m_type == Talker.Type.Ping)
+ {
+ text = wt.m_name + ": ";
+ }
+ text += wt.m_text;
+ wt.m_textField.text = text;
+ }
+
+ private WorldTextInstance FindExistingWorldText(long senderID)
+ {
+ foreach (WorldTextInstance worldText in m_worldTexts)
+ {
+ if (worldText.m_talkerID == senderID)
+ {
+ return worldText;
+ }
+ }
+ return null;
+ }
+
+ private void AddString(string user, string text, Talker.Type type)
+ {
+ Color white = Color.white;
+ switch (type)
+ {
+ case Talker.Type.Shout:
+ white = Color.yellow;
+ text = text.ToUpper();
+ break;
+ case Talker.Type.Whisper:
+ white = new Color(1f, 1f, 1f, 0.75f);
+ text = text.ToLowerInvariant();
+ break;
+ default:
+ white = Color.white;
+ break;
+ }
+ string text2 = "<color=orange>" + user + "</color>: <color=#" + ColorUtility.ToHtmlStringRGBA(white) + ">" + text + "</color>";
+ AddString(text2);
+ }
+
+ private void AddString(string text)
+ {
+ m_chatBuffer.Add(text);
+ while (m_chatBuffer.Count > 15)
+ {
+ m_chatBuffer.RemoveAt(0);
+ }
+ UpdateChat();
+ }
+
+ private void InputText()
+ {
+ string text = m_input.text;
+ if (text == "/resetspawn")
+ {
+ Game.instance.GetPlayerProfile()?.ClearCustomSpawnPoint();
+ AddString("Reseting spawn point");
+ return;
+ }
+ if (text == "/killme")
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 99999f;
+ Player.m_localPlayer.Damage(hitData);
+ SendText(Talker.Type.Normal, "I am off to valhalla");
+ return;
+ }
+ Talker.Type type = Talker.Type.Normal;
+ if (text.StartsWith("/s ") || text.StartsWith("/S "))
+ {
+ type = Talker.Type.Shout;
+ text = text.Substring(3);
+ }
+ if (text.StartsWith("/w ") || text.StartsWith("/W "))
+ {
+ type = Talker.Type.Whisper;
+ text = text.Substring(3);
+ }
+ if (text.StartsWith("/wave"))
+ {
+ Player.m_localPlayer.StartEmote("wave");
+ }
+ else if (text.StartsWith("/sit"))
+ {
+ Player.m_localPlayer.StartEmote("sit", oneshot: false);
+ }
+ else if (text.StartsWith("/challenge"))
+ {
+ Player.m_localPlayer.StartEmote("challenge");
+ }
+ else if (text.StartsWith("/cheer"))
+ {
+ Player.m_localPlayer.StartEmote("cheer");
+ }
+ else if (text.StartsWith("/nonono"))
+ {
+ Player.m_localPlayer.StartEmote("nonono");
+ }
+ else if (text.StartsWith("/thumbsup"))
+ {
+ Player.m_localPlayer.StartEmote("thumbsup");
+ }
+ else if (text.StartsWith("/point"))
+ {
+ Player.m_localPlayer.FaceLookDirection();
+ Player.m_localPlayer.StartEmote("point");
+ }
+ else
+ {
+ SendText(type, text);
+ }
+ }
+
+ private void RPC_ChatMessage(long sender, Vector3 position, int type, string name, string text)
+ {
+ OnNewChatMessage(null, sender, position, (Talker.Type)type, name, text);
+ }
+
+ public void SendText(Talker.Type type, string text)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ if (type == Talker.Type.Shout)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ChatMessage", localPlayer.GetHeadPoint(), 2, localPlayer.GetPlayerName(), text);
+ }
+ else
+ {
+ localPlayer.GetComponent<Talker>().Say(type, text);
+ }
+ }
+ }
+
+ public void SendPing(Vector3 position)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ Vector3 vector = position;
+ vector.y = localPlayer.transform.position.y;
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ChatMessage", vector, 3, localPlayer.GetPlayerName(), "");
+ }
+ }
+
+ public void GetShoutWorldTexts(List<WorldTextInstance> texts)
+ {
+ foreach (WorldTextInstance worldText in m_worldTexts)
+ {
+ if (worldText.m_type == Talker.Type.Shout)
+ {
+ texts.Add(worldText);
+ }
+ }
+ }
+
+ public void GetPingWorldTexts(List<WorldTextInstance> texts)
+ {
+ foreach (WorldTextInstance worldText in m_worldTexts)
+ {
+ if (worldText.m_type == Talker.Type.Ping)
+ {
+ texts.Add(worldText);
+ }
+ }
+ }
+
+ private void UpdateNpcTexts(float dt)
+ {
+ NpcText npcText = null;
+ Camera mainCamera = Utils.GetMainCamera();
+ foreach (NpcText npcText2 in m_npcTexts)
+ {
+ if (!npcText2.m_go)
+ {
+ npcText2.m_gui.SetActive(value: false);
+ if (npcText == null)
+ {
+ npcText = npcText2;
+ }
+ continue;
+ }
+ if (npcText2.m_timeout)
+ {
+ npcText2.m_ttl -= dt;
+ if (npcText2.m_ttl <= 0f)
+ {
+ npcText2.SetVisible(visible: false);
+ if (!npcText2.IsVisible())
+ {
+ npcText = npcText2;
+ }
+ continue;
+ }
+ }
+ Vector3 vector = npcText2.m_go.transform.position + npcText2.m_offset;
+ Vector3 position = mainCamera.WorldToScreenPoint(vector);
+ if (position.x < 0f || position.x > (float)Screen.width || position.y < 0f || position.y > (float)Screen.height || position.z < 0f)
+ {
+ npcText2.SetVisible(visible: false);
+ }
+ else
+ {
+ npcText2.SetVisible(visible: true);
+ RectTransform rectTransform = npcText2.m_gui.transform as RectTransform;
+ position.x = Mathf.Clamp(position.x, rectTransform.rect.width / 2f, (float)Screen.width - rectTransform.rect.width / 2f);
+ position.y = Mathf.Clamp(position.y, rectTransform.rect.height / 2f, (float)Screen.height - rectTransform.rect.height);
+ npcText2.m_gui.transform.position = position;
+ }
+ if (Vector3.Distance(mainCamera.transform.position, vector) > npcText2.m_cullDistance)
+ {
+ npcText2.SetVisible(visible: false);
+ if (npcText == null && !npcText2.IsVisible())
+ {
+ npcText = npcText2;
+ }
+ }
+ }
+ if (npcText != null)
+ {
+ ClearNpcText(npcText);
+ }
+ }
+
+ public void SetNpcText(GameObject talker, Vector3 offset, float cullDistance, float ttl, string topic, string text, bool large)
+ {
+ NpcText npcText = FindNpcText(talker);
+ if (npcText != null)
+ {
+ ClearNpcText(npcText);
+ }
+ npcText = new NpcText();
+ npcText.m_go = talker;
+ npcText.m_gui = Object.Instantiate(large ? m_npcTextBaseLarge : m_npcTextBase, base.transform);
+ npcText.m_gui.SetActive(value: true);
+ npcText.m_animator = npcText.m_gui.GetComponent<Animator>();
+ npcText.m_topicField = npcText.m_gui.transform.Find("Topic").GetComponent<Text>();
+ npcText.m_textField = npcText.m_gui.transform.Find("Text").GetComponent<Text>();
+ npcText.m_ttl = ttl;
+ npcText.m_timeout = ttl > 0f;
+ npcText.m_offset = offset;
+ npcText.m_cullDistance = cullDistance;
+ if (topic.Length > 0)
+ {
+ npcText.m_textField.text = "<color=orange>" + Localization.instance.Localize(topic) + "</color>\n" + Localization.instance.Localize(text);
+ }
+ else
+ {
+ npcText.m_textField.text = Localization.instance.Localize(text);
+ }
+ m_npcTexts.Add(npcText);
+ }
+
+ public bool IsDialogVisible(GameObject talker)
+ {
+ return FindNpcText(talker)?.IsVisible() ?? false;
+ }
+
+ public void ClearNpcText(GameObject talker)
+ {
+ NpcText npcText = FindNpcText(talker);
+ if (npcText != null)
+ {
+ ClearNpcText(npcText);
+ }
+ }
+
+ private void ClearNpcText(NpcText npcText)
+ {
+ Object.Destroy(npcText.m_gui);
+ m_npcTexts.Remove(npcText);
+ }
+
+ private NpcText FindNpcText(GameObject go)
+ {
+ foreach (NpcText npcText in m_npcTexts)
+ {
+ if (npcText.m_go == go)
+ {
+ return npcText;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CircleProjector.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CircleProjector.cs
new file mode 100644
index 0000000..a60fab6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CircleProjector.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class CircleProjector : MonoBehaviour
+{
+ public float m_radius = 5f;
+
+ public int m_nrOfSegments = 20;
+
+ public GameObject m_prefab;
+
+ public LayerMask m_mask;
+
+ private List<GameObject> m_segments = new List<GameObject>();
+
+ private void Start()
+ {
+ CreateSegments();
+ }
+
+ private void Update()
+ {
+ CreateSegments();
+ float num = (float)Math.PI * 2f / (float)m_segments.Count;
+ for (int i = 0; i < m_segments.Count; i++)
+ {
+ float f = (float)i * num + Time.time * 0.1f;
+ Vector3 vector = base.transform.position + new Vector3(Mathf.Sin(f) * m_radius, 0f, Mathf.Cos(f) * m_radius);
+ GameObject obj = m_segments[i];
+ if (Physics.Raycast(vector + Vector3.up * 500f, Vector3.down, out var hitInfo, 1000f, m_mask.value))
+ {
+ vector.y = hitInfo.point.y;
+ }
+ obj.transform.position = vector;
+ }
+ for (int j = 0; j < m_segments.Count; j++)
+ {
+ GameObject obj2 = m_segments[j];
+ GameObject gameObject = ((j == 0) ? m_segments[m_segments.Count - 1] : m_segments[j - 1]);
+ Vector3 normalized = (((j == m_segments.Count - 1) ? m_segments[0] : m_segments[j + 1]).transform.position - gameObject.transform.position).normalized;
+ obj2.transform.rotation = Quaternion.LookRotation(normalized, Vector3.up);
+ }
+ }
+
+ private void CreateSegments()
+ {
+ if (m_segments.Count == m_nrOfSegments)
+ {
+ return;
+ }
+ foreach (GameObject segment in m_segments)
+ {
+ UnityEngine.Object.Destroy(segment);
+ }
+ m_segments.Clear();
+ for (int i = 0; i < m_nrOfSegments; i++)
+ {
+ GameObject item = UnityEngine.Object.Instantiate(m_prefab, base.transform.position, Quaternion.identity, base.transform);
+ m_segments.Add(item);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ClutterSystem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ClutterSystem.cs
new file mode 100644
index 0000000..b08e638
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ClutterSystem.cs
@@ -0,0 +1,472 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+public class ClutterSystem : MonoBehaviour
+{
+ [Serializable]
+ public class Clutter
+ {
+ public string m_name = "";
+
+ public bool m_enabled = true;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ public bool m_instanced;
+
+ public GameObject m_prefab;
+
+ public int m_amount = 80;
+
+ public bool m_onUncleared = true;
+
+ public bool m_onCleared;
+
+ public float m_scaleMin = 1f;
+
+ public float m_scaleMax = 1f;
+
+ public float m_maxTilt = 18f;
+
+ public float m_maxAlt = 1000f;
+
+ public float m_minAlt = 27f;
+
+ public bool m_snapToWater;
+
+ public bool m_terrainTilt;
+
+ public float m_randomOffset;
+
+ [Header("Ocean depth ")]
+ public float m_minOceanDepth;
+
+ public float m_maxOceanDepth;
+
+ [Header("Forest fractal 0-1 inside forest")]
+ public bool m_inForest;
+
+ public float m_forestTresholdMin;
+
+ public float m_forestTresholdMax = 1f;
+
+ [Header("Fractal placement (m_fractalScale > 0 == enabled) ")]
+ public float m_fractalScale;
+
+ public float m_fractalOffset;
+
+ public float m_fractalTresholdMin = 0.5f;
+
+ public float m_fractalTresholdMax = 1f;
+ }
+
+ private class PatchData
+ {
+ public Vector3 center;
+
+ public List<GameObject> m_objects = new List<GameObject>();
+
+ public float m_timer;
+
+ public bool m_reset;
+ }
+
+ public enum Quality
+ {
+ Off,
+ Med,
+ High
+ }
+
+ private static ClutterSystem m_instance;
+
+ private int m_placeRayMask;
+
+ public List<Clutter> m_clutter = new List<Clutter>();
+
+ public float m_grassPatchSize = 8f;
+
+ public float m_distance = 40f;
+
+ public float m_waterLevel = 27f;
+
+ public float m_playerPushFade = 0.05f;
+
+ public float m_amountScale = 1f;
+
+ public bool m_menuHack;
+
+ private Dictionary<Vector2Int, PatchData> m_patches = new Dictionary<Vector2Int, PatchData>();
+
+ private Stack<PatchData> m_freePatches = new Stack<PatchData>();
+
+ private GameObject m_grassRoot;
+
+ private Vector3 m_oldPlayerPos = Vector3.zero;
+
+ private List<Vector2Int> m_tempToRemove = new List<Vector2Int>();
+
+ private List<KeyValuePair<Vector2Int, PatchData>> m_tempToRemovePair = new List<KeyValuePair<Vector2Int, PatchData>>();
+
+ private Quality m_quality = Quality.High;
+
+ private bool m_forceRebuild;
+
+ public static ClutterSystem instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null)
+ {
+ ApplySettings();
+ m_placeRayMask = LayerMask.GetMask("terrain");
+ m_grassRoot = new GameObject("grassroot");
+ m_grassRoot.transform.SetParent(base.transform);
+ }
+ }
+
+ public void ApplySettings()
+ {
+ Quality @int = (Quality)PlayerPrefs.GetInt("ClutterQuality", 2);
+ if (m_quality != @int)
+ {
+ m_quality = @int;
+ ClearAll();
+ }
+ }
+
+ private void LateUpdate()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return;
+ }
+ Vector3 center = ((!GameCamera.InFreeFly() && (bool)Player.m_localPlayer) ? Player.m_localPlayer.transform.position : mainCamera.transform.position);
+ if (m_forceRebuild)
+ {
+ if (IsHeightmapReady())
+ {
+ m_forceRebuild = false;
+ UpdateGrass(Time.deltaTime, rebuildAll: true, center);
+ }
+ }
+ else if (IsHeightmapReady())
+ {
+ UpdateGrass(Time.deltaTime, rebuildAll: false, center);
+ }
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer != null)
+ {
+ m_oldPlayerPos = Vector3.Lerp(m_oldPlayerPos, localPlayer.transform.position, m_playerPushFade);
+ Shader.SetGlobalVector("_PlayerPosition", localPlayer.transform.position);
+ Shader.SetGlobalVector("_PlayerOldPosition", m_oldPlayerPos);
+ }
+ else
+ {
+ Shader.SetGlobalVector("_PlayerPosition", new Vector3(999999f, 999999f, 999999f));
+ Shader.SetGlobalVector("_PlayerOldPosition", new Vector3(999999f, 999999f, 999999f));
+ }
+ }
+
+ public Vector2Int GetVegPatch(Vector3 point)
+ {
+ int x = Mathf.FloorToInt((point.x + m_grassPatchSize / 2f) / m_grassPatchSize);
+ int y = Mathf.FloorToInt((point.z + m_grassPatchSize / 2f) / m_grassPatchSize);
+ return new Vector2Int(x, y);
+ }
+
+ public Vector3 GetVegPatchCenter(Vector2Int p)
+ {
+ return new Vector3((float)p.x * m_grassPatchSize, 0f, (float)p.y * m_grassPatchSize);
+ }
+
+ private bool IsHeightmapReady()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!mainCamera)
+ {
+ return false;
+ }
+ if (Heightmap.HaveQueuedRebuild(mainCamera.transform.position, m_distance))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void UpdateGrass(float dt, bool rebuildAll, Vector3 center)
+ {
+ if (m_quality != 0)
+ {
+ GeneratePatches(rebuildAll, center);
+ TimeoutPatches(dt);
+ }
+ }
+
+ private void GeneratePatches(bool rebuildAll, Vector3 center)
+ {
+ bool generated = false;
+ Vector2Int vegPatch = GetVegPatch(center);
+ GeneratePatch(center, vegPatch, ref generated, rebuildAll);
+ int num = Mathf.CeilToInt((m_distance - m_grassPatchSize / 2f) / m_grassPatchSize);
+ for (int i = 1; i <= num; i++)
+ {
+ for (int j = vegPatch.x - i; j <= vegPatch.x + i; j++)
+ {
+ GeneratePatch(center, new Vector2Int(j, vegPatch.y - i), ref generated, rebuildAll);
+ GeneratePatch(center, new Vector2Int(j, vegPatch.y + i), ref generated, rebuildAll);
+ }
+ for (int k = vegPatch.y - i + 1; k <= vegPatch.y + i - 1; k++)
+ {
+ GeneratePatch(center, new Vector2Int(vegPatch.x - i, k), ref generated, rebuildAll);
+ GeneratePatch(center, new Vector2Int(vegPatch.x + i, k), ref generated, rebuildAll);
+ }
+ }
+ }
+
+ private void GeneratePatch(Vector3 camPos, Vector2Int p, ref bool generated, bool rebuildAll)
+ {
+ if (Utils.DistanceXZ(GetVegPatchCenter(p), camPos) > m_distance)
+ {
+ return;
+ }
+ if (m_patches.TryGetValue(p, out var value) && !value.m_reset)
+ {
+ value.m_timer = 0f;
+ }
+ else
+ {
+ if (!rebuildAll && generated && !m_menuHack)
+ {
+ return;
+ }
+ PatchData patchData = GenerateVegPatch(p, m_grassPatchSize);
+ if (patchData == null)
+ {
+ return;
+ }
+ if (m_patches.TryGetValue(p, out var value2))
+ {
+ foreach (GameObject @object in value2.m_objects)
+ {
+ UnityEngine.Object.Destroy(@object);
+ }
+ FreePatch(value2);
+ m_patches.Remove(p);
+ }
+ m_patches.Add(p, patchData);
+ generated = true;
+ }
+ }
+
+ private void TimeoutPatches(float dt)
+ {
+ m_tempToRemovePair.Clear();
+ foreach (KeyValuePair<Vector2Int, PatchData> patch in m_patches)
+ {
+ patch.Value.m_timer += dt;
+ if (patch.Value.m_timer >= 2f)
+ {
+ m_tempToRemovePair.Add(patch);
+ }
+ }
+ foreach (KeyValuePair<Vector2Int, PatchData> item in m_tempToRemovePair)
+ {
+ foreach (GameObject @object in item.Value.m_objects)
+ {
+ UnityEngine.Object.Destroy(@object);
+ }
+ m_patches.Remove(item.Key);
+ FreePatch(item.Value);
+ }
+ }
+
+ private void ClearAll()
+ {
+ foreach (KeyValuePair<Vector2Int, PatchData> patch in m_patches)
+ {
+ foreach (GameObject @object in patch.Value.m_objects)
+ {
+ UnityEngine.Object.Destroy(@object);
+ }
+ FreePatch(patch.Value);
+ }
+ m_patches.Clear();
+ m_forceRebuild = true;
+ }
+
+ public void ResetGrass(Vector3 center, float radius)
+ {
+ float num = m_grassPatchSize / 2f;
+ foreach (KeyValuePair<Vector2Int, PatchData> patch in m_patches)
+ {
+ Vector3 center2 = patch.Value.center;
+ if (!(center2.x + num < center.x - radius) && !(center2.x - num > center.x + radius) && !(center2.z + num < center.z - radius) && !(center2.z - num > center.z + radius))
+ {
+ patch.Value.m_reset = true;
+ m_forceRebuild = true;
+ }
+ }
+ }
+
+ public bool GetGroundInfo(Vector3 p, out Vector3 point, out Vector3 normal, out Heightmap hmap, out Heightmap.Biome biome)
+ {
+ if (Physics.Raycast(p + Vector3.up * 500f, Vector3.down, out var hitInfo, 1000f, m_placeRayMask))
+ {
+ point = hitInfo.point;
+ normal = hitInfo.normal;
+ hmap = hitInfo.collider.GetComponent<Heightmap>();
+ biome = hmap.GetBiome(point);
+ return true;
+ }
+ point = p;
+ normal = Vector3.up;
+ hmap = null;
+ biome = Heightmap.Biome.Meadows;
+ return false;
+ }
+
+ private Heightmap.Biome GetPatchBiomes(Vector3 center, float halfSize)
+ {
+ Heightmap.Biome biome = Heightmap.FindBiomeClutter(new Vector3(center.x - halfSize, 0f, center.z - halfSize));
+ Heightmap.Biome biome2 = Heightmap.FindBiomeClutter(new Vector3(center.x + halfSize, 0f, center.z - halfSize));
+ Heightmap.Biome biome3 = Heightmap.FindBiomeClutter(new Vector3(center.x - halfSize, 0f, center.z + halfSize));
+ Heightmap.Biome biome4 = Heightmap.FindBiomeClutter(new Vector3(center.x + halfSize, 0f, center.z + halfSize));
+ if (biome == Heightmap.Biome.None || biome2 == Heightmap.Biome.None || biome3 == Heightmap.Biome.None || biome4 == Heightmap.Biome.None)
+ {
+ return Heightmap.Biome.None;
+ }
+ return biome | biome2 | biome3 | biome4;
+ }
+
+ private PatchData GenerateVegPatch(Vector2Int patchID, float size)
+ {
+ Vector3 vegPatchCenter = GetVegPatchCenter(patchID);
+ float num = size / 2f;
+ Heightmap.Biome patchBiomes = GetPatchBiomes(vegPatchCenter, num);
+ if (patchBiomes == Heightmap.Biome.None)
+ {
+ return null;
+ }
+ _ = Time.realtimeSinceStartup;
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ PatchData patchData = AllocatePatch();
+ patchData.center = vegPatchCenter;
+ for (int i = 0; i < m_clutter.Count; i++)
+ {
+ Clutter clutter = m_clutter[i];
+ if (!clutter.m_enabled || (patchBiomes & clutter.m_biome) == 0)
+ {
+ continue;
+ }
+ InstanceRenderer instanceRenderer = null;
+ UnityEngine.Random.InitState(patchID.x * (patchID.y * 1374) + i * 9321);
+ Vector3 vector = new Vector3(clutter.m_fractalOffset, 0f, 0f);
+ float num2 = Mathf.Cos((float)Math.PI / 180f * clutter.m_maxTilt);
+ int num3 = ((m_quality == Quality.High) ? clutter.m_amount : (clutter.m_amount / 2));
+ num3 = (int)((float)num3 * m_amountScale);
+ for (int j = 0; j < num3; j++)
+ {
+ Vector3 vector2 = new Vector3(UnityEngine.Random.Range(vegPatchCenter.x - num, vegPatchCenter.x + num), 0f, UnityEngine.Random.Range(vegPatchCenter.z - num, vegPatchCenter.z + num));
+ float num4 = UnityEngine.Random.Range(0, 360);
+ if (clutter.m_inForest)
+ {
+ float forestFactor = WorldGenerator.GetForestFactor(vector2);
+ if (forestFactor < clutter.m_forestTresholdMin || forestFactor > clutter.m_forestTresholdMax)
+ {
+ continue;
+ }
+ }
+ if (clutter.m_fractalScale > 0f)
+ {
+ float num5 = Utils.Fbm(vector2 * 0.01f * clutter.m_fractalScale + vector, 3, 1.6f, 0.7f);
+ if (num5 < clutter.m_fractalTresholdMin || num5 > clutter.m_fractalTresholdMax)
+ {
+ continue;
+ }
+ }
+ if (!GetGroundInfo(vector2, out var point, out var normal, out var hmap, out var biome) || (clutter.m_biome & biome) == 0)
+ {
+ continue;
+ }
+ float num6 = point.y - m_waterLevel;
+ if (num6 < clutter.m_minAlt || num6 > clutter.m_maxAlt || normal.y < num2)
+ {
+ continue;
+ }
+ if (clutter.m_minOceanDepth != clutter.m_maxOceanDepth)
+ {
+ float oceanDepth = hmap.GetOceanDepth(vector2);
+ if (oceanDepth < clutter.m_minOceanDepth || oceanDepth > clutter.m_maxOceanDepth)
+ {
+ continue;
+ }
+ }
+ if (!clutter.m_onCleared || !clutter.m_onUncleared)
+ {
+ bool flag = hmap.IsCleared(point);
+ if ((clutter.m_onCleared && !flag) || (clutter.m_onUncleared && flag))
+ {
+ continue;
+ }
+ }
+ vector2 = point;
+ if (clutter.m_snapToWater)
+ {
+ vector2.y = m_waterLevel;
+ }
+ if (clutter.m_randomOffset != 0f)
+ {
+ vector2.y += UnityEngine.Random.Range(0f - clutter.m_randomOffset, clutter.m_randomOffset);
+ }
+ Quaternion identity = Quaternion.identity;
+ identity = ((!clutter.m_terrainTilt) ? Quaternion.Euler(0f, num4, 0f) : Quaternion.AngleAxis(num4, normal));
+ if (clutter.m_instanced)
+ {
+ if (instanceRenderer == null)
+ {
+ GameObject gameObject = UnityEngine.Object.Instantiate(clutter.m_prefab, vegPatchCenter, Quaternion.identity, m_grassRoot.transform);
+ instanceRenderer = gameObject.GetComponent<InstanceRenderer>();
+ if (instanceRenderer.m_lodMaxDistance > m_distance - m_grassPatchSize / 2f)
+ {
+ instanceRenderer.m_lodMaxDistance = m_distance - m_grassPatchSize / 2f;
+ }
+ patchData.m_objects.Add(gameObject);
+ }
+ float scale = UnityEngine.Random.Range(clutter.m_scaleMin, clutter.m_scaleMax);
+ instanceRenderer.AddInstance(vector2, identity, scale);
+ }
+ else
+ {
+ GameObject item = UnityEngine.Object.Instantiate(clutter.m_prefab, vector2, identity, m_grassRoot.transform);
+ patchData.m_objects.Add(item);
+ }
+ }
+ }
+ UnityEngine.Random.state = state;
+ return patchData;
+ }
+
+ private PatchData AllocatePatch()
+ {
+ if (m_freePatches.Count > 0)
+ {
+ return m_freePatches.Pop();
+ }
+ return new PatchData();
+ }
+
+ private void FreePatch(PatchData patch)
+ {
+ patch.center = Vector3.zero;
+ patch.m_objects.Clear();
+ patch.m_timer = 0f;
+ patch.m_reset = false;
+ m_freePatches.Push(patch);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ConnectPanel.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ConnectPanel.cs
new file mode 100644
index 0000000..cd973c6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ConnectPanel.cs
@@ -0,0 +1,215 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ConnectPanel : MonoBehaviour
+{
+ private static ConnectPanel m_instance;
+
+ public Transform m_root;
+
+ public Text m_serverField;
+
+ public Text m_worldField;
+
+ public Text m_statusField;
+
+ public Text m_connections;
+
+ public RectTransform m_playerList;
+
+ public Scrollbar m_playerListScroll;
+
+ public GameObject m_playerElement;
+
+ public InputField m_hostName;
+
+ public InputField m_hostPort;
+
+ public Button m_connectButton;
+
+ public Text m_myPort;
+
+ public Text m_myUID;
+
+ public Text m_knownHosts;
+
+ public Text m_nrOfConnections;
+
+ public Text m_pendingConnections;
+
+ public Toggle m_autoConnect;
+
+ public Text m_zdos;
+
+ public Text m_zdosPool;
+
+ public Text m_zdosSent;
+
+ public Text m_zdosRecv;
+
+ public Text m_zdosInstances;
+
+ public Text m_activePeers;
+
+ public Text m_ntp;
+
+ public Text m_upnp;
+
+ public Text m_dataSent;
+
+ public Text m_dataRecv;
+
+ public Text m_clientSendQueue;
+
+ public Text m_fps;
+
+ public Text m_frameTime;
+
+ private float m_playerListBaseSize;
+
+ private List<GameObject> m_playerListElements = new List<GameObject>();
+
+ private int m_frameSamples;
+
+ private float m_frameTimer;
+
+ public static ConnectPanel instance => m_instance;
+
+ private void Start()
+ {
+ m_instance = this;
+ m_root.gameObject.SetActive(value: false);
+ m_playerListBaseSize = m_playerList.rect.height;
+ }
+
+ public static bool IsVisible()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_root.gameObject.activeSelf;
+ }
+ return false;
+ }
+
+ private void Update()
+ {
+ if (Input.GetKeyDown(KeyCode.F2))
+ {
+ m_root.gameObject.SetActive(!m_root.gameObject.activeSelf);
+ }
+ if (!m_root.gameObject.activeInHierarchy)
+ {
+ return;
+ }
+ if (!ZNet.instance.IsServer() && ZNet.GetConnectionStatus() == ZNet.ConnectionStatus.Connected)
+ {
+ m_serverField.gameObject.SetActive(value: true);
+ m_serverField.text = ZNet.GetServerString();
+ }
+ else
+ {
+ m_serverField.gameObject.SetActive(value: false);
+ }
+ m_worldField.text = ZNet.instance.GetWorldName();
+ UpdateFps();
+ m_myPort.gameObject.SetActive(ZNet.instance.IsServer());
+ m_myPort.text = ZNet.instance.GetHostPort().ToString();
+ m_myUID.text = ZNet.instance.GetUID().ToString();
+ if (ZDOMan.instance != null)
+ {
+ m_zdos.text = ZDOMan.instance.NrOfObjects().ToString();
+ ZDOMan.instance.GetAverageStats(out var sentZdos, out var recvZdos);
+ m_zdosSent.text = sentZdos.ToString("0.0");
+ m_zdosRecv.text = recvZdos.ToString("0.0");
+ m_activePeers.text = ZNet.instance.GetNrOfPlayers().ToString();
+ }
+ m_zdosPool.text = ZDOPool.GetPoolActive() + " / " + ZDOPool.GetPoolSize() + " / " + ZDOPool.GetPoolTotal();
+ if ((bool)ZNetScene.instance)
+ {
+ m_zdosInstances.text = ZNetScene.instance.NrOfInstances().ToString();
+ }
+ if (ZNtp.instance != null)
+ {
+ m_ntp.text = (ZNtp.instance.GetStatus() ? "OK" : "fail");
+ }
+ if (ZNet.instance != null && ZNet.instance.GetZNat() != null)
+ {
+ m_upnp.text = (ZNet.instance.GetZNat().GetStatus() ? "OK" : "fail");
+ }
+ ZNet.instance.GetNetStats(out var totalSent, out var totalRecv);
+ m_dataSent.text = totalSent / 1024 + "kb/s";
+ m_dataRecv.text = totalRecv / 1024 + "kb/s";
+ m_clientSendQueue.text = ZDOMan.instance.GetClientChangeQueue().ToString();
+ m_nrOfConnections.text = ZNet.instance.GetPeerConnections().ToString();
+ string text = "";
+ foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers())
+ {
+ text = ((!connectedPeer.IsReady()) ? (text + connectedPeer.m_socket.GetEndPointString() + " connecting \n") : (text + connectedPeer.m_socket.GetEndPointString() + " UID: " + connectedPeer.m_uid + "\n"));
+ }
+ m_connections.text = text;
+ List<ZNet.PlayerInfo> playerList = ZNet.instance.GetPlayerList();
+ float num = 16f;
+ if (playerList.Count != m_playerListElements.Count)
+ {
+ foreach (GameObject playerListElement in m_playerListElements)
+ {
+ Object.Destroy(playerListElement);
+ }
+ m_playerListElements.Clear();
+ for (int i = 0; i < playerList.Count; i++)
+ {
+ GameObject gameObject = Object.Instantiate(m_playerElement, m_playerList);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)i * (0f - num));
+ m_playerListElements.Add(gameObject);
+ }
+ float b = (float)playerList.Count * num;
+ b = Mathf.Max(m_playerListBaseSize, b);
+ m_playerList.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, b);
+ m_playerListScroll.value = 1f;
+ }
+ for (int j = 0; j < playerList.Count; j++)
+ {
+ ZNet.PlayerInfo playerInfo = playerList[j];
+ Text component = m_playerListElements[j].transform.Find("name").GetComponent<Text>();
+ Text component2 = m_playerListElements[j].transform.Find("hostname").GetComponent<Text>();
+ Button component3 = m_playerListElements[j].transform.Find("KickButton").GetComponent<Button>();
+ component.text = playerInfo.m_name;
+ component2.text = playerInfo.m_host;
+ component3.gameObject.SetActive(value: false);
+ }
+ m_connectButton.interactable = ValidHost();
+ }
+
+ private void UpdateFps()
+ {
+ m_frameTimer += Time.deltaTime;
+ m_frameSamples++;
+ if (m_frameTimer > 1f)
+ {
+ float num = m_frameTimer / (float)m_frameSamples;
+ m_fps.text = (1f / num).ToString("0.0");
+ m_frameTime.text = "( " + (num * 1000f).ToString("00.0") + "ms )";
+ m_frameSamples = 0;
+ m_frameTimer = 0f;
+ }
+ }
+
+ private bool ValidHost()
+ {
+ int num = 0;
+ try
+ {
+ num = int.Parse(m_hostPort.text);
+ }
+ catch
+ {
+ return false;
+ }
+ if (string.IsNullOrEmpty(m_hostName.text) || num == 0)
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Console.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Console.cs
new file mode 100644
index 0000000..f2310db
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Console.cs
@@ -0,0 +1,654 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class Console : MonoBehaviour
+{
+ private static Console m_instance;
+
+ public RectTransform m_chatWindow;
+
+ public Text m_output;
+
+ public InputField m_input;
+
+ private const int m_maxBufferLength = 30;
+
+ private List<string> m_chatBuffer = new List<string>();
+
+ private bool m_cheat;
+
+ private string m_lastEntry = "";
+
+ public static Console instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ AddString("Valheim " + Version.GetVersionString());
+ AddString("");
+ AddString("type \"help\" - for commands");
+ AddString("");
+ m_chatWindow.gameObject.SetActive(value: false);
+ }
+
+ private void Update()
+ {
+ if ((bool)ZNet.instance && ZNet.instance.InPasswordDialog())
+ {
+ m_chatWindow.gameObject.SetActive(value: false);
+ return;
+ }
+ if (Input.GetKeyDown(KeyCode.F5) || (IsVisible() && Input.GetKeyDown(KeyCode.Escape)))
+ {
+ m_chatWindow.gameObject.SetActive(!m_chatWindow.gameObject.activeSelf);
+ }
+ if (!m_chatWindow.gameObject.activeInHierarchy)
+ {
+ return;
+ }
+ if (Input.GetKeyDown(KeyCode.UpArrow))
+ {
+ m_input.text = m_lastEntry;
+ m_input.caretPosition = m_input.text.Length;
+ }
+ if (Input.GetKeyDown(KeyCode.DownArrow))
+ {
+ m_input.text = "";
+ }
+ m_input.gameObject.SetActive(value: true);
+ m_input.ActivateInputField();
+ if (Input.GetKeyDown(KeyCode.Return))
+ {
+ if (!string.IsNullOrEmpty(m_input.text))
+ {
+ InputText();
+ m_lastEntry = m_input.text;
+ m_input.text = "";
+ }
+ EventSystem.current.SetSelectedGameObject(null);
+ m_input.gameObject.SetActive(value: false);
+ }
+ }
+
+ public static bool IsVisible()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_chatWindow.gameObject.activeInHierarchy;
+ }
+ return false;
+ }
+
+ public void Print(string text)
+ {
+ AddString(text);
+ }
+
+ private void AddString(string text)
+ {
+ m_chatBuffer.Add(text);
+ while (m_chatBuffer.Count > 30)
+ {
+ m_chatBuffer.RemoveAt(0);
+ }
+ UpdateChat();
+ }
+
+ private void UpdateChat()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ foreach (string item in m_chatBuffer)
+ {
+ stringBuilder.Append(item);
+ stringBuilder.Append("\n");
+ }
+ m_output.text = stringBuilder.ToString();
+ }
+
+ private void InputText()
+ {
+ string text = m_input.text;
+ AddString(text);
+ string[] array = text.Split(' ');
+ if (text.StartsWith("help"))
+ {
+ AddString("kick [name/ip/userID] - kick user");
+ AddString("ban [name/ip/userID] - ban user");
+ AddString("unban [ip/userID] - unban user");
+ AddString("banned - list banned users");
+ AddString("ping - ping server");
+ AddString("lodbias - set distance lod bias");
+ AddString("info - print system info");
+ if (IsCheatsEnabled())
+ {
+ AddString("genloc - regenerate all locations.");
+ AddString("debugmode - fly mode");
+ AddString("spawn [amount] [level] - spawn something");
+ AddString("pos - print current player position");
+ AddString("goto [x,z]- teleport");
+ AddString("exploremap - explore entire map");
+ AddString("resetmap - reset map exploration");
+ AddString("killall - kill nearby enemies");
+ AddString("tame - tame all nearby tameable creatures");
+ AddString("hair");
+ AddString("beard");
+ AddString("location - spawn location");
+ AddString("raiseskill [skill] [amount]");
+ AddString("resetskill [skill]");
+ AddString("freefly - freefly photo mode");
+ AddString("ffsmooth - freefly smoothness");
+ AddString("tod -1 OR [0-1]");
+ AddString("env [env]");
+ AddString("resetenv");
+ AddString("wind [angle] [intensity]");
+ AddString("resetwind");
+ AddString("god");
+ AddString("event [name] - start event");
+ AddString("stopevent - stop current event");
+ AddString("randomevent");
+ AddString("save - force saving of world");
+ AddString("resetcharacter - reset character data");
+ AddString("removedrops - remove all item-drops in area");
+ AddString("setkey [name]");
+ AddString("resetkeys [name]");
+ AddString("listkeys");
+ AddString("players [nr] - force diffuculty scale ( 0 = reset)");
+ AddString("dpsdebug - toggle dps debug print");
+ }
+ }
+ if (text.StartsWith("imacheater"))
+ {
+ m_cheat = !m_cheat;
+ AddString("Cheats: " + m_cheat);
+ GoogleAnalyticsV4.instance.LogEvent("Cheat", "CheatsEnabled", m_cheat.ToString(), 0L);
+ return;
+ }
+ if (array[0] == "hidebetatext" && (bool)Hud.instance)
+ {
+ Hud.instance.ToggleBetaTextVisible();
+ }
+ if (array[0] == "ping")
+ {
+ if ((bool)Game.instance)
+ {
+ Game.instance.Ping();
+ }
+ return;
+ }
+ if (array[0] == "dpsdebug")
+ {
+ Character.SetDPSDebug(!Character.IsDPSDebugEnabled());
+ AddString("DPS debug " + Character.IsDPSDebugEnabled());
+ }
+ if (array[0] == "lodbias")
+ {
+ float result;
+ if (array.Length == 1)
+ {
+ Print("Lod bias:" + QualitySettings.lodBias);
+ }
+ else if (float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result))
+ {
+ Print("Setting lod bias:" + result);
+ QualitySettings.lodBias = result;
+ }
+ return;
+ }
+ if (array[0] == "info")
+ {
+ Print("Render threading mode:" + SystemInfo.renderingThreadingMode);
+ long totalMemory = GC.GetTotalMemory(forceFullCollection: false);
+ Print("Total allocated mem: " + (totalMemory / 1048576).ToString("0") + "mb");
+ }
+ if (array[0] == "gc")
+ {
+ long totalMemory2 = GC.GetTotalMemory(forceFullCollection: false);
+ GC.Collect();
+ long totalMemory3 = GC.GetTotalMemory(forceFullCollection: true);
+ long num = totalMemory3 - totalMemory2;
+ Print("GC collect, Delta: " + (num / 1048576).ToString("0") + "mb Total left:" + (totalMemory3 / 1048576).ToString("0") + "mb");
+ }
+ if (array[0] == "fov")
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if ((bool)mainCamera)
+ {
+ float result2;
+ if (array.Length == 1)
+ {
+ Print("Fov:" + mainCamera.fieldOfView);
+ }
+ else if (float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result2) && result2 > 5f)
+ {
+ Print("Setting fov to " + result2);
+ Camera[] componentsInChildren = mainCamera.GetComponentsInChildren<Camera>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].fieldOfView = result2;
+ }
+ }
+ }
+ }
+ if ((bool)ZNet.instance)
+ {
+ if (text.StartsWith("kick "))
+ {
+ string user = text.Substring(5);
+ ZNet.instance.Kick(user);
+ return;
+ }
+ if (text.StartsWith("ban "))
+ {
+ string user2 = text.Substring(4);
+ ZNet.instance.Ban(user2);
+ return;
+ }
+ if (text.StartsWith("unban "))
+ {
+ string user3 = text.Substring(6);
+ ZNet.instance.Unban(user3);
+ return;
+ }
+ if (text.StartsWith("banned"))
+ {
+ ZNet.instance.PrintBanned();
+ return;
+ }
+ }
+ if (!ZNet.instance || !ZNet.instance.IsServer() || !Player.m_localPlayer)
+ {
+ return;
+ }
+ if (array[0] == "save")
+ {
+ if ((bool)ZNet.instance)
+ {
+ ZNet.instance.Save();
+ }
+ }
+ else
+ {
+ if (!IsCheatsEnabled())
+ {
+ return;
+ }
+ if (array[0] == "genloc")
+ {
+ ZoneSystem.instance.GenerateLocations();
+ return;
+ }
+ if (array[0] == "players" && array.Length >= 2)
+ {
+ if (int.TryParse(array[1], out var result3))
+ {
+ Game.instance.SetForcePlayerDifficulty(result3);
+ Print("Setting players to " + result3);
+ }
+ return;
+ }
+ if (array[0] == "setkey")
+ {
+ if (array.Length >= 2)
+ {
+ ZoneSystem.instance.SetGlobalKey(array[1]);
+ Print("Setting global key " + array[1]);
+ }
+ else
+ {
+ Print("Syntax: setkey [key]");
+ }
+ }
+ if (array[0] == "resetkeys")
+ {
+ ZoneSystem.instance.ResetGlobalKeys();
+ Print("Global keys cleared");
+ }
+ if (array[0] == "listkeys")
+ {
+ List<string> globalKeys = ZoneSystem.instance.GetGlobalKeys();
+ Print("Keys " + globalKeys.Count);
+ foreach (string item in globalKeys)
+ {
+ Print(item);
+ }
+ }
+ if (array[0] == "debugmode")
+ {
+ Player.m_debugMode = !Player.m_debugMode;
+ Print("Debugmode " + Player.m_debugMode);
+ }
+ if (array[0] == "raiseskill")
+ {
+ if (array.Length > 2)
+ {
+ string text2 = array[1];
+ int num2 = int.Parse(array[2]);
+ Player.m_localPlayer.GetSkills().CheatRaiseSkill(text2, num2);
+ }
+ else
+ {
+ Print("Syntax: raiseskill [skill] [amount]");
+ }
+ return;
+ }
+ if (array[0] == "resetskill")
+ {
+ if (array.Length > 1)
+ {
+ string text3 = array[1];
+ Player.m_localPlayer.GetSkills().CheatResetSkill(text3);
+ }
+ else
+ {
+ Print("Syntax: resetskill [skill]");
+ }
+ return;
+ }
+ if (text == "sleep")
+ {
+ EnvMan.instance.SkipToMorning();
+ return;
+ }
+ if (array[0] == "skiptime")
+ {
+ double timeSeconds = ZNet.instance.GetTimeSeconds();
+ float num3 = 240f;
+ if (array.Length > 1)
+ {
+ num3 = float.Parse(array[1]);
+ }
+ timeSeconds += (double)num3;
+ ZNet.instance.SetNetTime(timeSeconds);
+ Print("Skipping " + num3.ToString("0") + "s , Day:" + EnvMan.instance.GetDay(timeSeconds));
+ return;
+ }
+ if (text == "resetcharacter")
+ {
+ AddString("Reseting character");
+ Player.m_localPlayer.ResetCharacter();
+ return;
+ }
+ if (array[0] == "randomevent")
+ {
+ RandEventSystem.instance.StartRandomEvent();
+ }
+ if (text.StartsWith("event "))
+ {
+ if (array.Length > 1)
+ {
+ string text4 = text.Substring(6);
+ if (!RandEventSystem.instance.HaveEvent(text4))
+ {
+ Print("Random event not found:" + text4);
+ }
+ else
+ {
+ RandEventSystem.instance.SetRandomEventByName(text4, Player.m_localPlayer.transform.position);
+ }
+ }
+ return;
+ }
+ if (array[0] == "stopevent")
+ {
+ RandEventSystem.instance.ResetRandomEvent();
+ return;
+ }
+ if (text.StartsWith("removedrops"))
+ {
+ AddString("Removing item drops");
+ ItemDrop[] array2 = UnityEngine.Object.FindObjectsOfType<ItemDrop>();
+ for (int i = 0; i < array2.Length; i++)
+ {
+ ZNetView component = array2[i].GetComponent<ZNetView>();
+ if ((bool)component)
+ {
+ component.Destroy();
+ }
+ }
+ }
+ if (text.StartsWith("freefly"))
+ {
+ Print("Toggling free fly camera");
+ GameCamera.instance.ToggleFreeFly();
+ return;
+ }
+ if (array[0] == "ffsmooth")
+ {
+ if (array.Length <= 1)
+ {
+ Print(GameCamera.instance.GetFreeFlySmoothness().ToString());
+ return;
+ }
+ if (!float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
+ {
+ Print("syntax error");
+ return;
+ }
+ Print("Setting free fly camera smoothing:" + result4);
+ GameCamera.instance.SetFreeFlySmoothness(result4);
+ return;
+ }
+ if (text.StartsWith("location "))
+ {
+ if (array.Length <= 1)
+ {
+ return;
+ }
+ string text5 = text.Substring(9);
+ Vector3 pos = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 10f;
+ ZoneSystem.instance.TestSpawnLocation(text5, pos);
+ }
+ if (array[0] == "spawn")
+ {
+ if (array.Length <= 1)
+ {
+ return;
+ }
+ string text6 = array[1];
+ int num4 = ((array.Length < 3) ? 1 : int.Parse(array[2]));
+ int num5 = ((array.Length < 4) ? 1 : int.Parse(array[3]));
+ GameObject prefab = ZNetScene.instance.GetPrefab(text6);
+ if (!prefab)
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, "Missing object " + text6);
+ return;
+ }
+ DateTime now = DateTime.Now;
+ if (num4 == 1)
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, "Spawning object " + text6);
+ Character component2 = UnityEngine.Object.Instantiate(prefab, Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 2f + Vector3.up, Quaternion.identity).GetComponent<Character>();
+ if ((bool)component2 && num5 > 1)
+ {
+ component2.SetLevel(num5);
+ }
+ }
+ else
+ {
+ for (int j = 0; j < num4; j++)
+ {
+ Vector3 vector = UnityEngine.Random.insideUnitSphere * 0.5f;
+ Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, "Spawning object " + text6);
+ Character component3 = UnityEngine.Object.Instantiate(prefab, Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 2f + Vector3.up + vector, Quaternion.identity).GetComponent<Character>();
+ if ((bool)component3 && num5 > 1)
+ {
+ component3.SetLevel(num5);
+ }
+ }
+ }
+ ZLog.Log("Spawn time :" + (DateTime.Now - now).TotalMilliseconds + " ms");
+ GoogleAnalyticsV4.instance.LogEvent("Cheat", "Spawn", text6, num4);
+ return;
+ }
+ if (array[0] == "pos")
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ AddString("Player position (X,Y,Z):" + localPlayer.transform.position.ToString("F0"));
+ }
+ }
+ if (text.StartsWith("goto "))
+ {
+ string text7 = text.Substring(5);
+ char[] separator = new char[2] { ',', ' ' };
+ string[] array3 = text7.Split(separator);
+ if (array3.Length < 2)
+ {
+ AddString("Syntax /goto x,y");
+ return;
+ }
+ try
+ {
+ float x = float.Parse(array3[0]);
+ float z = float.Parse(array3[1]);
+ Player localPlayer2 = Player.m_localPlayer;
+ if ((bool)localPlayer2)
+ {
+ Vector3 pos2 = new Vector3(x, localPlayer2.transform.position.y, z);
+ localPlayer2.TeleportTo(pos2, localPlayer2.transform.rotation, distantTeleport: true);
+ }
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("parse error:" + ex.ToString() + " " + text7);
+ }
+ GoogleAnalyticsV4.instance.LogEvent("Cheat", "Goto", "", 0L);
+ return;
+ }
+ if (text.StartsWith("exploremap"))
+ {
+ Minimap.instance.ExploreAll();
+ return;
+ }
+ if (text.StartsWith("resetmap"))
+ {
+ Minimap.instance.Reset();
+ return;
+ }
+ if (text.StartsWith("puke") && (bool)Player.m_localPlayer)
+ {
+ Player.m_localPlayer.ClearFood();
+ }
+ if (text.StartsWith("tame"))
+ {
+ Tameable.TameAllInArea(Player.m_localPlayer.transform.position, 20f);
+ }
+ if (text.StartsWith("killall"))
+ {
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (!allCharacter.IsPlayer())
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 1E+10f;
+ allCharacter.Damage(hitData);
+ }
+ }
+ return;
+ }
+ if (text.StartsWith("heal"))
+ {
+ Player.m_localPlayer.Heal(Player.m_localPlayer.GetMaxHealth());
+ return;
+ }
+ if (text.StartsWith("god"))
+ {
+ Player.m_localPlayer.SetGodMode(!Player.m_localPlayer.InGodMode());
+ Print("God mode:" + Player.m_localPlayer.InGodMode());
+ GoogleAnalyticsV4.instance.LogEvent("Cheat", "God", Player.m_localPlayer.InGodMode().ToString(), 0L);
+ }
+ if (text.StartsWith("ghost"))
+ {
+ Player.m_localPlayer.SetGhostMode(!Player.m_localPlayer.InGhostMode());
+ Print("Ghost mode:" + Player.m_localPlayer.InGhostMode());
+ GoogleAnalyticsV4.instance.LogEvent("Cheat", "Ghost", Player.m_localPlayer.InGhostMode().ToString(), 0L);
+ }
+ if (text.StartsWith("beard"))
+ {
+ string beard = ((text.Length >= 6) ? text.Substring(6) : "");
+ if ((bool)Player.m_localPlayer)
+ {
+ Player.m_localPlayer.SetBeard(beard);
+ }
+ return;
+ }
+ if (text.StartsWith("hair"))
+ {
+ string hair = ((text.Length >= 5) ? text.Substring(5) : "");
+ if ((bool)Player.m_localPlayer)
+ {
+ Player.m_localPlayer.SetHair(hair);
+ }
+ return;
+ }
+ if (text.StartsWith("model "))
+ {
+ string s = text.Substring(6);
+ if ((bool)Player.m_localPlayer && int.TryParse(s, out var result5))
+ {
+ Player.m_localPlayer.SetPlayerModel(result5);
+ }
+ return;
+ }
+ if (text.StartsWith("tod "))
+ {
+ if (!float.TryParse(text.Substring(4), NumberStyles.Float, CultureInfo.InvariantCulture, out var result6))
+ {
+ return;
+ }
+ Print("Setting time of day:" + result6);
+ if (result6 < 0f)
+ {
+ EnvMan.instance.m_debugTimeOfDay = false;
+ }
+ else
+ {
+ EnvMan.instance.m_debugTimeOfDay = true;
+ EnvMan.instance.m_debugTime = Mathf.Clamp01(result6);
+ }
+ }
+ if (array[0] == "env" && array.Length > 1)
+ {
+ string text8 = text.Substring(4);
+ Print("Setting debug enviornment:" + text8);
+ EnvMan.instance.m_debugEnv = text8;
+ return;
+ }
+ if (text.StartsWith("resetenv"))
+ {
+ Print("Reseting debug enviornment");
+ EnvMan.instance.m_debugEnv = "";
+ return;
+ }
+ if (array[0] == "wind" && array.Length == 3)
+ {
+ float angle = float.Parse(array[1]);
+ float intensity = float.Parse(array[2]);
+ EnvMan.instance.SetDebugWind(angle, intensity);
+ }
+ if (array[0] == "resetwind")
+ {
+ EnvMan.instance.ResetDebugWind();
+ }
+ }
+ }
+
+ public bool IsCheatsEnabled()
+ {
+ if (m_cheat)
+ {
+ if ((bool)ZNet.instance)
+ {
+ return ZNet.instance.IsServer();
+ }
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Container.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Container.cs
new file mode 100644
index 0000000..54b8214
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Container.cs
@@ -0,0 +1,417 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Container : MonoBehaviour, Hoverable, Interactable
+{
+ public enum PrivacySetting
+ {
+ Private,
+ Group,
+ Public
+ }
+
+ private float m_lastTakeAllTime;
+
+ public Action m_onTakeAllSuccess;
+
+ public string m_name = "Container";
+
+ public Sprite m_bkg;
+
+ public int m_width = 3;
+
+ public int m_height = 2;
+
+ public PrivacySetting m_privacy = PrivacySetting.Public;
+
+ public bool m_checkGuardStone;
+
+ public bool m_autoDestroyEmpty;
+
+ public DropTable m_defaultItems = new DropTable();
+
+ public GameObject m_open;
+
+ public GameObject m_closed;
+
+ public EffectList m_openEffects = new EffectList();
+
+ public EffectList m_closeEffects = new EffectList();
+
+ public ZNetView m_rootObjectOverride;
+
+ public Vagon m_wagon;
+
+ public GameObject m_destroyedLootPrefab;
+
+ private Inventory m_inventory;
+
+ private ZNetView m_nview;
+
+ private Piece m_piece;
+
+ private bool m_inUse;
+
+ private bool m_loading;
+
+ private uint m_lastRevision;
+
+ private string m_lastDataString = "";
+
+ private void Awake()
+ {
+ m_nview = (m_rootObjectOverride ? m_rootObjectOverride.GetComponent<ZNetView>() : GetComponent<ZNetView>());
+ if (m_nview.GetZDO() != null)
+ {
+ m_inventory = new Inventory(m_name, m_bkg, m_width, m_height);
+ Inventory inventory = m_inventory;
+ inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnContainerChanged));
+ m_piece = GetComponent<Piece>();
+ if ((bool)m_nview)
+ {
+ m_nview.Register<long>("RequestOpen", RPC_RequestOpen);
+ m_nview.Register<bool>("OpenRespons", RPC_OpenRespons);
+ m_nview.Register<long>("RequestTakeAll", RPC_RequestTakeAll);
+ m_nview.Register<bool>("TakeAllRespons", RPC_TakeAllRespons);
+ }
+ WearNTear wearNTear = (m_rootObjectOverride ? m_rootObjectOverride.GetComponent<WearNTear>() : GetComponent<WearNTear>());
+ if ((bool)wearNTear)
+ {
+ wearNTear.m_onDestroyed = (Action)Delegate.Combine(wearNTear.m_onDestroyed, new Action(OnDestroyed));
+ }
+ Destructible destructible = (m_rootObjectOverride ? m_rootObjectOverride.GetComponent<Destructible>() : GetComponent<Destructible>());
+ if ((bool)destructible)
+ {
+ destructible.m_onDestroyed = (Action)Delegate.Combine(destructible.m_onDestroyed, new Action(OnDestroyed));
+ }
+ if (m_nview.IsOwner() && !m_nview.GetZDO().GetBool("addedDefaultItems"))
+ {
+ AddDefaultItems();
+ m_nview.GetZDO().Set("addedDefaultItems", value: true);
+ }
+ InvokeRepeating("CheckForChanges", 0f, 1f);
+ }
+ }
+
+ private void AddDefaultItems()
+ {
+ foreach (ItemDrop.ItemData dropListItem in m_defaultItems.GetDropListItems())
+ {
+ m_inventory.AddItem(dropListItem);
+ }
+ }
+
+ private void DropAllItems(GameObject lootContainerPrefab)
+ {
+ while (m_inventory.NrOfItems() > 0)
+ {
+ Vector3 position = base.transform.position + UnityEngine.Random.insideUnitSphere * 1f;
+ UnityEngine.Object.Instantiate(lootContainerPrefab, position, UnityEngine.Random.rotation).GetComponent<Container>().GetInventory()
+ .MoveAll(m_inventory);
+ }
+ }
+
+ private void DropAllItems()
+ {
+ List<ItemDrop.ItemData> allItems = m_inventory.GetAllItems();
+ int num = 1;
+ foreach (ItemDrop.ItemData item in allItems)
+ {
+ Vector3 position = base.transform.position + Vector3.up * 0.5f + UnityEngine.Random.insideUnitSphere * 0.3f;
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ ItemDrop.DropItem(item, 0, position, rotation);
+ num++;
+ }
+ m_inventory.RemoveAll();
+ Save();
+ }
+
+ private void OnDestroyed()
+ {
+ if (m_nview.IsOwner())
+ {
+ if ((bool)m_destroyedLootPrefab)
+ {
+ DropAllItems(m_destroyedLootPrefab);
+ }
+ else
+ {
+ DropAllItems();
+ }
+ }
+ }
+
+ private void CheckForChanges()
+ {
+ if (m_nview.IsValid())
+ {
+ Load();
+ UpdateUseVisual();
+ if (m_autoDestroyEmpty && m_nview.IsOwner() && !IsInUse() && m_inventory.NrOfItems() == 0)
+ {
+ m_nview.Destroy();
+ }
+ }
+ }
+
+ private void UpdateUseVisual()
+ {
+ bool flag;
+ if (m_nview.IsOwner())
+ {
+ flag = m_inUse;
+ m_nview.GetZDO().Set("InUse", m_inUse ? 1 : 0);
+ }
+ else
+ {
+ flag = m_nview.GetZDO().GetInt("InUse") == 1;
+ }
+ if ((bool)m_open)
+ {
+ m_open.SetActive(flag);
+ }
+ if ((bool)m_closed)
+ {
+ m_closed.SetActive(!flag);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (m_checkGuardStone && !PrivateArea.CheckAccess(base.transform.position, 0f, flash: false))
+ {
+ return Localization.instance.Localize(m_name + "\n$piece_noaccess");
+ }
+ string text = ((m_inventory.NrOfItems() != 0) ? m_name : (m_name + " ( $piece_container_empty )"));
+ text += "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open";
+ return Localization.instance.Localize(text);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (m_checkGuardStone && !PrivateArea.CheckAccess(base.transform.position))
+ {
+ return true;
+ }
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ if (!CheckAccess(playerID))
+ {
+ character.Message(MessageHud.MessageType.Center, "$msg_cantopen");
+ return true;
+ }
+ m_nview.InvokeRPC("RequestOpen", playerID);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public bool CanBeRemoved()
+ {
+ if (m_privacy == PrivacySetting.Private && GetInventory().NrOfItems() > 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool CheckAccess(long playerID)
+ {
+ switch (m_privacy)
+ {
+ case PrivacySetting.Public:
+ return true;
+ case PrivacySetting.Private:
+ if (m_piece.GetCreator() == playerID)
+ {
+ return true;
+ }
+ return false;
+ case PrivacySetting.Group:
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ public bool IsOwner()
+ {
+ return m_nview.IsOwner();
+ }
+
+ public bool IsInUse()
+ {
+ return m_inUse;
+ }
+
+ public void SetInUse(bool inUse)
+ {
+ if (m_nview.IsOwner() && m_inUse != inUse)
+ {
+ m_inUse = inUse;
+ UpdateUseVisual();
+ if (inUse)
+ {
+ m_openEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ else
+ {
+ m_closeEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ }
+ }
+
+ public Inventory GetInventory()
+ {
+ return m_inventory;
+ }
+
+ private void RPC_RequestOpen(long uid, long playerID)
+ {
+ ZLog.Log("Player " + uid + " wants to open " + base.gameObject.name + " im: " + ZDOMan.instance.GetMyID());
+ if (!m_nview.IsOwner())
+ {
+ ZLog.Log(" but im not the owner");
+ }
+ else if ((IsInUse() || ((bool)m_wagon && m_wagon.InUse())) && uid != ZNet.instance.GetUID())
+ {
+ ZLog.Log(" in use");
+ m_nview.InvokeRPC(uid, "OpenRespons", false);
+ }
+ else if (!CheckAccess(playerID))
+ {
+ ZLog.Log(" not yours");
+ m_nview.InvokeRPC(uid, "OpenRespons", false);
+ }
+ else
+ {
+ ZDOMan.instance.ForceSendZDO(uid, m_nview.GetZDO().m_uid);
+ m_nview.GetZDO().SetOwner(uid);
+ m_nview.InvokeRPC(uid, "OpenRespons", true);
+ }
+ }
+
+ private void RPC_OpenRespons(long uid, bool granted)
+ {
+ if ((bool)Player.m_localPlayer)
+ {
+ if (granted)
+ {
+ InventoryGui.instance.Show(this);
+ }
+ else
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, "$msg_inuse");
+ }
+ }
+ }
+
+ public bool TakeAll(Humanoid character)
+ {
+ if (m_checkGuardStone && !PrivateArea.CheckAccess(base.transform.position))
+ {
+ return false;
+ }
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ if (!CheckAccess(playerID))
+ {
+ character.Message(MessageHud.MessageType.Center, "$msg_cantopen");
+ return false;
+ }
+ m_nview.InvokeRPC("RequestTakeAll", playerID);
+ return true;
+ }
+
+ private void RPC_RequestTakeAll(long uid, long playerID)
+ {
+ ZLog.Log("Player " + uid + " wants to takeall from " + base.gameObject.name + " im: " + ZDOMan.instance.GetMyID());
+ if (!m_nview.IsOwner())
+ {
+ ZLog.Log(" but im not the owner");
+ }
+ else if ((IsInUse() || ((bool)m_wagon && m_wagon.InUse())) && uid != ZNet.instance.GetUID())
+ {
+ ZLog.Log(" in use");
+ m_nview.InvokeRPC(uid, "TakeAllRespons", false);
+ }
+ else if (!CheckAccess(playerID))
+ {
+ ZLog.Log(" not yours");
+ m_nview.InvokeRPC(uid, "TakeAllRespons", false);
+ }
+ else if (!(Time.time - m_lastTakeAllTime < 2f))
+ {
+ m_lastTakeAllTime = Time.time;
+ m_nview.InvokeRPC(uid, "TakeAllRespons", true);
+ }
+ }
+
+ private void RPC_TakeAllRespons(long uid, bool granted)
+ {
+ if (!Player.m_localPlayer)
+ {
+ return;
+ }
+ if (granted)
+ {
+ m_nview.ClaimOwnership();
+ ZDOMan.instance.ForceSendZDO(uid, m_nview.GetZDO().m_uid);
+ Player.m_localPlayer.GetInventory().MoveAll(m_inventory);
+ if (m_onTakeAllSuccess != null)
+ {
+ m_onTakeAllSuccess();
+ }
+ }
+ else
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, "$msg_inuse");
+ }
+ }
+
+ private void OnContainerChanged()
+ {
+ if (!m_loading && IsOwner())
+ {
+ Save();
+ }
+ }
+
+ private void Save()
+ {
+ ZPackage zPackage = new ZPackage();
+ m_inventory.Save(zPackage);
+ string @base = zPackage.GetBase64();
+ m_nview.GetZDO().Set("items", @base);
+ m_lastRevision = m_nview.GetZDO().m_dataRevision;
+ m_lastDataString = @base;
+ }
+
+ private void Load()
+ {
+ if (m_nview.GetZDO().m_dataRevision != m_lastRevision)
+ {
+ string @string = m_nview.GetZDO().GetString("items");
+ if (!string.IsNullOrEmpty(@string) && !(@string == m_lastDataString))
+ {
+ ZPackage pkg = new ZPackage(@string);
+ m_loading = true;
+ m_inventory.Load(pkg);
+ m_loading = false;
+ m_lastRevision = m_nview.GetZDO().m_dataRevision;
+ m_lastDataString = @string;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CookingStation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CookingStation.cs
new file mode 100644
index 0000000..24fa4b0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CookingStation.cs
@@ -0,0 +1,363 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+public class CookingStation : MonoBehaviour, Interactable, Hoverable
+{
+ [Serializable]
+ public class ItemConversion
+ {
+ public ItemDrop m_from;
+
+ public ItemDrop m_to;
+
+ public float m_cookTime = 10f;
+ }
+
+ private const float cookDelta = 1f;
+
+ public EffectList m_addEffect = new EffectList();
+
+ public EffectList m_doneEffect = new EffectList();
+
+ public EffectList m_overcookedEffect = new EffectList();
+
+ public EffectList m_pickEffector = new EffectList();
+
+ public float m_spawnOffset = 0.5f;
+
+ public float m_spawnForce = 5f;
+
+ public ItemDrop m_overCookedItem;
+
+ public List<ItemConversion> m_conversion = new List<ItemConversion>();
+
+ public Transform[] m_slots;
+
+ public string m_name = "";
+
+ private ZNetView m_nview;
+
+ private ParticleSystem[] m_ps;
+
+ private AudioSource[] m_as;
+
+ private void Awake()
+ {
+ m_nview = base.gameObject.GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ m_ps = new ParticleSystem[m_slots.Length];
+ m_as = new AudioSource[m_slots.Length];
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ m_ps[i] = m_slots[i].GetComponentInChildren<ParticleSystem>();
+ m_as[i] = m_slots[i].GetComponentInChildren<AudioSource>();
+ }
+ m_nview.Register("RemoveDoneItem", RPC_RemoveDoneItem);
+ m_nview.Register<string>("AddItem", RPC_AddItem);
+ m_nview.Register<int, string>("SetSlotVisual", RPC_SetSlotVisual);
+ InvokeRepeating("UpdateCooking", 0f, 1f);
+ }
+ }
+
+ private void UpdateCooking()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ if (m_nview.IsOwner() && IsFireLit())
+ {
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ GetSlot(i, out var itemName, out var cookedTime);
+ if (!(itemName != "") || !(itemName != m_overCookedItem.name))
+ {
+ continue;
+ }
+ ItemConversion itemConversion = GetItemConversion(itemName);
+ if (itemName == null)
+ {
+ SetSlot(i, "", 0f);
+ continue;
+ }
+ cookedTime += 1f;
+ if (cookedTime > itemConversion.m_cookTime * 2f)
+ {
+ m_overcookedEffect.Create(m_slots[i].position, Quaternion.identity);
+ SetSlot(i, m_overCookedItem.name, cookedTime);
+ }
+ else if (cookedTime > itemConversion.m_cookTime && itemName == itemConversion.m_from.name)
+ {
+ m_doneEffect.Create(m_slots[i].position, Quaternion.identity);
+ SetSlot(i, itemConversion.m_to.name, cookedTime);
+ }
+ else
+ {
+ SetSlot(i, itemName, cookedTime);
+ }
+ }
+ }
+ UpdateVisual();
+ }
+
+ private void UpdateVisual()
+ {
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ GetSlot(i, out var itemName, out var _);
+ SetSlotVisual(i, itemName);
+ }
+ }
+
+ private void RPC_SetSlotVisual(long sender, int slot, string item)
+ {
+ SetSlotVisual(slot, item);
+ }
+
+ private void SetSlotVisual(int i, string item)
+ {
+ if (item == "")
+ {
+ ParticleSystem.EmissionModule emission = m_ps[i].emission;
+ emission.enabled = false;
+ m_as[i].mute = true;
+ if (m_slots[i].childCount > 0)
+ {
+ UnityEngine.Object.Destroy(m_slots[i].GetChild(0).gameObject);
+ }
+ return;
+ }
+ ParticleSystem.EmissionModule emission2 = m_ps[i].emission;
+ emission2.enabled = true;
+ m_as[i].mute = false;
+ if (m_slots[i].childCount == 0 || m_slots[i].GetChild(0).name != item)
+ {
+ if (m_slots[i].childCount > 0)
+ {
+ UnityEngine.Object.Destroy(m_slots[i].GetChild(0).gameObject);
+ }
+ Transform obj = ObjectDB.instance.GetItemPrefab(item).transform.Find("attach");
+ Transform transform = m_slots[i];
+ GameObject obj2 = UnityEngine.Object.Instantiate(obj.gameObject, transform.position, transform.rotation, transform);
+ obj2.name = item;
+ Renderer[] componentsInChildren = obj2.GetComponentsInChildren<Renderer>();
+ for (int j = 0; j < componentsInChildren.Length; j++)
+ {
+ componentsInChildren[j].shadowCastingMode = ShadowCastingMode.Off;
+ }
+ }
+ }
+
+ private void RPC_RemoveDoneItem(long sender)
+ {
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ GetSlot(i, out var itemName, out var _);
+ if (itemName != "" && IsItemDone(itemName))
+ {
+ SpawnItem(itemName);
+ SetSlot(i, "", 0f);
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetSlotVisual", i, "");
+ break;
+ }
+ }
+ }
+
+ private bool HaveDoneItem()
+ {
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ GetSlot(i, out var itemName, out var _);
+ if (itemName != "" && IsItemDone(itemName))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsItemDone(string itemName)
+ {
+ if (itemName == m_overCookedItem.name)
+ {
+ return true;
+ }
+ ItemConversion itemConversion = GetItemConversion(itemName);
+ if (itemConversion == null)
+ {
+ return false;
+ }
+ if (itemName == itemConversion.m_to.name)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void SpawnItem(string name)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
+ Vector3 vector = base.transform.position + Vector3.up * m_spawnOffset;
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ UnityEngine.Object.Instantiate(itemPrefab, vector, rotation).GetComponent<Rigidbody>().velocity = Vector3.up * m_spawnForce;
+ m_pickEffector.Create(vector, Quaternion.identity);
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_cstand_cook\n[<color=yellow><b>1-8</b></color>] $piece_cstand_cook");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (HaveDoneItem())
+ {
+ m_nview.InvokeRPC("RemoveDoneItem");
+ return true;
+ }
+ ItemDrop.ItemData itemData = FindCookableItem(user.GetInventory());
+ if (itemData == null)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_nocookitems");
+ return false;
+ }
+ UseItem(user, itemData);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (!IsFireLit())
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_needfire");
+ return false;
+ }
+ if (GetFreeSlot() == -1)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_nocookroom");
+ return false;
+ }
+ return CookItem(user.GetInventory(), item);
+ }
+
+ private bool IsFireLit()
+ {
+ if ((bool)EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.Burning, 0.25f))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private ItemDrop.ItemData FindCookableItem(Inventory inventory)
+ {
+ foreach (ItemConversion item2 in m_conversion)
+ {
+ ItemDrop.ItemData item = inventory.GetItem(item2.m_from.m_itemData.m_shared.m_name);
+ if (item != null)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private bool CookItem(Inventory inventory, ItemDrop.ItemData item)
+ {
+ string text = item.m_dropPrefab.name;
+ if (!m_nview.HasOwner())
+ {
+ m_nview.ClaimOwnership();
+ }
+ if (!IsItemAllowed(item))
+ {
+ return false;
+ }
+ if (GetFreeSlot() == -1)
+ {
+ return false;
+ }
+ inventory.RemoveOneItem(item);
+ m_nview.InvokeRPC("AddItem", text);
+ return true;
+ }
+
+ private void RPC_AddItem(long sender, string itemName)
+ {
+ if (IsItemAllowed(itemName))
+ {
+ int freeSlot = GetFreeSlot();
+ if (freeSlot != -1)
+ {
+ SetSlot(freeSlot, itemName, 0f);
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetSlotVisual", freeSlot, itemName);
+ m_addEffect.Create(m_slots[freeSlot].position, Quaternion.identity);
+ }
+ }
+ }
+
+ private void SetSlot(int slot, string itemName, float cookedTime)
+ {
+ m_nview.GetZDO().Set("slot" + slot, itemName);
+ m_nview.GetZDO().Set("slot" + slot, cookedTime);
+ }
+
+ private void GetSlot(int slot, out string itemName, out float cookedTime)
+ {
+ itemName = m_nview.GetZDO().GetString("slot" + slot);
+ cookedTime = m_nview.GetZDO().GetFloat("slot" + slot);
+ }
+
+ private int GetFreeSlot()
+ {
+ for (int i = 0; i < m_slots.Length; i++)
+ {
+ if (m_nview.GetZDO().GetString("slot" + i) == "")
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private bool IsItemAllowed(ItemDrop.ItemData item)
+ {
+ return IsItemAllowed(item.m_dropPrefab.name);
+ }
+
+ private bool IsItemAllowed(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ItemConversion GetItemConversion(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName || item.m_to.gameObject.name == itemName)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Corpse.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Corpse.cs
new file mode 100644
index 0000000..995e11a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Corpse.cs
@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Corpse : MonoBehaviour
+{
+ private static float m_updateDt = 2f;
+
+ public float m_emptyDespawnDelaySec = 10f;
+
+ public float m_DespawnDelayMin = 20f;
+
+ private float m_emptyTimer;
+
+ private Container m_container;
+
+ private ZNetView m_nview;
+
+ private SkinnedMeshRenderer m_model;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_container = GetComponent<Container>();
+ m_model = GetComponentInChildren<SkinnedMeshRenderer>();
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong("timeOfDeath", 0L) == 0L)
+ {
+ m_nview.GetZDO().Set("timeOfDeath", ZNet.instance.GetTime().Ticks);
+ }
+ InvokeRepeating("UpdateDespawn", m_updateDt, m_updateDt);
+ }
+
+ public void SetEquipedItems(List<ItemDrop.ItemData> items)
+ {
+ foreach (ItemDrop.ItemData item in items)
+ {
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Chest)
+ {
+ m_nview.GetZDO().Set("ChestItem", item.m_shared.m_name);
+ }
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Legs)
+ {
+ m_nview.GetZDO().Set("LegItem", item.m_shared.m_name);
+ }
+ }
+ }
+
+ private void UpdateDespawn()
+ {
+ if (!m_nview.IsOwner() || m_container.IsInUse())
+ {
+ return;
+ }
+ if (m_container.GetInventory().NrOfItems() <= 0)
+ {
+ m_emptyTimer += m_updateDt;
+ if (m_emptyTimer >= m_emptyDespawnDelaySec)
+ {
+ ZLog.Log("Despawning looted corpse");
+ m_nview.Destroy();
+ }
+ }
+ else
+ {
+ m_emptyTimer = 0f;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CraftingStation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CraftingStation.cs
new file mode 100644
index 0000000..aef3ad6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CraftingStation.cs
@@ -0,0 +1,317 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class CraftingStation : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "";
+
+ public Sprite m_icon;
+
+ public float m_discoverRange = 4f;
+
+ public float m_rangeBuild = 10f;
+
+ public bool m_craftRequireRoof = true;
+
+ public bool m_craftRequireFire = true;
+
+ public Transform m_roofCheckPoint;
+
+ public Transform m_connectionPoint;
+
+ public bool m_showBasicRecipies;
+
+ public float m_useDistance = 2f;
+
+ public int m_useAnimation;
+
+ public GameObject m_areaMarker;
+
+ public GameObject m_inUseObject;
+
+ public GameObject m_haveFireObject;
+
+ public EffectList m_craftItemEffects = new EffectList();
+
+ public EffectList m_craftItemDoneEffects = new EffectList();
+
+ public EffectList m_repairItemDoneEffects = new EffectList();
+
+ private const float m_updateExtensionInterval = 2f;
+
+ private float m_updateExtensionTimer;
+
+ private float m_useTimer = 10f;
+
+ private bool m_haveFire;
+
+ private ZNetView m_nview;
+
+ private List<StationExtension> m_attachedExtensions = new List<StationExtension>();
+
+ private static List<CraftingStation> m_allStations = new List<CraftingStation>();
+
+ private static int m_triggerMask = 0;
+
+ private void Start()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (!m_nview || m_nview.GetZDO() != null)
+ {
+ m_allStations.Add(this);
+ if ((bool)m_areaMarker)
+ {
+ m_areaMarker.SetActive(value: false);
+ }
+ if (m_craftRequireFire)
+ {
+ InvokeRepeating("CheckFire", 1f, 1f);
+ }
+ }
+ }
+
+ private void OnDestroy()
+ {
+ m_allStations.Remove(this);
+ }
+
+ public bool Interact(Humanoid user, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ if (user == Player.m_localPlayer)
+ {
+ if (!InUseDistance(user))
+ {
+ return false;
+ }
+ Player player = user as Player;
+ if (CheckUsable(player, showMessage: true))
+ {
+ player.SetCraftingStation(this);
+ InventoryGui.instance.Show(null);
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public bool CheckUsable(Player player, bool showMessage)
+ {
+ if (m_craftRequireRoof)
+ {
+ Cover.GetCoverForPoint(m_roofCheckPoint.position, out var coverPercentage, out var underRoof);
+ if (!underRoof)
+ {
+ if (showMessage)
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_stationneedroof");
+ }
+ return false;
+ }
+ if (coverPercentage < 0.7f)
+ {
+ if (showMessage)
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_stationtooexposed");
+ }
+ return false;
+ }
+ }
+ if (m_craftRequireFire && !m_haveFire)
+ {
+ if (showMessage)
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_needfire");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public string GetHoverText()
+ {
+ if (!InUseDistance(Player.m_localPlayer))
+ {
+ return Localization.instance.Localize("<color=grey>$piece_toofar</color>");
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use ");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public void ShowAreaMarker()
+ {
+ if ((bool)m_areaMarker)
+ {
+ m_areaMarker.SetActive(value: true);
+ CancelInvoke("HideMarker");
+ Invoke("HideMarker", 0.5f);
+ PokeInUse();
+ }
+ }
+
+ private void HideMarker()
+ {
+ m_areaMarker.SetActive(value: false);
+ }
+
+ public static void UpdateKnownStationsInRange(Player player)
+ {
+ Vector3 position = player.transform.position;
+ foreach (CraftingStation allStation in m_allStations)
+ {
+ if (Vector3.Distance(allStation.transform.position, position) < allStation.m_discoverRange)
+ {
+ player.AddKnownStation(allStation);
+ }
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (!(m_nview == null) && m_nview.IsValid())
+ {
+ m_useTimer += Time.fixedDeltaTime;
+ m_updateExtensionTimer += Time.fixedDeltaTime;
+ if ((bool)m_inUseObject)
+ {
+ m_inUseObject.SetActive(m_useTimer < 1f);
+ }
+ }
+ }
+
+ private void CheckFire()
+ {
+ m_haveFire = EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.Burning, 0.25f);
+ if ((bool)m_haveFireObject)
+ {
+ m_haveFireObject.SetActive(m_haveFire);
+ }
+ }
+
+ public void PokeInUse()
+ {
+ m_useTimer = 0f;
+ TriggerExtensionEffects();
+ }
+
+ public static CraftingStation GetCraftingStation(Vector3 point)
+ {
+ if (m_triggerMask == 0)
+ {
+ m_triggerMask = LayerMask.GetMask("character_trigger");
+ }
+ Collider[] array = Physics.OverlapSphere(point, 0.1f, m_triggerMask, QueryTriggerInteraction.Collide);
+ foreach (Collider collider in array)
+ {
+ if (collider.gameObject.CompareTag("StationUseArea"))
+ {
+ CraftingStation componentInParent = collider.GetComponentInParent<CraftingStation>();
+ if (componentInParent != null)
+ {
+ return componentInParent;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static CraftingStation HaveBuildStationInRange(string name, Vector3 point)
+ {
+ foreach (CraftingStation allStation in m_allStations)
+ {
+ if (!(allStation.m_name != name))
+ {
+ float rangeBuild = allStation.m_rangeBuild;
+ if (Vector3.Distance(allStation.transform.position, point) < rangeBuild)
+ {
+ return allStation;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static void FindStationsInRange(string name, Vector3 point, float range, List<CraftingStation> stations)
+ {
+ foreach (CraftingStation allStation in m_allStations)
+ {
+ if (!(allStation.m_name != name) && Vector3.Distance(allStation.transform.position, point) < range)
+ {
+ stations.Add(allStation);
+ }
+ }
+ }
+
+ public static CraftingStation FindClosestStationInRange(string name, Vector3 point, float range)
+ {
+ CraftingStation craftingStation = null;
+ float num = 99999f;
+ foreach (CraftingStation allStation in m_allStations)
+ {
+ if (!(allStation.m_name != name))
+ {
+ float num2 = Vector3.Distance(allStation.transform.position, point);
+ if (num2 < range && (num2 < num || craftingStation == null))
+ {
+ craftingStation = allStation;
+ num = num2;
+ }
+ }
+ }
+ return craftingStation;
+ }
+
+ private List<StationExtension> GetExtensions()
+ {
+ if (m_updateExtensionTimer > 2f)
+ {
+ m_updateExtensionTimer = 0f;
+ m_attachedExtensions.Clear();
+ StationExtension.FindExtensions(this, base.transform.position, m_attachedExtensions);
+ }
+ return m_attachedExtensions;
+ }
+
+ private void TriggerExtensionEffects()
+ {
+ Vector3 connectionEffectPoint = GetConnectionEffectPoint();
+ foreach (StationExtension extension in GetExtensions())
+ {
+ if ((bool)extension)
+ {
+ extension.StartConnectionEffect(connectionEffectPoint);
+ }
+ }
+ }
+
+ public Vector3 GetConnectionEffectPoint()
+ {
+ if ((bool)m_connectionPoint)
+ {
+ return m_connectionPoint.position;
+ }
+ return base.transform.position;
+ }
+
+ public int GetLevel()
+ {
+ return 1 + GetExtensions().Count;
+ }
+
+ public bool InUseDistance(Humanoid human)
+ {
+ return Vector3.Distance(human.transform.position, base.transform.position) < m_useDistance;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CreatureSpawner.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CreatureSpawner.cs
new file mode 100644
index 0000000..5cc99f5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/CreatureSpawner.cs
@@ -0,0 +1,160 @@
+using System;
+using UnityEngine;
+
+public class CreatureSpawner : MonoBehaviour
+{
+ private const float m_radius = 0.75f;
+
+ public GameObject m_creaturePrefab;
+
+ [Header("Level")]
+ public int m_maxLevel = 1;
+
+ public int m_minLevel = 1;
+
+ public float m_levelupChance = 15f;
+
+ [Header("Spawn settings")]
+ public float m_respawnTimeMinuts = 20f;
+
+ public float m_triggerDistance = 60f;
+
+ public float m_triggerNoise;
+
+ public bool m_spawnAtNight = true;
+
+ public bool m_spawnAtDay = true;
+
+ public bool m_requireSpawnArea;
+
+ public bool m_spawnInPlayerBase;
+
+ public bool m_setPatrolSpawnPoint;
+
+ public EffectList m_spawnEffects = new EffectList();
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ InvokeRepeating("UpdateSpawner", UnityEngine.Random.Range(3f, 5f), 5f);
+ }
+ }
+
+ private void UpdateSpawner()
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID("spawn_id");
+ if (m_respawnTimeMinuts <= 0f && !zDOID.IsNone())
+ {
+ return;
+ }
+ if (!zDOID.IsNone() && ZDOMan.instance.GetZDO(zDOID) != null)
+ {
+ m_nview.GetZDO().Set("alive_time", ZNet.instance.GetTime().Ticks);
+ return;
+ }
+ if (m_respawnTimeMinuts > 0f)
+ {
+ DateTime time = ZNet.instance.GetTime();
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("alive_time", 0L));
+ if ((time - dateTime).TotalMinutes < (double)m_respawnTimeMinuts)
+ {
+ return;
+ }
+ }
+ if ((!m_spawnAtDay && EnvMan.instance.IsDay()) || (!m_spawnAtNight && EnvMan.instance.IsNight()))
+ {
+ return;
+ }
+ _ = m_requireSpawnArea;
+ if (!m_spawnInPlayerBase && (bool)EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.PlayerBase))
+ {
+ return;
+ }
+ if (m_triggerNoise > 0f)
+ {
+ if (!Player.IsPlayerInRange(base.transform.position, m_triggerDistance, m_triggerNoise))
+ {
+ return;
+ }
+ }
+ else if (!Player.IsPlayerInRange(base.transform.position, m_triggerDistance))
+ {
+ return;
+ }
+ Spawn();
+ }
+
+ private bool HasSpawned()
+ {
+ if (m_nview == null || m_nview.GetZDO() == null)
+ {
+ return false;
+ }
+ return !m_nview.GetZDO().GetZDOID("spawn_id").IsNone();
+ }
+
+ private ZNetView Spawn()
+ {
+ Vector3 position = base.transform.position;
+ if (ZoneSystem.instance.FindFloor(position, out var height))
+ {
+ position.y = height + 0.25f;
+ }
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0f, 360f), 0f);
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_creaturePrefab, position, rotation);
+ ZNetView component = gameObject.GetComponent<ZNetView>();
+ BaseAI component2 = gameObject.GetComponent<BaseAI>();
+ if (component2 != null && m_setPatrolSpawnPoint)
+ {
+ component2.SetPatrolPoint();
+ }
+ if (m_maxLevel > 1)
+ {
+ Character component3 = gameObject.GetComponent<Character>();
+ if ((bool)component3)
+ {
+ int i;
+ for (i = m_minLevel; i < m_maxLevel; i++)
+ {
+ if (!(UnityEngine.Random.Range(0f, 100f) <= m_levelupChance))
+ {
+ break;
+ }
+ }
+ if (i > 1)
+ {
+ component3.SetLevel(i);
+ }
+ }
+ }
+ component.GetZDO().SetPGWVersion(m_nview.GetZDO().GetPGWVersion());
+ m_nview.GetZDO().Set("spawn_id", component.GetZDO().m_uid);
+ m_nview.GetZDO().Set("alive_time", ZNet.instance.GetTime().Ticks);
+ SpawnEffect(gameObject);
+ return component;
+ }
+
+ private void SpawnEffect(GameObject spawnedObject)
+ {
+ Character component = spawnedObject.GetComponent<Character>();
+ Vector3 pos = (component ? component.GetCenterPoint() : (base.transform.position + Vector3.up * 0.75f));
+ m_spawnEffects.Create(pos, Quaternion.identity);
+ }
+
+ private float GetRadius()
+ {
+ return 0.75f;
+ }
+
+ private void OnDrawGizmos()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DLCMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DLCMan.cs
new file mode 100644
index 0000000..b4375ec
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DLCMan.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using Steamworks;
+using UnityEngine;
+
+public class DLCMan : MonoBehaviour
+{
+ [Serializable]
+ public class DLCInfo
+ {
+ public string m_name = "DLC";
+
+ public uint[] m_steamAPPID = new uint[0];
+
+ [NonSerialized]
+ public bool m_installed;
+ }
+
+ private static DLCMan m_instance;
+
+ public List<DLCInfo> m_dlcs = new List<DLCInfo>();
+
+ public static DLCMan instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ CheckDLCsSTEAM();
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public bool IsDLCInstalled(string name)
+ {
+ if (name.Length == 0)
+ {
+ return true;
+ }
+ foreach (DLCInfo dlc in m_dlcs)
+ {
+ if (dlc.m_name == name)
+ {
+ return dlc.m_installed;
+ }
+ }
+ ZLog.LogWarning("DLC " + name + " not registered in DLCMan");
+ return false;
+ }
+
+ private void CheckDLCsSTEAM()
+ {
+ if (!SteamManager.Initialized)
+ {
+ ZLog.Log("Steam not initialized");
+ return;
+ }
+ ZLog.Log("Checking for installed DLCs");
+ foreach (DLCInfo dlc in m_dlcs)
+ {
+ dlc.m_installed = IsDLCInstalled(dlc);
+ ZLog.Log("DLC:" + dlc.m_name + " installed:" + dlc.m_installed);
+ }
+ }
+
+ private bool IsDLCInstalled(DLCInfo dlc)
+ {
+ uint[] steamAPPID = dlc.m_steamAPPID;
+ foreach (uint id in steamAPPID)
+ {
+ if (IsDLCInstalled(id))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsDLCInstalled(uint id)
+ {
+ AppId_t appId_t = new AppId_t(id);
+ int dLCCount = SteamApps.GetDLCCount();
+ for (int i = 0; i < dLCCount; i++)
+ {
+ if (SteamApps.BGetDLCDataByIndex(i, out var pAppID, out var _, out var _, 200) && appId_t == pAppID)
+ {
+ ZLog.Log("DLC installed:" + id);
+ return SteamApps.BIsDlcInstalled(pAppID);
+ }
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DamageText.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DamageText.cs
new file mode 100644
index 0000000..bdca3fb
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DamageText.cs
@@ -0,0 +1,181 @@
+using System.Collections.Generic;
+using System.Globalization;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class DamageText : MonoBehaviour
+{
+ public enum TextType
+ {
+ Normal,
+ Resistant,
+ Weak,
+ Immune,
+ Heal,
+ TooHard,
+ Blocked
+ }
+
+ private class WorldTextInstance
+ {
+ public Vector3 m_worldPos;
+
+ public GameObject m_gui;
+
+ public float m_timer;
+
+ public Text m_textField;
+ }
+
+ private static DamageText m_instance;
+
+ public float m_textDuration = 1.5f;
+
+ public float m_maxTextDistance = 30f;
+
+ public int m_largeFontSize = 16;
+
+ public int m_smallFontSize = 8;
+
+ public float m_smallFontDistance = 10f;
+
+ public GameObject m_worldTextBase;
+
+ private List<WorldTextInstance> m_worldTexts = new List<WorldTextInstance>();
+
+ public static DamageText instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ ZRoutedRpc.instance.Register<ZPackage>("DamageText", RPC_DamageText);
+ }
+
+ private void LateUpdate()
+ {
+ UpdateWorldTexts(Time.deltaTime);
+ }
+
+ private void UpdateWorldTexts(float dt)
+ {
+ WorldTextInstance worldTextInstance = null;
+ Camera mainCamera = Utils.GetMainCamera();
+ foreach (WorldTextInstance worldText in m_worldTexts)
+ {
+ worldText.m_timer += dt;
+ if (worldText.m_timer > m_textDuration && worldTextInstance == null)
+ {
+ worldTextInstance = worldText;
+ }
+ worldText.m_worldPos.y += dt;
+ float f = Mathf.Clamp01(worldText.m_timer / m_textDuration);
+ Color color = worldText.m_textField.color;
+ color.a = 1f - Mathf.Pow(f, 3f);
+ worldText.m_textField.color = color;
+ Vector3 position = mainCamera.WorldToScreenPoint(worldText.m_worldPos);
+ if (position.x < 0f || position.x > (float)Screen.width || position.y < 0f || position.y > (float)Screen.height || position.z < 0f)
+ {
+ worldText.m_gui.SetActive(value: false);
+ continue;
+ }
+ worldText.m_gui.SetActive(value: true);
+ worldText.m_gui.transform.position = position;
+ }
+ if (worldTextInstance != null)
+ {
+ Object.Destroy(worldTextInstance.m_gui);
+ m_worldTexts.Remove(worldTextInstance);
+ }
+ }
+
+ private void AddInworldText(TextType type, Vector3 pos, float distance, float dmg, bool mySelf)
+ {
+ WorldTextInstance worldTextInstance = new WorldTextInstance();
+ worldTextInstance.m_worldPos = pos;
+ worldTextInstance.m_gui = Object.Instantiate(m_worldTextBase, base.transform);
+ worldTextInstance.m_textField = worldTextInstance.m_gui.GetComponent<Text>();
+ m_worldTexts.Add(worldTextInstance);
+ Color color = ((type == TextType.Heal) ? new Color(0.5f, 1f, 0.5f, 0.7f) : (mySelf ? ((dmg != 0f) ? new Color(1f, 0f, 0f, 1f) : new Color(0.5f, 0.5f, 0.5f, 1f)) : (type switch
+ {
+ TextType.Normal => new Color(1f, 1f, 1f, 1f),
+ TextType.Resistant => new Color(0.6f, 0.6f, 0.6f, 1f),
+ TextType.Weak => new Color(1f, 1f, 0f, 1f),
+ TextType.Immune => new Color(0.6f, 0.6f, 0.6f, 1f),
+ TextType.TooHard => new Color(0.8f, 0.7f, 0.7f, 1f),
+ _ => Color.white,
+ })));
+ worldTextInstance.m_textField.color = color;
+ if (distance > m_smallFontDistance)
+ {
+ worldTextInstance.m_textField.fontSize = m_smallFontSize;
+ }
+ else
+ {
+ worldTextInstance.m_textField.fontSize = m_largeFontSize;
+ }
+ string text = type switch
+ {
+ TextType.TooHard => Localization.instance.Localize("$msg_toohard"),
+ TextType.Heal => "+" + dmg.ToString("0.#", CultureInfo.InvariantCulture),
+ TextType.Blocked => Localization.instance.Localize("$msg_blocked: ") + dmg.ToString("0.#", CultureInfo.InvariantCulture),
+ _ => dmg.ToString("0.#", CultureInfo.InvariantCulture),
+ };
+ worldTextInstance.m_textField.text = text;
+ worldTextInstance.m_timer = 0f;
+ }
+
+ public void ShowText(HitData.DamageModifier type, Vector3 pos, float dmg, bool player = false)
+ {
+ TextType type2 = TextType.Normal;
+ switch (type)
+ {
+ case HitData.DamageModifier.Normal:
+ type2 = TextType.Normal;
+ break;
+ case HitData.DamageModifier.Immune:
+ type2 = TextType.Immune;
+ break;
+ case HitData.DamageModifier.Resistant:
+ type2 = TextType.Resistant;
+ break;
+ case HitData.DamageModifier.VeryResistant:
+ type2 = TextType.Resistant;
+ break;
+ case HitData.DamageModifier.Weak:
+ type2 = TextType.Weak;
+ break;
+ case HitData.DamageModifier.VeryWeak:
+ type2 = TextType.Weak;
+ break;
+ }
+ ShowText(type2, pos, dmg, player);
+ }
+
+ public void ShowText(TextType type, Vector3 pos, float dmg, bool player = false)
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write((int)type);
+ zPackage.Write(pos);
+ zPackage.Write(dmg);
+ zPackage.Write(player);
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "DamageText", zPackage);
+ }
+
+ private void RPC_DamageText(long sender, ZPackage pkg)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if ((bool)mainCamera && !Hud.IsUserHidden())
+ {
+ TextType type = (TextType)pkg.ReadInt();
+ Vector3 vector = pkg.ReadVector3();
+ float dmg = pkg.ReadSingle();
+ bool flag = pkg.ReadBool();
+ float num = Vector3.Distance(mainCamera.transform.position, vector);
+ if (!(num > m_maxTextDistance))
+ {
+ bool mySelf = flag && sender == ZNet.instance.GetUID();
+ AddInworldText(type, vector, num, dmg, mySelf);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DepthCamera.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DepthCamera.cs
new file mode 100644
index 0000000..9790a6c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DepthCamera.cs
@@ -0,0 +1,39 @@
+using UnityEngine;
+
+public class DepthCamera : MonoBehaviour
+{
+ public Shader m_depthShader;
+
+ public float m_offset = 50f;
+
+ public RenderTexture m_texture;
+
+ public float m_updateInterval = 1f;
+
+ private Camera m_camera;
+
+ private void Start()
+ {
+ m_camera = GetComponent<Camera>();
+ InvokeRepeating("RenderDepth", m_updateInterval, m_updateInterval);
+ }
+
+ private void RenderDepth()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null))
+ {
+ Vector3 position = (Player.m_localPlayer ? Player.m_localPlayer.transform.position : mainCamera.transform.position) + Vector3.up * m_offset;
+ position.x = Mathf.Round(position.x);
+ position.y = Mathf.Round(position.y);
+ position.z = Mathf.Round(position.z);
+ base.transform.position = position;
+ float lodBias = QualitySettings.lodBias;
+ QualitySettings.lodBias = 10f;
+ m_camera.RenderWithShader(m_depthShader, "RenderType");
+ QualitySettings.lodBias = lodBias;
+ Shader.SetGlobalTexture("_SkyAlphaTexture", m_texture);
+ Shader.SetGlobalVector("_SkyAlphaPosition", base.transform.position);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Destructible.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Destructible.cs
new file mode 100644
index 0000000..e6b56a9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Destructible.cs
@@ -0,0 +1,213 @@
+using System;
+using UnityEngine;
+
+public class Destructible : MonoBehaviour, IDestructible
+{
+ public Action m_onDestroyed;
+
+ public Action m_onDamaged;
+
+ [Header("Destruction")]
+ public DestructibleType m_destructibleType = DestructibleType.Default;
+
+ public float m_health = 1f;
+
+ public HitData.DamageModifiers m_damages;
+
+ public float m_minDamageTreshold;
+
+ public int m_minToolTier;
+
+ public float m_hitNoise;
+
+ public float m_destroyNoise;
+
+ public float m_ttl;
+
+ public GameObject m_spawnWhenDestroyed;
+
+ [Header("Effects")]
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public bool m_autoCreateFragments;
+
+ private ZNetView m_nview;
+
+ private Rigidbody m_body;
+
+ private bool m_firstFrame = true;
+
+ private bool m_destroyed;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ if ((bool)m_nview && m_nview.GetZDO() != null)
+ {
+ m_nview.Register<HitData>("Damage", RPC_Damage);
+ if (m_autoCreateFragments)
+ {
+ m_nview.Register("CreateFragments", RPC_CreateFragments);
+ }
+ if (m_ttl > 0f)
+ {
+ InvokeRepeating("DestroyNow", m_ttl, 1f);
+ }
+ }
+ }
+
+ private void Start()
+ {
+ m_firstFrame = false;
+ }
+
+ public GameObject GetParentObject()
+ {
+ return null;
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return m_destructibleType;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (!m_firstFrame && m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("Damage", hit);
+ }
+ }
+
+ private void RPC_Damage(long sender, HitData hit)
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner() || m_destroyed)
+ {
+ return;
+ }
+ float @float = m_nview.GetZDO().GetFloat("health", m_health);
+ hit.ApplyResistance(m_damages, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if ((bool)m_body)
+ {
+ m_body.AddForceAtPosition(hit.m_dir * hit.m_pushForce, hit.m_point, ForceMode.Impulse);
+ }
+ if (hit.m_toolTier < m_minToolTier)
+ {
+ DamageText.instance.ShowText(DamageText.TextType.TooHard, hit.m_point, 0f);
+ return;
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return;
+ }
+ @float -= totalDamage;
+ m_nview.GetZDO().Set("health", @float);
+ m_hitEffect.Create(hit.m_point, Quaternion.identity, base.transform);
+ if (m_onDamaged != null)
+ {
+ m_onDamaged();
+ }
+ if (m_hitNoise > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(m_hitNoise);
+ }
+ }
+ if (@float <= 0f)
+ {
+ Destroy();
+ }
+ }
+
+ private void DestroyNow()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ Destroy();
+ }
+ }
+
+ public void Destroy()
+ {
+ CreateDestructionEffects();
+ if (m_destroyNoise > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(m_destroyNoise);
+ }
+ }
+ if ((bool)m_spawnWhenDestroyed)
+ {
+ ZNetView component = UnityEngine.Object.Instantiate(m_spawnWhenDestroyed, base.transform.position, base.transform.rotation).GetComponent<ZNetView>();
+ component.SetLocalScale(base.transform.localScale);
+ component.GetZDO().SetPGWVersion(m_nview.GetZDO().GetPGWVersion());
+ }
+ if (m_onDestroyed != null)
+ {
+ m_onDestroyed();
+ }
+ ZNetScene.instance.Destroy(base.gameObject);
+ m_destroyed = true;
+ }
+
+ private void CreateDestructionEffects()
+ {
+ m_destroyedEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ if (m_autoCreateFragments)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "CreateFragments");
+ }
+ }
+
+ private void RPC_CreateFragments(long peer)
+ {
+ CreateFragments(base.gameObject);
+ }
+
+ public static void CreateFragments(GameObject rootObject, bool visibleOnly = true)
+ {
+ MeshRenderer[] componentsInChildren = rootObject.GetComponentsInChildren<MeshRenderer>(includeInactive: true);
+ int layer = LayerMask.NameToLayer("effect");
+ MeshRenderer[] array = componentsInChildren;
+ foreach (MeshRenderer meshRenderer in array)
+ {
+ if (!meshRenderer.gameObject.activeInHierarchy || (visibleOnly && !meshRenderer.isVisible))
+ {
+ continue;
+ }
+ MeshFilter component = meshRenderer.gameObject.GetComponent<MeshFilter>();
+ if (!(component == null))
+ {
+ if (component.sharedMesh == null)
+ {
+ ZLog.Log("Meshfilter missing mesh " + component.gameObject.name);
+ continue;
+ }
+ ZLog.Log("Creating fragment " + meshRenderer.gameObject.name);
+ GameObject obj = new GameObject();
+ obj.layer = layer;
+ obj.transform.position = component.gameObject.transform.position;
+ obj.transform.rotation = component.gameObject.transform.rotation;
+ obj.transform.localScale = component.gameObject.transform.lossyScale * 0.9f;
+ obj.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
+ MeshRenderer meshRenderer2 = obj.AddComponent<MeshRenderer>();
+ meshRenderer2.sharedMaterials = meshRenderer.sharedMaterials;
+ meshRenderer2.material.SetFloat("_RippleDistance", 0f);
+ meshRenderer2.material.SetFloat("_ValueNoise", 0f);
+ Rigidbody rigidbody = obj.AddComponent<Rigidbody>();
+ obj.AddComponent<BoxCollider>();
+ rigidbody.AddForce(UnityEngine.Random.onUnitSphere * 2f, ForceMode.VelocityChange);
+ obj.AddComponent<TimedDestruction>().Trigger(UnityEngine.Random.Range(2, 4));
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DestructibleType.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DestructibleType.cs
new file mode 100644
index 0000000..8060cd9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DestructibleType.cs
@@ -0,0 +1,7 @@
+public enum DestructibleType
+{
+ None = 0,
+ Default = 1,
+ Tree = 2,
+ Character = 4
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DistantFogEmitter.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DistantFogEmitter.cs
new file mode 100644
index 0000000..fb42650
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DistantFogEmitter.cs
@@ -0,0 +1,114 @@
+using System;
+using UnityEngine;
+
+public class DistantFogEmitter : MonoBehaviour
+{
+ public float m_interval = 1f;
+
+ public float m_minRadius = 100f;
+
+ public float m_maxRadius = 500f;
+
+ public float m_mountainSpawnChance = 1f;
+
+ public float m_landSpawnChance = 0.5f;
+
+ public float m_waterSpawnChance = 0.25f;
+
+ public float m_mountainLimit = 120f;
+
+ public float m_emitStep = 10f;
+
+ public int m_emitPerStep = 10;
+
+ public int m_particles = 100;
+
+ public float m_placeOffset = 1f;
+
+ public ParticleSystem[] m_psystems;
+
+ public bool m_skipWater;
+
+ private float m_placeTimer;
+
+ private bool m_emit = true;
+
+ private Vector3 m_lastPosition = Vector3.zero;
+
+ public void SetEmit(bool emit)
+ {
+ m_emit = emit;
+ }
+
+ private void Update()
+ {
+ if (!m_emit || WorldGenerator.instance == null)
+ {
+ return;
+ }
+ m_placeTimer += Time.deltaTime;
+ if (m_placeTimer > m_interval)
+ {
+ m_placeTimer = 0f;
+ int num = Mathf.Max(0, m_particles - TotalNrOfParticles());
+ num /= 4;
+ for (int i = 0; i < num; i++)
+ {
+ PlaceOne();
+ }
+ }
+ }
+
+ private int TotalNrOfParticles()
+ {
+ int num = 0;
+ ParticleSystem[] psystems = m_psystems;
+ foreach (ParticleSystem particleSystem in psystems)
+ {
+ num += particleSystem.particleCount;
+ }
+ return num;
+ }
+
+ private void PlaceOne()
+ {
+ if (GetRandomPoint(base.transform.position, out var p))
+ {
+ ParticleSystem.EmitParams emitParams = default(ParticleSystem.EmitParams);
+ emitParams.position = p + Vector3.up * m_placeOffset;
+ m_psystems[UnityEngine.Random.Range(0, m_psystems.Length)].Emit(emitParams, 1);
+ }
+ }
+
+ private bool GetRandomPoint(Vector3 center, out Vector3 p)
+ {
+ float f = UnityEngine.Random.value * (float)Math.PI * 2f;
+ float num = Mathf.Sqrt(UnityEngine.Random.value) * (m_maxRadius - m_minRadius) + m_minRadius;
+ p = center + new Vector3(Mathf.Sin(f) * num, 0f, Mathf.Cos(f) * num);
+ p.y = WorldGenerator.instance.GetHeight(p.x, p.z);
+ if (p.y < ZoneSystem.instance.m_waterLevel)
+ {
+ if (m_skipWater)
+ {
+ return false;
+ }
+ if (UnityEngine.Random.value > m_waterSpawnChance)
+ {
+ return false;
+ }
+ p.y = ZoneSystem.instance.m_waterLevel;
+ }
+ else if (p.y > m_mountainLimit)
+ {
+ if (UnityEngine.Random.value > m_mountainSpawnChance)
+ {
+ return false;
+ }
+ }
+ else if (UnityEngine.Random.value > m_landSpawnChance)
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Door.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Door.cs
new file mode 100644
index 0000000..e9ac2b9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Door.cs
@@ -0,0 +1,166 @@
+using UnityEngine;
+
+public class Door : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "door";
+
+ public GameObject m_doorObject;
+
+ public ItemDrop m_keyItem;
+
+ public EffectList m_openEffects = new EffectList();
+
+ public EffectList m_closeEffects = new EffectList();
+
+ public EffectList m_lockedEffects = new EffectList();
+
+ private ZNetView m_nview;
+
+ private Animator m_animator;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ m_animator = GetComponent<Animator>();
+ if ((bool)m_nview)
+ {
+ m_nview.Register<bool>("UseDoor", RPC_UseDoor);
+ }
+ InvokeRepeating("UpdateState", 0f, 0.2f);
+ }
+ }
+
+ private void UpdateState()
+ {
+ if (m_nview.IsValid())
+ {
+ int @int = m_nview.GetZDO().GetInt("state");
+ SetState(@int);
+ }
+ }
+
+ private void SetState(int state)
+ {
+ if (m_animator.GetInteger("state") != state)
+ {
+ if (state != 0)
+ {
+ m_openEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ else
+ {
+ m_closeEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ m_animator.SetInteger("state", state);
+ }
+ }
+
+ private bool CanInteract()
+ {
+ if (m_keyItem != null && m_nview.GetZDO().GetInt("state") != 0)
+ {
+ return false;
+ }
+ if (!m_animator.GetCurrentAnimatorStateInfo(0).IsTag("open"))
+ {
+ return m_animator.GetCurrentAnimatorStateInfo(0).IsTag("closed");
+ }
+ return true;
+ }
+
+ public string GetHoverText()
+ {
+ if (!m_nview.IsValid())
+ {
+ return "";
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position, 0f, flash: false))
+ {
+ return Localization.instance.Localize(m_name + "\n$piece_noaccess");
+ }
+ if (CanInteract())
+ {
+ if (m_nview.GetZDO().GetInt("state") != 0)
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_door_close");
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_door_open");
+ }
+ return Localization.instance.Localize(m_name);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!CanInteract())
+ {
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ return true;
+ }
+ if (m_keyItem != null)
+ {
+ if (!HaveKey(character))
+ {
+ m_lockedEffects.Create(base.transform.position, base.transform.rotation);
+ character.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_door_needkey", m_keyItem.m_itemData.m_shared.m_name));
+ return true;
+ }
+ character.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_door_usingkey", m_keyItem.m_itemData.m_shared.m_name));
+ }
+ Vector3 normalized = (character.transform.position - base.transform.position).normalized;
+ bool flag = Vector3.Dot(base.transform.forward, normalized) < 0f;
+ m_nview.InvokeRPC("UseDoor", flag);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private bool HaveKey(Humanoid player)
+ {
+ if (m_keyItem == null)
+ {
+ return true;
+ }
+ return player.GetInventory().HaveItem(m_keyItem.m_itemData.m_shared.m_name);
+ }
+
+ private void RPC_UseDoor(long uid, bool forward)
+ {
+ if (!CanInteract())
+ {
+ return;
+ }
+ if (m_nview.GetZDO().GetInt("state") == 0)
+ {
+ if (forward)
+ {
+ m_nview.GetZDO().Set("state", 1);
+ }
+ else
+ {
+ m_nview.GetZDO().Set("state", -1);
+ }
+ }
+ else
+ {
+ m_nview.GetZDO().Set("state", 0);
+ }
+ UpdateState();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DreamTexts.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DreamTexts.cs
new file mode 100644
index 0000000..4c2b44d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DreamTexts.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class DreamTexts : MonoBehaviour
+{
+ [Serializable]
+ public class DreamText
+ {
+ public string m_text = "Fluffy sheep";
+
+ public float m_chanceToDream = 0.1f;
+
+ public List<string> m_trueKeys = new List<string>();
+
+ public List<string> m_falseKeys = new List<string>();
+ }
+
+ public List<DreamText> m_texts = new List<DreamText>();
+
+ public DreamText GetRandomDreamText()
+ {
+ List<DreamText> list = new List<DreamText>();
+ foreach (DreamText text in m_texts)
+ {
+ if (HaveGlobalKeys(text))
+ {
+ list.Add(text);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ DreamText dreamText = list[UnityEngine.Random.Range(0, list.Count)];
+ if (UnityEngine.Random.value <= dreamText.m_chanceToDream)
+ {
+ return dreamText;
+ }
+ return null;
+ }
+
+ private bool HaveGlobalKeys(DreamText dream)
+ {
+ foreach (string trueKey in dream.m_trueKeys)
+ {
+ if (!ZoneSystem.instance.GetGlobalKey(trueKey))
+ {
+ return false;
+ }
+ }
+ foreach (string falseKey in dream.m_falseKeys)
+ {
+ if (ZoneSystem.instance.GetGlobalKey(falseKey))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropOnDestroyed.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropOnDestroyed.cs
new file mode 100644
index 0000000..99df9bd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropOnDestroyed.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class DropOnDestroyed : MonoBehaviour
+{
+ [Header("Drops")]
+ public DropTable m_dropWhenDestroyed = new DropTable();
+
+ public float m_spawnYOffset = 0.5f;
+
+ public float m_spawnYStep = 0.3f;
+
+ private void Awake()
+ {
+ IDestructible component = GetComponent<IDestructible>();
+ Destructible destructible = component as Destructible;
+ if ((bool)destructible)
+ {
+ destructible.m_onDestroyed = (Action)Delegate.Combine(destructible.m_onDestroyed, new Action(OnDestroyed));
+ }
+ WearNTear wearNTear = component as WearNTear;
+ if ((bool)wearNTear)
+ {
+ wearNTear.m_onDestroyed = (Action)Delegate.Combine(wearNTear.m_onDestroyed, new Action(OnDestroyed));
+ }
+ }
+
+ private void OnDestroyed()
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ Vector3 position = base.transform.position;
+ if (position.y < groundHeight)
+ {
+ position.y = groundHeight + 0.1f;
+ }
+ List<GameObject> dropList = m_dropWhenDestroyed.GetDropList();
+ for (int i = 0; i < dropList.Count; i++)
+ {
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * 0.5f;
+ Vector3 position2 = position + Vector3.up * m_spawnYOffset + new Vector3(vector.x, m_spawnYStep * (float)i, vector.y);
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ UnityEngine.Object.Instantiate(dropList[i], position2, rotation);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropTable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropTable.cs
new file mode 100644
index 0000000..b50151a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DropTable.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[Serializable]
+public class DropTable
+{
+ [Serializable]
+ public struct DropData
+ {
+ public GameObject m_item;
+
+ public int m_stackMin;
+
+ public int m_stackMax;
+
+ public float m_weight;
+ }
+
+ public List<DropData> m_drops = new List<DropData>();
+
+ public int m_dropMin = 1;
+
+ public int m_dropMax = 1;
+
+ [Range(0f, 1f)]
+ public float m_dropChance = 1f;
+
+ public bool m_oneOfEach;
+
+ public DropTable Clone()
+ {
+ return MemberwiseClone() as DropTable;
+ }
+
+ public List<ItemDrop.ItemData> GetDropListItems()
+ {
+ List<ItemDrop.ItemData> list = new List<ItemDrop.ItemData>();
+ if (m_drops.Count == 0)
+ {
+ return list;
+ }
+ if (UnityEngine.Random.value > m_dropChance)
+ {
+ return list;
+ }
+ List<DropData> list2 = new List<DropData>(m_drops);
+ float num = 0f;
+ foreach (DropData item in list2)
+ {
+ num += item.m_weight;
+ }
+ int num2 = UnityEngine.Random.Range(m_dropMin, m_dropMax + 1);
+ for (int i = 0; i < num2; i++)
+ {
+ float num3 = UnityEngine.Random.Range(0f, num);
+ bool flag = false;
+ float num4 = 0f;
+ foreach (DropData item2 in list2)
+ {
+ num4 += item2.m_weight;
+ if (num3 <= num4)
+ {
+ flag = true;
+ AddItemToList(list, item2);
+ if (m_oneOfEach)
+ {
+ list2.Remove(item2);
+ num -= item2.m_weight;
+ }
+ break;
+ }
+ }
+ if (!flag && list2.Count > 0)
+ {
+ AddItemToList(list, list2[0]);
+ }
+ }
+ return list;
+ }
+
+ private void AddItemToList(List<ItemDrop.ItemData> toDrop, DropData data)
+ {
+ ItemDrop.ItemData itemData = data.m_item.GetComponent<ItemDrop>().m_itemData;
+ ItemDrop.ItemData itemData2 = itemData.Clone();
+ itemData2.m_dropPrefab = data.m_item;
+ int min = Mathf.Max(1, data.m_stackMin);
+ int num = Mathf.Min(itemData.m_shared.m_maxStackSize, data.m_stackMax);
+ itemData2.m_stack = UnityEngine.Random.Range(min, num + 1);
+ toDrop.Add(itemData2);
+ }
+
+ public List<GameObject> GetDropList()
+ {
+ int amount = UnityEngine.Random.Range(m_dropMin, m_dropMax + 1);
+ return GetDropList(amount);
+ }
+
+ private List<GameObject> GetDropList(int amount)
+ {
+ List<GameObject> list = new List<GameObject>();
+ if (m_drops.Count == 0)
+ {
+ return list;
+ }
+ if (UnityEngine.Random.value > m_dropChance)
+ {
+ return list;
+ }
+ List<DropData> list2 = new List<DropData>(m_drops);
+ float num = 0f;
+ foreach (DropData item in list2)
+ {
+ num += item.m_weight;
+ }
+ for (int i = 0; i < amount; i++)
+ {
+ float num2 = UnityEngine.Random.Range(0f, num);
+ bool flag = false;
+ float num3 = 0f;
+ foreach (DropData item2 in list2)
+ {
+ num3 += item2.m_weight;
+ if (num2 <= num3)
+ {
+ flag = true;
+ int num4 = UnityEngine.Random.Range(item2.m_stackMin, item2.m_stackMax);
+ for (int j = 0; j < num4; j++)
+ {
+ list.Add(item2.m_item);
+ }
+ if (m_oneOfEach)
+ {
+ list2.Remove(item2);
+ num -= item2.m_weight;
+ }
+ break;
+ }
+ }
+ if (!flag && list2.Count > 0)
+ {
+ list.Add(list2[0].m_item);
+ }
+ }
+ return list;
+ }
+
+ public bool IsEmpty()
+ {
+ return m_drops.Count == 0;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonDB.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonDB.cs
new file mode 100644
index 0000000..d6a7d35
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonDB.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class DungeonDB : MonoBehaviour
+{
+ public class RoomData
+ {
+ public Room m_room;
+
+ [NonSerialized]
+ public List<ZNetView> m_netViews = new List<ZNetView>();
+
+ [NonSerialized]
+ public List<RandomSpawn> m_randomSpawns = new List<RandomSpawn>();
+ }
+
+ private static DungeonDB m_instance;
+
+ private List<RoomData> m_rooms = new List<RoomData>();
+
+ private Dictionary<int, RoomData> m_roomByHash = new Dictionary<int, RoomData>();
+
+ private bool m_error;
+
+ public static DungeonDB instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ SceneManager.LoadScene("rooms", LoadSceneMode.Additive);
+ ZLog.Log("DungeonDB Awake " + Time.frameCount);
+ }
+
+ public bool SkipSaving()
+ {
+ return m_error;
+ }
+
+ private void Start()
+ {
+ ZLog.Log("DungeonDB Start " + Time.frameCount);
+ m_rooms = SetupRooms();
+ GenerateHashList();
+ }
+
+ public static List<RoomData> GetRooms()
+ {
+ return m_instance.m_rooms;
+ }
+
+ private static List<RoomData> SetupRooms()
+ {
+ GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
+ GameObject gameObject = null;
+ GameObject[] array2 = array;
+ foreach (GameObject gameObject2 in array2)
+ {
+ if (gameObject2.name == "_Rooms")
+ {
+ gameObject = gameObject2;
+ break;
+ }
+ }
+ if (gameObject == null || ((bool)m_instance && gameObject.activeSelf))
+ {
+ if ((bool)m_instance)
+ {
+ m_instance.m_error = true;
+ }
+ ZLog.LogError("Rooms are fucked, missing _Rooms or its enabled");
+ }
+ List<RoomData> list = new List<RoomData>();
+ for (int j = 0; j < gameObject.transform.childCount; j++)
+ {
+ Room component = gameObject.transform.GetChild(j).GetComponent<Room>();
+ RoomData roomData = new RoomData();
+ roomData.m_room = component;
+ ZoneSystem.PrepareNetViews(component.gameObject, roomData.m_netViews);
+ ZoneSystem.PrepareRandomSpawns(component.gameObject, roomData.m_randomSpawns);
+ list.Add(roomData);
+ }
+ return list;
+ }
+
+ public RoomData GetRoom(int hash)
+ {
+ if (m_roomByHash.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ private void GenerateHashList()
+ {
+ m_roomByHash.Clear();
+ foreach (RoomData room in m_rooms)
+ {
+ int stableHashCode = room.m_room.gameObject.name.GetStableHashCode();
+ m_roomByHash.Add(stableHashCode, room);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonGenerator.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonGenerator.cs
new file mode 100644
index 0000000..f7a73aa
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/DungeonGenerator.cs
@@ -0,0 +1,787 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class DungeonGenerator : MonoBehaviour
+{
+ [Serializable]
+ public class DoorDef
+ {
+ public GameObject m_prefab;
+
+ public string m_connectionType = "";
+ }
+
+ public enum Algorithm
+ {
+ Dungeon,
+ CampGrid,
+ CampRadial
+ }
+
+ public Algorithm m_algorithm;
+
+ public int m_maxRooms = 3;
+
+ public int m_minRooms = 20;
+
+ public int m_minRequiredRooms;
+
+ public List<string> m_requiredRooms = new List<string>();
+
+ [BitMask(typeof(Room.Theme))]
+ public Room.Theme m_themes = Room.Theme.Crypt;
+
+ [Header("Dungeon")]
+ public List<DoorDef> m_doorTypes = new List<DoorDef>();
+
+ [Range(0f, 1f)]
+ public float m_doorChance = 0.5f;
+
+ [Header("Camp")]
+ public float m_maxTilt = 10f;
+
+ public float m_tileWidth = 8f;
+
+ public int m_gridSize = 4;
+
+ public float m_spawnChance = 1f;
+
+ [Header("Camp radial")]
+ public float m_campRadiusMin = 15f;
+
+ public float m_campRadiusMax = 30f;
+
+ public float m_minAltitude = 1f;
+
+ public int m_perimeterSections;
+
+ public float m_perimeterBuffer = 2f;
+
+ [Header("Misc")]
+ public Vector3 m_zoneCenter = new Vector3(0f, 0f, 0f);
+
+ public Vector3 m_zoneSize = new Vector3(64f, 64f, 64f);
+
+ private static List<Room> m_placedRooms = new List<Room>();
+
+ private static List<RoomConnection> m_openConnections = new List<RoomConnection>();
+
+ private static List<RoomConnection> m_doorConnections = new List<RoomConnection>();
+
+ private static List<DungeonDB.RoomData> m_availableRooms = new List<DungeonDB.RoomData>();
+
+ private static List<DungeonDB.RoomData> m_tempRooms = new List<DungeonDB.RoomData>();
+
+ private BoxCollider m_colliderA;
+
+ private BoxCollider m_colliderB;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ Load();
+ }
+
+ public void Clear()
+ {
+ while (base.transform.childCount > 0)
+ {
+ UnityEngine.Object.DestroyImmediate(base.transform.GetChild(0).gameObject);
+ }
+ }
+
+ public void Generate(ZoneSystem.SpawnMode mode)
+ {
+ int seed = WorldGenerator.instance.GetSeed();
+ Vector2i zone = ZoneSystem.instance.GetZone(base.transform.position);
+ int seed2 = seed + zone.x * 4271 + zone.y * 9187;
+ Generate(seed2, mode);
+ }
+
+ public void Generate(int seed, ZoneSystem.SpawnMode mode)
+ {
+ DateTime now = DateTime.Now;
+ Clear();
+ SetupColliders();
+ SetupAvailableRooms();
+ if ((bool)ZoneSystem.instance)
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(base.transform.position);
+ m_zoneCenter = ZoneSystem.instance.GetZonePos(zone);
+ m_zoneCenter.y = base.transform.position.y;
+ }
+ ZLog.Log("Available rooms:" + m_availableRooms.Count);
+ ZLog.Log("To place:" + m_maxRooms);
+ m_placedRooms.Clear();
+ m_openConnections.Clear();
+ m_doorConnections.Clear();
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(seed);
+ GenerateRooms(mode);
+ Save();
+ ZLog.Log("Placed " + m_placedRooms.Count + " rooms");
+ UnityEngine.Random.state = state;
+ SnapToGround.SnappAll();
+ if (mode == ZoneSystem.SpawnMode.Ghost)
+ {
+ foreach (Room placedRoom in m_placedRooms)
+ {
+ UnityEngine.Object.DestroyImmediate(placedRoom.gameObject);
+ }
+ }
+ m_placedRooms.Clear();
+ m_openConnections.Clear();
+ m_doorConnections.Clear();
+ UnityEngine.Object.DestroyImmediate(m_colliderA);
+ UnityEngine.Object.DestroyImmediate(m_colliderB);
+ _ = DateTime.Now - now;
+ }
+
+ private void GenerateRooms(ZoneSystem.SpawnMode mode)
+ {
+ switch (m_algorithm)
+ {
+ case Algorithm.Dungeon:
+ GenerateDungeon(mode);
+ break;
+ case Algorithm.CampGrid:
+ GenerateCampGrid(mode);
+ break;
+ case Algorithm.CampRadial:
+ GenerateCampRadial(mode);
+ break;
+ }
+ }
+
+ private void GenerateDungeon(ZoneSystem.SpawnMode mode)
+ {
+ PlaceStartRoom(mode);
+ PlaceRooms(mode);
+ PlaceEndCaps(mode);
+ PlaceDoors(mode);
+ }
+
+ private void GenerateCampGrid(ZoneSystem.SpawnMode mode)
+ {
+ float num = Mathf.Cos((float)Math.PI / 180f * m_maxTilt);
+ Vector3 vector = base.transform.position + new Vector3((float)(-m_gridSize) * m_tileWidth * 0.5f, 0f, (float)(-m_gridSize) * m_tileWidth * 0.5f);
+ for (int i = 0; i < m_gridSize; i++)
+ {
+ for (int j = 0; j < m_gridSize; j++)
+ {
+ if (UnityEngine.Random.value > m_spawnChance)
+ {
+ continue;
+ }
+ Vector3 p = vector + new Vector3((float)j * m_tileWidth, 0f, (float)i * m_tileWidth);
+ DungeonDB.RoomData randomWeightedRoom = GetRandomWeightedRoom(perimeterRoom: false);
+ if (randomWeightedRoom == null)
+ {
+ continue;
+ }
+ if ((bool)ZoneSystem.instance)
+ {
+ ZoneSystem.instance.GetGroundData(ref p, out var normal, out var _, out var _, out var _);
+ if (normal.y < num)
+ {
+ continue;
+ }
+ }
+ Quaternion rot = Quaternion.Euler(0f, (float)UnityEngine.Random.Range(0, 16) * 22.5f, 0f);
+ PlaceRoom(randomWeightedRoom, p, rot, null, mode);
+ }
+ }
+ }
+
+ private void GenerateCampRadial(ZoneSystem.SpawnMode mode)
+ {
+ float num = UnityEngine.Random.Range(m_campRadiusMin, m_campRadiusMax);
+ float num2 = Mathf.Cos((float)Math.PI / 180f * m_maxTilt);
+ int num3 = UnityEngine.Random.Range(m_minRooms, m_maxRooms);
+ int num4 = num3 * 20;
+ int num5 = 0;
+ for (int i = 0; i < num4; i++)
+ {
+ Vector3 p = base.transform.position + Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward * UnityEngine.Random.Range(0f, num - m_perimeterBuffer);
+ DungeonDB.RoomData randomWeightedRoom = GetRandomWeightedRoom(perimeterRoom: false);
+ if (randomWeightedRoom == null)
+ {
+ continue;
+ }
+ if ((bool)ZoneSystem.instance)
+ {
+ ZoneSystem.instance.GetGroundData(ref p, out var normal, out var _, out var _, out var _);
+ if (normal.y < num2 || p.y - ZoneSystem.instance.m_waterLevel < m_minAltitude)
+ {
+ continue;
+ }
+ }
+ Quaternion campRoomRotation = GetCampRoomRotation(randomWeightedRoom, p);
+ if (!TestCollision(randomWeightedRoom.m_room, p, campRoomRotation))
+ {
+ PlaceRoom(randomWeightedRoom, p, campRoomRotation, null, mode);
+ num5++;
+ if (num5 >= num3)
+ {
+ break;
+ }
+ }
+ }
+ if (m_perimeterSections > 0)
+ {
+ PlaceWall(num, m_perimeterSections, mode);
+ }
+ }
+
+ private Quaternion GetCampRoomRotation(DungeonDB.RoomData room, Vector3 pos)
+ {
+ if (room.m_room.m_faceCenter)
+ {
+ Vector3 vector = base.transform.position - pos;
+ vector.y = 0f;
+ if (vector == Vector3.zero)
+ {
+ vector = Vector3.forward;
+ }
+ vector.Normalize();
+ float y = Mathf.Round(Utils.YawFromDirection(vector) / 22.5f) * 22.5f;
+ return Quaternion.Euler(0f, y, 0f);
+ }
+ return Quaternion.Euler(0f, (float)UnityEngine.Random.Range(0, 16) * 22.5f, 0f);
+ }
+
+ private void PlaceWall(float radius, int sections, ZoneSystem.SpawnMode mode)
+ {
+ float num = Mathf.Cos((float)Math.PI / 180f * m_maxTilt);
+ int num2 = 0;
+ int num3 = sections * 20;
+ for (int i = 0; i < num3; i++)
+ {
+ DungeonDB.RoomData randomWeightedRoom = GetRandomWeightedRoom(perimeterRoom: true);
+ if (randomWeightedRoom == null)
+ {
+ continue;
+ }
+ Vector3 p = base.transform.position + Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward * radius;
+ Quaternion campRoomRotation = GetCampRoomRotation(randomWeightedRoom, p);
+ if ((bool)ZoneSystem.instance)
+ {
+ ZoneSystem.instance.GetGroundData(ref p, out var normal, out var _, out var _, out var _);
+ if (normal.y < num || p.y - ZoneSystem.instance.m_waterLevel < m_minAltitude)
+ {
+ continue;
+ }
+ }
+ if (!TestCollision(randomWeightedRoom.m_room, p, campRoomRotation))
+ {
+ PlaceRoom(randomWeightedRoom, p, campRoomRotation, null, mode);
+ num2++;
+ if (num2 >= sections)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ private void Save()
+ {
+ if (!(m_nview == null))
+ {
+ ZDO zDO = m_nview.GetZDO();
+ zDO.Set("rooms", m_placedRooms.Count);
+ for (int i = 0; i < m_placedRooms.Count; i++)
+ {
+ Room room = m_placedRooms[i];
+ string text = "room" + i;
+ zDO.Set(text, room.GetHash());
+ zDO.Set(text + "_pos", room.transform.position);
+ zDO.Set(text + "_rot", room.transform.rotation);
+ }
+ }
+ }
+
+ private void Load()
+ {
+ if (m_nview == null)
+ {
+ return;
+ }
+ DateTime now = DateTime.Now;
+ ZLog.Log("Loading dungeon");
+ ZDO zDO = m_nview.GetZDO();
+ int @int = zDO.GetInt("rooms");
+ for (int i = 0; i < @int; i++)
+ {
+ string text = "room" + i;
+ int int2 = zDO.GetInt(text);
+ Vector3 vec = zDO.GetVec3(text + "_pos", Vector3.zero);
+ Quaternion quaternion = zDO.GetQuaternion(text + "_rot", Quaternion.identity);
+ DungeonDB.RoomData room = DungeonDB.instance.GetRoom(int2);
+ if (room == null)
+ {
+ ZLog.LogWarning("Missing room:" + int2);
+ }
+ else
+ {
+ PlaceRoom(room, vec, quaternion, null, ZoneSystem.SpawnMode.Client);
+ }
+ }
+ ZLog.Log("Dungeon loaded " + @int);
+ ZLog.Log("Dungeon load time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ }
+
+ private void SetupAvailableRooms()
+ {
+ m_availableRooms.Clear();
+ foreach (DungeonDB.RoomData room in DungeonDB.GetRooms())
+ {
+ if ((room.m_room.m_theme & m_themes) != 0 && room.m_room.m_enabled)
+ {
+ m_availableRooms.Add(room);
+ }
+ }
+ }
+
+ private DoorDef FindDoorType(string type)
+ {
+ List<DoorDef> list = new List<DoorDef>();
+ foreach (DoorDef doorType in m_doorTypes)
+ {
+ if (doorType.m_connectionType == type)
+ {
+ list.Add(doorType);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ private void PlaceDoors(ZoneSystem.SpawnMode mode)
+ {
+ int num = 0;
+ foreach (RoomConnection doorConnection in m_doorConnections)
+ {
+ if (UnityEngine.Random.value > m_doorChance)
+ {
+ continue;
+ }
+ DoorDef doorDef = FindDoorType(doorConnection.m_type);
+ if (doorDef == null)
+ {
+ ZLog.Log("No door type for connection:" + doorConnection.m_type);
+ continue;
+ }
+ GameObject obj = UnityEngine.Object.Instantiate(doorDef.m_prefab, doorConnection.transform.position, doorConnection.transform.rotation);
+ if (mode == ZoneSystem.SpawnMode.Ghost)
+ {
+ UnityEngine.Object.Destroy(obj);
+ }
+ num++;
+ }
+ ZLog.Log("placed " + num + " doors");
+ }
+
+ private void PlaceEndCaps(ZoneSystem.SpawnMode mode)
+ {
+ for (int i = 0; i < m_openConnections.Count; i++)
+ {
+ RoomConnection roomConnection = m_openConnections[i];
+ bool flag = false;
+ for (int j = 0; j < m_openConnections.Count; j++)
+ {
+ if (j != i && roomConnection.TestContact(m_openConnections[j]))
+ {
+ flag = true;
+ break;
+ }
+ }
+ if (flag)
+ {
+ ZLog.Log("cyclic detected , cool");
+ continue;
+ }
+ FindEndCaps(roomConnection, m_tempRooms);
+ IOrderedEnumerable<DungeonDB.RoomData> orderedEnumerable = m_tempRooms.OrderByDescending((DungeonDB.RoomData item) => item.m_room.m_endCapPrio);
+ bool flag2 = false;
+ foreach (DungeonDB.RoomData item in orderedEnumerable)
+ {
+ if (PlaceRoom(roomConnection, item, mode))
+ {
+ flag2 = true;
+ break;
+ }
+ }
+ if (!flag2)
+ {
+ ZLog.LogWarning("Failed to place end cap " + roomConnection.name + " " + roomConnection.transform.parent.gameObject.name);
+ }
+ }
+ }
+
+ private void FindEndCaps(RoomConnection connection, List<DungeonDB.RoomData> rooms)
+ {
+ rooms.Clear();
+ foreach (DungeonDB.RoomData availableRoom in m_availableRooms)
+ {
+ if (availableRoom.m_room.m_endCap && availableRoom.m_room.HaveConnection(connection))
+ {
+ rooms.Add(availableRoom);
+ }
+ }
+ rooms.Shuffle();
+ }
+
+ private DungeonDB.RoomData FindEndCap(RoomConnection connection)
+ {
+ m_tempRooms.Clear();
+ foreach (DungeonDB.RoomData availableRoom in m_availableRooms)
+ {
+ if (availableRoom.m_room.m_endCap && availableRoom.m_room.HaveConnection(connection))
+ {
+ m_tempRooms.Add(availableRoom);
+ }
+ }
+ if (m_tempRooms.Count == 0)
+ {
+ return null;
+ }
+ return m_tempRooms[UnityEngine.Random.Range(0, m_tempRooms.Count)];
+ }
+
+ private void PlaceRooms(ZoneSystem.SpawnMode mode)
+ {
+ for (int i = 0; i < m_maxRooms; i++)
+ {
+ PlaceOneRoom(mode);
+ if (CheckRequiredRooms() && m_placedRooms.Count > m_minRooms)
+ {
+ ZLog.Log("All required rooms have been placed, stopping generation");
+ break;
+ }
+ }
+ }
+
+ private void PlaceStartRoom(ZoneSystem.SpawnMode mode)
+ {
+ DungeonDB.RoomData roomData = FindStartRoom();
+ RoomConnection entrance = roomData.m_room.GetEntrance();
+ Quaternion rotation = base.transform.rotation;
+ CalculateRoomPosRot(entrance, base.transform.position, rotation, out var pos, out var rot);
+ PlaceRoom(roomData, pos, rot, entrance, mode);
+ }
+
+ private bool PlaceOneRoom(ZoneSystem.SpawnMode mode)
+ {
+ RoomConnection openConnection = GetOpenConnection();
+ if (openConnection == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < 10; i++)
+ {
+ DungeonDB.RoomData randomRoom = GetRandomRoom(openConnection);
+ if (randomRoom == null)
+ {
+ break;
+ }
+ if (PlaceRoom(openConnection, randomRoom, mode))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void CalculateRoomPosRot(RoomConnection roomCon, Vector3 exitPos, Quaternion exitRot, out Vector3 pos, out Quaternion rot)
+ {
+ Quaternion quaternion = Quaternion.Inverse(roomCon.transform.localRotation);
+ rot = exitRot * quaternion;
+ Vector3 localPosition = roomCon.transform.localPosition;
+ pos = exitPos - rot * localPosition;
+ }
+
+ private bool PlaceRoom(RoomConnection connection, DungeonDB.RoomData roomData, ZoneSystem.SpawnMode mode)
+ {
+ Room room = roomData.m_room;
+ Quaternion rotation = connection.transform.rotation;
+ rotation *= Quaternion.Euler(0f, 180f, 0f);
+ RoomConnection connection2 = room.GetConnection(connection);
+ CalculateRoomPosRot(connection2, connection.transform.position, rotation, out var pos, out var rot);
+ if (room.m_size.x != 0 && room.m_size.z != 0 && TestCollision(room, pos, rot))
+ {
+ return false;
+ }
+ PlaceRoom(roomData, pos, rot, connection, mode);
+ if (!room.m_endCap)
+ {
+ if (connection.m_allowDoor)
+ {
+ m_doorConnections.Add(connection);
+ }
+ m_openConnections.Remove(connection);
+ }
+ return true;
+ }
+
+ private void PlaceRoom(DungeonDB.RoomData room, Vector3 pos, Quaternion rot, RoomConnection fromConnection, ZoneSystem.SpawnMode mode)
+ {
+ int seed = (int)pos.x * 4271 + (int)pos.y * 9187 + (int)pos.z * 2134;
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(seed);
+ if (mode == ZoneSystem.SpawnMode.Full || mode == ZoneSystem.SpawnMode.Ghost)
+ {
+ foreach (ZNetView netView in room.m_netViews)
+ {
+ netView.gameObject.SetActive(value: true);
+ }
+ foreach (RandomSpawn randomSpawn in room.m_randomSpawns)
+ {
+ randomSpawn.Randomize();
+ }
+ Vector3 position = room.m_room.transform.position;
+ Quaternion quaternion = Quaternion.Inverse(room.m_room.transform.rotation);
+ foreach (ZNetView netView2 in room.m_netViews)
+ {
+ if (netView2.gameObject.activeSelf)
+ {
+ Vector3 vector = quaternion * (netView2.gameObject.transform.position - position);
+ Vector3 position2 = pos + rot * vector;
+ Quaternion quaternion2 = quaternion * netView2.gameObject.transform.rotation;
+ Quaternion rotation = rot * quaternion2;
+ GameObject gameObject = UnityEngine.Object.Instantiate(netView2.gameObject, position2, rotation);
+ ZNetView component = gameObject.GetComponent<ZNetView>();
+ if (component.GetZDO() != null)
+ {
+ component.GetZDO().SetPGWVersion(ZoneSystem.instance.m_pgwVersion);
+ }
+ if (mode == ZoneSystem.SpawnMode.Ghost)
+ {
+ UnityEngine.Object.Destroy(gameObject);
+ }
+ }
+ }
+ }
+ else
+ {
+ foreach (RandomSpawn randomSpawn2 in room.m_randomSpawns)
+ {
+ randomSpawn2.Randomize();
+ }
+ }
+ foreach (ZNetView netView3 in room.m_netViews)
+ {
+ netView3.gameObject.SetActive(value: false);
+ }
+ Room component2 = UnityEngine.Object.Instantiate(room.m_room.gameObject, pos, rot, base.transform).GetComponent<Room>();
+ component2.gameObject.name = room.m_room.gameObject.name;
+ if (mode != ZoneSystem.SpawnMode.Client)
+ {
+ component2.m_placeOrder = (fromConnection ? (fromConnection.m_placeOrder + 1) : 0);
+ m_placedRooms.Add(component2);
+ AddOpenConnections(component2, fromConnection);
+ }
+ UnityEngine.Random.state = state;
+ }
+
+ private void AddOpenConnections(Room newRoom, RoomConnection skipConnection)
+ {
+ RoomConnection[] connections = newRoom.GetConnections();
+ if (skipConnection != null)
+ {
+ RoomConnection[] array = connections;
+ foreach (RoomConnection roomConnection in array)
+ {
+ if (!roomConnection.m_entrance && !(Vector3.Distance(roomConnection.transform.position, skipConnection.transform.position) < 0.1f))
+ {
+ roomConnection.m_placeOrder = newRoom.m_placeOrder;
+ m_openConnections.Add(roomConnection);
+ }
+ }
+ }
+ else
+ {
+ RoomConnection[] array = connections;
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i].m_placeOrder = newRoom.m_placeOrder;
+ }
+ m_openConnections.AddRange(connections);
+ }
+ }
+
+ private void SetupColliders()
+ {
+ if (!(m_colliderA != null))
+ {
+ BoxCollider[] componentsInChildren = base.gameObject.GetComponentsInChildren<BoxCollider>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ UnityEngine.Object.DestroyImmediate(componentsInChildren[i]);
+ }
+ m_colliderA = base.gameObject.AddComponent<BoxCollider>();
+ m_colliderB = base.gameObject.AddComponent<BoxCollider>();
+ }
+ }
+
+ public void Derp()
+ {
+ }
+
+ private bool IsInsideDungeon(Room room, Vector3 pos, Quaternion rot)
+ {
+ Bounds bounds = new Bounds(m_zoneCenter, m_zoneSize);
+ Vector3 vector = room.m_size;
+ vector *= 0.5f;
+ if (!bounds.Contains(pos + rot * new Vector3(vector.x, vector.y, 0f - vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(0f - vector.x, vector.y, 0f - vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(vector.x, vector.y, vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(0f - vector.x, vector.y, vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(vector.x, 0f - vector.y, 0f - vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(0f - vector.x, 0f - vector.y, 0f - vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(vector.x, 0f - vector.y, vector.z)))
+ {
+ return false;
+ }
+ if (!bounds.Contains(pos + rot * new Vector3(0f - vector.x, 0f - vector.y, vector.z)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool TestCollision(Room room, Vector3 pos, Quaternion rot)
+ {
+ if (!IsInsideDungeon(room, pos, rot))
+ {
+ return true;
+ }
+ m_colliderA.size = new Vector3((float)room.m_size.x - 0.1f, (float)room.m_size.y - 0.1f, (float)room.m_size.z - 0.1f);
+ foreach (Room placedRoom in m_placedRooms)
+ {
+ m_colliderB.size = placedRoom.m_size;
+ if (Physics.ComputePenetration(m_colliderA, pos, rot, m_colliderB, placedRoom.transform.position, placedRoom.transform.rotation, out var _, out var _))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private DungeonDB.RoomData GetRandomWeightedRoom(bool perimeterRoom)
+ {
+ m_tempRooms.Clear();
+ float num = 0f;
+ foreach (DungeonDB.RoomData availableRoom in m_availableRooms)
+ {
+ if (!availableRoom.m_room.m_entrance && !availableRoom.m_room.m_endCap && availableRoom.m_room.m_perimeter == perimeterRoom)
+ {
+ num += availableRoom.m_room.m_weight;
+ m_tempRooms.Add(availableRoom);
+ }
+ }
+ if (m_tempRooms.Count == 0)
+ {
+ return null;
+ }
+ float num2 = UnityEngine.Random.Range(0f, num);
+ float num3 = 0f;
+ foreach (DungeonDB.RoomData tempRoom in m_tempRooms)
+ {
+ num3 += tempRoom.m_room.m_weight;
+ if (num2 <= num3)
+ {
+ return tempRoom;
+ }
+ }
+ return m_tempRooms[0];
+ }
+
+ private DungeonDB.RoomData GetRandomRoom(RoomConnection connection)
+ {
+ m_tempRooms.Clear();
+ foreach (DungeonDB.RoomData availableRoom in m_availableRooms)
+ {
+ if (!availableRoom.m_room.m_entrance && !availableRoom.m_room.m_endCap && (!connection || (availableRoom.m_room.HaveConnection(connection) && connection.m_placeOrder >= availableRoom.m_room.m_minPlaceOrder)))
+ {
+ m_tempRooms.Add(availableRoom);
+ }
+ }
+ if (m_tempRooms.Count == 0)
+ {
+ return null;
+ }
+ return m_tempRooms[UnityEngine.Random.Range(0, m_tempRooms.Count)];
+ }
+
+ private RoomConnection GetOpenConnection()
+ {
+ if (m_openConnections.Count == 0)
+ {
+ return null;
+ }
+ return m_openConnections[UnityEngine.Random.Range(0, m_openConnections.Count)];
+ }
+
+ private DungeonDB.RoomData FindStartRoom()
+ {
+ m_tempRooms.Clear();
+ foreach (DungeonDB.RoomData availableRoom in m_availableRooms)
+ {
+ if (availableRoom.m_room.m_entrance)
+ {
+ m_tempRooms.Add(availableRoom);
+ }
+ }
+ return m_tempRooms[UnityEngine.Random.Range(0, m_tempRooms.Count)];
+ }
+
+ private bool CheckRequiredRooms()
+ {
+ if (m_minRequiredRooms == 0 || m_requiredRooms.Count == 0)
+ {
+ return false;
+ }
+ int num = 0;
+ foreach (Room placedRoom in m_placedRooms)
+ {
+ if (m_requiredRooms.Contains(placedRoom.gameObject.name))
+ {
+ num++;
+ }
+ }
+ return num >= m_minRequiredRooms;
+ }
+
+ private void OnDrawGizmos()
+ {
+ Gizmos.color = new Color(0f, 1.5f, 0f, 0.5f);
+ Gizmos.DrawWireCube(m_zoneCenter, new Vector3(m_zoneSize.x, m_zoneSize.y, m_zoneSize.z));
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectArea.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectArea.cs
new file mode 100644
index 0000000..0fbedb1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectArea.cs
@@ -0,0 +1,108 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class EffectArea : MonoBehaviour
+{
+ public enum Type
+ {
+ Heat = 1,
+ Fire = 2,
+ PlayerBase = 4,
+ Burning = 8,
+ Teleport = 16,
+ NoMonsters = 32,
+ None = 999
+ }
+
+ [BitMask(typeof(Type))]
+ public Type m_type = Type.None;
+
+ public string m_statusEffect = "";
+
+ private Collider m_collider;
+
+ private static int m_characterMask = 0;
+
+ private static List<EffectArea> m_allAreas = new List<EffectArea>();
+
+ private static Collider[] m_tempColliders = new Collider[128];
+
+ private void Awake()
+ {
+ if (m_characterMask == 0)
+ {
+ m_characterMask = LayerMask.GetMask("character_trigger");
+ }
+ m_collider = GetComponent<Collider>();
+ m_allAreas.Add(this);
+ }
+
+ private void OnDestroy()
+ {
+ m_allAreas.Remove(this);
+ }
+
+ private void OnTriggerStay(Collider collider)
+ {
+ if (ZNet.instance == null)
+ {
+ return;
+ }
+ Character component = collider.GetComponent<Character>();
+ if ((bool)component && component.IsOwner())
+ {
+ if (!string.IsNullOrEmpty(m_statusEffect))
+ {
+ component.GetSEMan().AddStatusEffect(m_statusEffect, resetTime: true);
+ }
+ if ((m_type & Type.Heat) != 0)
+ {
+ component.OnNearFire(base.transform.position);
+ }
+ }
+ }
+
+ public float GetRadius()
+ {
+ SphereCollider sphereCollider = m_collider as SphereCollider;
+ if (sphereCollider != null)
+ {
+ return sphereCollider.radius;
+ }
+ return m_collider.bounds.size.magnitude;
+ }
+
+ public static EffectArea IsPointInsideArea(Vector3 p, Type type, float radius = 0f)
+ {
+ int num = Physics.OverlapSphereNonAlloc(p, radius, m_tempColliders, m_characterMask);
+ for (int i = 0; i < num; i++)
+ {
+ EffectArea component = m_tempColliders[i].GetComponent<EffectArea>();
+ if ((bool)component && (component.m_type & type) != 0)
+ {
+ return component;
+ }
+ }
+ return null;
+ }
+
+ public static int GetBaseValue(Vector3 p, float radius)
+ {
+ int num = 0;
+ int num2 = Physics.OverlapSphereNonAlloc(p, radius, m_tempColliders, m_characterMask);
+ for (int i = 0; i < num2; i++)
+ {
+ EffectArea component = m_tempColliders[i].GetComponent<EffectArea>();
+ if ((bool)component && (component.m_type & Type.PlayerBase) != 0)
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ public static List<EffectArea> GetAllAreas()
+ {
+ return m_allAreas;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectFade.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectFade.cs
new file mode 100644
index 0000000..cefd3a0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectFade.cs
@@ -0,0 +1,66 @@
+using UnityEngine;
+
+public class EffectFade : MonoBehaviour
+{
+ public float m_fadeDuration = 1f;
+
+ private ParticleSystem[] m_particles;
+
+ private Light m_light;
+
+ private AudioSource m_audioSource;
+
+ private float m_baseVolume;
+
+ private float m_lightBaseIntensity;
+
+ private bool m_active = true;
+
+ private float m_intensity;
+
+ private void Awake()
+ {
+ m_particles = base.gameObject.GetComponentsInChildren<ParticleSystem>();
+ m_light = base.gameObject.GetComponentInChildren<Light>();
+ m_audioSource = base.gameObject.GetComponentInChildren<AudioSource>();
+ if ((bool)m_light)
+ {
+ m_lightBaseIntensity = m_light.intensity;
+ m_light.intensity = 0f;
+ }
+ if ((bool)m_audioSource)
+ {
+ m_baseVolume = m_audioSource.volume;
+ m_audioSource.volume = 0f;
+ }
+ SetActive(active: false);
+ }
+
+ private void Update()
+ {
+ m_intensity = Mathf.MoveTowards(m_intensity, m_active ? 1f : 0f, Time.deltaTime / m_fadeDuration);
+ if ((bool)m_light)
+ {
+ m_light.intensity = m_intensity * m_lightBaseIntensity;
+ m_light.enabled = m_light.intensity > 0f;
+ }
+ if ((bool)m_audioSource)
+ {
+ m_audioSource.volume = m_intensity * m_baseVolume;
+ }
+ }
+
+ public void SetActive(bool active)
+ {
+ if (m_active != active)
+ {
+ m_active = active;
+ ParticleSystem[] particles = m_particles;
+ for (int i = 0; i < particles.Length; i++)
+ {
+ ParticleSystem.EmissionModule emission = particles[i].emission;
+ emission.enabled = active;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectList.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectList.cs
new file mode 100644
index 0000000..61350b6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EffectList.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[Serializable]
+public class EffectList
+{
+ [Serializable]
+ public class EffectData
+ {
+ public GameObject m_prefab;
+
+ public bool m_enabled = true;
+
+ public bool m_attach;
+
+ public bool m_inheritParentRotation;
+
+ public bool m_inheritParentScale;
+
+ public bool m_randomRotation;
+
+ public bool m_scale;
+ }
+
+ public EffectData[] m_effectPrefabs = new EffectData[0];
+
+ public GameObject[] Create(Vector3 pos, Quaternion rot, Transform parent = null, float scale = 1f)
+ {
+ List<GameObject> list = new List<GameObject>();
+ for (int i = 0; i < m_effectPrefabs.Length; i++)
+ {
+ EffectData effectData = m_effectPrefabs[i];
+ if (!effectData.m_enabled)
+ {
+ continue;
+ }
+ if ((bool)parent && m_effectPrefabs[i].m_inheritParentRotation)
+ {
+ rot = parent.rotation;
+ }
+ if (effectData.m_randomRotation)
+ {
+ rot = UnityEngine.Random.rotation;
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(effectData.m_prefab, pos, rot);
+ if (effectData.m_scale)
+ {
+ if ((bool)parent && m_effectPrefabs[i].m_inheritParentScale)
+ {
+ Vector3 localScale = parent.localScale * scale;
+ gameObject.transform.localScale = localScale;
+ }
+ else
+ {
+ gameObject.transform.localScale = new Vector3(scale, scale, scale);
+ }
+ }
+ else if ((bool)parent && m_effectPrefabs[i].m_inheritParentScale)
+ {
+ gameObject.transform.localScale = parent.localScale;
+ }
+ if (effectData.m_attach && parent != null)
+ {
+ gameObject.transform.SetParent(parent);
+ }
+ list.Add(gameObject);
+ }
+ return list.ToArray();
+ }
+
+ public bool HasEffects()
+ {
+ if (m_effectPrefabs == null || m_effectPrefabs.Length == 0)
+ {
+ return false;
+ }
+ EffectData[] effectPrefabs = m_effectPrefabs;
+ for (int i = 0; i < effectPrefabs.Length; i++)
+ {
+ if (effectPrefabs[i].m_enabled)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EmitterRotation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EmitterRotation.cs
new file mode 100644
index 0000000..41fe5e5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EmitterRotation.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+
+public class EmitterRotation : MonoBehaviour
+{
+ public float m_maxSpeed = 10f;
+
+ public float m_rotSpeed = 90f;
+
+ private Vector3 m_lastPos;
+
+ private ParticleSystem m_ps;
+
+ private void Start()
+ {
+ m_lastPos = base.transform.position;
+ m_ps = GetComponentInChildren<ParticleSystem>();
+ }
+
+ private void Update()
+ {
+ if (m_ps.emission.enabled)
+ {
+ Vector3 position = base.transform.position;
+ Vector3 vector = position - m_lastPos;
+ m_lastPos = position;
+ float t = Mathf.Clamp01(vector.magnitude / Time.deltaTime / m_maxSpeed);
+ if (vector == Vector3.zero)
+ {
+ vector = Vector3.up;
+ }
+ Quaternion a = Quaternion.LookRotation(Vector3.up);
+ Quaternion b = Quaternion.LookRotation(vector);
+ Quaternion to = Quaternion.Lerp(a, b, t);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, to, Time.deltaTime * m_rotSpeed);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnemyHud.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnemyHud.cs
new file mode 100644
index 0000000..3c4802a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnemyHud.cs
@@ -0,0 +1,216 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class EnemyHud : MonoBehaviour
+{
+ private class HudData
+ {
+ public Character m_character;
+
+ public BaseAI m_ai;
+
+ public GameObject m_gui;
+
+ public GameObject m_healthRoot;
+
+ public RectTransform m_level2;
+
+ public RectTransform m_level3;
+
+ public GuiBar m_healthFast;
+
+ public GuiBar m_healthSlow;
+
+ public Text m_name;
+
+ public float m_hoverTimer = 99999f;
+ }
+
+ private static EnemyHud m_instance;
+
+ public GameObject m_hudRoot;
+
+ public GameObject m_baseHud;
+
+ public GameObject m_baseHudBoss;
+
+ public GameObject m_baseHudPlayer;
+
+ public float m_maxShowDistance = 10f;
+
+ public float m_maxShowDistanceBoss = 100f;
+
+ public float m_hoverShowDuration = 60f;
+
+ private Vector3 m_refPoint = Vector3.zero;
+
+ private Dictionary<Character, HudData> m_huds = new Dictionary<Character, HudData>();
+
+ public static EnemyHud instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_baseHud.SetActive(value: false);
+ m_baseHudBoss.SetActive(value: false);
+ m_baseHudPlayer.SetActive(value: false);
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void LateUpdate()
+ {
+ m_hudRoot.SetActive(!Hud.IsUserHidden());
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer != null)
+ {
+ m_refPoint = localPlayer.transform.position;
+ }
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (!(allCharacter == localPlayer) && TestShow(allCharacter))
+ {
+ ShowHud(allCharacter);
+ }
+ }
+ UpdateHuds(localPlayer, Time.deltaTime);
+ }
+
+ private bool TestShow(Character c)
+ {
+ float num = Vector3.SqrMagnitude(c.transform.position - m_refPoint);
+ if (c.IsBoss() && num < m_maxShowDistanceBoss * m_maxShowDistanceBoss)
+ {
+ if (num < m_maxShowDistanceBoss * m_maxShowDistanceBoss && c.GetComponent<BaseAI>().IsAlerted())
+ {
+ return true;
+ }
+ }
+ else if (num < m_maxShowDistance * m_maxShowDistance)
+ {
+ if (c.IsPlayer() && c.IsCrouching())
+ {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void ShowHud(Character c)
+ {
+ if (!m_huds.TryGetValue(c, out var value))
+ {
+ GameObject original = (c.IsPlayer() ? m_baseHudPlayer : ((!c.IsBoss()) ? m_baseHud : m_baseHudBoss));
+ value = new HudData();
+ value.m_character = c;
+ value.m_ai = c.GetComponent<BaseAI>();
+ value.m_gui = Object.Instantiate(original, m_hudRoot.transform);
+ value.m_gui.SetActive(value: true);
+ value.m_healthRoot = value.m_gui.transform.Find("Health").gameObject;
+ value.m_healthFast = value.m_healthRoot.transform.Find("health_fast").GetComponent<GuiBar>();
+ value.m_healthSlow = value.m_healthRoot.transform.Find("health_slow").GetComponent<GuiBar>();
+ value.m_level2 = value.m_gui.transform.Find("level_2") as RectTransform;
+ value.m_level3 = value.m_gui.transform.Find("level_3") as RectTransform;
+ value.m_name = value.m_gui.transform.Find("Name").GetComponent<Text>();
+ value.m_name.text = Localization.instance.Localize(c.GetHoverName());
+ m_huds.Add(c, value);
+ }
+ }
+
+ private void UpdateHuds(Player player, float dt)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!mainCamera)
+ {
+ return;
+ }
+ Character character = (player ? player.GetHoverCreature() : null);
+ Character character2 = null;
+ foreach (KeyValuePair<Character, HudData> hud in m_huds)
+ {
+ HudData value = hud.Value;
+ if (!value.m_character || !TestShow(value.m_character))
+ {
+ if (character2 == null)
+ {
+ character2 = value.m_character;
+ Object.Destroy(value.m_gui);
+ }
+ continue;
+ }
+ if (value.m_character == character)
+ {
+ value.m_hoverTimer = 0f;
+ }
+ value.m_hoverTimer += dt;
+ float healthPercentage = value.m_character.GetHealthPercentage();
+ if (value.m_character.IsPlayer() || value.m_character.IsBoss() || value.m_hoverTimer < m_hoverShowDuration)
+ {
+ value.m_gui.SetActive(value: true);
+ int level = value.m_character.GetLevel();
+ if ((bool)value.m_level2)
+ {
+ value.m_level2.gameObject.SetActive(level == 2);
+ }
+ if ((bool)value.m_level3)
+ {
+ value.m_level3.gameObject.SetActive(level == 3);
+ }
+ }
+ else
+ {
+ value.m_gui.SetActive(value: false);
+ }
+ value.m_healthSlow.SetValue(healthPercentage);
+ value.m_healthFast.SetValue(healthPercentage);
+ if (!value.m_character.IsBoss() && value.m_gui.activeSelf)
+ {
+ Vector3 zero = Vector3.zero;
+ zero = ((!value.m_character.IsPlayer()) ? value.m_character.GetTopPoint() : (value.m_character.GetHeadPoint() + Vector3.up * 0.3f));
+ Vector3 position = mainCamera.WorldToScreenPoint(zero);
+ if (position.x < 0f || position.x > (float)Screen.width || position.y < 0f || position.y > (float)Screen.height || position.z > 0f)
+ {
+ value.m_gui.transform.position = position;
+ value.m_gui.SetActive(value: true);
+ }
+ else
+ {
+ value.m_gui.SetActive(value: false);
+ }
+ }
+ }
+ if (character2 != null)
+ {
+ m_huds.Remove(character2);
+ }
+ }
+
+ public bool ShowingBossHud()
+ {
+ foreach (KeyValuePair<Character, HudData> hud in m_huds)
+ {
+ if ((bool)hud.Value.m_character && hud.Value.m_character.IsBoss())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Character GetActiveBoss()
+ {
+ foreach (KeyValuePair<Character, HudData> hud in m_huds)
+ {
+ if ((bool)hud.Value.m_character && hud.Value.m_character.IsBoss())
+ {
+ return hud.Value.m_character;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvEntry.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvEntry.cs
new file mode 100644
index 0000000..e21e0fe
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvEntry.cs
@@ -0,0 +1,12 @@
+using System;
+
+[Serializable]
+public class EnvEntry
+{
+ public string m_environment = "";
+
+ public float m_weight = 1f;
+
+ [NonSerialized]
+ public EnvSetup m_env;
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvMan.cs
new file mode 100644
index 0000000..7119264
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvMan.cs
@@ -0,0 +1,987 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+using UnityStandardAssets.ImageEffects;
+
+public class EnvMan : MonoBehaviour
+{
+ private static EnvMan m_instance;
+
+ public Light m_dirLight;
+
+ public bool m_debugTimeOfDay;
+
+ [Range(0f, 1f)]
+ public float m_debugTime = 0.5f;
+
+ public string m_debugEnv = "";
+
+ public bool m_debugWind;
+
+ [Range(0f, 360f)]
+ public float m_debugWindAngle;
+
+ [Range(0f, 1f)]
+ public float m_debugWindIntensity = 1f;
+
+ private const float m_morningL = 0.15f;
+
+ public float m_sunHorizonTransitionH = 0.08f;
+
+ public float m_sunHorizonTransitionL = 0.02f;
+
+ public long m_dayLengthSec = 1200L;
+
+ public float m_transitionDuration = 2f;
+
+ public long m_environmentDuration = 20L;
+
+ public long m_windPeriodDuration = 10L;
+
+ public float m_windTransitionDuration = 5f;
+
+ public List<EnvSetup> m_environments = new List<EnvSetup>();
+
+ public List<BiomeEnvSetup> m_biomes = new List<BiomeEnvSetup>();
+
+ public string m_introEnvironment = "ThunderStorm";
+
+ public float m_edgeOfWorldWidth = 500f;
+
+ [Header("Music")]
+ public float m_randomMusicIntervalMin = 60f;
+
+ public float m_randomMusicIntervalMax = 200f;
+
+ [Header("Other")]
+ public MeshRenderer m_clouds;
+
+ public MeshRenderer m_rainClouds;
+
+ public MeshRenderer m_rainCloudsDownside;
+
+ public float m_wetTransitionDuration = 15f;
+
+ private bool m_skipTime;
+
+ private double m_skipToTime;
+
+ private double m_timeSkipSpeed = 1.0;
+
+ private const double m_timeSkipDuration = 12.0;
+
+ private double m_totalSeconds;
+
+ private float m_smoothDayFraction;
+
+ private Color m_sunFogColor = Color.white;
+
+ private GameObject[] m_currentPSystems;
+
+ private GameObject m_currentEnvObject;
+
+ private Vector4 m_windDir1 = new Vector4(0f, 0f, -1f, 0f);
+
+ private Vector4 m_windDir2 = new Vector4(0f, 0f, -1f, 0f);
+
+ private Vector4 m_wind = new Vector4(0f, 0f, -1f, 0f);
+
+ private float m_windTransitionTimer = -1f;
+
+ private Vector3 m_cloudOffset = Vector3.zero;
+
+ private string m_forceEnv = "";
+
+ private EnvSetup m_currentEnv;
+
+ private EnvSetup m_prevEnv;
+
+ private EnvSetup m_nextEnv;
+
+ private string m_ambientMusic;
+
+ private float m_ambientMusicTimer;
+
+ private Heightmap m_cachedHeightmap;
+
+ private Heightmap.Biome m_currentBiome;
+
+ private long m_environmentPeriod;
+
+ private float m_transitionTimer;
+
+ private bool m_firstEnv = true;
+
+ private int _NetRefPos = Shader.PropertyToID("_NetRefPos");
+
+ private int _SkyboxSunDir = Shader.PropertyToID("_SkyboxSunDir");
+
+ private int _SunDir = Shader.PropertyToID("_SunDir");
+
+ private int _SunFogColor = Shader.PropertyToID("_SunFogColor");
+
+ private int _Wet = Shader.PropertyToID("_Wet");
+
+ private int _SunColor = Shader.PropertyToID("_SunColor");
+
+ private int _AmbientColor = Shader.PropertyToID("_AmbientColor");
+
+ private int _GlobalWind1 = Shader.PropertyToID("_GlobalWind1");
+
+ private int _GlobalWind2 = Shader.PropertyToID("_GlobalWind2");
+
+ private int _GlobalWindAlpha = Shader.PropertyToID("_GlobalWindAlpha");
+
+ private int _CloudOffset = Shader.PropertyToID("_CloudOffset");
+
+ private int _GlobalWindForce = Shader.PropertyToID("_GlobalWindForce");
+
+ private int _Rain = Shader.PropertyToID("_Rain");
+
+ public static EnvMan instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ foreach (EnvSetup environment in m_environments)
+ {
+ SetParticleArrayEnabled(environment.m_psystems, enabled: false);
+ if ((bool)environment.m_envObject)
+ {
+ environment.m_envObject.SetActive(value: false);
+ }
+ }
+ foreach (BiomeEnvSetup biome in m_biomes)
+ {
+ foreach (EnvEntry environment2 in biome.m_environments)
+ {
+ environment2.m_env = GetEnv(environment2.m_environment);
+ }
+ }
+ m_currentEnv = GetDefaultEnv();
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void SetParticleArrayEnabled(GameObject[] psystems, bool enabled)
+ {
+ foreach (GameObject gameObject in psystems)
+ {
+ ParticleSystem[] componentsInChildren = gameObject.GetComponentsInChildren<ParticleSystem>();
+ for (int j = 0; j < componentsInChildren.Length; j++)
+ {
+ ParticleSystem.EmissionModule emission = componentsInChildren[j].emission;
+ emission.enabled = enabled;
+ }
+ MistEmitter componentInChildren = gameObject.GetComponentInChildren<MistEmitter>();
+ if ((bool)componentInChildren)
+ {
+ componentInChildren.enabled = enabled;
+ }
+ }
+ }
+
+ private float RescaleDayFraction(float fraction)
+ {
+ if (fraction >= 0.15f && fraction <= 0.85f)
+ {
+ float num = (fraction - 0.15f) / 0.7f;
+ fraction = 0.25f + num * 0.5f;
+ }
+ else if (fraction < 0.5f)
+ {
+ fraction = fraction / 0.15f * 0.25f;
+ }
+ else
+ {
+ float num2 = (fraction - 0.85f) / 0.15f;
+ fraction = 0.75f + num2 * 0.25f;
+ }
+ return fraction;
+ }
+
+ private void Update()
+ {
+ Vector3 windForce = instance.GetWindForce();
+ m_cloudOffset += windForce * Time.deltaTime * 0.01f;
+ Shader.SetGlobalVector(_CloudOffset, m_cloudOffset);
+ Shader.SetGlobalVector(_NetRefPos, ZNet.instance.GetReferencePosition());
+ }
+
+ private void FixedUpdate()
+ {
+ UpdateTimeSkip(Time.fixedDeltaTime);
+ m_totalSeconds = ZNet.instance.GetTimeSeconds();
+ long num = (long)m_totalSeconds;
+ double num2 = m_totalSeconds * 1000.0;
+ long num3 = m_dayLengthSec * 1000;
+ float fraction = Mathf.Clamp01((float)(num2 % (double)num3 / 1000.0) / (float)m_dayLengthSec);
+ fraction = RescaleDayFraction(fraction);
+ float smoothDayFraction = m_smoothDayFraction;
+ float t = Mathf.LerpAngle(m_smoothDayFraction * 360f, fraction * 360f, 0.01f);
+ m_smoothDayFraction = Mathf.Repeat(t, 360f) / 360f;
+ if (m_debugTimeOfDay)
+ {
+ m_smoothDayFraction = m_debugTime;
+ }
+ float num4 = Mathf.Pow(Mathf.Max(1f - Mathf.Clamp01(m_smoothDayFraction / 0.25f), Mathf.Clamp01((m_smoothDayFraction - 0.75f) / 0.25f)), 0.5f);
+ float num5 = Mathf.Pow(Mathf.Clamp01(1f - Mathf.Abs(m_smoothDayFraction - 0.5f) / 0.25f), 0.5f);
+ float num6 = Mathf.Min(Mathf.Clamp01(1f - (m_smoothDayFraction - 0.26f) / (0f - m_sunHorizonTransitionL)), Mathf.Clamp01(1f - (m_smoothDayFraction - 0.26f) / m_sunHorizonTransitionH));
+ float num7 = Mathf.Min(Mathf.Clamp01(1f - (m_smoothDayFraction - 0.74f) / (0f - m_sunHorizonTransitionH)), Mathf.Clamp01(1f - (m_smoothDayFraction - 0.74f) / m_sunHorizonTransitionL));
+ float num8 = 1f / (num4 + num5 + num6 + num7);
+ num4 *= num8;
+ num5 *= num8;
+ num6 *= num8;
+ num7 *= num8;
+ Heightmap.Biome biome = GetBiome();
+ UpdateTriggers(smoothDayFraction, m_smoothDayFraction, biome, Time.fixedDeltaTime);
+ UpdateEnvironment(num, biome);
+ InterpolateEnvironment(Time.fixedDeltaTime);
+ UpdateWind(num, Time.fixedDeltaTime);
+ if (!string.IsNullOrEmpty(m_forceEnv))
+ {
+ EnvSetup env = GetEnv(m_forceEnv);
+ if (env != null)
+ {
+ SetEnv(env, num5, num4, num6, num7, Time.fixedDeltaTime);
+ }
+ }
+ else
+ {
+ SetEnv(m_currentEnv, num5, num4, num6, num7, Time.fixedDeltaTime);
+ }
+ }
+
+ private int GetCurrentDay()
+ {
+ return (int)(m_totalSeconds / (double)m_dayLengthSec);
+ }
+
+ private void UpdateTriggers(float oldDayFraction, float newDayFraction, Heightmap.Biome biome, float dt)
+ {
+ if (Player.m_localPlayer == null || biome == Heightmap.Biome.None)
+ {
+ return;
+ }
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ if (currentEnvironment != null)
+ {
+ UpdateAmbientMusic(biome, currentEnvironment, dt);
+ if (oldDayFraction > 0.2f && oldDayFraction < 0.25f && newDayFraction > 0.25f && newDayFraction < 0.3f)
+ {
+ OnMorning(biome, currentEnvironment);
+ }
+ if (oldDayFraction > 0.7f && oldDayFraction < 0.75f && newDayFraction > 0.75f && newDayFraction < 0.8f)
+ {
+ OnEvening(biome, currentEnvironment);
+ }
+ }
+ }
+
+ private void UpdateAmbientMusic(Heightmap.Biome biome, EnvSetup currentEnv, float dt)
+ {
+ m_ambientMusicTimer += dt;
+ if (!(m_ambientMusicTimer > 2f))
+ {
+ return;
+ }
+ m_ambientMusicTimer = 0f;
+ m_ambientMusic = null;
+ BiomeEnvSetup biomeEnvSetup = GetBiomeEnvSetup(biome);
+ if (IsDay())
+ {
+ if (currentEnv.m_musicDay.Length > 0)
+ {
+ m_ambientMusic = currentEnv.m_musicDay;
+ }
+ else if (biomeEnvSetup.m_musicDay.Length > 0)
+ {
+ m_ambientMusic = biomeEnvSetup.m_musicDay;
+ }
+ }
+ else if (currentEnv.m_musicNight.Length > 0)
+ {
+ m_ambientMusic = currentEnv.m_musicNight;
+ }
+ else if (biomeEnvSetup.m_musicNight.Length > 0)
+ {
+ m_ambientMusic = biomeEnvSetup.m_musicNight;
+ }
+ }
+
+ public string GetAmbientMusic()
+ {
+ return m_ambientMusic;
+ }
+
+ private void OnMorning(Heightmap.Biome biome, EnvSetup currentEnv)
+ {
+ string text = "morning";
+ if (currentEnv.m_musicMorning.Length > 0)
+ {
+ text = currentEnv.m_musicMorning;
+ }
+ else
+ {
+ BiomeEnvSetup biomeEnvSetup = GetBiomeEnvSetup(biome);
+ if (biomeEnvSetup.m_musicMorning.Length > 0)
+ {
+ text = biomeEnvSetup.m_musicMorning;
+ }
+ }
+ MusicMan.instance.TriggerMusic(text);
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_newday", GetCurrentDay().ToString()));
+ }
+
+ private void OnEvening(Heightmap.Biome biome, EnvSetup currentEnv)
+ {
+ string text = "evening";
+ if (currentEnv.m_musicEvening.Length > 0)
+ {
+ text = currentEnv.m_musicEvening;
+ }
+ else
+ {
+ BiomeEnvSetup biomeEnvSetup = GetBiomeEnvSetup(biome);
+ if (biomeEnvSetup.m_musicEvening.Length > 0)
+ {
+ text = biomeEnvSetup.m_musicEvening;
+ }
+ }
+ MusicMan.instance.TriggerMusic(text);
+ }
+
+ public void SetForceEnvironment(string env)
+ {
+ if (!(m_forceEnv == env))
+ {
+ ZLog.Log("Setting forced environment " + env);
+ m_forceEnv = env;
+ FixedUpdate();
+ if ((bool)ReflectionUpdate.instance)
+ {
+ ReflectionUpdate.instance.UpdateReflection();
+ }
+ }
+ }
+
+ private EnvSetup SelectWeightedEnvironment(List<EnvEntry> environments)
+ {
+ float num = 0f;
+ foreach (EnvEntry environment in environments)
+ {
+ num += environment.m_weight;
+ }
+ float num2 = UnityEngine.Random.Range(0f, num);
+ float num3 = 0f;
+ foreach (EnvEntry environment2 in environments)
+ {
+ num3 += environment2.m_weight;
+ if (num3 >= num2)
+ {
+ return environment2.m_env;
+ }
+ }
+ return environments[environments.Count - 1].m_env;
+ }
+
+ private string GetEnvironmentOverride()
+ {
+ if (!string.IsNullOrEmpty(m_debugEnv))
+ {
+ return m_debugEnv;
+ }
+ if (Player.m_localPlayer != null && Player.m_localPlayer.InIntro())
+ {
+ return m_introEnvironment;
+ }
+ string envOverride = RandEventSystem.instance.GetEnvOverride();
+ if (!string.IsNullOrEmpty(envOverride))
+ {
+ return envOverride;
+ }
+ string environment = EnvZone.GetEnvironment();
+ if (!string.IsNullOrEmpty(environment))
+ {
+ return environment;
+ }
+ return null;
+ }
+
+ private void UpdateEnvironment(long sec, Heightmap.Biome biome)
+ {
+ string environmentOverride = GetEnvironmentOverride();
+ if (!string.IsNullOrEmpty(environmentOverride))
+ {
+ m_environmentPeriod = -1L;
+ m_currentBiome = GetBiome();
+ QueueEnvironment(environmentOverride);
+ return;
+ }
+ long num = sec / m_environmentDuration;
+ if (m_environmentPeriod != num || m_currentBiome != biome)
+ {
+ m_environmentPeriod = num;
+ m_currentBiome = biome;
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState((int)num);
+ List<EnvEntry> availableEnvironments = GetAvailableEnvironments(biome);
+ if (availableEnvironments != null && availableEnvironments.Count > 0)
+ {
+ EnvSetup env = SelectWeightedEnvironment(availableEnvironments);
+ QueueEnvironment(env);
+ }
+ UnityEngine.Random.state = state;
+ }
+ }
+
+ private BiomeEnvSetup GetBiomeEnvSetup(Heightmap.Biome biome)
+ {
+ foreach (BiomeEnvSetup biome2 in m_biomes)
+ {
+ if (biome2.m_biome == biome)
+ {
+ return biome2;
+ }
+ }
+ return null;
+ }
+
+ private List<EnvEntry> GetAvailableEnvironments(Heightmap.Biome biome)
+ {
+ return GetBiomeEnvSetup(biome)?.m_environments;
+ }
+
+ private Heightmap.Biome GetBiome()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return Heightmap.Biome.None;
+ }
+ Vector3 position = mainCamera.transform.position;
+ if (m_cachedHeightmap == null || !m_cachedHeightmap.IsPointInside(position))
+ {
+ m_cachedHeightmap = Heightmap.FindHeightmap(position);
+ }
+ if ((bool)m_cachedHeightmap)
+ {
+ return m_cachedHeightmap.GetBiome(position);
+ }
+ return Heightmap.Biome.None;
+ }
+
+ private void InterpolateEnvironment(float dt)
+ {
+ if (m_nextEnv != null)
+ {
+ m_transitionTimer += dt;
+ float num = Mathf.Clamp01(m_transitionTimer / m_transitionDuration);
+ m_currentEnv = InterpolateEnvironment(m_prevEnv, m_nextEnv, num);
+ if (num >= 1f)
+ {
+ m_currentEnv = m_nextEnv;
+ m_prevEnv = null;
+ m_nextEnv = null;
+ }
+ }
+ }
+
+ private void QueueEnvironment(string name)
+ {
+ if (!(m_currentEnv.m_name == name) && (m_nextEnv == null || !(m_nextEnv.m_name == name)))
+ {
+ EnvSetup env = GetEnv(name);
+ if (env != null)
+ {
+ QueueEnvironment(env);
+ }
+ }
+ }
+
+ private void QueueEnvironment(EnvSetup env)
+ {
+ if (m_firstEnv)
+ {
+ m_firstEnv = false;
+ m_currentEnv = env;
+ }
+ else
+ {
+ m_prevEnv = m_currentEnv.Clone();
+ m_nextEnv = env;
+ m_transitionTimer = 0f;
+ }
+ }
+
+ private EnvSetup InterpolateEnvironment(EnvSetup a, EnvSetup b, float i)
+ {
+ EnvSetup envSetup = a.Clone();
+ envSetup.m_name = b.m_name;
+ if (i >= 0.5f)
+ {
+ envSetup.m_isFreezingAtNight = b.m_isFreezingAtNight;
+ envSetup.m_isFreezing = b.m_isFreezing;
+ envSetup.m_isCold = b.m_isCold;
+ envSetup.m_isColdAtNight = b.m_isColdAtNight;
+ envSetup.m_isColdAtNight = b.m_isColdAtNight;
+ }
+ envSetup.m_ambColorDay = Color.Lerp(a.m_ambColorDay, b.m_ambColorDay, i);
+ envSetup.m_ambColorNight = Color.Lerp(a.m_ambColorNight, b.m_ambColorNight, i);
+ envSetup.m_fogColorDay = Color.Lerp(a.m_fogColorDay, b.m_fogColorDay, i);
+ envSetup.m_fogColorEvening = Color.Lerp(a.m_fogColorEvening, b.m_fogColorEvening, i);
+ envSetup.m_fogColorMorning = Color.Lerp(a.m_fogColorMorning, b.m_fogColorMorning, i);
+ envSetup.m_fogColorNight = Color.Lerp(a.m_fogColorNight, b.m_fogColorNight, i);
+ envSetup.m_fogColorSunDay = Color.Lerp(a.m_fogColorSunDay, b.m_fogColorSunDay, i);
+ envSetup.m_fogColorSunEvening = Color.Lerp(a.m_fogColorSunEvening, b.m_fogColorSunEvening, i);
+ envSetup.m_fogColorSunMorning = Color.Lerp(a.m_fogColorSunMorning, b.m_fogColorSunMorning, i);
+ envSetup.m_fogColorSunNight = Color.Lerp(a.m_fogColorSunNight, b.m_fogColorSunNight, i);
+ envSetup.m_fogDensityDay = Mathf.Lerp(a.m_fogDensityDay, b.m_fogDensityDay, i);
+ envSetup.m_fogDensityEvening = Mathf.Lerp(a.m_fogDensityEvening, b.m_fogDensityEvening, i);
+ envSetup.m_fogDensityMorning = Mathf.Lerp(a.m_fogDensityMorning, b.m_fogDensityMorning, i);
+ envSetup.m_fogDensityNight = Mathf.Lerp(a.m_fogDensityNight, b.m_fogDensityNight, i);
+ envSetup.m_sunColorDay = Color.Lerp(a.m_sunColorDay, b.m_sunColorDay, i);
+ envSetup.m_sunColorEvening = Color.Lerp(a.m_sunColorEvening, b.m_sunColorEvening, i);
+ envSetup.m_sunColorMorning = Color.Lerp(a.m_sunColorMorning, b.m_sunColorMorning, i);
+ envSetup.m_sunColorNight = Color.Lerp(a.m_sunColorNight, b.m_sunColorNight, i);
+ envSetup.m_lightIntensityDay = Mathf.Lerp(a.m_lightIntensityDay, b.m_lightIntensityDay, i);
+ envSetup.m_lightIntensityNight = Mathf.Lerp(a.m_lightIntensityNight, b.m_lightIntensityNight, i);
+ envSetup.m_sunAngle = Mathf.Lerp(a.m_sunAngle, b.m_sunAngle, i);
+ envSetup.m_windMin = Mathf.Lerp(a.m_windMin, b.m_windMin, i);
+ envSetup.m_windMax = Mathf.Lerp(a.m_windMax, b.m_windMax, i);
+ envSetup.m_rainCloudAlpha = Mathf.Lerp(a.m_rainCloudAlpha, b.m_rainCloudAlpha, i);
+ envSetup.m_ambientLoop = ((i > 0.75f) ? b.m_ambientLoop : a.m_ambientLoop);
+ envSetup.m_ambientVol = ((i > 0.75f) ? b.m_ambientVol : a.m_ambientVol);
+ envSetup.m_musicEvening = b.m_musicEvening;
+ envSetup.m_musicMorning = b.m_musicMorning;
+ envSetup.m_musicDay = b.m_musicDay;
+ envSetup.m_musicNight = b.m_musicNight;
+ return envSetup;
+ }
+
+ private void SetEnv(EnvSetup env, float dayInt, float nightInt, float morningInt, float eveningInt, float dt)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return;
+ }
+ m_dirLight.transform.rotation = Quaternion.Euler(-90f + env.m_sunAngle, 0f, 0f) * Quaternion.Euler(0f, -90f, 0f) * Quaternion.Euler(-90f + 360f * m_smoothDayFraction, 0f, 0f);
+ Vector3 vector = -m_dirLight.transform.forward;
+ m_dirLight.intensity = env.m_lightIntensityDay * dayInt;
+ m_dirLight.intensity += env.m_lightIntensityNight * nightInt;
+ if (nightInt > 0f)
+ {
+ m_dirLight.transform.rotation = m_dirLight.transform.rotation * Quaternion.Euler(180f, 0f, 0f);
+ }
+ m_dirLight.transform.position = mainCamera.transform.position - m_dirLight.transform.forward * 3000f;
+ m_dirLight.color = new Color(0f, 0f, 0f, 0f);
+ m_dirLight.color += env.m_sunColorNight * nightInt;
+ if (dayInt > 0f)
+ {
+ m_dirLight.color += env.m_sunColorDay * dayInt;
+ m_dirLight.color += env.m_sunColorMorning * morningInt;
+ m_dirLight.color += env.m_sunColorEvening * eveningInt;
+ }
+ RenderSettings.fogColor = new Color(0f, 0f, 0f, 0f);
+ RenderSettings.fogColor += env.m_fogColorNight * nightInt;
+ RenderSettings.fogColor += env.m_fogColorDay * dayInt;
+ RenderSettings.fogColor += env.m_fogColorMorning * morningInt;
+ RenderSettings.fogColor += env.m_fogColorEvening * eveningInt;
+ m_sunFogColor = new Color(0f, 0f, 0f, 0f);
+ m_sunFogColor += env.m_fogColorSunNight * nightInt;
+ if (dayInt > 0f)
+ {
+ m_sunFogColor += env.m_fogColorSunDay * dayInt;
+ m_sunFogColor += env.m_fogColorSunMorning * morningInt;
+ m_sunFogColor += env.m_fogColorSunEvening * eveningInt;
+ }
+ m_sunFogColor = Color.Lerp(RenderSettings.fogColor, m_sunFogColor, Mathf.Clamp01(Mathf.Max(nightInt, dayInt) * 3f));
+ RenderSettings.fogDensity = 0f;
+ RenderSettings.fogDensity += env.m_fogDensityNight * nightInt;
+ RenderSettings.fogDensity += env.m_fogDensityDay * dayInt;
+ RenderSettings.fogDensity += env.m_fogDensityMorning * morningInt;
+ RenderSettings.fogDensity += env.m_fogDensityEvening * eveningInt;
+ RenderSettings.ambientMode = AmbientMode.Flat;
+ RenderSettings.ambientLight = Color.Lerp(env.m_ambColorNight, env.m_ambColorDay, dayInt);
+ SunShafts component = mainCamera.GetComponent<SunShafts>();
+ if ((bool)component)
+ {
+ component.sunColor = m_dirLight.color;
+ }
+ if (env.m_envObject != m_currentEnvObject)
+ {
+ if ((bool)m_currentEnvObject)
+ {
+ m_currentEnvObject.SetActive(value: false);
+ m_currentEnvObject = null;
+ }
+ if ((bool)env.m_envObject)
+ {
+ m_currentEnvObject = env.m_envObject;
+ m_currentEnvObject.SetActive(value: true);
+ }
+ }
+ if (env.m_psystems != m_currentPSystems)
+ {
+ if (m_currentPSystems != null)
+ {
+ SetParticleArrayEnabled(m_currentPSystems, enabled: false);
+ m_currentPSystems = null;
+ }
+ if (env.m_psystems != null && (!env.m_psystemsOutsideOnly || ((bool)Player.m_localPlayer && !Player.m_localPlayer.InShelter())))
+ {
+ SetParticleArrayEnabled(env.m_psystems, enabled: true);
+ m_currentPSystems = env.m_psystems;
+ }
+ }
+ m_clouds.material.SetFloat(_Rain, env.m_rainCloudAlpha);
+ if ((bool)env.m_ambientLoop)
+ {
+ AudioMan.instance.QueueAmbientLoop(env.m_ambientLoop, env.m_ambientVol);
+ }
+ else
+ {
+ AudioMan.instance.StopAmbientLoop();
+ }
+ Shader.SetGlobalVector(_SkyboxSunDir, vector);
+ Shader.SetGlobalVector(_SkyboxSunDir, vector);
+ Shader.SetGlobalVector(_SunDir, -m_dirLight.transform.forward);
+ Shader.SetGlobalColor(_SunFogColor, m_sunFogColor);
+ Shader.SetGlobalColor(_SunColor, m_dirLight.color * m_dirLight.intensity);
+ Shader.SetGlobalColor(_AmbientColor, RenderSettings.ambientLight);
+ float globalFloat = Shader.GetGlobalFloat(_Wet);
+ globalFloat = Mathf.MoveTowards(globalFloat, env.m_isWet ? 1f : 0f, dt / m_wetTransitionDuration);
+ Shader.SetGlobalFloat(_Wet, globalFloat);
+ }
+
+ private float GetDayFraction()
+ {
+ return m_smoothDayFraction;
+ }
+
+ public int GetDay(double time)
+ {
+ return (int)(time / (double)m_dayLengthSec);
+ }
+
+ public double GetMorningStartSec(int day)
+ {
+ return (float)(day * m_dayLengthSec) + (float)m_dayLengthSec * 0.15f;
+ }
+
+ private void UpdateTimeSkip(float dt)
+ {
+ if (ZNet.instance.IsServer() && m_skipTime)
+ {
+ double timeSeconds = ZNet.instance.GetTimeSeconds();
+ timeSeconds += (double)dt * m_timeSkipSpeed;
+ if (timeSeconds >= m_skipToTime)
+ {
+ timeSeconds = m_skipToTime;
+ m_skipTime = false;
+ }
+ ZNet.instance.SetNetTime(timeSeconds);
+ }
+ }
+
+ public bool IsTimeSkipping()
+ {
+ return m_skipTime;
+ }
+
+ public void SkipToMorning()
+ {
+ double timeSeconds = ZNet.instance.GetTimeSeconds();
+ double time = timeSeconds - (double)((float)m_dayLengthSec * 0.15f);
+ int day = GetDay(time);
+ double morningStartSec = GetMorningStartSec(day + 1);
+ m_skipTime = true;
+ m_skipToTime = morningStartSec;
+ double num = morningStartSec - timeSeconds;
+ m_timeSkipSpeed = num / 12.0;
+ ZLog.Log("Time " + timeSeconds + ", day:" + day + " nextm:" + morningStartSec + " skipspeed:" + m_timeSkipSpeed);
+ }
+
+ public bool IsDay()
+ {
+ float dayFraction = GetDayFraction();
+ if (dayFraction >= 0.25f)
+ {
+ return dayFraction <= 0.75f;
+ }
+ return false;
+ }
+
+ public bool IsAfternoon()
+ {
+ float dayFraction = GetDayFraction();
+ if (dayFraction >= 0.5f)
+ {
+ return dayFraction <= 0.75f;
+ }
+ return false;
+ }
+
+ public bool IsNight()
+ {
+ float dayFraction = GetDayFraction();
+ if (!(dayFraction <= 0.25f))
+ {
+ return dayFraction >= 0.75f;
+ }
+ return true;
+ }
+
+ public bool IsDaylight()
+ {
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ if (currentEnvironment != null && currentEnvironment.m_alwaysDark)
+ {
+ return false;
+ }
+ return IsDay();
+ }
+
+ public Heightmap.Biome GetCurrentBiome()
+ {
+ return m_currentBiome;
+ }
+
+ public bool IsEnvironment(string name)
+ {
+ return GetCurrentEnvironment().m_name == name;
+ }
+
+ public bool IsEnvironment(List<string> names)
+ {
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ return names.Contains(currentEnvironment.m_name);
+ }
+
+ public EnvSetup GetCurrentEnvironment()
+ {
+ if (!string.IsNullOrEmpty(m_forceEnv))
+ {
+ EnvSetup env = GetEnv(m_forceEnv);
+ if (env != null)
+ {
+ return env;
+ }
+ }
+ return m_currentEnv;
+ }
+
+ public bool IsFreezing()
+ {
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ if (currentEnvironment == null)
+ {
+ return false;
+ }
+ if (currentEnvironment.m_isFreezing)
+ {
+ return true;
+ }
+ if (currentEnvironment.m_isFreezingAtNight && !IsDay())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsCold()
+ {
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ if (currentEnvironment == null)
+ {
+ return false;
+ }
+ if (currentEnvironment.m_isCold)
+ {
+ return true;
+ }
+ if (currentEnvironment.m_isColdAtNight && !IsDay())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsWet()
+ {
+ return GetCurrentEnvironment()?.m_isWet ?? false;
+ }
+
+ public Color GetSunFogColor()
+ {
+ return m_sunFogColor;
+ }
+
+ public Vector3 GetSunDirection()
+ {
+ return m_dirLight.transform.forward;
+ }
+
+ private EnvSetup GetEnv(string name)
+ {
+ foreach (EnvSetup environment in m_environments)
+ {
+ if (environment.m_name == name)
+ {
+ return environment;
+ }
+ }
+ return null;
+ }
+
+ private EnvSetup GetDefaultEnv()
+ {
+ foreach (EnvSetup environment in m_environments)
+ {
+ if (environment.m_default)
+ {
+ return environment;
+ }
+ }
+ return null;
+ }
+
+ public void SetDebugWind(float angle, float intensity)
+ {
+ m_debugWind = true;
+ m_debugWindAngle = angle;
+ m_debugWindIntensity = Mathf.Clamp01(intensity);
+ }
+
+ public void ResetDebugWind()
+ {
+ m_debugWind = false;
+ }
+
+ public Vector3 GetWindForce()
+ {
+ return GetWindDir() * m_wind.w;
+ }
+
+ public Vector3 GetWindDir()
+ {
+ return new Vector3(m_wind.x, m_wind.y, m_wind.z);
+ }
+
+ public float GetWindIntensity()
+ {
+ return m_wind.w;
+ }
+
+ private void UpdateWind(long timeSec, float dt)
+ {
+ if (m_debugWind)
+ {
+ float f = (float)Math.PI / 180f * m_debugWindAngle;
+ Vector3 dir = new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f));
+ SetTargetWind(dir, m_debugWindIntensity);
+ }
+ else
+ {
+ EnvSetup currentEnvironment = GetCurrentEnvironment();
+ if (currentEnvironment != null)
+ {
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ float angle = 0f;
+ float intensity = 0.5f;
+ AddWindOctave(timeSec, 1, ref angle, ref intensity);
+ AddWindOctave(timeSec, 2, ref angle, ref intensity);
+ AddWindOctave(timeSec, 4, ref angle, ref intensity);
+ AddWindOctave(timeSec, 8, ref angle, ref intensity);
+ UnityEngine.Random.state = state;
+ Vector3 dir2 = new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle));
+ intensity = Mathf.Lerp(currentEnvironment.m_windMin, currentEnvironment.m_windMax, intensity);
+ if ((bool)Player.m_localPlayer)
+ {
+ float magnitude = Player.m_localPlayer.transform.position.magnitude;
+ if (magnitude > 10500f - m_edgeOfWorldWidth)
+ {
+ float num = Utils.LerpStep(10500f - m_edgeOfWorldWidth, 10500f, magnitude);
+ num = 1f - Mathf.Pow(1f - num, 2f);
+ dir2 = Player.m_localPlayer.transform.position.normalized;
+ intensity = Mathf.Lerp(intensity, 1f, num);
+ }
+ else
+ {
+ Ship localShip = Ship.GetLocalShip();
+ if ((bool)localShip && localShip.IsWindControllActive())
+ {
+ dir2 = localShip.transform.forward;
+ }
+ }
+ }
+ SetTargetWind(dir2, intensity);
+ }
+ }
+ UpdateWindTransition(dt);
+ }
+
+ private void AddWindOctave(long timeSec, int octave, ref float angle, ref float intensity)
+ {
+ UnityEngine.Random.InitState((int)(timeSec / (m_windPeriodDuration / octave)));
+ angle += UnityEngine.Random.value * ((float)Math.PI * 2f / (float)octave);
+ intensity += 0f - 0.5f / (float)octave + UnityEngine.Random.value / (float)octave;
+ }
+
+ private void SetTargetWind(Vector3 dir, float intensity)
+ {
+ if (!(m_windTransitionTimer >= 0f))
+ {
+ intensity = Mathf.Clamp(intensity, 0.05f, 1f);
+ if (!Mathf.Approximately(dir.x, m_windDir1.x) || !Mathf.Approximately(dir.y, m_windDir1.y) || !Mathf.Approximately(dir.z, m_windDir1.z) || !Mathf.Approximately(intensity, m_windDir1.w))
+ {
+ m_windTransitionTimer = 0f;
+ m_windDir2 = new Vector4(dir.x, dir.y, dir.z, intensity);
+ }
+ }
+ }
+
+ private void UpdateWindTransition(float dt)
+ {
+ if (m_windTransitionTimer >= 0f)
+ {
+ m_windTransitionTimer += dt;
+ float num = Mathf.Clamp01(m_windTransitionTimer / m_windTransitionDuration);
+ Shader.SetGlobalVector(_GlobalWind1, m_windDir1);
+ Shader.SetGlobalVector(_GlobalWind2, m_windDir2);
+ Shader.SetGlobalFloat(_GlobalWindAlpha, num);
+ m_wind = Vector4.Lerp(m_windDir1, m_windDir2, num);
+ if (num >= 1f)
+ {
+ m_windDir1 = m_windDir2;
+ m_windTransitionTimer = -1f;
+ }
+ }
+ else
+ {
+ Shader.SetGlobalVector(_GlobalWind1, m_windDir1);
+ Shader.SetGlobalFloat(_GlobalWindAlpha, 0f);
+ m_wind = m_windDir1;
+ }
+ Shader.SetGlobalVector(_GlobalWindForce, GetWindForce());
+ }
+
+ public void GetWindData(out Vector4 wind1, out Vector4 wind2, out float alpha)
+ {
+ wind1 = m_windDir1;
+ wind2 = m_windDir2;
+ if (m_windTransitionTimer >= 0f)
+ {
+ alpha = Mathf.Clamp01(m_windTransitionTimer / m_windTransitionDuration);
+ }
+ else
+ {
+ alpha = 0f;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvSetup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvSetup.cs
new file mode 100644
index 0000000..deb01ad
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvSetup.cs
@@ -0,0 +1,108 @@
+using System;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+[Serializable]
+public class EnvSetup
+{
+ public string m_name = "";
+
+ public bool m_default;
+
+ [Header("Gameplay")]
+ public bool m_isWet;
+
+ public bool m_isFreezing;
+
+ public bool m_isFreezingAtNight;
+
+ public bool m_isCold;
+
+ public bool m_isColdAtNight = true;
+
+ public bool m_alwaysDark;
+
+ [Header("Ambience")]
+ public Color m_ambColorNight = Color.white;
+
+ public Color m_ambColorDay = Color.white;
+
+ [Header("Fog-ambient")]
+ public Color m_fogColorNight = Color.white;
+
+ public Color m_fogColorMorning = Color.white;
+
+ public Color m_fogColorDay = Color.white;
+
+ public Color m_fogColorEvening = Color.white;
+
+ [Header("Fog-sun")]
+ public Color m_fogColorSunNight = Color.white;
+
+ public Color m_fogColorSunMorning = Color.white;
+
+ public Color m_fogColorSunDay = Color.white;
+
+ public Color m_fogColorSunEvening = Color.white;
+
+ [Header("Fog-distance")]
+ public float m_fogDensityNight = 0.01f;
+
+ public float m_fogDensityMorning = 0.01f;
+
+ public float m_fogDensityDay = 0.01f;
+
+ public float m_fogDensityEvening = 0.01f;
+
+ [Header("Sun")]
+ public Color m_sunColorNight = Color.white;
+
+ public Color m_sunColorMorning = Color.white;
+
+ public Color m_sunColorDay = Color.white;
+
+ public Color m_sunColorEvening = Color.white;
+
+ public float m_lightIntensityDay = 1.2f;
+
+ public float m_lightIntensityNight;
+
+ public float m_sunAngle = 60f;
+
+ [Header("Wind")]
+ public float m_windMin;
+
+ public float m_windMax = 1f;
+
+ [Header("Effects")]
+ public GameObject m_envObject;
+
+ public GameObject[] m_psystems;
+
+ public bool m_psystemsOutsideOnly;
+
+ public float m_rainCloudAlpha;
+
+ [Header("Audio")]
+ public AudioClip m_ambientLoop;
+
+ public float m_ambientVol = 0.3f;
+
+ public string m_ambientList = "";
+
+ [Header("Music overrides")]
+ public string m_musicMorning = "";
+
+ public string m_musicEvening = "";
+
+ [FormerlySerializedAs("m_musicRandomDay")]
+ public string m_musicDay = "";
+
+ [FormerlySerializedAs("m_musicRandomNight")]
+ public string m_musicNight = "";
+
+ public EnvSetup Clone()
+ {
+ return MemberwiseClone() as EnvSetup;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvZone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvZone.cs
new file mode 100644
index 0000000..210d6e5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EnvZone.cs
@@ -0,0 +1,49 @@
+using UnityEngine;
+
+public class EnvZone : MonoBehaviour
+{
+ public string m_environment = "";
+
+ public bool m_force = true;
+
+ private static EnvZone m_triggered;
+
+ private void OnTriggerStay(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ if (m_force)
+ {
+ EnvMan.instance.SetForceEnvironment(m_environment);
+ }
+ m_triggered = this;
+ }
+ }
+
+ private void OnTriggerExit(Collider collider)
+ {
+ if (m_triggered != this)
+ {
+ return;
+ }
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ if (m_force)
+ {
+ EnvMan.instance.SetForceEnvironment("");
+ }
+ m_triggered = null;
+ }
+ }
+
+ public static string GetEnvironment()
+ {
+ if ((bool)m_triggered && !m_triggered.m_force)
+ {
+ return m_triggered.m_environment;
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EventZone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EventZone.cs
new file mode 100644
index 0000000..3601944
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/EventZone.cs
@@ -0,0 +1,38 @@
+using UnityEngine;
+
+public class EventZone : MonoBehaviour
+{
+ public string m_event = "";
+
+ private static EventZone m_triggered;
+
+ private void OnTriggerStay(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ m_triggered = this;
+ }
+ }
+
+ private void OnTriggerExit(Collider collider)
+ {
+ if (!(m_triggered != this))
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ m_triggered = null;
+ }
+ }
+ }
+
+ public static string GetEvent()
+ {
+ if ((bool)m_triggered && m_triggered.m_event.Length > 0)
+ {
+ return m_triggered.m_event;
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Feedback.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Feedback.cs
new file mode 100644
index 0000000..05a7db3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Feedback.cs
@@ -0,0 +1,91 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Feedback : MonoBehaviour
+{
+ private static Feedback m_instance;
+
+ public Text m_subject;
+
+ public Text m_text;
+
+ public Button m_sendButton;
+
+ public Toggle m_catBug;
+
+ public Toggle m_catFeedback;
+
+ public Toggle m_catIdea;
+
+ private void Awake()
+ {
+ m_instance = this;
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public static bool IsVisible()
+ {
+ return m_instance != null;
+ }
+
+ private void LateUpdate()
+ {
+ m_sendButton.interactable = IsValid();
+ if (IsVisible() && (Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("JoyMenu")))
+ {
+ OnBack();
+ }
+ }
+
+ private bool IsValid()
+ {
+ if (m_subject.text.Length == 0)
+ {
+ return false;
+ }
+ if (m_text.text.Length == 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public void OnBack()
+ {
+ Object.Destroy(base.gameObject);
+ }
+
+ public void OnSend()
+ {
+ if (IsValid())
+ {
+ string category = GetCategory();
+ GoogleAnalyticsV4.instance.LogEvent("Feedback_" + category, m_subject.text, m_text.text, 0L);
+ Object.Destroy(base.gameObject);
+ }
+ }
+
+ private string GetCategory()
+ {
+ if (m_catBug.isOn)
+ {
+ return "Bug";
+ }
+ if (m_catFeedback.isOn)
+ {
+ return "Feedback";
+ }
+ if (m_catIdea.isOn)
+ {
+ return "Idea";
+ }
+ return "";
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FejdStartup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FejdStartup.cs
new file mode 100644
index 0000000..3de4355
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FejdStartup.cs
@@ -0,0 +1,1393 @@
+using System;
+using System.Collections.Generic;
+using Steamworks;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.SceneManagement;
+using UnityEngine.UI;
+
+public class FejdStartup : MonoBehaviour
+{
+ private Vector3 camSpeed = Vector3.zero;
+
+ private Vector3 camRotSpeed = Vector3.zero;
+
+ private static FejdStartup m_instance;
+
+ [Header("Start")]
+ public Animator m_menuAnimator;
+
+ public GameObject m_worldVersionPanel;
+
+ public GameObject m_playerVersionPanel;
+
+ public GameObject m_newGameVersionPanel;
+
+ public GameObject m_connectionFailedPanel;
+
+ public Text m_connectionFailedError;
+
+ public Text m_newVersionName;
+
+ public GameObject m_loading;
+
+ public Text m_versionLabel;
+
+ public GameObject m_mainMenu;
+
+ public GameObject m_ndaPanel;
+
+ public GameObject m_betaText;
+
+ public GameObject m_characterSelectScreen;
+
+ public GameObject m_selectCharacterPanel;
+
+ public GameObject m_newCharacterPanel;
+
+ public GameObject m_creditsPanel;
+
+ public GameObject m_startGamePanel;
+
+ public GameObject m_createWorldPanel;
+
+ [Header("Camera")]
+ public GameObject m_mainCamera;
+
+ public Transform m_cameraMarkerStart;
+
+ public Transform m_cameraMarkerMain;
+
+ public Transform m_cameraMarkerCharacter;
+
+ public Transform m_cameraMarkerCredits;
+
+ public Transform m_cameraMarkerGame;
+
+ public float m_cameraMoveSpeed = 1.5f;
+
+ public float m_cameraMoveSpeedStart = 1.5f;
+
+ [Header("Join")]
+ public GameObject m_serverListPanel;
+
+ public Toggle m_publicServerToggle;
+
+ public Toggle m_openServerToggle;
+
+ public InputField m_serverPassword;
+
+ public RectTransform m_serverListRoot;
+
+ public GameObject m_serverListElement;
+
+ public ScrollRectEnsureVisible m_serverListEnsureVisible;
+
+ public float m_serverListElementStep = 28f;
+
+ public Text m_serverCount;
+
+ public Button m_serverRefreshButton;
+
+ public InputField m_filterInputField;
+
+ public Text m_passwordError;
+
+ public Button m_manualIPButton;
+
+ public GameObject m_joinIPPanel;
+
+ public Button m_joinIPJoinButton;
+
+ public InputField m_joinIPAddress;
+
+ public Button m_joinGameButton;
+
+ public Toggle m_friendFilterSwitch;
+
+ public Toggle m_publicFilterSwitch;
+
+ public int m_minimumPasswordLength = 5;
+
+ public float m_characterRotateSpeed = 4f;
+
+ public float m_characterRotateSpeedGamepad = 200f;
+
+ public int m_joinHostPort = 2456;
+
+ public int m_serverPlayerLimit = 10;
+
+ [Header("World")]
+ public GameObject m_worldListPanel;
+
+ public RectTransform m_worldListRoot;
+
+ public GameObject m_worldListElement;
+
+ public ScrollRectEnsureVisible m_worldListEnsureVisible;
+
+ public float m_worldListElementStep = 28f;
+
+ public InputField m_newWorldName;
+
+ public InputField m_newWorldSeed;
+
+ public Button m_newWorldDone;
+
+ public Button m_worldStart;
+
+ public Button m_worldRemove;
+
+ public GameObject m_removeWorldDialog;
+
+ public Text m_removeWorldName;
+
+ public GameObject m_removeCharacterDialog;
+
+ public Text m_removeCharacterName;
+
+ [Header("Character selectoin")]
+ public Button m_csStartButton;
+
+ public Button m_csNewBigButton;
+
+ public Button m_csNewButton;
+
+ public Button m_csRemoveButton;
+
+ public Button m_csLeftButton;
+
+ public Button m_csRightButton;
+
+ public Button m_csNewCharacterDone;
+
+ public GameObject m_newCharacterError;
+
+ public Text m_csName;
+
+ public InputField m_csNewCharacterName;
+
+ [Header("Misc")]
+ public Transform m_characterPreviewPoint;
+
+ public GameObject m_playerPrefab;
+
+ public GameObject m_gameMainPrefab;
+
+ public GameObject m_settingsPrefab;
+
+ public GameObject m_consolePrefab;
+
+ public GameObject m_feedbackPrefab;
+
+ public GameObject m_changeEffectPrefab;
+
+ private string m_downloadUrl = "";
+
+ [TextArea]
+ public string m_versionXmlUrl = "https://dl.dropboxusercontent.com/s/5ibm05oelbqt8zq/fejdversion.xml?dl=0";
+
+ private World m_world;
+
+ private MasterClient.ServerData m_joinServer;
+
+ private MasterClient.ServerData m_queuedJoinServer;
+
+ private float m_serverListBaseSize;
+
+ private float m_worldListBaseSize;
+
+ private List<PlayerProfile> m_profiles;
+
+ private int m_profileIndex;
+
+ private string m_tempRemoveCharacterName = "";
+
+ private int m_tempRemoveCharacterIndex = -1;
+
+ private List<GameObject> m_serverListElements = new List<GameObject>();
+
+ private List<MasterClient.ServerData> m_serverList = new List<MasterClient.ServerData>();
+
+ private int m_serverListRevision = -1;
+
+ private List<GameObject> m_worldListElements = new List<GameObject>();
+
+ private List<World> m_worlds;
+
+ private GameObject m_playerInstance;
+
+ private static bool m_firstStartup = true;
+
+ public static FejdStartup instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ QualitySettings.maxQueuedFrames = 1;
+ Settings.ApplyStartupSettings();
+ WorldGenerator.Initialize(World.GetMenuWorld());
+ if (!Console.instance)
+ {
+ UnityEngine.Object.Instantiate(m_consolePrefab);
+ }
+ m_mainCamera.transform.position = m_cameraMarkerMain.transform.position;
+ m_mainCamera.transform.rotation = m_cameraMarkerMain.transform.rotation;
+ ZLog.Log("Render threading mode:" + SystemInfo.renderingThreadingMode);
+ GoogleAnalyticsV4.instance.StartSession();
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Version", Version.GetVersionString(), 0L);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "SteamID", SteamManager.APP_ID.ToString(), 0L);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "StartMenu", 0L);
+ InitializeSteam();
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Start()
+ {
+ Application.targetFrameRate = 60;
+ SetupGui();
+ SetupObjectDB();
+ ZInput.Initialize();
+ MusicMan.instance.Reset();
+ MusicMan.instance.TriggerMusic("menu");
+ ShowConnectError();
+ ZSteamMatchmaking.Initialize();
+ QueueServerListUpdate();
+ InvokeRepeating("UpdateServerList", 0.5f, 0.5f);
+ if (m_firstStartup)
+ {
+ HandleStartupJoin();
+ }
+ m_menuAnimator.SetBool("FirstStartup", m_firstStartup);
+ m_firstStartup = false;
+ string @string = PlayerPrefs.GetString("profile");
+ if (@string.Length > 0)
+ {
+ SetSelectedProfile(@string);
+ return;
+ }
+ m_profiles = PlayerProfile.GetAllPlayerProfiles();
+ if (m_profiles.Count > 0)
+ {
+ SetSelectedProfile(m_profiles[0].GetFilename());
+ }
+ else
+ {
+ UpdateCharacterList();
+ }
+ }
+
+ private void SetupGui()
+ {
+ HideAll();
+ m_mainMenu.SetActive(value: true);
+ if (SteamManager.APP_ID == 1223920)
+ {
+ m_betaText.SetActive(value: true);
+ if (!Debug.isDebugBuild && !AcceptedNDA())
+ {
+ m_ndaPanel.SetActive(value: true);
+ m_mainMenu.SetActive(value: false);
+ }
+ }
+ m_manualIPButton.gameObject.SetActive(value: false);
+ m_serverListBaseSize = m_serverListRoot.rect.height;
+ m_worldListBaseSize = m_worldListRoot.rect.height;
+ m_versionLabel.text = "version " + Version.GetVersionString();
+ Localization.instance.Localize(base.transform);
+ }
+
+ private void HideAll()
+ {
+ m_worldVersionPanel.SetActive(value: false);
+ m_playerVersionPanel.SetActive(value: false);
+ m_newGameVersionPanel.SetActive(value: false);
+ m_loading.SetActive(value: false);
+ m_characterSelectScreen.SetActive(value: false);
+ m_creditsPanel.SetActive(value: false);
+ m_startGamePanel.SetActive(value: false);
+ m_joinIPPanel.SetActive(value: false);
+ m_createWorldPanel.SetActive(value: false);
+ m_mainMenu.SetActive(value: false);
+ m_ndaPanel.SetActive(value: false);
+ m_betaText.SetActive(value: false);
+ }
+
+ private bool InitializeSteam()
+ {
+ if (SteamManager.Initialize())
+ {
+ string personaName = SteamFriends.GetPersonaName();
+ ZLog.Log("Steam initialized, persona:" + personaName);
+ return true;
+ }
+ ZLog.LogError("Steam is not initialized");
+ Application.Quit();
+ return false;
+ }
+
+ private void HandleStartupJoin()
+ {
+ string[] commandLineArgs = Environment.GetCommandLineArgs();
+ for (int i = 0; i < commandLineArgs.Length; i++)
+ {
+ string text = commandLineArgs[i];
+ ZLog.Log("ARG " + i + " " + text);
+ if (text == "+connect" && i < commandLineArgs.Length - 1)
+ {
+ string text2 = commandLineArgs[i + 1];
+ ZLog.Log("JOIN " + text2);
+ ZSteamMatchmaking.instance.QueueServerJoin(text2);
+ }
+ else if (text == "+connect_lobby" && i < commandLineArgs.Length - 1)
+ {
+ string s = commandLineArgs[i + 1];
+ CSteamID lobbyID = new CSteamID(ulong.Parse(s));
+ ZSteamMatchmaking.instance.QueueLobbyJoin(lobbyID);
+ }
+ }
+ }
+
+ private bool ParseServerArguments()
+ {
+ string[] commandLineArgs = Environment.GetCommandLineArgs();
+ bool flag = true;
+ bool openServer = true;
+ string text = "Dedicated";
+ string password = "";
+ string text2 = "";
+ int serverPort = 2456;
+ for (int i = 0; i < commandLineArgs.Length; i++)
+ {
+ switch (commandLineArgs[i])
+ {
+ case "-world":
+ {
+ string text3 = commandLineArgs[i + 1];
+ if (text3 != "")
+ {
+ text = text3;
+ }
+ i++;
+ break;
+ }
+ case "-name":
+ {
+ string text4 = commandLineArgs[i + 1];
+ if (text4 != "")
+ {
+ text2 = text4;
+ }
+ i++;
+ break;
+ }
+ case "-port":
+ {
+ string text5 = commandLineArgs[i + 1];
+ if (text5 != "")
+ {
+ serverPort = int.Parse(text5);
+ }
+ i++;
+ break;
+ }
+ case "-password":
+ password = commandLineArgs[i + 1];
+ i++;
+ break;
+ case "-public":
+ flag = ((commandLineArgs[i + 1] == "1") ? true : false);
+ break;
+ }
+ }
+ if (text2 == "")
+ {
+ text2 = text;
+ }
+ World createWorld = World.GetCreateWorld(text);
+ if (flag && !IsPublicPasswordValid(password, createWorld))
+ {
+ string publicPasswordError = GetPublicPasswordError(password, createWorld);
+ ZLog.LogError("Error bad password:" + publicPasswordError);
+ Application.Quit();
+ return false;
+ }
+ ZNet.SetServer(server: true, openServer, flag, text2, password, createWorld);
+ ZNet.SetServerHost("", 0);
+ SteamManager.SetServerPort(serverPort);
+ return true;
+ }
+
+ private void SetupObjectDB()
+ {
+ ObjectDB objectDB = base.gameObject.AddComponent<ObjectDB>();
+ ObjectDB component = m_gameMainPrefab.GetComponent<ObjectDB>();
+ objectDB.CopyOtherDB(component);
+ }
+
+ private void ShowConnectError()
+ {
+ ZNet.ConnectionStatus connectionStatus = ZNet.GetConnectionStatus();
+ if (connectionStatus != ZNet.ConnectionStatus.Connected && connectionStatus != ZNet.ConnectionStatus.Connecting && connectionStatus != 0)
+ {
+ m_connectionFailedPanel.SetActive(value: true);
+ switch (connectionStatus)
+ {
+ case ZNet.ConnectionStatus.ErrorVersion:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_incompatibleversion");
+ break;
+ case ZNet.ConnectionStatus.ErrorConnectFailed:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_failedconnect");
+ break;
+ case ZNet.ConnectionStatus.ErrorDisconnected:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_disconnected");
+ break;
+ case ZNet.ConnectionStatus.ErrorPassword:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_password");
+ break;
+ case ZNet.ConnectionStatus.ErrorAlreadyConnected:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_alreadyconnected");
+ break;
+ case ZNet.ConnectionStatus.ErrorBanned:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_banned");
+ break;
+ case ZNet.ConnectionStatus.ErrorFull:
+ m_connectionFailedError.text = Localization.instance.Localize("$error_serverfull");
+ break;
+ }
+ }
+ }
+
+ public void OnNewVersionButtonDownload()
+ {
+ Application.OpenURL(m_downloadUrl);
+ Application.Quit();
+ }
+
+ public void OnNewVersionButtonContinue()
+ {
+ m_newGameVersionPanel.SetActive(value: false);
+ }
+
+ public void OnStartGame()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "StartGame", 0L);
+ m_mainMenu.SetActive(value: false);
+ ShowCharacterSelection();
+ }
+
+ private void ShowStartGame()
+ {
+ m_mainMenu.SetActive(value: false);
+ m_startGamePanel.SetActive(value: true);
+ m_createWorldPanel.SetActive(value: false);
+ }
+
+ public void OnSelectWorldTab()
+ {
+ UpdateWorldList(centerSelection: true);
+ if (m_world == null)
+ {
+ string @string = PlayerPrefs.GetString("world");
+ if (@string.Length > 0)
+ {
+ m_world = FindWorld(@string);
+ }
+ if (m_world == null)
+ {
+ m_world = ((m_worlds.Count > 0) ? m_worlds[0] : null);
+ }
+ if (m_world != null)
+ {
+ UpdateWorldList(centerSelection: true);
+ }
+ }
+ }
+
+ private World FindWorld(string name)
+ {
+ foreach (World world in m_worlds)
+ {
+ if (world.m_name == name)
+ {
+ return world;
+ }
+ }
+ return null;
+ }
+
+ private void UpdateWorldList(bool centerSelection)
+ {
+ m_worlds = World.GetWorldList();
+ foreach (GameObject worldListElement in m_worldListElements)
+ {
+ UnityEngine.Object.Destroy(worldListElement);
+ }
+ m_worldListElements.Clear();
+ float b = (float)m_worlds.Count * m_worldListElementStep;
+ b = Mathf.Max(m_worldListBaseSize, b);
+ m_worldListRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, b);
+ for (int i = 0; i < m_worlds.Count; i++)
+ {
+ World world = m_worlds[i];
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_worldListElement, m_worldListRoot);
+ gameObject.SetActive(value: true);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)i * (0f - m_worldListElementStep));
+ gameObject.GetComponent<Button>().onClick.AddListener(OnSelectWorld);
+ Text component = gameObject.transform.Find("seed").GetComponent<Text>();
+ component.text = "Seed:" + world.m_seedName;
+ gameObject.transform.Find("name").GetComponent<Text>().text = world.m_name;
+ if (world.m_loadError)
+ {
+ component.text = " [LOAD ERROR]";
+ }
+ else if (world.m_versionError)
+ {
+ component.text = " [BAD VERSION]";
+ }
+ RectTransform rectTransform = gameObject.transform.Find("selected") as RectTransform;
+ bool flag = m_world != null && world.m_name == m_world.m_name;
+ rectTransform.gameObject.SetActive(flag);
+ if (flag && centerSelection)
+ {
+ m_worldListEnsureVisible.CenterOnItem(rectTransform);
+ }
+ m_worldListElements.Add(gameObject);
+ }
+ }
+
+ public void OnWorldRemove()
+ {
+ if (m_world != null)
+ {
+ m_removeWorldName.text = m_world.m_name;
+ m_removeWorldDialog.SetActive(value: true);
+ }
+ }
+
+ public void OnButtonRemoveWorldYes()
+ {
+ World.RemoveWorld(m_world.m_name);
+ m_world = null;
+ SetSelectedWorld(0, centerSelection: true);
+ m_removeWorldDialog.SetActive(value: false);
+ }
+
+ public void OnButtonRemoveWorldNo()
+ {
+ m_removeWorldDialog.SetActive(value: false);
+ }
+
+ private void OnSelectWorld()
+ {
+ GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
+ int index = FindSelectedWorld(currentSelectedGameObject);
+ SetSelectedWorld(index, centerSelection: false);
+ }
+
+ private void SetSelectedWorld(int index, bool centerSelection)
+ {
+ if (m_worlds.Count != 0)
+ {
+ index = Mathf.Clamp(index, 0, m_worlds.Count - 1);
+ m_world = m_worlds[index];
+ UpdateWorldList(centerSelection);
+ }
+ }
+
+ private int GetSelectedWorld()
+ {
+ if (m_world == null)
+ {
+ return -1;
+ }
+ for (int i = 0; i < m_worlds.Count; i++)
+ {
+ if (m_worlds[i].m_name == m_world.m_name)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int FindSelectedWorld(GameObject button)
+ {
+ for (int i = 0; i < m_worldListElements.Count; i++)
+ {
+ if (m_worldListElements[i] == button)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void OnWorldNew()
+ {
+ m_createWorldPanel.SetActive(value: true);
+ m_newWorldName.text = "";
+ m_newWorldSeed.text = World.GenerateSeed();
+ }
+
+ public void OnNewWorldDone()
+ {
+ string text = m_newWorldName.text;
+ string text2 = m_newWorldSeed.text;
+ if (!World.HaveWorld(text))
+ {
+ m_world = new World(text, text2);
+ m_world.SaveWorldMetaData();
+ UpdateWorldList(centerSelection: true);
+ ShowStartGame();
+ GoogleAnalyticsV4.instance.LogEvent("Menu", "NewWorld", text, 0L);
+ }
+ }
+
+ public void OnNewWorldBack()
+ {
+ ShowStartGame();
+ }
+
+ public void OnWorldStart()
+ {
+ if (m_world != null && !m_world.m_versionError && !m_world.m_loadError)
+ {
+ PlayerPrefs.SetString("world", m_world.m_name);
+ bool isOn = m_publicServerToggle.isOn;
+ bool isOn2 = m_openServerToggle.isOn;
+ string text = m_serverPassword.text;
+ ZNet.SetServer(server: true, isOn2, isOn, m_world.m_name, text, m_world);
+ ZNet.SetServerHost("", 0);
+ string eventLabel = "open:" + isOn2 + ",public:" + isOn;
+ GoogleAnalyticsV4.instance.LogEvent("Menu", "WorldStart", eventLabel, 0L);
+ TransitionToMainScene();
+ }
+ }
+
+ private void ShowCharacterSelection()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "CharacterSelection", 0L);
+ ZLog.Log("show character selection");
+ m_characterSelectScreen.SetActive(value: true);
+ m_selectCharacterPanel.SetActive(value: true);
+ m_newCharacterPanel.SetActive(value: false);
+ }
+
+ public void OnJoinGame()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "JoinGame", 0L);
+ HideAll();
+ ShowCharacterSelection();
+ }
+
+ public void OnServerFilterChanged()
+ {
+ ZSteamMatchmaking.instance.SetNameFilter(m_filterInputField.text);
+ ZSteamMatchmaking.instance.SetFriendFilter(m_friendFilterSwitch.isOn);
+ PlayerPrefs.SetInt("publicfilter", m_publicFilterSwitch.isOn ? 1 : 0);
+ QueueServerListUpdate();
+ }
+
+ public void QueueServerListUpdate()
+ {
+ ZLog.DevLog("Queue serverlist");
+ CancelInvoke("RequestServerList");
+ Invoke("RequestServerList", 0.5f);
+ m_serverRefreshButton.interactable = false;
+ }
+
+ private void RequestServerList()
+ {
+ ZLog.DevLog("Request serverlist");
+ ZSteamMatchmaking.instance.RequestServerlist();
+ }
+
+ private void UpdateServerList()
+ {
+ if (m_serverListRevision == ZSteamMatchmaking.instance.GetServerListRevision())
+ {
+ return;
+ }
+ m_serverListRevision = ZSteamMatchmaking.instance.GetServerListRevision();
+ m_serverList.Clear();
+ ZSteamMatchmaking.instance.GetServers(m_serverList);
+ m_serverList.Sort((MasterClient.ServerData a, MasterClient.ServerData b) => a.m_name.CompareTo(b.m_name));
+ if (!m_serverList.Contains(m_joinServer))
+ {
+ ZLog.Log("Serverlist does not contain selected server, clearing");
+ if (m_serverList.Count > 0)
+ {
+ m_joinServer = m_serverList[0];
+ }
+ else
+ {
+ m_joinServer = null;
+ }
+ }
+ UpdateServerListGui(centerSelection: true);
+ }
+
+ private void UpdateServerListGui(bool centerSelection)
+ {
+ m_serverCount.text = m_serverListElements.Count.ToString();
+ m_serverRefreshButton.interactable = true;
+ if (m_serverList.Count != m_serverListElements.Count)
+ {
+ foreach (GameObject serverListElement in m_serverListElements)
+ {
+ UnityEngine.Object.Destroy(serverListElement);
+ }
+ m_serverListElements.Clear();
+ float b = (float)m_serverList.Count * m_serverListElementStep;
+ b = Mathf.Max(m_serverListBaseSize, b);
+ m_serverListRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, b);
+ for (int i = 0; i < m_serverList.Count; i++)
+ {
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_serverListElement, m_serverListRoot);
+ gameObject.SetActive(value: true);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)i * (0f - m_serverListElementStep));
+ gameObject.GetComponent<Button>().onClick.AddListener(OnSelectedServer);
+ m_serverListElements.Add(gameObject);
+ }
+ }
+ for (int j = 0; j < m_serverList.Count; j++)
+ {
+ MasterClient.ServerData serverData = m_serverList[j];
+ GameObject gameObject2 = m_serverListElements[j];
+ gameObject2.GetComponentInChildren<Text>().text = j + ". " + serverData.m_name;
+ UITooltip componentInChildren = gameObject2.GetComponentInChildren<UITooltip>();
+ if (!string.IsNullOrEmpty(serverData.m_host))
+ {
+ componentInChildren.m_text = serverData.m_host + ":" + serverData.m_port;
+ }
+ else
+ {
+ componentInChildren.m_text = serverData.m_steamHostID.ToString();
+ }
+ gameObject2.transform.Find("version").GetComponent<Text>().text = serverData.m_version;
+ gameObject2.transform.Find("players").GetComponent<Text>().text = "Players:" + serverData.m_players + " / " + m_serverPlayerLimit;
+ gameObject2.transform.Find("Private").gameObject.SetActive(serverData.m_password);
+ Transform transform = gameObject2.transform.Find("selected");
+ bool flag = m_joinServer != null && m_joinServer.Equals(serverData);
+ transform.gameObject.SetActive(flag);
+ if (centerSelection && flag)
+ {
+ m_serverListEnsureVisible.CenterOnItem(transform as RectTransform);
+ }
+ }
+ }
+
+ private void OnSelectedServer()
+ {
+ GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
+ int index = FindSelectedServer(currentSelectedGameObject);
+ m_joinServer = m_serverList[index];
+ UpdateServerListGui(centerSelection: false);
+ }
+
+ private void SetSelectedServer(int index, bool centerSelection)
+ {
+ if (m_serverList.Count != 0)
+ {
+ index = Mathf.Clamp(index, 0, m_serverList.Count - 1);
+ m_joinServer = m_serverList[index];
+ UpdateServerListGui(centerSelection);
+ }
+ }
+
+ private int GetSelectedServer()
+ {
+ if (m_joinServer == null)
+ {
+ return -1;
+ }
+ for (int i = 0; i < m_serverList.Count; i++)
+ {
+ if (m_joinServer.Equals(m_serverList[i]))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int FindSelectedServer(GameObject button)
+ {
+ for (int i = 0; i < m_serverListElements.Count; i++)
+ {
+ if (m_serverListElements[i] == button)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void OnJoinStart()
+ {
+ JoinServer();
+ }
+
+ private void JoinServer()
+ {
+ ZNet.SetServer(server: false, openServer: false, publicServer: false, "", "", null);
+ ZNet.SetServerHost(m_joinServer.m_steamHostID);
+ GoogleAnalyticsV4.instance.LogEvent("Menu", "JoinServer", "", 0L);
+ TransitionToMainScene();
+ }
+
+ public void OnJoinIPOpen()
+ {
+ m_joinIPPanel.SetActive(value: true);
+ }
+
+ public void OnJoinIPConnect()
+ {
+ m_joinIPPanel.SetActive(value: true);
+ string[] array = m_joinIPAddress.text.Split(':');
+ if (array.Length != 0)
+ {
+ string text = array[0];
+ int port = m_joinHostPort;
+ if (array.Length > 1 && int.TryParse(array[1], out var result))
+ {
+ port = result;
+ }
+ if (text.Length != 0)
+ {
+ m_joinServer = new MasterClient.ServerData();
+ m_joinServer.m_host = text;
+ m_joinServer.m_port = port;
+ JoinServer();
+ }
+ }
+ }
+
+ public void OnJoinIPBack()
+ {
+ m_joinIPPanel.SetActive(value: false);
+ }
+
+ public void OnServerListTab()
+ {
+ bool publicFilter = PlayerPrefs.GetInt("publicfilter", 0) == 1;
+ SetPublicFilter(publicFilter);
+ QueueServerListUpdate();
+ UpdateServerListGui(centerSelection: true);
+ m_filterInputField.ActivateInputField();
+ }
+
+ private void SetPublicFilter(bool enabled)
+ {
+ m_friendFilterSwitch.isOn = !enabled;
+ m_publicFilterSwitch.isOn = enabled;
+ }
+
+ public void OnStartGameBack()
+ {
+ m_startGamePanel.SetActive(value: false);
+ ShowCharacterSelection();
+ }
+
+ public void OnCredits()
+ {
+ m_creditsPanel.SetActive(value: true);
+ m_mainMenu.SetActive(value: false);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Credits", 0L);
+ }
+
+ public void OnCreditsBack()
+ {
+ m_mainMenu.SetActive(value: true);
+ m_creditsPanel.SetActive(value: false);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "StartMenu", 0L);
+ }
+
+ public void OnSelelectCharacterBack()
+ {
+ m_characterSelectScreen.SetActive(value: false);
+ m_mainMenu.SetActive(value: true);
+ m_queuedJoinServer = null;
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "StartMenu", 0L);
+ }
+
+ public void OnAbort()
+ {
+ Application.Quit();
+ }
+
+ public void OnWorldVersionYes()
+ {
+ m_worldVersionPanel.SetActive(value: false);
+ }
+
+ public void OnPlayerVersionOk()
+ {
+ m_playerVersionPanel.SetActive(value: false);
+ }
+
+ private void FixedUpdate()
+ {
+ ZInput.FixedUpdate(Time.fixedDeltaTime);
+ }
+
+ private void UpdateCursor()
+ {
+ Cursor.lockState = CursorLockMode.None;
+ Cursor.visible = ZInput.IsMouseActive();
+ }
+
+ private void Update()
+ {
+ ZInput.Update(Time.deltaTime);
+ UpdateCursor();
+ UpdateGamepad();
+ CheckPendingSteamJoinRequest();
+ if (MasterClient.instance != null)
+ {
+ MasterClient.instance.Update(Time.deltaTime);
+ }
+ if (ZBroastcast.instance != null)
+ {
+ ZBroastcast.instance.Update(Time.deltaTime);
+ }
+ UpdateCharacterRotation(Time.deltaTime);
+ UpdateCamera(Time.deltaTime);
+ if (m_newCharacterPanel.activeInHierarchy)
+ {
+ m_csNewCharacterDone.interactable = m_csNewCharacterName.text.Length >= 3;
+ }
+ if (m_serverListPanel.activeInHierarchy)
+ {
+ m_joinGameButton.interactable = m_joinServer != null;
+ }
+ if (m_createWorldPanel.activeInHierarchy)
+ {
+ m_newWorldDone.interactable = m_newWorldName.text.Length >= 5;
+ }
+ if (m_startGamePanel.activeInHierarchy)
+ {
+ m_worldStart.interactable = CanStartServer();
+ m_worldRemove.interactable = m_world != null;
+ UpdatePasswordError();
+ }
+ if (m_joinIPPanel.activeInHierarchy)
+ {
+ m_joinIPJoinButton.interactable = m_joinIPAddress.text.Length > 0;
+ }
+ if (m_startGamePanel.activeInHierarchy)
+ {
+ m_publicServerToggle.interactable = m_openServerToggle.isOn;
+ m_serverPassword.interactable = m_openServerToggle.isOn;
+ }
+ }
+
+ private void LateUpdate()
+ {
+ if (Input.GetKeyDown(KeyCode.F11))
+ {
+ GameCamera.ScreenShot();
+ }
+ }
+
+ private void UpdateGamepad()
+ {
+ if (!ZInput.IsGamepadActive())
+ {
+ return;
+ }
+ if (m_worldListPanel.activeInHierarchy)
+ {
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ SetSelectedWorld(GetSelectedWorld() + 1, centerSelection: true);
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ SetSelectedWorld(GetSelectedWorld() - 1, centerSelection: true);
+ }
+ }
+ else if (m_serverListPanel.activeInHierarchy)
+ {
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ SetSelectedServer(GetSelectedServer() + 1, centerSelection: true);
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ SetSelectedServer(GetSelectedServer() - 1, centerSelection: true);
+ }
+ }
+ }
+
+ private void CheckPendingSteamJoinRequest()
+ {
+ if (ZSteamMatchmaking.instance != null)
+ {
+ CSteamID joinUserID = ZSteamMatchmaking.instance.GetJoinUserID();
+ if (joinUserID != CSteamID.Nil)
+ {
+ m_queuedJoinServer = new MasterClient.ServerData();
+ m_queuedJoinServer.m_steamHostID = (ulong)joinUserID;
+ OnJoinGame();
+ }
+ }
+ }
+
+ private void UpdateCharacterRotation(float dt)
+ {
+ if (!(m_playerInstance == null) && m_characterSelectScreen.activeInHierarchy)
+ {
+ if (Input.GetMouseButton(0) && !EventSystem.current.IsPointerOverGameObject())
+ {
+ float axis = Input.GetAxis("Mouse X");
+ m_playerInstance.transform.Rotate(0f, (0f - axis) * m_characterRotateSpeed, 0f);
+ }
+ float joyRightStickX = ZInput.GetJoyRightStickX();
+ if (joyRightStickX != 0f)
+ {
+ m_playerInstance.transform.Rotate(0f, (0f - joyRightStickX) * m_characterRotateSpeedGamepad * dt, 0f);
+ }
+ }
+ }
+
+ private void UpdatePasswordError()
+ {
+ string text = "";
+ if (m_publicServerToggle.isOn)
+ {
+ text = GetPublicPasswordError(m_serverPassword.text, m_world);
+ }
+ m_passwordError.text = text;
+ }
+
+ private string GetPublicPasswordError(string password, World world)
+ {
+ if (password.Length < m_minimumPasswordLength)
+ {
+ return Localization.instance.Localize("$menu_passwordshort");
+ }
+ if (world != null && (world.m_name.Contains(password) || world.m_seedName.Contains(password)))
+ {
+ return Localization.instance.Localize("$menu_passwordinvalid");
+ }
+ return "";
+ }
+
+ private bool IsPublicPasswordValid(string password, World world)
+ {
+ if (password.Length < m_minimumPasswordLength)
+ {
+ return false;
+ }
+ if (world.m_name.Contains(password))
+ {
+ return false;
+ }
+ if (world.m_seedName.Contains(password))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool CanStartServer()
+ {
+ if (m_world == null || m_world.m_loadError || m_world.m_versionError)
+ {
+ return false;
+ }
+ if (m_publicServerToggle.isOn && !IsPublicPasswordValid(m_serverPassword.text, m_world))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void UpdateCamera(float dt)
+ {
+ Transform transform = m_cameraMarkerMain;
+ if (m_characterSelectScreen.activeSelf)
+ {
+ transform = m_cameraMarkerCharacter;
+ }
+ else if (m_creditsPanel.activeSelf)
+ {
+ transform = m_cameraMarkerCredits;
+ }
+ else if (m_startGamePanel.activeSelf || m_joinIPPanel.activeSelf)
+ {
+ transform = m_cameraMarkerGame;
+ }
+ m_mainCamera.transform.position = Vector3.SmoothDamp(m_mainCamera.transform.position, transform.position, ref camSpeed, 1.5f, 1000f, dt);
+ Vector3 forward = Vector3.SmoothDamp(m_mainCamera.transform.forward, transform.forward, ref camRotSpeed, 1.5f, 1000f, dt);
+ forward.Normalize();
+ m_mainCamera.transform.rotation = Quaternion.LookRotation(forward);
+ }
+
+ private void UpdateCharacterList()
+ {
+ if (m_profiles == null)
+ {
+ m_profiles = PlayerProfile.GetAllPlayerProfiles();
+ }
+ if (m_profileIndex >= m_profiles.Count)
+ {
+ m_profileIndex = m_profiles.Count - 1;
+ }
+ m_csRemoveButton.gameObject.SetActive(m_profiles.Count > 0);
+ m_csStartButton.gameObject.SetActive(m_profiles.Count > 0);
+ m_csNewButton.gameObject.SetActive(m_profiles.Count > 0);
+ m_csNewBigButton.gameObject.SetActive(m_profiles.Count == 0);
+ m_csLeftButton.interactable = m_profileIndex > 0;
+ m_csRightButton.interactable = m_profileIndex < m_profiles.Count - 1;
+ if (m_profileIndex >= 0 && m_profileIndex < m_profiles.Count)
+ {
+ PlayerProfile playerProfile = m_profiles[m_profileIndex];
+ m_csName.text = playerProfile.GetName();
+ m_csName.gameObject.SetActive(value: true);
+ SetupCharacterPreview(playerProfile);
+ }
+ else
+ {
+ m_csName.gameObject.SetActive(value: false);
+ ClearCharacterPreview();
+ }
+ }
+
+ private void SetSelectedProfile(string filename)
+ {
+ if (m_profiles == null)
+ {
+ m_profiles = PlayerProfile.GetAllPlayerProfiles();
+ }
+ m_profileIndex = 0;
+ for (int i = 0; i < m_profiles.Count; i++)
+ {
+ if (m_profiles[i].GetFilename() == filename)
+ {
+ m_profileIndex = i;
+ break;
+ }
+ }
+ UpdateCharacterList();
+ }
+
+ public void OnNewCharacterDone()
+ {
+ string text = m_csNewCharacterName.text;
+ string text2 = text.ToLower();
+ if (PlayerProfile.HaveProfile(text2))
+ {
+ m_newCharacterError.SetActive(value: true);
+ return;
+ }
+ Player component = m_playerInstance.GetComponent<Player>();
+ component.GiveDefaultItems();
+ PlayerProfile playerProfile = new PlayerProfile(text2);
+ playerProfile.SetName(text);
+ playerProfile.SavePlayerData(component);
+ playerProfile.Save();
+ m_selectCharacterPanel.SetActive(value: true);
+ m_newCharacterPanel.SetActive(value: false);
+ m_profiles = null;
+ SetSelectedProfile(text2);
+ GoogleAnalyticsV4.instance.LogEvent("Menu", "NewCharacter", text, 0L);
+ }
+
+ public void OnNewCharacterCancel()
+ {
+ m_selectCharacterPanel.SetActive(value: true);
+ m_newCharacterPanel.SetActive(value: false);
+ UpdateCharacterList();
+ }
+
+ public void OnCharacterNew()
+ {
+ m_newCharacterPanel.SetActive(value: true);
+ m_selectCharacterPanel.SetActive(value: false);
+ m_csNewCharacterName.text = "";
+ m_newCharacterError.SetActive(value: false);
+ SetupCharacterPreview(null);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "CreateCharacter", 0L);
+ }
+
+ public void OnCharacterRemove()
+ {
+ if (m_profileIndex >= 0 && m_profileIndex < m_profiles.Count)
+ {
+ PlayerProfile playerProfile = m_profiles[m_profileIndex];
+ m_removeCharacterName.text = playerProfile.GetName();
+ m_tempRemoveCharacterName = playerProfile.GetFilename();
+ m_tempRemoveCharacterIndex = m_profileIndex;
+ m_removeCharacterDialog.SetActive(value: true);
+ }
+ }
+
+ public void OnButtonRemoveCharacterYes()
+ {
+ ZLog.Log("Remove character");
+ PlayerProfile.RemoveProfile(m_tempRemoveCharacterName);
+ m_profiles.RemoveAt(m_tempRemoveCharacterIndex);
+ UpdateCharacterList();
+ m_removeCharacterDialog.SetActive(value: false);
+ }
+
+ public void OnButtonRemoveCharacterNo()
+ {
+ m_removeCharacterDialog.SetActive(value: false);
+ }
+
+ public void OnCharacterLeft()
+ {
+ if (m_profileIndex > 0)
+ {
+ m_profileIndex--;
+ }
+ UpdateCharacterList();
+ }
+
+ public void OnCharacterRight()
+ {
+ if (m_profileIndex < m_profiles.Count - 1)
+ {
+ m_profileIndex++;
+ }
+ UpdateCharacterList();
+ }
+
+ public void OnCharacterStart()
+ {
+ ZLog.Log("OnCharacterStart");
+ if (m_profileIndex < 0 || m_profileIndex >= m_profiles.Count)
+ {
+ return;
+ }
+ PlayerProfile playerProfile = m_profiles[m_profileIndex];
+ PlayerPrefs.SetString("profile", playerProfile.GetFilename());
+ Game.SetProfile(playerProfile.GetFilename());
+ m_characterSelectScreen.SetActive(value: false);
+ if (m_queuedJoinServer != null)
+ {
+ m_joinServer = m_queuedJoinServer;
+ m_queuedJoinServer = null;
+ JoinServer();
+ return;
+ }
+ ShowStartGame();
+ if (m_worlds.Count == 0)
+ {
+ OnWorldNew();
+ }
+ }
+
+ private void TransitionToMainScene()
+ {
+ m_menuAnimator.SetTrigger("FadeOut");
+ Invoke("LoadMainScene", 1.5f);
+ }
+
+ private void LoadMainScene()
+ {
+ m_loading.SetActive(value: true);
+ SceneManager.LoadScene("main");
+ }
+
+ public void OnButtonSettings()
+ {
+ UnityEngine.Object.Instantiate(m_settingsPrefab, base.transform);
+ }
+
+ public void OnButtonFeedback()
+ {
+ UnityEngine.Object.Instantiate(m_feedbackPrefab, base.transform);
+ }
+
+ public void OnButtonTwitter()
+ {
+ Application.OpenURL("https://twitter.com/valheimgame");
+ }
+
+ public void OnButtonWebPage()
+ {
+ Application.OpenURL("http://valheimgame.com/");
+ }
+
+ public void OnButtonDiscord()
+ {
+ Application.OpenURL("https://discord.gg/44qXMJH");
+ }
+
+ public void OnButtonFacebook()
+ {
+ Application.OpenURL("https://www.facebook.com/valheimgame/");
+ }
+
+ public void OnButtonShowLog()
+ {
+ Application.OpenURL(Application.persistentDataPath + "/");
+ }
+
+ private bool AcceptedNDA()
+ {
+ return PlayerPrefs.GetInt("accepted_nda", 0) == 1;
+ }
+
+ public void OnButtonNDAAccept()
+ {
+ PlayerPrefs.SetInt("accepted_nda", 1);
+ m_ndaPanel.SetActive(value: false);
+ m_mainMenu.SetActive(value: true);
+ }
+
+ public void OnButtonNDADecline()
+ {
+ Application.Quit();
+ }
+
+ public void OnConnectionFailedOk()
+ {
+ m_connectionFailedPanel.SetActive(value: false);
+ }
+
+ public Player GetPreviewPlayer()
+ {
+ if (m_playerInstance != null)
+ {
+ return m_playerInstance.GetComponent<Player>();
+ }
+ return null;
+ }
+
+ private void ClearCharacterPreview()
+ {
+ if ((bool)m_playerInstance)
+ {
+ UnityEngine.Object.Instantiate(m_changeEffectPrefab, m_characterPreviewPoint.position, m_characterPreviewPoint.rotation);
+ UnityEngine.Object.Destroy(m_playerInstance);
+ m_playerInstance = null;
+ }
+ }
+
+ private void SetupCharacterPreview(PlayerProfile profile)
+ {
+ ClearCharacterPreview();
+ ZNetView.m_forceDisableInit = true;
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_playerPrefab, m_characterPreviewPoint.position, m_characterPreviewPoint.rotation);
+ ZNetView.m_forceDisableInit = false;
+ UnityEngine.Object.Destroy(gameObject.GetComponent<Rigidbody>());
+ Animator[] componentsInChildren = gameObject.GetComponentsInChildren<Animator>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].updateMode = AnimatorUpdateMode.Normal;
+ }
+ Player component = gameObject.GetComponent<Player>();
+ profile?.LoadPlayerData(component);
+ m_playerInstance = gameObject;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fermenter.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fermenter.cs
new file mode 100644
index 0000000..d4a1dde
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fermenter.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Fermenter : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public class ItemConversion
+ {
+ public ItemDrop m_from;
+
+ public ItemDrop m_to;
+
+ public int m_producedItems = 4;
+ }
+
+ private enum Status
+ {
+ Empty,
+ Fermenting,
+ Exposed,
+ Ready
+ }
+
+ private const float updateDT = 2f;
+
+ public string m_name = "Fermentation barrel";
+
+ public float m_fermentationDuration = 2400f;
+
+ public GameObject m_fermentingObject;
+
+ public GameObject m_readyObject;
+
+ public GameObject m_topObject;
+
+ public EffectList m_addedEffects = new EffectList();
+
+ public EffectList m_tapEffects = new EffectList();
+
+ public EffectList m_spawnEffects = new EffectList();
+
+ public Switch m_addSwitch;
+
+ public Switch m_tapSwitch;
+
+ public float m_tapDelay = 1.5f;
+
+ public Transform m_outputPoint;
+
+ public Transform m_roofCheckPoint;
+
+ public List<ItemConversion> m_conversion = new List<ItemConversion>();
+
+ private ZNetView m_nview;
+
+ private float m_updateCoverTimer;
+
+ private bool m_exposed;
+
+ private string m_delayedTapItem = "";
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_fermentingObject.SetActive(value: false);
+ m_readyObject.SetActive(value: false);
+ m_topObject.SetActive(value: true);
+ if (!(m_nview == null) && m_nview.GetZDO() != null)
+ {
+ m_nview.Register<string>("AddItem", RPC_AddItem);
+ m_nview.Register("Tap", RPC_Tap);
+ InvokeRepeating("UpdateVis", 2f, 2f);
+ }
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public string GetHoverText()
+ {
+ if (!PrivateArea.CheckAccess(base.transform.position, 0f, flash: false))
+ {
+ return Localization.instance.Localize(m_name + "\n$piece_noaccess");
+ }
+ switch (GetStatus())
+ {
+ case Status.Ready:
+ {
+ string contentName2 = GetContentName();
+ return Localization.instance.Localize(m_name + " ( " + contentName2 + ", $piece_fermenter_ready )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_fermenter_tap");
+ }
+ case Status.Fermenting:
+ {
+ string contentName = GetContentName();
+ if (m_exposed)
+ {
+ return Localization.instance.Localize(m_name + " ( " + contentName + ", $piece_fermenter_exposed )");
+ }
+ return Localization.instance.Localize(m_name + " ( " + contentName + ", $piece_fermenter_fermenting )");
+ }
+ case Status.Empty:
+ return Localization.instance.Localize(m_name + " ( $piece_container_empty )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_fermenter_add");
+ default:
+ return m_name;
+ }
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ return true;
+ }
+ switch (GetStatus())
+ {
+ case Status.Empty:
+ {
+ ItemDrop.ItemData itemData = FindCookableItem(user.GetInventory());
+ if (itemData == null)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_noprocessableitems");
+ return true;
+ }
+ AddItem(user, itemData);
+ break;
+ }
+ case Status.Ready:
+ m_nview.InvokeRPC("Tap");
+ break;
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ return false;
+ }
+ return AddItem(user, item);
+ }
+
+ private void UpdateVis()
+ {
+ UpdateCover(2f);
+ switch (GetStatus())
+ {
+ case Status.Empty:
+ m_fermentingObject.SetActive(value: false);
+ m_readyObject.SetActive(value: false);
+ m_topObject.SetActive(value: false);
+ break;
+ case Status.Fermenting:
+ m_readyObject.SetActive(value: false);
+ m_topObject.SetActive(value: true);
+ m_fermentingObject.SetActive(!m_exposed);
+ break;
+ case Status.Ready:
+ m_fermentingObject.SetActive(value: false);
+ m_readyObject.SetActive(value: true);
+ m_topObject.SetActive(value: true);
+ break;
+ case Status.Exposed:
+ break;
+ }
+ }
+
+ private Status GetStatus()
+ {
+ if (string.IsNullOrEmpty(GetContent()))
+ {
+ return Status.Empty;
+ }
+ if (GetFermentationTime() > (double)m_fermentationDuration)
+ {
+ return Status.Ready;
+ }
+ return Status.Fermenting;
+ }
+
+ private bool AddItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (GetStatus() != 0)
+ {
+ return false;
+ }
+ if (!IsItemAllowed(item))
+ {
+ return false;
+ }
+ if (!user.GetInventory().RemoveOneItem(item))
+ {
+ return false;
+ }
+ m_nview.InvokeRPC("AddItem", item.m_dropPrefab.name);
+ return true;
+ }
+
+ private void RPC_AddItem(long sender, string name)
+ {
+ if (m_nview.IsOwner() && GetStatus() == Status.Empty)
+ {
+ if (!IsItemAllowed(name))
+ {
+ ZLog.DevLog("Item not allowed");
+ return;
+ }
+ m_addedEffects.Create(base.transform.position, base.transform.rotation);
+ m_nview.GetZDO().Set("Content", name);
+ m_nview.GetZDO().Set("StartTime", ZNet.instance.GetTime().Ticks);
+ }
+ }
+
+ private void RPC_Tap(long sender)
+ {
+ if (m_nview.IsOwner() && GetStatus() == Status.Ready)
+ {
+ m_delayedTapItem = GetContent();
+ Invoke("DelayedTap", m_tapDelay);
+ m_tapEffects.Create(base.transform.position, base.transform.rotation);
+ m_nview.GetZDO().Set("Content", "");
+ m_nview.GetZDO().Set("StartTime", 0);
+ }
+ }
+
+ private void DelayedTap()
+ {
+ m_spawnEffects.Create(m_outputPoint.transform.position, Quaternion.identity);
+ ItemConversion itemConversion = GetItemConversion(m_delayedTapItem);
+ if (itemConversion != null)
+ {
+ float num = 0.3f;
+ for (int i = 0; i < itemConversion.m_producedItems; i++)
+ {
+ Vector3 position = m_outputPoint.position + Vector3.up * num;
+ UnityEngine.Object.Instantiate(itemConversion.m_to, position, Quaternion.identity);
+ }
+ }
+ }
+
+ private void ResetFermentationTimer()
+ {
+ if (GetStatus() == Status.Fermenting)
+ {
+ m_nview.GetZDO().Set("StartTime", ZNet.instance.GetTime().Ticks);
+ }
+ }
+
+ private double GetFermentationTime()
+ {
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("StartTime", 0L));
+ if (dateTime.Ticks == 0L)
+ {
+ return -1.0;
+ }
+ return (ZNet.instance.GetTime() - dateTime).TotalSeconds;
+ }
+
+ private string GetContentName()
+ {
+ string content = GetContent();
+ if (string.IsNullOrEmpty(content))
+ {
+ return "";
+ }
+ ItemConversion itemConversion = GetItemConversion(content);
+ if (itemConversion == null)
+ {
+ return "Invalid";
+ }
+ return itemConversion.m_from.m_itemData.m_shared.m_name;
+ }
+
+ private string GetContent()
+ {
+ return m_nview.GetZDO().GetString("Content");
+ }
+
+ private void UpdateCover(float dt)
+ {
+ m_updateCoverTimer += dt;
+ if (m_updateCoverTimer > 10f)
+ {
+ m_updateCoverTimer = 0f;
+ Cover.GetCoverForPoint(m_roofCheckPoint.position, out var coverPercentage, out var underRoof);
+ m_exposed = !underRoof || coverPercentage < 0.7f;
+ if (m_exposed && m_nview.IsOwner())
+ {
+ ResetFermentationTimer();
+ }
+ }
+ }
+
+ private bool IsItemAllowed(ItemDrop.ItemData item)
+ {
+ return IsItemAllowed(item.m_dropPrefab.name);
+ }
+
+ private bool IsItemAllowed(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ItemDrop.ItemData FindCookableItem(Inventory inventory)
+ {
+ foreach (ItemConversion item2 in m_conversion)
+ {
+ ItemDrop.ItemData item = inventory.GetItem(item2.m_from.m_itemData.m_shared.m_name);
+ if (item != null)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private ItemConversion GetItemConversion(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fireplace.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fireplace.cs
new file mode 100644
index 0000000..6cc6478
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fireplace.cs
@@ -0,0 +1,307 @@
+using System;
+using UnityEngine;
+
+public class Fireplace : MonoBehaviour, Hoverable, Interactable
+{
+ private ZNetView m_nview;
+
+ private Piece m_piece;
+
+ [Header("Fire")]
+ public string m_name = "Fire";
+
+ public float m_startFuel = 3f;
+
+ public float m_maxFuel = 10f;
+
+ public float m_secPerFuel = 3f;
+
+ public float m_checkTerrainOffset = 0.2f;
+
+ public float m_coverCheckOffset = 0.5f;
+
+ private const float m_minimumOpenSpace = 0.5f;
+
+ public GameObject m_enabledObject;
+
+ public GameObject m_enabledObjectLow;
+
+ public GameObject m_enabledObjectHigh;
+
+ public GameObject m_playerBaseObject;
+
+ public ItemDrop m_fuelItem;
+
+ public SmokeSpawner m_smokeSpawner;
+
+ public EffectList m_fuelAddedEffects = new EffectList();
+
+ [Header("Fireworks")]
+ public ItemDrop m_fireworkItem;
+
+ public int m_fireworkItems = 2;
+
+ public GameObject m_fireworks;
+
+ private bool m_blocked;
+
+ private bool m_wet;
+
+ private static int m_solidRayMask;
+
+ public void Awake()
+ {
+ m_nview = base.gameObject.GetComponent<ZNetView>();
+ m_piece = base.gameObject.GetComponent<Piece>();
+ if (m_nview.GetZDO() == null)
+ {
+ return;
+ }
+ if (m_solidRayMask == 0)
+ {
+ m_solidRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain");
+ }
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetFloat("fuel", -1f) == -1f)
+ {
+ m_nview.GetZDO().Set("fuel", m_startFuel);
+ if (m_startFuel > 0f)
+ {
+ m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ }
+ m_nview.Register("AddFuel", RPC_AddFuel);
+ InvokeRepeating("UpdateFireplace", 0f, 2f);
+ InvokeRepeating("CheckEnv", 4f, 4f);
+ }
+
+ private void Start()
+ {
+ if ((bool)m_playerBaseObject && (bool)m_piece)
+ {
+ m_playerBaseObject.SetActive(m_piece.IsPlacedByPlayer());
+ }
+ }
+
+ private double GetTimeSinceLastUpdate()
+ {
+ DateTime time = ZNet.instance.GetTime();
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("lastTime", time.Ticks));
+ TimeSpan timeSpan = time - dateTime;
+ m_nview.GetZDO().Set("lastTime", time.Ticks);
+ double num = timeSpan.TotalSeconds;
+ if (num < 0.0)
+ {
+ num = 0.0;
+ }
+ return num;
+ }
+
+ private void UpdateFireplace()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ if (m_nview.IsOwner())
+ {
+ float @float = m_nview.GetZDO().GetFloat("fuel");
+ double timeSinceLastUpdate = GetTimeSinceLastUpdate();
+ if (IsBurning())
+ {
+ float num = (float)(timeSinceLastUpdate / (double)m_secPerFuel);
+ @float -= num;
+ if (@float <= 0f)
+ {
+ @float = 0f;
+ }
+ m_nview.GetZDO().Set("fuel", @float);
+ }
+ }
+ UpdateState();
+ }
+
+ private void CheckEnv()
+ {
+ CheckUnderTerrain();
+ if (m_enabledObjectLow != null && m_enabledObjectHigh != null)
+ {
+ CheckWet();
+ }
+ }
+
+ private void CheckUnderTerrain()
+ {
+ m_blocked = false;
+ RaycastHit hitInfo;
+ if (Heightmap.GetHeight(base.transform.position, out var height) && height > base.transform.position.y + m_checkTerrainOffset)
+ {
+ m_blocked = true;
+ }
+ else if (Physics.Raycast(base.transform.position + Vector3.up * m_coverCheckOffset, Vector3.up, out hitInfo, 0.5f, m_solidRayMask))
+ {
+ m_blocked = true;
+ }
+ else if ((bool)m_smokeSpawner && m_smokeSpawner.IsBlocked())
+ {
+ m_blocked = true;
+ }
+ }
+
+ private void CheckWet()
+ {
+ Cover.GetCoverForPoint(base.transform.position + Vector3.up * m_coverCheckOffset, out var coverPercentage, out var underRoof);
+ m_wet = false;
+ if (EnvMan.instance.GetWindIntensity() >= 0.8f && coverPercentage < 0.7f)
+ {
+ m_wet = true;
+ }
+ if (EnvMan.instance.IsWet() && !underRoof)
+ {
+ m_wet = true;
+ }
+ }
+
+ private void UpdateState()
+ {
+ if (IsBurning())
+ {
+ m_enabledObject.SetActive(value: true);
+ if ((bool)m_enabledObjectHigh && (bool)m_enabledObjectLow)
+ {
+ m_enabledObjectHigh.SetActive(!m_wet);
+ m_enabledObjectLow.SetActive(m_wet);
+ }
+ }
+ else
+ {
+ m_enabledObject.SetActive(value: false);
+ if ((bool)m_enabledObjectHigh && (bool)m_enabledObjectLow)
+ {
+ m_enabledObjectLow.SetActive(value: false);
+ m_enabledObjectHigh.SetActive(value: false);
+ }
+ }
+ }
+
+ public string GetHoverText()
+ {
+ float @float = m_nview.GetZDO().GetFloat("fuel");
+ return Localization.instance.Localize(m_name + " ( $piece_fire_fuel " + Mathf.Ceil(@float) + "/" + (int)m_maxFuel + " )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use " + m_fuelItem.m_itemData.m_shared.m_name + "\n[<color=yellow><b>1-8</b></color>] $piece_useitem");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!m_nview.HasOwner())
+ {
+ m_nview.ClaimOwnership();
+ }
+ Inventory inventory = user.GetInventory();
+ if (inventory != null)
+ {
+ if (inventory.HaveItem(m_fuelItem.m_itemData.m_shared.m_name))
+ {
+ if ((float)Mathf.CeilToInt(m_nview.GetZDO().GetFloat("fuel")) >= m_maxFuel)
+ {
+ user.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_cantaddmore", m_fuelItem.m_itemData.m_shared.m_name));
+ return false;
+ }
+ user.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_fireadding", m_fuelItem.m_itemData.m_shared.m_name));
+ inventory.RemoveItem(m_fuelItem.m_itemData.m_shared.m_name, 1);
+ m_nview.InvokeRPC("AddFuel");
+ return true;
+ }
+ user.Message(MessageHud.MessageType.Center, "$msg_outof " + m_fuelItem.m_itemData.m_shared.m_name);
+ return false;
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (item.m_shared.m_name == m_fuelItem.m_itemData.m_shared.m_name)
+ {
+ if ((float)Mathf.CeilToInt(m_nview.GetZDO().GetFloat("fuel")) >= m_maxFuel)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_cantaddmore " + item.m_shared.m_name);
+ return true;
+ }
+ Inventory inventory = user.GetInventory();
+ user.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_fireadding", item.m_shared.m_name));
+ inventory.RemoveItem(item, 1);
+ m_nview.InvokeRPC("AddFuel");
+ return true;
+ }
+ if (m_fireworkItem != null && item.m_shared.m_name == m_fireworkItem.m_itemData.m_shared.m_name)
+ {
+ if (!IsBurning())
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_firenotburning");
+ return true;
+ }
+ if (user.GetInventory().CountItems(m_fireworkItem.m_itemData.m_shared.m_name) < m_fireworkItems)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_toofew " + m_fireworkItem.m_itemData.m_shared.m_name);
+ return true;
+ }
+ user.GetInventory().RemoveItem(item.m_shared.m_name, m_fireworkItems);
+ user.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_throwinfire", item.m_shared.m_name));
+ ZNetScene.instance.SpawnObject(base.transform.position, Quaternion.identity, m_fireworks);
+ m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation);
+ return true;
+ }
+ return false;
+ }
+
+ private void RPC_AddFuel(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ float @float = m_nview.GetZDO().GetFloat("fuel");
+ if (!((float)Mathf.CeilToInt(@float) >= m_maxFuel))
+ {
+ @float = Mathf.Clamp(@float, 0f, m_maxFuel);
+ @float += 1f;
+ @float = Mathf.Clamp(@float, 0f, m_maxFuel);
+ m_nview.GetZDO().Set("fuel", @float);
+ m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation);
+ UpdateState();
+ }
+ }
+ }
+
+ public bool CanBeRemoved()
+ {
+ return !IsBurning();
+ }
+
+ public bool IsBurning()
+ {
+ if (m_blocked)
+ {
+ return false;
+ }
+ float waterLevel = WaterVolume.GetWaterLevel(m_enabledObject.transform.position);
+ if (m_enabledObject.transform.position.y < waterLevel)
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetFloat("fuel") > 0f;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.white;
+ Gizmos.DrawWireSphere(base.transform.position + Vector3.up * m_coverCheckOffset, 0.5f);
+ Gizmos.color = Color.yellow;
+ Gizmos.DrawWireCube(base.transform.position + Vector3.up * m_checkTerrainOffset, new Vector3(1f, 0.01f, 1f));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fish.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fish.cs
new file mode 100644
index 0000000..8c88937
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Fish.cs
@@ -0,0 +1,373 @@
+using UnityEngine;
+
+public class Fish : MonoBehaviour, IWaterInteractable, Hoverable, Interactable
+{
+ public string m_name = "Fish";
+
+ public float m_swimRange = 20f;
+
+ public float m_minDepth = 1f;
+
+ public float m_maxDepth = 4f;
+
+ public float m_speed = 10f;
+
+ public float m_acceleration = 5f;
+
+ public float m_turnRate = 10f;
+
+ public float m_wpDurationMin = 4f;
+
+ public float m_wpDurationMax = 4f;
+
+ public float m_avoidSpeedScale = 2f;
+
+ public float m_avoidRange = 5f;
+
+ public float m_height = 0.2f;
+
+ public float m_eatDuration = 4f;
+
+ public float m_hookForce = 4f;
+
+ public float m_staminaUse = 1f;
+
+ public float m_baseHookChance = 0.5f;
+
+ public GameObject m_pickupItem;
+
+ public int m_pickupItemStackSize = 1;
+
+ private Vector3 m_spawnPoint;
+
+ private Vector3 m_waypoint;
+
+ private FishingFloat m_waypointFF;
+
+ private bool m_haveWaypoint;
+
+ private float m_swimTimer;
+
+ private float m_lastNibbleTime;
+
+ private float m_inWater = -10000f;
+
+ private float m_pickupTime;
+
+ private ZNetView m_nview;
+
+ private Rigidbody m_body;
+
+ private void Start()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ m_spawnPoint = m_nview.GetZDO().GetVec3("spawnpoint", base.transform.position);
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("spawnpoint", m_spawnPoint);
+ }
+ if (m_nview.IsOwner())
+ {
+ RandomizeWaypoint(canHook: true);
+ }
+ if ((bool)m_nview && m_nview.IsValid())
+ {
+ m_nview.Register("RequestPickup", RPC_RequestPickup);
+ m_nview.Register("Pickup", RPC_Pickup);
+ }
+ }
+
+ public bool IsOwner()
+ {
+ if ((bool)m_nview && m_nview.IsValid())
+ {
+ return m_nview.IsOwner();
+ }
+ return false;
+ }
+
+ public string GetHoverText()
+ {
+ string text = m_name;
+ if (IsOutOfWater())
+ {
+ text += "\n[<color=yellow><b>$KEY_Use</b></color>] $inventory_pickup";
+ }
+ return Localization.instance.Localize(text);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ if (!IsOutOfWater())
+ {
+ return false;
+ }
+ if (Pickup(character))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool Pickup(Humanoid character)
+ {
+ if (!character.GetInventory().CanAddItem(m_pickupItem, m_pickupItemStackSize))
+ {
+ character.Message(MessageHud.MessageType.Center, "$msg_noroom");
+ return false;
+ }
+ m_nview.InvokeRPC("RequestPickup");
+ return true;
+ }
+
+ private void RPC_RequestPickup(long uid)
+ {
+ if (Time.time - m_pickupTime > 2f)
+ {
+ m_pickupTime = Time.time;
+ m_nview.InvokeRPC(uid, "Pickup");
+ }
+ }
+
+ private void RPC_Pickup(long uid)
+ {
+ if ((bool)Player.m_localPlayer && Player.m_localPlayer.PickupPrefab(m_pickupItem, m_pickupItemStackSize) != null)
+ {
+ m_nview.ClaimOwnership();
+ m_nview.Destroy();
+ }
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public void SetInWater(float waterLevel)
+ {
+ m_inWater = waterLevel;
+ }
+
+ public Transform GetTransform()
+ {
+ if (this == null)
+ {
+ return null;
+ }
+ return base.transform;
+ }
+
+ private bool IsOutOfWater()
+ {
+ return m_inWater < base.transform.position.y - m_height;
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ FishingFloat fishingFloat = FishingFloat.FindFloat(this);
+ if ((bool)fishingFloat)
+ {
+ Utils.Pull(m_body, fishingFloat.transform.position, 1f, m_hookForce, 1f, 0.5f);
+ }
+ if (m_inWater <= -10000f || m_inWater < base.transform.position.y + m_height)
+ {
+ m_body.useGravity = true;
+ if (IsOutOfWater())
+ {
+ return;
+ }
+ }
+ m_body.useGravity = false;
+ bool flag = false;
+ Player playerNoiseRange = Player.GetPlayerNoiseRange(base.transform.position);
+ if ((bool)playerNoiseRange)
+ {
+ if (Vector3.Distance(base.transform.position, playerNoiseRange.transform.position) > m_avoidRange / 2f)
+ {
+ Vector3 normalized = (base.transform.position - playerNoiseRange.transform.position).normalized;
+ SwimDirection(normalized, fast: true, avoidLand: true, fixedDeltaTime);
+ return;
+ }
+ flag = true;
+ if (m_swimTimer > 0.5f)
+ {
+ m_swimTimer = 0.5f;
+ }
+ }
+ m_swimTimer -= fixedDeltaTime;
+ if (m_swimTimer <= 0f)
+ {
+ RandomizeWaypoint(!flag);
+ }
+ if (m_haveWaypoint)
+ {
+ if ((bool)m_waypointFF)
+ {
+ m_waypoint = m_waypointFF.transform.position + Vector3.down;
+ }
+ if (Vector3.Distance(m_waypoint, base.transform.position) < 0.2f)
+ {
+ if (!m_waypointFF)
+ {
+ m_haveWaypoint = false;
+ return;
+ }
+ if (Time.time - m_lastNibbleTime > 1f)
+ {
+ m_lastNibbleTime = Time.time;
+ m_waypointFF.Nibble(this);
+ }
+ }
+ Vector3 dir = Vector3.Normalize(m_waypoint - base.transform.position);
+ SwimDirection(dir, flag, avoidLand: false, fixedDeltaTime);
+ }
+ else
+ {
+ Stop(fixedDeltaTime);
+ }
+ }
+
+ private void Stop(float dt)
+ {
+ if (!(m_inWater < base.transform.position.y + m_height))
+ {
+ Vector3 forward = base.transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ Quaternion to = Quaternion.LookRotation(forward, Vector3.up);
+ Quaternion rot = Quaternion.RotateTowards(m_body.rotation, to, m_turnRate * dt);
+ m_body.MoveRotation(rot);
+ Vector3 force = -m_body.velocity * m_acceleration;
+ m_body.AddForce(force, ForceMode.VelocityChange);
+ }
+ }
+
+ private void SwimDirection(Vector3 dir, bool fast, bool avoidLand, float dt)
+ {
+ Vector3 forward = dir;
+ forward.y = 0f;
+ forward.Normalize();
+ float num = m_turnRate;
+ if (fast)
+ {
+ num *= m_avoidSpeedScale;
+ }
+ Quaternion to = Quaternion.LookRotation(forward, Vector3.up);
+ Quaternion rotation = Quaternion.RotateTowards(base.transform.rotation, to, num * dt);
+ m_body.rotation = rotation;
+ float num2 = m_speed;
+ if (fast)
+ {
+ num2 *= m_avoidSpeedScale;
+ }
+ if (avoidLand && GetPointDepth(base.transform.position + base.transform.forward) < m_minDepth)
+ {
+ num2 = 0f;
+ }
+ if (fast && Vector3.Dot(dir, base.transform.forward) < 0f)
+ {
+ num2 = 0f;
+ }
+ Vector3 forward2 = base.transform.forward;
+ forward2.y = dir.y;
+ Vector3 vector = forward2 * num2 - m_body.velocity;
+ if (m_inWater < base.transform.position.y + m_height && vector.y > 0f)
+ {
+ vector.y = 0f;
+ }
+ m_body.AddForce(vector * m_acceleration, ForceMode.VelocityChange);
+ }
+
+ private FishingFloat FindFloat()
+ {
+ foreach (FishingFloat allInstance in FishingFloat.GetAllInstances())
+ {
+ if (!(Vector3.Distance(base.transform.position, allInstance.transform.position) > allInstance.m_range) && allInstance.IsInWater() && !(allInstance.GetCatch() != null))
+ {
+ float baseHookChance = m_baseHookChance;
+ if (Random.value < baseHookChance)
+ {
+ return allInstance;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void RandomizeWaypoint(bool canHook)
+ {
+ Vector2 vector = Random.insideUnitCircle * m_swimRange;
+ m_waypoint = m_spawnPoint + new Vector3(vector.x, 0f, vector.y);
+ m_waypointFF = null;
+ if (canHook)
+ {
+ FishingFloat fishingFloat = FindFloat();
+ if ((bool)fishingFloat)
+ {
+ m_waypointFF = fishingFloat;
+ m_waypoint = fishingFloat.transform.position + Vector3.down;
+ }
+ }
+ float pointDepth = GetPointDepth(m_waypoint);
+ if (!(pointDepth < m_minDepth))
+ {
+ Vector3 p = (m_waypoint + base.transform.position) * 0.5f;
+ if (!(GetPointDepth(p) < m_minDepth))
+ {
+ float max = Mathf.Min(m_maxDepth, pointDepth - m_height);
+ float waterLevel = WaterVolume.GetWaterLevel(m_waypoint);
+ m_waypoint.y = waterLevel - Random.Range(m_minDepth, max);
+ m_haveWaypoint = true;
+ m_swimTimer = Random.Range(m_wpDurationMin, m_wpDurationMax);
+ }
+ }
+ }
+
+ private float GetPointDepth(Vector3 p)
+ {
+ if (ZoneSystem.instance.GetSolidHeight(p, out var height))
+ {
+ return ZoneSystem.instance.m_waterLevel - height;
+ }
+ return 0f;
+ }
+
+ private bool DangerNearby()
+ {
+ if (Player.GetPlayerNoiseRange(base.transform.position) != null)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public ZDOID GetZDOID()
+ {
+ return m_nview.GetZDO().m_uid;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.blue;
+ Gizmos.DrawWireCube(base.transform.position + Vector3.up * m_height, new Vector3(1f, 0.02f, 1f));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FishingFloat.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FishingFloat.cs
new file mode 100644
index 0000000..735f68b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FishingFloat.cs
@@ -0,0 +1,313 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class FishingFloat : MonoBehaviour, IProjectile
+{
+ public float m_maxDistance = 30f;
+
+ public float m_moveForce = 10f;
+
+ public float m_pullLineSpeed = 1f;
+
+ public float m_pullStaminaUse = 10f;
+
+ public float m_hookedStaminaPerSec = 1f;
+
+ public float m_breakDistance = 4f;
+
+ public float m_range = 10f;
+
+ public float m_nibbleForce = 10f;
+
+ public EffectList m_nibbleEffect = new EffectList();
+
+ public EffectList m_lineBreakEffect = new EffectList();
+
+ public float m_maxLineSlack = 0.3f;
+
+ public LineConnect m_rodLine;
+
+ public LineConnect m_hookLine;
+
+ private ZNetView m_nview;
+
+ private Rigidbody m_body;
+
+ private Floating m_floating;
+
+ private float m_lineLength;
+
+ private float m_msgTime;
+
+ private Fish m_nibbler;
+
+ private float m_nibbleTime;
+
+ private static List<FishingFloat> m_allInstances = new List<FishingFloat>();
+
+ public string GetTooltipString(int itemQuality)
+ {
+ return "";
+ }
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ m_floating = GetComponent<Floating>();
+ m_nview.Register<ZDOID>("Nibble", RPC_Nibble);
+ }
+
+ private void OnDestroy()
+ {
+ m_allInstances.Remove(this);
+ }
+
+ public void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemDrop.ItemData item)
+ {
+ FishingFloat fishingFloat = FindFloat(owner);
+ if ((bool)fishingFloat)
+ {
+ ZNetScene.instance.Destroy(fishingFloat.gameObject);
+ }
+ ZDOID zDOID = owner.GetZDOID();
+ m_nview.GetZDO().Set("RodOwner", zDOID);
+ m_allInstances.Add(this);
+ Transform rodTop = GetRodTop(owner);
+ if (rodTop == null)
+ {
+ ZLog.LogWarning("Failed to find fishing rod top");
+ return;
+ }
+ m_rodLine.SetPeer(owner.GetZDOID());
+ m_lineLength = Vector3.Distance(rodTop.position, base.transform.position);
+ owner.Message(MessageHud.MessageType.Center, m_lineLength.ToString("0m"));
+ }
+
+ public Character GetOwner()
+ {
+ if (!m_nview.IsValid())
+ {
+ return null;
+ }
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID("RodOwner");
+ GameObject gameObject = ZNetScene.instance.FindInstance(zDOID);
+ if (gameObject == null)
+ {
+ return null;
+ }
+ return gameObject.GetComponent<Character>();
+ }
+
+ private Transform GetRodTop(Character owner)
+ {
+ Transform transform = Utils.FindChild(owner.transform, "_RodTop");
+ if (transform == null)
+ {
+ ZLog.LogWarning("Failed to find fishing rod top");
+ return null;
+ }
+ return transform;
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ Character owner = GetOwner();
+ if (!owner)
+ {
+ ZLog.LogWarning("Fishing rod not found, destroying fishing float");
+ m_nview.Destroy();
+ return;
+ }
+ Transform rodTop = GetRodTop(owner);
+ if (!rodTop)
+ {
+ ZLog.LogWarning("Fishing rod not found, destroying fishing float");
+ m_nview.Destroy();
+ return;
+ }
+ if (owner.InAttack() || owner.IsHoldingAttack())
+ {
+ m_nview.Destroy();
+ return;
+ }
+ float magnitude = (rodTop.transform.position - base.transform.position).magnitude;
+ Fish fish = GetCatch();
+ if (!owner.HaveStamina() && fish != null)
+ {
+ SetCatch(null);
+ fish = null;
+ Message("$msg_fishing_lost", prioritized: true);
+ }
+ if ((bool)fish)
+ {
+ owner.UseStamina(m_hookedStaminaPerSec * fixedDeltaTime);
+ }
+ if (!fish && Utils.LengthXZ(m_body.velocity) > 2f)
+ {
+ TryToHook();
+ }
+ if (owner.IsBlocking() && owner.HaveStamina())
+ {
+ float num = m_pullStaminaUse;
+ if (fish != null)
+ {
+ num += fish.m_staminaUse;
+ }
+ owner.UseStamina(num * fixedDeltaTime);
+ if (m_lineLength > magnitude - 0.2f)
+ {
+ float lineLength = m_lineLength;
+ m_lineLength -= fixedDeltaTime * m_pullLineSpeed;
+ TryToHook();
+ if ((int)m_lineLength != (int)lineLength)
+ {
+ Message(m_lineLength.ToString("0m"));
+ }
+ }
+ if (m_lineLength <= 0.5f)
+ {
+ if ((bool)fish)
+ {
+ if (fish.Pickup(owner as Humanoid))
+ {
+ Message("$msg_fishing_catched " + fish.GetHoverName(), prioritized: true);
+ SetCatch(null);
+ }
+ }
+ else
+ {
+ m_nview.Destroy();
+ }
+ return;
+ }
+ }
+ m_rodLine.m_slack = (1f - Utils.LerpStep(m_lineLength / 2f, m_lineLength, magnitude)) * m_maxLineSlack;
+ if (magnitude - m_lineLength > m_breakDistance || magnitude > m_maxDistance)
+ {
+ Message("$msg_fishing_linebroke", prioritized: true);
+ m_nview.Destroy();
+ m_lineBreakEffect.Create(base.transform.position, Quaternion.identity);
+ return;
+ }
+ if ((bool)fish)
+ {
+ Utils.Pull(m_body, fish.transform.position, 0.5f, m_moveForce, 0.5f, 0.3f);
+ }
+ Utils.Pull(m_body, rodTop.transform.position, m_lineLength, m_moveForce, 1f, 0.3f);
+ }
+
+ private void TryToHook()
+ {
+ if (m_nibbler != null && Time.time - m_nibbleTime < 0.5f && GetCatch() == null)
+ {
+ Message("$msg_fishing_hooked", prioritized: true);
+ SetCatch(m_nibbler);
+ m_nibbler = null;
+ }
+ }
+
+ private void SetCatch(Fish fish)
+ {
+ if ((bool)fish)
+ {
+ m_nview.GetZDO().Set("CatchID", fish.GetZDOID());
+ m_hookLine.SetPeer(fish.GetZDOID());
+ }
+ else
+ {
+ m_nview.GetZDO().Set("CatchID", ZDOID.None);
+ m_hookLine.SetPeer(ZDOID.None);
+ }
+ }
+
+ public Fish GetCatch()
+ {
+ if (!m_nview.IsValid())
+ {
+ return null;
+ }
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID("CatchID");
+ if (!zDOID.IsNone())
+ {
+ GameObject gameObject = ZNetScene.instance.FindInstance(zDOID);
+ if ((bool)gameObject)
+ {
+ return gameObject.GetComponent<Fish>();
+ }
+ }
+ return null;
+ }
+
+ public bool IsInWater()
+ {
+ return m_floating.IsInWater();
+ }
+
+ public void Nibble(Fish fish)
+ {
+ m_nview.InvokeRPC("Nibble", fish.GetZDOID());
+ }
+
+ public void RPC_Nibble(long sender, ZDOID fishID)
+ {
+ if (!(Time.time - m_nibbleTime < 1f) && !(GetCatch() != null))
+ {
+ m_nibbleEffect.Create(base.transform.position, Quaternion.identity, base.transform);
+ m_body.AddForce(Vector3.down * m_nibbleForce, ForceMode.VelocityChange);
+ GameObject gameObject = ZNetScene.instance.FindInstance(fishID);
+ if ((bool)gameObject)
+ {
+ m_nibbler = gameObject.GetComponent<Fish>();
+ m_nibbleTime = Time.time;
+ }
+ }
+ }
+
+ public static List<FishingFloat> GetAllInstances()
+ {
+ return m_allInstances;
+ }
+
+ private static FishingFloat FindFloat(Character owner)
+ {
+ foreach (FishingFloat allInstance in m_allInstances)
+ {
+ if (owner == allInstance.GetOwner())
+ {
+ return allInstance;
+ }
+ }
+ return null;
+ }
+
+ public static FishingFloat FindFloat(Fish fish)
+ {
+ foreach (FishingFloat allInstance in m_allInstances)
+ {
+ if (allInstance.GetCatch() == fish)
+ {
+ return allInstance;
+ }
+ }
+ return null;
+ }
+
+ private void Message(string msg, bool prioritized = false)
+ {
+ if (prioritized || !(Time.time - m_msgTime < 1f))
+ {
+ m_msgTime = Time.time;
+ Character owner = GetOwner();
+ if ((bool)owner)
+ {
+ owner.Message(MessageHud.MessageType.Center, Localization.instance.Localize(msg));
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Floating.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Floating.cs
new file mode 100644
index 0000000..de3b5ff
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Floating.cs
@@ -0,0 +1,174 @@
+using UnityEngine;
+
+public class Floating : MonoBehaviour, IWaterInteractable
+{
+ public float m_waterLevelOffset;
+
+ public float m_forceDistance = 1f;
+
+ public float m_force = 0.5f;
+
+ public float m_balanceForceFraction = 0.02f;
+
+ public float m_damping = 0.05f;
+
+ private static float m_minImpactEffectVelocity = 0.5f;
+
+ public EffectList m_impactEffects = new EffectList();
+
+ public GameObject m_surfaceEffects;
+
+ private float m_inWater = -10000f;
+
+ private bool m_beenInWater;
+
+ private bool m_wasInWater = true;
+
+ private Rigidbody m_body;
+
+ private Collider m_collider;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ m_collider = GetComponentInChildren<Collider>();
+ SetSurfaceEffect(enabled: false);
+ InvokeRepeating("TerrainCheck", Random.Range(10f, 30f), 30f);
+ }
+
+ public Transform GetTransform()
+ {
+ if (this == null)
+ {
+ return null;
+ }
+ return base.transform;
+ }
+
+ public bool IsOwner()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.IsOwner();
+ }
+ return false;
+ }
+
+ private void TerrainCheck()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return;
+ }
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ if (base.transform.position.y - groundHeight < -1f)
+ {
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + 1f;
+ base.transform.position = position;
+ Rigidbody component = GetComponent<Rigidbody>();
+ if ((bool)component)
+ {
+ component.velocity = Vector3.zero;
+ }
+ ZLog.Log("Moved up item " + base.gameObject.name);
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return;
+ }
+ if (!IsInWater())
+ {
+ SetSurfaceEffect(enabled: false);
+ return;
+ }
+ UpdateImpactEffect();
+ float floatDepth = GetFloatDepth();
+ if (floatDepth > 0f)
+ {
+ SetSurfaceEffect(enabled: false);
+ return;
+ }
+ SetSurfaceEffect(enabled: true);
+ Vector3 position = m_collider.ClosestPoint(base.transform.position + Vector3.down * 1000f);
+ Vector3 worldCenterOfMass = m_body.worldCenterOfMass;
+ float num = Mathf.Clamp01(Mathf.Abs(floatDepth) / m_forceDistance);
+ Vector3 vector = Vector3.up * m_force * num * (Time.fixedDeltaTime * 50f);
+ m_body.WakeUp();
+ m_body.AddForceAtPosition(vector * m_balanceForceFraction, position, ForceMode.VelocityChange);
+ m_body.AddForceAtPosition(vector, worldCenterOfMass, ForceMode.VelocityChange);
+ m_body.velocity -= m_body.velocity * m_damping * num;
+ m_body.angularVelocity -= m_body.angularVelocity * m_damping * num;
+ }
+
+ public bool IsInWater()
+ {
+ return m_inWater > -10000f;
+ }
+
+ private void SetSurfaceEffect(bool enabled)
+ {
+ if (m_surfaceEffects != null)
+ {
+ m_surfaceEffects.SetActive(enabled);
+ }
+ }
+
+ private void UpdateImpactEffect()
+ {
+ if (m_body.IsSleeping() || !m_impactEffects.HasEffects())
+ {
+ return;
+ }
+ Vector3 vector = m_collider.ClosestPoint(base.transform.position + Vector3.down * 1000f);
+ if (vector.y < m_inWater)
+ {
+ if (!m_wasInWater)
+ {
+ m_wasInWater = true;
+ Vector3 pos = vector;
+ pos.y = m_inWater;
+ if (m_body.GetPointVelocity(vector).magnitude > m_minImpactEffectVelocity)
+ {
+ m_impactEffects.Create(pos, Quaternion.identity);
+ }
+ }
+ }
+ else
+ {
+ m_wasInWater = false;
+ }
+ }
+
+ private float GetFloatDepth()
+ {
+ return m_body.worldCenterOfMass.y - m_inWater - m_waterLevelOffset;
+ }
+
+ public void SetInWater(float waterLevel)
+ {
+ m_inWater = waterLevel;
+ if (!m_beenInWater && waterLevel > -10000f && GetFloatDepth() < 0f)
+ {
+ m_beenInWater = true;
+ }
+ }
+
+ public bool BeenInWater()
+ {
+ return m_beenInWater;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.blue;
+ Gizmos.DrawWireCube(base.transform.position + Vector3.down * m_waterLevelOffset, new Vector3(1f, 0.05f, 1f));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FollowPlayer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FollowPlayer.cs
new file mode 100644
index 0000000..d5c2992
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FollowPlayer.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+
+public class FollowPlayer : MonoBehaviour
+{
+ public enum Type
+ {
+ Player,
+ Camera
+ }
+
+ public Type m_follow = Type.Camera;
+
+ public bool m_lockYPos;
+
+ public bool m_followCameraInFreefly;
+
+ public float m_maxYPos = 1000000f;
+
+ private void LateUpdate()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(Player.m_localPlayer == null) && !(mainCamera == null))
+ {
+ Vector3 zero = Vector3.zero;
+ zero = ((m_follow != Type.Camera && !GameCamera.InFreeFly()) ? Player.m_localPlayer.transform.position : mainCamera.transform.position);
+ if (m_lockYPos)
+ {
+ zero.y = base.transform.position.y;
+ }
+ if (zero.y > m_maxYPos)
+ {
+ zero.y = m_maxYPos;
+ }
+ base.transform.position = zero;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FootStep.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FootStep.cs
new file mode 100644
index 0000000..711bd91
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/FootStep.cs
@@ -0,0 +1,401 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class FootStep : MonoBehaviour
+{
+ public enum MotionType
+ {
+ Walk = 1,
+ Run = 2,
+ Sneak = 4,
+ Climbing = 8,
+ Swiming = 0x10,
+ Land = 0x20
+ }
+
+ public enum GroundMaterial
+ {
+ None = 0,
+ Default = 1,
+ Water = 2,
+ Stone = 4,
+ Wood = 8,
+ Snow = 0x10,
+ Mud = 0x20,
+ Grass = 0x40,
+ GenericGround = 0x80,
+ Metal = 0x100
+ }
+
+ [Serializable]
+ public class StepEffect
+ {
+ public string m_name = "";
+
+ [BitMask(typeof(MotionType))]
+ public MotionType m_motionType = MotionType.Walk;
+
+ [BitMask(typeof(GroundMaterial))]
+ public GroundMaterial m_material = GroundMaterial.Default;
+
+ public GameObject[] m_effectPrefabs = new GameObject[0];
+ }
+
+ private static Queue<GameObject> m_stepInstances = new Queue<GameObject>();
+
+ private const int m_maxFootstepInstances = 30;
+
+ public float m_footstepCullDistance = 20f;
+
+ public List<StepEffect> m_effects = new List<StepEffect>();
+
+ public Transform[] m_feet = new Transform[0];
+
+ private static int m_footstepID = 0;
+
+ private static int m_forwardSpeedID = 0;
+
+ private static int m_sidewaySpeedID = 0;
+
+ private float m_footstep;
+
+ private float m_footstepTimer;
+
+ private const float m_minFootstepInterval = 0.2f;
+
+ private int m_pieceLayer;
+
+ private Animator m_animator;
+
+ private Character m_character;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_animator = GetComponentInChildren<Animator>();
+ m_character = GetComponent<Character>();
+ m_nview = GetComponent<ZNetView>();
+ if (m_footstepID == 0)
+ {
+ m_footstepID = Animator.StringToHash("footstep");
+ m_forwardSpeedID = Animator.StringToHash("forward_speed");
+ m_sidewaySpeedID = Animator.StringToHash("sideway_speed");
+ }
+ m_footstep = m_animator.GetFloat(m_footstepID);
+ if (m_pieceLayer == 0)
+ {
+ m_pieceLayer = LayerMask.NameToLayer("piece");
+ }
+ Character character = m_character;
+ character.m_onLand = (Action<Vector3>)Delegate.Combine(character.m_onLand, new Action<Vector3>(OnLand));
+ if (m_nview.IsValid())
+ {
+ m_nview.Register<int, Vector3>("Step", RPC_Step);
+ }
+ }
+
+ private void Update()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ UpdateFootstep(Time.deltaTime);
+ }
+ }
+
+ private void UpdateFootstep(float dt)
+ {
+ if (m_feet.Length == 0)
+ {
+ return;
+ }
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null) && !(Vector3.Distance(base.transform.position, mainCamera.transform.position) > m_footstepCullDistance))
+ {
+ m_footstepTimer += dt;
+ float @float = m_animator.GetFloat(m_footstepID);
+ if (Mathf.Sign(@float) != Mathf.Sign(m_footstep) && Mathf.Max(Mathf.Abs(m_animator.GetFloat(m_forwardSpeedID)), Mathf.Abs(m_animator.GetFloat(m_sidewaySpeedID))) > 0.2f && m_footstepTimer > 0.2f)
+ {
+ m_footstepTimer = 0f;
+ OnFoot();
+ }
+ m_footstep = @float;
+ }
+ }
+
+ private Transform FindActiveFoot()
+ {
+ Transform transform = null;
+ float num = 9999f;
+ Vector3 forward = base.transform.forward;
+ Transform[] feet = m_feet;
+ foreach (Transform transform2 in feet)
+ {
+ Vector3 rhs = transform2.position - base.transform.position;
+ float num2 = Vector3.Dot(forward, rhs);
+ if (num2 > num || transform == null)
+ {
+ transform = transform2;
+ num = num2;
+ }
+ }
+ return transform;
+ }
+
+ private Transform FindFoot(string name)
+ {
+ Transform[] feet = m_feet;
+ foreach (Transform transform in feet)
+ {
+ if (transform.gameObject.name == name)
+ {
+ return transform;
+ }
+ }
+ return null;
+ }
+
+ public void OnFoot()
+ {
+ Transform transform = FindActiveFoot();
+ if (!(transform == null))
+ {
+ OnFoot(transform);
+ }
+ }
+
+ public void OnFoot(string name)
+ {
+ Transform transform = FindFoot(name);
+ if (transform == null)
+ {
+ ZLog.LogWarning("FAiled to find foot:" + name);
+ }
+ else
+ {
+ OnFoot(transform);
+ }
+ }
+
+ private void OnLand(Vector3 point)
+ {
+ if (m_nview.IsValid())
+ {
+ GroundMaterial groundMaterial = GetGroundMaterial(m_character, point);
+ int num = FindBestStepEffect(groundMaterial, MotionType.Land);
+ if (num != -1)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "Step", num, point);
+ }
+ }
+ }
+
+ private void OnFoot(Transform foot)
+ {
+ if (m_nview.IsValid())
+ {
+ Vector3 vector = ((foot != null) ? foot.position : base.transform.position);
+ MotionType motionType = GetMotionType(m_character);
+ GroundMaterial groundMaterial = GetGroundMaterial(m_character, vector);
+ int num = FindBestStepEffect(groundMaterial, motionType);
+ if (num != -1)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "Step", num, vector);
+ }
+ }
+ }
+
+ private static void PurgeOldEffects()
+ {
+ while (m_stepInstances.Count > 30)
+ {
+ GameObject gameObject = m_stepInstances.Dequeue();
+ if ((bool)gameObject)
+ {
+ UnityEngine.Object.Destroy(gameObject);
+ }
+ }
+ }
+
+ private void DoEffect(StepEffect effect, Vector3 point)
+ {
+ GameObject[] effectPrefabs = effect.m_effectPrefabs;
+ foreach (GameObject gameObject in effectPrefabs)
+ {
+ GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, point, base.transform.rotation);
+ m_stepInstances.Enqueue(gameObject2);
+ if (gameObject2.GetComponent<ZNetView>() != null)
+ {
+ ZLog.LogWarning("Foot step effect " + effect.m_name + " prefab " + gameObject.name + " in " + m_character.gameObject.name + " should not contain a ZNetView component");
+ }
+ }
+ PurgeOldEffects();
+ }
+
+ private void RPC_Step(long sender, int effectIndex, Vector3 point)
+ {
+ StepEffect effect = m_effects[effectIndex];
+ DoEffect(effect, point);
+ }
+
+ private MotionType GetMotionType(Character character)
+ {
+ if (m_character.IsSwiming())
+ {
+ return MotionType.Swiming;
+ }
+ if (m_character.IsWallRunning())
+ {
+ return MotionType.Climbing;
+ }
+ if (m_character.IsRunning())
+ {
+ return MotionType.Run;
+ }
+ if (m_character.IsSneaking())
+ {
+ return MotionType.Sneak;
+ }
+ return MotionType.Walk;
+ }
+
+ private GroundMaterial GetGroundMaterial(Character character, Vector3 point)
+ {
+ if (character.InWater())
+ {
+ return GroundMaterial.Water;
+ }
+ if (!character.IsOnGround())
+ {
+ return GroundMaterial.None;
+ }
+ float num = Mathf.Acos(Mathf.Clamp01(character.GetLastGroundNormal().y)) * 57.29578f;
+ Collider lastGroundCollider = character.GetLastGroundCollider();
+ if ((bool)lastGroundCollider)
+ {
+ Heightmap component = lastGroundCollider.GetComponent<Heightmap>();
+ if (component != null)
+ {
+ switch (component.GetBiome(point))
+ {
+ case Heightmap.Biome.Mountain:
+ case Heightmap.Biome.DeepNorth:
+ if (num < 40f && !component.IsCleared(point))
+ {
+ return GroundMaterial.Snow;
+ }
+ break;
+ case Heightmap.Biome.Swamp:
+ if (num < 40f)
+ {
+ return GroundMaterial.Mud;
+ }
+ break;
+ case Heightmap.Biome.Meadows:
+ case Heightmap.Biome.BlackForest:
+ if (num < 25f)
+ {
+ return GroundMaterial.Grass;
+ }
+ break;
+ }
+ return GroundMaterial.GenericGround;
+ }
+ if (lastGroundCollider.gameObject.layer == m_pieceLayer)
+ {
+ WearNTear componentInParent = lastGroundCollider.GetComponentInParent<WearNTear>();
+ if ((bool)componentInParent)
+ {
+ switch (componentInParent.m_materialType)
+ {
+ case WearNTear.MaterialType.Wood:
+ return GroundMaterial.Wood;
+ case WearNTear.MaterialType.Stone:
+ return GroundMaterial.Stone;
+ case WearNTear.MaterialType.HardWood:
+ return GroundMaterial.Wood;
+ case WearNTear.MaterialType.Iron:
+ return GroundMaterial.Metal;
+ }
+ }
+ }
+ }
+ return GroundMaterial.Default;
+ }
+
+ public void FindJoints()
+ {
+ ZLog.Log("Finding joints");
+ Transform transform = Utils.FindChild(base.transform, "LeftFootFront");
+ Transform transform2 = Utils.FindChild(base.transform, "RightFootFront");
+ Transform transform3 = Utils.FindChild(base.transform, "LeftFoot");
+ if (transform3 == null)
+ {
+ transform3 = Utils.FindChild(base.transform, "LeftFootBack");
+ }
+ if (transform3 == null)
+ {
+ transform3 = Utils.FindChild(base.transform, "l_foot");
+ }
+ if (transform3 == null)
+ {
+ transform3 = Utils.FindChild(base.transform, "Foot.l");
+ }
+ if (transform3 == null)
+ {
+ transform3 = Utils.FindChild(base.transform, "foot.l");
+ }
+ Transform transform4 = Utils.FindChild(base.transform, "RightFoot");
+ if (transform4 == null)
+ {
+ transform4 = Utils.FindChild(base.transform, "RightFootBack");
+ }
+ if (transform4 == null)
+ {
+ transform4 = Utils.FindChild(base.transform, "r_foot");
+ }
+ if (transform4 == null)
+ {
+ transform4 = Utils.FindChild(base.transform, "Foot.r");
+ }
+ if (transform4 == null)
+ {
+ transform4 = Utils.FindChild(base.transform, "foot.r");
+ }
+ List<Transform> list = new List<Transform>();
+ if ((bool)transform)
+ {
+ list.Add(transform);
+ }
+ if ((bool)transform2)
+ {
+ list.Add(transform2);
+ }
+ if ((bool)transform3)
+ {
+ list.Add(transform3);
+ }
+ if ((bool)transform4)
+ {
+ list.Add(transform4);
+ }
+ m_feet = list.ToArray();
+ }
+
+ private int FindBestStepEffect(GroundMaterial material, MotionType motion)
+ {
+ StepEffect stepEffect = null;
+ int result = -1;
+ for (int i = 0; i < m_effects.Count; i++)
+ {
+ StepEffect stepEffect2 = m_effects[i];
+ if (((stepEffect2.m_material & material) != 0 || (stepEffect == null && (stepEffect2.m_material & GroundMaterial.Default) != 0)) && (stepEffect2.m_motionType & motion) != 0)
+ {
+ stepEffect = stepEffect2;
+ result = i;
+ }
+ }
+ return result;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Game.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Game.cs
new file mode 100644
index 0000000..ce6806a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Game.cs
@@ -0,0 +1,575 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Assertions;
+using UnityEngine.SceneManagement;
+
+public class Game : MonoBehaviour
+{
+ private List<ZDO> m_tempPortalList = new List<ZDO>();
+
+ private static Game m_instance;
+
+ public GameObject m_playerPrefab;
+
+ public GameObject m_portalPrefab;
+
+ public GameObject m_consolePrefab;
+
+ public string m_StartLocation = "StartTemple";
+
+ private static string m_profileFilename;
+
+ private PlayerProfile m_playerProfile;
+
+ private bool m_requestRespawn;
+
+ private float m_respawnWait;
+
+ private const float m_respawnLoadDuration = 8f;
+
+ private bool m_haveSpawned;
+
+ private bool m_firstSpawn = true;
+
+ private bool m_loggedOut;
+
+ private Vector3 m_randomStartPoint = Vector3.zero;
+
+ private UnityEngine.Random.State m_spawnRandomState;
+
+ private bool m_sleeping;
+
+ private const float m_collectResourcesInterval = 600f;
+
+ private float m_saveTimer;
+
+ private const float m_saveInterval = 1800f;
+
+ private const float m_difficultyScaleRange = 200f;
+
+ private const float m_damageScalePerPlayer = 0.08f;
+
+ private const float m_healthScalePerPlayer = 0.4f;
+
+ private int m_forcePlayers;
+
+ public static Game instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ Assert.raiseExceptions = true;
+ ZInput.Initialize();
+ if (!Console.instance)
+ {
+ UnityEngine.Object.Instantiate(m_consolePrefab);
+ }
+ if (string.IsNullOrEmpty(m_profileFilename))
+ {
+ m_playerProfile = new PlayerProfile("Developer");
+ m_playerProfile.SetName("Odev");
+ m_playerProfile.Load();
+ }
+ else
+ {
+ ZLog.Log("Loading player profile " + m_profileFilename);
+ m_playerProfile = new PlayerProfile(m_profileFilename);
+ m_playerProfile.Load();
+ }
+ InvokeRepeating("CollectResources", 600f, 600f);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "InGame", 0L);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "InputMode", ZInput.IsGamepadActive() ? "Gamepad" : "MK", 0L);
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Start()
+ {
+ Application.targetFrameRate = -1;
+ ZRoutedRpc.instance.Register("SleepStart", SleepStart);
+ ZRoutedRpc.instance.Register("SleepStop", SleepStop);
+ ZRoutedRpc.instance.Register<float>("Ping", RPC_Ping);
+ ZRoutedRpc.instance.Register<float>("Pong", RPC_Pong);
+ ZRoutedRpc.instance.Register<string, int, Vector3>("DiscoverLocationRespons", RPC_DiscoverLocationRespons);
+ if (ZNet.instance.IsServer())
+ {
+ ZRoutedRpc.instance.Register<string, Vector3, string, int>("DiscoverClosestLocation", RPC_DiscoverClosestLocation);
+ StartCoroutine("ConnectPortals");
+ InvokeRepeating("UpdateSleeping", 2f, 2f);
+ }
+ }
+
+ private void ServerLog()
+ {
+ int peerConnections = ZNet.instance.GetPeerConnections();
+ int num = ZDOMan.instance.NrOfObjects();
+ int sentZDOs = ZDOMan.instance.GetSentZDOs();
+ int recvZDOs = ZDOMan.instance.GetRecvZDOs();
+ ZLog.Log(" Connections " + peerConnections + " ZDOS:" + num + " sent:" + sentZDOs + " recv:" + recvZDOs);
+ }
+
+ private void CollectResources()
+ {
+ Resources.UnloadUnusedAssets();
+ }
+
+ public void Logout()
+ {
+ if (!m_loggedOut)
+ {
+ m_loggedOut = true;
+ Shutdown();
+ SceneManager.LoadScene("start");
+ }
+ }
+
+ public bool IsLoggingOut()
+ {
+ return m_loggedOut;
+ }
+
+ private void OnApplicationQuit()
+ {
+ ZLog.Log("Game - OnApplicationQuit");
+ Shutdown();
+ }
+
+ private void Shutdown()
+ {
+ SavePlayerProfile(setLogoutPoint: true);
+ ZNetScene.instance.Shutdown();
+ ZNet.instance.Shutdown();
+ }
+
+ private void SavePlayerProfile(bool setLogoutPoint)
+ {
+ if ((bool)Player.m_localPlayer)
+ {
+ m_playerProfile.SavePlayerData(Player.m_localPlayer);
+ Minimap.instance.SaveMapData();
+ if (setLogoutPoint)
+ {
+ m_playerProfile.SaveLogoutPoint();
+ }
+ }
+ m_playerProfile.Save();
+ }
+
+ private Player SpawnPlayer(Vector3 spawnPoint)
+ {
+ ZLog.DevLog("Spawning player:" + Time.frameCount);
+ Player component = UnityEngine.Object.Instantiate(m_playerPrefab, spawnPoint, Quaternion.identity).GetComponent<Player>();
+ component.SetLocalPlayer();
+ m_playerProfile.LoadPlayerData(component);
+ ZNet.instance.SetCharacterID(component.GetZDOID());
+ component.OnSpawned();
+ return component;
+ }
+
+ private Bed FindBedNearby(Vector3 point, float maxDistance)
+ {
+ Bed[] array = UnityEngine.Object.FindObjectsOfType<Bed>();
+ foreach (Bed bed in array)
+ {
+ if (bed.IsCurrent())
+ {
+ return bed;
+ }
+ }
+ return null;
+ }
+
+ private bool FindSpawnPoint(out Vector3 point, out bool usedLogoutPoint, float dt)
+ {
+ m_respawnWait += dt;
+ usedLogoutPoint = false;
+ if (m_playerProfile.HaveLogoutPoint())
+ {
+ Vector3 logoutPoint = m_playerProfile.GetLogoutPoint();
+ ZNet.instance.SetReferencePosition(logoutPoint);
+ if (m_respawnWait > 8f && ZNetScene.instance.IsAreaReady(logoutPoint))
+ {
+ if (!ZoneSystem.instance.GetGroundHeight(logoutPoint, out var height))
+ {
+ ZLog.Log("Invalid spawn point, no ground " + logoutPoint);
+ m_respawnWait = 0f;
+ m_playerProfile.ClearLoguoutPoint();
+ point = Vector3.zero;
+ return false;
+ }
+ m_playerProfile.ClearLoguoutPoint();
+ point = logoutPoint;
+ if (point.y < height)
+ {
+ point.y = height;
+ }
+ point.y += 0.25f;
+ usedLogoutPoint = true;
+ ZLog.Log("Spawned after " + m_respawnWait);
+ return true;
+ }
+ point = Vector3.zero;
+ return false;
+ }
+ if (m_playerProfile.HaveCustomSpawnPoint())
+ {
+ Vector3 customSpawnPoint = m_playerProfile.GetCustomSpawnPoint();
+ ZNet.instance.SetReferencePosition(customSpawnPoint);
+ if (m_respawnWait > 8f && ZNetScene.instance.IsAreaReady(customSpawnPoint))
+ {
+ Bed bed = FindBedNearby(customSpawnPoint, 5f);
+ if (bed != null)
+ {
+ ZLog.Log("Found bed at custom spawn point");
+ point = bed.GetSpawnPoint();
+ return true;
+ }
+ ZLog.Log("Failed to find bed at custom spawn point, using original");
+ m_playerProfile.ClearCustomSpawnPoint();
+ m_respawnWait = 0f;
+ point = Vector3.zero;
+ return false;
+ }
+ point = Vector3.zero;
+ return false;
+ }
+ if (ZoneSystem.instance.GetLocationIcon(m_StartLocation, out var pos))
+ {
+ point = pos + Vector3.up * 2f;
+ ZNet.instance.SetReferencePosition(point);
+ return ZNetScene.instance.IsAreaReady(point);
+ }
+ ZNet.instance.SetReferencePosition(Vector3.zero);
+ point = Vector3.zero;
+ return false;
+ }
+
+ private static Vector3 GetPointOnCircle(float distance, float angle)
+ {
+ return new Vector3(Mathf.Sin(angle) * distance, 0f, Mathf.Cos(angle) * distance);
+ }
+
+ public void RequestRespawn(float delay)
+ {
+ CancelInvoke("_RequestRespawn");
+ Invoke("_RequestRespawn", delay);
+ }
+
+ private void _RequestRespawn()
+ {
+ ZLog.Log("Starting respawn");
+ if ((bool)Player.m_localPlayer)
+ {
+ m_playerProfile.SavePlayerData(Player.m_localPlayer);
+ }
+ if ((bool)Player.m_localPlayer)
+ {
+ ZNetScene.instance.Destroy(Player.m_localPlayer.gameObject);
+ ZNet.instance.SetCharacterID(ZDOID.None);
+ }
+ m_respawnWait = 0f;
+ m_requestRespawn = true;
+ MusicMan.instance.TriggerMusic("respawn");
+ }
+
+ private void Update()
+ {
+ ZInput.Update(Time.deltaTime);
+ UpdateSaving(Time.deltaTime);
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_haveSpawned && ZNet.GetConnectionStatus() == ZNet.ConnectionStatus.Connected)
+ {
+ m_haveSpawned = true;
+ RequestRespawn(0f);
+ }
+ ZInput.FixedUpdate(Time.fixedDeltaTime);
+ if (ZNet.GetConnectionStatus() != ZNet.ConnectionStatus.Connecting && ZNet.GetConnectionStatus() != ZNet.ConnectionStatus.Connected)
+ {
+ ZLog.Log("Lost connection to server:" + ZNet.GetConnectionStatus());
+ Logout();
+ }
+ else
+ {
+ UpdateRespawn(Time.fixedDeltaTime);
+ }
+ }
+
+ private void UpdateSaving(float dt)
+ {
+ m_saveTimer += dt;
+ if (m_saveTimer > 1800f)
+ {
+ m_saveTimer = 0f;
+ SavePlayerProfile(setLogoutPoint: false);
+ if ((bool)ZNet.instance)
+ {
+ ZNet.instance.Save();
+ }
+ }
+ }
+
+ private void UpdateRespawn(float dt)
+ {
+ if (m_requestRespawn && FindSpawnPoint(out var point, out var usedLogoutPoint, dt))
+ {
+ if (!usedLogoutPoint)
+ {
+ m_playerProfile.SetHomePoint(point);
+ }
+ SpawnPlayer(point);
+ m_requestRespawn = false;
+ if (m_firstSpawn)
+ {
+ m_firstSpawn = false;
+ Chat.instance.SendText(Talker.Type.Shout, "I have arrived!");
+ }
+ GC.Collect();
+ }
+ }
+
+ public bool WaitingForRespawn()
+ {
+ return m_requestRespawn;
+ }
+
+ public PlayerProfile GetPlayerProfile()
+ {
+ return m_playerProfile;
+ }
+
+ public static void SetProfile(string filename)
+ {
+ m_profileFilename = filename;
+ }
+
+ private IEnumerator ConnectPortals()
+ {
+ while (true)
+ {
+ m_tempPortalList.Clear();
+ int index = 0;
+ bool done;
+ do
+ {
+ done = ZDOMan.instance.GetAllZDOsWithPrefabIterative(m_portalPrefab.name, m_tempPortalList, ref index);
+ yield return null;
+ }
+ while (!done);
+ foreach (ZDO tempPortal in m_tempPortalList)
+ {
+ ZDOID zDOID = tempPortal.GetZDOID("target");
+ string @string = tempPortal.GetString("tag");
+ if (!zDOID.IsNone())
+ {
+ ZDO zDO = ZDOMan.instance.GetZDO(zDOID);
+ if (zDO == null || zDO.GetString("tag") != @string)
+ {
+ tempPortal.SetOwner(ZDOMan.instance.GetMyID());
+ tempPortal.Set("target", ZDOID.None);
+ ZDOMan.instance.ForceSendZDO(tempPortal.m_uid);
+ }
+ }
+ }
+ foreach (ZDO tempPortal2 in m_tempPortalList)
+ {
+ string string2 = tempPortal2.GetString("tag");
+ if (tempPortal2.GetZDOID("target").IsNone())
+ {
+ ZDO zDO2 = FindRandomUnconnectedPortal(m_tempPortalList, tempPortal2, string2);
+ if (zDO2 != null)
+ {
+ tempPortal2.SetOwner(ZDOMan.instance.GetMyID());
+ zDO2.SetOwner(ZDOMan.instance.GetMyID());
+ tempPortal2.Set("target", zDO2.m_uid);
+ zDO2.Set("target", tempPortal2.m_uid);
+ ZDOMan.instance.ForceSendZDO(tempPortal2.m_uid);
+ ZDOMan.instance.ForceSendZDO(zDO2.m_uid);
+ }
+ }
+ }
+ yield return new WaitForSeconds(5f);
+ }
+ }
+
+ private ZDO FindRandomUnconnectedPortal(List<ZDO> portals, ZDO skip, string tag)
+ {
+ List<ZDO> list = new List<ZDO>();
+ foreach (ZDO portal in portals)
+ {
+ if (portal != skip && portal.GetZDOID("target").IsNone() && !(portal.GetString("tag") != tag))
+ {
+ list.Add(portal);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return null;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ private ZDO FindClosestUnconnectedPortal(List<ZDO> portals, ZDO skip, Vector3 refPos)
+ {
+ ZDO zDO = null;
+ float num = 99999f;
+ foreach (ZDO portal in portals)
+ {
+ if (portal != skip && portal.GetZDOID("target").IsNone())
+ {
+ float num2 = Vector3.Distance(refPos, portal.GetPosition());
+ if (zDO == null || num2 < num)
+ {
+ zDO = portal;
+ num = num2;
+ }
+ }
+ }
+ return zDO;
+ }
+
+ private void UpdateSleeping()
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ return;
+ }
+ if (m_sleeping)
+ {
+ if (!EnvMan.instance.IsTimeSkipping())
+ {
+ m_sleeping = false;
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SleepStop");
+ }
+ }
+ else if (!EnvMan.instance.IsTimeSkipping() && (EnvMan.instance.IsAfternoon() || EnvMan.instance.IsNight()) && EverybodyIsTryingToSleep())
+ {
+ EnvMan.instance.SkipToMorning();
+ m_sleeping = true;
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SleepStart");
+ }
+ }
+
+ private bool EverybodyIsTryingToSleep()
+ {
+ List<ZDO> allCharacterZDOS = ZNet.instance.GetAllCharacterZDOS();
+ if (allCharacterZDOS.Count == 0)
+ {
+ return false;
+ }
+ foreach (ZDO item in allCharacterZDOS)
+ {
+ if (!item.GetBool("inBed"))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void SleepStart(long sender)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ localPlayer.SetSleeping(sleep: true);
+ }
+ }
+
+ private void SleepStop(long sender)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ localPlayer.SetSleeping(sleep: false);
+ localPlayer.AttachStop();
+ }
+ }
+
+ public void DiscoverClosestLocation(string name, Vector3 point, string pinName, int pinType)
+ {
+ ZLog.Log("DiscoverClosestLocation");
+ ZRoutedRpc.instance.InvokeRoutedRPC("DiscoverClosestLocation", name, point, pinName, pinType);
+ }
+
+ private void RPC_DiscoverClosestLocation(long sender, string name, Vector3 point, string pinName, int pinType)
+ {
+ if (ZoneSystem.instance.FindClosestLocation(name, point, out var closest))
+ {
+ ZLog.Log("Found location of type " + name);
+ ZRoutedRpc.instance.InvokeRoutedRPC(sender, "DiscoverLocationRespons", pinName, pinType, closest.m_position);
+ }
+ else
+ {
+ ZLog.LogWarning("Failed to find location of type " + name);
+ }
+ }
+
+ private void RPC_DiscoverLocationRespons(long sender, string pinName, int pinType, Vector3 pos)
+ {
+ Minimap.instance.DiscoverLocation(pos, (Minimap.PinType)pinType, pinName);
+ }
+
+ public void Ping()
+ {
+ if ((bool)Console.instance)
+ {
+ Console.instance.Print("Ping sent to server");
+ }
+ ZRoutedRpc.instance.InvokeRoutedRPC("Ping", Time.time);
+ }
+
+ private void RPC_Ping(long sender, float time)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(sender, "Pong", time);
+ }
+
+ private void RPC_Pong(long sender, float time)
+ {
+ float num = Time.time - time;
+ string text = "Got ping reply from server: " + (int)(num * 1000f) + " ms";
+ ZLog.Log(text);
+ if ((bool)Console.instance)
+ {
+ Console.instance.Print(text);
+ }
+ }
+
+ public void SetForcePlayerDifficulty(int players)
+ {
+ m_forcePlayers = players;
+ }
+
+ private int GetPlayerDifficulty(Vector3 pos)
+ {
+ if (m_forcePlayers > 0)
+ {
+ return m_forcePlayers;
+ }
+ int num = Player.GetPlayersInRangeXZ(pos, 200f);
+ if (num < 1)
+ {
+ num = 1;
+ }
+ return num;
+ }
+
+ public float GetDifficultyDamageScale(Vector3 pos)
+ {
+ int playerDifficulty = GetPlayerDifficulty(pos);
+ return 1f + (float)(playerDifficulty - 1) * 0.08f;
+ }
+
+ public float GetDifficultyHealthScale(Vector3 pos)
+ {
+ int playerDifficulty = GetPlayerDifficulty(pos);
+ return 1f + (float)(playerDifficulty - 1) * 0.4f;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GameCamera.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GameCamera.cs
new file mode 100644
index 0000000..82f2d5e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GameCamera.cs
@@ -0,0 +1,663 @@
+using System;
+using System.IO;
+using UnityEngine;
+
+public class GameCamera : MonoBehaviour
+{
+ private Vector3 m_playerPos = Vector3.zero;
+
+ private Vector3 m_currentBaseOffset = Vector3.zero;
+
+ private Vector3 m_offsetBaseVel = Vector3.zero;
+
+ private Vector3 m_playerVel = Vector3.zero;
+
+ public Vector3 m_3rdOffset = Vector3.zero;
+
+ public Vector3 m_3rdCombatOffset = Vector3.zero;
+
+ public Vector3 m_fpsOffset = Vector3.zero;
+
+ public float m_flyingDistance = 15f;
+
+ public LayerMask m_blockCameraMask;
+
+ public float m_minDistance;
+
+ public float m_maxDistance = 6f;
+
+ public float m_maxDistanceBoat = 6f;
+
+ public float m_raycastWidth = 0.35f;
+
+ public bool m_smoothYTilt;
+
+ public float m_zoomSens = 10f;
+
+ public float m_inventoryOffset = 0.1f;
+
+ public float m_nearClipPlaneMin = 0.1f;
+
+ public float m_nearClipPlaneMax = 0.5f;
+
+ public float m_fov = 65f;
+
+ public float m_freeFlyMinFov = 5f;
+
+ public float m_freeFlyMaxFov = 120f;
+
+ public float m_tiltSmoothnessShipMin = 0.1f;
+
+ public float m_tiltSmoothnessShipMax = 0.5f;
+
+ public float m_shakeFreq = 10f;
+
+ public float m_shakeMovement = 1f;
+
+ public float m_smoothness = 0.1f;
+
+ public float m_minWaterDistance = 0.3f;
+
+ public Camera m_skyCamera;
+
+ private float m_distance = 4f;
+
+ private bool m_freeFly;
+
+ private float m_shakeIntensity;
+
+ private float m_shakeTimer;
+
+ private bool m_cameraShakeEnabled = true;
+
+ private bool m_mouseCapture;
+
+ private Quaternion m_freeFlyRef = Quaternion.identity;
+
+ private float m_freeFlyYaw;
+
+ private float m_freeFlyPitch;
+
+ private float m_freeFlySpeed = 20f;
+
+ private float m_freeFlySmooth;
+
+ private Vector3 m_freeFlySavedVel = Vector3.zero;
+
+ private Transform m_freeFlyTarget;
+
+ private Vector3 m_freeFlyTargetOffset = Vector3.zero;
+
+ private Transform m_freeFlyLockon;
+
+ private Vector3 m_freeFlyLockonOffset = Vector3.zero;
+
+ private Vector3 m_freeFlyVel = Vector3.zero;
+
+ private Vector3 m_freeFlyAcc = Vector3.zero;
+
+ private Vector3 m_freeFlyTurnVel = Vector3.zero;
+
+ private bool m_shipCameraTilt = true;
+
+ private Vector3 m_smoothedCameraUp = Vector3.up;
+
+ private Vector3 m_smoothedCameraUpVel = Vector3.zero;
+
+ private AudioListener m_listner;
+
+ private Camera m_camera;
+
+ private bool m_waterClipping;
+
+ private static GameCamera m_instance;
+
+ public static GameCamera instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_camera = GetComponent<Camera>();
+ m_listner = GetComponentInChildren<AudioListener>();
+ m_camera.depthTextureMode = DepthTextureMode.DepthNormals;
+ ApplySettings();
+ if (!Application.isEditor)
+ {
+ m_mouseCapture = true;
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void ApplySettings()
+ {
+ m_cameraShakeEnabled = PlayerPrefs.GetInt("CameraShake", 1) == 1;
+ m_shipCameraTilt = PlayerPrefs.GetInt("ShipCameraTilt", 1) == 1;
+ }
+
+ private void LateUpdate()
+ {
+ float deltaTime = Time.deltaTime;
+ if (Input.GetKeyDown(KeyCode.F11) || (m_freeFly && Input.GetKeyDown(KeyCode.Mouse1)))
+ {
+ ScreenShot();
+ }
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ UpdateBaseOffset(localPlayer, deltaTime);
+ }
+ UpdateMouseCapture();
+ UpdateCamera(deltaTime);
+ UpdateListner();
+ }
+
+ private void UpdateMouseCapture()
+ {
+ if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.F1))
+ {
+ m_mouseCapture = !m_mouseCapture;
+ }
+ if (m_mouseCapture && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible() && !Hud.IsPieceSelectionVisible())
+ {
+ Cursor.lockState = CursorLockMode.Locked;
+ Cursor.visible = false;
+ }
+ else
+ {
+ Cursor.lockState = CursorLockMode.None;
+ Cursor.visible = ZInput.IsMouseActive();
+ }
+ }
+
+ public static void ScreenShot()
+ {
+ DateTime now = DateTime.Now;
+ Directory.CreateDirectory(Application.persistentDataPath + "/screenshots");
+ string text = now.Hour.ToString("00") + now.Minute.ToString("00") + now.Second.ToString("00");
+ string text2 = now.ToString("yyyy-MM-dd");
+ string text3 = Application.persistentDataPath + "/screenshots/screenshot_" + text2 + "_" + text + ".png";
+ if (!File.Exists(text3))
+ {
+ ScreenCapture.CaptureScreenshot(text3);
+ ZLog.Log("Screenshot saved:" + text3);
+ }
+ }
+
+ private void UpdateListner()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer && !m_freeFly)
+ {
+ m_listner.transform.position = localPlayer.m_eye.position;
+ }
+ else
+ {
+ m_listner.transform.localPosition = Vector3.zero;
+ }
+ }
+
+ private void UpdateCamera(float dt)
+ {
+ if (m_freeFly)
+ {
+ UpdateFreeFly(dt);
+ UpdateCameraShake(dt);
+ return;
+ }
+ m_camera.fieldOfView = m_fov;
+ m_skyCamera.fieldOfView = m_fov;
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ if ((!Chat.instance || !Chat.instance.HasFocus()) && !Console.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !localPlayer.InCutscene() && !localPlayer.InPlaceMode())
+ {
+ float minDistance = m_minDistance;
+ float axis = Input.GetAxis("Mouse ScrollWheel");
+ m_distance -= axis * m_zoomSens;
+ float max = ((localPlayer.GetControlledShip() != null) ? m_maxDistanceBoat : m_maxDistance);
+ m_distance = Mathf.Clamp(m_distance, minDistance, max);
+ }
+ if (localPlayer.IsDead() && (bool)localPlayer.GetRagdoll())
+ {
+ Vector3 averageBodyPosition = localPlayer.GetRagdoll().GetAverageBodyPosition();
+ base.transform.LookAt(averageBodyPosition);
+ }
+ else
+ {
+ GetCameraPosition(dt, out var pos, out var rot);
+ base.transform.position = pos;
+ base.transform.rotation = rot;
+ }
+ UpdateCameraShake(dt);
+ }
+ }
+
+ private void GetCameraPosition(float dt, out Vector3 pos, out Quaternion rot)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null)
+ {
+ pos = base.transform.position;
+ rot = base.transform.rotation;
+ return;
+ }
+ Vector3 vector = GetOffsetedEyePos();
+ float num = m_distance;
+ if (localPlayer.InIntro())
+ {
+ vector = localPlayer.transform.position;
+ num = m_flyingDistance;
+ }
+ Vector3 vector2 = -localPlayer.m_eye.transform.forward;
+ if (m_smoothYTilt && !localPlayer.InIntro())
+ {
+ num = Mathf.Lerp(num, 1.5f, Utils.SmoothStep(0f, -0.5f, vector2.y));
+ }
+ Vector3 end = vector + vector2 * num;
+ CollideRay2(localPlayer.m_eye.position, vector, ref end);
+ UpdateNearClipping(vector, end, dt);
+ float waterLevel = WaterVolume.GetWaterLevel(end);
+ if (end.y < waterLevel + m_minWaterDistance)
+ {
+ end.y = waterLevel + m_minWaterDistance;
+ m_waterClipping = true;
+ }
+ else
+ {
+ m_waterClipping = false;
+ }
+ pos = end;
+ rot = localPlayer.m_eye.transform.rotation;
+ if (m_shipCameraTilt)
+ {
+ ApplyCameraTilt(localPlayer, dt, ref rot);
+ }
+ }
+
+ private void ApplyCameraTilt(Player player, float dt, ref Quaternion rot)
+ {
+ if (!player.InIntro())
+ {
+ Ship standingOnShip = player.GetStandingOnShip();
+ float f = Mathf.Clamp01((m_distance - m_minDistance) / (m_maxDistanceBoat - m_minDistance));
+ f = Mathf.Pow(f, 2f);
+ float smoothTime = Mathf.Lerp(m_tiltSmoothnessShipMin, m_tiltSmoothnessShipMax, f);
+ Vector3 up = Vector3.up;
+ if (standingOnShip != null)
+ {
+ up = standingOnShip.transform.up;
+ }
+ else if (player.IsAttached())
+ {
+ up = player.GetVisual().transform.up;
+ }
+ Vector3 forward = player.m_eye.transform.forward;
+ Vector3 target = Vector3.Lerp(up, Vector3.up, f * 0.5f);
+ m_smoothedCameraUp = Vector3.SmoothDamp(m_smoothedCameraUp, target, ref m_smoothedCameraUpVel, smoothTime, 99f, dt);
+ rot = Quaternion.LookRotation(forward, m_smoothedCameraUp);
+ }
+ }
+
+ private void UpdateNearClipping(Vector3 eyePos, Vector3 camPos, float dt)
+ {
+ float num = m_nearClipPlaneMax;
+ Vector3 normalized = (camPos - eyePos).normalized;
+ if (m_waterClipping || Physics.CheckSphere(camPos - normalized * m_nearClipPlaneMax, m_nearClipPlaneMax, m_blockCameraMask))
+ {
+ num = m_nearClipPlaneMin;
+ }
+ if (m_camera.nearClipPlane != num)
+ {
+ m_camera.nearClipPlane = num;
+ }
+ }
+
+ private void CollideRay2(Vector3 eyePos, Vector3 offsetedEyePos, ref Vector3 end)
+ {
+ if (RayTestPoint(eyePos, offsetedEyePos, (end - offsetedEyePos).normalized, Vector3.Distance(eyePos, end), out var distance))
+ {
+ float t = Utils.LerpStep(0.5f, 2f, distance);
+ Vector3 a = eyePos + (end - eyePos).normalized * distance;
+ Vector3 b = offsetedEyePos + (end - offsetedEyePos).normalized * distance;
+ end = Vector3.Lerp(a, b, t);
+ }
+ }
+
+ private bool RayTestPoint(Vector3 point, Vector3 offsetedPoint, Vector3 dir, float maxDist, out float distance)
+ {
+ bool result = false;
+ distance = maxDist;
+ if (Physics.SphereCast(offsetedPoint, m_raycastWidth, dir, out var hitInfo, maxDist, m_blockCameraMask))
+ {
+ distance = hitInfo.distance;
+ result = true;
+ }
+ _ = offsetedPoint + dir * distance;
+ if (Physics.SphereCast(point, m_raycastWidth, dir, out hitInfo, maxDist, m_blockCameraMask))
+ {
+ if (hitInfo.distance < distance)
+ {
+ distance = hitInfo.distance;
+ }
+ result = true;
+ }
+ if (Physics.Raycast(point, dir, out hitInfo, maxDist, m_blockCameraMask))
+ {
+ float num = hitInfo.distance - m_nearClipPlaneMin;
+ if (num < distance)
+ {
+ distance = num;
+ }
+ result = true;
+ }
+ return result;
+ }
+
+ private bool RayTestPoint(Vector3 point, Vector3 dir, float maxDist, out Vector3 hitPoint)
+ {
+ if (Physics.SphereCast(point, 0.2f, dir, out var hitInfo, maxDist, m_blockCameraMask))
+ {
+ hitPoint = point + dir * hitInfo.distance;
+ return true;
+ }
+ if (Physics.Raycast(point, dir, out hitInfo, maxDist, m_blockCameraMask))
+ {
+ hitPoint = point + dir * (hitInfo.distance - 0.05f);
+ return true;
+ }
+ hitPoint = Vector3.zero;
+ return false;
+ }
+
+ private void UpdateFreeFly(float dt)
+ {
+ if (Console.IsVisible())
+ {
+ return;
+ }
+ Vector2 zero = Vector2.zero;
+ zero.x = Input.GetAxis("Mouse X");
+ zero.y = Input.GetAxis("Mouse Y");
+ zero.x += ZInput.GetJoyRightStickX() * 110f * dt;
+ zero.y += (0f - ZInput.GetJoyRightStickY()) * 110f * dt;
+ m_freeFlyYaw += zero.x;
+ m_freeFlyPitch -= zero.y;
+ if (Input.GetAxis("Mouse ScrollWheel") < 0f)
+ {
+ m_freeFlySpeed *= 0.8f;
+ }
+ if (Input.GetAxis("Mouse ScrollWheel") > 0f)
+ {
+ m_freeFlySpeed *= 1.2f;
+ }
+ if (Input.GetAxis("Mouse ScrollWheel") > 0f)
+ {
+ m_freeFlySpeed *= 1.2f;
+ }
+ if (ZInput.GetButton("JoyTabLeft"))
+ {
+ m_camera.fieldOfView = Mathf.Max(m_freeFlyMinFov, m_camera.fieldOfView - dt * 20f);
+ }
+ if (ZInput.GetButton("JoyTabRight"))
+ {
+ m_camera.fieldOfView = Mathf.Min(m_freeFlyMaxFov, m_camera.fieldOfView + dt * 20f);
+ }
+ m_skyCamera.fieldOfView = m_camera.fieldOfView;
+ if (ZInput.GetButton("JoyButtonY"))
+ {
+ m_freeFlySpeed += m_freeFlySpeed * 0.1f * dt * 10f;
+ }
+ if (ZInput.GetButton("JoyButtonX"))
+ {
+ m_freeFlySpeed -= m_freeFlySpeed * 0.1f * dt * 10f;
+ }
+ m_freeFlySpeed = Mathf.Clamp(m_freeFlySpeed, 1f, 1000f);
+ if (ZInput.GetButtonDown("JoyLStick") || ZInput.GetButtonDown("SecondAttack"))
+ {
+ if ((bool)m_freeFlyLockon)
+ {
+ m_freeFlyLockon = null;
+ }
+ else
+ {
+ int mask = LayerMask.GetMask("Default", "static_solid", "terrain", "vehicle", "character", "piece", "character_net", "viewblock");
+ if (Physics.Raycast(base.transform.position, base.transform.forward, out var hitInfo, 10000f, mask))
+ {
+ m_freeFlyLockon = hitInfo.collider.transform;
+ m_freeFlyLockonOffset = m_freeFlyLockon.InverseTransformPoint(base.transform.position);
+ }
+ }
+ }
+ Vector3 vector = Vector3.zero;
+ if (ZInput.GetButton("Left"))
+ {
+ vector -= Vector3.right;
+ }
+ if (ZInput.GetButton("Right"))
+ {
+ vector += Vector3.right;
+ }
+ if (ZInput.GetButton("Forward"))
+ {
+ vector += Vector3.forward;
+ }
+ if (ZInput.GetButton("Backward"))
+ {
+ vector -= Vector3.forward;
+ }
+ if (ZInput.GetButton("Jump"))
+ {
+ vector += Vector3.up;
+ }
+ if (ZInput.GetButton("Crouch"))
+ {
+ vector -= Vector3.up;
+ }
+ vector += Vector3.up * ZInput.GetJoyRTrigger();
+ vector -= Vector3.up * ZInput.GetJoyLTrigger();
+ vector += Vector3.right * ZInput.GetJoyLeftStickX();
+ vector += -Vector3.forward * ZInput.GetJoyLeftStickY();
+ if (ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("Block"))
+ {
+ m_freeFlySavedVel = vector;
+ }
+ float magnitude = m_freeFlySavedVel.magnitude;
+ if (magnitude > 0.001f)
+ {
+ vector += m_freeFlySavedVel;
+ if (vector.magnitude > magnitude)
+ {
+ vector = vector.normalized * magnitude;
+ }
+ }
+ if (vector.magnitude > 1f)
+ {
+ vector.Normalize();
+ }
+ vector = base.transform.TransformVector(vector);
+ vector *= m_freeFlySpeed;
+ if (m_freeFlySmooth <= 0f)
+ {
+ m_freeFlyVel = vector;
+ }
+ else
+ {
+ m_freeFlyVel = Vector3.SmoothDamp(m_freeFlyVel, vector, ref m_freeFlyAcc, m_freeFlySmooth, 99f, dt);
+ }
+ if ((bool)m_freeFlyLockon)
+ {
+ m_freeFlyLockonOffset += m_freeFlyLockon.InverseTransformVector(m_freeFlyVel * dt);
+ base.transform.position = m_freeFlyLockon.TransformPoint(m_freeFlyLockonOffset);
+ }
+ else
+ {
+ base.transform.position = base.transform.position + m_freeFlyVel * dt;
+ }
+ Quaternion quaternion = Quaternion.Euler(0f, m_freeFlyYaw, 0f) * Quaternion.Euler(m_freeFlyPitch, 0f, 0f);
+ if ((bool)m_freeFlyLockon)
+ {
+ quaternion = m_freeFlyLockon.rotation * quaternion;
+ }
+ if (ZInput.GetButtonDown("JoyRStick") || ZInput.GetButtonDown("Attack"))
+ {
+ if ((bool)m_freeFlyTarget)
+ {
+ m_freeFlyTarget = null;
+ }
+ else
+ {
+ int mask2 = LayerMask.GetMask("Default", "static_solid", "terrain", "vehicle", "character", "piece", "character_net", "viewblock");
+ if (Physics.Raycast(base.transform.position, base.transform.forward, out var hitInfo2, 10000f, mask2))
+ {
+ m_freeFlyTarget = hitInfo2.collider.transform;
+ m_freeFlyTargetOffset = m_freeFlyTarget.InverseTransformPoint(hitInfo2.point);
+ }
+ }
+ }
+ if ((bool)m_freeFlyTarget)
+ {
+ quaternion = Quaternion.LookRotation((m_freeFlyTarget.TransformPoint(m_freeFlyTargetOffset) - base.transform.position).normalized, Vector3.up);
+ }
+ if (m_freeFlySmooth <= 0f)
+ {
+ base.transform.rotation = quaternion;
+ return;
+ }
+ Quaternion rotation = Utils.SmoothDamp(base.transform.rotation, quaternion, ref m_freeFlyRef, m_freeFlySmooth, 9999f, dt);
+ base.transform.rotation = rotation;
+ }
+
+ private void UpdateCameraShake(float dt)
+ {
+ m_shakeIntensity -= dt;
+ if (m_shakeIntensity <= 0f)
+ {
+ m_shakeIntensity = 0f;
+ return;
+ }
+ float num = m_shakeIntensity * m_shakeIntensity * m_shakeIntensity;
+ m_shakeTimer += dt * Mathf.Clamp01(m_shakeIntensity) * m_shakeFreq;
+ Quaternion quaternion = Quaternion.Euler(Mathf.Sin(m_shakeTimer) * num * m_shakeMovement, Mathf.Cos(m_shakeTimer * 0.9f) * num * m_shakeMovement, 0f);
+ base.transform.rotation = base.transform.rotation * quaternion;
+ }
+
+ public void AddShake(Vector3 point, float range, float strength, bool continous)
+ {
+ if (!m_cameraShakeEnabled)
+ {
+ return;
+ }
+ float num = Vector3.Distance(point, base.transform.position);
+ if (num > range)
+ {
+ return;
+ }
+ num = Mathf.Max(1f, num);
+ float num2 = 1f - num / range;
+ float num3 = strength * num2;
+ if (!(num3 < m_shakeIntensity))
+ {
+ m_shakeIntensity = num3;
+ if (continous)
+ {
+ m_shakeTimer = Time.time * Mathf.Clamp01(strength) * m_shakeFreq;
+ }
+ else
+ {
+ m_shakeTimer = Time.time * Mathf.Clamp01(m_shakeIntensity) * m_shakeFreq;
+ }
+ }
+ }
+
+ private float RayTest(Vector3 point, Vector3 dir, float maxDist)
+ {
+ if (Physics.SphereCast(point, 0.2f, dir, out var hitInfo, maxDist, m_blockCameraMask))
+ {
+ return hitInfo.distance;
+ }
+ return maxDist;
+ }
+
+ private Vector3 GetCameraBaseOffset(Player player)
+ {
+ if (player.InBed())
+ {
+ return player.GetHeadPoint() - player.transform.position;
+ }
+ if (player.IsAttached() || player.IsSitting())
+ {
+ return player.GetHeadPoint() + Vector3.up * 0.3f - player.transform.position;
+ }
+ return player.m_eye.transform.position - player.transform.position;
+ }
+
+ private void UpdateBaseOffset(Player player, float dt)
+ {
+ Vector3 cameraBaseOffset = GetCameraBaseOffset(player);
+ m_currentBaseOffset = Vector3.SmoothDamp(m_currentBaseOffset, cameraBaseOffset, ref m_offsetBaseVel, 0.5f, 999f, dt);
+ if (Vector3.Distance(m_playerPos, player.transform.position) > 20f)
+ {
+ m_playerPos = player.transform.position;
+ }
+ m_playerPos = Vector3.SmoothDamp(m_playerPos, player.transform.position, ref m_playerVel, m_smoothness, 999f, dt);
+ }
+
+ private Vector3 GetOffsetedEyePos()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ if (localPlayer.GetStandingOnShip() != null || localPlayer.IsAttached())
+ {
+ return localPlayer.transform.position + m_currentBaseOffset + GetCameraOffset(localPlayer);
+ }
+ return m_playerPos + m_currentBaseOffset + GetCameraOffset(localPlayer);
+ }
+ return base.transform.position;
+ }
+
+ private Vector3 GetCameraOffset(Player player)
+ {
+ if (m_distance <= 0f)
+ {
+ return player.m_eye.transform.TransformVector(m_fpsOffset);
+ }
+ if (player.InBed())
+ {
+ return Vector3.zero;
+ }
+ Vector3 vector = (player.UseMeleeCamera() ? m_3rdCombatOffset : m_3rdOffset);
+ return player.m_eye.transform.TransformVector(vector);
+ }
+
+ public void ToggleFreeFly()
+ {
+ m_freeFly = !m_freeFly;
+ }
+
+ public void SetFreeFlySmoothness(float smooth)
+ {
+ m_freeFlySmooth = Mathf.Clamp(smooth, 0f, 1f);
+ }
+
+ public float GetFreeFlySmoothness()
+ {
+ return m_freeFlySmooth;
+ }
+
+ public static bool InFreeFly()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_freeFly;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Gibber.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Gibber.cs
new file mode 100644
index 0000000..1f1c196
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Gibber.cs
@@ -0,0 +1,114 @@
+using System;
+using UnityEngine;
+
+public class Gibber : MonoBehaviour
+{
+ [Serializable]
+ public class GibbData
+ {
+ public GameObject m_object;
+
+ public float m_chanceToSpawn = 1f;
+ }
+
+ public EffectList m_punchEffector = new EffectList();
+
+ public GameObject m_gibHitEffect;
+
+ public GameObject m_gibDestroyEffect;
+
+ public float m_gibHitDestroyChance;
+
+ public GibbData[] m_gibbs = new GibbData[0];
+
+ public float m_minVel = 10f;
+
+ public float m_maxVel = 20f;
+
+ public float m_maxRotVel = 20f;
+
+ public float m_impactDirectionMix = 0.5f;
+
+ public float m_timeout = 5f;
+
+ private bool m_done;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (!m_done)
+ {
+ Explode(base.transform.position, Vector3.zero);
+ }
+ }
+
+ public void Setup(Vector3 hitPoint, Vector3 hitDirection)
+ {
+ Explode(hitPoint, hitDirection);
+ }
+
+ private void DestroyAll()
+ {
+ if ((bool)m_nview)
+ {
+ if (m_nview.GetZDO().m_owner == 0L)
+ {
+ m_nview.ClaimOwnership();
+ }
+ if (m_nview.IsOwner())
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ }
+ else
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+
+ private void CreateBodies()
+ {
+ MeshRenderer[] componentsInChildren = base.gameObject.GetComponentsInChildren<MeshRenderer>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ GameObject gameObject = componentsInChildren[i].gameObject;
+ if (!gameObject.GetComponent<Rigidbody>())
+ {
+ gameObject.AddComponent<BoxCollider>();
+ gameObject.AddComponent<Rigidbody>();
+ }
+ }
+ }
+
+ private void Explode(Vector3 hitPoint, Vector3 hitDirection)
+ {
+ m_done = true;
+ InvokeRepeating("DestroyAll", m_timeout, 1f);
+ Vector3 position = base.transform.position;
+ float t = (((double)hitDirection.magnitude > 0.01) ? m_impactDirectionMix : 0f);
+ CreateBodies();
+ Rigidbody[] componentsInChildren = base.gameObject.GetComponentsInChildren<Rigidbody>();
+ foreach (Rigidbody obj in componentsInChildren)
+ {
+ float num = UnityEngine.Random.Range(m_minVel, m_maxVel);
+ Vector3 vector = Vector3.Lerp(Vector3.Normalize(obj.worldCenterOfMass - position), hitDirection, t);
+ obj.velocity = vector * num;
+ obj.angularVelocity = new Vector3(UnityEngine.Random.Range(0f - m_maxRotVel, m_maxRotVel), UnityEngine.Random.Range(0f - m_maxRotVel, m_maxRotVel), UnityEngine.Random.Range(0f - m_maxRotVel, m_maxRotVel));
+ }
+ GibbData[] gibbs = m_gibbs;
+ foreach (GibbData gibbData in gibbs)
+ {
+ if ((bool)gibbData.m_object && gibbData.m_chanceToSpawn < 1f && UnityEngine.Random.value > gibbData.m_chanceToSpawn)
+ {
+ UnityEngine.Object.Destroy(gibbData.m_object);
+ }
+ }
+ if ((double)hitDirection.magnitude > 0.01)
+ {
+ Quaternion rot = Quaternion.LookRotation(hitDirection);
+ m_punchEffector.Create(hitPoint, rot);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GlobalWind.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GlobalWind.cs
new file mode 100644
index 0000000..c0d50a6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GlobalWind.cs
@@ -0,0 +1,98 @@
+using UnityEngine;
+
+public class GlobalWind : MonoBehaviour
+{
+ public float m_multiplier = 1f;
+
+ public bool m_smoothUpdate;
+
+ public bool m_alignToWindDirection;
+
+ [Header("Particles")]
+ public bool m_particleVelocity = true;
+
+ public bool m_particleForce;
+
+ public bool m_particleEmission;
+
+ public int m_particleEmissionMin;
+
+ public int m_particleEmissionMax = 1;
+
+ [Header("Cloth")]
+ public float m_clothRandomAccelerationFactor = 0.5f;
+
+ public bool m_checkPlayerShelter;
+
+ private ParticleSystem m_ps;
+
+ private Cloth m_cloth;
+
+ private Player m_player;
+
+ private void Start()
+ {
+ if (!(EnvMan.instance == null))
+ {
+ m_ps = GetComponent<ParticleSystem>();
+ m_cloth = GetComponent<Cloth>();
+ if (m_checkPlayerShelter)
+ {
+ m_player = GetComponentInParent<Player>();
+ }
+ if (m_smoothUpdate)
+ {
+ InvokeRepeating("UpdateWind", 0f, 0.01f);
+ return;
+ }
+ InvokeRepeating("UpdateWind", Random.Range(1.5f, 2.5f), 2f);
+ UpdateWind();
+ }
+ }
+
+ private void UpdateWind()
+ {
+ if (m_alignToWindDirection)
+ {
+ Vector3 windDir = EnvMan.instance.GetWindDir();
+ base.transform.rotation = Quaternion.LookRotation(windDir, Vector3.up);
+ }
+ if ((bool)m_ps)
+ {
+ if (!m_ps.emission.enabled)
+ {
+ return;
+ }
+ Vector3 windForce = EnvMan.instance.GetWindForce();
+ if (m_particleVelocity)
+ {
+ ParticleSystem.VelocityOverLifetimeModule velocityOverLifetime = m_ps.velocityOverLifetime;
+ velocityOverLifetime.space = ParticleSystemSimulationSpace.World;
+ velocityOverLifetime.x = windForce.x * m_multiplier;
+ velocityOverLifetime.z = windForce.z * m_multiplier;
+ }
+ if (m_particleForce)
+ {
+ ParticleSystem.ForceOverLifetimeModule forceOverLifetime = m_ps.forceOverLifetime;
+ forceOverLifetime.space = ParticleSystemSimulationSpace.World;
+ forceOverLifetime.x = windForce.x * m_multiplier;
+ forceOverLifetime.z = windForce.z * m_multiplier;
+ }
+ if (m_particleEmission)
+ {
+ ParticleSystem.EmissionModule emission = m_ps.emission;
+ emission.rateOverTimeMultiplier = Mathf.Lerp(m_particleEmissionMin, m_particleEmissionMax, EnvMan.instance.GetWindIntensity());
+ }
+ }
+ if ((bool)m_cloth)
+ {
+ Vector3 vector = EnvMan.instance.GetWindForce();
+ if (m_checkPlayerShelter && m_player != null && m_player.InShelter())
+ {
+ vector = Vector3.zero;
+ }
+ m_cloth.externalAcceleration = vector * m_multiplier;
+ m_cloth.randomAcceleration = vector * m_multiplier * m_clothRandomAccelerationFactor;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Growup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Growup.cs
new file mode 100644
index 0000000..b04c2bf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Growup.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+
+public class Growup : MonoBehaviour
+{
+ public float m_growTime = 60f;
+
+ public GameObject m_grownPrefab;
+
+ private BaseAI m_baseAI;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_baseAI = GetComponent<BaseAI>();
+ m_nview = GetComponent<ZNetView>();
+ InvokeRepeating("GrowUpdate", Random.Range(10f, 15f), 10f);
+ }
+
+ private void GrowUpdate()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && m_baseAI.GetTimeSinceSpawned().TotalSeconds > (double)m_growTime)
+ {
+ Character component = GetComponent<Character>();
+ Character component2 = Object.Instantiate(m_grownPrefab, base.transform.position, base.transform.rotation).GetComponent<Character>();
+ if ((bool)component && (bool)component2)
+ {
+ component2.SetTamed(component.IsTamed());
+ component2.SetLevel(component.GetLevel());
+ }
+ m_nview.Destroy();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GuidePoint.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GuidePoint.cs
new file mode 100644
index 0000000..23ec869
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/GuidePoint.cs
@@ -0,0 +1,28 @@
+using UnityEngine;
+
+public class GuidePoint : MonoBehaviour
+{
+ public Raven.RavenText m_text = new Raven.RavenText();
+
+ public GameObject m_ravenPrefab;
+
+ private void Start()
+ {
+ if (!Raven.IsInstantiated())
+ {
+ Object.Instantiate(m_ravenPrefab, new Vector3(0f, 0f, 0f), Quaternion.identity);
+ }
+ m_text.m_static = true;
+ m_text.m_guidePoint = this;
+ Raven.RegisterStaticText(m_text);
+ }
+
+ private void OnDestroy()
+ {
+ Raven.UnregisterStaticText(m_text);
+ }
+
+ private void OnDrawGizmos()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Heightmap.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Heightmap.cs
new file mode 100644
index 0000000..b498b19
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Heightmap.cs
@@ -0,0 +1,1111 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class Heightmap : MonoBehaviour
+{
+ public enum Biome
+ {
+ None = 0,
+ Meadows = 1,
+ Swamp = 2,
+ Mountain = 4,
+ BlackForest = 8,
+ Plains = 16,
+ AshLands = 32,
+ DeepNorth = 64,
+ Ocean = 256,
+ Mistlands = 512,
+ BiomesMax = 513
+ }
+
+ public enum BiomeArea
+ {
+ Edge = 1,
+ Median,
+ Everything
+ }
+
+ private static float[] tempBiomeWeights = new float[513];
+
+ private static List<Heightmap> tempHmaps = new List<Heightmap>();
+
+ public int m_width = 32;
+
+ public float m_scale = 1f;
+
+ public Material m_material;
+
+ private const float m_levelMaxDelta = 8f;
+
+ private const float m_smoothMaxDelta = 1f;
+
+ public bool m_isDistantLod;
+
+ public bool m_distantLodEditorHax;
+
+ private List<float> m_heights = new List<float>();
+
+ private HeightmapBuilder.HMBuildData m_buildData;
+
+ private Texture2D m_clearedMask;
+
+ private Material m_materialInstance;
+
+ private MeshCollider m_collider;
+
+ private float[] m_oceanDepth = new float[4];
+
+ private Biome[] m_cornerBiomes = new Biome[4]
+ {
+ Biome.Meadows,
+ Biome.Meadows,
+ Biome.Meadows,
+ Biome.Meadows
+ };
+
+ private Bounds m_bounds;
+
+ private BoundingSphere m_boundingSphere;
+
+ private Mesh m_collisionMesh;
+
+ private Mesh m_renderMesh;
+
+ private bool m_dirty;
+
+ private static List<Heightmap> m_heightmaps = new List<Heightmap>();
+
+ private static List<Vector3> m_tempVertises = new List<Vector3>();
+
+ private static List<Vector2> m_tempUVs = new List<Vector2>();
+
+ private static List<int> m_tempIndices = new List<int>();
+
+ private static List<Color32> m_tempColors = new List<Color32>();
+
+ private void Awake()
+ {
+ if (!m_isDistantLod)
+ {
+ m_heightmaps.Add(this);
+ }
+ m_collider = GetComponent<MeshCollider>();
+ }
+
+ private void OnDestroy()
+ {
+ if (!m_isDistantLod)
+ {
+ m_heightmaps.Remove(this);
+ }
+ if ((bool)m_materialInstance)
+ {
+ Object.DestroyImmediate(m_materialInstance);
+ }
+ }
+
+ private void OnEnable()
+ {
+ if (!m_isDistantLod || !Application.isPlaying || m_distantLodEditorHax)
+ {
+ Regenerate();
+ }
+ }
+
+ private void Update()
+ {
+ Render();
+ }
+
+ private void Render()
+ {
+ if (IsVisible())
+ {
+ if (m_dirty)
+ {
+ m_dirty = false;
+ m_materialInstance.SetTexture("_ClearedMaskTex", m_clearedMask);
+ RebuildRenderMesh();
+ }
+ if ((bool)m_renderMesh)
+ {
+ Matrix4x4 matrix = Matrix4x4.TRS(base.transform.position, Quaternion.identity, Vector3.one);
+ Graphics.DrawMesh(m_renderMesh, matrix, m_materialInstance, base.gameObject.layer);
+ }
+ }
+ }
+
+ private bool IsVisible()
+ {
+ if (!Utils.InsideMainCamera(m_boundingSphere))
+ {
+ return false;
+ }
+ if (!Utils.InsideMainCamera(m_bounds))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public static void ForceGenerateAll()
+ {
+ foreach (Heightmap heightmap in m_heightmaps)
+ {
+ if (heightmap.HaveQueuedRebuild())
+ {
+ ZLog.Log("Force generaeting hmap " + heightmap.transform.position);
+ heightmap.Regenerate();
+ }
+ }
+ }
+
+ public void Poke(bool delayed)
+ {
+ if (delayed)
+ {
+ if (HaveQueuedRebuild())
+ {
+ CancelInvoke("Regenerate");
+ }
+ InvokeRepeating("Regenerate", 0.1f, 0f);
+ }
+ else
+ {
+ Regenerate();
+ }
+ }
+
+ public bool HaveQueuedRebuild()
+ {
+ return IsInvoking("Regenerate");
+ }
+
+ public void Regenerate()
+ {
+ if (HaveQueuedRebuild())
+ {
+ CancelInvoke("Regenerate");
+ }
+ Generate();
+ RebuildCollisionMesh();
+ UpdateCornerDepths();
+ m_dirty = true;
+ }
+
+ private void UpdateCornerDepths()
+ {
+ float num = (ZoneSystem.instance ? ZoneSystem.instance.m_waterLevel : 30f);
+ m_oceanDepth[0] = GetHeight(0, m_width);
+ m_oceanDepth[1] = GetHeight(m_width, m_width);
+ m_oceanDepth[2] = GetHeight(m_width, 0);
+ m_oceanDepth[3] = GetHeight(0, 0);
+ m_oceanDepth[0] = Mathf.Max(0f, num - m_oceanDepth[0]);
+ m_oceanDepth[1] = Mathf.Max(0f, num - m_oceanDepth[1]);
+ m_oceanDepth[2] = Mathf.Max(0f, num - m_oceanDepth[2]);
+ m_oceanDepth[3] = Mathf.Max(0f, num - m_oceanDepth[3]);
+ m_materialInstance.SetFloatArray("_depth", m_oceanDepth);
+ }
+
+ public float[] GetOceanDepth()
+ {
+ return m_oceanDepth;
+ }
+
+ public static float GetOceanDepthAll(Vector3 worldPos)
+ {
+ Heightmap heightmap = FindHeightmap(worldPos);
+ if ((bool)heightmap)
+ {
+ return heightmap.GetOceanDepth(worldPos);
+ }
+ return 0f;
+ }
+
+ public float GetOceanDepth(Vector3 worldPos)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float t = (float)x / (float)m_width;
+ float t2 = (float)y / (float)m_width;
+ float a = Mathf.Lerp(m_oceanDepth[3], m_oceanDepth[2], t);
+ float b = Mathf.Lerp(m_oceanDepth[0], m_oceanDepth[1], t);
+ return Mathf.Lerp(a, b, t2);
+ }
+
+ private void Initialize()
+ {
+ int num = m_width + 1;
+ int num2 = num * num;
+ if (m_heights.Count != num2)
+ {
+ m_heights.Clear();
+ for (int i = 0; i < num2; i++)
+ {
+ m_heights.Add(0f);
+ }
+ m_clearedMask = new Texture2D(m_width, m_width);
+ m_clearedMask.wrapMode = TextureWrapMode.Clamp;
+ m_materialInstance = new Material(m_material);
+ m_materialInstance.SetTexture("_ClearedMaskTex", m_clearedMask);
+ }
+ }
+
+ private void Generate()
+ {
+ Initialize();
+ int num = m_width + 1;
+ int num2 = num * num;
+ Vector3 position = base.transform.position;
+ if (m_buildData == null || m_buildData.m_baseHeights.Count != num2 || m_buildData.m_center != position || m_buildData.m_scale != m_scale || m_buildData.m_worldGen != WorldGenerator.instance)
+ {
+ m_buildData = HeightmapBuilder.instance.RequestTerrainSync(position, m_width, m_scale, m_isDistantLod, WorldGenerator.instance);
+ m_cornerBiomes = m_buildData.m_cornerBiomes;
+ }
+ for (int i = 0; i < num2; i++)
+ {
+ m_heights[i] = m_buildData.m_baseHeights[i];
+ }
+ Color[] pixels = new Color[m_clearedMask.width * m_clearedMask.height];
+ m_clearedMask.SetPixels(pixels);
+ ApplyModifiers();
+ }
+
+ private float Distance(float x, float y, float rx, float ry)
+ {
+ float num = x - rx;
+ float num2 = y - ry;
+ float num3 = Mathf.Sqrt(num * num + num2 * num2);
+ float num4 = 1.414f - num3;
+ return num4 * num4 * num4;
+ }
+
+ public List<Biome> GetBiomes()
+ {
+ List<Biome> list = new List<Biome>();
+ Biome[] cornerBiomes = m_cornerBiomes;
+ foreach (Biome item in cornerBiomes)
+ {
+ if (!list.Contains(item))
+ {
+ list.Add(item);
+ }
+ }
+ return list;
+ }
+
+ public bool HaveBiome(Biome biome)
+ {
+ if ((m_cornerBiomes[0] & biome) == 0 && (m_cornerBiomes[1] & biome) == 0 && (m_cornerBiomes[2] & biome) == 0)
+ {
+ return (m_cornerBiomes[3] & biome) != 0;
+ }
+ return true;
+ }
+
+ public Biome GetBiome(Vector3 point)
+ {
+ if (m_isDistantLod)
+ {
+ return WorldGenerator.instance.GetBiome(point.x, point.z);
+ }
+ if (m_cornerBiomes[0] == m_cornerBiomes[1] && m_cornerBiomes[0] == m_cornerBiomes[2] && m_cornerBiomes[0] == m_cornerBiomes[3])
+ {
+ return m_cornerBiomes[0];
+ }
+ float x = point.x;
+ float y = point.z;
+ WorldToNormalizedHM(point, out x, out y);
+ for (int i = 1; i < tempBiomeWeights.Length; i++)
+ {
+ tempBiomeWeights[i] = 0f;
+ }
+ tempBiomeWeights[(int)m_cornerBiomes[0]] += Distance(x, y, 0f, 0f);
+ tempBiomeWeights[(int)m_cornerBiomes[1]] += Distance(x, y, 1f, 0f);
+ tempBiomeWeights[(int)m_cornerBiomes[2]] += Distance(x, y, 0f, 1f);
+ tempBiomeWeights[(int)m_cornerBiomes[3]] += Distance(x, y, 1f, 1f);
+ int result = 0;
+ float num = -99999f;
+ for (int j = 1; j < tempBiomeWeights.Length; j++)
+ {
+ if (tempBiomeWeights[j] > num)
+ {
+ result = j;
+ num = tempBiomeWeights[j];
+ }
+ }
+ return (Biome)result;
+ }
+
+ public BiomeArea GetBiomeArea()
+ {
+ if (IsBiomeEdge())
+ {
+ return BiomeArea.Edge;
+ }
+ return BiomeArea.Median;
+ }
+
+ public bool IsBiomeEdge()
+ {
+ if (m_cornerBiomes[0] == m_cornerBiomes[1] && m_cornerBiomes[0] == m_cornerBiomes[2] && m_cornerBiomes[0] == m_cornerBiomes[3])
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void ApplyModifiers()
+ {
+ List<TerrainModifier> allInstances = TerrainModifier.GetAllInstances();
+ float[] array = null;
+ float[] levelOnly = null;
+ foreach (TerrainModifier item in allInstances)
+ {
+ if (item.enabled && TerrainVSModifier(item))
+ {
+ if (item.m_playerModifiction && array == null)
+ {
+ array = m_heights.ToArray();
+ levelOnly = m_heights.ToArray();
+ }
+ ApplyModifier(item, array, levelOnly);
+ }
+ }
+ m_clearedMask.Apply();
+ }
+
+ private void ApplyModifier(TerrainModifier modifier, float[] baseHeights, float[] levelOnly)
+ {
+ if (modifier.m_level)
+ {
+ LevelTerrain(modifier.transform.position + Vector3.up * modifier.m_levelOffset, modifier.m_levelRadius, modifier.m_square, baseHeights, levelOnly, modifier.m_playerModifiction);
+ }
+ if (modifier.m_smooth)
+ {
+ SmoothTerrain2(modifier.transform.position + Vector3.up * modifier.m_levelOffset, modifier.m_smoothRadius, modifier.m_square, levelOnly, modifier.m_smoothPower, modifier.m_playerModifiction);
+ }
+ if (modifier.m_paintCleared)
+ {
+ PaintCleared(modifier.transform.position, modifier.m_paintRadius, modifier.m_paintType, modifier.m_paintHeightCheck, apply: false);
+ }
+ }
+
+ public bool TerrainVSModifier(TerrainModifier modifier)
+ {
+ Vector3 position = modifier.transform.position;
+ float num = modifier.GetRadius() + 4f;
+ Vector3 position2 = base.transform.position;
+ float num2 = (float)m_width * m_scale * 0.5f;
+ if (position.x + num < position2.x - num2)
+ {
+ return false;
+ }
+ if (position.x - num > position2.x + num2)
+ {
+ return false;
+ }
+ if (position.z + num < position2.z - num2)
+ {
+ return false;
+ }
+ if (position.z - num > position2.z + num2)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private Vector3 CalcNormal2(List<Vector3> vertises, int x, int y)
+ {
+ int num = m_width + 1;
+ Vector3 vector = vertises[y * num + x];
+ Vector3 rhs;
+ if (x != m_width)
+ {
+ rhs = ((x != 0) ? (vertises[y * num + x + 1] - vertises[y * num + x - 1]) : (vertises[y * num + x + 1] - vector));
+ }
+ else
+ {
+ Vector3 vector2 = vertises[y * num + x - 1];
+ rhs = vector - vector2;
+ }
+ Vector3 lhs;
+ if (y != m_width)
+ {
+ lhs = ((y != 0) ? (vertises[(y + 1) * num + x] - vertises[(y - 1) * num + x]) : (CalcVertex(x, y + 1) - vector));
+ }
+ else
+ {
+ Vector3 vector3 = CalcVertex(x, y - 1);
+ lhs = vector - vector3;
+ }
+ Vector3 result = Vector3.Cross(lhs, rhs);
+ result.Normalize();
+ return result;
+ }
+
+ private Vector3 CalcNormal(int x, int y)
+ {
+ Vector3 vector = CalcVertex(x, y);
+ Vector3 rhs;
+ if (x == m_width)
+ {
+ Vector3 vector2 = CalcVertex(x - 1, y);
+ rhs = vector - vector2;
+ }
+ else
+ {
+ rhs = CalcVertex(x + 1, y) - vector;
+ }
+ Vector3 lhs;
+ if (y == m_width)
+ {
+ Vector3 vector3 = CalcVertex(x, y - 1);
+ lhs = vector - vector3;
+ }
+ else
+ {
+ lhs = CalcVertex(x, y + 1) - vector;
+ }
+ return Vector3.Cross(lhs, rhs).normalized;
+ }
+
+ private Vector3 CalcVertex(int x, int y)
+ {
+ int num = m_width + 1;
+ return new Vector3((float)m_width * m_scale * -0.5f, 0f, (float)m_width * m_scale * -0.5f) + new Vector3(y: m_heights[y * num + x], x: (float)x * m_scale, z: (float)y * m_scale);
+ }
+
+ private Color GetBiomeColor(float ix, float iy)
+ {
+ if (m_cornerBiomes[0] == m_cornerBiomes[1] && m_cornerBiomes[0] == m_cornerBiomes[2] && m_cornerBiomes[0] == m_cornerBiomes[3])
+ {
+ return GetBiomeColor(m_cornerBiomes[0]);
+ }
+ Color32 biomeColor = GetBiomeColor(m_cornerBiomes[0]);
+ Color32 biomeColor2 = GetBiomeColor(m_cornerBiomes[1]);
+ Color32 biomeColor3 = GetBiomeColor(m_cornerBiomes[2]);
+ Color32 biomeColor4 = GetBiomeColor(m_cornerBiomes[3]);
+ Color32 a = Color32.Lerp(biomeColor, biomeColor2, ix);
+ Color32 b = Color32.Lerp(biomeColor3, biomeColor4, ix);
+ return Color32.Lerp(a, b, iy);
+ }
+
+ public static Color32 GetBiomeColor(Biome biome)
+ {
+ return biome switch
+ {
+ Biome.Swamp => new Color32(byte.MaxValue, 0, 0, 0),
+ Biome.Mountain => new Color32(0, byte.MaxValue, 0, 0),
+ Biome.BlackForest => new Color32(0, 0, byte.MaxValue, 0),
+ Biome.Plains => new Color32(0, 0, 0, byte.MaxValue),
+ Biome.AshLands => new Color32(byte.MaxValue, 0, 0, byte.MaxValue),
+ Biome.DeepNorth => new Color32(0, byte.MaxValue, 0, 0),
+ Biome.Mistlands => new Color32(0, 0, byte.MaxValue, byte.MaxValue),
+ _ => new Color32(0, 0, 0, 0),
+ };
+ }
+
+ private void RebuildCollisionMesh()
+ {
+ if (m_collisionMesh == null)
+ {
+ m_collisionMesh = new Mesh();
+ }
+ int num = m_width + 1;
+ float num2 = -999999f;
+ float num3 = 999999f;
+ m_tempVertises.Clear();
+ for (int i = 0; i < num; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ Vector3 item = CalcVertex(j, i);
+ m_tempVertises.Add(item);
+ if (item.y > num2)
+ {
+ num2 = item.y;
+ }
+ if (item.y < num3)
+ {
+ num3 = item.y;
+ }
+ }
+ }
+ m_collisionMesh.SetVertices(m_tempVertises);
+ int num4 = (num - 1) * (num - 1) * 6;
+ if (m_collisionMesh.GetIndexCount(0) != num4)
+ {
+ m_tempIndices.Clear();
+ for (int k = 0; k < num - 1; k++)
+ {
+ for (int l = 0; l < num - 1; l++)
+ {
+ int item2 = k * num + l;
+ int item3 = k * num + l + 1;
+ int item4 = (k + 1) * num + l + 1;
+ int item5 = (k + 1) * num + l;
+ m_tempIndices.Add(item2);
+ m_tempIndices.Add(item5);
+ m_tempIndices.Add(item3);
+ m_tempIndices.Add(item3);
+ m_tempIndices.Add(item5);
+ m_tempIndices.Add(item4);
+ }
+ }
+ m_collisionMesh.SetIndices(m_tempIndices.ToArray(), MeshTopology.Triangles, 0);
+ }
+ if ((bool)m_collider)
+ {
+ m_collider.sharedMesh = m_collisionMesh;
+ }
+ float num5 = (float)m_width * m_scale * 0.5f;
+ m_bounds.SetMinMax(base.transform.position + new Vector3(0f - num5, num3, 0f - num5), base.transform.position + new Vector3(num5, num2, num5));
+ m_boundingSphere.position = m_bounds.center;
+ m_boundingSphere.radius = Vector3.Distance(m_boundingSphere.position, m_bounds.max);
+ }
+
+ private void RebuildRenderMesh()
+ {
+ if (m_renderMesh == null)
+ {
+ m_renderMesh = new Mesh();
+ }
+ WorldGenerator instance = WorldGenerator.instance;
+ int num = m_width + 1;
+ Vector3 vector = base.transform.position + new Vector3((float)m_width * m_scale * -0.5f, 0f, (float)m_width * m_scale * -0.5f);
+ m_tempVertises.Clear();
+ m_tempUVs.Clear();
+ m_tempIndices.Clear();
+ m_tempColors.Clear();
+ for (int i = 0; i < num; i++)
+ {
+ float iy = Mathf.SmoothStep(0f, 1f, (float)i / (float)m_width);
+ for (int j = 0; j < num; j++)
+ {
+ float ix = Mathf.SmoothStep(0f, 1f, (float)j / (float)m_width);
+ m_tempUVs.Add(new Vector2((float)j / (float)m_width, (float)i / (float)m_width));
+ if (m_isDistantLod)
+ {
+ float wx = vector.x + (float)j * m_scale;
+ float wy = vector.z + (float)i * m_scale;
+ Biome biome = instance.GetBiome(wx, wy);
+ m_tempColors.Add(GetBiomeColor(biome));
+ }
+ else
+ {
+ m_tempColors.Add(GetBiomeColor(ix, iy));
+ }
+ }
+ }
+ m_collisionMesh.GetVertices(m_tempVertises);
+ m_collisionMesh.GetIndices(m_tempIndices, 0);
+ m_renderMesh.Clear();
+ m_renderMesh.SetVertices(m_tempVertises);
+ m_renderMesh.SetColors(m_tempColors);
+ m_renderMesh.SetUVs(0, m_tempUVs);
+ m_renderMesh.SetIndices(m_tempIndices.ToArray(), MeshTopology.Triangles, 0, calculateBounds: true);
+ m_renderMesh.RecalculateNormals();
+ m_renderMesh.RecalculateTangents();
+ }
+
+ private void SmoothTerrain2(Vector3 worldPos, float radius, bool square, float[] levelOnlyHeights, float power, bool playerModifiction)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float b = worldPos.y - base.transform.position.y;
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ Vector2 a = new Vector2(x, y);
+ int num3 = m_width + 1;
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ float num4 = Vector2.Distance(a, new Vector2(j, i));
+ if (num4 > num)
+ {
+ continue;
+ }
+ float num5 = num4 / num;
+ if (j >= 0 && i >= 0 && j < num3 && i < num3)
+ {
+ num5 = ((power != 3f) ? Mathf.Pow(num5, power) : (num5 * num5 * num5));
+ float height = GetHeight(j, i);
+ float t = 1f - num5;
+ float num6 = Mathf.Lerp(height, b, t);
+ if (playerModifiction)
+ {
+ float num7 = levelOnlyHeights[i * num3 + j];
+ num6 = Mathf.Clamp(num6, num7 - 1f, num7 + 1f);
+ }
+ SetHeight(j, i, num6);
+ }
+ }
+ }
+ }
+
+ private bool AtMaxWorldLevelDepth(Vector3 worldPos)
+ {
+ GetWorldHeight(worldPos, out var height);
+ GetWorldBaseHeight(worldPos, out var height2);
+ return Mathf.Max(0f - (height - height2), 0f) >= 7.95f;
+ }
+
+ private bool GetWorldBaseHeight(Vector3 worldPos, out float height)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ int num = m_width + 1;
+ if (x < 0 || y < 0 || x >= num || y >= num)
+ {
+ height = 0f;
+ return false;
+ }
+ height = m_buildData.m_baseHeights[y * num + x] + base.transform.position.y;
+ return true;
+ }
+
+ private bool GetWorldHeight(Vector3 worldPos, out float height)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ int num = m_width + 1;
+ if (x < 0 || y < 0 || x >= num || y >= num)
+ {
+ height = 0f;
+ return false;
+ }
+ height = m_heights[y * num + x] + base.transform.position.y;
+ return true;
+ }
+
+ private bool GetAverageWorldHeight(Vector3 worldPos, float radius, out float height)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ Vector2 a = new Vector2(x, y);
+ int num3 = m_width + 1;
+ float num4 = 0f;
+ int num5 = 0;
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ if (!(Vector2.Distance(a, new Vector2(j, i)) > num) && j >= 0 && i >= 0 && j < num3 && i < num3)
+ {
+ num4 += GetHeight(j, i);
+ num5++;
+ }
+ }
+ }
+ if (num5 == 0)
+ {
+ height = 0f;
+ return false;
+ }
+ height = num4 / (float)num5 + base.transform.position.y;
+ return true;
+ }
+
+ private bool GetMinWorldHeight(Vector3 worldPos, float radius, out float height)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ Vector2 a = new Vector2(x, y);
+ int num3 = m_width + 1;
+ height = 99999f;
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ if (!(Vector2.Distance(a, new Vector2(j, i)) > num) && j >= 0 && i >= 0 && j < num3 && i < num3)
+ {
+ float height2 = GetHeight(j, i);
+ if (height2 < height)
+ {
+ height = height2;
+ }
+ }
+ }
+ }
+ return height != 99999f;
+ }
+
+ private bool GetMaxWorldHeight(Vector3 worldPos, float radius, out float height)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ Vector2 a = new Vector2(x, y);
+ int num3 = m_width + 1;
+ height = -99999f;
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ if (!(Vector2.Distance(a, new Vector2(j, i)) > num) && j >= 0 && i >= 0 && j < num3 && i < num3)
+ {
+ float height2 = GetHeight(j, i);
+ if (height2 > height)
+ {
+ height = height2;
+ }
+ }
+ }
+ }
+ return height != -99999f;
+ }
+
+ public static bool AtMaxLevelDepth(Vector3 worldPos)
+ {
+ Heightmap heightmap = FindHeightmap(worldPos);
+ if ((bool)heightmap)
+ {
+ return heightmap.AtMaxWorldLevelDepth(worldPos);
+ }
+ return false;
+ }
+
+ public static bool GetHeight(Vector3 worldPos, out float height)
+ {
+ Heightmap heightmap = FindHeightmap(worldPos);
+ if ((bool)heightmap && heightmap.GetWorldHeight(worldPos, out height))
+ {
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ public static bool GetAverageHeight(Vector3 worldPos, float radius, out float height)
+ {
+ List<Heightmap> list = new List<Heightmap>();
+ FindHeightmap(worldPos, radius, list);
+ float num = 0f;
+ int num2 = 0;
+ foreach (Heightmap item in list)
+ {
+ if (item.GetAverageWorldHeight(worldPos, radius, out var height2))
+ {
+ num += height2;
+ num2++;
+ }
+ }
+ if (num2 > 0)
+ {
+ height = num / (float)num2;
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ private void SmoothTerrain(Vector3 worldPos, float radius, bool square, float intensity)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ Vector2 a = new Vector2(x, y);
+ List<KeyValuePair<Vector2i, float>> list = new List<KeyValuePair<Vector2i, float>>();
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ if ((square || !(Vector2.Distance(a, new Vector2(j, i)) > num)) && j != 0 && i != 0 && j != m_width && i != m_width)
+ {
+ list.Add(new KeyValuePair<Vector2i, float>(new Vector2i(j, i), GetAvgHeight(j, i, 1)));
+ }
+ }
+ }
+ foreach (KeyValuePair<Vector2i, float> item in list)
+ {
+ float h = Mathf.Lerp(GetHeight(item.Key.x, item.Key.y), item.Value, intensity);
+ SetHeight(item.Key.x, item.Key.y, h);
+ }
+ }
+
+ private float GetAvgHeight(int cx, int cy, int w)
+ {
+ int num = m_width + 1;
+ float num2 = 0f;
+ int num3 = 0;
+ for (int i = cy - w; i <= cy + w; i++)
+ {
+ for (int j = cx - w; j <= cx + w; j++)
+ {
+ if (j >= 0 && i >= 0 && j < num && i < num)
+ {
+ num2 += GetHeight(j, i);
+ num3++;
+ }
+ }
+ }
+ if (num3 == 0)
+ {
+ return 0f;
+ }
+ return num2 / (float)num3;
+ }
+
+ private float GroundHeight(Vector3 point)
+ {
+ Ray ray = new Ray(point + Vector3.up * 100f, Vector3.down);
+ if (m_collider.Raycast(ray, out var hitInfo, 300f))
+ {
+ return hitInfo.point.y;
+ }
+ return -10000f;
+ }
+
+ private void FindObjectsToMove(Vector3 worldPos, float area, List<Rigidbody> objects)
+ {
+ if (m_collider == null)
+ {
+ return;
+ }
+ Collider[] array = Physics.OverlapBox(worldPos, new Vector3(area / 2f, 500f, area / 2f));
+ foreach (Collider collider in array)
+ {
+ if (!(collider == m_collider) && (bool)collider.attachedRigidbody)
+ {
+ Rigidbody attachedRigidbody = collider.attachedRigidbody;
+ ZNetView component = attachedRigidbody.GetComponent<ZNetView>();
+ if (!component || component.IsOwner())
+ {
+ objects.Add(attachedRigidbody);
+ }
+ }
+ }
+ }
+
+ private void PaintCleared(Vector3 worldPos, float radius, TerrainModifier.PaintType paintType, bool heightCheck, bool apply)
+ {
+ worldPos.x -= 0.5f;
+ worldPos.z -= 0.5f;
+ float num = worldPos.y - base.transform.position.y;
+ WorldToVertex(worldPos, out var x, out var y);
+ float num2 = radius / m_scale;
+ int num3 = Mathf.CeilToInt(num2);
+ Vector2 a = new Vector2(x, y);
+ for (int i = y - num3; i <= y + num3; i++)
+ {
+ for (int j = x - num3; j <= x + num3; j++)
+ {
+ float num4 = Vector2.Distance(a, new Vector2(j, i));
+ if (j >= 0 && i >= 0 && j < m_clearedMask.width && i < m_clearedMask.height && (!heightCheck || !(GetHeight(j, i) > num)))
+ {
+ float f = 1f - Mathf.Clamp01(num4 / num2);
+ f = Mathf.Pow(f, 0.1f);
+ Color color = m_clearedMask.GetPixel(j, i);
+ switch (paintType)
+ {
+ case TerrainModifier.PaintType.Dirt:
+ color = Color.Lerp(color, Color.red, f);
+ break;
+ case TerrainModifier.PaintType.Cultivate:
+ color = Color.Lerp(color, Color.green, f);
+ break;
+ case TerrainModifier.PaintType.Paved:
+ color = Color.Lerp(color, Color.blue, f);
+ break;
+ case TerrainModifier.PaintType.Reset:
+ color = Color.Lerp(color, Color.black, f);
+ break;
+ }
+ m_clearedMask.SetPixel(j, i, color);
+ }
+ }
+ }
+ if (apply)
+ {
+ m_clearedMask.Apply();
+ }
+ }
+
+ public bool IsCleared(Vector3 worldPos)
+ {
+ worldPos.x -= 0.5f;
+ worldPos.z -= 0.5f;
+ WorldToVertex(worldPos, out var x, out var y);
+ Color pixel = m_clearedMask.GetPixel(x, y);
+ if (!(pixel.r > 0.5f) && !(pixel.g > 0.5f))
+ {
+ return pixel.b > 0.5f;
+ }
+ return true;
+ }
+
+ public bool IsCultivated(Vector3 worldPos)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ return m_clearedMask.GetPixel(x, y).g > 0.5f;
+ }
+
+ private void WorldToVertex(Vector3 worldPos, out int x, out int y)
+ {
+ Vector3 vector = worldPos - base.transform.position;
+ x = Mathf.FloorToInt(vector.x / m_scale + 0.5f) + m_width / 2;
+ y = Mathf.FloorToInt(vector.z / m_scale + 0.5f) + m_width / 2;
+ }
+
+ private void WorldToNormalizedHM(Vector3 worldPos, out float x, out float y)
+ {
+ float num = (float)m_width * m_scale;
+ Vector3 vector = worldPos - base.transform.position;
+ x = vector.x / num + 0.5f;
+ y = vector.z / num + 0.5f;
+ }
+
+ private void LevelTerrain(Vector3 worldPos, float radius, bool square, float[] baseHeights, float[] levelOnly, bool playerModifiction)
+ {
+ WorldToVertex(worldPos, out var x, out var y);
+ Vector3 vector = worldPos - base.transform.position;
+ float num = radius / m_scale;
+ int num2 = Mathf.CeilToInt(num);
+ int num3 = m_width + 1;
+ Vector2 a = new Vector2(x, y);
+ for (int i = y - num2; i <= y + num2; i++)
+ {
+ for (int j = x - num2; j <= x + num2; j++)
+ {
+ if ((square || !(Vector2.Distance(a, new Vector2(j, i)) > num)) && j >= 0 && i >= 0 && j < num3 && i < num3)
+ {
+ float num4 = vector.y;
+ if (playerModifiction)
+ {
+ float num5 = baseHeights[i * num3 + j];
+ num4 = (levelOnly[i * num3 + j] = Mathf.Clamp(num4, num5 - 8f, num5 + 8f));
+ }
+ SetHeight(j, i, num4);
+ }
+ }
+ }
+ }
+
+ private float GetHeight(int x, int y)
+ {
+ int num = m_width + 1;
+ if (x < 0 || y < 0 || x >= num || y >= num)
+ {
+ return 0f;
+ }
+ return m_heights[y * num + x];
+ }
+
+ private float GetBaseHeight(int x, int y)
+ {
+ int num = m_width + 1;
+ if (x < 0 || y < 0 || x >= num || y >= num)
+ {
+ return 0f;
+ }
+ return m_buildData.m_baseHeights[y * num + x];
+ }
+
+ private void SetHeight(int x, int y, float h)
+ {
+ int num = m_width + 1;
+ if (x >= 0 && y >= 0 && x < num && y < num)
+ {
+ m_heights[y * num + x] = h;
+ }
+ }
+
+ public bool IsPointInside(Vector3 point, float radius = 0f)
+ {
+ float num = (float)m_width * m_scale * 0.5f;
+ Vector3 position = base.transform.position;
+ if (point.x + radius >= position.x - num && point.x - radius <= position.x + num && point.z + radius >= position.z - num && point.z - radius <= position.z + num)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public static List<Heightmap> GetAllHeightmaps()
+ {
+ return m_heightmaps;
+ }
+
+ public static Heightmap FindHeightmap(Vector3 point)
+ {
+ foreach (Heightmap heightmap in m_heightmaps)
+ {
+ if (heightmap.IsPointInside(point))
+ {
+ return heightmap;
+ }
+ }
+ return null;
+ }
+
+ public static void FindHeightmap(Vector3 point, float radius, List<Heightmap> heightmaps)
+ {
+ foreach (Heightmap heightmap in m_heightmaps)
+ {
+ if (heightmap.IsPointInside(point, radius))
+ {
+ heightmaps.Add(heightmap);
+ }
+ }
+ }
+
+ public static Biome FindBiome(Vector3 point)
+ {
+ Heightmap heightmap = FindHeightmap(point);
+ if ((bool)heightmap)
+ {
+ return heightmap.GetBiome(point);
+ }
+ return Biome.None;
+ }
+
+ public static bool HaveQueuedRebuild(Vector3 point, float radius)
+ {
+ tempHmaps.Clear();
+ FindHeightmap(point, radius, tempHmaps);
+ foreach (Heightmap tempHmap in tempHmaps)
+ {
+ if (tempHmap.HaveQueuedRebuild())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Biome FindBiomeClutter(Vector3 point)
+ {
+ if ((bool)ZoneSystem.instance && !ZoneSystem.instance.IsZoneLoaded(point))
+ {
+ return Biome.None;
+ }
+ Heightmap heightmap = FindHeightmap(point);
+ if ((bool)heightmap)
+ {
+ return heightmap.GetBiome(point);
+ }
+ return Biome.None;
+ }
+
+ public void Clear()
+ {
+ m_heights.Clear();
+ m_clearedMask = null;
+ m_materialInstance = null;
+ m_buildData = null;
+ if ((bool)m_collisionMesh)
+ {
+ m_collisionMesh.Clear();
+ }
+ if ((bool)m_renderMesh)
+ {
+ m_renderMesh.Clear();
+ }
+ if ((bool)m_collider)
+ {
+ m_collider.sharedMesh = null;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HeightmapBuilder.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HeightmapBuilder.cs
new file mode 100644
index 0000000..6fab0cc
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HeightmapBuilder.cs
@@ -0,0 +1,273 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using UnityEngine;
+
+public class HeightmapBuilder
+{
+ public class HMBuildData
+ {
+ public Vector3 m_center;
+
+ public int m_width;
+
+ public float m_scale;
+
+ public bool m_distantLod;
+
+ public bool m_menu;
+
+ public WorldGenerator m_worldGen;
+
+ public Heightmap.Biome[] m_cornerBiomes;
+
+ public List<float> m_baseHeights;
+
+ public HMBuildData(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen)
+ {
+ m_center = center;
+ m_width = width;
+ m_scale = scale;
+ m_distantLod = distantLod;
+ m_worldGen = worldGen;
+ }
+
+ public bool IsEqual(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen)
+ {
+ if (m_center == center && m_width == width && m_scale == scale && m_distantLod == distantLod)
+ {
+ return m_worldGen == worldGen;
+ }
+ return false;
+ }
+ }
+
+ private static HeightmapBuilder m_instance;
+
+ private const int m_maxReadyQueue = 16;
+
+ private List<HMBuildData> m_toBuild = new List<HMBuildData>();
+
+ private List<HMBuildData> m_ready = new List<HMBuildData>();
+
+ private Thread m_builder;
+
+ private Mutex m_lock = new Mutex();
+
+ private bool m_stop;
+
+ public static HeightmapBuilder instance
+ {
+ get
+ {
+ if (m_instance == null)
+ {
+ m_instance = new HeightmapBuilder();
+ }
+ return m_instance;
+ }
+ }
+
+ public HeightmapBuilder()
+ {
+ m_instance = this;
+ m_builder = new Thread(BuildThread);
+ m_builder.Start();
+ }
+
+ public void Dispose()
+ {
+ if (m_builder != null)
+ {
+ ZLog.Log("Stoping build thread");
+ m_lock.WaitOne();
+ m_stop = true;
+ m_builder.Abort();
+ m_lock.ReleaseMutex();
+ m_builder = null;
+ }
+ if (m_lock != null)
+ {
+ m_lock.Close();
+ m_lock = null;
+ }
+ }
+
+ private void BuildThread()
+ {
+ ZLog.Log("Builder started");
+ while (!m_stop)
+ {
+ m_lock.WaitOne();
+ bool num = m_toBuild.Count > 0;
+ m_lock.ReleaseMutex();
+ if (num)
+ {
+ m_lock.WaitOne();
+ HMBuildData hMBuildData = m_toBuild[0];
+ m_lock.ReleaseMutex();
+ new Stopwatch().Start();
+ Build(hMBuildData);
+ m_lock.WaitOne();
+ m_toBuild.Remove(hMBuildData);
+ m_ready.Add(hMBuildData);
+ while (m_ready.Count > 16)
+ {
+ m_ready.RemoveAt(0);
+ }
+ m_lock.ReleaseMutex();
+ }
+ Thread.Sleep(10);
+ }
+ }
+
+ private void Build(HMBuildData data)
+ {
+ int num = data.m_width + 1;
+ int num2 = num * num;
+ Vector3 vector = data.m_center + new Vector3((float)data.m_width * data.m_scale * -0.5f, 0f, (float)data.m_width * data.m_scale * -0.5f);
+ WorldGenerator worldGen = data.m_worldGen;
+ data.m_cornerBiomes = new Heightmap.Biome[4];
+ data.m_cornerBiomes[0] = worldGen.GetBiome(vector.x, vector.z);
+ data.m_cornerBiomes[1] = worldGen.GetBiome(vector.x + (float)data.m_width * data.m_scale, vector.z);
+ data.m_cornerBiomes[2] = worldGen.GetBiome(vector.x, vector.z + (float)data.m_width * data.m_scale);
+ data.m_cornerBiomes[3] = worldGen.GetBiome(vector.x + (float)data.m_width * data.m_scale, vector.z + (float)data.m_width * data.m_scale);
+ Heightmap.Biome biome = data.m_cornerBiomes[0];
+ Heightmap.Biome biome2 = data.m_cornerBiomes[1];
+ Heightmap.Biome biome3 = data.m_cornerBiomes[2];
+ Heightmap.Biome biome4 = data.m_cornerBiomes[3];
+ data.m_baseHeights = new List<float>(num * num);
+ for (int i = 0; i < num2; i++)
+ {
+ data.m_baseHeights.Add(0f);
+ }
+ for (int j = 0; j < num; j++)
+ {
+ float wy = vector.z + (float)j * data.m_scale;
+ float t = Mathf.SmoothStep(0f, 1f, (float)j / (float)data.m_width);
+ for (int k = 0; k < num; k++)
+ {
+ float wx = vector.x + (float)k * data.m_scale;
+ float t2 = Mathf.SmoothStep(0f, 1f, (float)k / (float)data.m_width);
+ float num3 = 0f;
+ if (data.m_distantLod)
+ {
+ Heightmap.Biome biome5 = worldGen.GetBiome(wx, wy);
+ num3 = worldGen.GetBiomeHeight(biome5, wx, wy);
+ }
+ else if (biome3 == biome && biome2 == biome && biome4 == biome)
+ {
+ num3 = worldGen.GetBiomeHeight(biome, wx, wy);
+ }
+ else
+ {
+ float biomeHeight = worldGen.GetBiomeHeight(biome, wx, wy);
+ float biomeHeight2 = worldGen.GetBiomeHeight(biome2, wx, wy);
+ float biomeHeight3 = worldGen.GetBiomeHeight(biome3, wx, wy);
+ float biomeHeight4 = worldGen.GetBiomeHeight(biome4, wx, wy);
+ float a = Mathf.Lerp(biomeHeight, biomeHeight2, t2);
+ float b = Mathf.Lerp(biomeHeight3, biomeHeight4, t2);
+ num3 = Mathf.Lerp(a, b, t);
+ }
+ data.m_baseHeights[j * num + k] = num3;
+ }
+ }
+ if (!data.m_distantLod)
+ {
+ return;
+ }
+ for (int l = 0; l < 4; l++)
+ {
+ List<float> list = new List<float>(data.m_baseHeights);
+ for (int m = 1; m < num - 1; m++)
+ {
+ for (int n = 1; n < num - 1; n++)
+ {
+ float num4 = list[m * num + n];
+ float num5 = list[(m - 1) * num + n];
+ float num6 = list[(m + 1) * num + n];
+ float num7 = list[m * num + n - 1];
+ float num8 = list[m * num + n + 1];
+ if (Mathf.Abs(num4 - num5) > 10f)
+ {
+ num4 = (num4 + num5) * 0.5f;
+ }
+ if (Mathf.Abs(num4 - num6) > 10f)
+ {
+ num4 = (num4 + num6) * 0.5f;
+ }
+ if (Mathf.Abs(num4 - num7) > 10f)
+ {
+ num4 = (num4 + num7) * 0.5f;
+ }
+ if (Mathf.Abs(num4 - num8) > 10f)
+ {
+ num4 = (num4 + num8) * 0.5f;
+ }
+ data.m_baseHeights[m * num + n] = num4;
+ }
+ }
+ }
+ }
+
+ public HMBuildData RequestTerrainSync(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen)
+ {
+ HMBuildData hMBuildData;
+ do
+ {
+ hMBuildData = RequestTerrain(center, width, scale, distantLod, worldGen);
+ }
+ while (hMBuildData == null);
+ return hMBuildData;
+ }
+
+ public HMBuildData RequestTerrain(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen)
+ {
+ m_lock.WaitOne();
+ for (int i = 0; i < m_ready.Count; i++)
+ {
+ HMBuildData hMBuildData = m_ready[i];
+ if (hMBuildData.IsEqual(center, width, scale, distantLod, worldGen))
+ {
+ m_ready.RemoveAt(i);
+ m_lock.ReleaseMutex();
+ return hMBuildData;
+ }
+ }
+ for (int j = 0; j < m_toBuild.Count; j++)
+ {
+ if (m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen))
+ {
+ m_lock.ReleaseMutex();
+ return null;
+ }
+ }
+ m_toBuild.Add(new HMBuildData(center, width, scale, distantLod, worldGen));
+ m_lock.ReleaseMutex();
+ return null;
+ }
+
+ public bool IsTerrainReady(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen)
+ {
+ m_lock.WaitOne();
+ for (int i = 0; i < m_ready.Count; i++)
+ {
+ if (m_ready[i].IsEqual(center, width, scale, distantLod, worldGen))
+ {
+ m_lock.ReleaseMutex();
+ return true;
+ }
+ }
+ for (int j = 0; j < m_toBuild.Count; j++)
+ {
+ if (m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen))
+ {
+ m_lock.ReleaseMutex();
+ return false;
+ }
+ }
+ m_toBuild.Add(new HMBuildData(center, width, scale, distantLod, worldGen));
+ m_lock.ReleaseMutex();
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitArea.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitArea.cs
new file mode 100644
index 0000000..3e89592
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitArea.cs
@@ -0,0 +1,25 @@
+using System;
+using UnityEngine;
+
+public class HitArea : MonoBehaviour, IDestructible
+{
+ public Action<HitData, HitArea> m_onHit;
+
+ public float m_health = 1f;
+
+ [NonSerialized]
+ public GameObject m_parentObject;
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Default;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (m_onHit != null)
+ {
+ m_onHit(hit, this);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitData.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitData.cs
new file mode 100644
index 0000000..fc6a332
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HitData.cs
@@ -0,0 +1,625 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HitData
+{
+ [Flags]
+ public enum DamageType
+ {
+ Blunt = 1,
+ Slash = 2,
+ Pierce = 4,
+ Chop = 8,
+ Pickaxe = 0x10,
+ Fire = 0x20,
+ Frost = 0x40,
+ Lightning = 0x80,
+ Poison = 0x100,
+ Spirit = 0x200,
+ Physical = 0x1F,
+ Elemental = 0xE0
+ }
+
+ public enum DamageModifier
+ {
+ Normal,
+ Resistant,
+ Weak,
+ Immune,
+ Ignore,
+ VeryResistant,
+ VeryWeak
+ }
+
+ [Serializable]
+ public struct DamageModPair
+ {
+ public DamageType m_type;
+
+ public DamageModifier m_modifier;
+ }
+
+ [Serializable]
+ public struct DamageModifiers
+ {
+ public DamageModifier m_blunt;
+
+ public DamageModifier m_slash;
+
+ public DamageModifier m_pierce;
+
+ public DamageModifier m_chop;
+
+ public DamageModifier m_pickaxe;
+
+ public DamageModifier m_fire;
+
+ public DamageModifier m_frost;
+
+ public DamageModifier m_lightning;
+
+ public DamageModifier m_poison;
+
+ public DamageModifier m_spirit;
+
+ public DamageModifiers Clone()
+ {
+ return (DamageModifiers)MemberwiseClone();
+ }
+
+ public void Apply(List<DamageModPair> modifiers)
+ {
+ foreach (DamageModPair modifier in modifiers)
+ {
+ switch (modifier.m_type)
+ {
+ case DamageType.Blunt:
+ ApplyIfBetter(ref m_blunt, modifier.m_modifier);
+ break;
+ case DamageType.Slash:
+ ApplyIfBetter(ref m_slash, modifier.m_modifier);
+ break;
+ case DamageType.Pierce:
+ ApplyIfBetter(ref m_pierce, modifier.m_modifier);
+ break;
+ case DamageType.Chop:
+ ApplyIfBetter(ref m_chop, modifier.m_modifier);
+ break;
+ case DamageType.Pickaxe:
+ ApplyIfBetter(ref m_pickaxe, modifier.m_modifier);
+ break;
+ case DamageType.Fire:
+ ApplyIfBetter(ref m_fire, modifier.m_modifier);
+ break;
+ case DamageType.Frost:
+ ApplyIfBetter(ref m_frost, modifier.m_modifier);
+ break;
+ case DamageType.Lightning:
+ ApplyIfBetter(ref m_lightning, modifier.m_modifier);
+ break;
+ case DamageType.Poison:
+ ApplyIfBetter(ref m_poison, modifier.m_modifier);
+ break;
+ case DamageType.Spirit:
+ ApplyIfBetter(ref m_spirit, modifier.m_modifier);
+ break;
+ }
+ }
+ }
+
+ public DamageModifier GetModifier(DamageType type)
+ {
+ return type switch
+ {
+ DamageType.Blunt => m_blunt,
+ DamageType.Slash => m_slash,
+ DamageType.Pierce => m_pierce,
+ DamageType.Chop => m_chop,
+ DamageType.Pickaxe => m_pickaxe,
+ DamageType.Fire => m_fire,
+ DamageType.Frost => m_frost,
+ DamageType.Lightning => m_lightning,
+ DamageType.Poison => m_poison,
+ DamageType.Spirit => m_spirit,
+ _ => DamageModifier.Normal,
+ };
+ }
+
+ private void ApplyIfBetter(ref DamageModifier original, DamageModifier mod)
+ {
+ if (ShouldOverride(original, mod))
+ {
+ original = mod;
+ }
+ }
+
+ private bool ShouldOverride(DamageModifier a, DamageModifier b)
+ {
+ if (a == DamageModifier.Ignore)
+ {
+ return false;
+ }
+ if (b == DamageModifier.Immune)
+ {
+ return true;
+ }
+ if (a == DamageModifier.VeryResistant && b == DamageModifier.Resistant)
+ {
+ return false;
+ }
+ if (a == DamageModifier.VeryWeak && b == DamageModifier.Weak)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public void Print()
+ {
+ ZLog.Log("m_blunt " + m_blunt);
+ ZLog.Log("m_slash " + m_slash);
+ ZLog.Log("m_pierce " + m_pierce);
+ ZLog.Log("m_chop " + m_chop);
+ ZLog.Log("m_pickaxe " + m_pickaxe);
+ ZLog.Log("m_fire " + m_fire);
+ ZLog.Log("m_frost " + m_frost);
+ ZLog.Log("m_lightning " + m_lightning);
+ ZLog.Log("m_poison " + m_poison);
+ ZLog.Log("m_spirit " + m_spirit);
+ }
+ }
+
+ [Serializable]
+ public struct DamageTypes
+ {
+ public float m_damage;
+
+ public float m_blunt;
+
+ public float m_slash;
+
+ public float m_pierce;
+
+ public float m_chop;
+
+ public float m_pickaxe;
+
+ public float m_fire;
+
+ public float m_frost;
+
+ public float m_lightning;
+
+ public float m_poison;
+
+ public float m_spirit;
+
+ public bool HaveDamage()
+ {
+ if (!(m_damage > 0f) && !(m_blunt > 0f) && !(m_slash > 0f) && !(m_pierce > 0f) && !(m_chop > 0f) && !(m_pickaxe > 0f) && !(m_fire > 0f) && !(m_frost > 0f) && !(m_lightning > 0f) && !(m_poison > 0f))
+ {
+ return m_spirit > 0f;
+ }
+ return true;
+ }
+
+ public float GetTotalPhysicalDamage()
+ {
+ return m_blunt + m_slash + m_pierce;
+ }
+
+ public float GetTotalElementalDamage()
+ {
+ return m_fire + m_frost + m_lightning;
+ }
+
+ public float GetTotalDamage()
+ {
+ return m_damage + m_blunt + m_slash + m_pierce + m_chop + m_pickaxe + m_fire + m_frost + m_lightning + m_poison + m_spirit;
+ }
+
+ public DamageTypes Clone()
+ {
+ return (DamageTypes)MemberwiseClone();
+ }
+
+ public void Add(DamageTypes other, int multiplier = 1)
+ {
+ m_damage += other.m_damage * (float)multiplier;
+ m_blunt += other.m_blunt * (float)multiplier;
+ m_slash += other.m_slash * (float)multiplier;
+ m_pierce += other.m_pierce * (float)multiplier;
+ m_chop += other.m_chop * (float)multiplier;
+ m_pickaxe += other.m_pickaxe * (float)multiplier;
+ m_fire += other.m_fire * (float)multiplier;
+ m_frost += other.m_frost * (float)multiplier;
+ m_lightning += other.m_lightning * (float)multiplier;
+ m_poison += other.m_poison * (float)multiplier;
+ m_spirit += other.m_spirit * (float)multiplier;
+ }
+
+ public void Modify(float multiplier)
+ {
+ m_damage *= multiplier;
+ m_blunt *= multiplier;
+ m_slash *= multiplier;
+ m_pierce *= multiplier;
+ m_chop *= multiplier;
+ m_pickaxe *= multiplier;
+ m_fire *= multiplier;
+ m_frost *= multiplier;
+ m_lightning *= multiplier;
+ m_poison *= multiplier;
+ m_spirit *= multiplier;
+ }
+
+ private float ApplyArmor(float dmg, float ac)
+ {
+ float result = Mathf.Clamp01(dmg / (ac * 4f)) * dmg;
+ if (ac < dmg / 2f)
+ {
+ result = dmg - ac;
+ }
+ return result;
+ }
+
+ public void ApplyArmor(float ac)
+ {
+ if (!(ac <= 0f))
+ {
+ float num = m_blunt + m_chop + m_pickaxe + m_slash + m_pierce + m_fire + m_frost + m_lightning + m_spirit;
+ if (!(num <= 0f))
+ {
+ float num2 = ApplyArmor(num, ac) / num;
+ m_blunt *= num2;
+ m_chop *= num2;
+ m_pickaxe *= num2;
+ m_slash *= num2;
+ m_pierce *= num2;
+ m_fire *= num2;
+ m_frost *= num2;
+ m_lightning *= num2;
+ m_spirit *= num2;
+ }
+ }
+ }
+
+ private string DamageRange(float damage, float minFactor, float maxFactor)
+ {
+ int num = Mathf.RoundToInt(damage * minFactor);
+ int num2 = Mathf.RoundToInt(damage * maxFactor);
+ return "<color=orange>" + Mathf.RoundToInt(damage) + "</color> <color=yellow>(" + num.ToString() + "-" + num2.ToString() + ") </color>";
+ }
+
+ public string GetTooltipString(Skills.SkillType skillType = Skills.SkillType.None)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return "";
+ }
+ Player.m_localPlayer.GetSkills().GetRandomSkillRange(out var min, out var max, skillType);
+ string text = "";
+ if (m_damage != 0f)
+ {
+ text = text + "\n$inventory_damage: " + DamageRange(m_damage, min, max);
+ }
+ if (m_blunt != 0f)
+ {
+ text = text + "\n$inventory_blunt: " + DamageRange(m_blunt, min, max);
+ }
+ if (m_slash != 0f)
+ {
+ text = text + "\n$inventory_slash: " + DamageRange(m_slash, min, max);
+ }
+ if (m_pierce != 0f)
+ {
+ text = text + "\n$inventory_pierce: " + DamageRange(m_pierce, min, max);
+ }
+ if (m_fire != 0f)
+ {
+ text = text + "\n$inventory_fire: " + DamageRange(m_fire, min, max);
+ }
+ if (m_frost != 0f)
+ {
+ text = text + "\n$inventory_frost: " + DamageRange(m_frost, min, max);
+ }
+ if (m_lightning != 0f)
+ {
+ text = text + "\n$inventory_lightning: " + DamageRange(m_lightning, min, max);
+ }
+ if (m_poison != 0f)
+ {
+ text = text + "\n$inventory_poison: " + DamageRange(m_poison, min, max);
+ }
+ if (m_spirit != 0f)
+ {
+ text = text + "\n$inventory_spirit: " + DamageRange(m_spirit, min, max);
+ }
+ return text;
+ }
+
+ public string GetTooltipString()
+ {
+ string text = "";
+ if (m_damage != 0f)
+ {
+ text = text + "\n$inventory_damage: <color=yellow>" + m_damage + "</color>";
+ }
+ if (m_blunt != 0f)
+ {
+ text = text + "\n$inventory_blunt: <color=yellow>" + m_blunt + "</color>";
+ }
+ if (m_slash != 0f)
+ {
+ text = text + "\n$inventory_slash: <color=yellow>" + m_slash + "</color>";
+ }
+ if (m_pierce != 0f)
+ {
+ text = text + "\n$inventory_pierce: <color=yellow>" + m_pierce + "</color>";
+ }
+ if (m_fire != 0f)
+ {
+ text = text + "\n$inventory_fire: <color=yellow>" + m_fire + "</color>";
+ }
+ if (m_frost != 0f)
+ {
+ text = text + "\n$inventory_frost: <color=yellow>" + m_frost + "</color>";
+ }
+ if (m_lightning != 0f)
+ {
+ text = text + "\n$inventory_lightning: <color=yellow>" + m_frost + "</color>";
+ }
+ if (m_poison != 0f)
+ {
+ text = text + "\n$inventory_poison: <color=yellow>" + m_poison + "</color>";
+ }
+ if (m_spirit != 0f)
+ {
+ text = text + "\n$inventory_spirit: <color=yellow>" + m_spirit + "</color>";
+ }
+ return text;
+ }
+ }
+
+ public DamageTypes m_damage;
+
+ public int m_toolTier;
+
+ public bool m_dodgeable;
+
+ public bool m_blockable;
+
+ public float m_pushForce;
+
+ public float m_backstabBonus = 1f;
+
+ public float m_staggerMultiplier = 1f;
+
+ public Vector3 m_point = Vector3.zero;
+
+ public Vector3 m_dir = Vector3.zero;
+
+ public string m_statusEffect = "";
+
+ public ZDOID m_attacker = ZDOID.None;
+
+ public Skills.SkillType m_skill;
+
+ public Collider m_hitCollider;
+
+ public void Serialize(ref ZPackage pkg)
+ {
+ pkg.Write(m_damage.m_damage);
+ pkg.Write(m_damage.m_blunt);
+ pkg.Write(m_damage.m_slash);
+ pkg.Write(m_damage.m_pierce);
+ pkg.Write(m_damage.m_chop);
+ pkg.Write(m_damage.m_pickaxe);
+ pkg.Write(m_damage.m_fire);
+ pkg.Write(m_damage.m_frost);
+ pkg.Write(m_damage.m_lightning);
+ pkg.Write(m_damage.m_poison);
+ pkg.Write(m_damage.m_spirit);
+ pkg.Write(m_toolTier);
+ pkg.Write(m_pushForce);
+ pkg.Write(m_backstabBonus);
+ pkg.Write(m_staggerMultiplier);
+ pkg.Write(m_dodgeable);
+ pkg.Write(m_blockable);
+ pkg.Write(m_point);
+ pkg.Write(m_dir);
+ pkg.Write(m_statusEffect);
+ pkg.Write(m_attacker);
+ pkg.Write((int)m_skill);
+ }
+
+ public void Deserialize(ref ZPackage pkg)
+ {
+ m_damage.m_damage = pkg.ReadSingle();
+ m_damage.m_blunt = pkg.ReadSingle();
+ m_damage.m_slash = pkg.ReadSingle();
+ m_damage.m_pierce = pkg.ReadSingle();
+ m_damage.m_chop = pkg.ReadSingle();
+ m_damage.m_pickaxe = pkg.ReadSingle();
+ m_damage.m_fire = pkg.ReadSingle();
+ m_damage.m_frost = pkg.ReadSingle();
+ m_damage.m_lightning = pkg.ReadSingle();
+ m_damage.m_poison = pkg.ReadSingle();
+ m_damage.m_spirit = pkg.ReadSingle();
+ m_toolTier = pkg.ReadInt();
+ m_pushForce = pkg.ReadSingle();
+ m_backstabBonus = pkg.ReadSingle();
+ m_staggerMultiplier = pkg.ReadSingle();
+ m_dodgeable = pkg.ReadBool();
+ m_blockable = pkg.ReadBool();
+ m_point = pkg.ReadVector3();
+ m_dir = pkg.ReadVector3();
+ m_statusEffect = pkg.ReadString();
+ m_attacker = pkg.ReadZDOID();
+ m_skill = (Skills.SkillType)pkg.ReadInt();
+ }
+
+ public float GetTotalPhysicalDamage()
+ {
+ return m_damage.GetTotalPhysicalDamage();
+ }
+
+ public float GetTotalElementalDamage()
+ {
+ return m_damage.GetTotalElementalDamage();
+ }
+
+ public float GetTotalDamage()
+ {
+ return m_damage.GetTotalDamage();
+ }
+
+ private float ApplyModifier(float baseDamage, DamageModifier mod, ref float normalDmg, ref float resistantDmg, ref float weakDmg, ref float immuneDmg)
+ {
+ if (mod == DamageModifier.Ignore)
+ {
+ return 0f;
+ }
+ float num = baseDamage;
+ switch (mod)
+ {
+ case DamageModifier.Resistant:
+ num /= 2f;
+ resistantDmg += baseDamage;
+ break;
+ case DamageModifier.VeryResistant:
+ num /= 4f;
+ resistantDmg += baseDamage;
+ break;
+ case DamageModifier.Weak:
+ num *= 1.5f;
+ weakDmg += baseDamage;
+ break;
+ case DamageModifier.VeryWeak:
+ num *= 2f;
+ weakDmg += baseDamage;
+ break;
+ case DamageModifier.Immune:
+ num = 0f;
+ immuneDmg += baseDamage;
+ break;
+ default:
+ normalDmg += baseDamage;
+ break;
+ }
+ return num;
+ }
+
+ public void ApplyResistance(DamageModifiers modifiers, out DamageModifier significantModifier)
+ {
+ float normalDmg = m_damage.m_damage;
+ float resistantDmg = 0f;
+ float weakDmg = 0f;
+ float immuneDmg = 0f;
+ m_damage.m_blunt = ApplyModifier(m_damage.m_blunt, modifiers.m_blunt, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_slash = ApplyModifier(m_damage.m_slash, modifiers.m_slash, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_pierce = ApplyModifier(m_damage.m_pierce, modifiers.m_pierce, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_chop = ApplyModifier(m_damage.m_chop, modifiers.m_chop, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_pickaxe = ApplyModifier(m_damage.m_pickaxe, modifiers.m_pickaxe, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_fire = ApplyModifier(m_damage.m_fire, modifiers.m_fire, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_frost = ApplyModifier(m_damage.m_frost, modifiers.m_frost, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_lightning = ApplyModifier(m_damage.m_lightning, modifiers.m_lightning, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_poison = ApplyModifier(m_damage.m_poison, modifiers.m_poison, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ m_damage.m_spirit = ApplyModifier(m_damage.m_spirit, modifiers.m_spirit, ref normalDmg, ref resistantDmg, ref weakDmg, ref immuneDmg);
+ significantModifier = DamageModifier.Immune;
+ if (immuneDmg >= resistantDmg && immuneDmg >= weakDmg && immuneDmg >= normalDmg)
+ {
+ significantModifier = DamageModifier.Immune;
+ }
+ if (normalDmg >= resistantDmg && normalDmg >= weakDmg && normalDmg >= immuneDmg)
+ {
+ significantModifier = DamageModifier.Normal;
+ }
+ if (resistantDmg >= weakDmg && resistantDmg >= immuneDmg && resistantDmg >= normalDmg)
+ {
+ significantModifier = DamageModifier.Resistant;
+ }
+ if (weakDmg >= resistantDmg && weakDmg >= immuneDmg && weakDmg >= normalDmg)
+ {
+ significantModifier = DamageModifier.Weak;
+ }
+ }
+
+ public void ApplyArmor(float ac)
+ {
+ m_damage.ApplyArmor(ac);
+ }
+
+ public void ApplyModifier(float multiplier)
+ {
+ m_damage.m_blunt *= multiplier;
+ m_damage.m_slash *= multiplier;
+ m_damage.m_pierce *= multiplier;
+ m_damage.m_chop *= multiplier;
+ m_damage.m_pickaxe *= multiplier;
+ m_damage.m_fire *= multiplier;
+ m_damage.m_frost *= multiplier;
+ m_damage.m_lightning *= multiplier;
+ m_damage.m_poison *= multiplier;
+ m_damage.m_spirit *= multiplier;
+ }
+
+ public float GetTotalBlockableDamage()
+ {
+ return m_damage.m_blunt + m_damage.m_slash + m_damage.m_pierce + m_damage.m_fire + m_damage.m_frost + m_damage.m_lightning + m_damage.m_poison + m_damage.m_spirit;
+ }
+
+ public void BlockDamage(float damage)
+ {
+ float totalBlockableDamage = GetTotalBlockableDamage();
+ float num = Mathf.Max(0f, totalBlockableDamage - damage);
+ if (!(totalBlockableDamage <= 0f))
+ {
+ float num2 = num / totalBlockableDamage;
+ m_damage.m_blunt *= num2;
+ m_damage.m_slash *= num2;
+ m_damage.m_pierce *= num2;
+ m_damage.m_fire *= num2;
+ m_damage.m_frost *= num2;
+ m_damage.m_lightning *= num2;
+ m_damage.m_poison *= num2;
+ m_damage.m_spirit *= num2;
+ }
+ }
+
+ public bool HaveAttacker()
+ {
+ return !m_attacker.IsNone();
+ }
+
+ public Character GetAttacker()
+ {
+ if (m_attacker.IsNone())
+ {
+ return null;
+ }
+ if (ZNetScene.instance == null)
+ {
+ return null;
+ }
+ GameObject gameObject = ZNetScene.instance.FindInstance(m_attacker);
+ if (gameObject == null)
+ {
+ return null;
+ }
+ return gameObject.GetComponent<Character>();
+ }
+
+ public void SetAttacker(Character attacker)
+ {
+ if ((bool)attacker)
+ {
+ m_attacker = attacker.GetZDOID();
+ }
+ else
+ {
+ m_attacker = ZDOID.None;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HotkeyBar.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HotkeyBar.cs
new file mode 100644
index 0000000..c884d08
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HotkeyBar.cs
@@ -0,0 +1,156 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HotkeyBar : MonoBehaviour
+{
+ private class ElementData
+ {
+ public bool m_used;
+
+ public GameObject m_go;
+
+ public Image m_icon;
+
+ public GuiBar m_durability;
+
+ public Text m_amount;
+
+ public GameObject m_equiped;
+
+ public GameObject m_queued;
+
+ public GameObject m_selection;
+ }
+
+ public GameObject m_elementPrefab;
+
+ public float m_elementSpace = 70f;
+
+ private int m_selected;
+
+ private List<ElementData> m_elements = new List<ElementData>();
+
+ private List<ItemDrop.ItemData> m_items = new List<ItemDrop.ItemData>();
+
+ private void Update()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer && !InventoryGui.IsVisible() && !Menu.IsVisible() && !GameCamera.InFreeFly())
+ {
+ if (ZInput.GetButtonDown("JoyDPadLeft"))
+ {
+ m_selected = Mathf.Max(0, m_selected - 1);
+ }
+ if (ZInput.GetButtonDown("JoyDPadRight"))
+ {
+ m_selected = Mathf.Min(m_elements.Count - 1, m_selected + 1);
+ }
+ if (ZInput.GetButtonDown("JoyDPadUp"))
+ {
+ localPlayer.UseHotbarItem(m_selected + 1);
+ }
+ }
+ if (m_selected > m_elements.Count - 1)
+ {
+ m_selected = Mathf.Max(0, m_elements.Count - 1);
+ }
+ UpdateIcons(localPlayer);
+ }
+
+ private void UpdateIcons(Player player)
+ {
+ if (!player || player.IsDead())
+ {
+ foreach (ElementData element in m_elements)
+ {
+ Object.Destroy(element.m_go);
+ }
+ m_elements.Clear();
+ return;
+ }
+ player.GetInventory().GetBoundItems(m_items);
+ m_items.Sort((ItemDrop.ItemData x, ItemDrop.ItemData y) => x.m_gridPos.x.CompareTo(y.m_gridPos.x));
+ int num = 0;
+ foreach (ItemDrop.ItemData item in m_items)
+ {
+ if (item.m_gridPos.x + 1 > num)
+ {
+ num = item.m_gridPos.x + 1;
+ }
+ }
+ if (m_elements.Count != num)
+ {
+ foreach (ElementData element2 in m_elements)
+ {
+ Object.Destroy(element2.m_go);
+ }
+ m_elements.Clear();
+ for (int i = 0; i < num; i++)
+ {
+ ElementData elementData = new ElementData();
+ elementData.m_go = Object.Instantiate(m_elementPrefab, base.transform);
+ elementData.m_go.transform.localPosition = new Vector3((float)i * m_elementSpace, 0f, 0f);
+ elementData.m_go.transform.Find("binding").GetComponent<Text>().text = (i + 1).ToString();
+ elementData.m_icon = elementData.m_go.transform.transform.Find("icon").GetComponent<Image>();
+ elementData.m_durability = elementData.m_go.transform.Find("durability").GetComponent<GuiBar>();
+ elementData.m_amount = elementData.m_go.transform.Find("amount").GetComponent<Text>();
+ elementData.m_equiped = elementData.m_go.transform.Find("equiped").gameObject;
+ elementData.m_queued = elementData.m_go.transform.Find("queued").gameObject;
+ elementData.m_selection = elementData.m_go.transform.Find("selected").gameObject;
+ m_elements.Add(elementData);
+ }
+ }
+ foreach (ElementData element3 in m_elements)
+ {
+ element3.m_used = false;
+ }
+ bool flag = ZInput.IsGamepadActive();
+ for (int j = 0; j < m_items.Count; j++)
+ {
+ ItemDrop.ItemData itemData = m_items[j];
+ ElementData elementData2 = m_elements[itemData.m_gridPos.x];
+ elementData2.m_used = true;
+ elementData2.m_icon.gameObject.SetActive(value: true);
+ elementData2.m_icon.sprite = itemData.GetIcon();
+ elementData2.m_durability.gameObject.SetActive(itemData.m_shared.m_useDurability);
+ if (itemData.m_shared.m_useDurability)
+ {
+ if (itemData.m_durability <= 0f)
+ {
+ elementData2.m_durability.SetValue(1f);
+ elementData2.m_durability.SetColor((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : new Color(0f, 0f, 0f, 0f));
+ }
+ else
+ {
+ elementData2.m_durability.SetValue(itemData.GetDurabilityPercentage());
+ elementData2.m_durability.ResetColor();
+ }
+ }
+ elementData2.m_equiped.SetActive(itemData.m_equiped);
+ elementData2.m_queued.SetActive(player.IsItemQueued(itemData));
+ if (itemData.m_shared.m_maxStackSize > 1)
+ {
+ elementData2.m_amount.gameObject.SetActive(value: true);
+ elementData2.m_amount.text = itemData.m_stack + "/" + itemData.m_shared.m_maxStackSize;
+ }
+ else
+ {
+ elementData2.m_amount.gameObject.SetActive(value: false);
+ }
+ }
+ for (int k = 0; k < m_elements.Count; k++)
+ {
+ ElementData elementData3 = m_elements[k];
+ elementData3.m_selection.SetActive(flag && k == m_selected);
+ if (!elementData3.m_used)
+ {
+ elementData3.m_icon.gameObject.SetActive(value: false);
+ elementData3.m_durability.gameObject.SetActive(value: false);
+ elementData3.m_equiped.SetActive(value: false);
+ elementData3.m_queued.SetActive(value: false);
+ elementData3.m_amount.gameObject.SetActive(value: false);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HoverText.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HoverText.cs
new file mode 100644
index 0000000..5cf4f59
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/HoverText.cs
@@ -0,0 +1,16 @@
+using UnityEngine;
+
+public class HoverText : MonoBehaviour, Hoverable
+{
+ public string m_text = "";
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_text);
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_text);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hoverable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hoverable.cs
new file mode 100644
index 0000000..a340096
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hoverable.cs
@@ -0,0 +1,6 @@
+public interface Hoverable
+{
+ string GetHoverText();
+
+ string GetHoverName();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hud.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hud.cs
new file mode 100644
index 0000000..facecda
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Hud.cs
@@ -0,0 +1,1171 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Hud : MonoBehaviour
+{
+ private class PieceIconData
+ {
+ public GameObject m_go;
+
+ public Image m_icon;
+
+ public GameObject m_marker;
+
+ public GameObject m_upgrade;
+
+ public UITooltip m_tooltip;
+ }
+
+ private static Hud m_instance;
+
+ public GameObject m_rootObject;
+
+ public Text m_buildSelection;
+
+ public Text m_pieceDescription;
+
+ public Image m_buildIcon;
+
+ public GameObject m_buildHud;
+
+ public GameObject m_saveIcon;
+
+ public GameObject m_badConnectionIcon;
+
+ public GameObject m_betaText;
+
+ [Header("Piece")]
+ public GameObject[] m_requirementItems = new GameObject[0];
+
+ public GameObject[] m_pieceCategoryTabs = new GameObject[0];
+
+ public GameObject m_pieceSelectionWindow;
+
+ public GameObject m_pieceCategoryRoot;
+
+ public RectTransform m_pieceListRoot;
+
+ public RectTransform m_pieceListMask;
+
+ public GameObject m_pieceIconPrefab;
+
+ public UIInputHandler m_closePieceSelectionButton;
+
+ public EffectList m_selectItemEffect = new EffectList();
+
+ public float m_pieceIconSpacing = 64f;
+
+ private float m_pieceBarPosX;
+
+ private float m_pieceBarTargetPosX;
+
+ private Piece.PieceCategory m_lastPieceCategory = Piece.PieceCategory.Max;
+
+ [Header("Health")]
+ public RectTransform m_healthBarRoot;
+
+ public RectTransform m_healthPanel;
+
+ private const float m_healthPanelBuffer = 56f;
+
+ private const float m_healthPanelMinSize = 138f;
+
+ public Animator m_healthAnimator;
+
+ public GuiBar m_healthBarFast;
+
+ public GuiBar m_healthBarSlow;
+
+ public Text m_healthText;
+
+ public Text m_healthMaxText;
+
+ [Header("Food")]
+ public Image[] m_foodBars;
+
+ public Image[] m_foodIcons;
+
+ public RectTransform m_foodBarRoot;
+
+ public RectTransform m_foodBaseBar;
+
+ public Image m_foodIcon;
+
+ public Color m_foodColorHungry = Color.white;
+
+ public Color m_foodColorFull = Color.white;
+
+ public Text m_foodText;
+
+ [Header("Action bar")]
+ public GameObject m_actionBarRoot;
+
+ public GuiBar m_actionProgress;
+
+ public Text m_actionName;
+
+ [Header("Guardian power")]
+ public RectTransform m_gpRoot;
+
+ public Text m_gpName;
+
+ public Text m_gpCooldown;
+
+ public Image m_gpIcon;
+
+ [Header("Stamina")]
+ public GameObject m_staminaBar;
+
+ public GuiBar m_staminaBarFast;
+
+ public GuiBar m_staminaBarSlow;
+
+ public Animator m_staminaAnimator;
+
+ private float m_staminaBarBorderBuffer = 16f;
+
+ public RectTransform m_staminaBar2Root;
+
+ public GuiBar m_staminaBar2Fast;
+
+ public GuiBar m_staminaBar2Slow;
+
+ [Header("Loading")]
+ public CanvasGroup m_loadingScreen;
+
+ public GameObject m_loadingProgress;
+
+ public GameObject m_sleepingProgress;
+
+ public GameObject m_teleportingProgress;
+
+ public Image m_loadingImage;
+
+ public Text m_loadingTip;
+
+ public bool m_useRandomImages = true;
+
+ public string m_loadingImagePath = "/loadingscreens/";
+
+ public int m_loadingImages = 2;
+
+ public List<string> m_loadingTips = new List<string>();
+
+ [Header("Crosshair")]
+ public Image m_crosshair;
+
+ public Image m_crosshairBow;
+
+ public Text m_hoverName;
+
+ public RectTransform m_pieceHealthRoot;
+
+ public GuiBar m_pieceHealthBar;
+
+ public Image m_damageScreen;
+
+ [Header("Target")]
+ public GameObject m_targetedAlert;
+
+ public GameObject m_targeted;
+
+ public GameObject m_hidden;
+
+ public GuiBar m_stealthBar;
+
+ [Header("Status effect")]
+ public RectTransform m_statusEffectListRoot;
+
+ public RectTransform m_statusEffectTemplate;
+
+ public float m_statusEffectSpacing = 55f;
+
+ private List<RectTransform> m_statusEffects = new List<RectTransform>();
+
+ [Header("Ship hud")]
+ public GameObject m_shipHudRoot;
+
+ public GameObject m_shipControlsRoot;
+
+ public GameObject m_rudderLeft;
+
+ public GameObject m_rudderRight;
+
+ public GameObject m_rudderSlow;
+
+ public GameObject m_rudderForward;
+
+ public GameObject m_rudderFastForward;
+
+ public GameObject m_rudderBackward;
+
+ public GameObject m_halfSail;
+
+ public GameObject m_fullSail;
+
+ public GameObject m_rudder;
+
+ public RectTransform m_shipWindIndicatorRoot;
+
+ public Image m_shipWindIcon;
+
+ public RectTransform m_shipWindIconRoot;
+
+ public Image m_shipRudderIndicator;
+
+ public Image m_shipRudderIcon;
+
+ [Header("Event")]
+ public GameObject m_eventBar;
+
+ public Text m_eventName;
+
+ private bool m_userHidden;
+
+ private CraftingStation m_currentCraftingStation;
+
+ private List<string> m_buildCategoryNames = new List<string>();
+
+ private List<StatusEffect> m_tempStatusEffects = new List<StatusEffect>();
+
+ private List<PieceIconData> m_pieceIcons = new List<PieceIconData>();
+
+ private int m_pieceIconUpdateIndex;
+
+ private bool m_haveSetupLoadScreen;
+
+ private int m_closePieceSelection;
+
+ private Piece m_hoveredPiece;
+
+ public static Hud instance => m_instance;
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_pieceSelectionWindow.SetActive(value: false);
+ m_loadingScreen.gameObject.SetActive(value: false);
+ m_statusEffectTemplate.gameObject.SetActive(value: false);
+ m_eventBar.SetActive(value: false);
+ m_gpRoot.gameObject.SetActive(value: false);
+ m_betaText.SetActive(value: false);
+ UIInputHandler closePieceSelectionButton = m_closePieceSelectionButton;
+ closePieceSelectionButton.m_onLeftClick = (Action<UIInputHandler>)Delegate.Combine(closePieceSelectionButton.m_onLeftClick, new Action<UIInputHandler>(OnClosePieceSelection));
+ UIInputHandler closePieceSelectionButton2 = m_closePieceSelectionButton;
+ closePieceSelectionButton2.m_onRightClick = (Action<UIInputHandler>)Delegate.Combine(closePieceSelectionButton2.m_onRightClick, new Action<UIInputHandler>(OnClosePieceSelection));
+ if (SteamManager.APP_ID == 1223920)
+ {
+ m_betaText.SetActive(value: true);
+ }
+ GameObject[] pieceCategoryTabs = m_pieceCategoryTabs;
+ foreach (GameObject gameObject in pieceCategoryTabs)
+ {
+ m_buildCategoryNames.Add(gameObject.transform.Find("Text").GetComponent<Text>().text);
+ UIInputHandler component = gameObject.GetComponent<UIInputHandler>();
+ component.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftDown, new Action<UIInputHandler>(OnLeftClickCategory));
+ }
+ }
+
+ private void SetVisible(bool visible)
+ {
+ if (visible != IsVisible())
+ {
+ if (visible)
+ {
+ m_rootObject.transform.localPosition = new Vector3(0f, 0f, 0f);
+ }
+ else
+ {
+ m_rootObject.transform.localPosition = new Vector3(10000f, 0f, 0f);
+ }
+ }
+ }
+
+ private bool IsVisible()
+ {
+ return m_rootObject.transform.localPosition.x < 1000f;
+ }
+
+ private void Update()
+ {
+ m_saveIcon.SetActive(ZNet.instance != null && ZNet.instance.IsSaving());
+ m_badConnectionIcon.SetActive(ZNet.instance != null && ZNet.instance.HasBadConnection() && Mathf.Sin(Time.time * 10f) > 0f);
+ Player localPlayer = Player.m_localPlayer;
+ UpdateDamageFlash(Time.deltaTime);
+ if ((bool)localPlayer)
+ {
+ if (Input.GetKeyDown(KeyCode.F3) && Input.GetKey(KeyCode.LeftControl))
+ {
+ m_userHidden = !m_userHidden;
+ }
+ SetVisible(!m_userHidden && !localPlayer.InCutscene());
+ UpdateBuild(localPlayer, forceUpdateAllBuildStatuses: false);
+ m_tempStatusEffects.Clear();
+ localPlayer.GetSEMan().GetHUDStatusEffects(m_tempStatusEffects);
+ UpdateStatusEffects(m_tempStatusEffects);
+ UpdateGuardianPower(localPlayer);
+ float attackDrawPercentage = localPlayer.GetAttackDrawPercentage();
+ UpdateFood(localPlayer);
+ UpdateHealth(localPlayer);
+ UpdateStamina(localPlayer);
+ UpdateStealth(localPlayer, attackDrawPercentage);
+ UpdateCrosshair(localPlayer, attackDrawPercentage);
+ UpdateEvent(localPlayer);
+ UpdateActionProgress(localPlayer);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ UpdateBlackScreen(Player.m_localPlayer, Time.deltaTime);
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ UpdateShipHud(localPlayer, Time.deltaTime);
+ }
+ }
+
+ private float GetFadeDuration(Player player)
+ {
+ if (player != null)
+ {
+ if (player.IsDead())
+ {
+ return 9.5f;
+ }
+ if (player.IsSleeping())
+ {
+ return 3f;
+ }
+ }
+ return 1f;
+ }
+
+ private void UpdateBlackScreen(Player player, float dt)
+ {
+ if (player == null || player.IsDead() || player.IsTeleporting() || Game.instance.IsLoggingOut() || player.IsSleeping())
+ {
+ m_loadingScreen.gameObject.SetActive(value: true);
+ float alpha = m_loadingScreen.alpha;
+ float fadeDuration = GetFadeDuration(player);
+ alpha = Mathf.MoveTowards(alpha, 1f, dt / fadeDuration);
+ if (Game.instance.IsLoggingOut())
+ {
+ alpha = 1f;
+ }
+ m_loadingScreen.alpha = alpha;
+ if (player != null && player.IsSleeping())
+ {
+ m_sleepingProgress.SetActive(value: true);
+ m_loadingProgress.SetActive(value: false);
+ m_teleportingProgress.SetActive(value: false);
+ }
+ else if (player != null && player.ShowTeleportAnimation())
+ {
+ m_loadingProgress.SetActive(value: false);
+ m_sleepingProgress.SetActive(value: false);
+ m_teleportingProgress.SetActive(value: true);
+ }
+ else if ((bool)Game.instance && Game.instance.WaitingForRespawn())
+ {
+ if (!m_haveSetupLoadScreen)
+ {
+ m_haveSetupLoadScreen = true;
+ if (m_useRandomImages)
+ {
+ int num = UnityEngine.Random.Range(0, m_loadingImages);
+ string text = m_loadingImagePath + "loading" + num;
+ ZLog.Log("Loading image:" + text);
+ m_loadingImage.sprite = Resources.Load<Sprite>(text);
+ }
+ string text2 = m_loadingTips[UnityEngine.Random.Range(0, m_loadingTips.Count)];
+ ZLog.Log("tip:" + text2);
+ m_loadingTip.text = Localization.instance.Localize(text2);
+ }
+ m_loadingProgress.SetActive(value: true);
+ m_sleepingProgress.SetActive(value: false);
+ m_teleportingProgress.SetActive(value: false);
+ }
+ else
+ {
+ m_loadingProgress.SetActive(value: false);
+ m_sleepingProgress.SetActive(value: false);
+ m_teleportingProgress.SetActive(value: false);
+ }
+ }
+ else
+ {
+ m_haveSetupLoadScreen = false;
+ float fadeDuration2 = GetFadeDuration(player);
+ float alpha2 = m_loadingScreen.alpha;
+ alpha2 = Mathf.MoveTowards(alpha2, 0f, dt / fadeDuration2);
+ m_loadingScreen.alpha = alpha2;
+ if (m_loadingScreen.alpha <= 0f)
+ {
+ m_loadingScreen.gameObject.SetActive(value: false);
+ }
+ }
+ }
+
+ private void UpdateShipHud(Player player, float dt)
+ {
+ Ship controlledShip = player.GetControlledShip();
+ if (controlledShip == null)
+ {
+ m_shipHudRoot.gameObject.SetActive(value: false);
+ return;
+ }
+ Ship.Speed speedSetting = controlledShip.GetSpeedSetting();
+ float rudder = controlledShip.GetRudder();
+ float rudderValue = controlledShip.GetRudderValue();
+ m_shipHudRoot.SetActive(value: true);
+ m_rudderSlow.SetActive(speedSetting == Ship.Speed.Slow);
+ m_rudderForward.SetActive(speedSetting == Ship.Speed.Half);
+ m_rudderFastForward.SetActive(speedSetting == Ship.Speed.Full);
+ m_rudderBackward.SetActive(speedSetting == Ship.Speed.Back);
+ m_rudderLeft.SetActive(value: false);
+ m_rudderRight.SetActive(value: false);
+ m_fullSail.SetActive(speedSetting == Ship.Speed.Full);
+ m_halfSail.SetActive(speedSetting == Ship.Speed.Half);
+ GameObject rudder2 = m_rudder;
+ int active;
+ switch (speedSetting)
+ {
+ case Ship.Speed.Stop:
+ active = ((Mathf.Abs(rudderValue) > 0.2f) ? 1 : 0);
+ break;
+ default:
+ active = 0;
+ break;
+ case Ship.Speed.Back:
+ case Ship.Speed.Slow:
+ active = 1;
+ break;
+ }
+ rudder2.SetActive((byte)active != 0);
+ if ((rudder > 0f && rudderValue < 1f) || (rudder < 0f && rudderValue > -1f))
+ {
+ m_shipRudderIcon.transform.Rotate(new Vector3(0f, 0f, 200f * (0f - rudder) * dt));
+ }
+ if (Mathf.Abs(rudderValue) < 0.02f)
+ {
+ m_shipRudderIndicator.gameObject.SetActive(value: false);
+ }
+ else
+ {
+ m_shipRudderIndicator.gameObject.SetActive(value: true);
+ if (rudderValue > 0f)
+ {
+ m_shipRudderIndicator.fillClockwise = true;
+ m_shipRudderIndicator.fillAmount = rudderValue * 0.25f;
+ }
+ else
+ {
+ m_shipRudderIndicator.fillClockwise = false;
+ m_shipRudderIndicator.fillAmount = (0f - rudderValue) * 0.25f;
+ }
+ }
+ float shipYawAngle = controlledShip.GetShipYawAngle();
+ m_shipWindIndicatorRoot.localRotation = Quaternion.Euler(0f, 0f, shipYawAngle);
+ float windAngle = controlledShip.GetWindAngle();
+ m_shipWindIconRoot.localRotation = Quaternion.Euler(0f, 0f, windAngle);
+ float windAngleFactor = controlledShip.GetWindAngleFactor();
+ m_shipWindIcon.color = Color.Lerp(new Color(0.2f, 0.2f, 0.2f, 1f), Color.white, windAngleFactor);
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null))
+ {
+ m_shipControlsRoot.transform.position = mainCamera.WorldToScreenPoint(controlledShip.m_controlGuiPos.position);
+ }
+ }
+
+ private void UpdateActionProgress(Player player)
+ {
+ player.GetActionProgress(out var text, out var progress);
+ if (!string.IsNullOrEmpty(text))
+ {
+ m_actionBarRoot.SetActive(value: true);
+ m_actionProgress.SetValue(progress);
+ m_actionName.text = Localization.instance.Localize(text);
+ }
+ else
+ {
+ m_actionBarRoot.SetActive(value: false);
+ }
+ }
+
+ private void UpdateCrosshair(Player player, float bowDrawPercentage)
+ {
+ GameObject hoverObject = player.GetHoverObject();
+ Hoverable hoverable = (hoverObject ? hoverObject.GetComponentInParent<Hoverable>() : null);
+ if (hoverable != null && !TextViewer.instance.IsVisible())
+ {
+ m_hoverName.text = hoverable.GetHoverText();
+ m_crosshair.color = ((m_hoverName.text.Length > 0) ? Color.yellow : new Color(1f, 1f, 1f, 0.5f));
+ }
+ else
+ {
+ m_crosshair.color = new Color(1f, 1f, 1f, 0.5f);
+ m_hoverName.text = "";
+ }
+ Piece hoveringPiece = player.GetHoveringPiece();
+ if ((bool)hoveringPiece)
+ {
+ WearNTear component = hoveringPiece.GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ m_pieceHealthRoot.gameObject.SetActive(value: true);
+ m_pieceHealthBar.SetValue(component.GetHealthPercentage());
+ }
+ else
+ {
+ m_pieceHealthRoot.gameObject.SetActive(value: false);
+ }
+ }
+ else
+ {
+ m_pieceHealthRoot.gameObject.SetActive(value: false);
+ }
+ if (bowDrawPercentage > 0f)
+ {
+ float num = Mathf.Lerp(1f, 0.15f, bowDrawPercentage);
+ m_crosshairBow.gameObject.SetActive(value: true);
+ m_crosshairBow.transform.localScale = new Vector3(num, num, num);
+ m_crosshairBow.color = Color.Lerp(new Color(1f, 1f, 1f, 0f), Color.yellow, bowDrawPercentage);
+ }
+ else
+ {
+ m_crosshairBow.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ UpdatePieceBar(Time.fixedDeltaTime);
+ }
+
+ private void UpdateStealth(Player player, float bowDrawPercentage)
+ {
+ float stealthFactor = player.GetStealthFactor();
+ if ((player.IsCrouching() || stealthFactor < 1f) && bowDrawPercentage == 0f)
+ {
+ if (player.IsSensed())
+ {
+ m_targetedAlert.SetActive(value: true);
+ m_targeted.SetActive(value: false);
+ m_hidden.SetActive(value: false);
+ }
+ else if (player.IsTargeted())
+ {
+ m_targetedAlert.SetActive(value: false);
+ m_targeted.SetActive(value: true);
+ m_hidden.SetActive(value: false);
+ }
+ else
+ {
+ m_targetedAlert.SetActive(value: false);
+ m_targeted.SetActive(value: false);
+ m_hidden.SetActive(value: true);
+ }
+ m_stealthBar.gameObject.SetActive(value: true);
+ m_stealthBar.SetValue(stealthFactor);
+ }
+ else
+ {
+ m_targetedAlert.SetActive(value: false);
+ m_hidden.SetActive(value: false);
+ m_targeted.SetActive(value: false);
+ m_stealthBar.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void SetHealthBarSize(float size)
+ {
+ size = Mathf.Ceil(size);
+ float size2 = Mathf.Max(size + 56f, 138f);
+ m_healthPanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size2);
+ m_healthBarRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size);
+ m_healthBarSlow.SetWidth(size);
+ m_healthBarFast.SetWidth(size);
+ }
+
+ private void SetStaminaBarSize(float size)
+ {
+ m_staminaBar2Root.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size + m_staminaBarBorderBuffer);
+ m_staminaBar2Slow.SetWidth(size);
+ m_staminaBar2Fast.SetWidth(size);
+ }
+
+ private void UpdateFood(Player player)
+ {
+ List<Player.Food> foods = player.GetFoods();
+ float num = player.GetBaseFoodHP() / 25f * 32f;
+ m_foodBaseBar.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, num);
+ float num2 = num;
+ for (int i = 0; i < m_foodBars.Length; i++)
+ {
+ Image image = m_foodBars[i];
+ Image image2 = m_foodIcons[i];
+ if (i < foods.Count)
+ {
+ image.gameObject.SetActive(value: true);
+ Player.Food food = foods[i];
+ float num3 = food.m_health / 25f * 32f;
+ image.color = food.m_item.m_shared.m_foodColor;
+ image.rectTransform.anchoredPosition = new Vector2(num2, 0f);
+ image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Mathf.Ceil(num3));
+ num2 += num3;
+ image2.gameObject.SetActive(value: true);
+ image2.sprite = food.m_item.GetIcon();
+ if (food.CanEatAgain())
+ {
+ image2.color = new Color(1f, 1f, 1f, 0.6f + Mathf.Sin(Time.time * 10f) * 0.4f);
+ }
+ else
+ {
+ image2.color = Color.white;
+ }
+ }
+ else
+ {
+ image.gameObject.SetActive(value: false);
+ image2.gameObject.SetActive(value: false);
+ }
+ }
+ float size = Mathf.Ceil(player.GetMaxHealth() / 25f * 32f);
+ m_foodBarRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size);
+ }
+
+ private void UpdateHealth(Player player)
+ {
+ float maxHealth = player.GetMaxHealth();
+ SetHealthBarSize(maxHealth / 25f * 32f);
+ float health = player.GetHealth();
+ m_healthBarFast.SetMaxValue(maxHealth);
+ m_healthBarFast.SetValue(health);
+ m_healthBarSlow.SetMaxValue(maxHealth);
+ m_healthBarSlow.SetValue(health);
+ string text = Mathf.CeilToInt(player.GetHealth()).ToString();
+ string text2 = Mathf.CeilToInt(player.GetMaxHealth()).ToString();
+ m_healthText.text = text.ToString();
+ m_healthMaxText.text = text2.ToString();
+ }
+
+ private void UpdateStamina(Player player)
+ {
+ float stamina = player.GetStamina();
+ float maxStamina = player.GetMaxStamina();
+ m_staminaBar.SetActive(value: false);
+ m_staminaAnimator.SetBool("Visible", stamina < maxStamina);
+ SetStaminaBarSize(player.GetMaxStamina() / 25f * 32f);
+ RectTransform rectTransform = m_staminaBar2Root.transform as RectTransform;
+ if (m_buildHud.activeSelf || m_shipHudRoot.activeSelf)
+ {
+ rectTransform.anchoredPosition = new Vector2(0f, 190f);
+ }
+ else
+ {
+ rectTransform.anchoredPosition = new Vector2(0f, 130f);
+ }
+ m_staminaBar2Slow.SetValue(stamina / maxStamina);
+ m_staminaBar2Fast.SetValue(stamina / maxStamina);
+ }
+
+ public void DamageFlash()
+ {
+ Color color = m_damageScreen.color;
+ color.a = 1f;
+ m_damageScreen.color = color;
+ m_damageScreen.gameObject.SetActive(value: true);
+ }
+
+ private void UpdateDamageFlash(float dt)
+ {
+ Color color = m_damageScreen.color;
+ color.a = Mathf.MoveTowards(color.a, 0f, dt * 4f);
+ m_damageScreen.color = color;
+ if (color.a <= 0f)
+ {
+ m_damageScreen.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void UpdatePieceList(Player player, Vector2Int selectedNr, Piece.PieceCategory category, bool updateAllBuildStatuses)
+ {
+ List<Piece> buildPieces = player.GetBuildPieces();
+ int num = 10;
+ int num2 = 5;
+ if (buildPieces.Count <= 1)
+ {
+ num = 1;
+ num2 = 1;
+ }
+ if (m_pieceIcons.Count != num * num2)
+ {
+ foreach (PieceIconData pieceIcon in m_pieceIcons)
+ {
+ UnityEngine.Object.Destroy(pieceIcon.m_go);
+ }
+ m_pieceIcons.Clear();
+ for (int i = 0; i < num2; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_pieceIconPrefab, m_pieceListRoot);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2((float)j * m_pieceIconSpacing, (float)(-i) * m_pieceIconSpacing);
+ PieceIconData pieceIconData = new PieceIconData();
+ pieceIconData.m_go = gameObject;
+ pieceIconData.m_tooltip = gameObject.GetComponent<UITooltip>();
+ pieceIconData.m_icon = gameObject.transform.Find("icon").GetComponent<Image>();
+ pieceIconData.m_marker = gameObject.transform.Find("selected").gameObject;
+ pieceIconData.m_upgrade = gameObject.transform.Find("upgrade").gameObject;
+ pieceIconData.m_icon.color = new Color(1f, 0f, 1f, 0f);
+ UIInputHandler component = gameObject.GetComponent<UIInputHandler>();
+ component.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftDown, new Action<UIInputHandler>(OnLeftClickPiece));
+ component.m_onRightDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onRightDown, new Action<UIInputHandler>(OnRightClickPiece));
+ component.m_onPointerEnter = (Action<UIInputHandler>)Delegate.Combine(component.m_onPointerEnter, new Action<UIInputHandler>(OnHoverPiece));
+ component.m_onPointerExit = (Action<UIInputHandler>)Delegate.Combine(component.m_onPointerExit, new Action<UIInputHandler>(OnHoverPieceExit));
+ m_pieceIcons.Add(pieceIconData);
+ }
+ }
+ }
+ for (int k = 0; k < num2; k++)
+ {
+ for (int l = 0; l < num; l++)
+ {
+ int num3 = k * num + l;
+ PieceIconData pieceIconData2 = m_pieceIcons[num3];
+ pieceIconData2.m_marker.SetActive(new Vector2Int(l, k) == selectedNr);
+ if (num3 < buildPieces.Count)
+ {
+ Piece piece = buildPieces[num3];
+ pieceIconData2.m_icon.sprite = piece.m_icon;
+ pieceIconData2.m_icon.enabled = true;
+ pieceIconData2.m_tooltip.m_text = piece.m_name;
+ pieceIconData2.m_upgrade.SetActive(piece.m_isUpgrade);
+ }
+ else
+ {
+ pieceIconData2.m_icon.enabled = false;
+ pieceIconData2.m_tooltip.m_text = "";
+ pieceIconData2.m_upgrade.SetActive(value: false);
+ }
+ }
+ }
+ UpdatePieceBuildStatus(buildPieces, player);
+ if (updateAllBuildStatuses)
+ {
+ UpdatePieceBuildStatusAll(buildPieces, player);
+ }
+ if (m_lastPieceCategory != category)
+ {
+ m_lastPieceCategory = category;
+ m_pieceBarPosX = m_pieceBarTargetPosX;
+ UpdatePieceBuildStatusAll(buildPieces, player);
+ }
+ }
+
+ private void OnLeftClickCategory(UIInputHandler ih)
+ {
+ for (int i = 0; i < m_pieceCategoryTabs.Length; i++)
+ {
+ if (m_pieceCategoryTabs[i] == ih.gameObject)
+ {
+ Player.m_localPlayer.SetBuildCategory(i);
+ break;
+ }
+ }
+ }
+
+ private void OnLeftClickPiece(UIInputHandler ih)
+ {
+ SelectPiece(ih);
+ HidePieceSelection();
+ }
+
+ private void OnRightClickPiece(UIInputHandler ih)
+ {
+ if (IsQuickPieceSelectEnabled())
+ {
+ SelectPiece(ih);
+ HidePieceSelection();
+ }
+ }
+
+ private void OnHoverPiece(UIInputHandler ih)
+ {
+ Vector2Int selectedGrid = GetSelectedGrid(ih);
+ if (selectedGrid.x != -1)
+ {
+ m_hoveredPiece = Player.m_localPlayer.GetPiece(selectedGrid);
+ }
+ }
+
+ private void OnHoverPieceExit(UIInputHandler ih)
+ {
+ m_hoveredPiece = null;
+ }
+
+ public bool IsQuickPieceSelectEnabled()
+ {
+ return PlayerPrefs.GetInt("QuickPieceSelect", 0) == 1;
+ }
+
+ private Vector2Int GetSelectedGrid(UIInputHandler ih)
+ {
+ int num = 10;
+ int num2 = 5;
+ for (int i = 0; i < num2; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ int index = i * num + j;
+ if (m_pieceIcons[index].m_go == ih.gameObject)
+ {
+ return new Vector2Int(j, i);
+ }
+ }
+ }
+ return new Vector2Int(-1, -1);
+ }
+
+ private void SelectPiece(UIInputHandler ih)
+ {
+ Vector2Int selectedGrid = GetSelectedGrid(ih);
+ if (selectedGrid.x != -1)
+ {
+ Player.m_localPlayer.SetSelectedPiece(selectedGrid);
+ m_selectItemEffect.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+
+ private void UpdatePieceBuildStatus(List<Piece> pieces, Player player)
+ {
+ if (m_pieceIcons.Count != 0)
+ {
+ if (m_pieceIconUpdateIndex >= m_pieceIcons.Count)
+ {
+ m_pieceIconUpdateIndex = 0;
+ }
+ PieceIconData pieceIconData = m_pieceIcons[m_pieceIconUpdateIndex];
+ if (m_pieceIconUpdateIndex < pieces.Count)
+ {
+ Piece piece = pieces[m_pieceIconUpdateIndex];
+ bool flag = player.HaveRequirements(piece, Player.RequirementMode.CanBuild);
+ pieceIconData.m_icon.color = (flag ? new Color(1f, 1f, 1f, 1f) : new Color(1f, 0f, 1f, 0f));
+ }
+ m_pieceIconUpdateIndex++;
+ }
+ }
+
+ private void UpdatePieceBuildStatusAll(List<Piece> pieces, Player player)
+ {
+ for (int i = 0; i < m_pieceIcons.Count; i++)
+ {
+ PieceIconData pieceIconData = m_pieceIcons[i];
+ if (i < pieces.Count)
+ {
+ Piece piece = pieces[i];
+ bool flag = player.HaveRequirements(piece, Player.RequirementMode.CanBuild);
+ pieceIconData.m_icon.color = (flag ? new Color(1f, 1f, 1f, 1f) : new Color(1f, 0f, 1f, 0f));
+ }
+ else
+ {
+ pieceIconData.m_icon.color = Color.white;
+ }
+ }
+ m_pieceIconUpdateIndex = 0;
+ }
+
+ private void UpdatePieceBar(float dt)
+ {
+ m_pieceBarPosX = Mathf.Lerp(m_pieceBarPosX, m_pieceBarTargetPosX, 0.1f);
+ Vector3 vector = m_pieceListRoot.anchoredPosition;
+ vector.x = Mathf.Round(m_pieceBarPosX);
+ }
+
+ public void TogglePieceSelection()
+ {
+ m_hoveredPiece = null;
+ if (m_pieceSelectionWindow.activeSelf)
+ {
+ m_pieceSelectionWindow.SetActive(value: false);
+ return;
+ }
+ m_pieceSelectionWindow.SetActive(value: true);
+ UpdateBuild(Player.m_localPlayer, forceUpdateAllBuildStatuses: true);
+ }
+
+ private void OnClosePieceSelection(UIInputHandler ih)
+ {
+ HidePieceSelection();
+ }
+
+ public static void HidePieceSelection()
+ {
+ if (!(m_instance == null))
+ {
+ m_instance.m_closePieceSelection = 2;
+ }
+ }
+
+ public static bool IsPieceSelectionVisible()
+ {
+ if (m_instance == null)
+ {
+ return false;
+ }
+ if (m_instance.m_buildHud.activeSelf)
+ {
+ return m_instance.m_pieceSelectionWindow.activeSelf;
+ }
+ return false;
+ }
+
+ private void UpdateBuild(Player player, bool forceUpdateAllBuildStatuses)
+ {
+ if (player.InPlaceMode())
+ {
+ if (m_closePieceSelection > 0)
+ {
+ m_closePieceSelection--;
+ if (m_closePieceSelection <= 0 && m_pieceSelectionWindow.activeSelf)
+ {
+ m_pieceSelectionWindow.SetActive(value: false);
+ }
+ }
+ player.GetBuildSelection(out var go, out var id, out var _, out var category, out var useCategory);
+ m_buildHud.SetActive(value: true);
+ if (m_pieceSelectionWindow.activeSelf)
+ {
+ UpdatePieceList(player, id, category, forceUpdateAllBuildStatuses);
+ m_pieceCategoryRoot.SetActive(useCategory);
+ if (useCategory)
+ {
+ for (int i = 0; i < m_pieceCategoryTabs.Length; i++)
+ {
+ GameObject gameObject = m_pieceCategoryTabs[i];
+ Transform transform = gameObject.transform.Find("Selected");
+ string text = m_buildCategoryNames[i] + " [<color=yellow>" + player.GetAvailableBuildPiecesInCategory((Piece.PieceCategory)i) + "</color>]";
+ if (i == (int)category)
+ {
+ transform.gameObject.SetActive(value: true);
+ transform.GetComponentInChildren<Text>().text = text;
+ }
+ else
+ {
+ transform.gameObject.SetActive(value: false);
+ gameObject.GetComponentInChildren<Text>().text = text;
+ }
+ }
+ }
+ }
+ if ((bool)m_hoveredPiece && (ZInput.IsGamepadActive() || !player.IsPieceAvailable(m_hoveredPiece)))
+ {
+ m_hoveredPiece = null;
+ }
+ if ((bool)m_hoveredPiece)
+ {
+ SetupPieceInfo(m_hoveredPiece);
+ }
+ else
+ {
+ SetupPieceInfo(go);
+ }
+ }
+ else
+ {
+ m_buildHud.SetActive(value: false);
+ m_pieceSelectionWindow.SetActive(value: false);
+ }
+ }
+
+ private void SetupPieceInfo(Piece piece)
+ {
+ if (piece == null)
+ {
+ m_buildSelection.text = Localization.instance.Localize("$hud_nothingtobuild");
+ m_pieceDescription.text = "";
+ m_buildIcon.enabled = false;
+ for (int i = 0; i < m_requirementItems.Length; i++)
+ {
+ m_requirementItems[i].SetActive(value: false);
+ }
+ return;
+ }
+ Player localPlayer = Player.m_localPlayer;
+ m_buildSelection.text = Localization.instance.Localize(piece.m_name);
+ m_pieceDescription.text = Localization.instance.Localize(piece.m_description);
+ m_buildIcon.enabled = true;
+ m_buildIcon.sprite = piece.m_icon;
+ for (int j = 0; j < m_requirementItems.Length; j++)
+ {
+ if (j < piece.m_resources.Length)
+ {
+ Piece.Requirement req = piece.m_resources[j];
+ m_requirementItems[j].SetActive(value: true);
+ InventoryGui.SetupRequirement(m_requirementItems[j].transform, req, localPlayer, craft: false, 0);
+ }
+ else
+ {
+ m_requirementItems[j].SetActive(value: false);
+ }
+ }
+ if ((bool)piece.m_craftingStation)
+ {
+ CraftingStation craftingStation = CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, localPlayer.transform.position);
+ GameObject obj = m_requirementItems[piece.m_resources.Length];
+ obj.SetActive(value: true);
+ Image component = obj.transform.Find("res_icon").GetComponent<Image>();
+ Text component2 = obj.transform.Find("res_name").GetComponent<Text>();
+ Text component3 = obj.transform.Find("res_amount").GetComponent<Text>();
+ UITooltip component4 = obj.GetComponent<UITooltip>();
+ component.sprite = piece.m_craftingStation.m_icon;
+ component2.text = Localization.instance.Localize(piece.m_craftingStation.m_name);
+ component4.m_text = piece.m_craftingStation.m_name;
+ if (craftingStation != null)
+ {
+ craftingStation.ShowAreaMarker();
+ component.color = Color.white;
+ component3.text = "";
+ component3.color = Color.white;
+ }
+ else
+ {
+ component.color = Color.gray;
+ component3.text = "None";
+ component3.color = ((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : Color.white);
+ }
+ }
+ }
+
+ private void UpdateGuardianPower(Player player)
+ {
+ player.GetGuardianPowerHUD(out var se, out var cooldown);
+ if ((bool)se)
+ {
+ m_gpRoot.gameObject.SetActive(value: true);
+ m_gpIcon.sprite = se.m_icon;
+ m_gpIcon.color = ((cooldown <= 0f) ? Color.white : new Color(1f, 0f, 1f, 0f));
+ m_gpName.text = Localization.instance.Localize(se.m_name);
+ if (cooldown > 0f)
+ {
+ m_gpCooldown.text = StatusEffect.GetTimeString(cooldown);
+ }
+ else
+ {
+ m_gpCooldown.text = Localization.instance.Localize("$hud_ready");
+ }
+ }
+ else
+ {
+ m_gpRoot.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void UpdateStatusEffects(List<StatusEffect> statusEffects)
+ {
+ if (m_statusEffects.Count != statusEffects.Count)
+ {
+ foreach (RectTransform statusEffect2 in m_statusEffects)
+ {
+ UnityEngine.Object.Destroy(statusEffect2.gameObject);
+ }
+ m_statusEffects.Clear();
+ for (int i = 0; i < statusEffects.Count; i++)
+ {
+ RectTransform rectTransform = UnityEngine.Object.Instantiate(m_statusEffectTemplate, m_statusEffectListRoot);
+ rectTransform.gameObject.SetActive(value: true);
+ rectTransform.anchoredPosition = new Vector3(-4f - (float)i * m_statusEffectSpacing, 0f, 0f);
+ m_statusEffects.Add(rectTransform);
+ }
+ }
+ for (int j = 0; j < statusEffects.Count; j++)
+ {
+ StatusEffect statusEffect = statusEffects[j];
+ RectTransform rectTransform2 = m_statusEffects[j];
+ Image component = rectTransform2.Find("Icon").GetComponent<Image>();
+ component.sprite = statusEffect.m_icon;
+ if (statusEffect.m_flashIcon)
+ {
+ component.color = ((Mathf.Sin(Time.time * 10f) > 0f) ? new Color(1f, 0.5f, 0.5f, 1f) : Color.white);
+ }
+ else
+ {
+ component.color = Color.white;
+ }
+ rectTransform2.Find("Cooldown").gameObject.SetActive(statusEffect.m_cooldownIcon);
+ rectTransform2.GetComponentInChildren<Text>().text = Localization.instance.Localize(statusEffect.m_name);
+ Text component2 = rectTransform2.Find("TimeText").GetComponent<Text>();
+ string iconText = statusEffect.GetIconText();
+ if (!string.IsNullOrEmpty(iconText))
+ {
+ component2.gameObject.SetActive(value: true);
+ component2.text = iconText;
+ }
+ else
+ {
+ component2.gameObject.SetActive(value: false);
+ }
+ if (statusEffect.m_isNew)
+ {
+ statusEffect.m_isNew = false;
+ rectTransform2.GetComponentInChildren<Animator>().SetTrigger("flash");
+ }
+ }
+ }
+
+ private void UpdateEvent(Player player)
+ {
+ RandomEvent activeEvent = RandEventSystem.instance.GetActiveEvent();
+ if (activeEvent != null && !EnemyHud.instance.ShowingBossHud() && activeEvent.GetTime() > 3f)
+ {
+ m_eventBar.SetActive(value: true);
+ m_eventName.text = Localization.instance.Localize(activeEvent.GetHudText());
+ }
+ else
+ {
+ m_eventBar.SetActive(value: false);
+ }
+ }
+
+ public void ToggleBetaTextVisible()
+ {
+ m_betaText.SetActive(!m_betaText.activeSelf);
+ }
+
+ public void FlashHealthBar()
+ {
+ m_healthAnimator.SetTrigger("Flash");
+ }
+
+ public void StaminaBarUppgradeFlash()
+ {
+ m_staminaAnimator.SetBool("Visible", value: true);
+ m_staminaAnimator.SetTrigger("Flash");
+ }
+
+ public void StaminaBarNoStaminaFlash()
+ {
+ if (!m_staminaAnimator.GetCurrentAnimatorStateInfo(0).IsTag("nostamina"))
+ {
+ m_staminaAnimator.SetBool("Visible", value: true);
+ m_staminaAnimator.SetTrigger("NoStamina");
+ }
+ }
+
+ public static bool IsUserHidden()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_userHidden;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Humanoid.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Humanoid.cs
new file mode 100644
index 0000000..501fe2b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Humanoid.cs
@@ -0,0 +1,1550 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Humanoid : Character
+{
+ [Serializable]
+ public class ItemSet
+ {
+ public string m_name = "";
+
+ public GameObject[] m_items = new GameObject[0];
+ }
+
+ private static List<ItemDrop.ItemData> optimalWeapons = new List<ItemDrop.ItemData>();
+
+ private static List<ItemDrop.ItemData> outofRangeWeapons = new List<ItemDrop.ItemData>();
+
+ private static List<ItemDrop.ItemData> allWeapons = new List<ItemDrop.ItemData>();
+
+ [Header("Humanoid")]
+ public float m_equipStaminaDrain = 10f;
+
+ public float m_blockStaminaDrain = 25f;
+
+ [Header("Default items")]
+ public GameObject[] m_defaultItems;
+
+ public GameObject[] m_randomWeapon;
+
+ public GameObject[] m_randomArmor;
+
+ public GameObject[] m_randomShield;
+
+ public ItemSet[] m_randomSets;
+
+ public ItemDrop m_unarmedWeapon;
+
+ [Header("Effects")]
+ public EffectList m_pickupEffects = new EffectList();
+
+ public EffectList m_dropEffects = new EffectList();
+
+ public EffectList m_consumeItemEffects = new EffectList();
+
+ public EffectList m_equipEffects = new EffectList();
+
+ public EffectList m_perfectBlockEffect = new EffectList();
+
+ protected Inventory m_inventory = new Inventory("Inventory", null, 8, 4);
+
+ protected ItemDrop.ItemData m_rightItem;
+
+ protected ItemDrop.ItemData m_leftItem;
+
+ protected ItemDrop.ItemData m_chestItem;
+
+ protected ItemDrop.ItemData m_legItem;
+
+ protected ItemDrop.ItemData m_ammoItem;
+
+ protected ItemDrop.ItemData m_helmetItem;
+
+ protected ItemDrop.ItemData m_shoulderItem;
+
+ protected ItemDrop.ItemData m_utilityItem;
+
+ protected string m_beardItem = "";
+
+ protected string m_hairItem = "";
+
+ private int m_lastEquipEffectFrame;
+
+ protected ItemDrop.ItemData m_hiddenLeftItem;
+
+ protected ItemDrop.ItemData m_hiddenRightItem;
+
+ protected Attack m_currentAttack;
+
+ protected Attack m_previousAttack;
+
+ private float m_timeSinceLastAttack;
+
+ private bool m_internalBlockingState;
+
+ private float m_blockTimer = 9999f;
+
+ private const float m_perfectBlockInterval = 0.25f;
+
+ protected float m_attackDrawTime;
+
+ protected float m_lastCombatTimer = 999f;
+
+ protected VisEquipment m_visEquipment;
+
+ private static int statef = 0;
+
+ private static int statei = 0;
+
+ private static int blocking = 0;
+
+ private static int isBlockingHash = 0;
+
+ private HashSet<StatusEffect> m_eqipmentStatusEffects = new HashSet<StatusEffect>();
+
+ protected static int m_animatorTagAttack = Animator.StringToHash("attack");
+
+ protected override void Awake()
+ {
+ base.Awake();
+ m_visEquipment = GetComponent<VisEquipment>();
+ if (statef == 0)
+ {
+ statef = ZSyncAnimation.GetHash("statef");
+ statei = ZSyncAnimation.GetHash("statei");
+ blocking = ZSyncAnimation.GetHash("blocking");
+ }
+ if (isBlockingHash == 0)
+ {
+ isBlockingHash = "IsBlocking".GetStableHashCode();
+ }
+ }
+
+ protected override void Start()
+ {
+ base.Start();
+ if (!IsPlayer())
+ {
+ GiveDefaultItems();
+ }
+ }
+
+ public void GiveDefaultItems()
+ {
+ GameObject[] defaultItems = m_defaultItems;
+ foreach (GameObject prefab in defaultItems)
+ {
+ GiveDefaultItem(prefab);
+ }
+ if (m_randomWeapon.Length == 0 && m_randomArmor.Length == 0 && m_randomShield.Length == 0 && m_randomSets.Length == 0)
+ {
+ return;
+ }
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(m_nview.GetZDO().m_uid.GetHashCode());
+ if (m_randomShield.Length != 0)
+ {
+ GameObject gameObject = m_randomShield[UnityEngine.Random.Range(0, m_randomShield.Length)];
+ if ((bool)gameObject)
+ {
+ GiveDefaultItem(gameObject);
+ }
+ }
+ if (m_randomWeapon.Length != 0)
+ {
+ GameObject gameObject2 = m_randomWeapon[UnityEngine.Random.Range(0, m_randomWeapon.Length)];
+ if ((bool)gameObject2)
+ {
+ GiveDefaultItem(gameObject2);
+ }
+ }
+ if (m_randomArmor.Length != 0)
+ {
+ GameObject gameObject3 = m_randomArmor[UnityEngine.Random.Range(0, m_randomArmor.Length)];
+ if ((bool)gameObject3)
+ {
+ GiveDefaultItem(gameObject3);
+ }
+ }
+ if (m_randomSets.Length != 0)
+ {
+ defaultItems = m_randomSets[UnityEngine.Random.Range(0, m_randomSets.Length)].m_items;
+ foreach (GameObject prefab2 in defaultItems)
+ {
+ GiveDefaultItem(prefab2);
+ }
+ }
+ UnityEngine.Random.state = state;
+ }
+
+ private void GiveDefaultItem(GameObject prefab)
+ {
+ ItemDrop.ItemData itemData = PickupPrefab(prefab);
+ if (itemData != null && !itemData.IsWeapon())
+ {
+ EquipItem(itemData, triggerEquipEffects: false);
+ }
+ }
+
+ protected override void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ if (m_nview == null || m_nview.IsOwner())
+ {
+ UpdateAttack(Time.fixedDeltaTime);
+ UpdateEquipment(Time.fixedDeltaTime);
+ UpdateBlock(Time.fixedDeltaTime);
+ }
+ base.FixedUpdate();
+ }
+ }
+
+ public override bool InAttack()
+ {
+ if (m_animator.IsInTransition(0))
+ {
+ if (m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagAttack)
+ {
+ return true;
+ }
+ if (m_animator.GetNextAnimatorStateInfo(0).tagHash == m_animatorTagAttack)
+ {
+ return true;
+ }
+ return false;
+ }
+ if (m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagAttack)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public override bool StartAttack(Character target, bool secondaryAttack)
+ {
+ AbortEquipQueue();
+ if ((InAttack() && !HaveQueuedChain()) || InDodge() || !CanMove() || IsKnockedBack() || IsStaggering() || InMinorAction())
+ {
+ return false;
+ }
+ ItemDrop.ItemData currentWeapon = GetCurrentWeapon();
+ if (currentWeapon == null)
+ {
+ return false;
+ }
+ if (m_currentAttack != null)
+ {
+ m_currentAttack.Stop();
+ m_previousAttack = m_currentAttack;
+ m_currentAttack = null;
+ }
+ Attack attack;
+ if (secondaryAttack)
+ {
+ if (!currentWeapon.HaveSecondaryAttack())
+ {
+ return false;
+ }
+ attack = currentWeapon.m_shared.m_secondaryAttack.Clone();
+ }
+ else
+ {
+ if (!currentWeapon.HavePrimaryAttack())
+ {
+ return false;
+ }
+ attack = currentWeapon.m_shared.m_attack.Clone();
+ }
+ if (attack.Start(this, m_body, m_zanim, m_animEvent, m_visEquipment, currentWeapon, m_previousAttack, m_timeSinceLastAttack, GetAttackDrawPercentage()))
+ {
+ m_currentAttack = attack;
+ m_lastCombatTimer = 0f;
+ return true;
+ }
+ return false;
+ }
+
+ public float GetAttackDrawPercentage()
+ {
+ ItemDrop.ItemData currentWeapon = GetCurrentWeapon();
+ if (currentWeapon != null && currentWeapon.m_shared.m_holdDurationMin > 0f && m_attackDrawTime > 0f)
+ {
+ float skillFactor = GetSkillFactor(currentWeapon.m_shared.m_skillType);
+ float num = currentWeapon.m_shared.m_holdDurationMin * (1f - skillFactor);
+ if (!(num > 0f))
+ {
+ return 1f;
+ }
+ return Mathf.Clamp01(m_attackDrawTime / num);
+ }
+ return 0f;
+ }
+
+ private void UpdateEquipment(float dt)
+ {
+ if (IsPlayer())
+ {
+ if (IsSwiming() && !IsOnGround())
+ {
+ HideHandItems();
+ }
+ if (m_rightItem != null && m_rightItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_rightItem, dt);
+ }
+ if (m_leftItem != null && m_leftItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_leftItem, dt);
+ }
+ if (m_chestItem != null && m_chestItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_chestItem, dt);
+ }
+ if (m_legItem != null && m_legItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_legItem, dt);
+ }
+ if (m_helmetItem != null && m_helmetItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_helmetItem, dt);
+ }
+ if (m_shoulderItem != null && m_shoulderItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_shoulderItem, dt);
+ }
+ if (m_utilityItem != null && m_utilityItem.m_shared.m_useDurability)
+ {
+ DrainEquipedItemDurability(m_utilityItem, dt);
+ }
+ }
+ }
+
+ private void DrainEquipedItemDurability(ItemDrop.ItemData item, float dt)
+ {
+ item.m_durability -= item.m_shared.m_durabilityDrain * dt;
+ if (item.m_durability <= 0f)
+ {
+ Message(MessageHud.MessageType.TopLeft, Localization.instance.Localize("$msg_broke", item.m_shared.m_name), 0, item.GetIcon());
+ UnequipItem(item, triggerEquipEffects: false);
+ if (item.m_shared.m_destroyBroken)
+ {
+ m_inventory.RemoveItem(item);
+ }
+ }
+ }
+
+ protected override void OnDamaged(HitData hit)
+ {
+ SetCrouch(crouch: false);
+ }
+
+ protected override void DamageArmorDurability(HitData hit)
+ {
+ List<ItemDrop.ItemData> list = new List<ItemDrop.ItemData>();
+ if (m_chestItem != null)
+ {
+ list.Add(m_chestItem);
+ }
+ if (m_legItem != null)
+ {
+ list.Add(m_legItem);
+ }
+ if (m_helmetItem != null)
+ {
+ list.Add(m_helmetItem);
+ }
+ if (m_shoulderItem != null)
+ {
+ list.Add(m_shoulderItem);
+ }
+ if (list.Count != 0)
+ {
+ float num = hit.GetTotalPhysicalDamage() + hit.GetTotalElementalDamage();
+ if (!(num <= 0f))
+ {
+ int index = UnityEngine.Random.Range(0, list.Count);
+ ItemDrop.ItemData itemData = list[index];
+ itemData.m_durability = Mathf.Max(0f, itemData.m_durability - num);
+ }
+ }
+ }
+
+ public ItemDrop.ItemData GetCurrentWeapon()
+ {
+ if (m_rightItem != null && m_rightItem.IsWeapon())
+ {
+ return m_rightItem;
+ }
+ if (m_leftItem != null && m_leftItem.IsWeapon() && m_leftItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Torch)
+ {
+ return m_leftItem;
+ }
+ if ((bool)m_unarmedWeapon)
+ {
+ return m_unarmedWeapon.m_itemData;
+ }
+ return null;
+ }
+
+ protected ItemDrop.ItemData GetCurrentBlocker()
+ {
+ if (m_leftItem != null)
+ {
+ return m_leftItem;
+ }
+ return GetCurrentWeapon();
+ }
+
+ private void UpdateAttack(float dt)
+ {
+ m_lastCombatTimer += dt;
+ if (GetCurrentWeapon() != null && m_currentAttack != null)
+ {
+ m_currentAttack.Update(dt);
+ }
+ if (InAttack())
+ {
+ m_timeSinceLastAttack = 0f;
+ }
+ else
+ {
+ m_timeSinceLastAttack += dt;
+ }
+ }
+
+ protected override float GetAttackSpeedFactorMovement()
+ {
+ if (InAttack() && m_currentAttack != null)
+ {
+ if (!IsFlying() && !IsOnGround())
+ {
+ return 1f;
+ }
+ return m_currentAttack.m_speedFactor;
+ }
+ return 1f;
+ }
+
+ protected override float GetAttackSpeedFactorRotation()
+ {
+ if (InAttack() && m_currentAttack != null)
+ {
+ return m_currentAttack.m_speedFactorRotation;
+ }
+ return 1f;
+ }
+
+ protected virtual bool HaveQueuedChain()
+ {
+ return false;
+ }
+
+ public override void OnWeaponTrailStart()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && GetCurrentWeapon() != null && m_currentAttack != null)
+ {
+ m_currentAttack.OnTrailStart();
+ }
+ }
+
+ public override void OnAttackTrigger()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && GetCurrentWeapon() != null && m_currentAttack != null)
+ {
+ m_currentAttack.OnAttackTrigger();
+ }
+ }
+
+ public override void OnStopMoving()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && InAttack() && GetCurrentWeapon() != null && m_currentAttack != null)
+ {
+ m_currentAttack.m_speedFactorRotation = 0f;
+ m_currentAttack.m_speedFactorRotation = 0f;
+ }
+ }
+
+ public virtual Vector3 GetAimDir(Vector3 fromPoint)
+ {
+ return GetLookDir();
+ }
+
+ public ItemDrop.ItemData PickupPrefab(GameObject prefab, int stackSize = 0)
+ {
+ ZNetView.m_forceDisableInit = true;
+ GameObject gameObject = UnityEngine.Object.Instantiate(prefab);
+ ZNetView.m_forceDisableInit = false;
+ if (stackSize > 0)
+ {
+ ItemDrop component = gameObject.GetComponent<ItemDrop>();
+ component.m_itemData.m_stack = Mathf.Clamp(stackSize, 1, component.m_itemData.m_shared.m_maxStackSize);
+ }
+ if (Pickup(gameObject))
+ {
+ return gameObject.GetComponent<ItemDrop>().m_itemData;
+ }
+ UnityEngine.Object.Destroy(gameObject);
+ return null;
+ }
+
+ public virtual bool HaveUniqueKey(string name)
+ {
+ return false;
+ }
+
+ public virtual void AddUniqueKey(string name)
+ {
+ }
+
+ public bool Pickup(GameObject go)
+ {
+ ItemDrop component = go.GetComponent<ItemDrop>();
+ if (component == null)
+ {
+ return false;
+ }
+ if (!component.CanPickup())
+ {
+ return false;
+ }
+ if (m_inventory.ContainsItem(component.m_itemData))
+ {
+ return false;
+ }
+ if (component.m_itemData.m_shared.m_questItem && HaveUniqueKey(component.m_itemData.m_shared.m_name))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_cantpickup");
+ return false;
+ }
+ bool flag = m_inventory.AddItem(component.m_itemData);
+ if (m_nview.GetZDO() == null)
+ {
+ UnityEngine.Object.Destroy(go);
+ return true;
+ }
+ if (!flag)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_noroom");
+ return false;
+ }
+ if (component.m_itemData.m_shared.m_questItem)
+ {
+ AddUniqueKey(component.m_itemData.m_shared.m_name);
+ }
+ ZNetScene.instance.Destroy(go);
+ if (flag && IsPlayer() && m_rightItem == null && m_hiddenRightItem == null && component.m_itemData.IsWeapon())
+ {
+ EquipItem(component.m_itemData);
+ }
+ m_pickupEffects.Create(base.transform.position, Quaternion.identity);
+ if (IsPlayer())
+ {
+ ShowPickupMessage(component.m_itemData, component.m_itemData.m_stack);
+ }
+ return flag;
+ }
+
+ public void EquipBestWeapon(Character targetCreature, StaticTarget targetStatic, Character hurtFriend, Character friend)
+ {
+ List<ItemDrop.ItemData> allItems = m_inventory.GetAllItems();
+ if (allItems.Count == 0 || InAttack())
+ {
+ return;
+ }
+ float num = 0f;
+ if ((bool)targetCreature)
+ {
+ float radius = targetCreature.GetRadius();
+ num = Vector3.Distance(targetCreature.transform.position, base.transform.position) - radius;
+ }
+ else if ((bool)targetStatic)
+ {
+ num = Vector3.Distance(targetStatic.transform.position, base.transform.position);
+ }
+ float time = Time.time;
+ IsFlying();
+ IsSwiming();
+ optimalWeapons.Clear();
+ outofRangeWeapons.Clear();
+ allWeapons.Clear();
+ foreach (ItemDrop.ItemData item in allItems)
+ {
+ if (!item.IsWeapon() || !BaseAI.CanUseAttack(this, item))
+ {
+ continue;
+ }
+ if (item.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Enemy)
+ {
+ if (num < item.m_shared.m_aiAttackRangeMin)
+ {
+ continue;
+ }
+ allWeapons.Add(item);
+ if ((targetCreature == null && targetStatic == null) || time - item.m_lastAttackTime < item.m_shared.m_aiAttackInterval)
+ {
+ continue;
+ }
+ if (num > item.m_shared.m_aiAttackRange)
+ {
+ outofRangeWeapons.Add(item);
+ continue;
+ }
+ if (item.m_shared.m_aiPrioritized)
+ {
+ EquipItem(item);
+ return;
+ }
+ optimalWeapons.Add(item);
+ }
+ else if (item.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt)
+ {
+ if (!(hurtFriend == null) && !(time - item.m_lastAttackTime < item.m_shared.m_aiAttackInterval))
+ {
+ if (item.m_shared.m_aiPrioritized)
+ {
+ EquipItem(item);
+ return;
+ }
+ optimalWeapons.Add(item);
+ }
+ }
+ else if (item.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Friend && !(friend == null) && !(time - item.m_lastAttackTime < item.m_shared.m_aiAttackInterval))
+ {
+ if (item.m_shared.m_aiPrioritized)
+ {
+ EquipItem(item);
+ return;
+ }
+ optimalWeapons.Add(item);
+ }
+ }
+ if (optimalWeapons.Count > 0)
+ {
+ EquipItem(optimalWeapons[UnityEngine.Random.Range(0, optimalWeapons.Count)]);
+ return;
+ }
+ if (outofRangeWeapons.Count > 0)
+ {
+ EquipItem(outofRangeWeapons[UnityEngine.Random.Range(0, outofRangeWeapons.Count)]);
+ return;
+ }
+ if (allWeapons.Count > 0)
+ {
+ EquipItem(allWeapons[UnityEngine.Random.Range(0, allWeapons.Count)]);
+ return;
+ }
+ ItemDrop.ItemData currentWeapon = GetCurrentWeapon();
+ if (currentWeapon != null)
+ {
+ UnequipItem(currentWeapon, triggerEquipEffects: false);
+ }
+ }
+
+ public bool DropItem(Inventory inventory, ItemDrop.ItemData item, int amount)
+ {
+ if (item.m_shared.m_questItem)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_cantdrop");
+ return false;
+ }
+ RemoveFromEquipQueue(item);
+ UnequipItem(item, triggerEquipEffects: false);
+ if (m_hiddenLeftItem == item)
+ {
+ m_hiddenLeftItem = null;
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ }
+ if (m_hiddenRightItem == item)
+ {
+ m_hiddenRightItem = null;
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ }
+ if (amount == item.m_stack)
+ {
+ ZLog.Log("drop all " + amount + " " + item.m_stack);
+ if (!inventory.RemoveItem(item))
+ {
+ ZLog.Log("Was not removed");
+ return false;
+ }
+ }
+ else
+ {
+ ZLog.Log("drop some " + amount + " " + item.m_stack);
+ inventory.RemoveItem(item, amount);
+ }
+ ItemDrop itemDrop = ItemDrop.DropItem(item, amount, base.transform.position + base.transform.forward + base.transform.up, base.transform.rotation);
+ if (IsPlayer())
+ {
+ itemDrop.OnPlayerDrop();
+ }
+ itemDrop.GetComponent<Rigidbody>().velocity = (base.transform.forward + Vector3.up) * 5f;
+ m_zanim.SetTrigger("interact");
+ m_dropEffects.Create(base.transform.position, Quaternion.identity);
+ Message(MessageHud.MessageType.TopLeft, "$msg_dropped " + itemDrop.m_itemData.m_shared.m_name, itemDrop.m_itemData.m_stack, itemDrop.m_itemData.GetIcon());
+ return true;
+ }
+
+ protected virtual void SetPlaceMode(PieceTable buildPieces)
+ {
+ }
+
+ public Inventory GetInventory()
+ {
+ return m_inventory;
+ }
+
+ public void UseItem(Inventory inventory, ItemDrop.ItemData item, bool fromInventoryGui)
+ {
+ if (inventory == null)
+ {
+ inventory = m_inventory;
+ }
+ if (!inventory.ContainsItem(item))
+ {
+ return;
+ }
+ GameObject hoverObject = GetHoverObject();
+ Hoverable hoverable = (hoverObject ? hoverObject.GetComponentInParent<Hoverable>() : null);
+ if (hoverable != null && !fromInventoryGui)
+ {
+ Interactable componentInParent = hoverObject.GetComponentInParent<Interactable>();
+ if (componentInParent != null && componentInParent.UseItem(this, item))
+ {
+ return;
+ }
+ }
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Consumable)
+ {
+ if (ConsumeItem(inventory, item))
+ {
+ m_consumeItemEffects.Create(Player.m_localPlayer.transform.position, Quaternion.identity);
+ m_zanim.SetTrigger("eat");
+ }
+ }
+ else if ((inventory != m_inventory || !ToggleEquiped(item)) && !fromInventoryGui)
+ {
+ if (hoverable != null)
+ {
+ Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_cantuseon", item.m_shared.m_name, hoverable.GetHoverName()));
+ }
+ else
+ {
+ Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_useonwhat", item.m_shared.m_name));
+ }
+ }
+ }
+
+ public virtual void AbortEquipQueue()
+ {
+ }
+
+ public virtual void RemoveFromEquipQueue(ItemDrop.ItemData item)
+ {
+ }
+
+ protected virtual bool ToggleEquiped(ItemDrop.ItemData item)
+ {
+ if (item.IsEquipable())
+ {
+ if (InAttack())
+ {
+ return true;
+ }
+ if (IsItemEquiped(item))
+ {
+ UnequipItem(item);
+ }
+ else
+ {
+ EquipItem(item);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public virtual bool CanConsumeItem(ItemDrop.ItemData item)
+ {
+ if (item.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Consumable)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public virtual bool ConsumeItem(Inventory inventory, ItemDrop.ItemData item)
+ {
+ CanConsumeItem(item);
+ return false;
+ }
+
+ public bool EquipItem(ItemDrop.ItemData item, bool triggerEquipEffects = true)
+ {
+ if (IsItemEquiped(item))
+ {
+ return false;
+ }
+ if (!m_inventory.ContainsItem(item))
+ {
+ return false;
+ }
+ if (InAttack() || InDodge())
+ {
+ return false;
+ }
+ if (IsPlayer() && !IsDead() && IsSwiming() && !IsOnGround())
+ {
+ return false;
+ }
+ if (item.m_shared.m_useDurability && item.m_durability <= 0f)
+ {
+ return false;
+ }
+ if (item.m_shared.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(item.m_shared.m_dlc))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_dlcrequired");
+ return false;
+ }
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Tool)
+ {
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ m_rightItem = item;
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Torch)
+ {
+ if (m_rightItem != null && m_leftItem == null && m_rightItem.m_shared.m_itemType == ItemDrop.ItemData.ItemType.OneHandedWeapon)
+ {
+ m_leftItem = item;
+ }
+ else
+ {
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ if (m_leftItem != null && m_leftItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Shield)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ }
+ m_rightItem = item;
+ }
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.OneHandedWeapon)
+ {
+ if (m_rightItem != null && m_rightItem.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Torch && m_leftItem == null)
+ {
+ ItemDrop.ItemData rightItem = m_rightItem;
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ m_leftItem = rightItem;
+ m_leftItem.m_equiped = true;
+ }
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ if (m_leftItem != null && m_leftItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Shield && m_leftItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Torch)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ }
+ m_rightItem = item;
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Shield)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ if (m_rightItem != null && m_rightItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.OneHandedWeapon && m_rightItem.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Torch)
+ {
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ }
+ m_leftItem = item;
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Bow)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ m_leftItem = item;
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.TwoHandedWeapon)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects);
+ UnequipItem(m_rightItem, triggerEquipEffects);
+ m_rightItem = item;
+ m_hiddenRightItem = null;
+ m_hiddenLeftItem = null;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Chest)
+ {
+ UnequipItem(m_chestItem, triggerEquipEffects);
+ m_chestItem = item;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Legs)
+ {
+ UnequipItem(m_legItem, triggerEquipEffects);
+ m_legItem = item;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Ammo)
+ {
+ UnequipItem(m_ammoItem, triggerEquipEffects);
+ m_ammoItem = item;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Helmet)
+ {
+ UnequipItem(m_helmetItem, triggerEquipEffects);
+ m_helmetItem = item;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Shoulder)
+ {
+ UnequipItem(m_shoulderItem, triggerEquipEffects);
+ m_shoulderItem = item;
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Utility)
+ {
+ UnequipItem(m_utilityItem, triggerEquipEffects);
+ m_utilityItem = item;
+ }
+ if (IsItemEquiped(item))
+ {
+ item.m_equiped = true;
+ }
+ SetupEquipment();
+ if (triggerEquipEffects)
+ {
+ TriggerEquipEffect(item);
+ }
+ return true;
+ }
+
+ public void UnequipItem(ItemDrop.ItemData item, bool triggerEquipEffects = true)
+ {
+ if (item == null)
+ {
+ return;
+ }
+ if (m_hiddenLeftItem == item)
+ {
+ m_hiddenLeftItem = null;
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ }
+ if (m_hiddenRightItem == item)
+ {
+ m_hiddenRightItem = null;
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ }
+ if (!IsItemEquiped(item))
+ {
+ return;
+ }
+ if (item.IsWeapon())
+ {
+ if (m_currentAttack != null && m_currentAttack.GetWeapon() == item)
+ {
+ m_currentAttack.Stop();
+ m_previousAttack = m_currentAttack;
+ m_currentAttack = null;
+ }
+ if (!string.IsNullOrEmpty(item.m_shared.m_holdAnimationState))
+ {
+ m_zanim.SetBool(item.m_shared.m_holdAnimationState, value: false);
+ }
+ m_attackDrawTime = 0f;
+ }
+ if (m_rightItem == item)
+ {
+ m_rightItem = null;
+ }
+ else if (m_leftItem == item)
+ {
+ m_leftItem = null;
+ }
+ else if (m_chestItem == item)
+ {
+ m_chestItem = null;
+ }
+ else if (m_legItem == item)
+ {
+ m_legItem = null;
+ }
+ else if (m_ammoItem == item)
+ {
+ m_ammoItem = null;
+ }
+ else if (m_helmetItem == item)
+ {
+ m_helmetItem = null;
+ }
+ else if (m_shoulderItem == item)
+ {
+ m_shoulderItem = null;
+ }
+ else if (m_utilityItem == item)
+ {
+ m_utilityItem = null;
+ }
+ item.m_equiped = false;
+ SetupEquipment();
+ if (triggerEquipEffects)
+ {
+ TriggerEquipEffect(item);
+ }
+ }
+
+ private void TriggerEquipEffect(ItemDrop.ItemData item)
+ {
+ if (m_nview.GetZDO() != null && Time.frameCount != m_lastEquipEffectFrame)
+ {
+ m_lastEquipEffectFrame = Time.frameCount;
+ m_equipEffects.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+
+ public void UnequipAllItems()
+ {
+ if (m_rightItem != null)
+ {
+ UnequipItem(m_rightItem, triggerEquipEffects: false);
+ }
+ if (m_leftItem != null)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects: false);
+ }
+ if (m_chestItem != null)
+ {
+ UnequipItem(m_chestItem, triggerEquipEffects: false);
+ }
+ if (m_legItem != null)
+ {
+ UnequipItem(m_legItem, triggerEquipEffects: false);
+ }
+ if (m_helmetItem != null)
+ {
+ UnequipItem(m_helmetItem, triggerEquipEffects: false);
+ }
+ if (m_ammoItem != null)
+ {
+ UnequipItem(m_ammoItem, triggerEquipEffects: false);
+ }
+ if (m_shoulderItem != null)
+ {
+ UnequipItem(m_shoulderItem, triggerEquipEffects: false);
+ }
+ if (m_utilityItem != null)
+ {
+ UnequipItem(m_utilityItem, triggerEquipEffects: false);
+ }
+ }
+
+ protected override void OnRagdollCreated(Ragdoll ragdoll)
+ {
+ VisEquipment component = ragdoll.GetComponent<VisEquipment>();
+ if ((bool)component)
+ {
+ SetupVisEquipment(component, isRagdoll: true);
+ }
+ }
+
+ protected virtual void SetupVisEquipment(VisEquipment visEq, bool isRagdoll)
+ {
+ if (!isRagdoll)
+ {
+ visEq.SetLeftItem((m_leftItem != null) ? m_leftItem.m_dropPrefab.name : "", (m_leftItem != null) ? m_leftItem.m_variant : 0);
+ visEq.SetRightItem((m_rightItem != null) ? m_rightItem.m_dropPrefab.name : "");
+ if (IsPlayer())
+ {
+ visEq.SetLeftBackItem((m_hiddenLeftItem != null) ? m_hiddenLeftItem.m_dropPrefab.name : "", (m_hiddenLeftItem != null) ? m_hiddenLeftItem.m_variant : 0);
+ visEq.SetRightBackItem((m_hiddenRightItem != null) ? m_hiddenRightItem.m_dropPrefab.name : "");
+ }
+ }
+ visEq.SetChestItem((m_chestItem != null) ? m_chestItem.m_dropPrefab.name : "");
+ visEq.SetLegItem((m_legItem != null) ? m_legItem.m_dropPrefab.name : "");
+ visEq.SetHelmetItem((m_helmetItem != null) ? m_helmetItem.m_dropPrefab.name : "");
+ visEq.SetShoulderItem((m_shoulderItem != null) ? m_shoulderItem.m_dropPrefab.name : "", (m_shoulderItem != null) ? m_shoulderItem.m_variant : 0);
+ visEq.SetUtilityItem((m_utilityItem != null) ? m_utilityItem.m_dropPrefab.name : "");
+ if (IsPlayer())
+ {
+ visEq.SetBeardItem(m_beardItem);
+ visEq.SetHairItem(m_hairItem);
+ }
+ }
+
+ private void SetupEquipment()
+ {
+ if ((bool)m_visEquipment && (m_nview.GetZDO() == null || m_nview.IsOwner()))
+ {
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ }
+ if (m_nview.GetZDO() != null)
+ {
+ UpdateEquipmentStatusEffects();
+ if (m_rightItem != null && (bool)m_rightItem.m_shared.m_buildPieces)
+ {
+ SetPlaceMode(m_rightItem.m_shared.m_buildPieces);
+ }
+ else
+ {
+ SetPlaceMode(null);
+ }
+ SetupAnimationState();
+ }
+ }
+
+ private void SetupAnimationState()
+ {
+ if (m_leftItem != null)
+ {
+ if (m_leftItem.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Torch)
+ {
+ SetAnimationState(ItemDrop.ItemData.AnimationState.LeftTorch);
+ }
+ else
+ {
+ SetAnimationState(m_leftItem.m_shared.m_animationState);
+ }
+ }
+ else if (m_rightItem != null)
+ {
+ SetAnimationState(m_rightItem.m_shared.m_animationState);
+ }
+ else if (m_unarmedWeapon != null)
+ {
+ SetAnimationState(m_unarmedWeapon.m_itemData.m_shared.m_animationState);
+ }
+ }
+
+ private void SetAnimationState(ItemDrop.ItemData.AnimationState state)
+ {
+ m_zanim.SetFloat(statef, (float)state);
+ m_zanim.SetInt(statei, (int)state);
+ }
+
+ public bool IsSitting()
+ {
+ return m_animator.GetCurrentAnimatorStateInfo(0).tagHash == Character.m_animatorTagSitting;
+ }
+
+ private void UpdateEquipmentStatusEffects()
+ {
+ HashSet<StatusEffect> hashSet = new HashSet<StatusEffect>();
+ if (m_leftItem != null && (bool)m_leftItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_leftItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_rightItem != null && (bool)m_rightItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_rightItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_chestItem != null && (bool)m_chestItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_chestItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_legItem != null && (bool)m_legItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_legItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_helmetItem != null && (bool)m_helmetItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_helmetItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_shoulderItem != null && (bool)m_shoulderItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_shoulderItem.m_shared.m_equipStatusEffect);
+ }
+ if (m_utilityItem != null && (bool)m_utilityItem.m_shared.m_equipStatusEffect)
+ {
+ hashSet.Add(m_utilityItem.m_shared.m_equipStatusEffect);
+ }
+ if (HaveSetEffect(m_leftItem))
+ {
+ hashSet.Add(m_leftItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_rightItem))
+ {
+ hashSet.Add(m_rightItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_chestItem))
+ {
+ hashSet.Add(m_chestItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_legItem))
+ {
+ hashSet.Add(m_legItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_helmetItem))
+ {
+ hashSet.Add(m_helmetItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_shoulderItem))
+ {
+ hashSet.Add(m_shoulderItem.m_shared.m_setStatusEffect);
+ }
+ if (HaveSetEffect(m_utilityItem))
+ {
+ hashSet.Add(m_utilityItem.m_shared.m_setStatusEffect);
+ }
+ foreach (StatusEffect eqipmentStatusEffect in m_eqipmentStatusEffects)
+ {
+ if (!hashSet.Contains(eqipmentStatusEffect))
+ {
+ m_seman.RemoveStatusEffect(eqipmentStatusEffect.name);
+ }
+ }
+ foreach (StatusEffect item in hashSet)
+ {
+ if (!m_eqipmentStatusEffects.Contains(item))
+ {
+ m_seman.AddStatusEffect(item);
+ }
+ }
+ m_eqipmentStatusEffects.Clear();
+ m_eqipmentStatusEffects.UnionWith(hashSet);
+ }
+
+ private bool HaveSetEffect(ItemDrop.ItemData item)
+ {
+ if (item == null)
+ {
+ return false;
+ }
+ if (item.m_shared.m_setStatusEffect == null || item.m_shared.m_setName.Length == 0 || item.m_shared.m_setSize <= 1)
+ {
+ return false;
+ }
+ if (GetSetCount(item.m_shared.m_setName) >= item.m_shared.m_setSize)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private int GetSetCount(string setName)
+ {
+ int num = 0;
+ if (m_leftItem != null && m_leftItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_rightItem != null && m_rightItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_chestItem != null && m_chestItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_legItem != null && m_legItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_helmetItem != null && m_helmetItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_shoulderItem != null && m_shoulderItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ if (m_utilityItem != null && m_utilityItem.m_shared.m_setName == setName)
+ {
+ num++;
+ }
+ return num;
+ }
+
+ public void SetBeard(string name)
+ {
+ m_beardItem = name;
+ SetupEquipment();
+ }
+
+ public string GetBeard()
+ {
+ return m_beardItem;
+ }
+
+ public void SetHair(string hair)
+ {
+ m_hairItem = hair;
+ SetupEquipment();
+ }
+
+ public string GetHair()
+ {
+ return m_hairItem;
+ }
+
+ public bool IsItemEquiped(ItemDrop.ItemData item)
+ {
+ if (m_rightItem == item)
+ {
+ return true;
+ }
+ if (m_leftItem == item)
+ {
+ return true;
+ }
+ if (m_chestItem == item)
+ {
+ return true;
+ }
+ if (m_legItem == item)
+ {
+ return true;
+ }
+ if (m_ammoItem == item)
+ {
+ return true;
+ }
+ if (m_helmetItem == item)
+ {
+ return true;
+ }
+ if (m_shoulderItem == item)
+ {
+ return true;
+ }
+ if (m_utilityItem == item)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public ItemDrop.ItemData GetRightItem()
+ {
+ return m_rightItem;
+ }
+
+ public ItemDrop.ItemData GetLeftItem()
+ {
+ return m_leftItem;
+ }
+
+ protected override bool CheckRun(Vector3 moveDir, float dt)
+ {
+ if (IsHoldingAttack())
+ {
+ return false;
+ }
+ if (IsBlocking())
+ {
+ return false;
+ }
+ return base.CheckRun(moveDir, dt);
+ }
+
+ public override bool IsHoldingAttack()
+ {
+ ItemDrop.ItemData currentWeapon = GetCurrentWeapon();
+ if (currentWeapon != null && currentWeapon.m_shared.m_holdDurationMin > 0f && m_attackDrawTime > 0f)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ protected override bool BlockAttack(HitData hit, Character attacker)
+ {
+ if (Vector3.Dot(hit.m_dir, base.transform.forward) > 0f)
+ {
+ return false;
+ }
+ ItemDrop.ItemData currentBlocker = GetCurrentBlocker();
+ if (currentBlocker == null)
+ {
+ return false;
+ }
+ bool flag = currentBlocker.m_shared.m_timedBlockBonus > 1f && m_blockTimer != -1f && m_blockTimer < 0.25f;
+ float skillFactor = GetSkillFactor(Skills.SkillType.Blocking);
+ float num = currentBlocker.GetBlockPower(skillFactor);
+ if (flag)
+ {
+ num *= currentBlocker.m_shared.m_timedBlockBonus;
+ }
+ float totalBlockableDamage = hit.GetTotalBlockableDamage();
+ float num2 = Mathf.Min(totalBlockableDamage, num);
+ float num3 = Mathf.Clamp01(num2 / num);
+ float stamina = m_blockStaminaDrain * num3;
+ UseStamina(stamina);
+ bool num4 = HaveStamina();
+ bool flag2 = num4 && num >= totalBlockableDamage;
+ if (num4)
+ {
+ hit.m_statusEffect = "";
+ hit.BlockDamage(num2);
+ DamageText.instance.ShowText(DamageText.TextType.Blocked, hit.m_point + Vector3.up * 0.5f, num2);
+ }
+ if (!num4 || !flag2)
+ {
+ Stagger(hit.m_dir);
+ }
+ if (currentBlocker.m_shared.m_useDurability)
+ {
+ float num5 = currentBlocker.m_shared.m_useDurabilityDrain * num3;
+ currentBlocker.m_durability -= num5;
+ }
+ RaiseSkill(Skills.SkillType.Blocking, flag ? 2f : 1f);
+ currentBlocker.m_shared.m_blockEffect.Create(hit.m_point, Quaternion.identity);
+ if ((bool)attacker && flag && flag2)
+ {
+ m_perfectBlockEffect.Create(hit.m_point, Quaternion.identity);
+ if (attacker.m_staggerWhenBlocked)
+ {
+ attacker.Stagger(-hit.m_dir);
+ }
+ }
+ if (flag2)
+ {
+ float num6 = Mathf.Clamp01(num3 * 0.5f);
+ hit.m_pushForce *= num6;
+ if ((bool)attacker && flag)
+ {
+ HitData hitData = new HitData();
+ hitData.m_pushForce = currentBlocker.GetDeflectionForce() * (1f - num6);
+ hitData.m_dir = attacker.transform.position - base.transform.position;
+ hitData.m_dir.y = 0f;
+ hitData.m_dir.Normalize();
+ attacker.Damage(hitData);
+ }
+ }
+ return true;
+ }
+
+ public override bool IsBlocking()
+ {
+ if (m_nview.IsValid() && !m_nview.IsOwner())
+ {
+ return m_nview.GetZDO().GetBool(isBlockingHash);
+ }
+ if (m_blocking && !InAttack() && !InDodge() && !InPlaceMode() && !IsEncumbered())
+ {
+ return !InMinorAction();
+ }
+ return false;
+ }
+
+ private void UpdateBlock(float dt)
+ {
+ if (IsBlocking())
+ {
+ if (!m_internalBlockingState)
+ {
+ m_internalBlockingState = true;
+ m_nview.GetZDO().Set(isBlockingHash, value: true);
+ m_zanim.SetBool(blocking, value: true);
+ }
+ if (m_blockTimer < 0f)
+ {
+ m_blockTimer = 0f;
+ }
+ else
+ {
+ m_blockTimer += dt;
+ }
+ }
+ else
+ {
+ if (m_internalBlockingState)
+ {
+ m_internalBlockingState = false;
+ m_nview.GetZDO().Set(isBlockingHash, value: false);
+ m_zanim.SetBool(blocking, value: false);
+ }
+ m_blockTimer = -1f;
+ }
+ }
+
+ public void HideHandItems()
+ {
+ if (m_leftItem != null || m_rightItem != null)
+ {
+ ItemDrop.ItemData leftItem = m_leftItem;
+ ItemDrop.ItemData rightItem = m_rightItem;
+ UnequipItem(m_leftItem);
+ UnequipItem(m_rightItem);
+ m_hiddenLeftItem = leftItem;
+ m_hiddenRightItem = rightItem;
+ SetupVisEquipment(m_visEquipment, isRagdoll: false);
+ m_zanim.SetTrigger("equip_hip");
+ }
+ }
+
+ public void ShowHandItems()
+ {
+ ItemDrop.ItemData hiddenLeftItem = m_hiddenLeftItem;
+ ItemDrop.ItemData hiddenRightItem = m_hiddenRightItem;
+ if (hiddenLeftItem != null || hiddenRightItem != null)
+ {
+ m_hiddenLeftItem = null;
+ m_hiddenRightItem = null;
+ if (hiddenLeftItem != null)
+ {
+ EquipItem(hiddenLeftItem);
+ }
+ if (hiddenRightItem != null)
+ {
+ EquipItem(hiddenRightItem);
+ }
+ m_zanim.SetTrigger("equip_hip");
+ }
+ }
+
+ public ItemDrop.ItemData GetAmmoItem()
+ {
+ return m_ammoItem;
+ }
+
+ public virtual GameObject GetHoverObject()
+ {
+ return null;
+ }
+
+ public bool IsTeleportable()
+ {
+ return m_inventory.IsTeleportable();
+ }
+
+ public override bool UseMeleeCamera()
+ {
+ return GetCurrentWeapon()?.m_shared.m_centerCamera ?? false;
+ }
+
+ public float GetEquipmentWeight()
+ {
+ float num = 0f;
+ if (m_rightItem != null)
+ {
+ num += m_rightItem.m_shared.m_weight;
+ }
+ if (m_leftItem != null)
+ {
+ num += m_leftItem.m_shared.m_weight;
+ }
+ if (m_chestItem != null)
+ {
+ num += m_chestItem.m_shared.m_weight;
+ }
+ if (m_legItem != null)
+ {
+ num += m_legItem.m_shared.m_weight;
+ }
+ if (m_helmetItem != null)
+ {
+ num += m_helmetItem.m_shared.m_weight;
+ }
+ if (m_shoulderItem != null)
+ {
+ num += m_shoulderItem.m_shared.m_weight;
+ }
+ if (m_utilityItem != null)
+ {
+ num += m_utilityItem.m_shared.m_weight;
+ }
+ return num;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IDestructible.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IDestructible.cs
new file mode 100644
index 0000000..6d82fb1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IDestructible.cs
@@ -0,0 +1,6 @@
+public interface IDestructible
+{
+ void Damage(HitData hit);
+
+ DestructibleType GetDestructibleType();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IEquipmentVisual.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IEquipmentVisual.cs
new file mode 100644
index 0000000..7d4b4c2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IEquipmentVisual.cs
@@ -0,0 +1,4 @@
+internal interface IEquipmentVisual
+{
+ void Setup(int style);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IProjectile.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IProjectile.cs
new file mode 100644
index 0000000..81f27cf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IProjectile.cs
@@ -0,0 +1,8 @@
+using UnityEngine;
+
+public interface IProjectile
+{
+ void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemDrop.ItemData item);
+
+ string GetTooltipString(int itemQuality);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ISocket.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ISocket.cs
new file mode 100644
index 0000000..f6ca9b7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ISocket.cs
@@ -0,0 +1,30 @@
+public interface ISocket
+{
+ bool IsConnected();
+
+ void Send(ZPackage pkg);
+
+ ZPackage Recv();
+
+ bool IsSending();
+
+ bool IsHost();
+
+ void Dispose();
+
+ bool GotNewData();
+
+ void Close();
+
+ string GetEndPointString();
+
+ void GetAndResetStats(out int totalSent, out int totalRecv);
+
+ ISocket Accept();
+
+ int GetHostPort();
+
+ bool Flush();
+
+ string GetHostName();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IWaterInteractable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IWaterInteractable.cs
new file mode 100644
index 0000000..02008ce
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/IWaterInteractable.cs
@@ -0,0 +1,10 @@
+using UnityEngine;
+
+public interface IWaterInteractable
+{
+ bool IsOwner();
+
+ void SetInWater(float waterLevel);
+
+ Transform GetTransform();
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ImpactEffect.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ImpactEffect.cs
new file mode 100644
index 0000000..4beca90
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ImpactEffect.cs
@@ -0,0 +1,159 @@
+using UnityEngine;
+
+public class ImpactEffect : MonoBehaviour
+{
+ public EffectList m_hitEffect = new EffectList();
+
+ public EffectList m_destroyEffect = new EffectList();
+
+ public float m_hitDestroyChance;
+
+ public float m_minVelocity;
+
+ public float m_maxVelocity;
+
+ public bool m_damageToSelf;
+
+ public bool m_damagePlayers = true;
+
+ public bool m_damageFish;
+
+ public int m_toolTier;
+
+ public HitData.DamageTypes m_damages;
+
+ public LayerMask m_triggerMask;
+
+ public float m_interval = 0.5f;
+
+ private bool m_firstHit = true;
+
+ private bool m_hitEffectEnabled = true;
+
+ private ZNetView m_nview;
+
+ private Rigidbody m_body;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ if (m_maxVelocity < m_minVelocity)
+ {
+ m_maxVelocity = m_minVelocity;
+ }
+ }
+
+ public void OnCollisionEnter(Collision info)
+ {
+ if (!m_nview.IsValid() || ((bool)m_nview && !m_nview.IsOwner()) || info.contacts.Length == 0 || !m_hitEffectEnabled || (m_triggerMask.value & (1 << info.collider.gameObject.layer)) == 0)
+ {
+ return;
+ }
+ float magnitude = info.relativeVelocity.magnitude;
+ if (magnitude < m_minVelocity)
+ {
+ return;
+ }
+ ContactPoint contactPoint = info.contacts[0];
+ Vector3 point = contactPoint.point;
+ Vector3 pointVelocity = m_body.GetPointVelocity(point);
+ m_hitEffectEnabled = false;
+ Invoke("ResetHitTimer", m_interval);
+ if (m_damages.HaveDamage())
+ {
+ GameObject gameObject = Projectile.FindHitObject(contactPoint.otherCollider);
+ float num = (num = Utils.LerpStep(m_minVelocity, m_maxVelocity, magnitude));
+ IDestructible component = gameObject.GetComponent<IDestructible>();
+ if (component != null)
+ {
+ Character character = component as Character;
+ if ((bool)character)
+ {
+ if (!m_damagePlayers && character.IsPlayer())
+ {
+ return;
+ }
+ float num2 = Vector3.Dot(-info.relativeVelocity.normalized, pointVelocity);
+ if (num2 < m_minVelocity)
+ {
+ return;
+ }
+ ZLog.Log("Rel vel " + num2);
+ num = Utils.LerpStep(m_minVelocity, m_maxVelocity, num2);
+ if (character.GetSEMan().HaveStatusAttribute(StatusEffect.StatusAttribute.DoubleImpactDamage))
+ {
+ num *= 2f;
+ }
+ }
+ if (!m_damageFish && (bool)gameObject.GetComponent<Fish>())
+ {
+ return;
+ }
+ HitData hitData = new HitData();
+ hitData.m_point = point;
+ hitData.m_dir = pointVelocity.normalized;
+ hitData.m_hitCollider = info.collider;
+ hitData.m_toolTier = m_toolTier;
+ hitData.m_damage = m_damages.Clone();
+ hitData.m_damage.Modify(num);
+ component.Damage(hitData);
+ }
+ if (m_damageToSelf)
+ {
+ IDestructible component2 = GetComponent<IDestructible>();
+ if (component2 != null)
+ {
+ HitData hitData2 = new HitData();
+ hitData2.m_point = point;
+ hitData2.m_dir = -pointVelocity.normalized;
+ hitData2.m_toolTier = m_toolTier;
+ hitData2.m_damage = m_damages.Clone();
+ hitData2.m_damage.Modify(num);
+ component2.Damage(hitData2);
+ }
+ }
+ }
+ Vector3 rhs = Vector3.Cross(-Vector3.Normalize(info.relativeVelocity), contactPoint.normal);
+ Vector3 vector = Vector3.Cross(contactPoint.normal, rhs);
+ Quaternion rot = Quaternion.identity;
+ if (vector != Vector3.zero && contactPoint.normal != Vector3.zero)
+ {
+ rot = Quaternion.LookRotation(vector, contactPoint.normal);
+ }
+ m_hitEffect.Create(point, rot);
+ if (m_firstHit && m_hitDestroyChance > 0f && Random.value <= m_hitDestroyChance)
+ {
+ m_destroyEffect.Create(point, rot);
+ GameObject obj = base.gameObject;
+ if ((bool)base.transform.parent)
+ {
+ Animator componentInParent = base.transform.GetComponentInParent<Animator>();
+ if ((bool)componentInParent)
+ {
+ obj = componentInParent.gameObject;
+ }
+ }
+ Object.Destroy(obj);
+ }
+ m_firstHit = false;
+ }
+
+ private Vector3 GetAVGPos(ContactPoint[] points)
+ {
+ ZLog.Log("Pooints " + points.Length);
+ Vector3 zero = Vector3.zero;
+ for (int i = 0; i < points.Length; i++)
+ {
+ ContactPoint contactPoint = points[i];
+ ZLog.Log("P " + contactPoint.otherCollider.gameObject.name);
+ zero += contactPoint.point;
+ }
+ return zero;
+ }
+
+ private void ResetHitTimer()
+ {
+ m_hitEffectEnabled = true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InputFieldSubmit.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InputFieldSubmit.cs
new file mode 100644
index 0000000..1a8ac47
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InputFieldSubmit.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class InputFieldSubmit : MonoBehaviour
+{
+ public Action<string> m_onSubmit;
+
+ private InputField m_field;
+
+ private void Awake()
+ {
+ m_field = GetComponent<InputField>();
+ }
+
+ private void Update()
+ {
+ if (m_field.text != "" && Input.GetKey(KeyCode.Return))
+ {
+ m_onSubmit(m_field.text);
+ m_field.text = "";
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstanceRenderer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstanceRenderer.cs
new file mode 100644
index 0000000..3ced0a9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstanceRenderer.cs
@@ -0,0 +1,176 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+public class InstanceRenderer : MonoBehaviour
+{
+ public Mesh m_mesh;
+
+ public Material m_material;
+
+ public Vector3 m_scale = Vector3.one;
+
+ public bool m_frustumCull = true;
+
+ private bool m_dirtyBounds = true;
+
+ private BoundingSphere m_bounds;
+
+ public bool m_useLod;
+
+ public bool m_useXZLodDistance = true;
+
+ public float m_lodMinDistance = 5f;
+
+ public float m_lodMaxDistance = 20f;
+
+ public ShadowCastingMode m_shadowCasting;
+
+ private float m_lodCount;
+
+ private Matrix4x4[] m_instances = new Matrix4x4[1024];
+
+ private int m_instanceCount;
+
+ private bool m_firstFrame = true;
+
+ private void Update()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (m_instanceCount == 0 || mainCamera == null)
+ {
+ return;
+ }
+ if (m_frustumCull)
+ {
+ if (m_dirtyBounds)
+ {
+ UpdateBounds();
+ }
+ if (!Utils.InsideMainCamera(m_bounds))
+ {
+ return;
+ }
+ }
+ if (m_useLod)
+ {
+ float num = (m_useXZLodDistance ? Utils.DistanceXZ(mainCamera.transform.position, base.transform.position) : Vector3.Distance(mainCamera.transform.position, base.transform.position));
+ int num2 = (int)((1f - Utils.LerpStep(m_lodMinDistance, m_lodMaxDistance, num)) * (float)m_instanceCount);
+ float maxDelta = Time.deltaTime * (float)m_instanceCount;
+ m_lodCount = Mathf.MoveTowards(m_lodCount, num2, maxDelta);
+ if (m_firstFrame)
+ {
+ if (num < m_lodMinDistance)
+ {
+ m_lodCount = num2;
+ }
+ m_firstFrame = false;
+ }
+ m_lodCount = Mathf.Min(m_lodCount, m_instanceCount);
+ int num3 = (int)m_lodCount;
+ if (num3 > 0)
+ {
+ Graphics.DrawMeshInstanced(m_mesh, 0, m_material, m_instances, num3, null, m_shadowCasting);
+ }
+ }
+ else
+ {
+ Graphics.DrawMeshInstanced(m_mesh, 0, m_material, m_instances, m_instanceCount, null, m_shadowCasting);
+ }
+ }
+
+ private void UpdateBounds()
+ {
+ m_dirtyBounds = false;
+ Vector3 vector = new Vector3(9999999f, 9999999f, 9999999f);
+ Vector3 vector2 = new Vector3(-9999999f, -9999999f, -9999999f);
+ float magnitude = m_mesh.bounds.extents.magnitude;
+ for (int i = 0; i < m_instanceCount; i++)
+ {
+ Matrix4x4 matrix4x = m_instances[i];
+ Vector3 vector3 = new Vector3(matrix4x[0, 3], matrix4x[1, 3], matrix4x[2, 3]);
+ Vector3 lossyScale = matrix4x.lossyScale;
+ float num = Mathf.Max(Mathf.Max(lossyScale.x, lossyScale.y), lossyScale.z);
+ Vector3 vector4 = new Vector3(num * magnitude, num * magnitude, num * magnitude);
+ vector2 = Vector3.Max(vector2, vector3 + vector4);
+ vector = Vector3.Min(vector, vector3 - vector4);
+ }
+ m_bounds.position = (vector2 + vector) * 0.5f;
+ m_bounds.radius = Vector3.Distance(vector2, m_bounds.position);
+ }
+
+ public void AddInstance(Vector3 pos, Quaternion rot, float scale)
+ {
+ Matrix4x4 m = Matrix4x4.TRS(pos, rot, m_scale * scale);
+ AddInstance(m);
+ }
+
+ public void AddInstance(Vector3 pos, Quaternion rot)
+ {
+ Matrix4x4 m = Matrix4x4.TRS(pos, rot, m_scale);
+ AddInstance(m);
+ }
+
+ public void AddInstance(Matrix4x4 m)
+ {
+ if (m_instanceCount < 1023)
+ {
+ m_instances[m_instanceCount] = m;
+ m_instanceCount++;
+ m_dirtyBounds = true;
+ }
+ }
+
+ public void Clear()
+ {
+ m_instanceCount = 0;
+ m_dirtyBounds = true;
+ }
+
+ public void SetInstance(int index, Vector3 pos, Quaternion rot, float scale)
+ {
+ Matrix4x4 matrix4x = Matrix4x4.TRS(pos, rot, m_scale * scale);
+ m_instances[index] = matrix4x;
+ m_dirtyBounds = true;
+ }
+
+ private void Resize(int instances)
+ {
+ m_instanceCount = instances;
+ m_dirtyBounds = true;
+ }
+
+ public void SetInstances(List<Transform> transforms, bool faceCamera = false)
+ {
+ Resize(transforms.Count);
+ for (int i = 0; i < transforms.Count; i++)
+ {
+ Transform transform = transforms[i];
+ m_instances[i] = Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale);
+ }
+ m_dirtyBounds = true;
+ }
+
+ public void SetInstancesBillboard(List<Vector4> points)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null))
+ {
+ Vector3 forward = -mainCamera.transform.forward;
+ Resize(points.Count);
+ for (int i = 0; i < points.Count; i++)
+ {
+ Vector4 vector = points[i];
+ Vector3 pos = new Vector3(vector.x, vector.y, vector.z);
+ float w = vector.w;
+ Quaternion q = Quaternion.LookRotation(forward);
+ m_instances[i] = Matrix4x4.TRS(pos, q, w * m_scale);
+ }
+ m_dirtyBounds = true;
+ }
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstantiatePrefab.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstantiatePrefab.cs
new file mode 100644
index 0000000..eb2c331
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InstantiatePrefab.cs
@@ -0,0 +1,22 @@
+using UnityEngine;
+
+public class InstantiatePrefab : MonoBehaviour
+{
+ public GameObject m_prefab;
+
+ public bool m_attach = true;
+
+ public bool m_moveToTop;
+
+ private void Awake()
+ {
+ if (m_attach)
+ {
+ Object.Instantiate(m_prefab, base.transform).transform.SetAsFirstSibling();
+ }
+ else
+ {
+ Object.Instantiate(m_prefab);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interactable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interactable.cs
new file mode 100644
index 0000000..6d603a0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interactable.cs
@@ -0,0 +1,6 @@
+public interface Interactable
+{
+ bool Interact(Humanoid user, bool hold);
+
+ bool UseItem(Humanoid user, ItemDrop.ItemData item);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interpolate.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interpolate.cs
new file mode 100644
index 0000000..d393f29
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Interpolate.cs
@@ -0,0 +1,456 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Interpolate
+{
+ public enum EaseType
+ {
+ Linear,
+ EaseInQuad,
+ EaseOutQuad,
+ EaseInOutQuad,
+ EaseInCubic,
+ EaseOutCubic,
+ EaseInOutCubic,
+ EaseInQuart,
+ EaseOutQuart,
+ EaseInOutQuart,
+ EaseInQuint,
+ EaseOutQuint,
+ EaseInOutQuint,
+ EaseInSine,
+ EaseOutSine,
+ EaseInOutSine,
+ EaseInExpo,
+ EaseOutExpo,
+ EaseInOutExpo,
+ EaseInCirc,
+ EaseOutCirc,
+ EaseInOutCirc
+ }
+
+ public delegate Vector3 ToVector3<T>(T v);
+
+ public delegate float Function(float a, float b, float c, float d);
+
+ private static Vector3 Identity(Vector3 v)
+ {
+ return v;
+ }
+
+ private static Vector3 TransformDotPosition(Transform t)
+ {
+ return t.position;
+ }
+
+ private static IEnumerable<float> NewTimer(float duration)
+ {
+ float elapsedTime = 0f;
+ while (elapsedTime < duration)
+ {
+ yield return elapsedTime;
+ elapsedTime += Time.deltaTime;
+ if (elapsedTime >= duration)
+ {
+ yield return elapsedTime;
+ }
+ }
+ }
+
+ private static IEnumerable<float> NewCounter(int start, int end, int step)
+ {
+ for (int i = start; i <= end; i += step)
+ {
+ yield return i;
+ }
+ }
+
+ public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float duration)
+ {
+ IEnumerable<float> driver = NewTimer(duration);
+ return NewEase(ease, start, end, duration, driver);
+ }
+
+ public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, int slices)
+ {
+ IEnumerable<float> driver = NewCounter(0, slices + 1, 1);
+ return NewEase(ease, start, end, slices + 1, driver);
+ }
+
+ private static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float total, IEnumerable<float> driver)
+ {
+ Vector3 distance = end - start;
+ foreach (float item in driver)
+ {
+ yield return Ease(ease, start, distance, item, total);
+ }
+ }
+
+ private static Vector3 Ease(Function ease, Vector3 start, Vector3 distance, float elapsedTime, float duration)
+ {
+ start.x = ease(start.x, distance.x, elapsedTime, duration);
+ start.y = ease(start.y, distance.y, elapsedTime, duration);
+ start.z = ease(start.z, distance.z, elapsedTime, duration);
+ return start;
+ }
+
+ public static Function Ease(EaseType type)
+ {
+ Function result = null;
+ switch (type)
+ {
+ case EaseType.Linear:
+ result = Linear;
+ break;
+ case EaseType.EaseInQuad:
+ result = EaseInQuad;
+ break;
+ case EaseType.EaseOutQuad:
+ result = EaseOutQuad;
+ break;
+ case EaseType.EaseInOutQuad:
+ result = EaseInOutQuad;
+ break;
+ case EaseType.EaseInCubic:
+ result = EaseInCubic;
+ break;
+ case EaseType.EaseOutCubic:
+ result = EaseOutCubic;
+ break;
+ case EaseType.EaseInOutCubic:
+ result = EaseInOutCubic;
+ break;
+ case EaseType.EaseInQuart:
+ result = EaseInQuart;
+ break;
+ case EaseType.EaseOutQuart:
+ result = EaseOutQuart;
+ break;
+ case EaseType.EaseInOutQuart:
+ result = EaseInOutQuart;
+ break;
+ case EaseType.EaseInQuint:
+ result = EaseInQuint;
+ break;
+ case EaseType.EaseOutQuint:
+ result = EaseOutQuint;
+ break;
+ case EaseType.EaseInOutQuint:
+ result = EaseInOutQuint;
+ break;
+ case EaseType.EaseInSine:
+ result = EaseInSine;
+ break;
+ case EaseType.EaseOutSine:
+ result = EaseOutSine;
+ break;
+ case EaseType.EaseInOutSine:
+ result = EaseInOutSine;
+ break;
+ case EaseType.EaseInExpo:
+ result = EaseInExpo;
+ break;
+ case EaseType.EaseOutExpo:
+ result = EaseOutExpo;
+ break;
+ case EaseType.EaseInOutExpo:
+ result = EaseInOutExpo;
+ break;
+ case EaseType.EaseInCirc:
+ result = EaseInCirc;
+ break;
+ case EaseType.EaseOutCirc:
+ result = EaseOutCirc;
+ break;
+ case EaseType.EaseInOutCirc:
+ result = EaseInOutCirc;
+ break;
+ }
+ return result;
+ }
+
+ public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, float duration)
+ {
+ IEnumerable<float> steps = NewTimer(duration);
+ return NewBezier<Transform>(ease, nodes, TransformDotPosition, duration, steps);
+ }
+
+ public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, int slices)
+ {
+ IEnumerable<float> steps = NewCounter(0, slices + 1, 1);
+ return NewBezier<Transform>(ease, nodes, TransformDotPosition, slices + 1, steps);
+ }
+
+ public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, float duration)
+ {
+ IEnumerable<float> steps = NewTimer(duration);
+ return NewBezier<Vector3>(ease, points, Identity, duration, steps);
+ }
+
+ public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, int slices)
+ {
+ IEnumerable<float> steps = NewCounter(0, slices + 1, 1);
+ return NewBezier<Vector3>(ease, points, Identity, slices + 1, steps);
+ }
+
+ private static IEnumerable<Vector3> NewBezier<T>(Function ease, IList nodes, ToVector3<T> toVector3, float maxStep, IEnumerable<float> steps)
+ {
+ if (nodes.Count < 2)
+ {
+ yield break;
+ }
+ Vector3[] points = new Vector3[nodes.Count];
+ foreach (float step in steps)
+ {
+ for (int i = 0; i < nodes.Count; i++)
+ {
+ points[i] = toVector3((T)nodes[i]);
+ }
+ yield return Bezier(ease, points, step, maxStep);
+ }
+ }
+
+ private static Vector3 Bezier(Function ease, Vector3[] points, float elapsedTime, float duration)
+ {
+ for (int num = points.Length - 1; num > 0; num--)
+ {
+ for (int i = 0; i < num; i++)
+ {
+ points[i].x = ease(points[i].x, points[i + 1].x - points[i].x, elapsedTime, duration);
+ points[i].y = ease(points[i].y, points[i + 1].y - points[i].y, elapsedTime, duration);
+ points[i].z = ease(points[i].z, points[i + 1].z - points[i].z, elapsedTime, duration);
+ }
+ }
+ return points[0];
+ }
+
+ public static IEnumerable<Vector3> NewCatmullRom(Transform[] nodes, int slices, bool loop)
+ {
+ return NewCatmullRom<Transform>(nodes, TransformDotPosition, slices, loop);
+ }
+
+ public static IEnumerable<Vector3> NewCatmullRom(Vector3[] points, int slices, bool loop)
+ {
+ return NewCatmullRom<Vector3>(points, Identity, slices, loop);
+ }
+
+ private static IEnumerable<Vector3> NewCatmullRom<T>(IList nodes, ToVector3<T> toVector3, int slices, bool loop)
+ {
+ if (nodes.Count < 2)
+ {
+ yield break;
+ }
+ yield return toVector3((T)nodes[0]);
+ int last = nodes.Count - 1;
+ for (int current = 0; loop || current < last; current++)
+ {
+ if (loop && current > last)
+ {
+ current = 0;
+ }
+ int previous = ((current != 0) ? (current - 1) : (loop ? last : current));
+ int start = current;
+ int end = ((current != last) ? (current + 1) : ((!loop) ? current : 0));
+ int next = ((end != last) ? (end + 1) : ((!loop) ? end : 0));
+ int stepCount = slices + 1;
+ for (int step = 1; step <= stepCount; step++)
+ {
+ yield return CatmullRom(toVector3((T)nodes[previous]), toVector3((T)nodes[start]), toVector3((T)nodes[end]), toVector3((T)nodes[next]), step, stepCount);
+ }
+ }
+ }
+
+ private static Vector3 CatmullRom(Vector3 previous, Vector3 start, Vector3 end, Vector3 next, float elapsedTime, float duration)
+ {
+ float num = elapsedTime / duration;
+ float num2 = num * num;
+ float num3 = num2 * num;
+ return previous * (-0.5f * num3 + num2 - 0.5f * num) + start * (1.5f * num3 + -2.5f * num2 + 1f) + end * (-1.5f * num3 + 2f * num2 + 0.5f * num) + next * (0.5f * num3 - 0.5f * num2);
+ }
+
+ private static float Linear(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return distance * (elapsedTime / duration) + start;
+ }
+
+ private static float EaseInQuad(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return distance * elapsedTime * elapsedTime + start;
+ }
+
+ private static float EaseOutQuad(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return (0f - distance) * elapsedTime * (elapsedTime - 2f) + start;
+ }
+
+ private static float EaseInOutQuad(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return distance / 2f * elapsedTime * elapsedTime + start;
+ }
+ elapsedTime -= 1f;
+ return (0f - distance) / 2f * (elapsedTime * (elapsedTime - 2f) - 1f) + start;
+ }
+
+ private static float EaseInCubic(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return distance * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+
+ private static float EaseOutCubic(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ elapsedTime -= 1f;
+ return distance * (elapsedTime * elapsedTime * elapsedTime + 1f) + start;
+ }
+
+ private static float EaseInOutCubic(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return distance / 2f * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+ elapsedTime -= 2f;
+ return distance / 2f * (elapsedTime * elapsedTime * elapsedTime + 2f) + start;
+ }
+
+ private static float EaseInQuart(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+
+ private static float EaseOutQuart(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ elapsedTime -= 1f;
+ return (0f - distance) * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1f) + start;
+ }
+
+ private static float EaseInOutQuart(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return distance / 2f * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+ elapsedTime -= 2f;
+ return (0f - distance) / 2f * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2f) + start;
+ }
+
+ private static float EaseInQuint(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+
+ private static float EaseOutQuint(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ elapsedTime -= 1f;
+ return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1f) + start;
+ }
+
+ private static float EaseInOutQuint(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return distance / 2f * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
+ }
+ elapsedTime -= 2f;
+ return distance / 2f * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2f) + start;
+ }
+
+ private static float EaseInSine(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return (0f - distance) * Mathf.Cos(elapsedTime / duration * ((float)Math.PI / 2f)) + distance + start;
+ }
+
+ private static float EaseOutSine(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return distance * Mathf.Sin(elapsedTime / duration * ((float)Math.PI / 2f)) + start;
+ }
+
+ private static float EaseInOutSine(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return (0f - distance) / 2f * (Mathf.Cos((float)Math.PI * elapsedTime / duration) - 1f) + start;
+ }
+
+ private static float EaseInExpo(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return distance * Mathf.Pow(2f, 10f * (elapsedTime / duration - 1f)) + start;
+ }
+
+ private static float EaseOutExpo(float start, float distance, float elapsedTime, float duration)
+ {
+ if (elapsedTime > duration)
+ {
+ elapsedTime = duration;
+ }
+ return distance * (0f - Mathf.Pow(2f, -10f * elapsedTime / duration) + 1f) + start;
+ }
+
+ private static float EaseInOutExpo(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return distance / 2f * Mathf.Pow(2f, 10f * (elapsedTime - 1f)) + start;
+ }
+ elapsedTime -= 1f;
+ return distance / 2f * (0f - Mathf.Pow(2f, -10f * elapsedTime) + 2f) + start;
+ }
+
+ private static float EaseInCirc(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ return (0f - distance) * (Mathf.Sqrt(1f - elapsedTime * elapsedTime) - 1f) + start;
+ }
+
+ private static float EaseOutCirc(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 1f : (elapsedTime / duration));
+ elapsedTime -= 1f;
+ return distance * Mathf.Sqrt(1f - elapsedTime * elapsedTime) + start;
+ }
+
+ private static float EaseInOutCirc(float start, float distance, float elapsedTime, float duration)
+ {
+ elapsedTime = ((elapsedTime > duration) ? 2f : (elapsedTime / (duration / 2f)));
+ if (elapsedTime < 1f)
+ {
+ return (0f - distance) / 2f * (Mathf.Sqrt(1f - elapsedTime * elapsedTime) - 1f) + start;
+ }
+ elapsedTime -= 2f;
+ return distance / 2f * (Mathf.Sqrt(1f - elapsedTime * elapsedTime) + 1f) + start;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Inventory.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Inventory.cs
new file mode 100644
index 0000000..f31d5d5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Inventory.cs
@@ -0,0 +1,755 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Inventory
+{
+ private int currentVersion = 103;
+
+ public Action m_onChanged;
+
+ private string m_name = "";
+
+ private Sprite m_bkg;
+
+ private List<ItemDrop.ItemData> m_inventory = new List<ItemDrop.ItemData>();
+
+ private int m_width = 4;
+
+ private int m_height = 4;
+
+ private float m_totalWeight;
+
+ public Inventory(string name, Sprite bkg, int w, int h)
+ {
+ m_bkg = bkg;
+ m_name = name;
+ m_width = w;
+ m_height = h;
+ }
+
+ private bool AddItem(ItemDrop.ItemData item, int amount, int x, int y)
+ {
+ amount = Mathf.Min(amount, item.m_stack);
+ if (x < 0 || y < 0 || x >= m_width || y >= m_height)
+ {
+ return false;
+ }
+ bool flag = false;
+ ItemDrop.ItemData itemAt = GetItemAt(x, y);
+ if (itemAt != null)
+ {
+ if (itemAt.m_shared.m_name != item.m_shared.m_name || (itemAt.m_shared.m_maxQuality > 1 && itemAt.m_quality != item.m_quality))
+ {
+ return false;
+ }
+ int num = itemAt.m_shared.m_maxStackSize - itemAt.m_stack;
+ if (num <= 0)
+ {
+ return false;
+ }
+ int num2 = Mathf.Min(num, amount);
+ itemAt.m_stack += num2;
+ item.m_stack -= num2;
+ flag = num2 == amount;
+ ZLog.Log("Added to stack" + itemAt.m_stack + " " + item.m_stack);
+ }
+ else
+ {
+ ItemDrop.ItemData itemData = item.Clone();
+ itemData.m_stack = amount;
+ itemData.m_gridPos = new Vector2i(x, y);
+ m_inventory.Add(itemData);
+ item.m_stack -= amount;
+ flag = true;
+ }
+ Changed();
+ return flag;
+ }
+
+ public bool CanAddItem(GameObject prefab, int stack = -1)
+ {
+ ItemDrop component = prefab.GetComponent<ItemDrop>();
+ if (component == null)
+ {
+ return false;
+ }
+ return CanAddItem(component.m_itemData, stack);
+ }
+
+ public bool CanAddItem(ItemDrop.ItemData item, int stack = -1)
+ {
+ if (HaveEmptySlot())
+ {
+ return true;
+ }
+ if (stack <= 0)
+ {
+ stack = item.m_stack;
+ }
+ return FindFreeStackSpace(item.m_shared.m_name) >= stack;
+ }
+
+ public bool AddItem(ItemDrop.ItemData item)
+ {
+ bool result = true;
+ if (item.m_shared.m_maxStackSize > 1)
+ {
+ for (int i = 0; i < item.m_stack; i++)
+ {
+ ItemDrop.ItemData itemData = FindFreeStackItem(item.m_shared.m_name, item.m_quality);
+ if (itemData != null)
+ {
+ itemData.m_stack++;
+ continue;
+ }
+ int stack = item.m_stack - i;
+ item.m_stack = stack;
+ Vector2i gridPos = FindEmptySlot(TopFirst(item));
+ if (gridPos.x >= 0)
+ {
+ item.m_gridPos = gridPos;
+ m_inventory.Add(item);
+ }
+ else
+ {
+ result = false;
+ }
+ break;
+ }
+ }
+ else
+ {
+ Vector2i gridPos2 = FindEmptySlot(TopFirst(item));
+ if (gridPos2.x >= 0)
+ {
+ item.m_gridPos = gridPos2;
+ m_inventory.Add(item);
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ Changed();
+ return result;
+ }
+
+ private bool TopFirst(ItemDrop.ItemData item)
+ {
+ if (item.IsWeapon())
+ {
+ return true;
+ }
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Tool || item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Shield || item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Utility)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public void MoveAll(Inventory fromInventory)
+ {
+ List<ItemDrop.ItemData> list = new List<ItemDrop.ItemData>(fromInventory.GetAllItems());
+ List<ItemDrop.ItemData> list2 = new List<ItemDrop.ItemData>();
+ foreach (ItemDrop.ItemData item in list)
+ {
+ if (AddItem(item, item.m_stack, item.m_gridPos.x, item.m_gridPos.y))
+ {
+ fromInventory.RemoveItem(item);
+ }
+ else
+ {
+ list2.Add(item);
+ }
+ }
+ foreach (ItemDrop.ItemData item2 in list2)
+ {
+ if (AddItem(item2))
+ {
+ fromInventory.RemoveItem(item2);
+ continue;
+ }
+ break;
+ }
+ Changed();
+ fromInventory.Changed();
+ }
+
+ public void MoveItemToThis(Inventory fromInventory, ItemDrop.ItemData item)
+ {
+ if (AddItem(item))
+ {
+ fromInventory.RemoveItem(item);
+ }
+ Changed();
+ fromInventory.Changed();
+ }
+
+ public bool MoveItemToThis(Inventory fromInventory, ItemDrop.ItemData item, int amount, int x, int y)
+ {
+ bool result = AddItem(item, amount, x, y);
+ if (item.m_stack == 0)
+ {
+ fromInventory.RemoveItem(item);
+ return result;
+ }
+ fromInventory.Changed();
+ return result;
+ }
+
+ public bool RemoveItem(int index)
+ {
+ if (index < 0 || index >= m_inventory.Count)
+ {
+ return false;
+ }
+ m_inventory.RemoveAt(index);
+ Changed();
+ return true;
+ }
+
+ public bool ContainsItem(ItemDrop.ItemData item)
+ {
+ return m_inventory.Contains(item);
+ }
+
+ public bool RemoveOneItem(ItemDrop.ItemData item)
+ {
+ if (!m_inventory.Contains(item))
+ {
+ return false;
+ }
+ if (item.m_stack > 1)
+ {
+ item.m_stack--;
+ Changed();
+ }
+ else
+ {
+ m_inventory.Remove(item);
+ Changed();
+ }
+ return true;
+ }
+
+ public bool RemoveItem(ItemDrop.ItemData item)
+ {
+ if (!m_inventory.Contains(item))
+ {
+ ZLog.Log("Item is not in this container");
+ return false;
+ }
+ m_inventory.Remove(item);
+ Changed();
+ return true;
+ }
+
+ public bool RemoveItem(ItemDrop.ItemData item, int amount)
+ {
+ amount = Mathf.Min(item.m_stack, amount);
+ if (amount == item.m_stack)
+ {
+ return RemoveItem(item);
+ }
+ if (!m_inventory.Contains(item))
+ {
+ return false;
+ }
+ item.m_stack -= amount;
+ Changed();
+ return true;
+ }
+
+ public void RemoveItem(string name, int amount)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name)
+ {
+ int num = Mathf.Min(item.m_stack, amount);
+ item.m_stack -= num;
+ amount -= num;
+ if (amount <= 0)
+ {
+ break;
+ }
+ }
+ }
+ m_inventory.RemoveAll((ItemDrop.ItemData x) => x.m_stack <= 0);
+ Changed();
+ }
+
+ public bool HaveItem(string name)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void GetAllPieceTables(List<PieceTable> tables)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_buildPieces != null && !tables.Contains(item.m_shared.m_buildPieces))
+ {
+ tables.Add(item.m_shared.m_buildPieces);
+ }
+ }
+ }
+
+ public int CountItems(string name)
+ {
+ int num = 0;
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name)
+ {
+ num += item.m_stack;
+ }
+ }
+ return num;
+ }
+
+ public ItemDrop.ItemData GetItem(int index)
+ {
+ return m_inventory[index];
+ }
+
+ public ItemDrop.ItemData GetItem(string name)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public ItemDrop.ItemData GetAmmoItem(string ammoName)
+ {
+ int num = 0;
+ ItemDrop.ItemData itemData = null;
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if ((item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Ammo || item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Consumable) && item.m_shared.m_ammoType == ammoName)
+ {
+ int num2 = item.m_gridPos.y * m_width + item.m_gridPos.x;
+ if (num2 < num || itemData == null)
+ {
+ num = num2;
+ itemData = item;
+ }
+ }
+ }
+ return itemData;
+ }
+
+ private int FindFreeStackSpace(string name)
+ {
+ int num = 0;
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name && item.m_stack < item.m_shared.m_maxStackSize)
+ {
+ num += item.m_shared.m_maxStackSize - item.m_stack;
+ }
+ }
+ return num;
+ }
+
+ private ItemDrop.ItemData FindFreeStackItem(string name, int quality)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name && item.m_quality == quality && item.m_stack < item.m_shared.m_maxStackSize)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public int NrOfItems()
+ {
+ return m_inventory.Count;
+ }
+
+ public float SlotsUsedPercentage()
+ {
+ return (float)m_inventory.Count / (float)(m_width * m_height) * 100f;
+ }
+
+ public void Print()
+ {
+ for (int i = 0; i < m_inventory.Count; i++)
+ {
+ ItemDrop.ItemData itemData = m_inventory[i];
+ ZLog.Log(i.ToString() + ": " + itemData.m_shared.m_name + " " + itemData.m_stack + " / " + itemData.m_shared.m_maxStackSize);
+ }
+ }
+
+ public int GetEmptySlots()
+ {
+ return m_height * m_width - m_inventory.Count;
+ }
+
+ public bool HaveEmptySlot()
+ {
+ return m_inventory.Count < m_width * m_height;
+ }
+
+ private Vector2i FindEmptySlot(bool topFirst)
+ {
+ if (topFirst)
+ {
+ for (int i = 0; i < m_height; i++)
+ {
+ for (int j = 0; j < m_width; j++)
+ {
+ if (GetItemAt(j, i) == null)
+ {
+ return new Vector2i(j, i);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int num = m_height - 1; num >= 0; num--)
+ {
+ for (int k = 0; k < m_width; k++)
+ {
+ if (GetItemAt(k, num) == null)
+ {
+ return new Vector2i(k, num);
+ }
+ }
+ }
+ }
+ return new Vector2i(-1, -1);
+ }
+
+ public ItemDrop.ItemData GetOtherItemAt(int x, int y, ItemDrop.ItemData oldItem)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item != oldItem && item.m_gridPos.x == x && item.m_gridPos.y == y)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public ItemDrop.ItemData GetItemAt(int x, int y)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_gridPos.x == x && item.m_gridPos.y == y)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public List<ItemDrop.ItemData> GetEquipedtems()
+ {
+ List<ItemDrop.ItemData> list = new List<ItemDrop.ItemData>();
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_equiped)
+ {
+ list.Add(item);
+ }
+ }
+ return list;
+ }
+
+ public void GetWornItems(List<ItemDrop.ItemData> worn)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_useDurability && item.m_durability < item.GetMaxDurability())
+ {
+ worn.Add(item);
+ }
+ }
+ }
+
+ public void GetValuableItems(List<ItemDrop.ItemData> items)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_value > 0)
+ {
+ items.Add(item);
+ }
+ }
+ }
+
+ public List<ItemDrop.ItemData> GetAllItems()
+ {
+ return m_inventory;
+ }
+
+ public void GetAllItems(string name, List<ItemDrop.ItemData> items)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_name == name)
+ {
+ items.Add(item);
+ }
+ }
+ }
+
+ public void GetAllItems(ItemDrop.ItemData.ItemType type, List<ItemDrop.ItemData> items)
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_shared.m_itemType == type)
+ {
+ items.Add(item);
+ }
+ }
+ }
+
+ public int GetWidth()
+ {
+ return m_width;
+ }
+
+ public int GetHeight()
+ {
+ return m_height;
+ }
+
+ public string GetName()
+ {
+ return m_name;
+ }
+
+ public Sprite GetBkg()
+ {
+ return m_bkg;
+ }
+
+ public void Save(ZPackage pkg)
+ {
+ pkg.Write(currentVersion);
+ pkg.Write(m_inventory.Count);
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_dropPrefab == null)
+ {
+ ZLog.Log("Item missing prefab " + item.m_shared.m_name);
+ pkg.Write("");
+ }
+ else
+ {
+ pkg.Write(item.m_dropPrefab.name);
+ }
+ pkg.Write(item.m_stack);
+ pkg.Write(item.m_durability);
+ pkg.Write(item.m_gridPos);
+ pkg.Write(item.m_equiped);
+ pkg.Write(item.m_quality);
+ pkg.Write(item.m_variant);
+ pkg.Write(item.m_crafterID);
+ pkg.Write(item.m_crafterName);
+ }
+ }
+
+ public void Load(ZPackage pkg)
+ {
+ int num = pkg.ReadInt();
+ int num2 = pkg.ReadInt();
+ m_inventory.Clear();
+ for (int i = 0; i < num2; i++)
+ {
+ string text = pkg.ReadString();
+ int stack = pkg.ReadInt();
+ float durability = pkg.ReadSingle();
+ Vector2i pos = pkg.ReadVector2i();
+ bool equiped = pkg.ReadBool();
+ int quality = 1;
+ if (num >= 101)
+ {
+ quality = pkg.ReadInt();
+ }
+ int variant = 0;
+ if (num >= 102)
+ {
+ variant = pkg.ReadInt();
+ }
+ long crafterID = 0L;
+ string crafterName = "";
+ if (num >= 103)
+ {
+ crafterID = pkg.ReadLong();
+ crafterName = pkg.ReadString();
+ }
+ if (text != "")
+ {
+ AddItem(text, stack, durability, pos, equiped, quality, variant, crafterID, crafterName);
+ }
+ }
+ Changed();
+ }
+
+ public ItemDrop.ItemData AddItem(string name, int stack, int quality, int variant, long crafterID, string crafterName)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Failed to find item prefab " + name);
+ return null;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ if (component == null)
+ {
+ ZLog.Log("Invalid item " + name);
+ return null;
+ }
+ if (FindEmptySlot(TopFirst(component.m_itemData)).x == -1)
+ {
+ return null;
+ }
+ ItemDrop.ItemData result = null;
+ int num = stack;
+ while (num > 0)
+ {
+ ZNetView.m_forceDisableInit = true;
+ GameObject gameObject = UnityEngine.Object.Instantiate(itemPrefab);
+ ZNetView.m_forceDisableInit = false;
+ ItemDrop component2 = gameObject.GetComponent<ItemDrop>();
+ if (component2 == null)
+ {
+ ZLog.Log("Missing itemdrop in " + name);
+ UnityEngine.Object.Destroy(gameObject);
+ return null;
+ }
+ int num2 = Mathf.Min(num, component2.m_itemData.m_shared.m_maxStackSize);
+ num -= num2;
+ component2.m_itemData.m_stack = num2;
+ component2.m_itemData.m_quality = quality;
+ component2.m_itemData.m_variant = variant;
+ component2.m_itemData.m_durability = component2.m_itemData.GetMaxDurability();
+ component2.m_itemData.m_crafterID = crafterID;
+ component2.m_itemData.m_crafterName = crafterName;
+ AddItem(component2.m_itemData);
+ result = component2.m_itemData;
+ UnityEngine.Object.Destroy(gameObject);
+ }
+ return result;
+ }
+
+ private bool AddItem(string name, int stack, float durability, Vector2i pos, bool equiped, int quality, int variant, long crafterID, string crafterName)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Failed to find item prefab " + name);
+ return false;
+ }
+ ZNetView.m_forceDisableInit = true;
+ GameObject gameObject = UnityEngine.Object.Instantiate(itemPrefab);
+ ZNetView.m_forceDisableInit = false;
+ ItemDrop component = gameObject.GetComponent<ItemDrop>();
+ if (component == null)
+ {
+ ZLog.Log("Missing itemdrop in " + name);
+ UnityEngine.Object.Destroy(gameObject);
+ return false;
+ }
+ component.m_itemData.m_stack = Mathf.Min(stack, component.m_itemData.m_shared.m_maxStackSize);
+ component.m_itemData.m_durability = durability;
+ component.m_itemData.m_equiped = equiped;
+ component.m_itemData.m_quality = quality;
+ component.m_itemData.m_variant = variant;
+ component.m_itemData.m_crafterID = crafterID;
+ component.m_itemData.m_crafterName = crafterName;
+ AddItem(component.m_itemData, component.m_itemData.m_stack, pos.x, pos.y);
+ UnityEngine.Object.Destroy(gameObject);
+ return true;
+ }
+
+ public void MoveInventoryToGrave(Inventory original)
+ {
+ m_inventory.Clear();
+ m_width = original.m_width;
+ m_height = original.m_height;
+ foreach (ItemDrop.ItemData item in original.m_inventory)
+ {
+ if (!item.m_shared.m_questItem && !item.m_equiped)
+ {
+ m_inventory.Add(item);
+ }
+ }
+ original.m_inventory.RemoveAll((ItemDrop.ItemData x) => !x.m_shared.m_questItem && !x.m_equiped);
+ original.Changed();
+ Changed();
+ }
+
+ private void Changed()
+ {
+ UpdateTotalWeight();
+ if (m_onChanged != null)
+ {
+ m_onChanged();
+ }
+ }
+
+ public void RemoveAll()
+ {
+ m_inventory.Clear();
+ Changed();
+ }
+
+ private void UpdateTotalWeight()
+ {
+ m_totalWeight = 0f;
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ m_totalWeight += item.GetWeight();
+ }
+ }
+
+ public float GetTotalWeight()
+ {
+ return m_totalWeight;
+ }
+
+ public void GetBoundItems(List<ItemDrop.ItemData> bound)
+ {
+ bound.Clear();
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (item.m_gridPos.y == 0)
+ {
+ bound.Add(item);
+ }
+ }
+ }
+
+ public bool IsTeleportable()
+ {
+ foreach (ItemDrop.ItemData item in m_inventory)
+ {
+ if (!item.m_shared.m_teleportable)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGrid.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGrid.cs
new file mode 100644
index 0000000..1cec964
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGrid.cs
@@ -0,0 +1,378 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class InventoryGrid : MonoBehaviour
+{
+ private class Element
+ {
+ public Vector2i m_pos;
+
+ public GameObject m_go;
+
+ public Image m_icon;
+
+ public Text m_amount;
+
+ public Text m_quality;
+
+ public Image m_equiped;
+
+ public Image m_queued;
+
+ public GameObject m_selected;
+
+ public Image m_noteleport;
+
+ public UITooltip m_tooltip;
+
+ public GuiBar m_durability;
+
+ public bool m_used;
+ }
+
+ public enum Modifier
+ {
+ Select,
+ Split,
+ Move
+ }
+
+ public Action<InventoryGrid, ItemDrop.ItemData, Vector2i, Modifier> m_onSelected;
+
+ public Action<InventoryGrid, ItemDrop.ItemData, Vector2i> m_onRightClick;
+
+ public GameObject m_elementPrefab;
+
+ public RectTransform m_gridRoot;
+
+ public Scrollbar m_scrollbar;
+
+ public UIGroupHandler m_uiGroup;
+
+ public float m_elementSpace = 10f;
+
+ private int m_width = 4;
+
+ private int m_height = 4;
+
+ private Vector2i m_selected = new Vector2i(0, 0);
+
+ private Inventory m_inventory;
+
+ private List<Element> m_elements = new List<Element>();
+
+ protected void Awake()
+ {
+ }
+
+ public void ResetView()
+ {
+ RectTransform rectTransform = base.transform as RectTransform;
+ if (m_gridRoot.rect.height > rectTransform.rect.height)
+ {
+ m_gridRoot.pivot = new Vector2(m_gridRoot.pivot.x, 1f);
+ }
+ else
+ {
+ m_gridRoot.pivot = new Vector2(m_gridRoot.pivot.x, 0.5f);
+ }
+ m_gridRoot.anchoredPosition = new Vector2(0f, 0f);
+ }
+
+ public void UpdateInventory(Inventory inventory, Player player, ItemDrop.ItemData dragItem)
+ {
+ m_inventory = inventory;
+ UpdateGamepad();
+ UpdateGui(player, dragItem);
+ }
+
+ private void UpdateGamepad()
+ {
+ if (!m_uiGroup.IsActive())
+ {
+ return;
+ }
+ if (ZInput.GetButtonDown("JoyDPadLeft") || ZInput.GetButtonDown("JoyLStickLeft"))
+ {
+ m_selected.x = Mathf.Max(0, m_selected.x - 1);
+ }
+ if (ZInput.GetButtonDown("JoyDPadRight") || ZInput.GetButtonDown("JoyLStickRight"))
+ {
+ m_selected.x = Mathf.Min(m_width - 1, m_selected.x + 1);
+ }
+ if (ZInput.GetButtonDown("JoyDPadUp") || ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ m_selected.y = Mathf.Max(0, m_selected.y - 1);
+ }
+ if (ZInput.GetButtonDown("JoyDPadDown") || ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ m_selected.y = Mathf.Min(m_width - 1, m_selected.y + 1);
+ }
+ if (ZInput.GetButtonDown("JoyButtonA"))
+ {
+ Modifier arg = Modifier.Select;
+ if (ZInput.GetButton("JoyLTrigger"))
+ {
+ arg = Modifier.Split;
+ }
+ if (ZInput.GetButton("JoyRTrigger"))
+ {
+ arg = Modifier.Move;
+ }
+ ItemDrop.ItemData gamepadSelectedItem = GetGamepadSelectedItem();
+ m_onSelected(this, gamepadSelectedItem, m_selected, arg);
+ }
+ if (ZInput.GetButtonDown("JoyButtonX"))
+ {
+ ItemDrop.ItemData gamepadSelectedItem2 = GetGamepadSelectedItem();
+ m_onRightClick(this, gamepadSelectedItem2, m_selected);
+ }
+ }
+
+ private void UpdateGui(Player player, ItemDrop.ItemData dragItem)
+ {
+ RectTransform rectTransform = base.transform as RectTransform;
+ int width = m_inventory.GetWidth();
+ int height = m_inventory.GetHeight();
+ if (m_selected.x >= width - 1)
+ {
+ m_selected.x = width - 1;
+ }
+ if (m_selected.y >= height - 1)
+ {
+ m_selected.y = height - 1;
+ }
+ if (m_width != width || m_height != height)
+ {
+ m_width = width;
+ m_height = height;
+ foreach (Element element3 in m_elements)
+ {
+ UnityEngine.Object.Destroy(element3.m_go);
+ }
+ m_elements.Clear();
+ Vector2 widgetSize = GetWidgetSize();
+ Vector2 vector = new Vector2(rectTransform.rect.width / 2f, 0f) - new Vector2(widgetSize.x, 0f) * 0.5f;
+ for (int i = 0; i < height; i++)
+ {
+ for (int j = 0; j < width; j++)
+ {
+ Vector2 vector2 = new Vector3((float)j * m_elementSpace, (float)i * (0f - m_elementSpace));
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_elementPrefab, m_gridRoot);
+ (gameObject.transform as RectTransform).anchoredPosition = vector + vector2;
+ UIInputHandler componentInChildren = gameObject.GetComponentInChildren<UIInputHandler>();
+ componentInChildren.m_onRightDown = (Action<UIInputHandler>)Delegate.Combine(componentInChildren.m_onRightDown, new Action<UIInputHandler>(OnRightClick));
+ componentInChildren.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(componentInChildren.m_onLeftDown, new Action<UIInputHandler>(OnLeftClick));
+ Text component = gameObject.transform.Find("binding").GetComponent<Text>();
+ if ((bool)player && i == 0)
+ {
+ component.text = (j + 1).ToString();
+ }
+ else
+ {
+ component.enabled = false;
+ }
+ Element element = new Element();
+ element.m_pos = new Vector2i(j, i);
+ element.m_go = gameObject;
+ element.m_icon = gameObject.transform.Find("icon").GetComponent<Image>();
+ element.m_amount = gameObject.transform.Find("amount").GetComponent<Text>();
+ element.m_quality = gameObject.transform.Find("quality").GetComponent<Text>();
+ element.m_equiped = gameObject.transform.Find("equiped").GetComponent<Image>();
+ element.m_queued = gameObject.transform.Find("queued").GetComponent<Image>();
+ element.m_noteleport = gameObject.transform.Find("noteleport").GetComponent<Image>();
+ element.m_selected = gameObject.transform.Find("selected").gameObject;
+ element.m_tooltip = gameObject.GetComponent<UITooltip>();
+ element.m_durability = gameObject.transform.Find("durability").GetComponent<GuiBar>();
+ m_elements.Add(element);
+ }
+ }
+ }
+ foreach (Element element4 in m_elements)
+ {
+ element4.m_used = false;
+ }
+ bool flag = m_uiGroup.IsActive() && ZInput.IsGamepadActive();
+ foreach (ItemDrop.ItemData allItem in m_inventory.GetAllItems())
+ {
+ Element element2 = GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, width);
+ element2.m_used = true;
+ element2.m_icon.enabled = true;
+ element2.m_icon.sprite = allItem.GetIcon();
+ element2.m_icon.color = ((allItem == dragItem) ? Color.grey : Color.white);
+ element2.m_durability.gameObject.SetActive(allItem.m_shared.m_useDurability);
+ if (allItem.m_shared.m_useDurability)
+ {
+ if (allItem.m_durability <= 0f)
+ {
+ element2.m_durability.SetValue(1f);
+ element2.m_durability.SetColor((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : new Color(0f, 0f, 0f, 0f));
+ }
+ else
+ {
+ element2.m_durability.SetValue(allItem.GetDurabilityPercentage());
+ element2.m_durability.ResetColor();
+ }
+ }
+ element2.m_equiped.enabled = (bool)player && allItem.m_equiped;
+ element2.m_queued.enabled = (bool)player && player.IsItemQueued(allItem);
+ element2.m_noteleport.enabled = !allItem.m_shared.m_teleportable;
+ if (dragItem == null)
+ {
+ CreateItemTooltip(allItem, element2.m_tooltip);
+ }
+ element2.m_quality.enabled = allItem.m_shared.m_maxQuality > 1;
+ if (allItem.m_shared.m_maxQuality > 1)
+ {
+ element2.m_quality.text = allItem.m_quality.ToString();
+ }
+ element2.m_amount.enabled = allItem.m_shared.m_maxStackSize > 1;
+ if (allItem.m_shared.m_maxStackSize > 1)
+ {
+ element2.m_amount.text = allItem.m_stack + "/" + allItem.m_shared.m_maxStackSize;
+ }
+ }
+ foreach (Element element5 in m_elements)
+ {
+ element5.m_selected.SetActive(flag && element5.m_pos == m_selected);
+ if (!element5.m_used)
+ {
+ element5.m_durability.gameObject.SetActive(value: false);
+ element5.m_icon.enabled = false;
+ element5.m_amount.enabled = false;
+ element5.m_quality.enabled = false;
+ element5.m_equiped.enabled = false;
+ element5.m_queued.enabled = false;
+ element5.m_noteleport.enabled = false;
+ element5.m_tooltip.m_text = "";
+ element5.m_tooltip.m_topic = "";
+ }
+ }
+ float size = (float)height * m_elementSpace;
+ m_gridRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ }
+
+ private void CreateItemTooltip(ItemDrop.ItemData item, UITooltip tooltip)
+ {
+ tooltip.Set(item.m_shared.m_name, item.GetTooltip());
+ }
+
+ public Vector2 GetWidgetSize()
+ {
+ return new Vector2((float)m_width * m_elementSpace, (float)m_height * m_elementSpace);
+ }
+
+ private void OnRightClick(UIInputHandler element)
+ {
+ GameObject go = element.gameObject;
+ Vector2i buttonPos = GetButtonPos(go);
+ ItemDrop.ItemData itemAt = m_inventory.GetItemAt(buttonPos.x, buttonPos.y);
+ if (m_onRightClick != null)
+ {
+ m_onRightClick(this, itemAt, buttonPos);
+ }
+ }
+
+ private void OnLeftClick(UIInputHandler clickHandler)
+ {
+ GameObject go = clickHandler.gameObject;
+ Vector2i buttonPos = GetButtonPos(go);
+ ItemDrop.ItemData itemAt = m_inventory.GetItemAt(buttonPos.x, buttonPos.y);
+ Modifier arg = Modifier.Select;
+ if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
+ {
+ arg = Modifier.Split;
+ }
+ if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
+ {
+ arg = Modifier.Move;
+ }
+ if (m_onSelected != null)
+ {
+ m_onSelected(this, itemAt, buttonPos, arg);
+ }
+ }
+
+ private Element GetElement(int x, int y, int width)
+ {
+ int index = y * width + x;
+ return m_elements[index];
+ }
+
+ private Vector2i GetButtonPos(GameObject go)
+ {
+ for (int i = 0; i < m_elements.Count; i++)
+ {
+ if (m_elements[i].m_go == go)
+ {
+ int num = i / m_width;
+ return new Vector2i(i - num * m_width, num);
+ }
+ }
+ return new Vector2i(-1, -1);
+ }
+
+ public bool DropItem(Inventory fromInventory, ItemDrop.ItemData item, int amount, Vector2i pos)
+ {
+ ItemDrop.ItemData itemAt = m_inventory.GetItemAt(pos.x, pos.y);
+ if (itemAt == item)
+ {
+ return true;
+ }
+ if (itemAt != null && (itemAt.m_shared.m_name != item.m_shared.m_name || (item.m_shared.m_maxQuality > 1 && itemAt.m_quality != item.m_quality) || itemAt.m_shared.m_maxStackSize == 1) && item.m_stack == amount)
+ {
+ fromInventory.RemoveItem(item);
+ fromInventory.MoveItemToThis(m_inventory, itemAt, itemAt.m_stack, item.m_gridPos.x, item.m_gridPos.y);
+ m_inventory.MoveItemToThis(fromInventory, item, amount, pos.x, pos.y);
+ return true;
+ }
+ return m_inventory.MoveItemToThis(fromInventory, item, amount, pos.x, pos.y);
+ }
+
+ public ItemDrop.ItemData GetItem(Vector2i cursorPosition)
+ {
+ foreach (Element element in m_elements)
+ {
+ if (RectTransformUtility.RectangleContainsScreenPoint(element.m_go.transform as RectTransform, cursorPosition.ToVector2()))
+ {
+ Vector2i buttonPos = GetButtonPos(element.m_go);
+ return m_inventory.GetItemAt(buttonPos.x, buttonPos.y);
+ }
+ }
+ return null;
+ }
+
+ public Inventory GetInventory()
+ {
+ return m_inventory;
+ }
+
+ public void SetSelection(Vector2i pos)
+ {
+ m_selected = pos;
+ }
+
+ public ItemDrop.ItemData GetGamepadSelectedItem()
+ {
+ if (!m_uiGroup.IsActive())
+ {
+ return null;
+ }
+ return m_inventory.GetItemAt(m_selected.x, m_selected.y);
+ }
+
+ public RectTransform GetGamepadSelectedElement()
+ {
+ if (!m_uiGroup.IsActive())
+ {
+ return null;
+ }
+ if (m_selected.x < 0 || m_selected.x >= m_width || m_selected.y < 0 || m_selected.y >= m_height)
+ {
+ return null;
+ }
+ return GetElement(m_selected.x, m_selected.y, m_width).m_go.transform as RectTransform;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGui.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGui.cs
new file mode 100644
index 0000000..c9e63e3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/InventoryGui.cs
@@ -0,0 +1,1535 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class InventoryGui : MonoBehaviour
+{
+ private List<ItemDrop.ItemData> m_tempItemList = new List<ItemDrop.ItemData>();
+
+ private List<ItemDrop.ItemData> m_tempWornItems = new List<ItemDrop.ItemData>();
+
+ private static InventoryGui m_instance;
+
+ [Header("Gamepad")]
+ public UIGroupHandler m_inventoryGroup;
+
+ public UIGroupHandler[] m_uiGroups = new UIGroupHandler[0];
+
+ private int m_activeGroup = 1;
+
+ [Header("Other")]
+ public Transform m_inventoryRoot;
+
+ public RectTransform m_player;
+
+ public RectTransform m_container;
+
+ public GameObject m_dragItemPrefab;
+
+ public Text m_containerName;
+
+ public Button m_dropButton;
+
+ public Button m_takeAllButton;
+
+ public float m_autoCloseDistance = 4f;
+
+ [Header("Crafting dialog")]
+ public Button m_tabCraft;
+
+ public Button m_tabUpgrade;
+
+ public GameObject m_recipeElementPrefab;
+
+ public RectTransform m_recipeListRoot;
+
+ public Scrollbar m_recipeListScroll;
+
+ public float m_recipeListSpace = 30f;
+
+ public float m_craftDuration = 2f;
+
+ public Text m_craftingStationName;
+
+ public Image m_craftingStationIcon;
+
+ public RectTransform m_craftingStationLevelRoot;
+
+ public Text m_craftingStationLevel;
+
+ public Text m_recipeName;
+
+ public Text m_recipeDecription;
+
+ public Image m_recipeIcon;
+
+ public GameObject[] m_recipeRequirementList = new GameObject[0];
+
+ public Button m_variantButton;
+
+ public Button m_craftButton;
+
+ public Button m_craftCancelButton;
+
+ public Transform m_craftProgressPanel;
+
+ public GuiBar m_craftProgressBar;
+
+ [Header("Repair")]
+ public Button m_repairButton;
+
+ public Transform m_repairPanel;
+
+ public Image m_repairButtonGlow;
+
+ public Transform m_repairPanelSelection;
+
+ [Header("Upgrade")]
+ public Image m_upgradeItemIcon;
+
+ public GuiBar m_upgradeItemDurability;
+
+ public Text m_upgradeItemName;
+
+ public Text m_upgradeItemQuality;
+
+ public GameObject m_upgradeItemQualityArrow;
+
+ public Text m_upgradeItemNextQuality;
+
+ public Text m_upgradeItemIndex;
+
+ public Text m_itemCraftType;
+
+ public RectTransform m_qualityPanel;
+
+ public Button m_qualityLevelDown;
+
+ public Button m_qualityLevelUp;
+
+ public Text m_qualityLevel;
+
+ public Image m_minStationLevelIcon;
+
+ private Color m_minStationLevelBasecolor;
+
+ public Text m_minStationLevelText;
+
+ public ScrollRectEnsureVisible m_recipeEnsureVisible;
+
+ [Header("Variants dialog")]
+ public VariantDialog m_variantDialog;
+
+ [Header("Skills dialog")]
+ public SkillsDialog m_skillsDialog;
+
+ [Header("Texts dialog")]
+ public TextsDialog m_textsDialog;
+
+ [Header("Split dialog")]
+ public Transform m_splitPanel;
+
+ public Slider m_splitSlider;
+
+ public Text m_splitAmount;
+
+ public Button m_splitCancelButton;
+
+ public Button m_splitOkButton;
+
+ public Image m_splitIcon;
+
+ public Text m_splitIconName;
+
+ [Header("Character stats")]
+ public Transform m_infoPanel;
+
+ public Text m_playerName;
+
+ public Text m_armor;
+
+ public Text m_weight;
+
+ public Text m_containerWeight;
+
+ public Toggle m_pvp;
+
+ [Header("Trophies")]
+ public GameObject m_trophiesPanel;
+
+ public RectTransform m_trophieListRoot;
+
+ public float m_trophieListSpace = 30f;
+
+ public GameObject m_trophieElementPrefab;
+
+ public Scrollbar m_trophyListScroll;
+
+ [Header("Effects")]
+ public EffectList m_moveItemEffects = new EffectList();
+
+ public EffectList m_craftItemEffects = new EffectList();
+
+ public EffectList m_craftItemDoneEffects = new EffectList();
+
+ public EffectList m_openInventoryEffects = new EffectList();
+
+ public EffectList m_closeInventoryEffects = new EffectList();
+
+ private InventoryGrid m_playerGrid;
+
+ private InventoryGrid m_containerGrid;
+
+ private Animator m_animator;
+
+ private Container m_currentContainer;
+
+ private bool m_firstContainerUpdate = true;
+
+ private KeyValuePair<Recipe, ItemDrop.ItemData> m_selectedRecipe;
+
+ private List<ItemDrop.ItemData> m_upgradeItems = new List<ItemDrop.ItemData>();
+
+ private int m_selectedVariant;
+
+ private Recipe m_craftRecipe;
+
+ private ItemDrop.ItemData m_craftUpgradeItem;
+
+ private int m_craftVariant;
+
+ private List<GameObject> m_recipeList = new List<GameObject>();
+
+ private List<KeyValuePair<Recipe, ItemDrop.ItemData>> m_availableRecipes = new List<KeyValuePair<Recipe, ItemDrop.ItemData>>();
+
+ private GameObject m_dragGo;
+
+ private ItemDrop.ItemData m_dragItem;
+
+ private Inventory m_dragInventory;
+
+ private int m_dragAmount = 1;
+
+ private ItemDrop.ItemData m_splitItem;
+
+ private Inventory m_splitInventory;
+
+ private float m_craftTimer = -1f;
+
+ private float m_recipeListBaseSize;
+
+ private int m_hiddenFrames = 9999;
+
+ private List<GameObject> m_trophyList = new List<GameObject>();
+
+ private float m_trophieListBaseSize;
+
+ public static InventoryGui instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_animator = GetComponent<Animator>();
+ m_inventoryRoot.gameObject.SetActive(value: true);
+ m_container.gameObject.SetActive(value: false);
+ m_splitPanel.gameObject.SetActive(value: false);
+ m_trophiesPanel.SetActive(value: false);
+ m_variantDialog.gameObject.SetActive(value: false);
+ m_skillsDialog.gameObject.SetActive(value: false);
+ m_textsDialog.gameObject.SetActive(value: false);
+ m_playerGrid = m_player.GetComponentInChildren<InventoryGrid>();
+ m_containerGrid = m_container.GetComponentInChildren<InventoryGrid>();
+ InventoryGrid playerGrid = m_playerGrid;
+ playerGrid.m_onSelected = (Action<InventoryGrid, ItemDrop.ItemData, Vector2i, InventoryGrid.Modifier>)Delegate.Combine(playerGrid.m_onSelected, new Action<InventoryGrid, ItemDrop.ItemData, Vector2i, InventoryGrid.Modifier>(OnSelectedItem));
+ InventoryGrid playerGrid2 = m_playerGrid;
+ playerGrid2.m_onRightClick = (Action<InventoryGrid, ItemDrop.ItemData, Vector2i>)Delegate.Combine(playerGrid2.m_onRightClick, new Action<InventoryGrid, ItemDrop.ItemData, Vector2i>(OnRightClickItem));
+ InventoryGrid containerGrid = m_containerGrid;
+ containerGrid.m_onSelected = (Action<InventoryGrid, ItemDrop.ItemData, Vector2i, InventoryGrid.Modifier>)Delegate.Combine(containerGrid.m_onSelected, new Action<InventoryGrid, ItemDrop.ItemData, Vector2i, InventoryGrid.Modifier>(OnSelectedItem));
+ InventoryGrid containerGrid2 = m_containerGrid;
+ containerGrid2.m_onRightClick = (Action<InventoryGrid, ItemDrop.ItemData, Vector2i>)Delegate.Combine(containerGrid2.m_onRightClick, new Action<InventoryGrid, ItemDrop.ItemData, Vector2i>(OnRightClickItem));
+ m_craftButton.onClick.AddListener(OnCraftPressed);
+ m_craftCancelButton.onClick.AddListener(OnCraftCancelPressed);
+ m_dropButton.onClick.AddListener(OnDropOutside);
+ m_takeAllButton.onClick.AddListener(OnTakeAll);
+ m_repairButton.onClick.AddListener(OnRepairPressed);
+ m_splitSlider.onValueChanged.AddListener(OnSplitSliderChanged);
+ m_splitCancelButton.onClick.AddListener(OnSplitCancel);
+ m_splitOkButton.onClick.AddListener(OnSplitOk);
+ VariantDialog variantDialog = m_variantDialog;
+ variantDialog.m_selected = (Action<int>)Delegate.Combine(variantDialog.m_selected, new Action<int>(OnVariantSelected));
+ m_recipeListBaseSize = m_recipeListRoot.rect.height;
+ m_trophieListBaseSize = m_trophieListRoot.rect.height;
+ m_minStationLevelBasecolor = m_minStationLevelText.color;
+ m_tabCraft.interactable = false;
+ m_tabUpgrade.interactable = true;
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Update()
+ {
+ bool @bool = m_animator.GetBool("visible");
+ if (!@bool)
+ {
+ m_hiddenFrames++;
+ }
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null || localPlayer.IsDead() || localPlayer.InCutscene())
+ {
+ Hide();
+ return;
+ }
+ if (m_craftTimer < 0f && (Chat.instance == null || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && (bool)TextViewer.instance && !TextViewer.instance.IsVisible() && !localPlayer.InCutscene() && !GameCamera.InFreeFly() && !Minimap.IsOpen())
+ {
+ if (m_trophiesPanel.activeSelf && (ZInput.GetButtonDown("JoyButtonB") || Input.GetKeyDown(KeyCode.Escape)))
+ {
+ m_trophiesPanel.SetActive(value: false);
+ }
+ else if (m_skillsDialog.gameObject.activeSelf && (ZInput.GetButtonDown("JoyButtonB") || Input.GetKeyDown(KeyCode.Escape)))
+ {
+ m_skillsDialog.gameObject.SetActive(value: false);
+ }
+ else if (m_textsDialog.gameObject.activeSelf && (ZInput.GetButtonDown("JoyButtonB") || Input.GetKeyDown(KeyCode.Escape)))
+ {
+ m_textsDialog.gameObject.SetActive(value: false);
+ }
+ else if (@bool)
+ {
+ if (ZInput.GetButtonDown("Inventory") || ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("JoyButtonY") || Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("Use"))
+ {
+ ZInput.ResetButtonStatus("Inventory");
+ ZInput.ResetButtonStatus("JoyButtonB");
+ ZInput.ResetButtonStatus("JoyButtonY");
+ ZInput.ResetButtonStatus("Use");
+ Hide();
+ }
+ }
+ else if (ZInput.GetButtonDown("Inventory") || ZInput.GetButtonDown("JoyButtonY"))
+ {
+ ZInput.ResetButtonStatus("Inventory");
+ ZInput.ResetButtonStatus("JoyButtonY");
+ localPlayer.ShowTutorial("inventory", force: true);
+ Show(null);
+ }
+ }
+ if (@bool)
+ {
+ m_hiddenFrames = 0;
+ UpdateGamepad();
+ UpdateInventory(localPlayer);
+ UpdateContainer(localPlayer);
+ UpdateItemDrag();
+ UpdateCharacterStats(localPlayer);
+ UpdateInventoryWeight(localPlayer);
+ UpdateContainerWeight();
+ UpdateRecipe(localPlayer, Time.deltaTime);
+ UpdateRepair();
+ }
+ }
+
+ private void UpdateGamepad()
+ {
+ if (m_inventoryGroup.IsActive())
+ {
+ if (ZInput.GetButtonDown("JoyTabLeft"))
+ {
+ SetActiveGroup(m_activeGroup - 1);
+ }
+ if (ZInput.GetButtonDown("JoyTabRight"))
+ {
+ SetActiveGroup(m_activeGroup + 1);
+ }
+ if (m_activeGroup == 0 && !IsContainerOpen())
+ {
+ SetActiveGroup(1);
+ }
+ if (m_activeGroup == 3)
+ {
+ UpdateRecipeGamepadInput();
+ }
+ }
+ }
+
+ private void SetActiveGroup(int index)
+ {
+ index = Mathf.Clamp(index, 0, m_uiGroups.Length - 1);
+ m_activeGroup = index;
+ for (int i = 0; i < m_uiGroups.Length; i++)
+ {
+ m_uiGroups[i].SetActive(i == m_activeGroup);
+ }
+ }
+
+ private void UpdateCharacterStats(Player player)
+ {
+ PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
+ m_playerName.text = playerProfile.GetName();
+ float bodyArmor = player.GetBodyArmor();
+ m_armor.text = bodyArmor.ToString();
+ m_pvp.interactable = player.CanSwitchPVP();
+ player.SetPVP(m_pvp.isOn);
+ }
+
+ private void UpdateInventoryWeight(Player player)
+ {
+ int num = Mathf.CeilToInt(player.GetInventory().GetTotalWeight());
+ int num2 = Mathf.CeilToInt(player.GetMaxCarryWeight());
+ if (num > num2)
+ {
+ if (Mathf.Sin(Time.time * 10f) > 0f)
+ {
+ m_weight.text = "<color=red>" + num + "</color>/" + num2;
+ }
+ else
+ {
+ m_weight.text = num + "/" + num2;
+ }
+ }
+ else
+ {
+ m_weight.text = num + "/" + num2;
+ }
+ }
+
+ private void UpdateContainerWeight()
+ {
+ if (!(m_currentContainer == null))
+ {
+ int num = Mathf.CeilToInt(m_currentContainer.GetInventory().GetTotalWeight());
+ m_containerWeight.text = num.ToString();
+ }
+ }
+
+ private void UpdateInventory(Player player)
+ {
+ Inventory inventory = player.GetInventory();
+ m_playerGrid.UpdateInventory(inventory, player, m_dragItem);
+ }
+
+ private void UpdateContainer(Player player)
+ {
+ if (!m_animator.GetBool("visible"))
+ {
+ return;
+ }
+ if ((bool)m_currentContainer && m_currentContainer.IsOwner())
+ {
+ m_currentContainer.SetInUse(inUse: true);
+ m_container.gameObject.SetActive(value: true);
+ m_containerGrid.UpdateInventory(m_currentContainer.GetInventory(), null, m_dragItem);
+ m_containerName.text = Localization.instance.Localize(m_currentContainer.GetInventory().GetName());
+ if (m_firstContainerUpdate)
+ {
+ m_containerGrid.ResetView();
+ m_firstContainerUpdate = false;
+ }
+ if (Vector3.Distance(m_currentContainer.transform.position, player.transform.position) > m_autoCloseDistance)
+ {
+ CloseContainer();
+ }
+ }
+ else
+ {
+ m_container.gameObject.SetActive(value: false);
+ }
+ }
+
+ private RectTransform GetSelectedGamepadElement()
+ {
+ RectTransform gamepadSelectedElement = m_playerGrid.GetGamepadSelectedElement();
+ if ((bool)gamepadSelectedElement)
+ {
+ return gamepadSelectedElement;
+ }
+ if (m_container.gameObject.activeSelf)
+ {
+ return m_containerGrid.GetGamepadSelectedElement();
+ }
+ return null;
+ }
+
+ private void UpdateItemDrag()
+ {
+ if (!m_dragGo)
+ {
+ return;
+ }
+ if (ZInput.IsGamepadActive() && !ZInput.IsMouseActive())
+ {
+ RectTransform selectedGamepadElement = GetSelectedGamepadElement();
+ if ((bool)selectedGamepadElement)
+ {
+ Vector3[] array = new Vector3[4];
+ selectedGamepadElement.GetWorldCorners(array);
+ m_dragGo.transform.position = array[2] + new Vector3(0f, 32f, 0f);
+ }
+ else
+ {
+ m_dragGo.transform.position = new Vector3(-99999f, 0f, 0f);
+ }
+ }
+ else
+ {
+ m_dragGo.transform.position = Input.mousePosition;
+ }
+ Image component = m_dragGo.transform.Find("icon").GetComponent<Image>();
+ Text component2 = m_dragGo.transform.Find("name").GetComponent<Text>();
+ Text component3 = m_dragGo.transform.Find("amount").GetComponent<Text>();
+ component.sprite = m_dragItem.GetIcon();
+ component2.text = m_dragItem.m_shared.m_name;
+ component3.text = ((m_dragAmount > 1) ? m_dragAmount.ToString() : "");
+ if (Input.GetMouseButton(1))
+ {
+ SetupDragItem(null, null, 1);
+ }
+ }
+
+ private void OnTakeAll()
+ {
+ if ((bool)m_currentContainer)
+ {
+ SetupDragItem(null, null, 1);
+ Inventory inventory = m_currentContainer.GetInventory();
+ Player.m_localPlayer.GetInventory().MoveAll(inventory);
+ }
+ }
+
+ private void OnDropOutside()
+ {
+ if ((bool)m_dragGo)
+ {
+ ZLog.Log("Drop item " + m_dragItem.m_shared.m_name);
+ if (!m_dragInventory.ContainsItem(m_dragItem))
+ {
+ SetupDragItem(null, null, 1);
+ }
+ else if (Player.m_localPlayer.DropItem(m_dragInventory, m_dragItem, m_dragAmount))
+ {
+ m_moveItemEffects.Create(base.transform.position, Quaternion.identity);
+ SetupDragItem(null, null, 1);
+ UpdateCraftingPanel();
+ }
+ }
+ }
+
+ private void OnRightClickItem(InventoryGrid grid, ItemDrop.ItemData item, Vector2i pos)
+ {
+ if (item != null && (bool)Player.m_localPlayer)
+ {
+ Player.m_localPlayer.UseItem(grid.GetInventory(), item, fromInventoryGui: true);
+ }
+ }
+
+ private void OnSelectedItem(InventoryGrid grid, ItemDrop.ItemData item, Vector2i pos, InventoryGrid.Modifier mod)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)m_dragGo)
+ {
+ m_moveItemEffects.Create(base.transform.position, Quaternion.identity);
+ bool flag = localPlayer.IsItemEquiped(m_dragItem);
+ bool flag2 = item != null && localPlayer.IsItemEquiped(item);
+ Vector2i gridPos = m_dragItem.m_gridPos;
+ if ((m_dragItem.m_shared.m_questItem || (item != null && item.m_shared.m_questItem)) && m_dragInventory != grid.GetInventory())
+ {
+ return;
+ }
+ if (!m_dragInventory.ContainsItem(m_dragItem))
+ {
+ SetupDragItem(null, null, 1);
+ return;
+ }
+ localPlayer.RemoveFromEquipQueue(item);
+ localPlayer.RemoveFromEquipQueue(m_dragItem);
+ localPlayer.UnequipItem(m_dragItem, triggerEquipEffects: false);
+ localPlayer.UnequipItem(item, triggerEquipEffects: false);
+ bool num = grid.DropItem(m_dragInventory, m_dragItem, m_dragAmount, pos);
+ if (m_dragItem.m_stack < m_dragAmount)
+ {
+ m_dragAmount = m_dragItem.m_stack;
+ }
+ if (flag)
+ {
+ ItemDrop.ItemData itemAt = grid.GetInventory().GetItemAt(pos.x, pos.y);
+ if (itemAt != null)
+ {
+ localPlayer.EquipItem(itemAt, triggerEquipEffects: false);
+ }
+ if (localPlayer.GetInventory().ContainsItem(m_dragItem))
+ {
+ localPlayer.EquipItem(m_dragItem, triggerEquipEffects: false);
+ }
+ }
+ if (flag2)
+ {
+ ItemDrop.ItemData itemAt2 = m_dragInventory.GetItemAt(gridPos.x, gridPos.y);
+ if (itemAt2 != null)
+ {
+ localPlayer.EquipItem(itemAt2, triggerEquipEffects: false);
+ }
+ if (localPlayer.GetInventory().ContainsItem(item))
+ {
+ localPlayer.EquipItem(item, triggerEquipEffects: false);
+ }
+ }
+ if (num)
+ {
+ SetupDragItem(null, null, 1);
+ UpdateCraftingPanel();
+ }
+ }
+ else
+ {
+ if (item == null)
+ {
+ return;
+ }
+ switch (mod)
+ {
+ case InventoryGrid.Modifier.Move:
+ if (item.m_shared.m_questItem)
+ {
+ return;
+ }
+ if (m_currentContainer != null)
+ {
+ localPlayer.RemoveFromEquipQueue(item);
+ localPlayer.UnequipItem(item);
+ if (grid.GetInventory() == m_currentContainer.GetInventory())
+ {
+ localPlayer.GetInventory().MoveItemToThis(grid.GetInventory(), item);
+ }
+ else
+ {
+ m_currentContainer.GetInventory().MoveItemToThis(localPlayer.GetInventory(), item);
+ }
+ m_moveItemEffects.Create(base.transform.position, Quaternion.identity);
+ }
+ else if (Player.m_localPlayer.DropItem(localPlayer.GetInventory(), item, item.m_stack))
+ {
+ m_moveItemEffects.Create(base.transform.position, Quaternion.identity);
+ }
+ return;
+ case InventoryGrid.Modifier.Split:
+ if (item.m_stack > 1)
+ {
+ ShowSplitDialog(item, grid.GetInventory());
+ return;
+ }
+ break;
+ }
+ SetupDragItem(item, grid.GetInventory(), item.m_stack);
+ }
+ }
+
+ public static bool IsVisible()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_hiddenFrames <= 1;
+ }
+ return false;
+ }
+
+ public bool IsContainerOpen()
+ {
+ return m_currentContainer != null;
+ }
+
+ public void Show(Container container)
+ {
+ Hud.HidePieceSelection();
+ m_animator.SetBool("visible", value: true);
+ SetActiveGroup(1);
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ SetupCrafting();
+ }
+ m_currentContainer = container;
+ m_hiddenFrames = 0;
+ if ((bool)localPlayer)
+ {
+ m_openInventoryEffects.Create(localPlayer.transform.position, Quaternion.identity);
+ }
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Inventory", 0L);
+ }
+
+ public void Hide()
+ {
+ if (m_animator.GetBool("visible"))
+ {
+ m_craftTimer = -1f;
+ m_animator.SetBool("visible", value: false);
+ m_trophiesPanel.SetActive(value: false);
+ m_variantDialog.gameObject.SetActive(value: false);
+ m_skillsDialog.gameObject.SetActive(value: false);
+ m_textsDialog.gameObject.SetActive(value: false);
+ m_splitPanel.gameObject.SetActive(value: false);
+ SetupDragItem(null, null, 1);
+ if ((bool)m_currentContainer)
+ {
+ m_currentContainer.SetInUse(inUse: false);
+ m_currentContainer = null;
+ }
+ if ((bool)Player.m_localPlayer)
+ {
+ m_closeInventoryEffects.Create(Player.m_localPlayer.transform.position, Quaternion.identity);
+ }
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Exit", "Inventory", 0L);
+ }
+ }
+
+ private void CloseContainer()
+ {
+ if (m_dragInventory != null && m_dragInventory != Player.m_localPlayer.GetInventory())
+ {
+ SetupDragItem(null, null, 1);
+ }
+ if ((bool)m_currentContainer)
+ {
+ m_currentContainer.SetInUse(inUse: false);
+ m_currentContainer = null;
+ }
+ m_splitPanel.gameObject.SetActive(value: false);
+ m_firstContainerUpdate = true;
+ m_container.gameObject.SetActive(value: false);
+ }
+
+ private void SetupCrafting()
+ {
+ UpdateCraftingPanel(focusView: true);
+ }
+
+ private void UpdateCraftingPanel(bool focusView = false)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (!localPlayer.GetCurrentCraftingStation() && !localPlayer.NoCostCheat())
+ {
+ m_tabCraft.interactable = false;
+ m_tabUpgrade.interactable = true;
+ m_tabUpgrade.gameObject.SetActive(value: false);
+ }
+ else
+ {
+ m_tabUpgrade.gameObject.SetActive(value: true);
+ }
+ List<Recipe> available = new List<Recipe>();
+ localPlayer.GetAvailableRecipes(ref available);
+ UpdateRecipeList(available);
+ if (m_availableRecipes.Count > 0)
+ {
+ if (m_selectedRecipe.Key != null)
+ {
+ int selectedRecipeIndex = GetSelectedRecipeIndex();
+ SetRecipe(selectedRecipeIndex, focusView);
+ }
+ else
+ {
+ SetRecipe(0, focusView);
+ }
+ }
+ else
+ {
+ SetRecipe(-1, focusView);
+ }
+ }
+
+ private void UpdateRecipeList(List<Recipe> recipes)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ m_availableRecipes.Clear();
+ foreach (GameObject recipe3 in m_recipeList)
+ {
+ UnityEngine.Object.Destroy(recipe3);
+ }
+ m_recipeList.Clear();
+ if (InCraftTab())
+ {
+ bool[] array = new bool[recipes.Count];
+ for (int i = 0; i < recipes.Count; i++)
+ {
+ Recipe recipe = recipes[i];
+ array[i] = localPlayer.HaveRequirements(recipe, discover: false, 1);
+ }
+ for (int j = 0; j < recipes.Count; j++)
+ {
+ if (array[j])
+ {
+ AddRecipeToList(localPlayer, recipes[j], null, canCraft: true);
+ }
+ }
+ for (int k = 0; k < recipes.Count; k++)
+ {
+ if (!array[k])
+ {
+ AddRecipeToList(localPlayer, recipes[k], null, canCraft: false);
+ }
+ }
+ }
+ else
+ {
+ List<KeyValuePair<Recipe, ItemDrop.ItemData>> list = new List<KeyValuePair<Recipe, ItemDrop.ItemData>>();
+ List<KeyValuePair<Recipe, ItemDrop.ItemData>> list2 = new List<KeyValuePair<Recipe, ItemDrop.ItemData>>();
+ for (int l = 0; l < recipes.Count; l++)
+ {
+ Recipe recipe2 = recipes[l];
+ if (recipe2.m_item.m_itemData.m_shared.m_maxQuality <= 1)
+ {
+ continue;
+ }
+ m_tempItemList.Clear();
+ localPlayer.GetInventory().GetAllItems(recipe2.m_item.m_itemData.m_shared.m_name, m_tempItemList);
+ foreach (ItemDrop.ItemData tempItem in m_tempItemList)
+ {
+ if (tempItem.m_quality < tempItem.m_shared.m_maxQuality && localPlayer.HaveRequirements(recipe2, discover: false, tempItem.m_quality + 1))
+ {
+ list.Add(new KeyValuePair<Recipe, ItemDrop.ItemData>(recipe2, tempItem));
+ }
+ else
+ {
+ list2.Add(new KeyValuePair<Recipe, ItemDrop.ItemData>(recipe2, tempItem));
+ }
+ }
+ }
+ foreach (KeyValuePair<Recipe, ItemDrop.ItemData> item in list)
+ {
+ AddRecipeToList(localPlayer, item.Key, item.Value, canCraft: true);
+ }
+ foreach (KeyValuePair<Recipe, ItemDrop.ItemData> item2 in list2)
+ {
+ AddRecipeToList(localPlayer, item2.Key, item2.Value, canCraft: false);
+ }
+ }
+ float b = (float)m_recipeList.Count * m_recipeListSpace;
+ b = Mathf.Max(m_recipeListBaseSize, b);
+ m_recipeListRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, b);
+ }
+
+ private void AddRecipeToList(Player player, Recipe recipe, ItemDrop.ItemData item, bool canCraft)
+ {
+ int count = m_recipeList.Count;
+ GameObject element = UnityEngine.Object.Instantiate(m_recipeElementPrefab, m_recipeListRoot);
+ element.SetActive(value: true);
+ (element.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)count * (0f - m_recipeListSpace));
+ Image component = element.transform.Find("icon").GetComponent<Image>();
+ component.sprite = recipe.m_item.m_itemData.GetIcon();
+ component.color = (canCraft ? Color.white : new Color(1f, 0f, 1f, 0f));
+ Text component2 = element.transform.Find("name").GetComponent<Text>();
+ string text = Localization.instance.Localize(recipe.m_item.m_itemData.m_shared.m_name);
+ if (recipe.m_amount > 1)
+ {
+ text = text + " x" + recipe.m_amount;
+ }
+ component2.text = text;
+ component2.color = (canCraft ? Color.white : new Color(0.66f, 0.66f, 0.66f, 1f));
+ GuiBar component3 = element.transform.Find("Durability").GetComponent<GuiBar>();
+ if (item != null && item.m_shared.m_useDurability && item.m_durability < item.GetMaxDurability())
+ {
+ component3.gameObject.SetActive(value: true);
+ component3.SetValue(item.GetDurabilityPercentage());
+ }
+ else
+ {
+ component3.gameObject.SetActive(value: false);
+ }
+ Text component4 = element.transform.Find("QualityLevel").GetComponent<Text>();
+ if (item != null)
+ {
+ component4.gameObject.SetActive(value: true);
+ component4.text = item.m_quality.ToString();
+ }
+ else
+ {
+ component4.gameObject.SetActive(value: false);
+ }
+ element.GetComponent<Button>().onClick.AddListener(delegate
+ {
+ OnSelectedRecipe(element);
+ });
+ m_recipeList.Add(element);
+ m_availableRecipes.Add(new KeyValuePair<Recipe, ItemDrop.ItemData>(recipe, item));
+ }
+
+ private void OnSelectedRecipe(GameObject button)
+ {
+ int index = FindSelectedRecipe(button);
+ SetRecipe(index, center: false);
+ }
+
+ private void UpdateRecipeGamepadInput()
+ {
+ if (m_availableRecipes.Count > 0)
+ {
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ SetRecipe(Mathf.Min(m_availableRecipes.Count - 1, GetSelectedRecipeIndex() + 1), center: true);
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ SetRecipe(Mathf.Max(0, GetSelectedRecipeIndex() - 1), center: true);
+ }
+ }
+ }
+
+ private int GetSelectedRecipeIndex()
+ {
+ int result = 0;
+ for (int i = 0; i < m_availableRecipes.Count; i++)
+ {
+ if (m_availableRecipes[i].Key == m_selectedRecipe.Key && m_availableRecipes[i].Value == m_selectedRecipe.Value)
+ {
+ result = i;
+ }
+ }
+ return result;
+ }
+
+ private void SetRecipe(int index, bool center)
+ {
+ ZLog.Log("Setting selected recipe " + index);
+ for (int i = 0; i < m_recipeList.Count; i++)
+ {
+ bool active = i == index;
+ m_recipeList[i].transform.Find("selected").gameObject.SetActive(active);
+ }
+ if (center && index >= 0)
+ {
+ m_recipeEnsureVisible.CenterOnItem(m_recipeList[index].transform as RectTransform);
+ }
+ if (index < 0)
+ {
+ m_selectedRecipe = new KeyValuePair<Recipe, ItemDrop.ItemData>(null, null);
+ m_selectedVariant = 0;
+ return;
+ }
+ KeyValuePair<Recipe, ItemDrop.ItemData> selectedRecipe = m_availableRecipes[index];
+ if (selectedRecipe.Key != m_selectedRecipe.Key || selectedRecipe.Value != m_selectedRecipe.Value)
+ {
+ m_selectedRecipe = selectedRecipe;
+ m_selectedVariant = 0;
+ }
+ }
+
+ private void UpdateRecipe(Player player, float dt)
+ {
+ CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
+ if ((bool)currentCraftingStation)
+ {
+ m_craftingStationName.text = Localization.instance.Localize(currentCraftingStation.m_name);
+ m_craftingStationIcon.gameObject.SetActive(value: true);
+ m_craftingStationIcon.sprite = currentCraftingStation.m_icon;
+ int level = currentCraftingStation.GetLevel();
+ m_craftingStationLevel.text = level.ToString();
+ m_craftingStationLevelRoot.gameObject.SetActive(value: true);
+ }
+ else
+ {
+ m_craftingStationName.text = Localization.instance.Localize("$hud_crafting");
+ m_craftingStationIcon.gameObject.SetActive(value: false);
+ m_craftingStationLevelRoot.gameObject.SetActive(value: false);
+ }
+ if ((bool)m_selectedRecipe.Key)
+ {
+ m_recipeIcon.enabled = true;
+ m_recipeName.enabled = true;
+ m_recipeDecription.enabled = true;
+ ItemDrop.ItemData value = m_selectedRecipe.Value;
+ int num = ((value == null) ? 1 : (value.m_quality + 1));
+ bool flag = num <= m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_maxQuality;
+ int num2 = value?.m_variant ?? m_selectedVariant;
+ m_recipeIcon.sprite = m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_icons[num2];
+ string text = Localization.instance.Localize(m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_name);
+ if (m_selectedRecipe.Key.m_amount > 1)
+ {
+ text = text + " x" + m_selectedRecipe.Key.m_amount;
+ }
+ m_recipeName.text = text;
+ m_recipeDecription.text = Localization.instance.Localize(ItemDrop.ItemData.GetTooltip(m_selectedRecipe.Key.m_item.m_itemData, num, crafting: true));
+ if (value != null)
+ {
+ m_itemCraftType.gameObject.SetActive(value: true);
+ if (value.m_quality >= value.m_shared.m_maxQuality)
+ {
+ m_itemCraftType.text = Localization.instance.Localize("$inventory_maxquality");
+ }
+ else
+ {
+ string text2 = Localization.instance.Localize(value.m_shared.m_name);
+ m_itemCraftType.text = Localization.instance.Localize("$inventory_upgrade", text2, (value.m_quality + 1).ToString());
+ }
+ }
+ else
+ {
+ m_itemCraftType.gameObject.SetActive(value: false);
+ }
+ m_variantButton.gameObject.SetActive(m_selectedRecipe.Key.m_item.m_itemData.m_shared.m_variants > 1 && m_selectedRecipe.Value == null);
+ SetupRequirementList(num, player, flag);
+ int requiredStationLevel = m_selectedRecipe.Key.GetRequiredStationLevel(num);
+ CraftingStation requiredStation = m_selectedRecipe.Key.GetRequiredStation(num);
+ if (requiredStation != null && flag)
+ {
+ m_minStationLevelIcon.gameObject.SetActive(value: true);
+ m_minStationLevelText.text = requiredStationLevel.ToString();
+ if (currentCraftingStation == null || currentCraftingStation.GetLevel() < requiredStationLevel)
+ {
+ m_minStationLevelText.color = ((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : m_minStationLevelBasecolor);
+ }
+ else
+ {
+ m_minStationLevelText.color = m_minStationLevelBasecolor;
+ }
+ }
+ else
+ {
+ m_minStationLevelIcon.gameObject.SetActive(value: false);
+ }
+ bool flag2 = player.HaveRequirements(m_selectedRecipe.Key, discover: false, num);
+ bool flag3 = m_selectedRecipe.Value != null || player.GetInventory().HaveEmptySlot();
+ bool flag4 = !requiredStation || ((bool)currentCraftingStation && currentCraftingStation.CheckUsable(player, showMessage: false));
+ m_craftButton.interactable = ((flag2 && flag4) || player.NoCostCheat()) && flag3 && flag;
+ Text componentInChildren = m_craftButton.GetComponentInChildren<Text>();
+ if (num > 1)
+ {
+ componentInChildren.text = Localization.instance.Localize("$inventory_upgradebutton");
+ }
+ else
+ {
+ componentInChildren.text = Localization.instance.Localize("$inventory_craftbutton");
+ }
+ UITooltip component = m_craftButton.GetComponent<UITooltip>();
+ if (!flag3)
+ {
+ component.m_text = Localization.instance.Localize("$inventory_full");
+ }
+ else if (!flag2)
+ {
+ component.m_text = Localization.instance.Localize("$msg_missingrequirement");
+ }
+ else if (!flag4)
+ {
+ component.m_text = Localization.instance.Localize("$msg_missingstation");
+ }
+ else
+ {
+ component.m_text = "";
+ }
+ }
+ else
+ {
+ m_recipeIcon.enabled = false;
+ m_recipeName.enabled = false;
+ m_recipeDecription.enabled = false;
+ m_qualityPanel.gameObject.SetActive(value: false);
+ m_minStationLevelIcon.gameObject.SetActive(value: false);
+ m_craftButton.GetComponent<UITooltip>().m_text = "";
+ m_variantButton.gameObject.SetActive(value: false);
+ m_itemCraftType.gameObject.SetActive(value: false);
+ for (int i = 0; i < m_recipeRequirementList.Length; i++)
+ {
+ HideRequirement(m_recipeRequirementList[i].transform);
+ }
+ m_craftButton.interactable = false;
+ }
+ if (m_craftTimer < 0f)
+ {
+ m_craftProgressPanel.gameObject.SetActive(value: false);
+ m_craftButton.gameObject.SetActive(value: true);
+ return;
+ }
+ m_craftButton.gameObject.SetActive(value: false);
+ m_craftProgressPanel.gameObject.SetActive(value: true);
+ m_craftProgressBar.SetMaxValue(m_craftDuration);
+ m_craftProgressBar.SetValue(m_craftTimer);
+ m_craftTimer += dt;
+ if (m_craftTimer >= m_craftDuration)
+ {
+ DoCrafting(player);
+ m_craftTimer = -1f;
+ }
+ }
+
+ private void SetupRequirementList(int quality, Player player, bool allowedQuality)
+ {
+ int i = 0;
+ if (allowedQuality)
+ {
+ Piece.Requirement[] resources = m_selectedRecipe.Key.m_resources;
+ foreach (Piece.Requirement req in resources)
+ {
+ if (SetupRequirement(m_recipeRequirementList[i].transform, req, player, craft: true, quality))
+ {
+ i++;
+ }
+ }
+ }
+ for (; i < m_recipeRequirementList.Length; i++)
+ {
+ HideRequirement(m_recipeRequirementList[i].transform);
+ }
+ }
+
+ private void SetupUpgradeItem(Recipe recipe, ItemDrop.ItemData item)
+ {
+ if (item == null)
+ {
+ m_upgradeItemIcon.sprite = recipe.m_item.m_itemData.m_shared.m_icons[m_selectedVariant];
+ m_upgradeItemName.text = Localization.instance.Localize(recipe.m_item.m_itemData.m_shared.m_name);
+ m_upgradeItemNextQuality.text = ((recipe.m_item.m_itemData.m_shared.m_maxQuality > 1) ? "1" : "");
+ m_itemCraftType.text = Localization.instance.Localize("$inventory_new");
+ m_upgradeItemDurability.gameObject.SetActive(recipe.m_item.m_itemData.m_shared.m_useDurability);
+ if (recipe.m_item.m_itemData.m_shared.m_useDurability)
+ {
+ m_upgradeItemDurability.SetValue(1f);
+ }
+ return;
+ }
+ m_upgradeItemIcon.sprite = item.GetIcon();
+ m_upgradeItemName.text = Localization.instance.Localize(item.m_shared.m_name);
+ m_upgradeItemNextQuality.text = item.m_quality.ToString();
+ m_upgradeItemDurability.gameObject.SetActive(item.m_shared.m_useDurability);
+ if (item.m_shared.m_useDurability)
+ {
+ m_upgradeItemDurability.SetValue(item.GetDurabilityPercentage());
+ }
+ if (item.m_quality >= item.m_shared.m_maxQuality)
+ {
+ m_itemCraftType.text = Localization.instance.Localize("$inventory_maxquality");
+ }
+ else
+ {
+ m_itemCraftType.text = Localization.instance.Localize("$inventory_upgrade");
+ }
+ }
+
+ public static bool SetupRequirement(Transform elementRoot, Piece.Requirement req, Player player, bool craft, int quality)
+ {
+ Image component = elementRoot.transform.Find("res_icon").GetComponent<Image>();
+ Text component2 = elementRoot.transform.Find("res_name").GetComponent<Text>();
+ Text component3 = elementRoot.transform.Find("res_amount").GetComponent<Text>();
+ UITooltip component4 = elementRoot.GetComponent<UITooltip>();
+ if (req.m_resItem != null)
+ {
+ component.gameObject.SetActive(value: true);
+ component2.gameObject.SetActive(value: true);
+ component3.gameObject.SetActive(value: true);
+ component.sprite = req.m_resItem.m_itemData.GetIcon();
+ component.color = Color.white;
+ component4.m_text = Localization.instance.Localize(req.m_resItem.m_itemData.m_shared.m_name);
+ component2.text = Localization.instance.Localize(req.m_resItem.m_itemData.m_shared.m_name);
+ int num = player.GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name);
+ int amount = req.GetAmount(quality);
+ if (amount <= 0)
+ {
+ HideRequirement(elementRoot);
+ return false;
+ }
+ component3.text = amount.ToString();
+ if (num < amount)
+ {
+ component3.color = ((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : Color.white);
+ }
+ else
+ {
+ component3.color = Color.white;
+ }
+ }
+ return true;
+ }
+
+ public static void HideRequirement(Transform elementRoot)
+ {
+ Image component = elementRoot.transform.Find("res_icon").GetComponent<Image>();
+ Text component2 = elementRoot.transform.Find("res_name").GetComponent<Text>();
+ Text component3 = elementRoot.transform.Find("res_amount").GetComponent<Text>();
+ elementRoot.GetComponent<UITooltip>().m_text = "";
+ component.gameObject.SetActive(value: false);
+ component2.gameObject.SetActive(value: false);
+ component3.gameObject.SetActive(value: false);
+ }
+
+ private void DoCrafting(Player player)
+ {
+ if (m_craftRecipe == null)
+ {
+ return;
+ }
+ int num = ((m_craftUpgradeItem == null) ? 1 : (m_craftUpgradeItem.m_quality + 1));
+ if (num > m_craftRecipe.m_item.m_itemData.m_shared.m_maxQuality || (!player.HaveRequirements(m_craftRecipe, discover: false, num) && !player.NoCostCheat()) || (m_craftUpgradeItem != null && !player.GetInventory().ContainsItem(m_craftUpgradeItem)) || (m_craftUpgradeItem == null && !player.GetInventory().HaveEmptySlot()))
+ {
+ return;
+ }
+ if (m_craftRecipe.m_item.m_itemData.m_shared.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(m_craftRecipe.m_item.m_itemData.m_shared.m_dlc))
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_dlcrequired");
+ return;
+ }
+ int variant = m_craftVariant;
+ if (m_craftUpgradeItem != null)
+ {
+ variant = m_craftUpgradeItem.m_variant;
+ player.UnequipItem(m_craftUpgradeItem);
+ player.GetInventory().RemoveItem(m_craftUpgradeItem);
+ }
+ long playerID = player.GetPlayerID();
+ string playerName = player.GetPlayerName();
+ if (player.GetInventory().AddItem(m_craftRecipe.m_item.gameObject.name, m_craftRecipe.m_amount, num, variant, playerID, playerName) != null)
+ {
+ if (!player.NoCostCheat())
+ {
+ player.ConsumeResources(m_craftRecipe.m_resources, num);
+ }
+ UpdateCraftingPanel();
+ }
+ CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
+ if ((bool)currentCraftingStation)
+ {
+ currentCraftingStation.m_craftItemDoneEffects.Create(player.transform.position, Quaternion.identity);
+ }
+ else
+ {
+ m_craftItemDoneEffects.Create(player.transform.position, Quaternion.identity);
+ }
+ Game.instance.GetPlayerProfile().m_playerStats.m_crafts++;
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Crafted", m_craftRecipe.m_item.m_itemData.m_shared.m_name, num);
+ }
+
+ private int FindSelectedRecipe(GameObject button)
+ {
+ for (int i = 0; i < m_recipeList.Count; i++)
+ {
+ if (m_recipeList[i] == button)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void OnCraftCancelPressed()
+ {
+ if (m_craftTimer >= 0f)
+ {
+ m_craftTimer = -1f;
+ }
+ }
+
+ private void OnCraftPressed()
+ {
+ if (!m_selectedRecipe.Key)
+ {
+ return;
+ }
+ m_craftRecipe = m_selectedRecipe.Key;
+ m_craftUpgradeItem = m_selectedRecipe.Value;
+ m_craftVariant = m_selectedVariant;
+ m_craftTimer = 0f;
+ if ((bool)m_craftRecipe.m_craftingStation)
+ {
+ CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
+ if ((bool)currentCraftingStation)
+ {
+ currentCraftingStation.m_craftItemEffects.Create(Player.m_localPlayer.transform.position, Quaternion.identity);
+ }
+ }
+ else
+ {
+ m_craftItemEffects.Create(Player.m_localPlayer.transform.position, Quaternion.identity);
+ }
+ }
+
+ private void OnRepairPressed()
+ {
+ RepairOneItem();
+ UpdateRepair();
+ }
+
+ private void UpdateRepair()
+ {
+ if (Player.m_localPlayer.GetCurrentCraftingStation() == null && !Player.m_localPlayer.NoCostCheat())
+ {
+ m_repairPanel.gameObject.SetActive(value: false);
+ m_repairPanelSelection.gameObject.SetActive(value: false);
+ m_repairButton.gameObject.SetActive(value: false);
+ return;
+ }
+ m_repairButton.gameObject.SetActive(value: true);
+ m_repairPanel.gameObject.SetActive(value: true);
+ m_repairPanelSelection.gameObject.SetActive(value: true);
+ if (HaveRepairableItems())
+ {
+ m_repairButton.interactable = true;
+ m_repairButtonGlow.gameObject.SetActive(value: true);
+ Color color = m_repairButtonGlow.color;
+ color.a = 0.5f + Mathf.Sin(Time.time * 5f) * 0.5f;
+ m_repairButtonGlow.color = color;
+ }
+ else
+ {
+ m_repairButton.interactable = false;
+ m_repairButtonGlow.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void RepairOneItem()
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return;
+ }
+ CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
+ if ((currentCraftingStation == null && !Player.m_localPlayer.NoCostCheat()) || ((bool)currentCraftingStation && !currentCraftingStation.CheckUsable(Player.m_localPlayer, showMessage: false)))
+ {
+ return;
+ }
+ m_tempWornItems.Clear();
+ Player.m_localPlayer.GetInventory().GetWornItems(m_tempWornItems);
+ foreach (ItemDrop.ItemData tempWornItem in m_tempWornItems)
+ {
+ if (CanRepair(tempWornItem))
+ {
+ tempWornItem.m_durability = tempWornItem.GetMaxDurability();
+ if ((bool)currentCraftingStation)
+ {
+ currentCraftingStation.m_repairItemDoneEffects.Create(currentCraftingStation.transform.position, Quaternion.identity);
+ }
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_repaired", tempWornItem.m_shared.m_name));
+ return;
+ }
+ }
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, "No more item to repair");
+ }
+
+ private bool HaveRepairableItems()
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return false;
+ }
+ CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
+ if (currentCraftingStation == null && !Player.m_localPlayer.NoCostCheat())
+ {
+ return false;
+ }
+ if ((bool)currentCraftingStation && !currentCraftingStation.CheckUsable(Player.m_localPlayer, showMessage: false))
+ {
+ return false;
+ }
+ m_tempWornItems.Clear();
+ Player.m_localPlayer.GetInventory().GetWornItems(m_tempWornItems);
+ foreach (ItemDrop.ItemData tempWornItem in m_tempWornItems)
+ {
+ if (CanRepair(tempWornItem))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool CanRepair(ItemDrop.ItemData item)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return false;
+ }
+ if (!item.m_shared.m_canBeReparied)
+ {
+ return false;
+ }
+ if (Player.m_localPlayer.NoCostCheat())
+ {
+ return true;
+ }
+ CraftingStation currentCraftingStation = Player.m_localPlayer.GetCurrentCraftingStation();
+ if (currentCraftingStation == null)
+ {
+ return false;
+ }
+ Recipe recipe = ObjectDB.instance.GetRecipe(item);
+ if (recipe == null)
+ {
+ return false;
+ }
+ if (recipe.m_craftingStation == null && recipe.m_repairStation == null)
+ {
+ return false;
+ }
+ if ((recipe.m_repairStation != null && recipe.m_repairStation.m_name == currentCraftingStation.m_name) || (recipe.m_craftingStation != null && recipe.m_craftingStation.m_name == currentCraftingStation.m_name))
+ {
+ if (currentCraftingStation.GetLevel() < recipe.m_minStationLevel)
+ {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void SetupDragItem(ItemDrop.ItemData item, Inventory inventory, int amount)
+ {
+ if ((bool)m_dragGo)
+ {
+ UnityEngine.Object.Destroy(m_dragGo);
+ m_dragGo = null;
+ m_dragItem = null;
+ m_dragInventory = null;
+ m_dragAmount = 0;
+ }
+ if (item != null)
+ {
+ m_dragGo = UnityEngine.Object.Instantiate(m_dragItemPrefab, base.transform);
+ m_dragItem = item;
+ m_dragInventory = inventory;
+ m_dragAmount = amount;
+ m_moveItemEffects.Create(base.transform.position, Quaternion.identity);
+ UITooltip.HideTooltip();
+ }
+ }
+
+ private void ShowSplitDialog(ItemDrop.ItemData item, Inventory fromIventory)
+ {
+ m_splitSlider.minValue = 1f;
+ m_splitSlider.maxValue = item.m_stack;
+ m_splitSlider.value = Mathf.CeilToInt((float)item.m_stack / 2f);
+ m_splitIcon.sprite = item.GetIcon();
+ m_splitIconName.text = Localization.instance.Localize(item.m_shared.m_name);
+ m_splitPanel.gameObject.SetActive(value: true);
+ m_splitItem = item;
+ m_splitInventory = fromIventory;
+ OnSplitSliderChanged(m_splitSlider.value);
+ }
+
+ private void OnSplitSliderChanged(float value)
+ {
+ m_splitAmount.text = (int)value + "/" + (int)m_splitSlider.maxValue;
+ }
+
+ private void OnSplitCancel()
+ {
+ m_splitItem = null;
+ m_splitInventory = null;
+ m_splitPanel.gameObject.SetActive(value: false);
+ }
+
+ private void OnSplitOk()
+ {
+ SetupDragItem(m_splitItem, m_splitInventory, (int)m_splitSlider.value);
+ m_splitItem = null;
+ m_splitInventory = null;
+ m_splitPanel.gameObject.SetActive(value: false);
+ }
+
+ public void OnOpenSkills()
+ {
+ if ((bool)Player.m_localPlayer)
+ {
+ m_skillsDialog.Setup(Player.m_localPlayer);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Skills", 0L);
+ }
+ }
+
+ public void OnOpenTexts()
+ {
+ if ((bool)Player.m_localPlayer)
+ {
+ m_textsDialog.Setup(Player.m_localPlayer);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Texts", 0L);
+ }
+ }
+
+ public void OnOpenTrophies()
+ {
+ m_trophiesPanel.SetActive(value: true);
+ UpdateTrophyList();
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Trophies", 0L);
+ }
+
+ public void OnCloseTrophies()
+ {
+ m_trophiesPanel.SetActive(value: false);
+ }
+
+ private void UpdateTrophyList()
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return;
+ }
+ foreach (GameObject trophy in m_trophyList)
+ {
+ UnityEngine.Object.Destroy(trophy);
+ }
+ m_trophyList.Clear();
+ List<string> trophies = Player.m_localPlayer.GetTrophies();
+ float num = 0f;
+ for (int i = 0; i < trophies.Count; i++)
+ {
+ string text = trophies[i];
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
+ if (itemPrefab == null)
+ {
+ ZLog.LogWarning("Missing trophy prefab:" + text);
+ continue;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_trophieElementPrefab, m_trophieListRoot);
+ gameObject.SetActive(value: true);
+ RectTransform rectTransform = gameObject.transform as RectTransform;
+ rectTransform.anchoredPosition = new Vector2((float)component.m_itemData.m_shared.m_trophyPos.x * m_trophieListSpace, (float)component.m_itemData.m_shared.m_trophyPos.y * (0f - m_trophieListSpace));
+ num = Mathf.Min(num, rectTransform.anchoredPosition.y - m_trophieListSpace);
+ string text2 = Localization.instance.Localize(component.m_itemData.m_shared.m_name);
+ if (text2.EndsWith(" trophy"))
+ {
+ text2 = text2.Remove(text2.Length - 7);
+ }
+ rectTransform.Find("icon_bkg/icon").GetComponent<Image>().sprite = component.m_itemData.GetIcon();
+ rectTransform.Find("name").GetComponent<Text>().text = text2;
+ rectTransform.Find("description").GetComponent<Text>().text = Localization.instance.Localize(component.m_itemData.m_shared.m_name + "_lore");
+ m_trophyList.Add(gameObject);
+ }
+ ZLog.Log("SIZE " + num);
+ float size = Mathf.Max(m_trophieListBaseSize, 0f - num);
+ m_trophieListRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ m_trophyListScroll.value = 1f;
+ }
+
+ public void OnShowVariantSelection()
+ {
+ m_variantDialog.Setup(m_selectedRecipe.Key.m_item.m_itemData);
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "VariantSelection", 0L);
+ }
+
+ private void OnVariantSelected(int index)
+ {
+ ZLog.Log("Item variant selected " + index);
+ m_selectedVariant = index;
+ }
+
+ public bool InUpradeTab()
+ {
+ return !m_tabUpgrade.interactable;
+ }
+
+ public bool InCraftTab()
+ {
+ return !m_tabCraft.interactable;
+ }
+
+ public void OnTabCraftPressed()
+ {
+ m_tabCraft.interactable = false;
+ m_tabUpgrade.interactable = true;
+ UpdateCraftingPanel();
+ }
+
+ public void OnTabUpgradePressed()
+ {
+ m_tabCraft.interactable = true;
+ m_tabUpgrade.interactable = false;
+ UpdateCraftingPanel();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemDrop.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemDrop.cs
new file mode 100644
index 0000000..55e21cb
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemDrop.cs
@@ -0,0 +1,970 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+
+public class ItemDrop : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public class ItemData
+ {
+ public enum ItemType
+ {
+ None = 0,
+ Material = 1,
+ Consumable = 2,
+ OneHandedWeapon = 3,
+ Bow = 4,
+ Shield = 5,
+ Helmet = 6,
+ Chest = 7,
+ Ammo = 9,
+ Customization = 10,
+ Legs = 11,
+ Hands = 12,
+ Trophie = 13,
+ TwoHandedWeapon = 14,
+ Torch = 15,
+ Misc = 16,
+ Shoulder = 17,
+ Utility = 18,
+ Tool = 19,
+ Attach_Atgeir = 20
+ }
+
+ public enum AnimationState
+ {
+ Unarmed,
+ OneHanded,
+ TwoHandedClub,
+ Bow,
+ Shield,
+ Torch,
+ LeftTorch,
+ Atgeir,
+ TwoHandedAxe,
+ FishingRod
+ }
+
+ public enum AiTarget
+ {
+ Enemy,
+ FriendHurt,
+ Friend
+ }
+
+ [Serializable]
+ public class SharedData
+ {
+ public string m_name = "";
+
+ public string m_dlc = "";
+
+ public ItemType m_itemType = ItemType.Misc;
+
+ public Sprite[] m_icons = new Sprite[0];
+
+ public ItemType m_attachOverride;
+
+ [TextArea]
+ public string m_description = "";
+
+ public int m_maxStackSize = 1;
+
+ public int m_maxQuality = 1;
+
+ public float m_weight = 1f;
+
+ public int m_value;
+
+ public bool m_teleportable = true;
+
+ public bool m_questItem;
+
+ public float m_equipDuration = 1f;
+
+ public int m_variants;
+
+ public Vector2Int m_trophyPos = Vector2Int.zero;
+
+ public PieceTable m_buildPieces;
+
+ public bool m_centerCamera;
+
+ public string m_setName = "";
+
+ public int m_setSize;
+
+ public StatusEffect m_setStatusEffect;
+
+ public StatusEffect m_equipStatusEffect;
+
+ public float m_movementModifier;
+
+ [Header("Food settings")]
+ public float m_food;
+
+ public float m_foodStamina;
+
+ public float m_foodBurnTime;
+
+ public float m_foodRegen;
+
+ public Color m_foodColor = Color.white;
+
+ [Header("Armor settings")]
+ public Material m_armorMaterial;
+
+ public bool m_helmetHideHair = true;
+
+ public float m_armor = 10f;
+
+ public float m_armorPerLevel = 1f;
+
+ public List<HitData.DamageModPair> m_damageModifiers = new List<HitData.DamageModPair>();
+
+ [Header("Shield settings")]
+ public float m_blockPower = 10f;
+
+ public float m_blockPowerPerLevel;
+
+ public float m_deflectionForce;
+
+ public float m_deflectionForcePerLevel;
+
+ public float m_timedBlockBonus = 1.5f;
+
+ [Header("Weapon")]
+ public AnimationState m_animationState = AnimationState.OneHanded;
+
+ public Skills.SkillType m_skillType = Skills.SkillType.Swords;
+
+ public int m_toolTier;
+
+ public HitData.DamageTypes m_damages;
+
+ public HitData.DamageTypes m_damagesPerLevel;
+
+ public float m_attackForce = 30f;
+
+ public float m_backstabBonus = 4f;
+
+ public bool m_dodgeable;
+
+ public bool m_blockable;
+
+ public StatusEffect m_attackStatusEffect;
+
+ public GameObject m_spawnOnHit;
+
+ public GameObject m_spawnOnHitTerrain;
+
+ [Header("Attacks")]
+ public Attack m_attack;
+
+ public Attack m_secondaryAttack;
+
+ [Header("Durability")]
+ public bool m_useDurability;
+
+ public bool m_destroyBroken = true;
+
+ public bool m_canBeReparied = true;
+
+ public float m_maxDurability = 100f;
+
+ public float m_durabilityPerLevel = 50f;
+
+ public float m_useDurabilityDrain = 1f;
+
+ public float m_durabilityDrain;
+
+ [Header("Hold")]
+ public float m_holdDurationMin;
+
+ public float m_holdStaminaDrain;
+
+ public string m_holdAnimationState = "";
+
+ [Header("Ammo")]
+ public string m_ammoType = "";
+
+ [Header("AI")]
+ public float m_aiAttackRange = 2f;
+
+ public float m_aiAttackRangeMin;
+
+ public float m_aiAttackInterval = 2f;
+
+ public float m_aiAttackMaxAngle = 5f;
+
+ public bool m_aiWhenFlying = true;
+
+ public bool m_aiWhenWalking = true;
+
+ public bool m_aiWhenSwiming = true;
+
+ public bool m_aiPrioritized;
+
+ public AiTarget m_aiTargetType;
+
+ [Header("Effects")]
+ public EffectList m_hitEffect = new EffectList();
+
+ public EffectList m_hitTerrainEffect = new EffectList();
+
+ public EffectList m_blockEffect = new EffectList();
+
+ public EffectList m_startEffect = new EffectList();
+
+ public EffectList m_holdStartEffect = new EffectList();
+
+ public EffectList m_triggerEffect = new EffectList();
+
+ public EffectList m_trailStartEffect = new EffectList();
+
+ [Header("Consumable")]
+ public StatusEffect m_consumeStatusEffect;
+ }
+
+ public int m_stack = 1;
+
+ public float m_durability = 100f;
+
+ public int m_quality = 1;
+
+ public int m_variant;
+
+ public SharedData m_shared;
+
+ [NonSerialized]
+ public long m_crafterID;
+
+ [NonSerialized]
+ public string m_crafterName = "";
+
+ [NonSerialized]
+ public Vector2i m_gridPos = Vector2i.zero;
+
+ [NonSerialized]
+ public bool m_equiped;
+
+ [NonSerialized]
+ public GameObject m_dropPrefab;
+
+ [NonSerialized]
+ public float m_lastAttackTime;
+
+ [NonSerialized]
+ public GameObject m_lastProjectile;
+
+ public ItemData Clone()
+ {
+ return MemberwiseClone() as ItemData;
+ }
+
+ public bool IsEquipable()
+ {
+ if (m_shared.m_itemType != ItemType.Tool && m_shared.m_itemType != ItemType.OneHandedWeapon && m_shared.m_itemType != ItemType.TwoHandedWeapon && m_shared.m_itemType != ItemType.Bow && m_shared.m_itemType != ItemType.Shield && m_shared.m_itemType != ItemType.Helmet && m_shared.m_itemType != ItemType.Chest && m_shared.m_itemType != ItemType.Legs && m_shared.m_itemType != ItemType.Shoulder && m_shared.m_itemType != ItemType.Ammo && m_shared.m_itemType != ItemType.Torch)
+ {
+ return m_shared.m_itemType == ItemType.Utility;
+ }
+ return true;
+ }
+
+ public bool IsWeapon()
+ {
+ if (m_shared.m_itemType != ItemType.OneHandedWeapon && m_shared.m_itemType != ItemType.Bow && m_shared.m_itemType != ItemType.TwoHandedWeapon)
+ {
+ return m_shared.m_itemType == ItemType.Torch;
+ }
+ return true;
+ }
+
+ public bool HavePrimaryAttack()
+ {
+ return !string.IsNullOrEmpty(m_shared.m_attack.m_attackAnimation);
+ }
+
+ public bool HaveSecondaryAttack()
+ {
+ return !string.IsNullOrEmpty(m_shared.m_secondaryAttack.m_attackAnimation);
+ }
+
+ public float GetArmor()
+ {
+ return GetArmor(m_quality);
+ }
+
+ public float GetArmor(int quality)
+ {
+ return m_shared.m_armor + (float)Mathf.Max(0, quality - 1) * m_shared.m_armorPerLevel;
+ }
+
+ public int GetValue()
+ {
+ return m_shared.m_value * m_stack;
+ }
+
+ public float GetWeight()
+ {
+ return m_shared.m_weight * (float)m_stack;
+ }
+
+ public HitData.DamageTypes GetDamage()
+ {
+ return GetDamage(m_quality);
+ }
+
+ public float GetDurabilityPercentage()
+ {
+ float maxDurability = GetMaxDurability();
+ if (maxDurability == 0f)
+ {
+ return 1f;
+ }
+ return Mathf.Clamp01(m_durability / maxDurability);
+ }
+
+ public float GetMaxDurability()
+ {
+ return GetMaxDurability(m_quality);
+ }
+
+ public float GetMaxDurability(int quality)
+ {
+ return m_shared.m_maxDurability + (float)Mathf.Max(0, quality - 1) * m_shared.m_durabilityPerLevel;
+ }
+
+ public HitData.DamageTypes GetDamage(int quality)
+ {
+ HitData.DamageTypes damages = m_shared.m_damages;
+ if (quality > 1)
+ {
+ damages.Add(m_shared.m_damagesPerLevel, quality - 1);
+ }
+ return damages;
+ }
+
+ public float GetBaseBlockPower()
+ {
+ return GetBaseBlockPower(m_quality);
+ }
+
+ public float GetBaseBlockPower(int quality)
+ {
+ return m_shared.m_blockPower + (float)Mathf.Max(0, quality - 1) * m_shared.m_blockPowerPerLevel;
+ }
+
+ public float GetBlockPower(float skillFactor)
+ {
+ return GetBlockPower(m_quality, skillFactor);
+ }
+
+ public float GetBlockPower(int quality, float skillFactor)
+ {
+ float baseBlockPower = GetBaseBlockPower(quality);
+ return baseBlockPower + baseBlockPower * skillFactor * 0.5f;
+ }
+
+ public float GetBlockPowerTooltip(int quality)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return 0f;
+ }
+ float skillFactor = Player.m_localPlayer.GetSkillFactor(Skills.SkillType.Blocking);
+ return GetBlockPower(quality, skillFactor);
+ }
+
+ public float GetDeflectionForce()
+ {
+ return GetDeflectionForce(m_quality);
+ }
+
+ public float GetDeflectionForce(int quality)
+ {
+ return m_shared.m_deflectionForce + (float)Mathf.Max(0, quality - 1) * m_shared.m_deflectionForcePerLevel;
+ }
+
+ public string GetTooltip()
+ {
+ return GetTooltip(this, m_quality, crafting: false);
+ }
+
+ public Sprite GetIcon()
+ {
+ return m_shared.m_icons[m_variant];
+ }
+
+ private static void AddHandedTip(ItemData item, StringBuilder text)
+ {
+ switch (item.m_shared.m_itemType)
+ {
+ case ItemType.OneHandedWeapon:
+ case ItemType.Shield:
+ case ItemType.Torch:
+ text.Append("\n$item_onehanded");
+ break;
+ case ItemType.Bow:
+ case ItemType.TwoHandedWeapon:
+ case ItemType.Tool:
+ text.Append("\n$item_twohanded");
+ break;
+ }
+ }
+
+ public static string GetTooltip(ItemData item, int qualityLevel, bool crafting)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ StringBuilder stringBuilder = new StringBuilder(256);
+ stringBuilder.Append(item.m_shared.m_description);
+ stringBuilder.Append("\n\n");
+ if (item.m_shared.m_dlc.Length > 0)
+ {
+ stringBuilder.Append("\n<color=aqua>$item_dlc</color>");
+ }
+ AddHandedTip(item, stringBuilder);
+ if (item.m_crafterID != 0L)
+ {
+ stringBuilder.AppendFormat("\n$item_crafter: <color=orange>{0}</color>", item.m_crafterName);
+ }
+ if (!item.m_shared.m_teleportable)
+ {
+ stringBuilder.Append("\n<color=orange>$item_noteleport</color>");
+ }
+ if (item.m_shared.m_value > 0)
+ {
+ stringBuilder.AppendFormat("\n$item_value: <color=orange>{0} ({1})</color>", item.GetValue(), item.m_shared.m_value);
+ }
+ stringBuilder.AppendFormat("\n$item_weight: <color=orange>{0}</color>", item.GetWeight().ToString("0.0"));
+ if (item.m_shared.m_maxQuality > 1)
+ {
+ stringBuilder.AppendFormat("\n$item_quality: <color=orange>{0}</color>", qualityLevel);
+ }
+ if (item.m_shared.m_useDurability)
+ {
+ if (crafting)
+ {
+ float maxDurability = item.GetMaxDurability(qualityLevel);
+ stringBuilder.AppendFormat("\n$item_durability: <color=orange>{0}</color>", maxDurability);
+ }
+ else
+ {
+ float maxDurability2 = item.GetMaxDurability(qualityLevel);
+ float durability = item.m_durability;
+ stringBuilder.AppendFormat("\n$item_durability: <color=orange>{0}%</color> <color=yellow>({1}/{2})</color>", (item.GetDurabilityPercentage() * 100f).ToString("0"), durability.ToString("0"), maxDurability2.ToString("0"));
+ }
+ if (item.m_shared.m_canBeReparied)
+ {
+ Recipe recipe = ObjectDB.instance.GetRecipe(item);
+ if (recipe != null)
+ {
+ int minStationLevel = recipe.m_minStationLevel;
+ stringBuilder.AppendFormat("\n$item_repairlevel: <color=orange>{0}</color>", minStationLevel.ToString());
+ }
+ }
+ }
+ switch (item.m_shared.m_itemType)
+ {
+ case ItemType.Ammo:
+ stringBuilder.Append(item.GetDamage(qualityLevel).GetTooltipString(item.m_shared.m_skillType));
+ stringBuilder.AppendFormat("\n$item_knockback: <color=orange>{0}</color>", item.m_shared.m_attackForce);
+ break;
+ case ItemType.OneHandedWeapon:
+ case ItemType.Bow:
+ case ItemType.TwoHandedWeapon:
+ case ItemType.Torch:
+ {
+ stringBuilder.Append(item.GetDamage(qualityLevel).GetTooltipString(item.m_shared.m_skillType));
+ stringBuilder.AppendFormat("\n$item_blockpower: <color=orange>{0}</color> <color=yellow>({1})</color>", item.GetBaseBlockPower(qualityLevel), item.GetBlockPowerTooltip(qualityLevel).ToString("0"));
+ if (item.m_shared.m_timedBlockBonus > 1f)
+ {
+ stringBuilder.AppendFormat("\n$item_deflection: <color=orange>{0}</color>", item.GetDeflectionForce(qualityLevel));
+ stringBuilder.AppendFormat("\n$item_parrybonus: <color=orange>{0}x</color>", item.m_shared.m_timedBlockBonus);
+ }
+ stringBuilder.AppendFormat("\n$item_knockback: <color=orange>{0}</color>", item.m_shared.m_attackForce);
+ stringBuilder.AppendFormat("\n$item_backstab: <color=orange>{0}x</color>", item.m_shared.m_backstabBonus);
+ string projectileTooltip = item.GetProjectileTooltip(qualityLevel);
+ if (projectileTooltip.Length > 0)
+ {
+ stringBuilder.Append("\n\n");
+ stringBuilder.Append(projectileTooltip);
+ }
+ string statusEffectTooltip3 = item.GetStatusEffectTooltip();
+ if (statusEffectTooltip3.Length > 0)
+ {
+ stringBuilder.Append("\n\n");
+ stringBuilder.Append(statusEffectTooltip3);
+ }
+ break;
+ }
+ case ItemType.Helmet:
+ case ItemType.Chest:
+ case ItemType.Legs:
+ case ItemType.Shoulder:
+ {
+ stringBuilder.AppendFormat("\n$item_armor: <color=orange>{0}</color>", item.GetArmor(qualityLevel));
+ string damageModifiersTooltipString = SE_Stats.GetDamageModifiersTooltipString(item.m_shared.m_damageModifiers);
+ if (damageModifiersTooltipString.Length > 0)
+ {
+ stringBuilder.Append(damageModifiersTooltipString);
+ }
+ string statusEffectTooltip2 = item.GetStatusEffectTooltip();
+ if (statusEffectTooltip2.Length > 0)
+ {
+ stringBuilder.Append("\n\n");
+ stringBuilder.Append(statusEffectTooltip2);
+ }
+ break;
+ }
+ case ItemType.Shield:
+ stringBuilder.AppendFormat("\n$item_blockpower: <color=orange>{0}</color> <color=yellow>({1})</color>", item.GetBaseBlockPower(qualityLevel), item.GetBlockPowerTooltip(qualityLevel).ToString("0"));
+ if (item.m_shared.m_timedBlockBonus > 1f)
+ {
+ stringBuilder.AppendFormat("\n$item_deflection: <color=orange>{0}</color>", item.GetDeflectionForce(qualityLevel));
+ stringBuilder.AppendFormat("\n$item_parrybonus: <color=orange>{0}x</color>", item.m_shared.m_timedBlockBonus);
+ }
+ break;
+ case ItemType.Consumable:
+ {
+ if (item.m_shared.m_food > 0f)
+ {
+ stringBuilder.AppendFormat("\n$item_food_health: <color=orange>{0}</color>", item.m_shared.m_food);
+ stringBuilder.AppendFormat("\n$item_food_stamina: <color=orange>{0}</color>", item.m_shared.m_foodStamina);
+ stringBuilder.AppendFormat("\n$item_food_duration: <color=orange>{0}s</color>", item.m_shared.m_foodBurnTime);
+ stringBuilder.AppendFormat("\n$item_food_regen: <color=orange>{0} hp/tick</color>", item.m_shared.m_foodRegen);
+ }
+ string statusEffectTooltip = item.GetStatusEffectTooltip();
+ if (statusEffectTooltip.Length > 0)
+ {
+ stringBuilder.Append("\n\n");
+ stringBuilder.Append(statusEffectTooltip);
+ }
+ break;
+ }
+ }
+ if (item.m_shared.m_movementModifier != 0f && localPlayer != null)
+ {
+ float equipmentMovementModifier = localPlayer.GetEquipmentMovementModifier();
+ stringBuilder.AppendFormat("\n$item_movement_modifier: <color=orange>{0}%</color> ($item_total:<color=yellow>{1}%</color>)", (item.m_shared.m_movementModifier * 100f).ToString("+0;-0"), (equipmentMovementModifier * 100f).ToString("+0;-0"));
+ }
+ string setStatusEffectTooltip = item.GetSetStatusEffectTooltip();
+ if (setStatusEffectTooltip.Length > 0)
+ {
+ stringBuilder.AppendFormat("\n\n$item_seteffect (<color=orange>{0}</color> $item_parts):<color=orange>{1}</color>", item.m_shared.m_setSize, setStatusEffectTooltip);
+ }
+ return stringBuilder.ToString();
+ }
+
+ private string GetStatusEffectTooltip()
+ {
+ if ((bool)m_shared.m_attackStatusEffect)
+ {
+ return m_shared.m_attackStatusEffect.GetTooltipString();
+ }
+ if ((bool)m_shared.m_consumeStatusEffect)
+ {
+ return m_shared.m_consumeStatusEffect.GetTooltipString();
+ }
+ return "";
+ }
+
+ private string GetSetStatusEffectTooltip()
+ {
+ if ((bool)m_shared.m_setStatusEffect)
+ {
+ StatusEffect setStatusEffect = m_shared.m_setStatusEffect;
+ if (setStatusEffect != null)
+ {
+ return setStatusEffect.GetTooltipString();
+ }
+ }
+ return "";
+ }
+
+ private string GetProjectileTooltip(int itemQuality)
+ {
+ string text = "";
+ if ((bool)m_shared.m_attack.m_attackProjectile)
+ {
+ IProjectile component = m_shared.m_attack.m_attackProjectile.GetComponent<IProjectile>();
+ if (component != null)
+ {
+ text += component.GetTooltipString(itemQuality);
+ }
+ }
+ if ((bool)m_shared.m_spawnOnHit)
+ {
+ IProjectile component2 = m_shared.m_spawnOnHit.GetComponent<IProjectile>();
+ if (component2 != null)
+ {
+ text += component2.GetTooltipString(itemQuality);
+ }
+ }
+ return text;
+ }
+ }
+
+ private static List<ItemDrop> m_instances = new List<ItemDrop>();
+
+ private int m_myIndex = -1;
+
+ public bool m_autoPickup = true;
+
+ public bool m_autoDestroy = true;
+
+ public ItemData m_itemData = new ItemData();
+
+ private ZNetView m_nview;
+
+ private Character m_pickupRequester;
+
+ private float m_lastOwnerRequest;
+
+ private float m_spawnTime;
+
+ private const double m_autoDestroyTimeout = 3600.0;
+
+ private const double m_autoPickupDelay = 0.5;
+
+ private const float m_autoDespawnBaseMinAltitude = -2f;
+
+ private const int m_autoStackTreshold = 200;
+
+ private const float m_autoStackRange = 4f;
+
+ private static int m_itemMask = 0;
+
+ private bool m_haveAutoStacked;
+
+ private void Awake()
+ {
+ m_myIndex = m_instances.Count;
+ m_instances.Add(this);
+ string prefabName = GetPrefabName(base.gameObject.name);
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
+ m_itemData.m_dropPrefab = itemPrefab;
+ if (Application.isEditor)
+ {
+ m_itemData.m_shared = itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared;
+ }
+ Rigidbody component = GetComponent<Rigidbody>();
+ if ((bool)component)
+ {
+ component.maxDepenetrationVelocity = 1f;
+ }
+ m_spawnTime = Time.time;
+ m_nview = GetComponent<ZNetView>();
+ if ((bool)m_nview && m_nview.IsValid())
+ {
+ if (m_nview.IsOwner() && new DateTime(m_nview.GetZDO().GetLong("SpawnTime", 0L)).Ticks == 0L)
+ {
+ m_nview.GetZDO().Set("SpawnTime", ZNet.instance.GetTime().Ticks);
+ }
+ m_nview.Register("RequestOwn", RPC_RequestOwn);
+ Load();
+ InvokeRepeating("SlowUpdate", UnityEngine.Random.Range(1f, 2f), 10f);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ m_instances[m_myIndex] = m_instances[m_instances.Count - 1];
+ m_instances[m_myIndex].m_myIndex = m_myIndex;
+ m_instances.RemoveAt(m_instances.Count - 1);
+ }
+
+ private void Start()
+ {
+ Save();
+ base.gameObject.GetComponentInChildren<IEquipmentVisual>()?.Setup(m_itemData.m_variant);
+ }
+
+ private double GetTimeSinceSpawned()
+ {
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("SpawnTime", 0L));
+ return (ZNet.instance.GetTime() - dateTime).TotalSeconds;
+ }
+
+ private void SlowUpdate()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ TerrainCheck();
+ if (m_autoDestroy)
+ {
+ TimedDestruction();
+ }
+ if (m_instances.Count > 200)
+ {
+ AutoStackItems();
+ }
+ }
+ }
+
+ private void TerrainCheck()
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ if (base.transform.position.y - groundHeight < -0.5f)
+ {
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + 0.5f;
+ base.transform.position = position;
+ Rigidbody component = GetComponent<Rigidbody>();
+ if ((bool)component)
+ {
+ component.velocity = Vector3.zero;
+ }
+ }
+ }
+
+ private void TimedDestruction()
+ {
+ if (!IsInsideBase() && !Player.IsPlayerInRange(base.transform.position, 25f) && !(GetTimeSinceSpawned() < 3600.0))
+ {
+ m_nview.Destroy();
+ }
+ }
+
+ private bool IsInsideBase()
+ {
+ if (base.transform.position.y > ZoneSystem.instance.m_waterLevel + -2f && (bool)EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.PlayerBase))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void AutoStackItems()
+ {
+ if (m_itemData.m_shared.m_maxStackSize <= 1 || m_itemData.m_stack >= m_itemData.m_shared.m_maxStackSize || m_haveAutoStacked)
+ {
+ return;
+ }
+ m_haveAutoStacked = true;
+ if (m_itemMask == 0)
+ {
+ m_itemMask = LayerMask.GetMask("item");
+ }
+ bool flag = false;
+ Collider[] array = Physics.OverlapSphere(base.transform.position, 4f, m_itemMask);
+ foreach (Collider collider in array)
+ {
+ if (!collider.attachedRigidbody)
+ {
+ continue;
+ }
+ ItemDrop component = collider.attachedRigidbody.GetComponent<ItemDrop>();
+ if (!(component == null) && !(component == this) && !(component.m_nview == null) && component.m_nview.IsValid() && component.m_nview.IsOwner() && !(component.m_itemData.m_shared.m_name != m_itemData.m_shared.m_name) && component.m_itemData.m_quality == m_itemData.m_quality)
+ {
+ int num = m_itemData.m_shared.m_maxStackSize - m_itemData.m_stack;
+ if (num == 0)
+ {
+ break;
+ }
+ if (component.m_itemData.m_stack <= num)
+ {
+ m_itemData.m_stack += component.m_itemData.m_stack;
+ flag = true;
+ component.m_nview.Destroy();
+ }
+ }
+ }
+ if (flag)
+ {
+ Save();
+ }
+ }
+
+ public string GetHoverText()
+ {
+ string text = m_itemData.m_shared.m_name;
+ if (m_itemData.m_quality > 1)
+ {
+ text = text + "[" + m_itemData.m_quality + "] ";
+ }
+ if (m_itemData.m_stack > 1)
+ {
+ text = text + " x" + m_itemData.m_stack;
+ }
+ return Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] $inventory_pickup");
+ }
+
+ public string GetHoverName()
+ {
+ return m_itemData.m_shared.m_name;
+ }
+
+ private string GetPrefabName(string name)
+ {
+ char[] anyOf = new char[2] { '(', ' ' };
+ int num = name.IndexOfAny(anyOf);
+ if (num >= 0)
+ {
+ return name.Substring(0, num);
+ }
+ return name;
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ Pickup(character);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemData item)
+ {
+ return false;
+ }
+
+ public void Pickup(Humanoid character)
+ {
+ if (m_nview.IsValid())
+ {
+ if (CanPickup())
+ {
+ Load();
+ character.Pickup(base.gameObject);
+ Save();
+ }
+ else
+ {
+ m_pickupRequester = character;
+ CancelInvoke("PickupUpdate");
+ float num = 0.05f;
+ InvokeRepeating("PickupUpdate", num, num);
+ RequestOwn();
+ }
+ }
+ }
+
+ public void RequestOwn()
+ {
+ if (!(Time.time - m_lastOwnerRequest < 0.2f) && !m_nview.IsOwner())
+ {
+ m_lastOwnerRequest = Time.time;
+ m_nview.InvokeRPC("RequestOwn");
+ }
+ }
+
+ public bool RemoveOne()
+ {
+ if (!CanPickup())
+ {
+ RequestOwn();
+ return false;
+ }
+ if (m_itemData.m_stack <= 1)
+ {
+ m_nview.Destroy();
+ return true;
+ }
+ m_itemData.m_stack--;
+ Save();
+ return true;
+ }
+
+ public void OnPlayerDrop()
+ {
+ m_autoPickup = false;
+ }
+
+ public bool CanPickup()
+ {
+ if (m_nview == null || !m_nview.IsValid())
+ {
+ return true;
+ }
+ if ((double)(Time.time - m_spawnTime) < 0.5)
+ {
+ return false;
+ }
+ return m_nview.IsOwner();
+ }
+
+ private void RPC_RequestOwn(long uid)
+ {
+ ZLog.Log("Player " + uid + " wants to pickup " + base.gameObject.name + " im: " + ZDOMan.instance.GetMyID());
+ if (!m_nview.IsOwner())
+ {
+ ZLog.Log(" but im not the owner");
+ }
+ else
+ {
+ m_nview.GetZDO().SetOwner(uid);
+ }
+ }
+
+ private void PickupUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ if (CanPickup())
+ {
+ ZLog.Log("Im finally the owner");
+ CancelInvoke("PickupUpdate");
+ Load();
+ (m_pickupRequester as Player).Pickup(base.gameObject);
+ Save();
+ }
+ else
+ {
+ ZLog.Log("Im still nto the owner");
+ }
+ }
+ }
+
+ private void Save()
+ {
+ if (!(m_nview == null) && m_nview.IsValid() && m_nview.IsOwner())
+ {
+ SaveToZDO(m_itemData, m_nview.GetZDO());
+ }
+ }
+
+ private void Load()
+ {
+ LoadFromZDO(m_itemData, m_nview.GetZDO());
+ }
+
+ public static void SaveToZDO(ItemData itemData, ZDO zdo)
+ {
+ zdo.Set("durability", itemData.m_durability);
+ zdo.Set("stack", itemData.m_stack);
+ zdo.Set("quality", itemData.m_quality);
+ zdo.Set("variant", itemData.m_variant);
+ zdo.Set("crafterID", itemData.m_crafterID);
+ zdo.Set("crafterName", itemData.m_crafterName);
+ }
+
+ public static void LoadFromZDO(ItemData itemData, ZDO zdo)
+ {
+ itemData.m_durability = zdo.GetFloat("durability", itemData.m_durability);
+ itemData.m_stack = zdo.GetInt("stack", itemData.m_stack);
+ itemData.m_quality = zdo.GetInt("quality", itemData.m_quality);
+ itemData.m_variant = zdo.GetInt("variant", itemData.m_variant);
+ itemData.m_crafterID = zdo.GetLong("crafterID", itemData.m_crafterID);
+ itemData.m_crafterName = zdo.GetString("crafterName", itemData.m_crafterName);
+ }
+
+ public static ItemDrop DropItem(ItemData item, int amount, Vector3 position, Quaternion rotation)
+ {
+ ItemDrop component = UnityEngine.Object.Instantiate(item.m_dropPrefab, position, rotation).GetComponent<ItemDrop>();
+ component.m_itemData = item.Clone();
+ if (amount > 0)
+ {
+ component.m_itemData.m_stack = amount;
+ }
+ component.Save();
+ return component;
+ }
+
+ private void OnDrawGizmos()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStand.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStand.cs
new file mode 100644
index 0000000..f068855
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStand.cs
@@ -0,0 +1,392 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ItemStand : MonoBehaviour, Interactable, Hoverable
+{
+ public ZNetView m_netViewOverride;
+
+ public string m_name = "";
+
+ public Transform m_attachOther;
+
+ public Transform m_dropSpawnPoint;
+
+ public bool m_canBeRemoved = true;
+
+ public bool m_autoAttach;
+
+ public List<ItemDrop.ItemData.ItemType> m_supportedTypes = new List<ItemDrop.ItemData.ItemType>();
+
+ public List<ItemDrop> m_unsupportedItems = new List<ItemDrop>();
+
+ public List<ItemDrop> m_supportedItems = new List<ItemDrop>();
+
+ public EffectList m_effects = new EffectList();
+
+ public EffectList m_destroyEffects = new EffectList();
+
+ [Header("Guardian power")]
+ public float m_powerActivationDelay = 2f;
+
+ public StatusEffect m_guardianPower;
+
+ public EffectList m_activatePowerEffects = new EffectList();
+
+ public EffectList m_activatePowerEffectsPlayer = new EffectList();
+
+ private string m_visualName = "";
+
+ private int m_visualVariant;
+
+ private GameObject m_visualItem;
+
+ private string m_currentItemName = "";
+
+ private ItemDrop.ItemData m_queuedItem;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = (m_netViewOverride ? m_netViewOverride : base.gameObject.GetComponent<ZNetView>());
+ if (m_nview.GetZDO() != null)
+ {
+ WearNTear component = GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
+ }
+ m_nview.Register("DropItem", RPC_DropItem);
+ m_nview.Register("RequestOwn", RPC_RequestOwn);
+ m_nview.Register("DestroyAttachment", RPC_DestroyAttachment);
+ m_nview.Register<string, int>("SetVisualItem", RPC_SetVisualItem);
+ InvokeRepeating("UpdateVisual", 1f, 4f);
+ }
+ }
+
+ private void OnDestroyed()
+ {
+ if (m_nview.IsOwner())
+ {
+ DropItem();
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (!Player.m_localPlayer)
+ {
+ return "";
+ }
+ if (HaveAttachment())
+ {
+ if (!m_canBeRemoved)
+ {
+ if (m_guardianPower != null)
+ {
+ if (IsInvoking("DelayedPowerActivation"))
+ {
+ return "";
+ }
+ if (IsGuardianPowerActive(Player.m_localPlayer))
+ {
+ return "";
+ }
+ string tooltipString = m_guardianPower.GetTooltipString();
+ return Localization.instance.Localize("<color=orange>" + m_guardianPower.m_name + "</color>\n" + tooltipString + "\n\n[<color=yellow><b>$KEY_Use</b></color>] $guardianstone_hook_activate");
+ }
+ return "";
+ }
+ return Localization.instance.Localize(m_name + " ( " + m_currentItemName + " )\n[<color=yellow><b>$KEY_Use</b></color>] $piece_itemstand_take");
+ }
+ if (m_autoAttach && m_supportedItems.Count == 1)
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_itemstand_attach");
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>1-8</b></color>] $piece_itemstand_attach");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!HaveAttachment())
+ {
+ if (m_autoAttach && m_supportedItems.Count == 1)
+ {
+ ItemDrop.ItemData item = user.GetInventory().GetItem(m_supportedItems[0].m_itemData.m_shared.m_name);
+ if (item != null)
+ {
+ UseItem(user, item);
+ return true;
+ }
+ user.Message(MessageHud.MessageType.Center, "$piece_itemstand_missingitem");
+ return false;
+ }
+ }
+ else
+ {
+ if (m_canBeRemoved)
+ {
+ m_nview.InvokeRPC("DropItem");
+ return true;
+ }
+ if (m_guardianPower != null)
+ {
+ if (IsInvoking("DelayedPowerActivation"))
+ {
+ return false;
+ }
+ if (IsGuardianPowerActive(user))
+ {
+ return false;
+ }
+ user.Message(MessageHud.MessageType.Center, "$guardianstone_hook_power_activate ");
+ m_activatePowerEffects.Create(base.transform.position, base.transform.rotation);
+ m_activatePowerEffectsPlayer.Create(user.transform.position, Quaternion.identity, user.transform);
+ Invoke("DelayedPowerActivation", m_powerActivationDelay);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsGuardianPowerActive(Humanoid user)
+ {
+ return (user as Player).GetGuardianPowerName() == m_guardianPower.name;
+ }
+
+ private void DelayedPowerActivation()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (!(localPlayer == null))
+ {
+ localPlayer.SetGuardianPower(m_guardianPower.name);
+ }
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (HaveAttachment())
+ {
+ return false;
+ }
+ if (!CanAttach(item))
+ {
+ user.Message(MessageHud.MessageType.Center, "$piece_itemstand_cantattach");
+ return true;
+ }
+ if (!m_nview.IsOwner())
+ {
+ m_nview.InvokeRPC("RequestOwn");
+ }
+ m_queuedItem = item;
+ CancelInvoke("UpdateAttach");
+ InvokeRepeating("UpdateAttach", 0f, 0.1f);
+ return true;
+ }
+
+ private void RPC_DropItem(long sender)
+ {
+ if (m_nview.IsOwner() && m_canBeRemoved)
+ {
+ DropItem();
+ }
+ }
+
+ public void DestroyAttachment()
+ {
+ m_nview.InvokeRPC("DestroyAttachment");
+ }
+
+ public void RPC_DestroyAttachment(long sender)
+ {
+ if (m_nview.IsOwner() && HaveAttachment())
+ {
+ m_nview.GetZDO().Set("item", "");
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", "", 0);
+ m_destroyEffects.Create(m_dropSpawnPoint.position, Quaternion.identity);
+ }
+ }
+
+ private void DropItem()
+ {
+ if (HaveAttachment())
+ {
+ string @string = m_nview.GetZDO().GetString("item");
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(@string);
+ if ((bool)itemPrefab)
+ {
+ GameObject obj = UnityEngine.Object.Instantiate(itemPrefab, m_dropSpawnPoint.position, m_dropSpawnPoint.rotation);
+ ItemDrop.LoadFromZDO(obj.GetComponent<ItemDrop>().m_itemData, m_nview.GetZDO());
+ obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f;
+ m_effects.Create(m_dropSpawnPoint.position, Quaternion.identity);
+ }
+ m_nview.GetZDO().Set("item", "");
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", "", 0);
+ }
+ }
+
+ private Transform GetAttach(ItemDrop.ItemData item)
+ {
+ return m_attachOther;
+ }
+
+ private void UpdateAttach()
+ {
+ if (m_nview.IsOwner())
+ {
+ CancelInvoke("UpdateAttach");
+ Player localPlayer = Player.m_localPlayer;
+ if (m_queuedItem != null && localPlayer != null && localPlayer.GetInventory().ContainsItem(m_queuedItem) && !HaveAttachment())
+ {
+ ItemDrop.ItemData itemData = m_queuedItem.Clone();
+ itemData.m_stack = 1;
+ m_nview.GetZDO().Set("item", m_queuedItem.m_dropPrefab.name);
+ ItemDrop.SaveToZDO(itemData, m_nview.GetZDO());
+ localPlayer.UnequipItem(m_queuedItem);
+ localPlayer.GetInventory().RemoveOneItem(m_queuedItem);
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", itemData.m_dropPrefab.name, itemData.m_variant);
+ Transform attach = GetAttach(m_queuedItem);
+ m_effects.Create(attach.transform.position, Quaternion.identity);
+ }
+ m_queuedItem = null;
+ }
+ }
+
+ private void RPC_RequestOwn(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().SetOwner(sender);
+ }
+ }
+
+ private void UpdateVisual()
+ {
+ string @string = m_nview.GetZDO().GetString("item");
+ int @int = m_nview.GetZDO().GetInt("variant");
+ SetVisualItem(@string, @int);
+ }
+
+ private void RPC_SetVisualItem(long sender, string itemName, int variant)
+ {
+ SetVisualItem(itemName, variant);
+ }
+
+ private void SetVisualItem(string itemName, int variant)
+ {
+ if (m_visualName == itemName && m_visualVariant == variant)
+ {
+ return;
+ }
+ m_visualName = itemName;
+ m_visualVariant = variant;
+ m_currentItemName = "";
+ if (m_visualName == "")
+ {
+ UnityEngine.Object.Destroy(m_visualItem);
+ return;
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
+ if (itemPrefab == null)
+ {
+ ZLog.LogWarning("Missing item prefab " + itemName);
+ return;
+ }
+ GameObject attachPrefab = GetAttachPrefab(itemPrefab);
+ if (attachPrefab == null)
+ {
+ ZLog.LogWarning("Failed to get attach prefab for item " + itemName);
+ return;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ m_currentItemName = component.m_itemData.m_shared.m_name;
+ Transform attach = GetAttach(component.m_itemData);
+ m_visualItem = UnityEngine.Object.Instantiate(attachPrefab, attach.position, attach.rotation, attach);
+ m_visualItem.transform.localPosition = attachPrefab.transform.localPosition;
+ m_visualItem.transform.localRotation = attachPrefab.transform.localRotation;
+ m_visualItem.GetComponentInChildren<IEquipmentVisual>()?.Setup(m_visualVariant);
+ }
+
+ private GameObject GetAttachPrefab(GameObject item)
+ {
+ Transform transform = item.transform.Find("attach");
+ if ((bool)transform)
+ {
+ return transform.gameObject;
+ }
+ return null;
+ }
+
+ private bool CanAttach(ItemDrop.ItemData item)
+ {
+ if (GetAttachPrefab(item.m_dropPrefab) == null)
+ {
+ return false;
+ }
+ if (IsUnsupported(item))
+ {
+ return false;
+ }
+ if (!IsSupported(item))
+ {
+ return false;
+ }
+ return m_supportedTypes.Contains(item.m_shared.m_itemType);
+ }
+
+ public bool IsUnsupported(ItemDrop.ItemData item)
+ {
+ foreach (ItemDrop unsupportedItem in m_unsupportedItems)
+ {
+ if (unsupportedItem.m_itemData.m_shared.m_name == item.m_shared.m_name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsSupported(ItemDrop.ItemData item)
+ {
+ if (m_supportedItems.Count == 0)
+ {
+ return true;
+ }
+ foreach (ItemDrop supportedItem in m_supportedItems)
+ {
+ if (supportedItem.m_itemData.m_shared.m_name == item.m_shared.m_name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool HaveAttachment()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetString("item") != "";
+ }
+
+ public string GetAttachedItem()
+ {
+ if (!m_nview.IsValid())
+ {
+ return "";
+ }
+ return m_nview.GetZDO().GetString("item");
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStyle.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStyle.cs
new file mode 100644
index 0000000..eefa038
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ItemStyle.cs
@@ -0,0 +1,9 @@
+using UnityEngine;
+
+public class ItemStyle : MonoBehaviour, IEquipmentVisual
+{
+ public void Setup(int style)
+ {
+ GetComponent<Renderer>().material.SetFloat("_Style", style);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/KeyHints.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/KeyHints.cs
new file mode 100644
index 0000000..176f9fc
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/KeyHints.cs
@@ -0,0 +1,95 @@
+using UnityEngine;
+
+public class KeyHints : MonoBehaviour
+{
+ private static KeyHints m_instance;
+
+ [Header("Key hints")]
+ public GameObject m_buildHints;
+
+ public GameObject m_combatHints;
+
+ public GameObject m_primaryAttackGP;
+
+ public GameObject m_primaryAttackKB;
+
+ public GameObject m_secondaryAttackGP;
+
+ public GameObject m_secondaryAttackKB;
+
+ public GameObject m_bowDrawGP;
+
+ public GameObject m_bowDrawKB;
+
+ private bool m_keyHintsEnabled = true;
+
+ public static KeyHints instance => m_instance;
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Awake()
+ {
+ m_instance = this;
+ ApplySettings();
+ }
+
+ private void Start()
+ {
+ }
+
+ public void ApplySettings()
+ {
+ m_keyHintsEnabled = PlayerPrefs.GetInt("KeyHints", 1) == 1;
+ }
+
+ private void Update()
+ {
+ UpdateHints();
+ }
+
+ private void UpdateHints()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (!m_keyHintsEnabled || localPlayer == null || localPlayer.IsDead() || Chat.instance.IsChatDialogWindowVisible())
+ {
+ m_buildHints.SetActive(value: false);
+ m_combatHints.SetActive(value: false);
+ return;
+ }
+ _ = m_buildHints.activeSelf;
+ _ = m_buildHints.activeSelf;
+ ItemDrop.ItemData currentWeapon = localPlayer.GetCurrentWeapon();
+ if (localPlayer.InPlaceMode())
+ {
+ m_buildHints.SetActive(value: true);
+ m_combatHints.SetActive(value: false);
+ }
+ else if ((bool)localPlayer.GetShipControl())
+ {
+ m_buildHints.SetActive(value: false);
+ m_combatHints.SetActive(value: false);
+ }
+ else if (currentWeapon != null && (currentWeapon != localPlayer.m_unarmedWeapon.m_itemData || localPlayer.IsTargeted()))
+ {
+ m_buildHints.SetActive(value: false);
+ m_combatHints.SetActive(value: true);
+ bool flag = currentWeapon.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Bow;
+ bool active = !flag && currentWeapon.HavePrimaryAttack();
+ bool active2 = !flag && currentWeapon.HaveSecondaryAttack();
+ m_bowDrawGP.SetActive(flag);
+ m_bowDrawKB.SetActive(flag);
+ m_primaryAttackGP.SetActive(active);
+ m_primaryAttackKB.SetActive(active);
+ m_secondaryAttackGP.SetActive(active2);
+ m_secondaryAttackKB.SetActive(active2);
+ }
+ else
+ {
+ m_buildHints.SetActive(value: false);
+ m_combatHints.SetActive(value: false);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ladder.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ladder.cs
new file mode 100644
index 0000000..e139dde
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ladder.cs
@@ -0,0 +1,50 @@
+using UnityEngine;
+
+public class Ladder : MonoBehaviour, Interactable, Hoverable
+{
+ public Transform m_targetPos;
+
+ public string m_name = "Ladder";
+
+ public float m_useDistance = 2f;
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!InUseDistance(character))
+ {
+ return false;
+ }
+ character.transform.position = m_targetPos.position;
+ character.transform.rotation = m_targetPos.rotation;
+ character.SetLookDir(m_targetPos.forward);
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public string GetHoverText()
+ {
+ if (!InUseDistance(Player.m_localPlayer))
+ {
+ return Localization.instance.Localize("<color=grey>$piece_toofar</color>");
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ private bool InUseDistance(Humanoid human)
+ {
+ return Vector3.Distance(human.transform.position, base.transform.position) < m_useDistance;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ledge.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ledge.cs
new file mode 100644
index 0000000..dd78829
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ledge.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Ledge : MonoBehaviour
+{
+ public Collider m_collider;
+
+ public TriggerTracker m_above;
+
+ private void Awake()
+ {
+ if (GetComponent<ZNetView>().GetZDO() != null)
+ {
+ m_collider.enabled = true;
+ TriggerTracker above = m_above;
+ above.m_changed = (Action)Delegate.Combine(above.m_changed, new Action(Changed));
+ }
+ }
+
+ private void Changed()
+ {
+ List<Collider> colliders = m_above.GetColliders();
+ if (colliders.Count == 0)
+ {
+ m_collider.enabled = true;
+ return;
+ }
+ bool flag = false;
+ foreach (Collider item in colliders)
+ {
+ if (item.transform.position.y > base.transform.position.y)
+ {
+ flag = true;
+ break;
+ }
+ }
+ m_collider.enabled = flag;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LevelEffects.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LevelEffects.cs
new file mode 100644
index 0000000..9cb9333
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LevelEffects.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class LevelEffects : MonoBehaviour
+{
+ [Serializable]
+ public class LevelSetup
+ {
+ public float m_scale = 1f;
+
+ public float m_hue;
+
+ public float m_saturation;
+
+ public float m_value;
+
+ public GameObject m_enableObject;
+ }
+
+ public Renderer m_mainRender;
+
+ public GameObject m_baseEnableObject;
+
+ public List<LevelSetup> m_levelSetups = new List<LevelSetup>();
+
+ private static Dictionary<string, Material> m_materials = new Dictionary<string, Material>();
+
+ private Character m_character;
+
+ private void Start()
+ {
+ m_character = GetComponentInParent<Character>();
+ Character character = m_character;
+ character.m_onLevelSet = (Action<int>)Delegate.Combine(character.m_onLevelSet, new Action<int>(OnLevelSet));
+ SetupLevelVisualization(m_character.GetLevel());
+ }
+
+ private void OnLevelSet(int level)
+ {
+ SetupLevelVisualization(level);
+ }
+
+ private void SetupLevelVisualization(int level)
+ {
+ if (level <= 1 || m_levelSetups.Count < level - 1)
+ {
+ return;
+ }
+ LevelSetup levelSetup = m_levelSetups[level - 2];
+ base.transform.localScale = new Vector3(levelSetup.m_scale, levelSetup.m_scale, levelSetup.m_scale);
+ if ((bool)m_mainRender)
+ {
+ string key = m_character.m_name + level;
+ if (m_materials.TryGetValue(key, out var value))
+ {
+ Material[] sharedMaterials = m_mainRender.sharedMaterials;
+ sharedMaterials[0] = value;
+ m_mainRender.sharedMaterials = sharedMaterials;
+ }
+ else
+ {
+ Material[] sharedMaterials2 = m_mainRender.sharedMaterials;
+ sharedMaterials2[0] = new Material(sharedMaterials2[0]);
+ sharedMaterials2[0].SetFloat("_Hue", levelSetup.m_hue);
+ sharedMaterials2[0].SetFloat("_Saturation", levelSetup.m_saturation);
+ sharedMaterials2[0].SetFloat("_Value", levelSetup.m_value);
+ m_mainRender.sharedMaterials = sharedMaterials2;
+ m_materials[key] = sharedMaterials2[0];
+ }
+ }
+ if ((bool)m_baseEnableObject)
+ {
+ m_baseEnableObject.SetActive(value: false);
+ }
+ if ((bool)levelSetup.m_enableObject)
+ {
+ levelSetup.m_enableObject.SetActive(value: true);
+ }
+ }
+
+ public void GetColorChanges(out float hue, out float saturation, out float value)
+ {
+ int level = m_character.GetLevel();
+ if (level > 1 && m_levelSetups.Count >= level - 1)
+ {
+ LevelSetup levelSetup = m_levelSetups[level - 2];
+ hue = levelSetup.m_hue;
+ saturation = levelSetup.m_saturation;
+ value = levelSetup.m_value;
+ }
+ else
+ {
+ hue = 0f;
+ saturation = 0f;
+ value = 0f;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Leviathan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Leviathan.cs
new file mode 100644
index 0000000..1a7a21c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Leviathan.cs
@@ -0,0 +1,91 @@
+using System;
+using UnityEngine;
+
+public class Leviathan : MonoBehaviour
+{
+ public float m_waveScale = 0.5f;
+
+ public float m_floatOffset;
+
+ public float m_movementSpeed = 0.1f;
+
+ public float m_maxSpeed = 1f;
+
+ public MineRock m_mineRock;
+
+ public float m_hitReactionChance = 0.25f;
+
+ public int m_leaveDelay = 5;
+
+ public EffectList m_reactionEffects = new EffectList();
+
+ public EffectList m_leaveEffects = new EffectList();
+
+ private Rigidbody m_body;
+
+ private ZNetView m_nview;
+
+ private ZSyncAnimation m_zanimator;
+
+ private Animator m_animator;
+
+ private bool m_left;
+
+ private void Awake()
+ {
+ m_body = GetComponent<Rigidbody>();
+ m_nview = GetComponent<ZNetView>();
+ m_zanimator = GetComponent<ZSyncAnimation>();
+ m_animator = GetComponentInChildren<Animator>();
+ if ((bool)GetComponent<MineRock>())
+ {
+ MineRock mineRock = m_mineRock;
+ mineRock.m_onHit = (Action)Delegate.Combine(mineRock.m_onHit, new Action(OnHit));
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(base.transform.position, m_waveScale);
+ if (waterLevel > -100f)
+ {
+ Vector3 position = m_body.position;
+ float num = Mathf.Clamp((waterLevel - (position.y + m_floatOffset)) * m_movementSpeed * Time.fixedDeltaTime, 0f - m_maxSpeed, m_maxSpeed);
+ position.y += num;
+ m_body.MovePosition(position);
+ }
+ else
+ {
+ Vector3 position2 = m_body.position;
+ position2.y = 0f;
+ m_body.MovePosition(Vector3.MoveTowards(m_body.position, position2, Time.deltaTime));
+ }
+ if (m_animator.GetCurrentAnimatorStateInfo(0).IsTag("submerged"))
+ {
+ m_nview.Destroy();
+ }
+ }
+ }
+
+ private void OnHit()
+ {
+ if (UnityEngine.Random.value <= m_hitReactionChance && !m_left)
+ {
+ m_reactionEffects.Create(base.transform.position, base.transform.rotation);
+ m_zanimator.SetTrigger("shake");
+ Invoke("Leave", m_leaveDelay);
+ }
+ }
+
+ private void Leave()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && !m_left)
+ {
+ m_left = true;
+ m_leaveEffects.Create(base.transform.position, base.transform.rotation);
+ m_zanimator.SetTrigger("dive");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightFlicker.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightFlicker.cs
new file mode 100644
index 0000000..c2b944c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightFlicker.cs
@@ -0,0 +1,71 @@
+using UnityEngine;
+
+public class LightFlicker : MonoBehaviour
+{
+ public float m_flickerIntensity = 0.1f;
+
+ public float m_flickerSpeed = 10f;
+
+ public float m_movement = 0.1f;
+
+ public float m_ttl;
+
+ public float m_fadeDuration = 0.2f;
+
+ public float m_fadeInDuration;
+
+ private Light m_light;
+
+ private float m_baseIntensity = 1f;
+
+ private Vector3 m_basePosition = Vector3.zero;
+
+ private float m_time;
+
+ private float m_flickerOffset;
+
+ private void Awake()
+ {
+ m_light = GetComponent<Light>();
+ m_baseIntensity = m_light.intensity;
+ m_basePosition = base.transform.localPosition;
+ m_flickerOffset = Random.Range(0f, 10f);
+ }
+
+ private void OnEnable()
+ {
+ m_time = 0f;
+ if ((bool)m_light)
+ {
+ m_light.intensity = 0f;
+ }
+ }
+
+ private void Update()
+ {
+ if (!m_light)
+ {
+ return;
+ }
+ m_time += Time.deltaTime;
+ float num = m_flickerOffset + Time.time * m_flickerSpeed;
+ float num2 = 1f + Mathf.Sin(num) * Mathf.Sin(num * 0.56436f) * Mathf.Cos(num * 0.758348f) * m_flickerIntensity;
+ if (m_fadeInDuration > 0f)
+ {
+ num2 *= Utils.LerpStep(0f, m_fadeInDuration, m_time);
+ }
+ if (m_ttl > 0f)
+ {
+ if (m_time > m_ttl)
+ {
+ Object.Destroy(base.gameObject);
+ return;
+ }
+ float l = m_ttl - m_fadeDuration;
+ num2 *= 1f - Utils.LerpStep(l, m_ttl, m_time);
+ }
+ m_light.intensity = m_baseIntensity * num2;
+ Vector3 vector = new Vector3(Mathf.Sin(num) * Mathf.Sin(num * 0.56436f), Mathf.Sin(num * 0.56436f) * Mathf.Sin(num * 0.688742f), Mathf.Cos(num * 0.758348f) * Mathf.Cos(num * 0.4563696f)) * m_movement;
+ base.transform.localPosition = m_basePosition + vector;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightLod.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightLod.cs
new file mode 100644
index 0000000..9f8ab8f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LightLod.cs
@@ -0,0 +1,106 @@
+using System.Collections;
+using UnityEngine;
+
+public class LightLod : MonoBehaviour
+{
+ public bool m_lightLod = true;
+
+ public float m_lightDistance = 40f;
+
+ public bool m_shadowLod = true;
+
+ public float m_shadowDistance = 20f;
+
+ private Light m_light;
+
+ private float m_baseRange;
+
+ private float m_baseShadowStrength;
+
+ private void Awake()
+ {
+ m_light = GetComponent<Light>();
+ m_baseRange = m_light.range;
+ m_baseShadowStrength = m_light.shadowStrength;
+ if (m_shadowLod && m_light.shadows == LightShadows.None)
+ {
+ m_shadowLod = false;
+ }
+ if (m_lightLod)
+ {
+ m_light.range = 0f;
+ m_light.enabled = false;
+ }
+ if (m_shadowLod)
+ {
+ m_light.shadowStrength = 0f;
+ m_light.shadows = LightShadows.None;
+ }
+ }
+
+ private void OnEnable()
+ {
+ StartCoroutine("UpdateLoop");
+ }
+
+ private IEnumerator UpdateLoop()
+ {
+ while (true)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if ((bool)mainCamera && (bool)m_light)
+ {
+ float distance = Vector3.Distance(mainCamera.transform.position, base.transform.position);
+ if (m_lightLod)
+ {
+ if (distance < m_lightDistance)
+ {
+ while ((bool)m_light && (m_light.range < m_baseRange || !m_light.enabled))
+ {
+ m_light.enabled = true;
+ m_light.range = Mathf.Min(m_baseRange, m_light.range + Time.deltaTime * m_baseRange);
+ yield return null;
+ }
+ }
+ else
+ {
+ while ((bool)m_light && (m_light.range > 0f || m_light.enabled))
+ {
+ m_light.range = Mathf.Max(0f, m_light.range - Time.deltaTime * m_baseRange);
+ if (m_light.range <= 0f)
+ {
+ m_light.enabled = false;
+ }
+ yield return null;
+ }
+ }
+ }
+ if (m_shadowLod)
+ {
+ if (distance < m_shadowDistance)
+ {
+ while ((bool)m_light && (m_light.shadowStrength < m_baseShadowStrength || m_light.shadows == LightShadows.None))
+ {
+ m_light.shadows = LightShadows.Soft;
+ m_light.shadowStrength = Mathf.Min(m_baseShadowStrength, m_light.shadowStrength + Time.deltaTime * m_baseShadowStrength);
+ yield return null;
+ }
+ }
+ else
+ {
+ while ((bool)m_light && (m_light.shadowStrength > 0f || m_light.shadows != 0))
+ {
+ m_light.shadowStrength = Mathf.Max(0f, m_light.shadowStrength - Time.deltaTime * m_baseShadowStrength);
+ if (m_light.shadowStrength <= 0f)
+ {
+ m_light.shadows = LightShadows.None;
+ }
+ yield return null;
+ }
+ }
+ }
+ }
+ yield return new WaitForSeconds(1f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineAttach.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineAttach.cs
new file mode 100644
index 0000000..3fcbc50
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineAttach.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class LineAttach : MonoBehaviour
+{
+ public List<Transform> m_attachments = new List<Transform>();
+
+ private LineRenderer m_lineRenderer;
+
+ private void Start()
+ {
+ m_lineRenderer = GetComponent<LineRenderer>();
+ }
+
+ private void LateUpdate()
+ {
+ for (int i = 0; i < m_attachments.Count; i++)
+ {
+ Transform transform = m_attachments[i];
+ if ((bool)transform)
+ {
+ m_lineRenderer.SetPosition(i, base.transform.InverseTransformPoint(transform.position));
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineConnect.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineConnect.cs
new file mode 100644
index 0000000..e2f9298
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LineConnect.cs
@@ -0,0 +1,141 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class LineConnect : MonoBehaviour
+{
+ public bool m_centerOfCharacter;
+
+ public string m_childObject = "";
+
+ public bool m_hideIfNoConnection = true;
+
+ public Vector3 m_noConnectionWorldOffset = new Vector3(0f, -1f, 0f);
+
+ [Header("Dynamic slack")]
+ public bool m_dynamicSlack;
+
+ public float m_slack = 0.5f;
+
+ [Header("Thickness")]
+ public bool m_dynamicThickness = true;
+
+ public float m_minDistance = 6f;
+
+ public float m_maxDistance = 30f;
+
+ public float m_minThickness = 0.2f;
+
+ public float m_maxThickness = 0.8f;
+
+ public float m_thicknessPower = 0.2f;
+
+ public string m_netViewPrefix = "";
+
+ private LineRenderer m_lineRenderer;
+
+ private ZNetView m_nview;
+
+ private KeyValuePair<int, int> m_linePeerID;
+
+ private void Awake()
+ {
+ m_lineRenderer = GetComponent<LineRenderer>();
+ m_nview = GetComponentInParent<ZNetView>();
+ m_linePeerID = ZDO.GetHashZDOID(m_netViewPrefix + "line_peer");
+ }
+
+ private void LateUpdate()
+ {
+ if (!m_nview.IsValid())
+ {
+ m_lineRenderer.enabled = false;
+ return;
+ }
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID(m_linePeerID);
+ GameObject gameObject = ZNetScene.instance.FindInstance(zDOID);
+ if ((bool)gameObject && !string.IsNullOrEmpty(m_childObject))
+ {
+ Transform transform = Utils.FindChild(gameObject.transform, m_childObject);
+ if ((bool)transform)
+ {
+ gameObject = transform.gameObject;
+ }
+ }
+ if (gameObject != null)
+ {
+ Vector3 endpoint = gameObject.transform.position;
+ if (m_centerOfCharacter)
+ {
+ Character component = gameObject.GetComponent<Character>();
+ if ((bool)component)
+ {
+ endpoint = component.GetCenterPoint();
+ }
+ }
+ SetEndpoint(endpoint);
+ m_lineRenderer.enabled = true;
+ }
+ else if (m_hideIfNoConnection)
+ {
+ m_lineRenderer.enabled = false;
+ }
+ else
+ {
+ m_lineRenderer.enabled = true;
+ SetEndpoint(base.transform.position + m_noConnectionWorldOffset);
+ }
+ }
+
+ private void SetEndpoint(Vector3 pos)
+ {
+ Vector3 vector = base.transform.InverseTransformPoint(pos);
+ Vector3 vector2 = base.transform.InverseTransformDirection(Vector3.down);
+ if (m_dynamicSlack)
+ {
+ Vector3 position = m_lineRenderer.GetPosition(0);
+ Vector3 b = vector;
+ float num = Vector3.Distance(position, b) / 2f;
+ for (int i = 1; i < m_lineRenderer.positionCount; i++)
+ {
+ float num2 = (float)i / (float)(m_lineRenderer.positionCount - 1);
+ float num3 = Mathf.Abs(0.5f - num2) * 2f;
+ num3 *= num3;
+ num3 = 1f - num3;
+ Vector3 position2 = Vector3.Lerp(position, b, num2);
+ position2 += vector2 * num * m_slack * num3;
+ m_lineRenderer.SetPosition(i, position2);
+ }
+ }
+ else
+ {
+ m_lineRenderer.SetPosition(1, vector);
+ }
+ if (m_dynamicThickness)
+ {
+ float v = Vector3.Distance(base.transform.position, pos);
+ float f = Utils.LerpStep(m_minDistance, m_maxDistance, v);
+ f = Mathf.Pow(f, m_thicknessPower);
+ m_lineRenderer.widthMultiplier = Mathf.Lerp(m_maxThickness, m_minThickness, f);
+ }
+ }
+
+ public void SetPeer(ZNetView other)
+ {
+ if ((bool)other)
+ {
+ SetPeer(other.GetZDO().m_uid);
+ }
+ else
+ {
+ SetPeer(ZDOID.None);
+ }
+ }
+
+ public void SetPeer(ZDOID zdoid)
+ {
+ if (m_nview.IsValid())
+ {
+ m_nview.GetZDO().Set(m_linePeerID, zdoid);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Location.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Location.cs
new file mode 100644
index 0000000..1cb1b0c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Location.cs
@@ -0,0 +1,118 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Serialization;
+
+public class Location : MonoBehaviour
+{
+ [FormerlySerializedAs("m_radius")]
+ public float m_exteriorRadius = 20f;
+
+ public bool m_noBuild = true;
+
+ public bool m_clearArea = true;
+
+ [Header("Other")]
+ public bool m_applyRandomDamage;
+
+ [Header("Interior")]
+ public bool m_hasInterior;
+
+ public float m_interiorRadius = 20f;
+
+ public string m_interiorEnvironment = "";
+
+ public GameObject m_interiorPrefab;
+
+ private static List<Location> m_allLocations = new List<Location>();
+
+ private void Awake()
+ {
+ m_allLocations.Add(this);
+ if (m_hasInterior)
+ {
+ Vector3 zoneCenter = GetZoneCenter();
+ GameObject obj = Object.Instantiate(position: new Vector3(zoneCenter.x, base.transform.position.y + 5000f, zoneCenter.z), original: m_interiorPrefab, rotation: Quaternion.identity, parent: base.transform);
+ obj.transform.localScale = new Vector3(ZoneSystem.instance.m_zoneSize, 500f, ZoneSystem.instance.m_zoneSize);
+ obj.GetComponent<EnvZone>().m_environment = m_interiorEnvironment;
+ }
+ }
+
+ private Vector3 GetZoneCenter()
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(base.transform.position);
+ return ZoneSystem.instance.GetZonePos(zone);
+ }
+
+ private void OnDestroy()
+ {
+ m_allLocations.Remove(this);
+ }
+
+ private void OnDrawGizmos()
+ {
+ Gizmos.color = new Color(0.8f, 0.8f, 0.8f, 0.5f);
+ Gizmos.matrix = Matrix4x4.TRS(base.transform.position + new Vector3(0f, -0.01f, 0f), Quaternion.identity, new Vector3(1f, 0.001f, 1f));
+ Gizmos.DrawSphere(Vector3.zero, m_exteriorRadius);
+ Gizmos.matrix = Matrix4x4.identity;
+ Utils.DrawGizmoCircle(base.transform.position, m_exteriorRadius, 32);
+ if (m_hasInterior)
+ {
+ Utils.DrawGizmoCircle(base.transform.position + new Vector3(0f, 5000f, 0f), m_interiorRadius, 32);
+ Utils.DrawGizmoCircle(base.transform.position, m_interiorRadius, 32);
+ Gizmos.matrix = Matrix4x4.TRS(base.transform.position + new Vector3(0f, 5000f, 0f), Quaternion.identity, new Vector3(1f, 0.001f, 1f));
+ Gizmos.DrawSphere(Vector3.zero, m_interiorRadius);
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+ }
+
+ private float GetMaxRadius()
+ {
+ if (!m_hasInterior)
+ {
+ return m_exteriorRadius;
+ }
+ return Mathf.Max(m_exteriorRadius, m_interiorRadius);
+ }
+
+ public bool IsInside(Vector3 point, float radius)
+ {
+ float maxRadius = GetMaxRadius();
+ return Utils.DistanceXZ(base.transform.position, point) < maxRadius;
+ }
+
+ public static bool IsInsideLocation(Vector3 point, float distance)
+ {
+ foreach (Location allLocation in m_allLocations)
+ {
+ if (allLocation.IsInside(point, distance))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Location GetLocation(Vector3 point)
+ {
+ foreach (Location allLocation in m_allLocations)
+ {
+ if (allLocation.IsInside(point, 0f))
+ {
+ return allLocation;
+ }
+ }
+ return null;
+ }
+
+ public static bool IsInsideNoBuildLocation(Vector3 point)
+ {
+ foreach (Location allLocation in m_allLocations)
+ {
+ if (allLocation.m_noBuild && allLocation.IsInside(point, 0f))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LocationProxy.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LocationProxy.cs
new file mode 100644
index 0000000..2ff2833
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LocationProxy.cs
@@ -0,0 +1,43 @@
+using UnityEngine;
+
+public class LocationProxy : MonoBehaviour
+{
+ private GameObject m_instance;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ SpawnLocation();
+ }
+
+ public void SetLocation(string location, int seed, bool spawnNow, int pgw)
+ {
+ int stableHashCode = location.GetStableHashCode();
+ m_nview.GetZDO().Set("location", stableHashCode);
+ m_nview.GetZDO().Set("seed", seed);
+ m_nview.GetZDO().SetPGWVersion(pgw);
+ if (spawnNow)
+ {
+ SpawnLocation();
+ }
+ }
+
+ private bool SpawnLocation()
+ {
+ int @int = m_nview.GetZDO().GetInt("location");
+ int int2 = m_nview.GetZDO().GetInt("seed");
+ if (@int == 0)
+ {
+ return false;
+ }
+ m_instance = ZoneSystem.instance.SpawnProxyLocation(@int, int2, base.transform.position, base.transform.rotation);
+ if (m_instance == null)
+ {
+ return false;
+ }
+ m_instance.transform.SetParent(base.transform, worldPositionStays: true);
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LodFadeInOut.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LodFadeInOut.cs
new file mode 100644
index 0000000..ae4d2dd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LodFadeInOut.cs
@@ -0,0 +1,30 @@
+using UnityEngine;
+
+public class LodFadeInOut : MonoBehaviour
+{
+ private Vector3 m_originalLocalRef;
+
+ private LODGroup m_lodGroup;
+
+ private const float m_minTriggerDistance = 20f;
+
+ private void Awake()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null) && Vector3.Distance(mainCamera.transform.position, base.transform.position) > 20f)
+ {
+ m_lodGroup = GetComponent<LODGroup>();
+ if ((bool)m_lodGroup)
+ {
+ m_originalLocalRef = m_lodGroup.localReferencePoint;
+ m_lodGroup.localReferencePoint = new Vector3(999999f, 999999f, 999999f);
+ Invoke("FadeIn", Random.Range(0.1f, 0.3f));
+ }
+ }
+ }
+
+ private void FadeIn()
+ {
+ m_lodGroup.localReferencePoint = m_originalLocalRef;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LootSpawner.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LootSpawner.cs
new file mode 100644
index 0000000..5488631
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/LootSpawner.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class LootSpawner : MonoBehaviour
+{
+ public DropTable m_items = new DropTable();
+
+ public EffectList m_spawnEffect = new EffectList();
+
+ public float m_respawnTimeMinuts = 10f;
+
+ private const float m_triggerDistance = 20f;
+
+ public bool m_spawnAtNight = true;
+
+ public bool m_spawnAtDay = true;
+
+ public bool m_spawnWhenEnemiesCleared;
+
+ public float m_enemiesCheckRange = 30f;
+
+ private ZNetView m_nview;
+
+ private bool m_seenEnemies;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ InvokeRepeating("UpdateSpawner", 10f, 2f);
+ }
+ }
+
+ private void UpdateSpawner()
+ {
+ if (!m_nview.IsOwner() || (!m_spawnAtDay && EnvMan.instance.IsDay()) || (!m_spawnAtNight && EnvMan.instance.IsNight()))
+ {
+ return;
+ }
+ if (m_spawnWhenEnemiesCleared)
+ {
+ bool num = IsMonsterInRange(base.transform.position, m_enemiesCheckRange);
+ if (num && !m_seenEnemies)
+ {
+ m_seenEnemies = true;
+ }
+ if (num || !m_seenEnemies)
+ {
+ return;
+ }
+ }
+ long @long = m_nview.GetZDO().GetLong("spawn_time", 0L);
+ DateTime time = ZNet.instance.GetTime();
+ DateTime dateTime = new DateTime(@long);
+ TimeSpan timeSpan = time - dateTime;
+ if ((!(m_respawnTimeMinuts <= 0f) || @long == 0L) && !(timeSpan.TotalMinutes < (double)m_respawnTimeMinuts) && Player.IsPlayerInRange(base.transform.position, 20f))
+ {
+ List<GameObject> dropList = m_items.GetDropList();
+ for (int i = 0; i < dropList.Count; i++)
+ {
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * 0.3f;
+ Vector3 position = base.transform.position + new Vector3(vector.x, 0.3f * (float)i, vector.y);
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ UnityEngine.Object.Instantiate(dropList[i], position, rotation);
+ }
+ m_spawnEffect.Create(base.transform.position, Quaternion.identity);
+ m_nview.GetZDO().Set("spawn_time", ZNet.instance.GetTime().Ticks);
+ m_seenEnemies = false;
+ }
+ }
+
+ public static bool IsMonsterInRange(Vector3 point, float range)
+ {
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (allCharacter.IsMonsterFaction() && Vector3.Distance(allCharacter.transform.position, point) < range)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void OnDrawGizmos()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MasterClient.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MasterClient.cs
new file mode 100644
index 0000000..ce770bd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MasterClient.cs
@@ -0,0 +1,291 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class MasterClient
+{
+ public class ServerData
+ {
+ public string m_name;
+
+ public string m_host;
+
+ public int m_port;
+
+ public bool m_password;
+
+ public bool m_upnp;
+
+ public string m_version;
+
+ public int m_players;
+
+ public ulong m_steamHostID;
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is ServerData serverData))
+ {
+ return false;
+ }
+ if (serverData.m_name == m_name && serverData.m_host == m_host && serverData.m_port == m_port)
+ {
+ return serverData.m_steamHostID == m_steamHostID;
+ }
+ return false;
+ }
+ }
+
+ private const int statVersion = 2;
+
+ public Action<List<ServerData>> m_onServerList;
+
+ private string m_msHost = "dvoid.noip.me";
+
+ private int m_msPort = 9983;
+
+ private long m_sessionUID;
+
+ private ZConnector2 m_connector;
+
+ private ZSocket2 m_socket;
+
+ private ZRpc m_rpc;
+
+ private bool m_haveServerlist;
+
+ private List<ServerData> m_servers = new List<ServerData>();
+
+ private ZPackage m_registerPkg;
+
+ private float m_sendStatsTimer;
+
+ private int m_serverListRevision;
+
+ private string m_nameFilter = "";
+
+ private static MasterClient m_instance;
+
+ public static MasterClient instance => m_instance;
+
+ public static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new MasterClient();
+ }
+ }
+
+ public MasterClient()
+ {
+ m_sessionUID = Utils.GenerateUID();
+ }
+
+ public void Dispose()
+ {
+ if (m_socket != null)
+ {
+ m_socket.Dispose();
+ }
+ if (m_connector != null)
+ {
+ m_connector.Dispose();
+ }
+ if (m_rpc != null)
+ {
+ m_rpc.Dispose();
+ }
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void Update(float dt)
+ {
+ if (m_rpc == null)
+ {
+ if (m_connector == null)
+ {
+ m_connector = new ZConnector2(m_msHost, m_msPort);
+ return;
+ }
+ if (m_connector.UpdateStatus(dt))
+ {
+ m_socket = m_connector.Complete();
+ if (m_socket != null)
+ {
+ m_rpc = new ZRpc(m_socket);
+ m_rpc.Register<ZPackage>("ServerList", RPC_ServerList);
+ if (m_registerPkg != null)
+ {
+ m_rpc.Invoke("RegisterServer2", m_registerPkg);
+ }
+ }
+ m_connector.Dispose();
+ m_connector = null;
+ }
+ }
+ ZRpc rpc = m_rpc;
+ if (rpc != null)
+ {
+ rpc.Update(dt);
+ if (!rpc.IsConnected())
+ {
+ m_rpc.Dispose();
+ m_rpc = null;
+ }
+ }
+ if (m_rpc != null)
+ {
+ m_sendStatsTimer += dt;
+ if (m_sendStatsTimer > 60f)
+ {
+ m_sendStatsTimer = 0f;
+ SendStats(60f);
+ }
+ }
+ }
+
+ private void SendStats(float duration)
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(2);
+ zPackage.Write(m_sessionUID);
+ zPackage.Write(Time.time);
+ bool flag = Player.m_localPlayer != null;
+ zPackage.Write(flag ? duration : 0f);
+ bool flag2 = (bool)ZNet.instance && !ZNet.instance.IsServer();
+ zPackage.Write(flag2 ? duration : 0f);
+ zPackage.Write(Version.GetVersionString());
+ bool flag3 = (bool)ZNet.instance && ZNet.instance.IsServer();
+ zPackage.Write(flag3);
+ if (flag3)
+ {
+ zPackage.Write(ZNet.instance.GetWorldUID());
+ zPackage.Write(duration);
+ int num = ZNet.instance.GetPeerConnections();
+ if (Player.m_localPlayer != null)
+ {
+ num++;
+ }
+ zPackage.Write(num);
+ bool data = ZNet.instance.GetZNat() != null && ZNet.instance.GetZNat().GetStatus();
+ zPackage.Write(data);
+ }
+ PlayerProfile playerProfile = ((Game.instance != null) ? Game.instance.GetPlayerProfile() : null);
+ if (playerProfile != null)
+ {
+ zPackage.Write(data: true);
+ zPackage.Write(playerProfile.GetPlayerID());
+ zPackage.Write(playerProfile.m_playerStats.m_kills);
+ zPackage.Write(playerProfile.m_playerStats.m_deaths);
+ zPackage.Write(playerProfile.m_playerStats.m_crafts);
+ zPackage.Write(playerProfile.m_playerStats.m_builds);
+ }
+ else
+ {
+ zPackage.Write(data: false);
+ }
+ m_rpc.Invoke("Stats", zPackage);
+ }
+
+ public void RegisterServer(string name, string host, int port, bool password, bool upnp, long worldUID, string version)
+ {
+ m_registerPkg = new ZPackage();
+ m_registerPkg.Write(1);
+ m_registerPkg.Write(name);
+ m_registerPkg.Write(host);
+ m_registerPkg.Write(port);
+ m_registerPkg.Write(password);
+ m_registerPkg.Write(upnp);
+ m_registerPkg.Write(worldUID);
+ m_registerPkg.Write(version);
+ if (m_rpc != null)
+ {
+ m_rpc.Invoke("RegisterServer2", m_registerPkg);
+ }
+ ZLog.Log("Registering server " + name + " " + host + ":" + port);
+ }
+
+ public void UnregisterServer()
+ {
+ if (m_registerPkg != null)
+ {
+ if (m_rpc != null)
+ {
+ m_rpc.Invoke("UnregisterServer");
+ }
+ m_registerPkg = null;
+ }
+ }
+
+ public List<ServerData> GetServers()
+ {
+ return m_servers;
+ }
+
+ public bool GetServers(List<ServerData> servers)
+ {
+ if (!m_haveServerlist)
+ {
+ return false;
+ }
+ servers.Clear();
+ servers.AddRange(m_servers);
+ return true;
+ }
+
+ public void RequestServerlist()
+ {
+ if (m_rpc != null)
+ {
+ m_rpc.Invoke("RequestServerlist2");
+ }
+ }
+
+ private void RPC_ServerList(ZRpc rpc, ZPackage pkg)
+ {
+ m_haveServerlist = true;
+ m_serverListRevision++;
+ pkg.ReadInt();
+ int num = pkg.ReadInt();
+ m_servers.Clear();
+ for (int i = 0; i < num; i++)
+ {
+ ServerData serverData = new ServerData();
+ serverData.m_name = pkg.ReadString();
+ serverData.m_host = pkg.ReadString();
+ serverData.m_port = pkg.ReadInt();
+ serverData.m_password = pkg.ReadBool();
+ serverData.m_upnp = pkg.ReadBool();
+ pkg.ReadLong();
+ serverData.m_version = pkg.ReadString();
+ serverData.m_players = pkg.ReadInt();
+ if (m_nameFilter.Length <= 0 || serverData.m_name.Contains(m_nameFilter))
+ {
+ m_servers.Add(serverData);
+ }
+ }
+ if (m_onServerList != null)
+ {
+ m_onServerList(m_servers);
+ }
+ }
+
+ public int GetServerListRevision()
+ {
+ return m_serverListRevision;
+ }
+
+ public bool IsConnected()
+ {
+ return m_rpc != null;
+ }
+
+ public void SetNameFilter(string filter)
+ {
+ m_nameFilter = filter;
+ ZLog.Log("filter is " + filter);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs
new file mode 100644
index 0000000..1b0f539
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class MeleeWeaponTrail : MonoBehaviour
+{
+ [Serializable]
+ public class Point
+ {
+ public float timeCreated;
+
+ public Vector3 basePosition;
+
+ public Vector3 tipPosition;
+ }
+
+ [SerializeField]
+ private bool _emit = true;
+
+ private bool _use = true;
+
+ [SerializeField]
+ private float _emitTime;
+
+ [SerializeField]
+ private Material _material;
+
+ [SerializeField]
+ private float _lifeTime = 1f;
+
+ [SerializeField]
+ private Color[] _colors;
+
+ [SerializeField]
+ private float[] _sizes;
+
+ [SerializeField]
+ private float _minVertexDistance = 0.1f;
+
+ [SerializeField]
+ private float _maxVertexDistance = 10f;
+
+ private float _minVertexDistanceSqr;
+
+ private float _maxVertexDistanceSqr;
+
+ [SerializeField]
+ private float _maxAngle = 3f;
+
+ [SerializeField]
+ private bool _autoDestruct;
+
+ [SerializeField]
+ private int subdivisions = 4;
+
+ [SerializeField]
+ private Transform _base;
+
+ [SerializeField]
+ private Transform _tip;
+
+ private List<Point> _points = new List<Point>();
+
+ private List<Point> _smoothedPoints = new List<Point>();
+
+ private GameObject _trailObject;
+
+ private Mesh _trailMesh;
+
+ private Vector3 _lastPosition;
+
+ public bool Emit
+ {
+ set
+ {
+ _emit = value;
+ }
+ }
+
+ public bool Use
+ {
+ set
+ {
+ _use = value;
+ }
+ }
+
+ private void Start()
+ {
+ _lastPosition = base.transform.position;
+ _trailObject = new GameObject("Trail");
+ _trailObject.transform.parent = null;
+ _trailObject.transform.position = Vector3.zero;
+ _trailObject.transform.rotation = Quaternion.identity;
+ _trailObject.transform.localScale = Vector3.one;
+ _trailObject.AddComponent(typeof(MeshFilter));
+ _trailObject.AddComponent(typeof(MeshRenderer));
+ _trailObject.GetComponent<Renderer>().material = _material;
+ _trailMesh = new Mesh();
+ _trailMesh.name = base.name + "TrailMesh";
+ _trailObject.GetComponent<MeshFilter>().mesh = _trailMesh;
+ _minVertexDistanceSqr = _minVertexDistance * _minVertexDistance;
+ _maxVertexDistanceSqr = _maxVertexDistance * _maxVertexDistance;
+ }
+
+ private void OnDisable()
+ {
+ UnityEngine.Object.Destroy(_trailObject);
+ }
+
+ private void FixedUpdate()
+ {
+ if (!_use)
+ {
+ return;
+ }
+ if (_emit && _emitTime != 0f)
+ {
+ _emitTime -= Time.fixedDeltaTime;
+ if (_emitTime == 0f)
+ {
+ _emitTime = -1f;
+ }
+ if (_emitTime < 0f)
+ {
+ _emit = false;
+ }
+ }
+ if (!_emit && _points.Count == 0 && _autoDestruct)
+ {
+ UnityEngine.Object.Destroy(_trailObject);
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ if (Utils.GetMainCamera() == null)
+ {
+ return;
+ }
+ float sqrMagnitude = (_lastPosition - base.transform.position).sqrMagnitude;
+ if (_emit)
+ {
+ if (sqrMagnitude > _minVertexDistanceSqr)
+ {
+ bool flag = false;
+ if (_points.Count < 3)
+ {
+ flag = true;
+ }
+ else
+ {
+ Vector3 from = _points[_points.Count - 2].tipPosition - _points[_points.Count - 3].tipPosition;
+ Vector3 to = _points[_points.Count - 1].tipPosition - _points[_points.Count - 2].tipPosition;
+ if (Vector3.Angle(from, to) > _maxAngle || sqrMagnitude > _maxVertexDistanceSqr)
+ {
+ flag = true;
+ }
+ }
+ if (flag)
+ {
+ Point point = new Point();
+ point.basePosition = _base.position;
+ point.tipPosition = _tip.position;
+ point.timeCreated = Time.time;
+ _points.Add(point);
+ _lastPosition = base.transform.position;
+ if (_points.Count == 1)
+ {
+ _smoothedPoints.Add(point);
+ }
+ else if (_points.Count > 1)
+ {
+ for (int i = 0; i < 1 + subdivisions; i++)
+ {
+ _smoothedPoints.Add(point);
+ }
+ }
+ if (_points.Count >= 4)
+ {
+ IEnumerable<Vector3> collection = Interpolate.NewCatmullRom(new Vector3[4]
+ {
+ _points[_points.Count - 4].tipPosition,
+ _points[_points.Count - 3].tipPosition,
+ _points[_points.Count - 2].tipPosition,
+ _points[_points.Count - 1].tipPosition
+ }, subdivisions, loop: false);
+ IEnumerable<Vector3> collection2 = Interpolate.NewCatmullRom(new Vector3[4]
+ {
+ _points[_points.Count - 4].basePosition,
+ _points[_points.Count - 3].basePosition,
+ _points[_points.Count - 2].basePosition,
+ _points[_points.Count - 1].basePosition
+ }, subdivisions, loop: false);
+ List<Vector3> list = new List<Vector3>(collection);
+ List<Vector3> list2 = new List<Vector3>(collection2);
+ float timeCreated = _points[_points.Count - 4].timeCreated;
+ float timeCreated2 = _points[_points.Count - 1].timeCreated;
+ for (int j = 0; j < list.Count; j++)
+ {
+ int num = _smoothedPoints.Count - (list.Count - j);
+ if (num > -1 && num < _smoothedPoints.Count)
+ {
+ Point point2 = new Point();
+ point2.basePosition = list2[j];
+ point2.tipPosition = list[j];
+ point2.timeCreated = Mathf.Lerp(timeCreated, timeCreated2, (float)j / (float)list.Count);
+ _smoothedPoints[num] = point2;
+ }
+ }
+ }
+ }
+ else
+ {
+ _points[_points.Count - 1].basePosition = _base.position;
+ _points[_points.Count - 1].tipPosition = _tip.position;
+ _smoothedPoints[_smoothedPoints.Count - 1].basePosition = _base.position;
+ _smoothedPoints[_smoothedPoints.Count - 1].tipPosition = _tip.position;
+ }
+ }
+ else
+ {
+ if (_points.Count > 0)
+ {
+ _points[_points.Count - 1].basePosition = _base.position;
+ _points[_points.Count - 1].tipPosition = _tip.position;
+ }
+ if (_smoothedPoints.Count > 0)
+ {
+ _smoothedPoints[_smoothedPoints.Count - 1].basePosition = _base.position;
+ _smoothedPoints[_smoothedPoints.Count - 1].tipPosition = _tip.position;
+ }
+ }
+ }
+ RemoveOldPoints(_points);
+ if (_points.Count == 0)
+ {
+ _trailMesh.Clear();
+ }
+ RemoveOldPoints(_smoothedPoints);
+ if (_smoothedPoints.Count == 0)
+ {
+ _trailMesh.Clear();
+ }
+ List<Point> smoothedPoints = _smoothedPoints;
+ if (smoothedPoints.Count <= 1)
+ {
+ return;
+ }
+ Vector3[] array = new Vector3[smoothedPoints.Count * 2];
+ Vector2[] array2 = new Vector2[smoothedPoints.Count * 2];
+ int[] array3 = new int[(smoothedPoints.Count - 1) * 6];
+ Color[] array4 = new Color[smoothedPoints.Count * 2];
+ for (int k = 0; k < smoothedPoints.Count; k++)
+ {
+ Point point3 = smoothedPoints[k];
+ float num2 = (Time.time - point3.timeCreated) / _lifeTime;
+ Color color = Color.Lerp(Color.white, Color.clear, num2);
+ if (_colors != null && _colors.Length != 0)
+ {
+ float num3 = num2 * (float)(_colors.Length - 1);
+ float num4 = Mathf.Floor(num3);
+ float num5 = Mathf.Clamp(Mathf.Ceil(num3), 1f, _colors.Length - 1);
+ float t = Mathf.InverseLerp(num4, num5, num3);
+ if (num4 >= (float)_colors.Length)
+ {
+ num4 = _colors.Length - 1;
+ }
+ if (num4 < 0f)
+ {
+ num4 = 0f;
+ }
+ if (num5 >= (float)_colors.Length)
+ {
+ num5 = _colors.Length - 1;
+ }
+ if (num5 < 0f)
+ {
+ num5 = 0f;
+ }
+ color = Color.Lerp(_colors[(int)num4], _colors[(int)num5], t);
+ }
+ float num6 = 0f;
+ if (_sizes != null && _sizes.Length != 0)
+ {
+ float num7 = num2 * (float)(_sizes.Length - 1);
+ float num8 = Mathf.Floor(num7);
+ float num9 = Mathf.Clamp(Mathf.Ceil(num7), 1f, _sizes.Length - 1);
+ float t2 = Mathf.InverseLerp(num8, num9, num7);
+ if (num8 >= (float)_sizes.Length)
+ {
+ num8 = _sizes.Length - 1;
+ }
+ if (num8 < 0f)
+ {
+ num8 = 0f;
+ }
+ if (num9 >= (float)_sizes.Length)
+ {
+ num9 = _sizes.Length - 1;
+ }
+ if (num9 < 0f)
+ {
+ num9 = 0f;
+ }
+ num6 = Mathf.Lerp(_sizes[(int)num8], _sizes[(int)num9], t2);
+ }
+ Vector3 vector = point3.tipPosition - point3.basePosition;
+ array[k * 2] = point3.basePosition - vector * (num6 * 0.5f);
+ array[k * 2 + 1] = point3.tipPosition + vector * (num6 * 0.5f);
+ array4[k * 2] = (array4[k * 2 + 1] = color);
+ float x = (float)k / (float)smoothedPoints.Count;
+ array2[k * 2] = new Vector2(x, 0f);
+ array2[k * 2 + 1] = new Vector2(x, 1f);
+ if (k > 0)
+ {
+ array3[(k - 1) * 6] = k * 2 - 2;
+ array3[(k - 1) * 6 + 1] = k * 2 - 1;
+ array3[(k - 1) * 6 + 2] = k * 2;
+ array3[(k - 1) * 6 + 3] = k * 2 + 1;
+ array3[(k - 1) * 6 + 4] = k * 2;
+ array3[(k - 1) * 6 + 5] = k * 2 - 1;
+ }
+ }
+ _trailMesh.Clear();
+ _trailMesh.vertices = array;
+ _trailMesh.colors = array4;
+ _trailMesh.uv = array2;
+ _trailMesh.triangles = array3;
+ }
+
+ private void RemoveOldPoints(List<Point> pointList)
+ {
+ List<Point> list = new List<Point>();
+ foreach (Point point in pointList)
+ {
+ if (Time.time - point.timeCreated > _lifeTime)
+ {
+ list.Add(point);
+ }
+ }
+ foreach (Point item in list)
+ {
+ pointList.Remove(item);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Menu.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Menu.cs
new file mode 100644
index 0000000..0ab76a7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Menu.cs
@@ -0,0 +1,131 @@
+using UnityEngine;
+
+public class Menu : MonoBehaviour
+{
+ private GameObject m_settingsInstance;
+
+ private static Menu m_instance;
+
+ public Transform m_root;
+
+ public Transform m_menuDialog;
+
+ public Transform m_quitDialog;
+
+ public Transform m_logoutDialog;
+
+ public GameObject m_settingsPrefab;
+
+ public GameObject m_feedbackPrefab;
+
+ private int m_hiddenFrames;
+
+ public static Menu instance => m_instance;
+
+ private void Start()
+ {
+ m_instance = this;
+ m_root.gameObject.SetActive(value: false);
+ }
+
+ public static bool IsVisible()
+ {
+ if (m_instance == null)
+ {
+ return false;
+ }
+ return m_instance.m_hiddenFrames <= 2;
+ }
+
+ private void Update()
+ {
+ if (Game.instance.IsLoggingOut())
+ {
+ m_root.gameObject.SetActive(value: false);
+ return;
+ }
+ if (m_root.gameObject.activeSelf)
+ {
+ m_hiddenFrames = 0;
+ if ((Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("JoyMenu")) && !m_settingsInstance && !Feedback.IsVisible())
+ {
+ if (m_quitDialog.gameObject.activeSelf)
+ {
+ OnQuitNo();
+ }
+ else if (m_logoutDialog.gameObject.activeSelf)
+ {
+ OnLogoutNo();
+ }
+ else
+ {
+ m_root.gameObject.SetActive(value: false);
+ }
+ }
+ return;
+ }
+ m_hiddenFrames++;
+ bool flag = !InventoryGui.IsVisible() && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog() && !StoreGui.IsVisible() && !Hud.IsPieceSelectionVisible();
+ if ((Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("JoyMenu")) && flag)
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Menu", 0L);
+ m_root.gameObject.SetActive(value: true);
+ m_menuDialog.gameObject.SetActive(value: true);
+ m_logoutDialog.gameObject.SetActive(value: false);
+ m_quitDialog.gameObject.SetActive(value: false);
+ }
+ }
+
+ public void OnSettings()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Enter", "Settings", 0L);
+ m_settingsInstance = Object.Instantiate(m_settingsPrefab, base.transform);
+ }
+
+ public void OnQuit()
+ {
+ m_quitDialog.gameObject.SetActive(value: true);
+ m_menuDialog.gameObject.SetActive(value: false);
+ }
+
+ public void OnQuitYes()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Quit", "", 0L);
+ Application.Quit();
+ }
+
+ public void OnQuitNo()
+ {
+ m_quitDialog.gameObject.SetActive(value: false);
+ m_menuDialog.gameObject.SetActive(value: true);
+ }
+
+ public void OnLogout()
+ {
+ m_menuDialog.gameObject.SetActive(value: false);
+ m_logoutDialog.gameObject.SetActive(value: true);
+ }
+
+ public void OnLogoutYes()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Game", "LogOut", "", 0L);
+ Game.instance.Logout();
+ }
+
+ public void OnLogoutNo()
+ {
+ m_logoutDialog.gameObject.SetActive(value: false);
+ m_menuDialog.gameObject.SetActive(value: true);
+ }
+
+ public void OnClose()
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Screen", "Exit", "Menu", 0L);
+ m_root.gameObject.SetActive(value: false);
+ }
+
+ public void OnButtonFeedback()
+ {
+ Object.Instantiate(m_feedbackPrefab, base.transform);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuScene.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuScene.cs
new file mode 100644
index 0000000..6a14e0e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuScene.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class MenuScene : MonoBehaviour
+{
+ public Light m_dirLight;
+
+ public Color m_sunFogColor = Color.white;
+
+ public Color m_fogColor = Color.white;
+
+ public Color m_ambientLightColor = Color.white;
+
+ public float m_fogDensity = 1f;
+
+ public Vector3 m_windDir = Vector3.left;
+
+ public float m_windIntensity = 0.5f;
+
+ private void Awake()
+ {
+ Shader.SetGlobalFloat("_Wet", 0f);
+ }
+
+ private void Update()
+ {
+ Shader.SetGlobalVector("_SkyboxSunDir", -m_dirLight.transform.forward);
+ Shader.SetGlobalVector("_SunDir", -m_dirLight.transform.forward);
+ Shader.SetGlobalColor("_SunFogColor", m_sunFogColor);
+ Shader.SetGlobalColor("_SunColor", m_dirLight.color * m_dirLight.intensity);
+ Shader.SetGlobalColor("_AmbientColor", RenderSettings.ambientLight);
+ RenderSettings.fogColor = m_fogColor;
+ RenderSettings.fogDensity = m_fogDensity;
+ RenderSettings.ambientLight = m_ambientLightColor;
+ Vector3 normalized = m_windDir.normalized;
+ Shader.SetGlobalVector("_GlobalWindForce", normalized * m_windIntensity);
+ Shader.SetGlobalVector("_GlobalWind1", new Vector4(normalized.x, normalized.y, normalized.z, m_windIntensity));
+ Shader.SetGlobalVector("_GlobalWind2", Vector4.one);
+ Shader.SetGlobalFloat("_GlobalWindAlpha", 0f);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuShipMovement.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuShipMovement.cs
new file mode 100644
index 0000000..22ebd04
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MenuShipMovement.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+public class MenuShipMovement : MonoBehaviour
+{
+ public float m_freq = 1f;
+
+ public float m_xAngle = 5f;
+
+ public float m_zAngle = 5f;
+
+ private float m_time;
+
+ private void Start()
+ {
+ m_time = Random.Range(0, 10);
+ }
+
+ private void Update()
+ {
+ m_time += Time.deltaTime;
+ base.transform.rotation = Quaternion.Euler(Mathf.Sin(m_time * m_freq) * m_xAngle, 0f, Mathf.Sin(m_time * 1.5341234f * m_freq) * m_zAngle);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MessageHud.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MessageHud.cs
new file mode 100644
index 0000000..26ed8af
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MessageHud.cs
@@ -0,0 +1,305 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class MessageHud : MonoBehaviour
+{
+ public enum MessageType
+ {
+ TopLeft = 1,
+ Center
+ }
+
+ private class UnlockMsg
+ {
+ public Sprite m_icon;
+
+ public string m_topic;
+
+ public string m_description;
+ }
+
+ private class MsgData
+ {
+ public Sprite m_icon;
+
+ public string m_text;
+
+ public int m_amount;
+ }
+
+ private class BiomeMessage
+ {
+ public string m_text;
+
+ public bool m_playStinger;
+ }
+
+ private MsgData currentMsg = new MsgData();
+
+ private static MessageHud m_instance;
+
+ public Text m_messageText;
+
+ public Image m_messageIcon;
+
+ public Text m_messageCenterText;
+
+ public GameObject m_unlockMsgPrefab;
+
+ public int m_maxUnlockMsgSpace = 110;
+
+ public int m_maxUnlockMessages = 4;
+
+ public int m_maxLogMessages = 50;
+
+ public GameObject m_biomeFoundPrefab;
+
+ public GameObject m_biomeFoundStinger;
+
+ private Queue<BiomeMessage> m_biomeFoundQueue = new Queue<BiomeMessage>();
+
+ private List<string> m_messageLog = new List<string>();
+
+ private List<GameObject> m_unlockMessages = new List<GameObject>();
+
+ private Queue<UnlockMsg> m_unlockMsgQueue = new Queue<UnlockMsg>();
+
+ private Queue<MsgData> m_msgQeue = new Queue<MsgData>();
+
+ private float m_msgQueueTimer = -1f;
+
+ private GameObject m_biomeMsgInstance;
+
+ public static MessageHud instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Start()
+ {
+ m_messageText.canvasRenderer.SetAlpha(0f);
+ m_messageIcon.canvasRenderer.SetAlpha(0f);
+ m_messageCenterText.canvasRenderer.SetAlpha(0f);
+ for (int i = 0; i < m_maxUnlockMessages; i++)
+ {
+ m_unlockMessages.Add(null);
+ }
+ ZRoutedRpc.instance.Register<int, string>("ShowMessage", RPC_ShowMessage);
+ }
+
+ private void Update()
+ {
+ if (Hud.IsUserHidden())
+ {
+ HideAll();
+ return;
+ }
+ UpdateUnlockMsg(Time.deltaTime);
+ UpdateMessage(Time.deltaTime);
+ UpdateBiomeFound(Time.deltaTime);
+ }
+
+ private void HideAll()
+ {
+ for (int i = 0; i < m_maxUnlockMessages; i++)
+ {
+ if (m_unlockMessages[i] != null)
+ {
+ Object.Destroy(m_unlockMessages[i]);
+ m_unlockMessages[i] = null;
+ }
+ }
+ m_messageText.canvasRenderer.SetAlpha(0f);
+ m_messageIcon.canvasRenderer.SetAlpha(0f);
+ m_messageCenterText.canvasRenderer.SetAlpha(0f);
+ if ((bool)m_biomeMsgInstance)
+ {
+ Object.Destroy(m_biomeMsgInstance);
+ m_biomeMsgInstance = null;
+ }
+ }
+
+ public void MessageAll(MessageType type, string text)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ShowMessage", (int)type, text);
+ }
+
+ private void RPC_ShowMessage(long sender, int type, string text)
+ {
+ ShowMessage((MessageType)type, text);
+ }
+
+ public void ShowMessage(MessageType type, string text, int amount = 0, Sprite icon = null)
+ {
+ if (!Hud.IsUserHidden())
+ {
+ text = Localization.instance.Localize(text);
+ switch (type)
+ {
+ case MessageType.TopLeft:
+ {
+ MsgData msgData = new MsgData();
+ msgData.m_icon = icon;
+ msgData.m_text = text;
+ msgData.m_amount = amount;
+ m_msgQeue.Enqueue(msgData);
+ AddLog(text);
+ break;
+ }
+ case MessageType.Center:
+ m_messageCenterText.text = text;
+ m_messageCenterText.canvasRenderer.SetAlpha(1f);
+ m_messageCenterText.CrossFadeAlpha(0f, 4f, ignoreTimeScale: true);
+ break;
+ }
+ }
+ }
+
+ private void UpdateMessage(float dt)
+ {
+ m_msgQueueTimer += dt;
+ if (m_msgQeue.Count <= 0)
+ {
+ return;
+ }
+ MsgData msgData = m_msgQeue.Peek();
+ bool flag = m_msgQueueTimer < 4f && msgData.m_text == currentMsg.m_text && msgData.m_icon == currentMsg.m_icon;
+ if (m_msgQueueTimer >= 1f || flag)
+ {
+ MsgData msgData2 = m_msgQeue.Dequeue();
+ m_messageText.text = msgData2.m_text;
+ if (flag)
+ {
+ msgData2.m_amount += currentMsg.m_amount;
+ }
+ if (msgData2.m_amount > 1)
+ {
+ Text messageText = m_messageText;
+ messageText.text = messageText.text + " x" + msgData2.m_amount;
+ }
+ m_messageText.canvasRenderer.SetAlpha(1f);
+ m_messageText.CrossFadeAlpha(0f, 4f, ignoreTimeScale: true);
+ if (msgData2.m_icon != null)
+ {
+ m_messageIcon.sprite = msgData2.m_icon;
+ m_messageIcon.canvasRenderer.SetAlpha(1f);
+ m_messageIcon.CrossFadeAlpha(0f, 4f, ignoreTimeScale: true);
+ }
+ else
+ {
+ m_messageIcon.canvasRenderer.SetAlpha(0f);
+ }
+ currentMsg = msgData2;
+ m_msgQueueTimer = 0f;
+ }
+ }
+
+ private void UpdateBiomeFound(float dt)
+ {
+ if (m_biomeMsgInstance != null && m_biomeMsgInstance.GetComponentInChildren<Animator>().GetCurrentAnimatorStateInfo(0).IsTag("done"))
+ {
+ Object.Destroy(m_biomeMsgInstance);
+ m_biomeMsgInstance = null;
+ }
+ if (m_biomeFoundQueue.Count > 0 && m_biomeMsgInstance == null && m_msgQeue.Count == 0 && m_msgQueueTimer > 2f)
+ {
+ BiomeMessage biomeMessage = m_biomeFoundQueue.Dequeue();
+ m_biomeMsgInstance = Object.Instantiate(m_biomeFoundPrefab, base.transform);
+ Text component = Utils.FindChild(m_biomeMsgInstance.transform, "Title").GetComponent<Text>();
+ string text = Localization.instance.Localize(biomeMessage.m_text);
+ component.text = text;
+ if (biomeMessage.m_playStinger && (bool)m_biomeFoundStinger)
+ {
+ Object.Instantiate(m_biomeFoundStinger);
+ }
+ }
+ }
+
+ public void ShowBiomeFoundMsg(string text, bool playStinger)
+ {
+ BiomeMessage biomeMessage = new BiomeMessage();
+ biomeMessage.m_text = text;
+ biomeMessage.m_playStinger = playStinger;
+ m_biomeFoundQueue.Enqueue(biomeMessage);
+ }
+
+ public void QueueUnlockMsg(Sprite icon, string topic, string description)
+ {
+ UnlockMsg unlockMsg = new UnlockMsg();
+ unlockMsg.m_icon = icon;
+ unlockMsg.m_topic = Localization.instance.Localize(topic);
+ unlockMsg.m_description = Localization.instance.Localize(description);
+ m_unlockMsgQueue.Enqueue(unlockMsg);
+ AddLog(topic + ":" + description);
+ ZLog.Log("Queue unlock msg:" + topic + ":" + description);
+ }
+
+ private int GetFreeUnlockMsgSlot()
+ {
+ for (int i = 0; i < m_unlockMessages.Count; i++)
+ {
+ if (m_unlockMessages[i] == null)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void UpdateUnlockMsg(float dt)
+ {
+ for (int i = 0; i < m_unlockMessages.Count; i++)
+ {
+ GameObject gameObject = m_unlockMessages[i];
+ if (!(gameObject == null) && gameObject.GetComponentInChildren<Animator>().GetCurrentAnimatorStateInfo(0).IsTag("done"))
+ {
+ Object.Destroy(gameObject);
+ m_unlockMessages[i] = null;
+ break;
+ }
+ }
+ if (m_unlockMsgQueue.Count > 0)
+ {
+ int freeUnlockMsgSlot = GetFreeUnlockMsgSlot();
+ if (freeUnlockMsgSlot != -1)
+ {
+ Transform parent = base.transform;
+ GameObject gameObject2 = Object.Instantiate(m_unlockMsgPrefab, parent);
+ m_unlockMessages[freeUnlockMsgSlot] = gameObject2;
+ RectTransform obj = gameObject2.transform as RectTransform;
+ Vector3 vector = obj.anchoredPosition;
+ vector.y -= m_maxUnlockMsgSpace * freeUnlockMsgSlot;
+ obj.anchoredPosition = vector;
+ UnlockMsg unlockMsg = m_unlockMsgQueue.Dequeue();
+ Image component = obj.Find("UnlockMessage/icon_bkg/UnlockIcon").GetComponent<Image>();
+ Text component2 = obj.Find("UnlockMessage/UnlockTitle").GetComponent<Text>();
+ Text component3 = obj.Find("UnlockMessage/UnlockDescription").GetComponent<Text>();
+ component.sprite = unlockMsg.m_icon;
+ component2.text = unlockMsg.m_topic;
+ component3.text = unlockMsg.m_description;
+ }
+ }
+ }
+
+ private void AddLog(string logText)
+ {
+ m_messageLog.Add(logText);
+ while (m_messageLog.Count > m_maxLogMessages)
+ {
+ m_messageLog.RemoveAt(0);
+ }
+ }
+
+ public List<string> GetLog()
+ {
+ return m_messageLog;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock.cs
new file mode 100644
index 0000000..e177734
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock.cs
@@ -0,0 +1,233 @@
+using System;
+using UnityEngine;
+
+public class MineRock : MonoBehaviour, IDestructible, Hoverable
+{
+ public string m_name = "";
+
+ public float m_health = 2f;
+
+ public bool m_removeWhenDestroyed = true;
+
+ public HitData.DamageModifiers m_damageModifiers;
+
+ public int m_minToolTier;
+
+ public GameObject m_areaRoot;
+
+ public GameObject m_baseModel;
+
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public DropTable m_dropItems;
+
+ public Action m_onHit;
+
+ private Collider[] m_hitAreas;
+
+ private MeshRenderer[][] m_areaMeshes;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_hitAreas = ((m_areaRoot != null) ? m_areaRoot.GetComponentsInChildren<Collider>() : base.gameObject.GetComponentsInChildren<Collider>());
+ if ((bool)m_baseModel)
+ {
+ m_areaMeshes = new MeshRenderer[m_hitAreas.Length][];
+ for (int i = 0; i < m_hitAreas.Length; i++)
+ {
+ m_areaMeshes[i] = m_hitAreas[i].GetComponents<MeshRenderer>();
+ }
+ }
+ m_nview = GetComponent<ZNetView>();
+ if ((bool)m_nview && m_nview.GetZDO() != null)
+ {
+ m_nview.Register<HitData, int>("Hit", RPC_Hit);
+ m_nview.Register<int>("Hide", RPC_Hide);
+ }
+ InvokeRepeating("UpdateVisability", UnityEngine.Random.Range(1f, 2f), 10f);
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ private void UpdateVisability()
+ {
+ bool flag = false;
+ for (int i = 0; i < m_hitAreas.Length; i++)
+ {
+ Collider collider = m_hitAreas[i];
+ if ((bool)collider)
+ {
+ string text = "Health" + i;
+ bool flag2 = m_nview.GetZDO().GetFloat(text, m_health) > 0f;
+ collider.gameObject.SetActive(flag2);
+ if (!flag2)
+ {
+ flag = true;
+ }
+ }
+ }
+ if (!m_baseModel)
+ {
+ return;
+ }
+ m_baseModel.SetActive(!flag);
+ MeshRenderer[][] areaMeshes = m_areaMeshes;
+ foreach (MeshRenderer[] array in areaMeshes)
+ {
+ for (int k = 0; k < array.Length; k++)
+ {
+ array[k].enabled = flag;
+ }
+ }
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Default;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (hit.m_hitCollider == null)
+ {
+ ZLog.Log("Minerock hit has no collider");
+ return;
+ }
+ int areaIndex = GetAreaIndex(hit.m_hitCollider);
+ if (areaIndex == -1)
+ {
+ ZLog.Log("Invalid hit area on " + base.gameObject.name);
+ return;
+ }
+ ZLog.Log("Hit mine rock area " + areaIndex);
+ m_nview.InvokeRPC("Hit", hit, areaIndex);
+ }
+
+ private void RPC_Hit(long sender, HitData hit, int hitAreaIndex)
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ Collider hitArea = GetHitArea(hitAreaIndex);
+ if (hitArea == null)
+ {
+ ZLog.Log("Missing hit area " + hitAreaIndex);
+ return;
+ }
+ string text = "Health" + hitAreaIndex;
+ float @float = m_nview.GetZDO().GetFloat(text, m_health);
+ if (@float <= 0f)
+ {
+ ZLog.Log("Already destroyed");
+ return;
+ }
+ hit.ApplyResistance(m_damageModifiers, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if (hit.m_toolTier < m_minToolTier)
+ {
+ DamageText.instance.ShowText(DamageText.TextType.TooHard, hit.m_point, 0f);
+ return;
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return;
+ }
+ @float -= totalDamage;
+ m_nview.GetZDO().Set(text, @float);
+ m_hitEffect.Create(hit.m_point, Quaternion.identity);
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(100f);
+ }
+ if (m_onHit != null)
+ {
+ m_onHit();
+ }
+ if (!(@float <= 0f))
+ {
+ return;
+ }
+ m_destroyedEffect.Create(hitArea.bounds.center, Quaternion.identity);
+ m_nview.InvokeRPC(ZNetView.Everybody, "Hide", hitAreaIndex);
+ foreach (GameObject drop in m_dropItems.GetDropList())
+ {
+ Vector3 position = hit.m_point - hit.m_dir * 0.2f + UnityEngine.Random.insideUnitSphere * 0.3f;
+ UnityEngine.Object.Instantiate(drop, position, Quaternion.identity);
+ }
+ if (m_removeWhenDestroyed && AllDestroyed())
+ {
+ m_nview.Destroy();
+ }
+ }
+
+ private bool AllDestroyed()
+ {
+ for (int i = 0; i < m_hitAreas.Length; i++)
+ {
+ string text = "Health" + i;
+ if (m_nview.GetZDO().GetFloat(text, m_health) > 0f)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void RPC_Hide(long sender, int index)
+ {
+ Collider hitArea = GetHitArea(index);
+ if ((bool)hitArea)
+ {
+ hitArea.gameObject.SetActive(value: false);
+ }
+ if (!m_baseModel || !m_baseModel.activeSelf)
+ {
+ return;
+ }
+ m_baseModel.SetActive(value: false);
+ MeshRenderer[][] areaMeshes = m_areaMeshes;
+ foreach (MeshRenderer[] array in areaMeshes)
+ {
+ for (int j = 0; j < array.Length; j++)
+ {
+ array[j].enabled = true;
+ }
+ }
+ }
+
+ private int GetAreaIndex(Collider area)
+ {
+ for (int i = 0; i < m_hitAreas.Length; i++)
+ {
+ if (m_hitAreas[i] == area)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private Collider GetHitArea(int index)
+ {
+ if (index < 0 || index >= m_hitAreas.Length)
+ {
+ return null;
+ }
+ return m_hitAreas[index];
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock5.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock5.cs
new file mode 100644
index 0000000..c250c15
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MineRock5.cs
@@ -0,0 +1,472 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class MineRock5 : MonoBehaviour, IDestructible, Hoverable
+{
+ private struct BoundData
+ {
+ public Vector3 m_pos;
+
+ public Quaternion m_rot;
+
+ public Vector3 m_size;
+ }
+
+ private class HitArea
+ {
+ public Collider m_collider;
+
+ public MeshRenderer m_meshRenderer;
+
+ public MeshFilter m_meshFilter;
+
+ public StaticPhysics m_physics;
+
+ public float m_health;
+
+ public BoundData m_bound;
+
+ public bool m_supported;
+
+ public float m_baseScale;
+ }
+
+ private static Mesh m_tempMeshA;
+
+ private static Mesh m_tempMeshB;
+
+ private static List<CombineInstance> m_tempInstancesA = new List<CombineInstance>();
+
+ private static List<CombineInstance> m_tempInstancesB = new List<CombineInstance>();
+
+ public string m_name = "";
+
+ public float m_health = 2f;
+
+ public HitData.DamageModifiers m_damageModifiers;
+
+ public int m_minToolTier;
+
+ public bool m_supportCheck = true;
+
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public DropTable m_dropItems;
+
+ private List<HitArea> m_hitAreas;
+
+ private List<Renderer> m_extraRenderers;
+
+ private bool m_haveSetupBounds;
+
+ private ZNetView m_nview;
+
+ private MeshFilter m_meshFilter;
+
+ private MeshRenderer m_meshRenderer;
+
+ private uint m_lastDataRevision;
+
+ private const int m_supportIterations = 3;
+
+ private static int m_rayMask = 0;
+
+ private static int m_groundLayer = 0;
+
+ private static Collider[] m_tempColliders = new Collider[128];
+
+ private void Start()
+ {
+ Collider[] componentsInChildren = base.gameObject.GetComponentsInChildren<Collider>();
+ m_hitAreas = new List<HitArea>(componentsInChildren.Length);
+ m_extraRenderers = new List<Renderer>();
+ foreach (Collider collider in componentsInChildren)
+ {
+ HitArea hitArea = new HitArea();
+ hitArea.m_collider = collider;
+ hitArea.m_meshFilter = collider.GetComponent<MeshFilter>();
+ hitArea.m_meshRenderer = collider.GetComponent<MeshRenderer>();
+ hitArea.m_physics = collider.GetComponent<StaticPhysics>();
+ hitArea.m_health = m_health;
+ hitArea.m_baseScale = hitArea.m_collider.transform.localScale.x;
+ for (int j = 0; j < collider.transform.childCount; j++)
+ {
+ Renderer[] componentsInChildren2 = collider.transform.GetChild(j).GetComponentsInChildren<Renderer>();
+ m_extraRenderers.AddRange(componentsInChildren2);
+ }
+ m_hitAreas.Add(hitArea);
+ }
+ if (m_rayMask == 0)
+ {
+ m_rayMask = LayerMask.GetMask("piece", "Default", "static_solid", "Default_small", "terrain");
+ }
+ if (m_groundLayer == 0)
+ {
+ m_groundLayer = LayerMask.NameToLayer("terrain");
+ }
+ Material[] array = null;
+ foreach (HitArea hitArea2 in m_hitAreas)
+ {
+ if (array == null || hitArea2.m_meshRenderer.sharedMaterials.Length > array.Length)
+ {
+ array = hitArea2.m_meshRenderer.sharedMaterials;
+ }
+ }
+ m_meshFilter = base.gameObject.AddComponent<MeshFilter>();
+ m_meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
+ m_meshRenderer.sharedMaterials = array;
+ m_meshFilter.mesh = new Mesh();
+ m_nview = GetComponent<ZNetView>();
+ if ((bool)m_nview && m_nview.GetZDO() != null)
+ {
+ m_nview.Register<HitData, int>("Damage", RPC_Damage);
+ m_nview.Register<int, float>("SetAreaHealth", RPC_SetAreaHealth);
+ }
+ CheckForUpdate();
+ InvokeRepeating("CheckForUpdate", Random.Range(5f, 10f), 10f);
+ }
+
+ private void CheckSupport()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return;
+ }
+ UpdateSupport();
+ for (int i = 0; i < m_hitAreas.Count; i++)
+ {
+ HitArea hitArea = m_hitAreas[i];
+ if (hitArea.m_health > 0f && !hitArea.m_supported)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = m_health;
+ hitData.m_point = hitArea.m_collider.bounds.center;
+ DamageArea(i, hitData);
+ }
+ }
+ }
+
+ private void CheckForUpdate()
+ {
+ if (m_nview.IsValid() && m_nview.GetZDO().m_dataRevision != m_lastDataRevision)
+ {
+ LoadHealth();
+ UpdateMesh();
+ }
+ }
+
+ private void LoadHealth()
+ {
+ byte[] byteArray = m_nview.GetZDO().GetByteArray("health");
+ if (byteArray != null)
+ {
+ ZPackage zPackage = new ZPackage(byteArray);
+ int num = zPackage.ReadInt();
+ for (int i = 0; i < num; i++)
+ {
+ float health = zPackage.ReadSingle();
+ HitArea hitArea = GetHitArea(i);
+ if (hitArea != null)
+ {
+ hitArea.m_health = health;
+ }
+ }
+ }
+ m_lastDataRevision = m_nview.GetZDO().m_dataRevision;
+ }
+
+ private void SaveHealth()
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(m_hitAreas.Count);
+ foreach (HitArea hitArea in m_hitAreas)
+ {
+ zPackage.Write(hitArea.m_health);
+ }
+ m_nview.GetZDO().Set("health", zPackage.GetArray());
+ m_lastDataRevision = m_nview.GetZDO().m_dataRevision;
+ }
+
+ private void UpdateMesh()
+ {
+ m_tempInstancesA.Clear();
+ m_tempInstancesB.Clear();
+ Material material = m_meshRenderer.sharedMaterials[0];
+ Matrix4x4 inverse = base.transform.localToWorldMatrix.inverse;
+ for (int i = 0; i < m_hitAreas.Count; i++)
+ {
+ HitArea hitArea = m_hitAreas[i];
+ if (hitArea.m_health > 0f)
+ {
+ CombineInstance item = default(CombineInstance);
+ item.mesh = hitArea.m_meshFilter.sharedMesh;
+ item.transform = inverse * hitArea.m_meshFilter.transform.localToWorldMatrix;
+ for (int j = 0; j < hitArea.m_meshFilter.sharedMesh.subMeshCount; j++)
+ {
+ item.subMeshIndex = j;
+ if (hitArea.m_meshRenderer.sharedMaterials[j] == material)
+ {
+ m_tempInstancesA.Add(item);
+ }
+ else
+ {
+ m_tempInstancesB.Add(item);
+ }
+ }
+ hitArea.m_meshRenderer.enabled = false;
+ hitArea.m_collider.gameObject.SetActive(value: true);
+ }
+ else
+ {
+ hitArea.m_collider.gameObject.SetActive(value: false);
+ }
+ }
+ if (m_tempMeshA == null)
+ {
+ m_tempMeshA = new Mesh();
+ m_tempMeshB = new Mesh();
+ }
+ m_tempMeshA.CombineMeshes(m_tempInstancesA.ToArray());
+ m_tempMeshB.CombineMeshes(m_tempInstancesB.ToArray());
+ CombineInstance combineInstance = default(CombineInstance);
+ combineInstance.mesh = m_tempMeshA;
+ CombineInstance combineInstance2 = default(CombineInstance);
+ combineInstance2.mesh = m_tempMeshB;
+ m_meshFilter.mesh.CombineMeshes(new CombineInstance[2] { combineInstance, combineInstance2 }, mergeSubMeshes: false, useMatrices: false);
+ m_meshRenderer.enabled = true;
+ Renderer[] array = new Renderer[m_extraRenderers.Count + 1];
+ m_extraRenderers.CopyTo(0, array, 0, m_extraRenderers.Count);
+ array[array.Length - 1] = m_meshRenderer;
+ LODGroup component = base.gameObject.GetComponent<LODGroup>();
+ LOD[] lODs = component.GetLODs();
+ lODs[0].renderers = array;
+ component.SetLODs(lODs);
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Default;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (m_nview == null || !m_nview.IsValid() || m_hitAreas == null)
+ {
+ return;
+ }
+ if (hit.m_hitCollider == null)
+ {
+ ZLog.Log("Minerock hit has no collider");
+ return;
+ }
+ int areaIndex = GetAreaIndex(hit.m_hitCollider);
+ if (areaIndex == -1)
+ {
+ ZLog.Log("Invalid hit area on " + base.gameObject.name);
+ return;
+ }
+ m_nview.InvokeRPC("Damage", hit, areaIndex);
+ }
+
+ private void RPC_Damage(long sender, HitData hit, int hitAreaIndex)
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && DamageArea(hitAreaIndex, hit) && m_supportCheck)
+ {
+ CheckSupport();
+ }
+ }
+
+ private bool DamageArea(int hitAreaIndex, HitData hit)
+ {
+ ZLog.Log("hit mine rock " + hitAreaIndex);
+ HitArea hitArea = GetHitArea(hitAreaIndex);
+ if (hitArea == null)
+ {
+ ZLog.Log("Missing hit area " + hitAreaIndex);
+ return false;
+ }
+ LoadHealth();
+ if (hitArea.m_health <= 0f)
+ {
+ ZLog.Log("Already destroyed");
+ return false;
+ }
+ hit.ApplyResistance(m_damageModifiers, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if (hit.m_toolTier < m_minToolTier)
+ {
+ DamageText.instance.ShowText(DamageText.TextType.TooHard, hit.m_point, 0f);
+ return false;
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return false;
+ }
+ hitArea.m_health -= totalDamage;
+ SaveHealth();
+ m_hitEffect.Create(hit.m_point, Quaternion.identity);
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(100f);
+ }
+ if (hitArea.m_health <= 0f)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetAreaHealth", hitAreaIndex, hitArea.m_health);
+ m_destroyedEffect.Create(hit.m_point, Quaternion.identity);
+ foreach (GameObject drop in m_dropItems.GetDropList())
+ {
+ Vector3 position = hit.m_point + Random.insideUnitSphere * 0.3f;
+ Object.Instantiate(drop, position, Quaternion.identity);
+ }
+ if (AllDestroyed())
+ {
+ m_nview.Destroy();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private bool AllDestroyed()
+ {
+ for (int i = 0; i < m_hitAreas.Count; i++)
+ {
+ if (m_hitAreas[i].m_health > 0f)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool NonDestroyed()
+ {
+ for (int i = 0; i < m_hitAreas.Count; i++)
+ {
+ if (m_hitAreas[i].m_health <= 0f)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void RPC_SetAreaHealth(long sender, int index, float health)
+ {
+ HitArea hitArea = GetHitArea(index);
+ if (hitArea != null)
+ {
+ hitArea.m_health = health;
+ }
+ UpdateMesh();
+ }
+
+ private int GetAreaIndex(Collider area)
+ {
+ for (int i = 0; i < m_hitAreas.Count; i++)
+ {
+ if (m_hitAreas[i].m_collider == area)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private HitArea GetHitArea(int index)
+ {
+ if (index < 0 || index >= m_hitAreas.Count)
+ {
+ return null;
+ }
+ return m_hitAreas[index];
+ }
+
+ private void UpdateSupport()
+ {
+ float realtimeSinceStartup = Time.realtimeSinceStartup;
+ if (!m_haveSetupBounds)
+ {
+ SetupColliders();
+ m_haveSetupBounds = true;
+ }
+ foreach (HitArea hitArea in m_hitAreas)
+ {
+ hitArea.m_supported = false;
+ }
+ Vector3 position = base.transform.position;
+ for (int i = 0; i < 3; i++)
+ {
+ foreach (HitArea hitArea2 in m_hitAreas)
+ {
+ if (hitArea2.m_supported)
+ {
+ continue;
+ }
+ int num = Physics.OverlapBoxNonAlloc(position + hitArea2.m_bound.m_pos, hitArea2.m_bound.m_size, m_tempColliders, hitArea2.m_bound.m_rot, m_rayMask);
+ for (int j = 0; j < num; j++)
+ {
+ Collider collider = m_tempColliders[j];
+ if (!(collider == hitArea2.m_collider) && !(collider.attachedRigidbody != null) && !collider.isTrigger)
+ {
+ hitArea2.m_supported = hitArea2.m_supported || GetSupport(collider);
+ if (hitArea2.m_supported)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ ZLog.Log("Suport time " + (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f);
+ }
+
+ private bool GetSupport(Collider c)
+ {
+ if (c.gameObject.layer == m_groundLayer)
+ {
+ return true;
+ }
+ IDestructible componentInParent = c.gameObject.GetComponentInParent<IDestructible>();
+ if (componentInParent != null)
+ {
+ if (componentInParent == this)
+ {
+ foreach (HitArea hitArea in m_hitAreas)
+ {
+ if (hitArea.m_collider == c)
+ {
+ return hitArea.m_supported;
+ }
+ }
+ }
+ return c.transform.position.y < base.transform.position.y;
+ }
+ return true;
+ }
+
+ private void SetupColliders()
+ {
+ Vector3 position = base.transform.position;
+ foreach (HitArea hitArea in m_hitAreas)
+ {
+ hitArea.m_bound.m_rot = Quaternion.identity;
+ hitArea.m_bound.m_pos = hitArea.m_collider.bounds.center - position;
+ hitArea.m_bound.m_size = hitArea.m_collider.bounds.size * 0.5f;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Minimap.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Minimap.cs
new file mode 100644
index 0000000..3b7cefe
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Minimap.cs
@@ -0,0 +1,1463 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.Rendering;
+using UnityEngine.UI;
+
+public class Minimap : MonoBehaviour
+{
+ private enum MapMode
+ {
+ None,
+ Small,
+ Large
+ }
+
+ public enum PinType
+ {
+ Icon0,
+ Icon1,
+ Icon2,
+ Icon3,
+ Death,
+ Bed,
+ Icon4,
+ Shout,
+ None,
+ Boss,
+ Player,
+ RandomEvent,
+ Ping,
+ EventArea
+ }
+
+ public class PinData
+ {
+ public string m_name;
+
+ public PinType m_type;
+
+ public Sprite m_icon;
+
+ public Vector3 m_pos;
+
+ public bool m_save;
+
+ public bool m_checked;
+
+ public bool m_doubleSize;
+
+ public bool m_animate;
+
+ public float m_worldSize;
+
+ public RectTransform m_uiElement;
+
+ public GameObject m_checkedElement;
+
+ public Text m_nameElement;
+ }
+
+ [Serializable]
+ public struct SpriteData
+ {
+ public PinType m_name;
+
+ public Sprite m_icon;
+ }
+
+ [Serializable]
+ public struct LocationSpriteData
+ {
+ public string m_name;
+
+ public Sprite m_icon;
+ }
+
+ private Color forest = new Color(1f, 0f, 0f, 0f);
+
+ private Color noForest = new Color(0f, 0f, 0f, 0f);
+
+ private static int MAPVERSION = 3;
+
+ private static Minimap m_instance;
+
+ public GameObject m_smallRoot;
+
+ public GameObject m_largeRoot;
+
+ public RawImage m_mapImageSmall;
+
+ public RawImage m_mapImageLarge;
+
+ public RectTransform m_pinRootSmall;
+
+ public RectTransform m_pinRootLarge;
+
+ public Text m_biomeNameSmall;
+
+ public Text m_biomeNameLarge;
+
+ public RectTransform m_smallShipMarker;
+
+ public RectTransform m_largeShipMarker;
+
+ public RectTransform m_smallMarker;
+
+ public RectTransform m_largeMarker;
+
+ public RectTransform m_windMarker;
+
+ public RectTransform m_gamepadCrosshair;
+
+ public Toggle m_publicPosition;
+
+ public Image m_selectedIcon0;
+
+ public Image m_selectedIcon1;
+
+ public Image m_selectedIcon2;
+
+ public Image m_selectedIcon3;
+
+ public Image m_selectedIcon4;
+
+ public GameObject m_pinPrefab;
+
+ public InputField m_nameInput;
+
+ public int m_textureSize = 256;
+
+ public float m_pixelSize = 64f;
+
+ public float m_minZoom = 0.01f;
+
+ public float m_maxZoom = 1f;
+
+ public float m_showNamesZoom = 0.5f;
+
+ public float m_exploreInterval = 2f;
+
+ public float m_exploreRadius = 100f;
+
+ public float m_removeRadius = 128f;
+
+ public float m_pinSizeSmall = 32f;
+
+ public float m_pinSizeLarge = 48f;
+
+ public float m_clickDuration = 0.25f;
+
+ public List<SpriteData> m_icons = new List<SpriteData>();
+
+ public List<LocationSpriteData> m_locationIcons = new List<LocationSpriteData>();
+
+ public Color m_meadowsColor = new Color(0.45f, 1f, 0.43f);
+
+ public Color m_ashlandsColor = new Color(1f, 0.2f, 0.2f);
+
+ public Color m_blackforestColor = new Color(0f, 0.7f, 0f);
+
+ public Color m_deepnorthColor = new Color(1f, 1f, 1f);
+
+ public Color m_heathColor = new Color(1f, 1f, 0.2f);
+
+ public Color m_swampColor = new Color(0.6f, 0.5f, 0.5f);
+
+ public Color m_mountainColor = new Color(1f, 1f, 1f);
+
+ public Color m_mistlandsColor = new Color(0.5f, 0.5f, 0.5f);
+
+ private PinData m_namePin;
+
+ private PinType m_selectedType;
+
+ private PinData m_deathPin;
+
+ private PinData m_spawnPointPin;
+
+ private Dictionary<Vector3, PinData> m_locationPins = new Dictionary<Vector3, PinData>();
+
+ private float m_updateLocationsTimer;
+
+ private List<PinData> m_pingPins = new List<PinData>();
+
+ private List<PinData> m_shoutPins = new List<PinData>();
+
+ private List<Chat.WorldTextInstance> m_tempShouts = new List<Chat.WorldTextInstance>();
+
+ private List<PinData> m_playerPins = new List<PinData>();
+
+ private List<ZNet.PlayerInfo> m_tempPlayerInfo = new List<ZNet.PlayerInfo>();
+
+ private PinData m_randEventPin;
+
+ private PinData m_randEventAreaPin;
+
+ private float m_updateEventTime;
+
+ private bool[] m_explored;
+
+ private List<PinData> m_pins = new List<PinData>();
+
+ private Texture2D m_forestMaskTexture;
+
+ private Texture2D m_mapTexture;
+
+ private Texture2D m_heightTexture;
+
+ private Texture2D m_fogTexture;
+
+ private float m_largeZoom = 0.1f;
+
+ private float m_smallZoom = 0.01f;
+
+ private Heightmap.Biome m_biome;
+
+ private MapMode m_mode = MapMode.Small;
+
+ private float m_exploreTimer;
+
+ private bool m_hasGenerated;
+
+ private bool m_dragView = true;
+
+ private Vector3 m_mapOffset = Vector3.zero;
+
+ private float m_leftDownTime;
+
+ private float m_leftClickTime;
+
+ private Vector3 m_dragWorldPos = Vector3.zero;
+
+ private bool m_wasFocused;
+
+ public static Minimap instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_largeRoot.SetActive(value: false);
+ m_smallRoot.SetActive(value: true);
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ public static bool IsOpen()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_largeRoot.activeSelf;
+ }
+ return false;
+ }
+
+ public static bool InTextInput()
+ {
+ if ((bool)m_instance && m_instance.m_mode == MapMode.Large)
+ {
+ return m_instance.m_wasFocused;
+ }
+ return false;
+ }
+
+ private void Start()
+ {
+ m_mapTexture = new Texture2D(m_textureSize, m_textureSize, TextureFormat.RGBA32, mipChain: false);
+ m_mapTexture.wrapMode = TextureWrapMode.Clamp;
+ m_forestMaskTexture = new Texture2D(m_textureSize, m_textureSize, TextureFormat.RGBA32, mipChain: false);
+ m_forestMaskTexture.wrapMode = TextureWrapMode.Clamp;
+ m_heightTexture = new Texture2D(m_textureSize, m_textureSize, TextureFormat.RFloat, mipChain: false);
+ m_heightTexture.wrapMode = TextureWrapMode.Clamp;
+ m_fogTexture = new Texture2D(m_textureSize, m_textureSize, TextureFormat.RGBA32, mipChain: false);
+ m_fogTexture.wrapMode = TextureWrapMode.Clamp;
+ m_explored = new bool[m_textureSize * m_textureSize];
+ m_mapImageLarge.material = UnityEngine.Object.Instantiate(m_mapImageLarge.material);
+ m_mapImageSmall.material = UnityEngine.Object.Instantiate(m_mapImageSmall.material);
+ m_mapImageLarge.material.SetTexture("_MainTex", m_mapTexture);
+ m_mapImageLarge.material.SetTexture("_MaskTex", m_forestMaskTexture);
+ m_mapImageLarge.material.SetTexture("_HeightTex", m_heightTexture);
+ m_mapImageLarge.material.SetTexture("_FogTex", m_fogTexture);
+ m_mapImageSmall.material.SetTexture("_MainTex", m_mapTexture);
+ m_mapImageSmall.material.SetTexture("_MaskTex", m_forestMaskTexture);
+ m_mapImageSmall.material.SetTexture("_HeightTex", m_heightTexture);
+ m_mapImageSmall.material.SetTexture("_FogTex", m_fogTexture);
+ m_nameInput.gameObject.SetActive(value: false);
+ UIInputHandler component = m_mapImageLarge.GetComponent<UIInputHandler>();
+ component.m_onRightClick = (Action<UIInputHandler>)Delegate.Combine(component.m_onRightClick, new Action<UIInputHandler>(OnMapRightClick));
+ component.m_onMiddleClick = (Action<UIInputHandler>)Delegate.Combine(component.m_onMiddleClick, new Action<UIInputHandler>(OnMapMiddleClick));
+ component.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftDown, new Action<UIInputHandler>(OnMapLeftDown));
+ component.m_onLeftUp = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftUp, new Action<UIInputHandler>(OnMapLeftUp));
+ SelectIcon(PinType.Icon0);
+ Reset();
+ }
+
+ public void Reset()
+ {
+ Color32[] array = new Color32[m_textureSize * m_textureSize];
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
+ }
+ m_fogTexture.SetPixels32(array);
+ m_fogTexture.Apply();
+ for (int j = 0; j < m_explored.Length; j++)
+ {
+ m_explored[j] = false;
+ }
+ }
+
+ public void ForceRegen()
+ {
+ if (WorldGenerator.instance != null)
+ {
+ GenerateWorldMap();
+ }
+ }
+
+ private void Update()
+ {
+ if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null || Utils.GetMainCamera() == null)
+ {
+ return;
+ }
+ if (!m_hasGenerated)
+ {
+ if (WorldGenerator.instance == null)
+ {
+ return;
+ }
+ GenerateWorldMap();
+ LoadMapData();
+ m_hasGenerated = true;
+ }
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null)
+ {
+ return;
+ }
+ float deltaTime = Time.deltaTime;
+ UpdateExplore(deltaTime, localPlayer);
+ if (localPlayer.IsDead())
+ {
+ SetMapMode(MapMode.None);
+ return;
+ }
+ if (m_mode == MapMode.None)
+ {
+ SetMapMode(MapMode.Small);
+ }
+ bool flag = (Chat.instance == null || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible();
+ if (flag)
+ {
+ if (InTextInput())
+ {
+ if (Input.GetKeyDown(KeyCode.Escape))
+ {
+ m_namePin = null;
+ }
+ }
+ else if (ZInput.GetButtonDown("Map") || ZInput.GetButtonDown("JoyMap") || (m_mode == MapMode.Large && (Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("JoyButtonB"))))
+ {
+ switch (m_mode)
+ {
+ case MapMode.None:
+ SetMapMode(MapMode.Small);
+ break;
+ case MapMode.Small:
+ SetMapMode(MapMode.Large);
+ break;
+ case MapMode.Large:
+ SetMapMode(MapMode.Small);
+ break;
+ }
+ }
+ }
+ if (m_mode == MapMode.Large)
+ {
+ m_publicPosition.isOn = ZNet.instance.IsReferencePositionPublic();
+ m_gamepadCrosshair.gameObject.SetActive(ZInput.IsGamepadActive());
+ }
+ UpdateMap(localPlayer, deltaTime, flag);
+ UpdateDynamicPins(deltaTime);
+ UpdatePins();
+ UpdateBiome(localPlayer);
+ UpdateNameInput();
+ }
+
+ private void ShowPinNameInput(PinData pin)
+ {
+ m_namePin = pin;
+ m_nameInput.text = "";
+ }
+
+ private void UpdateNameInput()
+ {
+ if (m_namePin == null)
+ {
+ m_wasFocused = false;
+ }
+ if (m_namePin != null && m_mode == MapMode.Large)
+ {
+ m_nameInput.gameObject.SetActive(value: true);
+ if (!m_nameInput.isFocused)
+ {
+ EventSystem.current.SetSelectedGameObject(m_nameInput.gameObject);
+ }
+ if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
+ {
+ string text = m_nameInput.text;
+ text = text.Replace('$', ' ');
+ text = text.Replace('<', ' ');
+ text = text.Replace('>', ' ');
+ m_namePin.m_name = text;
+ m_namePin = null;
+ }
+ m_wasFocused = true;
+ }
+ else
+ {
+ m_nameInput.gameObject.SetActive(value: false);
+ }
+ }
+
+ private void UpdateMap(Player player, float dt, bool takeInput)
+ {
+ if (takeInput)
+ {
+ if (m_mode == MapMode.Large)
+ {
+ float num = 0f;
+ num += Input.GetAxis("Mouse ScrollWheel") * m_largeZoom * 2f;
+ if (ZInput.GetButton("JoyButtonX"))
+ {
+ Vector3 viewCenterWorldPoint = GetViewCenterWorldPoint();
+ Chat.instance.SendPing(viewCenterWorldPoint);
+ }
+ if (ZInput.GetButton("JoyLTrigger"))
+ {
+ num -= m_largeZoom * dt * 2f;
+ }
+ if (ZInput.GetButton("JoyRTrigger"))
+ {
+ num += m_largeZoom * dt * 2f;
+ }
+ if (ZInput.GetButtonDown("MapZoomOut") && !InTextInput())
+ {
+ num -= m_largeZoom * 0.5f;
+ }
+ if (ZInput.GetButtonDown("MapZoomIn") && !InTextInput())
+ {
+ num += m_largeZoom * 0.5f;
+ }
+ m_largeZoom = Mathf.Clamp(m_largeZoom - num, m_minZoom, m_maxZoom);
+ }
+ else
+ {
+ float num2 = 0f;
+ if (ZInput.GetButtonDown("MapZoomOut"))
+ {
+ num2 -= m_smallZoom * 0.5f;
+ }
+ if (ZInput.GetButtonDown("MapZoomIn"))
+ {
+ num2 += m_smallZoom * 0.5f;
+ }
+ m_smallZoom = Mathf.Clamp(m_smallZoom - num2, m_minZoom, m_maxZoom);
+ }
+ }
+ if (m_mode == MapMode.Large)
+ {
+ if (m_leftDownTime != 0f && m_leftDownTime > m_clickDuration && !m_dragView)
+ {
+ m_dragWorldPos = ScreenToWorldPoint(Input.mousePosition);
+ m_dragView = true;
+ m_namePin = null;
+ }
+ m_mapOffset.x += ZInput.GetJoyLeftStickX() * dt * 50000f * m_largeZoom;
+ m_mapOffset.z -= ZInput.GetJoyLeftStickY() * dt * 50000f * m_largeZoom;
+ if (m_dragView)
+ {
+ Vector3 vector = ScreenToWorldPoint(Input.mousePosition) - m_dragWorldPos;
+ m_mapOffset -= vector;
+ CenterMap(player.transform.position + m_mapOffset);
+ m_dragWorldPos = ScreenToWorldPoint(Input.mousePosition);
+ }
+ else
+ {
+ CenterMap(player.transform.position + m_mapOffset);
+ }
+ }
+ else
+ {
+ CenterMap(player.transform.position);
+ }
+ UpdateWindMarker();
+ UpdatePlayerMarker(player, Utils.GetMainCamera().transform.rotation);
+ }
+
+ private void SetMapMode(MapMode mode)
+ {
+ if (mode != m_mode)
+ {
+ m_mode = mode;
+ switch (mode)
+ {
+ case MapMode.None:
+ m_largeRoot.SetActive(value: false);
+ m_smallRoot.SetActive(value: false);
+ break;
+ case MapMode.Small:
+ m_largeRoot.SetActive(value: false);
+ m_smallRoot.SetActive(value: true);
+ break;
+ case MapMode.Large:
+ m_largeRoot.SetActive(value: true);
+ m_smallRoot.SetActive(value: false);
+ m_dragView = false;
+ m_mapOffset = Vector3.zero;
+ m_namePin = null;
+ break;
+ }
+ }
+ }
+
+ private void CenterMap(Vector3 centerPoint)
+ {
+ WorldToMapPoint(centerPoint, out var mx, out var my);
+ Rect uvRect = m_mapImageSmall.uvRect;
+ uvRect.width = m_smallZoom;
+ uvRect.height = m_smallZoom;
+ uvRect.center = new Vector2(mx, my);
+ m_mapImageSmall.uvRect = uvRect;
+ RectTransform rectTransform = m_mapImageLarge.transform as RectTransform;
+ float num = rectTransform.rect.width / rectTransform.rect.height;
+ Rect uvRect2 = m_mapImageSmall.uvRect;
+ uvRect2.width = m_largeZoom * num;
+ uvRect2.height = m_largeZoom;
+ uvRect2.center = new Vector2(mx, my);
+ m_mapImageLarge.uvRect = uvRect2;
+ if (m_mode == MapMode.Large)
+ {
+ m_mapImageLarge.material.SetFloat("_zoom", m_largeZoom);
+ m_mapImageLarge.material.SetFloat("_pixelSize", 200f / m_largeZoom);
+ m_mapImageLarge.material.SetVector("_mapCenter", centerPoint);
+ }
+ else
+ {
+ m_mapImageSmall.material.SetFloat("_zoom", m_smallZoom);
+ m_mapImageSmall.material.SetFloat("_pixelSize", 200f / m_smallZoom);
+ m_mapImageSmall.material.SetVector("_mapCenter", centerPoint);
+ }
+ }
+
+ private void UpdateDynamicPins(float dt)
+ {
+ UpdateProfilePins();
+ UpdateShoutPins();
+ UpdatePingPins();
+ UpdatePlayerPins(dt);
+ UpdateLocationPins(dt);
+ UpdateEventPin(dt);
+ }
+
+ private void UpdateProfilePins()
+ {
+ PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
+ if (playerProfile.HaveDeathPoint())
+ {
+ if (m_deathPin == null)
+ {
+ m_deathPin = AddPin(playerProfile.GetDeathPoint(), PinType.Death, "", save: false, isChecked: false);
+ }
+ m_deathPin.m_pos = playerProfile.GetDeathPoint();
+ }
+ else if (m_deathPin != null)
+ {
+ RemovePin(m_deathPin);
+ m_deathPin = null;
+ }
+ if (playerProfile.HaveCustomSpawnPoint())
+ {
+ if (m_spawnPointPin == null)
+ {
+ m_spawnPointPin = AddPin(playerProfile.GetCustomSpawnPoint(), PinType.Bed, "", save: false, isChecked: false);
+ }
+ m_spawnPointPin.m_pos = playerProfile.GetCustomSpawnPoint();
+ }
+ else if (m_spawnPointPin != null)
+ {
+ RemovePin(m_spawnPointPin);
+ m_spawnPointPin = null;
+ }
+ }
+
+ private void UpdateEventPin(float dt)
+ {
+ if (Time.time - m_updateEventTime < 1f)
+ {
+ return;
+ }
+ m_updateEventTime = Time.time;
+ RandomEvent currentRandomEvent = RandEventSystem.instance.GetCurrentRandomEvent();
+ if (currentRandomEvent != null)
+ {
+ if (m_randEventAreaPin == null)
+ {
+ m_randEventAreaPin = AddPin(currentRandomEvent.m_pos, PinType.EventArea, "", save: false, isChecked: false);
+ m_randEventAreaPin.m_worldSize = RandEventSystem.instance.m_randomEventRange * 2f;
+ m_randEventAreaPin.m_worldSize *= 0.9f;
+ }
+ if (m_randEventPin == null)
+ {
+ m_randEventPin = AddPin(currentRandomEvent.m_pos, PinType.RandomEvent, "", save: false, isChecked: false);
+ m_randEventPin.m_animate = true;
+ m_randEventPin.m_doubleSize = true;
+ }
+ m_randEventAreaPin.m_pos = currentRandomEvent.m_pos;
+ m_randEventPin.m_pos = currentRandomEvent.m_pos;
+ m_randEventPin.m_name = Localization.instance.Localize(currentRandomEvent.GetHudText());
+ }
+ else
+ {
+ if (m_randEventPin != null)
+ {
+ RemovePin(m_randEventPin);
+ m_randEventPin = null;
+ }
+ if (m_randEventAreaPin != null)
+ {
+ RemovePin(m_randEventAreaPin);
+ m_randEventAreaPin = null;
+ }
+ }
+ }
+
+ private void UpdateLocationPins(float dt)
+ {
+ m_updateLocationsTimer -= dt;
+ if (!(m_updateLocationsTimer <= 0f))
+ {
+ return;
+ }
+ m_updateLocationsTimer = 5f;
+ Dictionary<Vector3, string> dictionary = new Dictionary<Vector3, string>();
+ ZoneSystem.instance.GetLocationIcons(dictionary);
+ bool flag = false;
+ while (!flag)
+ {
+ flag = true;
+ foreach (KeyValuePair<Vector3, PinData> locationPin in m_locationPins)
+ {
+ if (!dictionary.ContainsKey(locationPin.Key))
+ {
+ ZLog.DevLog("Minimap: Removing location " + locationPin.Value.m_name);
+ RemovePin(locationPin.Value);
+ m_locationPins.Remove(locationPin.Key);
+ flag = false;
+ break;
+ }
+ }
+ }
+ foreach (KeyValuePair<Vector3, string> item in dictionary)
+ {
+ if (!m_locationPins.ContainsKey(item.Key))
+ {
+ Sprite locationIcon = GetLocationIcon(item.Value);
+ if ((bool)locationIcon)
+ {
+ PinData pinData = AddPin(item.Key, PinType.None, "", save: false, isChecked: false);
+ pinData.m_icon = locationIcon;
+ pinData.m_doubleSize = true;
+ m_locationPins.Add(item.Key, pinData);
+ ZLog.Log("Minimap: Adding unique location " + item.Key);
+ }
+ }
+ }
+ }
+
+ private Sprite GetLocationIcon(string name)
+ {
+ foreach (LocationSpriteData locationIcon in m_locationIcons)
+ {
+ if (locationIcon.m_name == name)
+ {
+ return locationIcon.m_icon;
+ }
+ }
+ return null;
+ }
+
+ private void UpdatePlayerPins(float dt)
+ {
+ m_tempPlayerInfo.Clear();
+ ZNet.instance.GetOtherPublicPlayers(m_tempPlayerInfo);
+ if (m_playerPins.Count != m_tempPlayerInfo.Count)
+ {
+ foreach (PinData playerPin in m_playerPins)
+ {
+ RemovePin(playerPin);
+ }
+ m_playerPins.Clear();
+ foreach (ZNet.PlayerInfo item2 in m_tempPlayerInfo)
+ {
+ _ = item2;
+ PinData item = AddPin(Vector3.zero, PinType.Player, "", save: false, isChecked: false);
+ m_playerPins.Add(item);
+ }
+ }
+ for (int i = 0; i < m_tempPlayerInfo.Count; i++)
+ {
+ PinData pinData = m_playerPins[i];
+ ZNet.PlayerInfo playerInfo = m_tempPlayerInfo[i];
+ if (pinData.m_name == playerInfo.m_name)
+ {
+ pinData.m_pos = Vector3.MoveTowards(pinData.m_pos, playerInfo.m_position, 200f * dt);
+ continue;
+ }
+ pinData.m_name = playerInfo.m_name;
+ pinData.m_pos = playerInfo.m_position;
+ }
+ }
+
+ private void UpdatePingPins()
+ {
+ m_tempShouts.Clear();
+ Chat.instance.GetPingWorldTexts(m_tempShouts);
+ if (m_pingPins.Count != m_tempShouts.Count)
+ {
+ foreach (PinData pingPin in m_pingPins)
+ {
+ RemovePin(pingPin);
+ }
+ m_pingPins.Clear();
+ foreach (Chat.WorldTextInstance tempShout in m_tempShouts)
+ {
+ _ = tempShout;
+ PinData pinData = AddPin(Vector3.zero, PinType.Ping, "", save: false, isChecked: false);
+ pinData.m_doubleSize = true;
+ pinData.m_animate = true;
+ m_pingPins.Add(pinData);
+ }
+ }
+ for (int i = 0; i < m_tempShouts.Count; i++)
+ {
+ PinData pinData2 = m_pingPins[i];
+ Chat.WorldTextInstance worldTextInstance = m_tempShouts[i];
+ pinData2.m_pos = worldTextInstance.m_position;
+ pinData2.m_name = worldTextInstance.m_name + ": " + worldTextInstance.m_text;
+ }
+ }
+
+ private void UpdateShoutPins()
+ {
+ m_tempShouts.Clear();
+ Chat.instance.GetShoutWorldTexts(m_tempShouts);
+ if (m_shoutPins.Count != m_tempShouts.Count)
+ {
+ foreach (PinData shoutPin in m_shoutPins)
+ {
+ RemovePin(shoutPin);
+ }
+ m_shoutPins.Clear();
+ foreach (Chat.WorldTextInstance tempShout in m_tempShouts)
+ {
+ _ = tempShout;
+ PinData pinData = AddPin(Vector3.zero, PinType.Shout, "", save: false, isChecked: false);
+ pinData.m_doubleSize = true;
+ pinData.m_animate = true;
+ m_shoutPins.Add(pinData);
+ }
+ }
+ for (int i = 0; i < m_tempShouts.Count; i++)
+ {
+ PinData pinData2 = m_shoutPins[i];
+ Chat.WorldTextInstance worldTextInstance = m_tempShouts[i];
+ pinData2.m_pos = worldTextInstance.m_position;
+ pinData2.m_name = worldTextInstance.m_name + ": " + worldTextInstance.m_text;
+ }
+ }
+
+ private void UpdatePins()
+ {
+ RawImage rawImage = ((m_mode == MapMode.Large) ? m_mapImageLarge : m_mapImageSmall);
+ float num = ((m_mode == MapMode.Large) ? m_pinSizeLarge : m_pinSizeSmall);
+ RectTransform rectTransform = ((m_mode == MapMode.Large) ? m_pinRootLarge : m_pinRootSmall);
+ if (m_mode != MapMode.Large)
+ {
+ _ = m_smallZoom;
+ }
+ else
+ {
+ _ = m_largeZoom;
+ }
+ foreach (PinData pin in m_pins)
+ {
+ if (IsPointVisible(pin.m_pos, rawImage))
+ {
+ if (pin.m_uiElement == null || pin.m_uiElement.parent != rectTransform)
+ {
+ if (pin.m_uiElement != null)
+ {
+ UnityEngine.Object.Destroy(pin.m_uiElement.gameObject);
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_pinPrefab);
+ gameObject.GetComponent<Image>().sprite = pin.m_icon;
+ pin.m_uiElement = gameObject.transform as RectTransform;
+ pin.m_uiElement.SetParent(rectTransform);
+ float size = (pin.m_doubleSize ? (num * 2f) : num);
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size);
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ pin.m_checkedElement = gameObject.transform.Find("Checked").gameObject;
+ pin.m_nameElement = gameObject.transform.Find("Name").GetComponent<Text>();
+ }
+ WorldToMapPoint(pin.m_pos, out var mx, out var my);
+ Vector2 anchoredPosition = MapPointToLocalGuiPos(mx, my, rawImage);
+ pin.m_uiElement.anchoredPosition = anchoredPosition;
+ if (pin.m_animate)
+ {
+ float num2 = (pin.m_doubleSize ? (num * 2f) : num);
+ num2 *= 0.8f + Mathf.Sin(Time.time * 5f) * 0.2f;
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, num2);
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, num2);
+ }
+ if (pin.m_worldSize > 0f)
+ {
+ Vector2 size2 = new Vector2(pin.m_worldSize / m_pixelSize / (float)m_textureSize, pin.m_worldSize / m_pixelSize / (float)m_textureSize);
+ Vector2 vector = MapSizeToLocalGuiSize(size2, rawImage);
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, vector.x);
+ pin.m_uiElement.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, vector.y);
+ }
+ pin.m_checkedElement.SetActive(pin.m_checked);
+ if (pin.m_name.Length > 0 && m_mode == MapMode.Large && m_largeZoom < m_showNamesZoom)
+ {
+ pin.m_nameElement.gameObject.SetActive(value: true);
+ pin.m_nameElement.text = Localization.instance.Localize(pin.m_name);
+ }
+ else
+ {
+ pin.m_nameElement.gameObject.SetActive(value: false);
+ }
+ }
+ else if (pin.m_uiElement != null)
+ {
+ UnityEngine.Object.Destroy(pin.m_uiElement.gameObject);
+ pin.m_uiElement = null;
+ }
+ }
+ }
+
+ private void UpdateWindMarker()
+ {
+ Quaternion quaternion = Quaternion.LookRotation(EnvMan.instance.GetWindDir());
+ m_windMarker.rotation = Quaternion.Euler(0f, 0f, 0f - quaternion.eulerAngles.y);
+ }
+
+ private void UpdatePlayerMarker(Player player, Quaternion playerRot)
+ {
+ Vector3 position = player.transform.position;
+ Vector3 eulerAngles = playerRot.eulerAngles;
+ m_smallMarker.rotation = Quaternion.Euler(0f, 0f, 0f - eulerAngles.y);
+ if (m_mode == MapMode.Large && IsPointVisible(position, m_mapImageLarge))
+ {
+ m_largeMarker.gameObject.SetActive(value: true);
+ m_largeMarker.rotation = m_smallMarker.rotation;
+ WorldToMapPoint(position, out var mx, out var my);
+ Vector2 anchoredPosition = MapPointToLocalGuiPos(mx, my, m_mapImageLarge);
+ m_largeMarker.anchoredPosition = anchoredPosition;
+ }
+ else
+ {
+ m_largeMarker.gameObject.SetActive(value: false);
+ }
+ Ship controlledShip = player.GetControlledShip();
+ if ((bool)controlledShip)
+ {
+ m_smallShipMarker.gameObject.SetActive(value: true);
+ Vector3 eulerAngles2 = controlledShip.transform.rotation.eulerAngles;
+ m_smallShipMarker.rotation = Quaternion.Euler(0f, 0f, 0f - eulerAngles2.y);
+ if (m_mode == MapMode.Large)
+ {
+ m_largeShipMarker.gameObject.SetActive(value: true);
+ Vector3 position2 = controlledShip.transform.position;
+ WorldToMapPoint(position2, out var mx2, out var my2);
+ Vector2 anchoredPosition2 = MapPointToLocalGuiPos(mx2, my2, m_mapImageLarge);
+ m_largeShipMarker.anchoredPosition = anchoredPosition2;
+ m_largeShipMarker.rotation = m_smallShipMarker.rotation;
+ }
+ }
+ else
+ {
+ m_smallShipMarker.gameObject.SetActive(value: false);
+ m_largeShipMarker.gameObject.SetActive(value: false);
+ }
+ }
+
+ private Vector2 MapPointToLocalGuiPos(float mx, float my, RawImage img)
+ {
+ Vector2 result = default(Vector2);
+ result.x = (mx - img.uvRect.xMin) / img.uvRect.width;
+ result.y = (my - img.uvRect.yMin) / img.uvRect.height;
+ result.x *= img.rectTransform.rect.width;
+ result.y *= img.rectTransform.rect.height;
+ return result;
+ }
+
+ private Vector2 MapSizeToLocalGuiSize(Vector2 size, RawImage img)
+ {
+ size.x /= img.uvRect.width;
+ size.y /= img.uvRect.height;
+ return new Vector2(size.x * img.rectTransform.rect.width, size.y * img.rectTransform.rect.height);
+ }
+
+ private bool IsPointVisible(Vector3 p, RawImage map)
+ {
+ WorldToMapPoint(p, out var mx, out var my);
+ if (mx > map.uvRect.xMin && mx < map.uvRect.xMax && my > map.uvRect.yMin)
+ {
+ return my < map.uvRect.yMax;
+ }
+ return false;
+ }
+
+ public void ExploreAll()
+ {
+ for (int i = 0; i < m_textureSize; i++)
+ {
+ for (int j = 0; j < m_textureSize; j++)
+ {
+ Explore(j, i);
+ }
+ }
+ m_fogTexture.Apply();
+ }
+
+ private void WorldToMapPoint(Vector3 p, out float mx, out float my)
+ {
+ int num = m_textureSize / 2;
+ mx = p.x / m_pixelSize + (float)num;
+ my = p.z / m_pixelSize + (float)num;
+ mx /= m_textureSize;
+ my /= m_textureSize;
+ }
+
+ private Vector3 MapPointToWorld(float mx, float my)
+ {
+ int num = m_textureSize / 2;
+ mx *= (float)m_textureSize;
+ my *= (float)m_textureSize;
+ mx -= (float)num;
+ my -= (float)num;
+ mx *= m_pixelSize;
+ my *= m_pixelSize;
+ return new Vector3(mx, 0f, my);
+ }
+
+ private void WorldToPixel(Vector3 p, out int px, out int py)
+ {
+ int num = m_textureSize / 2;
+ px = Mathf.RoundToInt(p.x / m_pixelSize + (float)num);
+ py = Mathf.RoundToInt(p.z / m_pixelSize + (float)num);
+ }
+
+ private void UpdateExplore(float dt, Player player)
+ {
+ m_exploreTimer += Time.deltaTime;
+ if (m_exploreTimer > m_exploreInterval)
+ {
+ m_exploreTimer = 0f;
+ Explore(player.transform.position, m_exploreRadius);
+ }
+ }
+
+ private void Explore(Vector3 p, float radius)
+ {
+ int num = (int)Mathf.Ceil(radius / m_pixelSize);
+ bool flag = false;
+ WorldToPixel(p, out var px, out var py);
+ for (int i = py - num; i <= py + num; i++)
+ {
+ for (int j = px - num; j <= px + num; j++)
+ {
+ if (j >= 0 && i >= 0 && j < m_textureSize && i < m_textureSize && !(new Vector2(j - px, i - py).magnitude > (float)num) && Explore(j, i))
+ {
+ flag = true;
+ }
+ }
+ }
+ if (flag)
+ {
+ m_fogTexture.Apply();
+ }
+ }
+
+ private bool Explore(int x, int y)
+ {
+ if (m_explored[y * m_textureSize + x])
+ {
+ return false;
+ }
+ m_fogTexture.SetPixel(x, y, new Color32(0, 0, 0, 0));
+ m_explored[y * m_textureSize + x] = true;
+ return true;
+ }
+
+ private bool IsExplored(Vector3 worldPos)
+ {
+ WorldToPixel(worldPos, out var px, out var py);
+ if (px < 0 || px >= m_textureSize || py < 0 || py >= m_textureSize)
+ {
+ return false;
+ }
+ return m_explored[py * m_textureSize + px];
+ }
+
+ private float GetHeight(int x, int y)
+ {
+ return m_heightTexture.GetPixel(x, y).r;
+ }
+
+ private void GenerateWorldMap()
+ {
+ int num = m_textureSize / 2;
+ float num2 = m_pixelSize / 2f;
+ Color32[] array = new Color32[m_textureSize * m_textureSize];
+ Color32[] array2 = new Color32[m_textureSize * m_textureSize];
+ Color[] array3 = new Color[m_textureSize * m_textureSize];
+ for (int i = 0; i < m_textureSize; i++)
+ {
+ for (int j = 0; j < m_textureSize; j++)
+ {
+ float wx = (float)(j - num) * m_pixelSize + num2;
+ float wy = (float)(i - num) * m_pixelSize + num2;
+ Heightmap.Biome biome = WorldGenerator.instance.GetBiome(wx, wy);
+ float biomeHeight = WorldGenerator.instance.GetBiomeHeight(biome, wx, wy);
+ array[i * m_textureSize + j] = GetPixelColor(biome);
+ array2[i * m_textureSize + j] = GetMaskColor(wx, wy, biomeHeight, biome);
+ array3[i * m_textureSize + j] = new Color(biomeHeight, 0f, 0f);
+ }
+ }
+ m_forestMaskTexture.SetPixels32(array2);
+ m_forestMaskTexture.Apply();
+ m_mapTexture.SetPixels32(array);
+ m_mapTexture.Apply();
+ m_heightTexture.SetPixels(array3);
+ m_heightTexture.Apply();
+ }
+
+ private Color GetMaskColor(float wx, float wy, float height, Heightmap.Biome biome)
+ {
+ if (height < ZoneSystem.instance.m_waterLevel)
+ {
+ return noForest;
+ }
+ switch (biome)
+ {
+ case Heightmap.Biome.Meadows:
+ if (!WorldGenerator.InForest(new Vector3(wx, 0f, wy)))
+ {
+ return noForest;
+ }
+ return forest;
+ case Heightmap.Biome.Plains:
+ if (!(WorldGenerator.GetForestFactor(new Vector3(wx, 0f, wy)) < 0.8f))
+ {
+ return noForest;
+ }
+ return forest;
+ case Heightmap.Biome.BlackForest:
+ case Heightmap.Biome.Mistlands:
+ return forest;
+ default:
+ return noForest;
+ }
+ }
+
+ private Color GetPixelColor(Heightmap.Biome biome)
+ {
+ return biome switch
+ {
+ Heightmap.Biome.Meadows => m_meadowsColor,
+ Heightmap.Biome.AshLands => m_ashlandsColor,
+ Heightmap.Biome.BlackForest => m_blackforestColor,
+ Heightmap.Biome.DeepNorth => m_deepnorthColor,
+ Heightmap.Biome.Plains => m_heathColor,
+ Heightmap.Biome.Swamp => m_swampColor,
+ Heightmap.Biome.Mountain => m_mountainColor,
+ Heightmap.Biome.Mistlands => m_mistlandsColor,
+ Heightmap.Biome.Ocean => Color.white,
+ _ => Color.white,
+ };
+ }
+
+ private void LoadMapData()
+ {
+ PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
+ if (playerProfile.GetMapData() != null)
+ {
+ SetMapData(playerProfile.GetMapData());
+ }
+ }
+
+ public void SaveMapData()
+ {
+ Game.instance.GetPlayerProfile().SetMapData(GetMapData());
+ }
+
+ private byte[] GetMapData()
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(MAPVERSION);
+ zPackage.Write(m_textureSize);
+ for (int i = 0; i < m_explored.Length; i++)
+ {
+ zPackage.Write(m_explored[i]);
+ }
+ int num = 0;
+ foreach (PinData pin in m_pins)
+ {
+ if (pin.m_save)
+ {
+ num++;
+ }
+ }
+ zPackage.Write(num);
+ foreach (PinData pin2 in m_pins)
+ {
+ if (pin2.m_save)
+ {
+ zPackage.Write(pin2.m_name);
+ zPackage.Write(pin2.m_pos);
+ zPackage.Write((int)pin2.m_type);
+ zPackage.Write(pin2.m_checked);
+ }
+ }
+ return zPackage.GetArray();
+ }
+
+ private void SetMapData(byte[] data)
+ {
+ ZPackage zPackage = new ZPackage(data);
+ int num = zPackage.ReadInt();
+ int num2 = zPackage.ReadInt();
+ if (m_textureSize != num2)
+ {
+ ZLog.LogWarning(string.Concat("Missmatching mapsize ", m_mapTexture, " vs ", num2));
+ return;
+ }
+ Reset();
+ for (int i = 0; i < m_explored.Length; i++)
+ {
+ if (zPackage.ReadBool())
+ {
+ int x = i % num2;
+ int y = i / num2;
+ Explore(x, y);
+ }
+ }
+ if (num >= 2)
+ {
+ int num3 = zPackage.ReadInt();
+ ClearPins();
+ for (int j = 0; j < num3; j++)
+ {
+ string text = zPackage.ReadString();
+ Vector3 pos = zPackage.ReadVector3();
+ PinType type = (PinType)zPackage.ReadInt();
+ bool isChecked = num >= 3 && zPackage.ReadBool();
+ AddPin(pos, type, text, save: true, isChecked);
+ }
+ }
+ m_fogTexture.Apply();
+ }
+
+ public bool RemovePin(Vector3 pos, float radius)
+ {
+ PinData closestPin = GetClosestPin(pos, radius);
+ if (closestPin != null)
+ {
+ RemovePin(closestPin);
+ return true;
+ }
+ return false;
+ }
+
+ private PinData GetClosestPin(Vector3 pos, float radius)
+ {
+ PinData pinData = null;
+ float num = 999999f;
+ foreach (PinData pin in m_pins)
+ {
+ if (pin.m_save)
+ {
+ float num2 = Utils.DistanceXZ(pos, pin.m_pos);
+ if (num2 < radius && (num2 < num || pinData == null))
+ {
+ pinData = pin;
+ num = num2;
+ }
+ }
+ }
+ return pinData;
+ }
+
+ public void RemovePin(PinData pin)
+ {
+ if ((bool)pin.m_uiElement)
+ {
+ UnityEngine.Object.Destroy(pin.m_uiElement.gameObject);
+ }
+ m_pins.Remove(pin);
+ }
+
+ public void ShowPointOnMap(Vector3 point)
+ {
+ if (!(Player.m_localPlayer == null))
+ {
+ SetMapMode(MapMode.Large);
+ m_mapOffset = point - Player.m_localPlayer.transform.position;
+ }
+ }
+
+ public bool DiscoverLocation(Vector3 pos, PinType type, string name)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return false;
+ }
+ if (HaveSimilarPin(pos, type, name, save: true))
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, "$msg_pin_exist");
+ ShowPointOnMap(pos);
+ return false;
+ }
+ Sprite sprite = GetSprite(type);
+ Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, "$msg_pin_added: " + name, 0, sprite);
+ AddPin(pos, type, name, save: true, isChecked: false);
+ ShowPointOnMap(pos);
+ return true;
+ }
+
+ private bool HaveSimilarPin(Vector3 pos, PinType type, string name, bool save)
+ {
+ foreach (PinData pin in m_pins)
+ {
+ if (pin.m_name == name && pin.m_type == type && pin.m_save == save && Utils.DistanceXZ(pos, pin.m_pos) < 1f)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public PinData AddPin(Vector3 pos, PinType type, string name, bool save, bool isChecked)
+ {
+ PinData pinData = new PinData();
+ pinData.m_type = type;
+ pinData.m_name = name;
+ pinData.m_pos = pos;
+ pinData.m_icon = GetSprite(type);
+ pinData.m_save = save;
+ pinData.m_checked = isChecked;
+ m_pins.Add(pinData);
+ return pinData;
+ }
+
+ private Sprite GetSprite(PinType type)
+ {
+ if (type == PinType.None)
+ {
+ return null;
+ }
+ return m_icons.Find((SpriteData x) => x.m_name == type).m_icon;
+ }
+
+ private Vector3 GetViewCenterWorldPoint()
+ {
+ Rect uvRect = m_mapImageLarge.uvRect;
+ float mx = uvRect.xMin + 0.5f * uvRect.width;
+ float my = uvRect.yMin + 0.5f * uvRect.height;
+ return MapPointToWorld(mx, my);
+ }
+
+ private Vector3 ScreenToWorldPoint(Vector3 mousePos)
+ {
+ Vector2 screenPoint = mousePos;
+ RectTransform rectTransform = m_mapImageLarge.transform as RectTransform;
+ if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, null, out var localPoint))
+ {
+ Vector2 vector = Rect.PointToNormalized(rectTransform.rect, localPoint);
+ Rect uvRect = m_mapImageLarge.uvRect;
+ float mx = uvRect.xMin + vector.x * uvRect.width;
+ float my = uvRect.yMin + vector.y * uvRect.height;
+ return MapPointToWorld(mx, my);
+ }
+ return Vector3.zero;
+ }
+
+ private void OnMapLeftDown(UIInputHandler handler)
+ {
+ if (Time.time - m_leftClickTime < 0.3f)
+ {
+ OnMapDblClick();
+ m_leftClickTime = 0f;
+ m_leftDownTime = 0f;
+ }
+ else
+ {
+ m_leftClickTime = Time.time;
+ m_leftDownTime = Time.time;
+ }
+ }
+
+ private void OnMapLeftUp(UIInputHandler handler)
+ {
+ if (m_leftDownTime != 0f)
+ {
+ if (Time.time - m_leftDownTime < m_clickDuration)
+ {
+ OnMapLeftClick();
+ }
+ m_leftDownTime = 0f;
+ }
+ m_dragView = false;
+ }
+
+ public void OnMapDblClick()
+ {
+ Vector3 pos = ScreenToWorldPoint(Input.mousePosition);
+ PinData pin = AddPin(pos, m_selectedType, "", save: true, isChecked: false);
+ ShowPinNameInput(pin);
+ }
+
+ public void OnMapLeftClick()
+ {
+ ZLog.Log("Left click");
+ Vector3 pos = ScreenToWorldPoint(Input.mousePosition);
+ PinData closestPin = GetClosestPin(pos, m_removeRadius * (m_largeZoom * 2f));
+ if (closestPin != null)
+ {
+ closestPin.m_checked = !closestPin.m_checked;
+ }
+ }
+
+ public void OnMapMiddleClick(UIInputHandler handler)
+ {
+ Vector3 position = ScreenToWorldPoint(Input.mousePosition);
+ Chat.instance.SendPing(position);
+ }
+
+ public void OnMapRightClick(UIInputHandler handler)
+ {
+ ZLog.Log("Right click");
+ Vector3 pos = ScreenToWorldPoint(Input.mousePosition);
+ RemovePin(pos, m_removeRadius * (m_largeZoom * 2f));
+ m_namePin = null;
+ }
+
+ public void OnPressedIcon0()
+ {
+ SelectIcon(PinType.Icon0);
+ }
+
+ public void OnPressedIcon1()
+ {
+ SelectIcon(PinType.Icon1);
+ }
+
+ public void OnPressedIcon2()
+ {
+ SelectIcon(PinType.Icon2);
+ }
+
+ public void OnPressedIcon3()
+ {
+ SelectIcon(PinType.Icon3);
+ }
+
+ public void OnPressedIcon4()
+ {
+ SelectIcon(PinType.Icon4);
+ }
+
+ public void OnTogglePublicPosition()
+ {
+ ZNet.instance.SetPublicReferencePosition(m_publicPosition.isOn);
+ }
+
+ private void SelectIcon(PinType type)
+ {
+ m_selectedType = type;
+ m_selectedIcon0.enabled = false;
+ m_selectedIcon1.enabled = false;
+ m_selectedIcon2.enabled = false;
+ m_selectedIcon3.enabled = false;
+ m_selectedIcon4.enabled = false;
+ switch (type)
+ {
+ case PinType.Icon0:
+ m_selectedIcon0.enabled = true;
+ break;
+ case PinType.Icon1:
+ m_selectedIcon1.enabled = true;
+ break;
+ case PinType.Icon2:
+ m_selectedIcon2.enabled = true;
+ break;
+ case PinType.Icon3:
+ m_selectedIcon3.enabled = true;
+ break;
+ case PinType.Icon4:
+ m_selectedIcon4.enabled = true;
+ break;
+ case PinType.Death:
+ case PinType.Bed:
+ break;
+ }
+ }
+
+ private void ClearPins()
+ {
+ foreach (PinData pin in m_pins)
+ {
+ if (pin.m_uiElement != null)
+ {
+ UnityEngine.Object.Destroy(pin.m_uiElement);
+ }
+ }
+ m_pins.Clear();
+ m_deathPin = null;
+ }
+
+ private void UpdateBiome(Player player)
+ {
+ if (m_mode == MapMode.Large && ZInput.IsMouseActive())
+ {
+ Vector3 vector = ScreenToWorldPoint(Input.mousePosition);
+ if (IsExplored(vector))
+ {
+ Heightmap.Biome biome = WorldGenerator.instance.GetBiome(vector);
+ string text = Localization.instance.Localize("$biome_" + biome.ToString().ToLower());
+ m_biomeNameLarge.text = text;
+ }
+ else
+ {
+ m_biomeNameLarge.text = "";
+ }
+ return;
+ }
+ Heightmap.Biome currentBiome = player.GetCurrentBiome();
+ if (currentBiome != m_biome)
+ {
+ m_biome = currentBiome;
+ string text2 = Localization.instance.Localize("$biome_" + currentBiome.ToString().ToLower());
+ m_biomeNameSmall.text = text2;
+ m_biomeNameLarge.text = text2;
+ m_biomeNameSmall.GetComponent<Animator>().SetTrigger("pulse");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MistEmitter.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MistEmitter.cs
new file mode 100644
index 0000000..ba59986
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MistEmitter.cs
@@ -0,0 +1,91 @@
+using System;
+using UnityEngine;
+
+public class MistEmitter : MonoBehaviour
+{
+ public float m_interval = 1f;
+
+ public float m_totalRadius = 30f;
+
+ public float m_testRadius = 5f;
+
+ public int m_rays = 10;
+
+ public float m_placeOffset = 1f;
+
+ public ParticleSystem m_psystem;
+
+ private float m_placeTimer;
+
+ private bool m_emit = true;
+
+ public void SetEmit(bool emit)
+ {
+ m_emit = emit;
+ }
+
+ private void Update()
+ {
+ if (m_emit)
+ {
+ m_placeTimer += Time.deltaTime;
+ if (m_placeTimer > m_interval)
+ {
+ m_placeTimer = 0f;
+ PlaceOne();
+ }
+ }
+ }
+
+ private void PlaceOne()
+ {
+ if (!GetRandomPoint(base.transform.position, m_totalRadius, out var p))
+ {
+ return;
+ }
+ int num = 0;
+ float num2 = (float)Math.PI * 2f / (float)m_rays;
+ for (int i = 0; i < m_rays; i++)
+ {
+ float angle = (float)i * num2;
+ if ((double)GetPointOnEdge(p, angle, m_testRadius).y < (double)p.y - 0.1)
+ {
+ num++;
+ }
+ }
+ if (num <= m_rays / 4 && !EffectArea.IsPointInsideArea(p, EffectArea.Type.Fire, m_testRadius))
+ {
+ ParticleSystem.EmitParams emitParams = default(ParticleSystem.EmitParams);
+ emitParams.position = p + Vector3.up * m_placeOffset;
+ m_psystem.Emit(emitParams, 1);
+ }
+ }
+
+ private bool GetRandomPoint(Vector3 center, float radius, out Vector3 p)
+ {
+ float f = UnityEngine.Random.value * (float)Math.PI * 2f;
+ float num = UnityEngine.Random.Range(0f, radius);
+ p = center + new Vector3(Mathf.Sin(f) * num, 0f, Mathf.Cos(f) * num);
+ if (ZoneSystem.instance.GetGroundHeight(p, out var height))
+ {
+ if (height < ZoneSystem.instance.m_waterLevel)
+ {
+ return false;
+ }
+ p.y = height;
+ return true;
+ }
+ return false;
+ }
+
+ private Vector3 GetPointOnEdge(Vector3 center, float angle, float radius)
+ {
+ Vector3 vector = center + new Vector3(Mathf.Sin(angle) * radius, 0f, Mathf.Cos(angle) * radius);
+ vector.y = ZoneSystem.instance.GetGroundHeight(vector);
+ if (vector.y < ZoneSystem.instance.m_waterLevel)
+ {
+ vector.y = ZoneSystem.instance.m_waterLevel;
+ }
+ return vector;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MonsterAI.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MonsterAI.cs
new file mode 100644
index 0000000..1c72d80
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MonsterAI.cs
@@ -0,0 +1,744 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class MonsterAI : BaseAI
+{
+ public Action<ItemDrop> m_onConsumedItem;
+
+ private const float m_giveUpTime = 15f;
+
+ private const float m_bossGiveUpTime = 15f;
+
+ private const float m_updateTargetFarRange = 32f;
+
+ private const float m_updateTargetIntervalNear = 3f;
+
+ private const float m_updateTargetIntervalFar = 10f;
+
+ private const float m_updateWeaponInterval = 1f;
+
+ [Header("Monster AI")]
+ public float m_alertRange = 9999f;
+
+ private const float m_alertOthersRange = 10f;
+
+ public bool m_fleeIfHurtWhenTargetCantBeReached = true;
+
+ public bool m_fleeIfNotAlerted;
+
+ public float m_fleeIfLowHealth;
+
+ public bool m_circulateWhileCharging;
+
+ public bool m_circulateWhileChargingFlying;
+
+ public bool m_enableHuntPlayer;
+
+ public bool m_attackPlayerObjects = true;
+
+ public bool m_attackPlayerObjectsWhenAlerted = true;
+
+ public float m_interceptTimeMax;
+
+ public float m_interceptTimeMin;
+
+ public float m_maxChaseDistance;
+
+ public float m_minAttackInterval;
+
+ [Header("Circle target")]
+ public float m_circleTargetInterval;
+
+ public float m_circleTargetDuration = 5f;
+
+ public float m_circleTargetDistance = 10f;
+
+ [Header("Sleep")]
+ public bool m_sleeping;
+
+ public bool m_noiseWakeup;
+
+ public float m_noiseRangeScale = 1f;
+
+ public float m_wakeupRange = 5f;
+
+ public EffectList m_wakeupEffects = new EffectList();
+
+ [Header("Other")]
+ public bool m_avoidLand;
+
+ [Header("Consume items")]
+ public List<ItemDrop> m_consumeItems;
+
+ public float m_consumeRange = 2f;
+
+ public float m_consumeSearchRange = 5f;
+
+ public float m_consumeSearchInterval = 10f;
+
+ public float m_consumeHeal;
+
+ private ItemDrop m_consumeTarget;
+
+ private float m_consumeSearchTimer;
+
+ private static int m_itemMask;
+
+ private string m_aiStatus = "";
+
+ private bool m_despawnInDay;
+
+ private bool m_eventCreature;
+
+ private Character m_targetCreature;
+
+ private bool m_havePathToTarget;
+
+ private Vector3 m_lastKnownTargetPos = Vector3.zero;
+
+ private bool m_beenAtLastPos;
+
+ private StaticTarget m_targetStatic;
+
+ private float m_timeSinceAttacking;
+
+ private float m_timeSinceSensedTargetCreature;
+
+ private float m_updateTargetTimer;
+
+ private float m_updateWeaponTimer;
+
+ private float m_lastAttackTime = -1000f;
+
+ private float m_interceptTime;
+
+ private float m_pauseTimer;
+
+ private bool m_goingHome;
+
+ private float m_sleepTimer;
+
+ private GameObject m_follow;
+
+ private Tameable m_tamable;
+
+ protected override void Awake()
+ {
+ base.Awake();
+ m_tamable = GetComponent<Tameable>();
+ m_despawnInDay = m_nview.GetZDO().GetBool("DespawnInDay", m_despawnInDay);
+ m_eventCreature = m_nview.GetZDO().GetBool("EventCreature", m_eventCreature);
+ m_animator.SetBool("sleeping", IsSleeping());
+ m_interceptTime = UnityEngine.Random.Range(m_interceptTimeMin, m_interceptTimeMax);
+ m_pauseTimer = UnityEngine.Random.Range(0f, m_circleTargetInterval);
+ m_updateTargetTimer = UnityEngine.Random.Range(0f, 3f);
+ if (m_enableHuntPlayer)
+ {
+ SetHuntPlayer(hunt: true);
+ }
+ }
+
+ private void Start()
+ {
+ if ((bool)m_nview && m_nview.IsValid() && m_nview.IsOwner())
+ {
+ Humanoid humanoid = m_character as Humanoid;
+ if ((bool)humanoid)
+ {
+ humanoid.EquipBestWeapon(null, null, null, null);
+ }
+ }
+ }
+
+ protected override void OnDamaged(float damage, Character attacker)
+ {
+ base.OnDamaged(damage, attacker);
+ SetAlerted(alert: true);
+ if (attacker != null && m_targetCreature == null && (!attacker.IsPlayer() || !m_character.IsTamed()))
+ {
+ m_targetCreature = attacker;
+ m_lastKnownTargetPos = attacker.transform.position;
+ m_beenAtLastPos = false;
+ m_havePathToTarget = HavePath(m_targetCreature.transform.position);
+ m_targetStatic = null;
+ }
+ }
+
+ public void MakeTame()
+ {
+ m_character.SetTamed(tamed: true);
+ SetAlerted(alert: false);
+ m_targetCreature = null;
+ m_targetStatic = null;
+ }
+
+ private void UpdateTarget(Humanoid humanoid, float dt, out bool canHearTarget, out bool canSeeTarget)
+ {
+ m_updateTargetTimer -= dt;
+ if (m_updateTargetTimer <= 0f && !m_character.InAttack())
+ {
+ m_updateTargetTimer = (Character.IsCharacterInRange(base.transform.position, 32f) ? 3f : 10f);
+ Character character = FindEnemy();
+ if ((bool)character)
+ {
+ m_targetCreature = character;
+ m_targetStatic = null;
+ }
+ if (m_targetCreature != null)
+ {
+ m_havePathToTarget = HavePath(m_targetCreature.transform.position);
+ }
+ if (!m_character.IsTamed() && (m_attackPlayerObjects || (m_attackPlayerObjectsWhenAlerted && IsAlerted())) && (m_targetCreature == null || ((bool)m_targetCreature && !m_havePathToTarget)))
+ {
+ StaticTarget staticTarget = FindClosestStaticPriorityTarget(99999f);
+ if ((bool)staticTarget)
+ {
+ m_targetStatic = staticTarget;
+ m_targetCreature = null;
+ }
+ if (m_targetStatic != null)
+ {
+ m_havePathToTarget = HavePath(m_targetStatic.transform.position);
+ }
+ if ((!staticTarget || ((bool)m_targetStatic && !m_havePathToTarget)) && IsAlerted())
+ {
+ StaticTarget staticTarget2 = FindRandomStaticTarget(10f, priorityTargetsOnly: false);
+ if ((bool)staticTarget2)
+ {
+ m_targetStatic = staticTarget2;
+ m_targetCreature = null;
+ }
+ }
+ }
+ }
+ if ((bool)m_targetCreature && m_character.IsTamed())
+ {
+ if (GetPatrolPoint(out var point))
+ {
+ if (Vector3.Distance(m_targetCreature.transform.position, point) > m_alertRange)
+ {
+ m_targetCreature = null;
+ }
+ }
+ else if ((bool)m_follow && Vector3.Distance(m_targetCreature.transform.position, m_follow.transform.position) > m_alertRange)
+ {
+ m_targetCreature = null;
+ }
+ }
+ if ((bool)m_targetCreature && m_targetCreature.IsDead())
+ {
+ m_targetCreature = null;
+ }
+ canHearTarget = false;
+ canSeeTarget = false;
+ if ((bool)m_targetCreature)
+ {
+ canHearTarget = CanHearTarget(m_targetCreature);
+ canSeeTarget = CanSeeTarget(m_targetCreature);
+ if (canSeeTarget | canHearTarget)
+ {
+ m_timeSinceSensedTargetCreature = 0f;
+ }
+ if (m_targetCreature.IsPlayer())
+ {
+ m_targetCreature.OnTargeted(canSeeTarget | canHearTarget, IsAlerted());
+ }
+ }
+ m_timeSinceSensedTargetCreature += dt;
+ if (IsAlerted() || m_targetCreature != null)
+ {
+ m_timeSinceAttacking += dt;
+ float num = (m_character.IsBoss() ? 15f : 15f);
+ float num2 = num * 2f;
+ float num3 = Vector3.Distance(m_spawnPoint, base.transform.position);
+ bool flag = HuntPlayer() && (bool)m_targetCreature && m_targetCreature.IsPlayer();
+ if (m_timeSinceSensedTargetCreature > num || (!flag && (m_timeSinceAttacking > num2 || (m_maxChaseDistance > 0f && m_timeSinceSensedTargetCreature > 1f && num3 > m_maxChaseDistance))))
+ {
+ SetAlerted(alert: false);
+ m_targetCreature = null;
+ m_targetStatic = null;
+ m_timeSinceAttacking = 0f;
+ m_updateTargetTimer = 5f;
+ }
+ }
+ }
+
+ protected override void UpdateAI(float dt)
+ {
+ base.UpdateAI(dt);
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ if (IsSleeping())
+ {
+ UpdateSleep(dt);
+ return;
+ }
+ m_aiStatus = "";
+ Humanoid humanoid = m_character as Humanoid;
+ UpdateTarget(humanoid, dt, out var canHearTarget, out var canSeeTarget);
+ if (m_avoidLand && !m_character.IsSwiming())
+ {
+ m_aiStatus = "Move to water";
+ MoveToWater(dt, 20f);
+ return;
+ }
+ if (((m_despawnInDay && EnvMan.instance.IsDay()) || (m_eventCreature && !RandEventSystem.HaveActiveEvent())) && (m_targetCreature == null || !canSeeTarget))
+ {
+ MoveAwayAndDespawn(dt, run: true);
+ m_aiStatus = "Trying to despawn ";
+ return;
+ }
+ if (m_fleeIfNotAlerted && !HuntPlayer() && (bool)m_targetCreature && !IsAlerted() && Vector3.Distance(m_targetCreature.transform.position, base.transform.position) - m_targetCreature.GetRadius() > m_alertRange)
+ {
+ Flee(dt, m_targetCreature.transform.position);
+ m_aiStatus = "Avoiding conflict";
+ return;
+ }
+ if (m_fleeIfLowHealth > 0f && m_character.GetHealthPercentage() < m_fleeIfLowHealth && m_timeSinceHurt < 20f && m_targetCreature != null)
+ {
+ Flee(dt, m_targetCreature.transform.position);
+ m_aiStatus = "Low health, flee";
+ return;
+ }
+ if ((m_afraidOfFire || m_avoidFire) && AvoidFire(dt, m_targetCreature, m_afraidOfFire))
+ {
+ if (m_afraidOfFire)
+ {
+ m_targetStatic = null;
+ m_targetCreature = null;
+ }
+ m_aiStatus = "Avoiding fire";
+ return;
+ }
+ if (m_circleTargetInterval > 0f && (bool)m_targetCreature)
+ {
+ if ((bool)m_targetCreature)
+ {
+ m_pauseTimer += dt;
+ if (m_pauseTimer > m_circleTargetInterval)
+ {
+ if (m_pauseTimer > m_circleTargetInterval + m_circleTargetDuration)
+ {
+ m_pauseTimer = 0f;
+ }
+ RandomMovementArroundPoint(dt, m_targetCreature.transform.position, m_circleTargetDistance, IsAlerted());
+ m_aiStatus = "Attack pause";
+ return;
+ }
+ }
+ else
+ {
+ m_pauseTimer = 0f;
+ }
+ }
+ if (m_targetCreature != null)
+ {
+ if ((bool)EffectArea.IsPointInsideArea(m_targetCreature.transform.position, EffectArea.Type.NoMonsters))
+ {
+ Flee(dt, m_targetCreature.transform.position);
+ m_aiStatus = "Avoid no-monster area";
+ return;
+ }
+ }
+ else
+ {
+ EffectArea effectArea = EffectArea.IsPointInsideArea(base.transform.position, EffectArea.Type.NoMonsters, 15f);
+ if (effectArea != null)
+ {
+ Flee(dt, effectArea.transform.position);
+ m_aiStatus = "Avoid no-monster area";
+ return;
+ }
+ }
+ if (m_fleeIfHurtWhenTargetCantBeReached && m_targetCreature != null && !m_havePathToTarget && m_timeSinceHurt < 20f)
+ {
+ m_aiStatus = "Hide from unreachable target";
+ Flee(dt, m_targetCreature.transform.position);
+ return;
+ }
+ if ((!IsAlerted() || (m_targetStatic == null && m_targetCreature == null)) && UpdateConsumeItem(humanoid, dt))
+ {
+ m_aiStatus = "Consume item";
+ return;
+ }
+ ItemDrop.ItemData itemData = SelectBestAttack(humanoid, dt);
+ bool flag = itemData != null && Time.time - itemData.m_lastAttackTime > itemData.m_shared.m_aiAttackInterval && Time.time - m_lastAttackTime > m_minAttackInterval && !IsTakingOff();
+ if ((m_character.IsFlying() ? m_circulateWhileChargingFlying : m_circulateWhileCharging) && (m_targetStatic != null || m_targetCreature != null) && itemData != null && !flag && !m_character.InAttack())
+ {
+ m_aiStatus = "Move around target weapon ready:" + flag;
+ if (itemData != null)
+ {
+ m_aiStatus = m_aiStatus + " Weapon:" + itemData.m_shared.m_name;
+ }
+ Vector3 point = (m_targetCreature ? m_targetCreature.transform.position : m_targetStatic.transform.position);
+ RandomMovementArroundPoint(dt, point, m_randomMoveRange, IsAlerted());
+ }
+ else if ((m_targetStatic == null && m_targetCreature == null) || itemData == null)
+ {
+ if ((bool)m_follow)
+ {
+ Follow(m_follow, dt);
+ m_aiStatus = "Follow";
+ return;
+ }
+ m_aiStatus = string.Concat("Random movement (weapon: ", (itemData != null) ? itemData.m_shared.m_name : "none", ") (targetpiece: ", m_targetStatic, ") (target: ", m_targetCreature ? m_targetCreature.gameObject.name : "none", ")");
+ IdleMovement(dt);
+ }
+ else if (itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.Enemy)
+ {
+ if ((bool)m_targetStatic)
+ {
+ Vector3 vector = m_targetStatic.FindClosestPoint(base.transform.position);
+ if (Vector3.Distance(vector, base.transform.position) < itemData.m_shared.m_aiAttackRange && CanSeeTarget(m_targetStatic))
+ {
+ LookAt(m_targetStatic.GetCenter());
+ if (IsLookingAt(m_targetStatic.GetCenter(), itemData.m_shared.m_aiAttackMaxAngle) && flag)
+ {
+ m_aiStatus = "Attacking piece";
+ DoAttack(null, isFriend: false);
+ }
+ else
+ {
+ StopMoving();
+ }
+ }
+ else
+ {
+ m_aiStatus = "Move to static target";
+ MoveTo(dt, vector, 0f, IsAlerted());
+ }
+ }
+ else
+ {
+ if (!m_targetCreature)
+ {
+ return;
+ }
+ if (canHearTarget || canSeeTarget || (HuntPlayer() && m_targetCreature.IsPlayer()))
+ {
+ m_beenAtLastPos = false;
+ m_lastKnownTargetPos = m_targetCreature.transform.position;
+ float num = Vector3.Distance(m_lastKnownTargetPos, base.transform.position) - m_targetCreature.GetRadius();
+ if ((canSeeTarget && num < m_alertRange) || HuntPlayer())
+ {
+ SetAlerted(alert: true);
+ }
+ bool num2 = num < itemData.m_shared.m_aiAttackRange;
+ if (!num2 || !canSeeTarget || itemData.m_shared.m_aiAttackRangeMin < 0f)
+ {
+ m_aiStatus = "Move closer";
+ Vector3 velocity = m_targetCreature.GetVelocity();
+ Vector3 vector2 = velocity * m_interceptTime;
+ Vector3 lastKnownTargetPos = m_lastKnownTargetPos;
+ if (num > vector2.magnitude / 4f)
+ {
+ lastKnownTargetPos += velocity * m_interceptTime;
+ }
+ MoveTo(dt, lastKnownTargetPos, 0f, IsAlerted());
+ }
+ else
+ {
+ StopMoving();
+ }
+ if (num2 && canSeeTarget)
+ {
+ m_aiStatus = "In attack range";
+ LookAt(m_targetCreature.GetTopPoint());
+ if (flag && IsLookingAt(m_lastKnownTargetPos, itemData.m_shared.m_aiAttackMaxAngle))
+ {
+ m_aiStatus = "Attacking creature";
+ DoAttack(m_targetCreature, isFriend: false);
+ }
+ }
+ }
+ else
+ {
+ m_aiStatus = "Searching for target";
+ if (m_beenAtLastPos)
+ {
+ RandomMovement(dt, m_lastKnownTargetPos);
+ }
+ else if (MoveTo(dt, m_lastKnownTargetPos, 0f, IsAlerted()))
+ {
+ m_beenAtLastPos = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (itemData.m_shared.m_aiTargetType != ItemDrop.ItemData.AiTarget.FriendHurt && itemData.m_shared.m_aiTargetType != ItemDrop.ItemData.AiTarget.Friend)
+ {
+ return;
+ }
+ m_aiStatus = "Helping friend";
+ Character character = ((itemData.m_shared.m_aiTargetType == ItemDrop.ItemData.AiTarget.FriendHurt) ? HaveHurtFriendInRange(m_viewRange) : HaveFriendInRange(m_viewRange));
+ if ((bool)character)
+ {
+ if (Vector3.Distance(character.transform.position, base.transform.position) < itemData.m_shared.m_aiAttackRange)
+ {
+ if (flag)
+ {
+ StopMoving();
+ LookAt(character.transform.position);
+ DoAttack(character, isFriend: true);
+ }
+ else
+ {
+ RandomMovement(dt, character.transform.position);
+ }
+ }
+ else
+ {
+ MoveTo(dt, character.transform.position, 0f, IsAlerted());
+ }
+ }
+ else
+ {
+ RandomMovement(dt, base.transform.position);
+ }
+ }
+ }
+
+ private bool UpdateConsumeItem(Humanoid humanoid, float dt)
+ {
+ if (m_consumeItems == null || m_consumeItems.Count == 0)
+ {
+ return false;
+ }
+ m_consumeSearchTimer += dt;
+ if (m_consumeSearchTimer > m_consumeSearchInterval)
+ {
+ m_consumeSearchTimer = 0f;
+ if ((bool)m_tamable && !m_tamable.IsHungry())
+ {
+ return false;
+ }
+ m_consumeTarget = FindClosestConsumableItem(m_consumeSearchRange);
+ }
+ if ((bool)m_consumeTarget)
+ {
+ if (MoveTo(dt, m_consumeTarget.transform.position, m_consumeRange, run: false))
+ {
+ LookAt(m_consumeTarget.transform.position);
+ if (IsLookingAt(m_consumeTarget.transform.position, 20f) && m_consumeTarget.RemoveOne())
+ {
+ if (m_onConsumedItem != null)
+ {
+ m_onConsumedItem(m_consumeTarget);
+ }
+ humanoid.m_consumeItemEffects.Create(base.transform.position, Quaternion.identity);
+ m_animator.SetTrigger("consume");
+ m_consumeTarget = null;
+ if (m_consumeHeal > 0f)
+ {
+ m_character.Heal(m_consumeHeal);
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private ItemDrop FindClosestConsumableItem(float maxRange)
+ {
+ if (m_itemMask == 0)
+ {
+ m_itemMask = LayerMask.GetMask("item");
+ }
+ Collider[] array = Physics.OverlapSphere(base.transform.position, maxRange, m_itemMask);
+ ItemDrop itemDrop = null;
+ float num = 999999f;
+ Collider[] array2 = array;
+ foreach (Collider collider in array2)
+ {
+ if (!collider.attachedRigidbody)
+ {
+ continue;
+ }
+ ItemDrop component = collider.attachedRigidbody.GetComponent<ItemDrop>();
+ if (!(component == null) && component.GetComponent<ZNetView>().IsValid() && CanConsume(component.m_itemData))
+ {
+ float num2 = Vector3.Distance(component.transform.position, base.transform.position);
+ if (itemDrop == null || num2 < num)
+ {
+ itemDrop = component;
+ num = num2;
+ }
+ }
+ }
+ if ((bool)itemDrop && HavePath(itemDrop.transform.position))
+ {
+ return itemDrop;
+ }
+ return null;
+ }
+
+ private bool CanConsume(ItemDrop.ItemData item)
+ {
+ foreach (ItemDrop consumeItem in m_consumeItems)
+ {
+ if (consumeItem.m_itemData.m_shared.m_name == item.m_shared.m_name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ItemDrop.ItemData SelectBestAttack(Humanoid humanoid, float dt)
+ {
+ if ((bool)m_targetCreature || (bool)m_targetStatic)
+ {
+ m_updateWeaponTimer -= dt;
+ if (m_updateWeaponTimer <= 0f && !m_character.InAttack())
+ {
+ m_updateWeaponTimer = 1f;
+ HaveFriendsInRange(m_viewRange, out var hurtFriend, out var friend);
+ humanoid.EquipBestWeapon(m_targetCreature, m_targetStatic, hurtFriend, friend);
+ }
+ }
+ return humanoid.GetCurrentWeapon();
+ }
+
+ private bool DoAttack(Character target, bool isFriend)
+ {
+ ItemDrop.ItemData currentWeapon = (m_character as Humanoid).GetCurrentWeapon();
+ if (currentWeapon != null)
+ {
+ if (!BaseAI.CanUseAttack(m_character, currentWeapon))
+ {
+ return false;
+ }
+ bool num = m_character.StartAttack(target, charge: false);
+ if (num)
+ {
+ m_timeSinceAttacking = 0f;
+ m_lastAttackTime = Time.time;
+ }
+ return num;
+ }
+ return false;
+ }
+
+ public void SetDespawnInDay(bool despawn)
+ {
+ m_despawnInDay = despawn;
+ m_nview.GetZDO().Set("DespawnInDay", despawn);
+ }
+
+ public void SetEventCreature(bool despawn)
+ {
+ m_eventCreature = despawn;
+ m_nview.GetZDO().Set("EventCreature", despawn);
+ }
+
+ public bool IsEventCreature()
+ {
+ return m_eventCreature;
+ }
+
+ protected override void OnDrawGizmosSelected()
+ {
+ base.OnDrawGizmosSelected();
+ }
+
+ public override Character GetTargetCreature()
+ {
+ return m_targetCreature;
+ }
+
+ private void UpdateSleep(float dt)
+ {
+ if (!IsSleeping())
+ {
+ return;
+ }
+ m_sleepTimer += dt;
+ if (m_sleepTimer < 0.5f)
+ {
+ return;
+ }
+ if (HuntPlayer())
+ {
+ Wakeup();
+ return;
+ }
+ if (m_wakeupRange > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, m_wakeupRange);
+ if ((bool)closestPlayer && !closestPlayer.InGhostMode() && !closestPlayer.IsDebugFlying())
+ {
+ Wakeup();
+ return;
+ }
+ }
+ if (m_noiseWakeup)
+ {
+ Player playerNoiseRange = Player.GetPlayerNoiseRange(base.transform.position, m_noiseRangeScale);
+ if ((bool)playerNoiseRange && !playerNoiseRange.InGhostMode() && !playerNoiseRange.IsDebugFlying())
+ {
+ Wakeup();
+ }
+ }
+ }
+
+ private void Wakeup()
+ {
+ if (IsSleeping())
+ {
+ m_animator.SetBool("sleeping", value: false);
+ m_nview.GetZDO().Set("sleeping", value: false);
+ m_wakeupEffects.Create(base.transform.position, base.transform.rotation);
+ }
+ }
+
+ public override bool IsSleeping()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetBool("sleeping", m_sleeping);
+ }
+
+ protected override void SetAlerted(bool alert)
+ {
+ if (alert)
+ {
+ m_timeSinceSensedTargetCreature = 0f;
+ }
+ base.SetAlerted(alert);
+ }
+
+ public override bool HuntPlayer()
+ {
+ if (base.HuntPlayer())
+ {
+ if (m_eventCreature && !RandEventSystem.InEvent())
+ {
+ return false;
+ }
+ if (m_despawnInDay && EnvMan.instance.IsDay())
+ {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public GameObject GetFollowTarget()
+ {
+ return m_follow;
+ }
+
+ public void SetFollowTarget(GameObject go)
+ {
+ m_follow = go;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MovementTest.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MovementTest.cs
new file mode 100644
index 0000000..4ac6ec2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MovementTest.cs
@@ -0,0 +1,30 @@
+using UnityEngine;
+
+public class MovementTest : MonoBehaviour
+{
+ public float m_speed = 10f;
+
+ private float m_timer;
+
+ private Rigidbody m_body;
+
+ private Vector3 m_center;
+
+ private Vector3 m_vel;
+
+ private void Start()
+ {
+ m_body = GetComponent<Rigidbody>();
+ m_center = base.transform.position;
+ }
+
+ private void FixedUpdate()
+ {
+ m_timer += Time.fixedDeltaTime;
+ float num = 5f;
+ Vector3 vector = m_center + new Vector3(Mathf.Sin(m_timer * m_speed) * num, 0f, Mathf.Cos(m_timer * m_speed) * num);
+ m_vel = (vector - m_body.position) / Time.fixedDeltaTime;
+ m_body.position = vector;
+ m_body.velocity = m_vel;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MusicMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MusicMan.cs
new file mode 100644
index 0000000..e5735f4
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/MusicMan.cs
@@ -0,0 +1,473 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Audio;
+
+public class MusicMan : MonoBehaviour
+{
+ [Serializable]
+ public class NamedMusic
+ {
+ public string m_name = "";
+
+ public AudioClip[] m_clips;
+
+ public float m_volume = 1f;
+
+ public float m_fadeInTime = 3f;
+
+ public bool m_alwaysFadeout;
+
+ public bool m_loop;
+
+ public bool m_resume;
+
+ public bool m_enabled = true;
+
+ public bool m_ambientMusic;
+
+ [NonSerialized]
+ public int m_savedPlaybackPos;
+
+ [NonSerialized]
+ public float m_lastPlayedTime;
+ }
+
+ private string m_triggeredMusic = "";
+
+ private static MusicMan m_instance;
+
+ public static float m_masterMusicVolume = 1f;
+
+ public AudioMixerGroup m_musicMixer;
+
+ public List<NamedMusic> m_music = new List<NamedMusic>();
+
+ [Header("Combat")]
+ public float m_combatMusicTimeout = 4f;
+
+ [Header("Sailing")]
+ public float m_sailMusicShipSpeedThreshold = 3f;
+
+ public float m_sailMusicMinSailTime = 20f;
+
+ [Header("Ambient music")]
+ public float m_randomMusicIntervalMin = 300f;
+
+ public float m_randomMusicIntervalMax = 500f;
+
+ private NamedMusic m_queuedMusic;
+
+ private NamedMusic m_currentMusic;
+
+ private float m_musicVolume = 1f;
+
+ private float m_musicFadeTime = 3f;
+
+ private bool m_alwaysFadeout;
+
+ private bool m_stopMusic;
+
+ private string m_randomEventMusic;
+
+ private float m_lastAmbientMusicTime;
+
+ private float m_randomAmbientInterval;
+
+ private string m_triggerMusic;
+
+ private float m_combatTimer;
+
+ private AudioSource m_musicSource;
+
+ private float m_currentMusicVol;
+
+ private float m_sailDuration;
+
+ private float m_notSailDuration;
+
+ public static MusicMan instance => m_instance;
+
+ private void Awake()
+ {
+ if ((bool)m_instance)
+ {
+ return;
+ }
+ m_instance = this;
+ GameObject gameObject = new GameObject("music");
+ gameObject.transform.SetParent(base.transform);
+ m_musicSource = gameObject.AddComponent<AudioSource>();
+ m_musicSource.loop = true;
+ m_musicSource.spatialBlend = 0f;
+ m_musicSource.outputAudioMixerGroup = m_musicMixer;
+ m_musicSource.bypassReverbZones = true;
+ m_randomAmbientInterval = UnityEngine.Random.Range(m_randomMusicIntervalMin, m_randomMusicIntervalMax);
+ m_masterMusicVolume = PlayerPrefs.GetFloat("MusicVolume", 1f);
+ ApplySettings();
+ foreach (NamedMusic item in m_music)
+ {
+ AudioClip[] clips = item.m_clips;
+ foreach (AudioClip audioClip in clips)
+ {
+ if (audioClip == null || !audioClip)
+ {
+ item.m_enabled = false;
+ ZLog.LogWarning("Missing audio clip in music " + item.m_name);
+ break;
+ }
+ }
+ }
+ }
+
+ public void ApplySettings()
+ {
+ bool flag = PlayerPrefs.GetInt("ContinousMusic", 0) == 1;
+ foreach (NamedMusic item in m_music)
+ {
+ if (item.m_ambientMusic)
+ {
+ item.m_loop = flag;
+ if (!flag && GetCurrentMusic() == item.m_name && m_musicSource.loop)
+ {
+ StopMusic();
+ }
+ }
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ private void Update()
+ {
+ if (!(m_instance != this))
+ {
+ float deltaTime = Time.deltaTime;
+ UpdateCurrentMusic(deltaTime);
+ UpdateCombatMusic(deltaTime);
+ UpdateMusic(deltaTime);
+ }
+ }
+
+ private void UpdateCurrentMusic(float dt)
+ {
+ string currentMusic = GetCurrentMusic();
+ if (Game.instance != null)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ StartMusic("respawn");
+ return;
+ }
+ if (currentMusic == "respawn")
+ {
+ StopMusic();
+ }
+ }
+ if ((bool)Player.m_localPlayer && Player.m_localPlayer.InIntro())
+ {
+ StartMusic("intro");
+ return;
+ }
+ if (currentMusic == "intro")
+ {
+ StopMusic();
+ }
+ if (!HandleEventMusic(currentMusic) && !HandleSailingMusic(dt, currentMusic) && !HandleTriggerMusic(currentMusic))
+ {
+ HandleEnvironmentMusic(dt, currentMusic);
+ }
+ }
+
+ private bool HandleEnvironmentMusic(float dt, string currentMusic)
+ {
+ if (!EnvMan.instance)
+ {
+ return false;
+ }
+ NamedMusic environmentMusic = GetEnvironmentMusic();
+ if (environmentMusic == null || (!environmentMusic.m_loop && environmentMusic.m_name != GetCurrentMusic()))
+ {
+ StopMusic();
+ return true;
+ }
+ if (!environmentMusic.m_loop)
+ {
+ if (Time.time - m_lastAmbientMusicTime < m_randomAmbientInterval)
+ {
+ return false;
+ }
+ m_randomAmbientInterval = UnityEngine.Random.Range(m_randomMusicIntervalMin, m_randomMusicIntervalMax);
+ m_lastAmbientMusicTime = Time.time;
+ }
+ StartMusic(environmentMusic);
+ return true;
+ }
+
+ private NamedMusic GetEnvironmentMusic()
+ {
+ string text = null;
+ text = ((!Player.m_localPlayer || !Player.m_localPlayer.IsSafeInHome()) ? EnvMan.instance.GetAmbientMusic() : "home");
+ return FindMusic(text);
+ }
+
+ private bool HandleTriggerMusic(string currentMusic)
+ {
+ if (m_triggerMusic != null)
+ {
+ StartMusic(m_triggerMusic);
+ m_triggeredMusic = m_triggerMusic;
+ m_triggerMusic = null;
+ return true;
+ }
+ if (m_triggeredMusic != null)
+ {
+ if (currentMusic == m_triggeredMusic)
+ {
+ return true;
+ }
+ m_triggeredMusic = null;
+ }
+ return false;
+ }
+
+ private bool HandleEventMusic(string currentMusic)
+ {
+ if ((bool)RandEventSystem.instance)
+ {
+ string musicOverride = RandEventSystem.instance.GetMusicOverride();
+ if (musicOverride != null)
+ {
+ StartMusic(musicOverride);
+ m_randomEventMusic = musicOverride;
+ return true;
+ }
+ if (currentMusic == m_randomEventMusic)
+ {
+ m_randomEventMusic = null;
+ StopMusic();
+ }
+ }
+ return false;
+ }
+
+ private bool HandleCombatMusic(string currentMusic)
+ {
+ if (InCombat())
+ {
+ StartMusic("combat");
+ return true;
+ }
+ if (currentMusic == "combat")
+ {
+ StopMusic();
+ }
+ return false;
+ }
+
+ private bool HandleSailingMusic(float dt, string currentMusic)
+ {
+ if (IsSailing())
+ {
+ m_notSailDuration = 0f;
+ m_sailDuration += dt;
+ if (m_sailDuration > m_sailMusicMinSailTime)
+ {
+ StartMusic("sailing");
+ return true;
+ }
+ }
+ else
+ {
+ m_sailDuration = 0f;
+ m_notSailDuration += dt;
+ if (m_notSailDuration > m_sailMusicMinSailTime / 2f && currentMusic == "sailing")
+ {
+ StopMusic();
+ }
+ }
+ return false;
+ }
+
+ private bool IsSailing()
+ {
+ if (!Player.m_localPlayer)
+ {
+ return false;
+ }
+ Ship localShip = Ship.GetLocalShip();
+ if ((bool)localShip && localShip.GetSpeed() > m_sailMusicShipSpeedThreshold)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void UpdateMusic(float dt)
+ {
+ if (m_queuedMusic != null || m_stopMusic)
+ {
+ if (!m_musicSource.isPlaying || m_currentMusicVol <= 0f)
+ {
+ if (m_musicSource.isPlaying && m_currentMusic != null && m_currentMusic.m_loop && m_currentMusic.m_resume)
+ {
+ m_currentMusic.m_lastPlayedTime = Time.time;
+ m_currentMusic.m_savedPlaybackPos = m_musicSource.timeSamples;
+ ZLog.Log("Stoped music " + m_currentMusic.m_name + " at " + m_currentMusic.m_savedPlaybackPos);
+ }
+ m_musicSource.Stop();
+ m_stopMusic = false;
+ m_currentMusic = null;
+ if (m_queuedMusic != null)
+ {
+ m_musicSource.clip = m_queuedMusic.m_clips[UnityEngine.Random.Range(0, m_queuedMusic.m_clips.Length)];
+ m_musicSource.loop = m_queuedMusic.m_loop;
+ m_musicSource.volume = 0f;
+ m_musicSource.timeSamples = 0;
+ m_musicSource.Play();
+ if (m_queuedMusic.m_loop && m_queuedMusic.m_resume && Time.time - m_queuedMusic.m_lastPlayedTime < m_musicSource.clip.length * 2f)
+ {
+ m_musicSource.timeSamples = m_queuedMusic.m_savedPlaybackPos;
+ ZLog.Log("Resumed music " + m_queuedMusic.m_name + " at " + m_queuedMusic.m_savedPlaybackPos);
+ }
+ m_currentMusicVol = 0f;
+ m_musicVolume = m_queuedMusic.m_volume;
+ m_musicFadeTime = m_queuedMusic.m_fadeInTime;
+ m_alwaysFadeout = m_queuedMusic.m_alwaysFadeout;
+ m_currentMusic = m_queuedMusic;
+ m_queuedMusic = null;
+ }
+ }
+ else
+ {
+ float num = ((m_queuedMusic != null) ? Mathf.Min(m_queuedMusic.m_fadeInTime, m_musicFadeTime) : m_musicFadeTime);
+ m_currentMusicVol = Mathf.MoveTowards(m_currentMusicVol, 0f, dt / num);
+ m_musicSource.volume = Utils.SmoothStep(0f, 1f, m_currentMusicVol) * m_musicVolume * m_masterMusicVolume;
+ }
+ }
+ else if (m_musicSource.isPlaying)
+ {
+ float num2 = m_musicSource.clip.length - m_musicSource.time;
+ if (m_alwaysFadeout && !m_musicSource.loop && num2 < m_musicFadeTime)
+ {
+ m_currentMusicVol = Mathf.MoveTowards(m_currentMusicVol, 0f, dt / m_musicFadeTime);
+ m_musicSource.volume = Utils.SmoothStep(0f, 1f, m_currentMusicVol) * m_musicVolume * m_masterMusicVolume;
+ }
+ else
+ {
+ m_currentMusicVol = Mathf.MoveTowards(m_currentMusicVol, 1f, dt / m_musicFadeTime);
+ m_musicSource.volume = Utils.SmoothStep(0f, 1f, m_currentMusicVol) * m_musicVolume * m_masterMusicVolume;
+ }
+ }
+ else if (m_currentMusic != null && !m_musicSource.isPlaying)
+ {
+ m_currentMusic = null;
+ }
+ }
+
+ private void UpdateCombatMusic(float dt)
+ {
+ if (m_combatTimer > 0f)
+ {
+ m_combatTimer -= Time.deltaTime;
+ }
+ }
+
+ public void ResetCombatTimer()
+ {
+ m_combatTimer = m_combatMusicTimeout;
+ }
+
+ private bool InCombat()
+ {
+ return m_combatTimer > 0f;
+ }
+
+ public void TriggerMusic(string name)
+ {
+ m_triggerMusic = name;
+ }
+
+ private void StartMusic(string name)
+ {
+ if (!(GetCurrentMusic() == name))
+ {
+ NamedMusic music = FindMusic(name);
+ StartMusic(music);
+ }
+ }
+
+ private void StartMusic(NamedMusic music)
+ {
+ if (music == null || !(GetCurrentMusic() == music.m_name))
+ {
+ if (music != null)
+ {
+ m_queuedMusic = music;
+ m_stopMusic = false;
+ }
+ else
+ {
+ StopMusic();
+ }
+ }
+ }
+
+ private NamedMusic FindMusic(string name)
+ {
+ if (name == null || name.Length == 0)
+ {
+ return null;
+ }
+ foreach (NamedMusic item in m_music)
+ {
+ if (item.m_name == name && item.m_enabled && item.m_clips.Length != 0 && (bool)item.m_clips[0])
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public bool IsPlaying()
+ {
+ return m_musicSource.isPlaying;
+ }
+
+ private string GetCurrentMusic()
+ {
+ if (m_stopMusic)
+ {
+ return "";
+ }
+ if (m_queuedMusic != null)
+ {
+ return m_queuedMusic.m_name;
+ }
+ if (m_currentMusic != null)
+ {
+ return m_currentMusic.m_name;
+ }
+ return "";
+ }
+
+ private void StopMusic()
+ {
+ m_queuedMusic = null;
+ m_stopMusic = true;
+ }
+
+ public void Reset()
+ {
+ StopMusic();
+ m_combatTimer = 0f;
+ m_randomEventMusic = null;
+ m_triggerMusic = null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/NavmeshTest.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/NavmeshTest.cs
new file mode 100644
index 0000000..c0b4a0c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/NavmeshTest.cs
@@ -0,0 +1,62 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class NavmeshTest : MonoBehaviour
+{
+ public Transform m_target;
+
+ public Pathfinding.AgentType m_agentType = Pathfinding.AgentType.Humanoid;
+
+ public bool m_cleanPath = true;
+
+ private List<Vector3> m_path = new List<Vector3>();
+
+ private bool m_havePath;
+
+ private void Awake()
+ {
+ }
+
+ private void Update()
+ {
+ if (Pathfinding.instance.GetPath(base.transform.position, m_target.position, m_path, m_agentType, requireFullPath: false, m_cleanPath))
+ {
+ m_havePath = true;
+ }
+ else
+ {
+ m_havePath = false;
+ }
+ }
+
+ private void OnDrawGizmos()
+ {
+ if (m_target == null)
+ {
+ return;
+ }
+ if (m_havePath)
+ {
+ Gizmos.color = Color.yellow;
+ for (int i = 0; i < m_path.Count - 1; i++)
+ {
+ Vector3 vector = m_path[i];
+ Gizmos.DrawLine(to: m_path[i + 1] + Vector3.up * 0.2f, from: vector + Vector3.up * 0.2f);
+ }
+ foreach (Vector3 item in m_path)
+ {
+ Gizmos.DrawSphere(item + Vector3.up * 0.2f, 0.1f);
+ }
+ Gizmos.color = Color.green;
+ Gizmos.DrawSphere(base.transform.position, 0.3f);
+ Gizmos.DrawSphere(m_target.position, 0.3f);
+ }
+ else
+ {
+ Gizmos.color = Color.red;
+ Gizmos.DrawLine(base.transform.position + Vector3.up * 0.2f, m_target.position + Vector3.up * 0.2f);
+ Gizmos.DrawSphere(base.transform.position, 0.3f);
+ Gizmos.DrawSphere(m_target.position, 0.3f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ObjectDB.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ObjectDB.cs
new file mode 100644
index 0000000..46c0f5c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ObjectDB.cs
@@ -0,0 +1,104 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ObjectDB : MonoBehaviour
+{
+ private static ObjectDB m_instance;
+
+ public List<StatusEffect> m_StatusEffects = new List<StatusEffect>();
+
+ public List<GameObject> m_items = new List<GameObject>();
+
+ public List<Recipe> m_recipes = new List<Recipe>();
+
+ private Dictionary<int, GameObject> m_itemByHash = new Dictionary<int, GameObject>();
+
+ public static ObjectDB instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ UpdateItemHashes();
+ }
+
+ public void CopyOtherDB(ObjectDB other)
+ {
+ m_items = other.m_items;
+ m_recipes = other.m_recipes;
+ m_StatusEffects = other.m_StatusEffects;
+ UpdateItemHashes();
+ }
+
+ private void UpdateItemHashes()
+ {
+ m_itemByHash.Clear();
+ foreach (GameObject item in m_items)
+ {
+ m_itemByHash.Add(item.name.GetStableHashCode(), item);
+ }
+ }
+
+ public StatusEffect GetStatusEffect(string name)
+ {
+ foreach (StatusEffect statusEffect in m_StatusEffects)
+ {
+ if (statusEffect.name == name)
+ {
+ return statusEffect;
+ }
+ }
+ return null;
+ }
+
+ public GameObject GetItemPrefab(string name)
+ {
+ foreach (GameObject item in m_items)
+ {
+ if (item.name == name)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public GameObject GetItemPrefab(int hash)
+ {
+ if (m_itemByHash.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ public int GetPrefabHash(GameObject prefab)
+ {
+ return prefab.name.GetStableHashCode();
+ }
+
+ public List<ItemDrop> GetAllItems(ItemDrop.ItemData.ItemType type, string startWith)
+ {
+ List<ItemDrop> list = new List<ItemDrop>();
+ foreach (GameObject item in m_items)
+ {
+ ItemDrop component = item.GetComponent<ItemDrop>();
+ if (component.m_itemData.m_shared.m_itemType == type && component.gameObject.name.StartsWith(startWith))
+ {
+ list.Add(component);
+ }
+ }
+ return list;
+ }
+
+ public Recipe GetRecipe(ItemDrop.ItemData item)
+ {
+ foreach (Recipe recipe in m_recipes)
+ {
+ if (!(recipe.m_item == null) && recipe.m_item.m_itemData.m_shared.m_name == item.m_shared.m_name)
+ {
+ return recipe;
+ }
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Odin.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Odin.cs
new file mode 100644
index 0000000..7a82e11
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Odin.cs
@@ -0,0 +1,55 @@
+using UnityEngine;
+
+public class Odin : MonoBehaviour
+{
+ public float m_despawnCloseDistance = 20f;
+
+ public float m_despawnFarDistance = 50f;
+
+ public EffectList m_despawn = new EffectList();
+
+ public float m_ttl = 300f;
+
+ private float m_time;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ }
+
+ private void Update()
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, m_despawnFarDistance);
+ if (closestPlayer == null)
+ {
+ m_despawn.Create(base.transform.position, base.transform.rotation);
+ m_nview.Destroy();
+ ZLog.Log("No player in range, despawning");
+ return;
+ }
+ Vector3 forward = closestPlayer.transform.position - base.transform.position;
+ forward.y = 0f;
+ forward.Normalize();
+ base.transform.rotation = Quaternion.LookRotation(forward);
+ if (Vector3.Distance(closestPlayer.transform.position, base.transform.position) < m_despawnCloseDistance)
+ {
+ m_despawn.Create(base.transform.position, base.transform.rotation);
+ m_nview.Destroy();
+ ZLog.Log("Player go too close,despawning");
+ return;
+ }
+ m_time += Time.deltaTime;
+ if (m_time > m_ttl)
+ {
+ m_despawn.Create(base.transform.position, base.transform.rotation);
+ m_nview.Destroy();
+ ZLog.Log("timeout " + m_time + " , despawning");
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/OfferingBowl.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/OfferingBowl.cs
new file mode 100644
index 0000000..8f361b3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/OfferingBowl.cs
@@ -0,0 +1,213 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class OfferingBowl : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "Ancient bowl";
+
+ public string m_useItemText = "Burn item";
+
+ public ItemDrop m_bossItem;
+
+ public int m_bossItems = 1;
+
+ public GameObject m_bossPrefab;
+
+ public ItemDrop m_itemPrefab;
+
+ public Transform m_itemSpawnPoint;
+
+ public string m_setGlobalKey = "";
+
+ [Header("Boss")]
+ public float m_spawnBossDelay = 5f;
+
+ public float m_spawnBossMaxDistance = 40f;
+
+ public float m_spawnBossMaxYDistance = 9999f;
+
+ public float m_spawnOffset = 1f;
+
+ [Header("Use itemstands")]
+ public bool m_useItemStands;
+
+ public string m_itemStandPrefix = "";
+
+ public float m_itemstandMaxRange = 20f;
+
+ [Header("Effects")]
+ public EffectList m_fuelAddedEffects = new EffectList();
+
+ public EffectList m_spawnBossStartEffects = new EffectList();
+
+ public EffectList m_spawnBossDoneffects = new EffectList();
+
+ private Vector3 m_bossSpawnPoint;
+
+ private void Awake()
+ {
+ }
+
+ public string GetHoverText()
+ {
+ if (m_useItemStands)
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] ") + Localization.instance.Localize(m_useItemText);
+ }
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>1-8</b></color>] " + m_useItemText);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (IsBossSpawnQueued())
+ {
+ return false;
+ }
+ if (m_useItemStands)
+ {
+ List<ItemStand> list = FindItemStands();
+ foreach (ItemStand item in list)
+ {
+ if (!item.HaveAttachment())
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_incompleteoffering");
+ return false;
+ }
+ }
+ if (SpawnBoss(base.transform.position))
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_offerdone");
+ foreach (ItemStand item2 in list)
+ {
+ item2.DestroyAttachment();
+ }
+ if ((bool)m_itemSpawnPoint)
+ {
+ m_fuelAddedEffects.Create(m_itemSpawnPoint.position, base.transform.rotation);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (m_useItemStands)
+ {
+ return false;
+ }
+ if (IsBossSpawnQueued())
+ {
+ return true;
+ }
+ if (m_bossItem != null)
+ {
+ if (item.m_shared.m_name == m_bossItem.m_itemData.m_shared.m_name)
+ {
+ int num = user.GetInventory().CountItems(m_bossItem.m_itemData.m_shared.m_name);
+ if (num < m_bossItems)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_incompleteoffering: " + m_bossItem.m_itemData.m_shared.m_name + " " + num + " / " + m_bossItems);
+ return true;
+ }
+ if (m_bossPrefab != null)
+ {
+ if (SpawnBoss(base.transform.position))
+ {
+ user.GetInventory().RemoveItem(item.m_shared.m_name, m_bossItems);
+ user.ShowRemovedMessage(m_bossItem.m_itemData, m_bossItems);
+ user.Message(MessageHud.MessageType.Center, "$msg_offerdone");
+ if ((bool)m_itemSpawnPoint)
+ {
+ m_fuelAddedEffects.Create(m_itemSpawnPoint.position, base.transform.rotation);
+ }
+ }
+ }
+ else if (m_itemPrefab != null && SpawnItem(m_itemPrefab, user as Player))
+ {
+ user.GetInventory().RemoveItem(item.m_shared.m_name, m_bossItems);
+ user.ShowRemovedMessage(m_bossItem.m_itemData, m_bossItems);
+ user.Message(MessageHud.MessageType.Center, "$msg_offerdone");
+ m_fuelAddedEffects.Create(m_itemSpawnPoint.position, base.transform.rotation);
+ }
+ if (!string.IsNullOrEmpty(m_setGlobalKey))
+ {
+ ZoneSystem.instance.SetGlobalKey(m_setGlobalKey);
+ }
+ return true;
+ }
+ user.Message(MessageHud.MessageType.Center, "$msg_offerwrong");
+ return true;
+ }
+ return false;
+ }
+
+ private bool SpawnItem(ItemDrop item, Player player)
+ {
+ if (item.m_itemData.m_shared.m_questItem && player.HaveUniqueKey(item.m_itemData.m_shared.m_name))
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_cantoffer");
+ return false;
+ }
+ Object.Instantiate(item, m_itemSpawnPoint.position, Quaternion.identity);
+ return true;
+ }
+
+ private bool SpawnBoss(Vector3 point)
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ Vector2 vector = Random.insideUnitCircle * m_spawnBossMaxDistance;
+ Vector3 vector2 = point + new Vector3(vector.x, 0f, vector.y);
+ float solidHeight = ZoneSystem.instance.GetSolidHeight(vector2);
+ if (!(solidHeight < 0f) && !(Mathf.Abs(solidHeight - base.transform.position.y) > m_spawnBossMaxYDistance))
+ {
+ vector2.y = solidHeight + m_spawnOffset;
+ m_spawnBossStartEffects.Create(vector2, Quaternion.identity);
+ m_bossSpawnPoint = vector2;
+ Invoke("DelayedSpawnBoss", m_spawnBossDelay);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsBossSpawnQueued()
+ {
+ return IsInvoking("DelayedSpawnBoss");
+ }
+
+ private void DelayedSpawnBoss()
+ {
+ BaseAI component = Object.Instantiate(m_bossPrefab, m_bossSpawnPoint, Quaternion.identity).GetComponent<BaseAI>();
+ if (component != null)
+ {
+ component.SetPatrolPoint();
+ }
+ m_spawnBossDoneffects.Create(m_bossSpawnPoint, Quaternion.identity);
+ }
+
+ private List<ItemStand> FindItemStands()
+ {
+ List<ItemStand> list = new List<ItemStand>();
+ ItemStand[] array = Object.FindObjectsOfType<ItemStand>();
+ foreach (ItemStand itemStand in array)
+ {
+ if (!(Vector3.Distance(base.transform.position, itemStand.transform.position) > m_itemstandMaxRange) && itemStand.gameObject.name.StartsWith(m_itemStandPrefix))
+ {
+ list.Add(itemStand);
+ }
+ }
+ return list;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ParticleDecal.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ParticleDecal.cs
new file mode 100644
index 0000000..f9bf10e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ParticleDecal.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class ParticleDecal : MonoBehaviour
+{
+ public ParticleSystem m_decalSystem;
+
+ [Range(0f, 100f)]
+ public float m_chance = 100f;
+
+ private ParticleSystem part;
+
+ private List<ParticleCollisionEvent> collisionEvents = new List<ParticleCollisionEvent>();
+
+ private void Awake()
+ {
+ part = GetComponent<ParticleSystem>();
+ collisionEvents = new List<ParticleCollisionEvent>();
+ }
+
+ private void OnParticleCollision(GameObject other)
+ {
+ if (!(m_chance < 100f) || !(Random.Range(0f, 100f) > m_chance))
+ {
+ int num = part.GetCollisionEvents(other, collisionEvents);
+ for (int i = 0; i < num; i++)
+ {
+ ParticleCollisionEvent particleCollisionEvent = collisionEvents[i];
+ Vector3 eulerAngles = Quaternion.LookRotation(particleCollisionEvent.normal).eulerAngles;
+ eulerAngles.x = 0f - eulerAngles.x + 180f;
+ eulerAngles.y = 0f - eulerAngles.y;
+ eulerAngles.z = Random.Range(0, 360);
+ ParticleSystem.EmitParams emitParams = default(ParticleSystem.EmitParams);
+ emitParams.position = particleCollisionEvent.intersection;
+ emitParams.rotation3D = eulerAngles;
+ emitParams.velocity = -particleCollisionEvent.normal * 0.001f;
+ m_decalSystem.Emit(emitParams, 1);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pathfinding.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pathfinding.cs
new file mode 100644
index 0000000..6e82c22
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pathfinding.cs
@@ -0,0 +1,755 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.AI;
+
+public class Pathfinding : MonoBehaviour
+{
+ // ؼ
+ private class NavMeshTile
+ {
+ public Vector3Int m_tile;
+
+ public Vector3 m_center;
+
+ public float m_pokeTime = -1000f;
+
+ public float m_buildTime = -1000f;
+
+ public NavMeshData m_data;
+
+ public NavMeshDataInstance m_instance;
+
+ public List<KeyValuePair<Vector3, NavMeshLinkInstance>> m_links1 = new List<KeyValuePair<Vector3, NavMeshLinkInstance>>();
+
+ public List<KeyValuePair<Vector3, NavMeshLinkInstance>> m_links2 = new List<KeyValuePair<Vector3, NavMeshLinkInstance>>();
+ }
+
+ public enum AgentType
+ {
+ Humanoid = 1,
+ TrollSize,
+ HugeSize,
+ HorseSize,
+ HumanoidNoSwim,
+ HumanoidAvoidWater,
+ Fish,
+ Wolf,
+ BigFish,
+ GoblinBruteSize,
+ HumanoidBigNoSwim
+ }
+
+ public enum AreaType
+ {
+ Default,
+ NotWalkable,
+ Jump,
+ Water
+ }
+
+ private class AgentSettings
+ {
+ public AgentType m_agentType;
+
+ public NavMeshBuildSettings m_build;
+
+ public bool m_canWalk = true;
+
+ public bool m_avoidWater;
+
+ public bool m_canSwim = true;
+
+ public float m_swimDepth;
+
+ public int m_areaMask = -1;
+
+ public AgentSettings(AgentType type)
+ {
+ m_agentType = type;
+ m_build = NavMesh.CreateSettings();
+ }
+ }
+
+ private List<Vector3> tempPath = new List<Vector3>();
+
+ private List<Vector3> optPath = new List<Vector3>();
+
+ private List<Vector3> tempStitchPoints = new List<Vector3>();
+
+ private RaycastHit[] tempHitArray = new RaycastHit[255];
+
+ private static Pathfinding m_instance;
+
+ public LayerMask m_layers;
+
+ public LayerMask m_waterLayers;
+
+ private Dictionary<Vector3Int, NavMeshTile> m_tiles = new Dictionary<Vector3Int, NavMeshTile>();
+
+ public float m_tileSize = 32f;
+
+ public float m_defaultCost = 1f;
+
+ public float m_waterCost = 4f;
+
+ public float m_linkCost = 10f;
+
+ public float m_linkWidth = 1f;
+
+ public float m_updateInterval = 5f;
+
+ public float m_tileTimeout = 30f;
+
+ private const float m_tileHeight = 6000f;
+
+ private const float m_tileY = 2500f;
+
+ private float m_updatePathfindingTimer;
+
+ private Queue<Vector3Int> m_queuedAreas = new Queue<Vector3Int>();
+
+ private Queue<NavMeshLinkInstance> m_linkRemoveQueue = new Queue<NavMeshLinkInstance>();
+
+ private Queue<NavMeshDataInstance> m_tileRemoveQueue = new Queue<NavMeshDataInstance>();
+
+ private Vector3Int m_cachedTileID = new Vector3Int(-9999999, -9999999, -9999999);
+
+ private NavMeshTile m_cachedTile;
+
+ private List<AgentSettings> m_agentSettings = new List<AgentSettings>();
+
+ private AsyncOperation m_buildOperation;
+
+ private NavMeshTile m_buildTile;
+
+ private List<KeyValuePair<NavMeshTile, NavMeshTile>> m_edgeBuildQueue = new List<KeyValuePair<NavMeshTile, NavMeshTile>>();
+
+ private NavMeshPath m_path;
+
+ public static Pathfinding instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ SetupAgents();
+ m_path = new NavMeshPath();
+ }
+
+ private void ClearAgentSettings()
+ {
+ List<NavMeshBuildSettings> list = new List<NavMeshBuildSettings>();
+ for (int i = 0; i < NavMesh.GetSettingsCount(); i++)
+ {
+ list.Add(NavMesh.GetSettingsByIndex(i));
+ }
+ ZLog.Log("Build settings:" + list.Count);
+ foreach (NavMeshBuildSettings item in list)
+ {
+ if (item.agentTypeID != 0)
+ {
+ ZLog.Log("Removing " + item.agentTypeID);
+ NavMesh.RemoveSettings(item.agentTypeID);
+ }
+ }
+ }
+
+ private void OnDestroy()
+ {
+ foreach (NavMeshTile value in m_tiles.Values)
+ {
+ ClearLinks(value);
+ if ((bool)value.m_data)
+ {
+ NavMesh.RemoveNavMeshData(value.m_instance);
+ }
+ }
+ m_tiles.Clear();
+ DestroyAllLinks();
+ }
+
+ private AgentSettings AddAgent(AgentType type, AgentSettings copy = null)
+ {
+ while ((int)(type + 1) > m_agentSettings.Count)
+ {
+ m_agentSettings.Add(null);
+ }
+ AgentSettings agentSettings = new AgentSettings(type);
+ if (copy != null)
+ {
+ agentSettings.m_build.agentHeight = copy.m_build.agentHeight;
+ agentSettings.m_build.agentClimb = copy.m_build.agentClimb;
+ agentSettings.m_build.agentRadius = copy.m_build.agentRadius;
+ agentSettings.m_build.agentSlope = copy.m_build.agentSlope;
+ }
+ m_agentSettings[(int)type] = agentSettings;
+ return agentSettings;
+ }
+
+ private void SetupAgents()
+ {
+ ClearAgentSettings();
+ AgentSettings agentSettings = AddAgent(AgentType.Humanoid);
+ agentSettings.m_build.agentHeight = 1.8f;
+ agentSettings.m_build.agentClimb = 0.3f;
+ agentSettings.m_build.agentRadius = 0.4f;
+ agentSettings.m_build.agentSlope = 85f;
+ AddAgent(AgentType.Wolf, agentSettings).m_build.agentSlope = 85f;
+ AddAgent(AgentType.HumanoidNoSwim, agentSettings).m_canSwim = false;
+ AgentSettings agentSettings2 = AddAgent(AgentType.HumanoidBigNoSwim);
+ agentSettings2.m_build.agentHeight = 2.5f;
+ agentSettings2.m_build.agentClimb = 0.3f;
+ agentSettings2.m_build.agentRadius = 0.5f;
+ agentSettings2.m_build.agentSlope = 85f;
+ agentSettings2.m_canSwim = false;
+ AddAgent(AgentType.HumanoidAvoidWater, agentSettings).m_avoidWater = true;
+ AgentSettings agentSettings3 = AddAgent(AgentType.TrollSize);
+ agentSettings3.m_build.agentHeight = 7f;
+ agentSettings3.m_build.agentClimb = 0.7f;
+ agentSettings3.m_build.agentRadius = 1f;
+ agentSettings3.m_build.agentSlope = 85f;
+ AgentSettings agentSettings4 = AddAgent(AgentType.GoblinBruteSize);
+ agentSettings4.m_build.agentHeight = 3.5f;
+ agentSettings4.m_build.agentClimb = 0.3f;
+ agentSettings4.m_build.agentRadius = 0.8f;
+ agentSettings4.m_build.agentSlope = 85f;
+ AgentSettings agentSettings5 = AddAgent(AgentType.HugeSize);
+ agentSettings5.m_build.agentHeight = 10f;
+ agentSettings5.m_build.agentClimb = 1.2f;
+ agentSettings5.m_build.agentRadius = 2f;
+ agentSettings5.m_build.agentSlope = 85f;
+ AgentSettings agentSettings6 = AddAgent(AgentType.HorseSize);
+ agentSettings6.m_build.agentHeight = 2.5f;
+ agentSettings6.m_build.agentClimb = 0.3f;
+ agentSettings6.m_build.agentRadius = 0.8f;
+ agentSettings6.m_build.agentSlope = 85f;
+ AgentSettings agentSettings7 = AddAgent(AgentType.Fish);
+ agentSettings7.m_build.agentHeight = 0.5f;
+ agentSettings7.m_build.agentClimb = 1f;
+ agentSettings7.m_build.agentRadius = 0.5f;
+ agentSettings7.m_build.agentSlope = 90f;
+ agentSettings7.m_canSwim = true;
+ agentSettings7.m_canWalk = false;
+ agentSettings7.m_swimDepth = 0.4f;
+ agentSettings7.m_areaMask = 12;
+ AgentSettings agentSettings8 = AddAgent(AgentType.BigFish);
+ agentSettings8.m_build.agentHeight = 1.5f;
+ agentSettings8.m_build.agentClimb = 1f;
+ agentSettings8.m_build.agentRadius = 1f;
+ agentSettings8.m_build.agentSlope = 90f;
+ agentSettings8.m_canSwim = true;
+ agentSettings8.m_canWalk = false;
+ agentSettings8.m_swimDepth = 1.5f;
+ agentSettings8.m_areaMask = 12;
+ NavMesh.SetAreaCost(0, m_defaultCost);
+ NavMesh.SetAreaCost(3, m_waterCost);
+ }
+
+ private AgentSettings GetSettings(AgentType agentType)
+ {
+ return m_agentSettings[(int)agentType];
+ }
+
+ private int GetAgentID(AgentType agentType)
+ {
+ return GetSettings(agentType).m_build.agentTypeID;
+ }
+
+ private void Update()
+ {
+ if (!IsBuilding())
+ {
+ m_updatePathfindingTimer += Time.deltaTime;
+ if (m_updatePathfindingTimer > 0.1f)
+ {
+ m_updatePathfindingTimer = 0f;
+ UpdatePathfinding();
+ }
+ if (!IsBuilding())
+ {
+ DestroyQueuedNavmeshData();
+ }
+ }
+ }
+
+ private void DestroyAllLinks()
+ {
+ while (m_linkRemoveQueue.Count > 0 || m_tileRemoveQueue.Count > 0)
+ {
+ DestroyQueuedNavmeshData();
+ }
+ }
+
+ private void DestroyQueuedNavmeshData()
+ {
+ if (m_linkRemoveQueue.Count > 0)
+ {
+ int num = Mathf.Min(m_linkRemoveQueue.Count, 25);
+ for (int i = 0; i < num; i++)
+ {
+ NavMesh.RemoveLink(m_linkRemoveQueue.Dequeue());
+ }
+ }
+ else if (m_tileRemoveQueue.Count > 0)
+ {
+ NavMesh.RemoveNavMeshData(m_tileRemoveQueue.Dequeue());
+ }
+ }
+
+ private void UpdatePathfinding()
+ {
+ Buildtiles();
+ TimeoutTiles();
+ }
+
+ public bool HavePath(Vector3 from, Vector3 to, AgentType agentType)
+ {
+ return GetPath(from, to, null, agentType, requireFullPath: true, cleanup: false);
+ }
+
+ public bool FindValidPoint(out Vector3 point, Vector3 center, float range, AgentType agentType)
+ {
+ PokePoint(center, agentType);
+ AgentSettings settings = GetSettings(agentType);
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = (int)settings.m_agentType;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.SamplePosition(center, out var hit, range, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ point = center;
+ return false;
+ }
+
+ public bool GetPath(Vector3 from, Vector3 to, List<Vector3> path, AgentType agentType, bool requireFullPath = false, bool cleanup = true)
+ {
+ path?.Clear();
+ PokeArea(from, agentType);
+ PokeArea(to, agentType);
+ AgentSettings settings = GetSettings(agentType);
+ if (!SnapToNavMesh(ref from, settings))
+ {
+ return false;
+ }
+ if (!SnapToNavMesh(ref to, settings))
+ {
+ return false;
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.CalculatePath(from, to, filter, m_path))
+ {
+ if (m_path.status == NavMeshPathStatus.PathPartial && requireFullPath)
+ {
+ return false;
+ }
+ if (path != null)
+ {
+ path.AddRange(m_path.corners);
+ if (cleanup)
+ {
+ CleanPath(path, settings);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void CleanPath(List<Vector3> basePath, AgentSettings settings)
+ {
+ if (basePath.Count <= 2)
+ {
+ return;
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ int num = 0;
+ optPath.Clear();
+ optPath.Add(basePath[num]);
+ do
+ {
+ num = FindNextNode(basePath, filter, num);
+ optPath.Add(basePath[num]);
+ }
+ while (num < basePath.Count - 1);
+ tempPath.Clear();
+ tempPath.Add(optPath[0]);
+ for (int i = 1; i < optPath.Count - 1; i++)
+ {
+ Vector3 vector = optPath[i - 1];
+ Vector3 vector2 = optPath[i];
+ Vector3 vector3 = optPath[i + 1];
+ Vector3 normalized = (vector3 - vector2).normalized;
+ Vector3 normalized2 = (vector2 - vector).normalized;
+ Vector3 vector4 = vector2 - (normalized + normalized2).normalized * Vector3.Distance(vector2, vector) * 0.33f;
+ vector4.y = (vector2.y + vector.y) * 0.5f;
+ Vector3 normalized3 = (vector4 - vector2).normalized;
+ if (!NavMesh.Raycast(vector2 + normalized3 * 0.1f, vector4, out var hit, filter) && !NavMesh.Raycast(vector4, vector, out hit, filter))
+ {
+ tempPath.Add(vector4);
+ }
+ tempPath.Add(vector2);
+ Vector3 vector5 = vector2 + (normalized + normalized2).normalized * Vector3.Distance(vector2, vector3) * 0.33f;
+ vector5.y = (vector2.y + vector3.y) * 0.5f;
+ Vector3 normalized4 = (vector5 - vector2).normalized;
+ if (!NavMesh.Raycast(vector2 + normalized4 * 0.1f, vector5, out hit, filter) && !NavMesh.Raycast(vector5, vector3, out hit, filter))
+ {
+ tempPath.Add(vector5);
+ }
+ }
+ tempPath.Add(optPath[optPath.Count - 1]);
+ basePath.Clear();
+ basePath.AddRange(tempPath);
+ }
+
+ private int FindNextNode(List<Vector3> path, NavMeshQueryFilter filter, int start)
+ {
+ for (int i = start + 2; i < path.Count; i++)
+ {
+ if (NavMesh.Raycast(path[start], path[i], out var _, filter))
+ {
+ return i - 1;
+ }
+ }
+ return path.Count - 1;
+ }
+
+ private bool SnapToNavMesh(ref Vector3 point, AgentSettings settings)
+ {
+ if ((bool)ZoneSystem.instance)
+ {
+ if (ZoneSystem.instance.GetGroundHeight(point, out var height) && point.y < height)
+ {
+ point.y = height;
+ }
+ if (settings.m_canSwim)
+ {
+ point.y = Mathf.Max(ZoneSystem.instance.m_waterLevel - settings.m_swimDepth, point.y);
+ }
+ }
+ NavMeshQueryFilter filter = default(NavMeshQueryFilter);
+ filter.agentTypeID = settings.m_build.agentTypeID;
+ filter.areaMask = settings.m_areaMask;
+ if (NavMesh.SamplePosition(point, out var hit, 1.5f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ if (NavMesh.SamplePosition(point, out hit, 10f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ if (NavMesh.SamplePosition(point, out hit, 20f, filter))
+ {
+ point = hit.position;
+ return true;
+ }
+ return false;
+ }
+
+ private void TimeoutTiles()
+ {
+ float realtimeSinceStartup = Time.realtimeSinceStartup;
+ foreach (KeyValuePair<Vector3Int, NavMeshTile> tile in m_tiles)
+ {
+ if (realtimeSinceStartup - tile.Value.m_pokeTime > m_tileTimeout)
+ {
+ ClearLinks(tile.Value);
+ if (tile.Value.m_instance.valid)
+ {
+ m_tileRemoveQueue.Enqueue(tile.Value.m_instance);
+ }
+ m_tiles.Remove(tile.Key);
+ break;
+ }
+ }
+ }
+
+ private void PokeArea(Vector3 point, AgentType agentType)
+ {
+ Vector3Int tile = GetTile(point, agentType);
+ PokeTile(tile);
+ for (int i = -1; i <= 1; i++)
+ {
+ for (int j = -1; j <= 1; j++)
+ {
+ if (j != 0 || i != 0)
+ {
+ Vector3Int tileID = new Vector3Int(tile.x + j, tile.y + i, tile.z);
+ PokeTile(tileID);
+ }
+ }
+ }
+ }
+
+ private void PokePoint(Vector3 point, AgentType agentType)
+ {
+ Vector3Int tile = GetTile(point, agentType);
+ PokeTile(tile);
+ }
+
+ private void PokeTile(Vector3Int tileID)
+ {
+ GetNavTile(tileID).m_pokeTime = Time.realtimeSinceStartup;
+ }
+
+ private void Buildtiles()
+ {
+ if (UpdateAsyncBuild())
+ {
+ return;
+ }
+ NavMeshTile navMeshTile = null;
+ float num = 0f;
+ foreach (NavMeshTile value in m_tiles.Values)
+ {
+ float num2 = value.m_pokeTime - value.m_buildTime;
+ if (num2 > m_updateInterval && (navMeshTile == null || num2 > num))
+ {
+ navMeshTile = value;
+ num = num2;
+ }
+ }
+ if (navMeshTile != null)
+ {
+ BuildTile(navMeshTile);
+ navMeshTile.m_buildTime = Time.realtimeSinceStartup;
+ }
+ }
+
+ private void BuildTile(NavMeshTile tile)
+ {
+ _ = DateTime.Now;
+ List<NavMeshBuildSource> list = new List<NavMeshBuildSource>();
+ List<NavMeshBuildMarkup> markups = new List<NavMeshBuildMarkup>();
+ AgentType z = (AgentType)tile.m_tile.z;
+ AgentSettings settings = GetSettings(z);
+ Bounds includedWorldBounds = new Bounds(tile.m_center, new Vector3(m_tileSize, 6000f, m_tileSize));
+ Bounds localBounds = new Bounds(Vector3.zero, new Vector3(m_tileSize, 6000f, m_tileSize));
+ int defaultArea = ((!settings.m_canWalk) ? 1 : 0);
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_layers.value, NavMeshCollectGeometry.PhysicsColliders, defaultArea, markups, list);
+ if (settings.m_avoidWater)
+ {
+ List<NavMeshBuildSource> list2 = new List<NavMeshBuildSource>();
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_waterLayers.value, NavMeshCollectGeometry.PhysicsColliders, 1, markups, list2);
+ foreach (NavMeshBuildSource item in list2)
+ {
+ NavMeshBuildSource current = item;
+ current.transform *= Matrix4x4.Translate(Vector3.down * 0.2f);
+ list.Add(current);
+ }
+ }
+ else if (settings.m_canSwim)
+ {
+ List<NavMeshBuildSource> list3 = new List<NavMeshBuildSource>();
+ NavMeshBuilder.CollectSources(includedWorldBounds, m_waterLayers.value, NavMeshCollectGeometry.PhysicsColliders, 3, markups, list3);
+ if (settings.m_swimDepth != 0f)
+ {
+ foreach (NavMeshBuildSource item2 in list3)
+ {
+ NavMeshBuildSource current2 = item2;
+ current2.transform *= Matrix4x4.Translate(Vector3.down * settings.m_swimDepth);
+ list.Add(current2);
+ }
+ }
+ else
+ {
+ list.AddRange(list3);
+ }
+ }
+ if (tile.m_data == null)
+ {
+ tile.m_data = new NavMeshData();
+ tile.m_data.position = tile.m_center;
+ }
+ m_buildOperation = NavMeshBuilder.UpdateNavMeshDataAsync(tile.m_data, settings.m_build, list, localBounds);
+ m_buildTile = tile;
+ }
+
+ private bool IsBuilding()
+ {
+ if (m_buildOperation != null)
+ {
+ return !m_buildOperation.isDone;
+ }
+ return false;
+ }
+
+ private bool UpdateAsyncBuild()
+ {
+ if (m_buildOperation == null)
+ {
+ return false;
+ }
+ if (!m_buildOperation.isDone)
+ {
+ return true;
+ }
+ if (!m_buildTile.m_instance.valid)
+ {
+ m_buildTile.m_instance = NavMesh.AddNavMeshData(m_buildTile.m_data);
+ }
+ RebuildLinks(m_buildTile);
+ m_buildOperation = null;
+ m_buildTile = null;
+ return true;
+ }
+
+ private void ClearLinks(NavMeshTile tile)
+ {
+ ClearLinks(tile.m_links1);
+ ClearLinks(tile.m_links2);
+ }
+
+ private void ClearLinks(List<KeyValuePair<Vector3, NavMeshLinkInstance>> links)
+ {
+ foreach (KeyValuePair<Vector3, NavMeshLinkInstance> link in links)
+ {
+ m_linkRemoveQueue.Enqueue(link.Value);
+ }
+ links.Clear();
+ }
+
+ private void RebuildLinks(NavMeshTile tile)
+ {
+ AgentType z = (AgentType)tile.m_tile.z;
+ AgentSettings settings = GetSettings(z);
+ float num = m_tileSize / 2f;
+ ConnectAlongEdge(tile.m_links1, tile.m_center + new Vector3(num, 0f, num), tile.m_center + new Vector3(num, 0f, 0f - num), m_linkWidth, settings);
+ ConnectAlongEdge(tile.m_links2, tile.m_center + new Vector3(0f - num, 0f, num), tile.m_center + new Vector3(num, 0f, num), m_linkWidth, settings);
+ }
+
+ private void ConnectAlongEdge(List<KeyValuePair<Vector3, NavMeshLinkInstance>> links, Vector3 p0, Vector3 p1, float step, AgentSettings settings)
+ {
+ Vector3 normalized = (p1 - p0).normalized;
+ Vector3 vector = Vector3.Cross(Vector3.up, normalized);
+ float num = Vector3.Distance(p0, p1);
+ bool canSwim = settings.m_canSwim;
+ tempStitchPoints.Clear();
+ for (float num2 = step / 2f; num2 <= num; num2 += step)
+ {
+ Vector3 p2 = p0 + normalized * num2;
+ FindGround(p2, canSwim, tempStitchPoints, settings);
+ }
+ if (CompareLinks(tempStitchPoints, links))
+ {
+ return;
+ }
+ ClearLinks(links);
+ foreach (Vector3 tempStitchPoint in tempStitchPoints)
+ {
+ NavMeshLinkData link = default(NavMeshLinkData);
+ link.startPosition = tempStitchPoint - vector * 0.1f;
+ link.endPosition = tempStitchPoint + vector * 0.1f;
+ link.width = step;
+ link.costModifier = m_linkCost;
+ link.bidirectional = true;
+ link.agentTypeID = settings.m_build.agentTypeID;
+ link.area = 2;
+ NavMeshLinkInstance value = NavMesh.AddLink(link);
+ if (value.valid)
+ {
+ links.Add(new KeyValuePair<Vector3, NavMeshLinkInstance>(tempStitchPoint, value));
+ }
+ }
+ }
+
+ private bool CompareLinks(List<Vector3> tempStitchPoints, List<KeyValuePair<Vector3, NavMeshLinkInstance>> links)
+ {
+ if (tempStitchPoints.Count != links.Count)
+ {
+ return false;
+ }
+ for (int i = 0; i < tempStitchPoints.Count; i++)
+ {
+ if (tempStitchPoints[i] != links[i].Key)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool SnapToNearestGround(Vector3 p, out Vector3 pos, float range)
+ {
+ if (Physics.Raycast(p + Vector3.up, Vector3.down, out var hitInfo, range + 1f, m_layers.value | m_waterLayers.value))
+ {
+ pos = hitInfo.point;
+ return true;
+ }
+ if (Physics.Raycast(p + Vector3.up * range, Vector3.down, out hitInfo, range, m_layers.value | m_waterLayers.value))
+ {
+ pos = hitInfo.point;
+ return true;
+ }
+ pos = p;
+ return false;
+ }
+
+ private void FindGround(Vector3 p, bool testWater, List<Vector3> hits, AgentSettings settings)
+ {
+ p.y = 6000f;
+ int layerMask = (testWater ? (m_layers.value | m_waterLayers.value) : m_layers.value);
+ float agentHeight = settings.m_build.agentHeight;
+ float y = p.y;
+ int num = Physics.RaycastNonAlloc(p, Vector3.down, tempHitArray, 10000f, layerMask);
+ for (int i = 0; i < num; i++)
+ {
+ Vector3 point = tempHitArray[i].point;
+ if (!(Mathf.Abs(point.y - y) < agentHeight))
+ {
+ y = point.y;
+ if (((1 << tempHitArray[i].collider.gameObject.layer) & (int)m_waterLayers) != 0)
+ {
+ point.y -= settings.m_swimDepth;
+ }
+ hits.Add(point);
+ }
+ }
+ }
+
+ private NavMeshTile GetNavTile(Vector3 point, AgentType agent)
+ {
+ Vector3Int tile = GetTile(point, agent);
+ return GetNavTile(tile);
+ }
+
+ private NavMeshTile GetNavTile(Vector3Int tile)
+ {
+ if (tile == m_cachedTileID)
+ {
+ return m_cachedTile;
+ }
+ if (m_tiles.TryGetValue(tile, out var value))
+ {
+ m_cachedTileID = tile;
+ m_cachedTile = value;
+ return value;
+ }
+ value = new NavMeshTile();
+ value.m_tile = tile;
+ value.m_center = GetTilePos(tile);
+ m_tiles.Add(tile, value);
+ m_cachedTileID = tile;
+ m_cachedTile = value;
+ return value;
+ }
+
+ private Vector3Int GetTile(Vector3 point, AgentType agent)
+ {
+ int x = Mathf.FloorToInt((point.x + m_tileSize / 2f) / m_tileSize);
+ int y = Mathf.FloorToInt((point.z + m_tileSize / 2f) / m_tileSize);
+ return new Vector3Int(x, y, (int)agent);
+ }
+
+ public Vector3 GetTilePos(Vector3Int id)
+ {
+ return new Vector3((float)id.x * m_tileSize, 2500f, (float)id.y * m_tileSize);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pickable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pickable.cs
new file mode 100644
index 0000000..23d83db
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Pickable.cs
@@ -0,0 +1,146 @@
+using System;
+using UnityEngine;
+
+public class Pickable : MonoBehaviour, Hoverable, Interactable
+{
+ public GameObject m_hideWhenPicked;
+
+ public GameObject m_itemPrefab;
+
+ public int m_amount = 1;
+
+ public DropTable m_extraDrops = new DropTable();
+
+ public string m_overrideName = "";
+
+ public int m_respawnTimeMinutes;
+
+ public float m_spawnOffset = 0.5f;
+
+ public EffectList m_pickEffector = new EffectList();
+
+ public bool m_pickEffectAtSpawnPoint;
+
+ public bool m_useInteractAnimation;
+
+ private ZNetView m_nview;
+
+ private bool m_picked;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ ZDO zDO = m_nview.GetZDO();
+ if (zDO != null)
+ {
+ m_nview.Register<bool>("SetPicked", RPC_SetPicked);
+ m_picked = zDO.GetBool("picked");
+ SetPicked(m_picked);
+ if (m_respawnTimeMinutes > 0)
+ {
+ InvokeRepeating("UpdateRespawn", UnityEngine.Random.Range(1f, 5f), 60f);
+ }
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (m_picked)
+ {
+ return "";
+ }
+ return Localization.instance.Localize(GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] $inventory_pickup");
+ }
+
+ public string GetHoverName()
+ {
+ if (!string.IsNullOrEmpty(m_overrideName))
+ {
+ return m_overrideName;
+ }
+ return m_itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
+ }
+
+ private void UpdateRespawn()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && m_picked)
+ {
+ long @long = m_nview.GetZDO().GetLong("picked_time", 0L);
+ DateTime dateTime = new DateTime(@long);
+ if ((ZNet.instance.GetTime() - dateTime).TotalMinutes > (double)m_respawnTimeMinutes)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetPicked", false);
+ }
+ }
+ }
+
+ private void RPC_SetPicked(long sender, bool picked)
+ {
+ SetPicked(picked);
+ }
+
+ private void SetPicked(bool picked)
+ {
+ m_picked = picked;
+ if ((bool)m_hideWhenPicked)
+ {
+ m_hideWhenPicked.SetActive(!picked);
+ }
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ if (m_respawnTimeMinutes > 0 || m_hideWhenPicked != null)
+ {
+ m_nview.GetZDO().Set("picked", m_picked);
+ if (picked && m_respawnTimeMinutes > 0)
+ {
+ DateTime time = ZNet.instance.GetTime();
+ m_nview.GetZDO().Set("picked_time", time.Ticks);
+ }
+ }
+ else if (picked)
+ {
+ m_nview.Destroy();
+ }
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (m_picked)
+ {
+ return false;
+ }
+ Vector3 pos = (m_pickEffectAtSpawnPoint ? (base.transform.position + Vector3.up * m_spawnOffset) : base.transform.position);
+ m_pickEffector.Create(pos, Quaternion.identity);
+ int num = 0;
+ for (int i = 0; i < m_amount; i++)
+ {
+ Drop(m_itemPrefab, num++, 1);
+ }
+ if (!m_extraDrops.IsEmpty())
+ {
+ foreach (ItemDrop.ItemData dropListItem in m_extraDrops.GetDropListItems())
+ {
+ Drop(dropListItem.m_dropPrefab, num++, dropListItem.m_stack);
+ }
+ }
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetPicked", true);
+ return m_useInteractAnimation;
+ }
+
+ private void Drop(GameObject prefab, int offset, int stack)
+ {
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * 0.2f;
+ Vector3 position = base.transform.position + Vector3.up * m_spawnOffset + new Vector3(vector.x, 0.5f * (float)offset, vector.y);
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ GameObject obj = UnityEngine.Object.Instantiate(prefab, position, rotation);
+ obj.GetComponent<ItemDrop>().m_itemData.m_stack = stack;
+ obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PickableItem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PickableItem.cs
new file mode 100644
index 0000000..10d4fdd
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PickableItem.cs
@@ -0,0 +1,194 @@
+using System;
+using UnityEngine;
+
+public class PickableItem : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public struct RandomItem
+ {
+ public ItemDrop m_itemPrefab;
+
+ public int m_stackMin;
+
+ public int m_stackMax;
+ }
+
+ public ItemDrop m_itemPrefab;
+
+ public int m_stack;
+
+ public RandomItem[] m_randomItemPrefabs = new RandomItem[0];
+
+ public EffectList m_pickEffector = new EffectList();
+
+ private ZNetView m_nview;
+
+ private GameObject m_instance;
+
+ private bool m_picked;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ SetupRandomPrefab();
+ m_nview.Register("Pick", RPC_Pick);
+ SetupItem(enabled: true);
+ }
+ }
+
+ private void SetupRandomPrefab()
+ {
+ if (!(m_itemPrefab == null) || m_randomItemPrefabs.Length == 0)
+ {
+ return;
+ }
+ int @int = m_nview.GetZDO().GetInt("itemPrefab");
+ if (@int == 0)
+ {
+ if (m_nview.IsOwner())
+ {
+ RandomItem randomItem = m_randomItemPrefabs[UnityEngine.Random.Range(0, m_randomItemPrefabs.Length)];
+ m_itemPrefab = randomItem.m_itemPrefab;
+ m_stack = UnityEngine.Random.Range(randomItem.m_stackMin, randomItem.m_stackMax + 1);
+ int prefabHash = ObjectDB.instance.GetPrefabHash(m_itemPrefab.gameObject);
+ m_nview.GetZDO().Set("itemPrefab", prefabHash);
+ m_nview.GetZDO().Set("itemStack", m_stack);
+ }
+ return;
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(@int);
+ if (itemPrefab == null)
+ {
+ ZLog.LogError("Failed to find saved prefab " + @int + " in PickableItem " + base.gameObject.name);
+ }
+ else
+ {
+ m_itemPrefab = itemPrefab.GetComponent<ItemDrop>();
+ m_stack = m_nview.GetZDO().GetInt("itemStack");
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (m_picked)
+ {
+ return "";
+ }
+ return Localization.instance.Localize(GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] $inventory_pickup");
+ }
+
+ public string GetHoverName()
+ {
+ if ((bool)m_itemPrefab)
+ {
+ int stackSize = GetStackSize();
+ if (stackSize > 1)
+ {
+ return m_itemPrefab.m_itemData.m_shared.m_name + " x " + stackSize;
+ }
+ return m_itemPrefab.m_itemData.m_shared.m_name;
+ }
+ return "None";
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ m_nview.InvokeRPC("Pick");
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void RPC_Pick(long sender)
+ {
+ if (m_nview.IsOwner() && !m_picked)
+ {
+ m_picked = true;
+ m_pickEffector.Create(base.transform.position, Quaternion.identity);
+ Drop();
+ m_nview.Destroy();
+ }
+ }
+
+ private void Drop()
+ {
+ Vector3 position = base.transform.position + Vector3.up * 0.2f;
+ GameObject obj = UnityEngine.Object.Instantiate(m_itemPrefab.gameObject, position, base.transform.rotation);
+ obj.GetComponent<ItemDrop>().m_itemData.m_stack = GetStackSize();
+ obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f;
+ }
+
+ private int GetStackSize()
+ {
+ return Mathf.Clamp((m_stack > 0) ? m_stack : m_itemPrefab.m_itemData.m_stack, 1, m_itemPrefab.m_itemData.m_shared.m_maxStackSize);
+ }
+
+ private GameObject GetAttachPrefab()
+ {
+ Transform transform = m_itemPrefab.transform.Find("attach");
+ if ((bool)transform)
+ {
+ return transform.gameObject;
+ }
+ return null;
+ }
+
+ private void SetupItem(bool enabled)
+ {
+ if (!enabled)
+ {
+ if ((bool)m_instance)
+ {
+ UnityEngine.Object.Destroy(m_instance);
+ m_instance = null;
+ }
+ }
+ else if (!m_instance && !(m_itemPrefab == null))
+ {
+ GameObject attachPrefab = GetAttachPrefab();
+ if (attachPrefab == null)
+ {
+ ZLog.LogWarning("Failed to get attach prefab for item " + m_itemPrefab.name);
+ return;
+ }
+ m_instance = UnityEngine.Object.Instantiate(attachPrefab, base.transform.position, base.transform.rotation, base.transform);
+ m_instance.transform.localPosition = attachPrefab.transform.localPosition;
+ m_instance.transform.localRotation = attachPrefab.transform.localRotation;
+ }
+ }
+
+ private bool DrawPrefabMesh(ItemDrop prefab)
+ {
+ if (prefab == null)
+ {
+ return false;
+ }
+ bool result = false;
+ Gizmos.color = Color.yellow;
+ MeshFilter[] componentsInChildren = prefab.gameObject.GetComponentsInChildren<MeshFilter>();
+ foreach (MeshFilter meshFilter in componentsInChildren)
+ {
+ if ((bool)meshFilter && (bool)meshFilter.sharedMesh)
+ {
+ Vector3 position = prefab.transform.position;
+ Quaternion quaternion = Quaternion.Inverse(prefab.transform.rotation);
+ Vector3 vector = meshFilter.transform.position - position;
+ Vector3 position2 = base.transform.position + base.transform.rotation * vector;
+ Quaternion quaternion2 = quaternion * meshFilter.transform.rotation;
+ Quaternion rotation = base.transform.rotation * quaternion2;
+ Gizmos.DrawMesh(meshFilter.sharedMesh, position2, rotation, meshFilter.transform.lossyScale);
+ result = true;
+ }
+ }
+ return result;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Piece.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Piece.cs
new file mode 100644
index 0000000..1ba0993
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Piece.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Piece : StaticTarget
+{
+ public enum PieceCategory
+ {
+ Misc = 0,
+ Crafting = 1,
+ Building = 2,
+ Furniture = 3,
+ Max = 4,
+ All = 100
+ }
+
+ public enum ComfortGroup
+ {
+ None,
+ Fire,
+ Bed,
+ Banner,
+ Chair
+ }
+
+ [Serializable]
+ public class Requirement
+ {
+ [Header("Resource")]
+ public ItemDrop m_resItem;
+
+ public int m_amount = 1;
+
+ [Header("Item")]
+ public int m_amountPerLevel = 1;
+
+ [Header("Piece")]
+ public bool m_recover = true;
+
+ public int GetAmount(int qualityLevel)
+ {
+ if (qualityLevel <= 1)
+ {
+ return m_amount;
+ }
+ return (qualityLevel - 1) * m_amountPerLevel;
+ }
+ }
+
+ private static int pieceRayMask = 0;
+
+ private static Collider[] pieceColliders = new Collider[2000];
+
+ [Header("Basic stuffs")]
+ public Sprite m_icon;
+
+ public string m_name = "";
+
+ public string m_description = "";
+
+ public bool m_enabled = true;
+
+ public PieceCategory m_category;
+
+ public bool m_isUpgrade;
+
+ [Header("Comfort")]
+ public int m_comfort;
+
+ public ComfortGroup m_comfortGroup;
+
+ [Header("Placement rules")]
+ public bool m_groundPiece;
+
+ public bool m_allowAltGroundPlacement;
+
+ public bool m_groundOnly;
+
+ public bool m_cultivatedGroundOnly;
+
+ public bool m_waterPiece;
+
+ public bool m_clipGround;
+
+ public bool m_clipEverything;
+
+ public bool m_noInWater;
+
+ public bool m_notOnWood;
+
+ public bool m_notOnTiltingSurface;
+
+ public bool m_inCeilingOnly;
+
+ public bool m_notOnFloor;
+
+ public bool m_noClipping;
+
+ public bool m_onlyInTeleportArea;
+
+ public bool m_allowedInDungeons;
+
+ public float m_spaceRequirement;
+
+ public bool m_repairPiece;
+
+ public bool m_canBeRemoved = true;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_onlyInBiome;
+
+ [Header("Effects")]
+ public EffectList m_placeEffect = new EffectList();
+
+ [Header("Requirements")]
+ public string m_dlc = "";
+
+ public CraftingStation m_craftingStation;
+
+ public Requirement[] m_resources = new Requirement[0];
+
+ public GameObject m_destroyedLootPrefab;
+
+ private ZNetView m_nview;
+
+ private List<KeyValuePair<Renderer, Material[]>> m_invalidPlacementMaterials;
+
+ private long m_creator;
+
+ private int m_myListIndex = -1;
+
+ private static List<Piece> m_allPieces = new List<Piece>();
+
+ private static int m_creatorHash = 0;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_allPieces.Add(this);
+ m_myListIndex = m_allPieces.Count - 1;
+ if ((bool)m_nview && m_nview.IsValid())
+ {
+ if (m_creatorHash == 0)
+ {
+ m_creatorHash = "creator".GetStableHashCode();
+ }
+ m_creator = m_nview.GetZDO().GetLong(m_creatorHash, 0L);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (m_myListIndex >= 0)
+ {
+ m_allPieces[m_myListIndex] = m_allPieces[m_allPieces.Count - 1];
+ m_allPieces[m_myListIndex].m_myListIndex = m_myListIndex;
+ m_allPieces.RemoveAt(m_allPieces.Count - 1);
+ m_myListIndex = -1;
+ }
+ }
+
+ public bool CanBeRemoved()
+ {
+ Container componentInChildren = GetComponentInChildren<Container>();
+ if (componentInChildren != null)
+ {
+ return componentInChildren.CanBeRemoved();
+ }
+ Ship componentInChildren2 = GetComponentInChildren<Ship>();
+ if (componentInChildren2 != null)
+ {
+ return componentInChildren2.CanBeRemoved();
+ }
+ return true;
+ }
+
+ public void DropResources()
+ {
+ Container container = null;
+ Requirement[] resources = m_resources;
+ foreach (Requirement requirement in resources)
+ {
+ if (requirement.m_resItem == null || !requirement.m_recover)
+ {
+ continue;
+ }
+ GameObject gameObject = requirement.m_resItem.gameObject;
+ int num = requirement.m_amount;
+ if (!IsPlacedByPlayer())
+ {
+ num = Mathf.Max(1, num / 3);
+ }
+ if ((bool)m_destroyedLootPrefab)
+ {
+ while (num > 0)
+ {
+ ItemDrop.ItemData itemData = gameObject.GetComponent<ItemDrop>().m_itemData.Clone();
+ itemData.m_dropPrefab = gameObject;
+ itemData.m_stack = Mathf.Min(num, itemData.m_shared.m_maxStackSize);
+ num -= itemData.m_stack;
+ if (container == null || !container.GetInventory().HaveEmptySlot())
+ {
+ container = UnityEngine.Object.Instantiate(m_destroyedLootPrefab, base.transform.position + Vector3.up, Quaternion.identity).GetComponent<Container>();
+ }
+ container.GetInventory().AddItem(itemData);
+ }
+ }
+ else
+ {
+ while (num > 0)
+ {
+ ItemDrop component = UnityEngine.Object.Instantiate(gameObject, base.transform.position + Vector3.up, Quaternion.identity).GetComponent<ItemDrop>();
+ component.m_itemData.m_stack = Mathf.Min(num, component.m_itemData.m_shared.m_maxStackSize);
+ num -= component.m_itemData.m_stack;
+ }
+ }
+ }
+ }
+
+ public override bool IsValidMonsterTarget()
+ {
+ return IsPlacedByPlayer();
+ }
+
+ public void SetCreator(long uid)
+ {
+ if (m_nview.IsOwner() && GetCreator() == 0L)
+ {
+ m_creator = uid;
+ m_nview.GetZDO().Set(m_creatorHash, uid);
+ }
+ }
+
+ public long GetCreator()
+ {
+ return m_creator;
+ }
+
+ public bool IsCreator()
+ {
+ long creator = GetCreator();
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ return creator == playerID;
+ }
+
+ public bool IsPlacedByPlayer()
+ {
+ return GetCreator() != 0;
+ }
+
+ public void SetInvalidPlacementHeightlight(bool enabled)
+ {
+ if ((enabled && m_invalidPlacementMaterials != null) || (!enabled && m_invalidPlacementMaterials == null))
+ {
+ return;
+ }
+ Renderer[] componentsInChildren = GetComponentsInChildren<Renderer>();
+ if (enabled)
+ {
+ m_invalidPlacementMaterials = new List<KeyValuePair<Renderer, Material[]>>();
+ Renderer[] array = componentsInChildren;
+ foreach (Renderer renderer in array)
+ {
+ Material[] sharedMaterials = renderer.sharedMaterials;
+ m_invalidPlacementMaterials.Add(new KeyValuePair<Renderer, Material[]>(renderer, sharedMaterials));
+ }
+ array = componentsInChildren;
+ for (int i = 0; i < array.Length; i++)
+ {
+ Material[] materials = array[i].materials;
+ foreach (Material material in materials)
+ {
+ if (material.HasProperty("_EmissionColor"))
+ {
+ material.SetColor("_EmissionColor", Color.red * 0.7f);
+ }
+ material.color = Color.red;
+ }
+ }
+ return;
+ }
+ foreach (KeyValuePair<Renderer, Material[]> invalidPlacementMaterial in m_invalidPlacementMaterials)
+ {
+ if ((bool)invalidPlacementMaterial.Key)
+ {
+ invalidPlacementMaterial.Key.materials = invalidPlacementMaterial.Value;
+ }
+ }
+ m_invalidPlacementMaterials = null;
+ }
+
+ public static void GetSnapPoints(Vector3 point, float radius, List<Transform> points, List<Piece> pieces)
+ {
+ if (pieceRayMask == 0)
+ {
+ pieceRayMask = LayerMask.GetMask("piece", "piece_nonsolid");
+ }
+ int num = Physics.OverlapSphereNonAlloc(point, radius, pieceColliders, pieceRayMask);
+ for (int i = 0; i < num; i++)
+ {
+ Piece componentInParent = pieceColliders[i].GetComponentInParent<Piece>();
+ if (componentInParent != null)
+ {
+ componentInParent.GetSnapPoints(points);
+ pieces.Add(componentInParent);
+ }
+ }
+ }
+
+ public static void GetAllPiecesInRadius(Vector3 p, float radius, List<Piece> pieces)
+ {
+ foreach (Piece allPiece in m_allPieces)
+ {
+ if (Vector3.Distance(p, allPiece.transform.position) < radius)
+ {
+ pieces.Add(allPiece);
+ }
+ }
+ }
+
+ public void GetSnapPoints(List<Transform> points)
+ {
+ for (int i = 0; i < base.transform.childCount; i++)
+ {
+ Transform child = base.transform.GetChild(i);
+ if (child.CompareTag("snappoint"))
+ {
+ points.Add(child);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PieceTable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PieceTable.cs
new file mode 100644
index 0000000..17944e2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PieceTable.cs
@@ -0,0 +1,224 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PieceTable : MonoBehaviour
+{
+ public const int m_gridWidth = 10;
+
+ public const int m_gridHeight = 5;
+
+ public List<GameObject> m_pieces = new List<GameObject>();
+
+ public bool m_useCategories = true;
+
+ public bool m_canRemovePieces = true;
+
+ [NonSerialized]
+ private List<List<Piece>> m_availablePieces = new List<List<Piece>>();
+
+ [NonSerialized]
+ public Piece.PieceCategory m_selectedCategory;
+
+ [NonSerialized]
+ public Vector2Int[] m_selectedPiece = new Vector2Int[5];
+
+ public void UpdateAvailable(HashSet<string> knownRecipies, Player player, bool hideUnavailable, bool noPlacementCost)
+ {
+ if (m_availablePieces.Count == 0)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ m_availablePieces.Add(new List<Piece>());
+ }
+ }
+ foreach (List<Piece> availablePiece in m_availablePieces)
+ {
+ availablePiece.Clear();
+ }
+ foreach (GameObject piece in m_pieces)
+ {
+ Piece component = piece.GetComponent<Piece>();
+ if (!noPlacementCost && (!knownRecipies.Contains(component.m_name) || !component.m_enabled || (hideUnavailable && !player.HaveRequirements(component, Player.RequirementMode.CanAlmostBuild))))
+ {
+ continue;
+ }
+ if (component.m_category == Piece.PieceCategory.All)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ m_availablePieces[j].Add(component);
+ }
+ }
+ else
+ {
+ m_availablePieces[(int)component.m_category].Add(component);
+ }
+ }
+ }
+
+ public GameObject GetSelectedPrefab()
+ {
+ Piece selectedPiece = GetSelectedPiece();
+ if ((bool)selectedPiece)
+ {
+ return selectedPiece.gameObject;
+ }
+ return null;
+ }
+
+ public Piece GetPiece(int category, Vector2Int p)
+ {
+ if (m_availablePieces[category].Count == 0)
+ {
+ return null;
+ }
+ int num = p.y * 10 + p.x;
+ if (num < 0 || num >= m_availablePieces[category].Count)
+ {
+ return null;
+ }
+ return m_availablePieces[category][num];
+ }
+
+ public Piece GetPiece(Vector2Int p)
+ {
+ return GetPiece((int)m_selectedCategory, p);
+ }
+
+ public bool IsPieceAvailable(Piece piece)
+ {
+ foreach (Piece item in m_availablePieces[(int)m_selectedCategory])
+ {
+ if (item == piece)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Piece GetSelectedPiece()
+ {
+ Vector2Int selectedIndex = GetSelectedIndex();
+ return GetPiece((int)m_selectedCategory, selectedIndex);
+ }
+
+ public int GetAvailablePiecesInCategory(Piece.PieceCategory cat)
+ {
+ return m_availablePieces[(int)cat].Count;
+ }
+
+ public List<Piece> GetPiecesInSelectedCategory()
+ {
+ return m_availablePieces[(int)m_selectedCategory];
+ }
+
+ public int GetAvailablePiecesInSelectedCategory()
+ {
+ return GetAvailablePiecesInCategory(m_selectedCategory);
+ }
+
+ public Vector2Int GetSelectedIndex()
+ {
+ return m_selectedPiece[(int)m_selectedCategory];
+ }
+
+ public void SetSelected(Vector2Int p)
+ {
+ m_selectedPiece[(int)m_selectedCategory] = p;
+ }
+
+ public void LeftPiece()
+ {
+ if (m_availablePieces[(int)m_selectedCategory].Count > 1)
+ {
+ Vector2Int vector2Int = m_selectedPiece[(int)m_selectedCategory];
+ int x = vector2Int.x - 1;
+ vector2Int.x = x;
+ if (vector2Int.x < 0)
+ {
+ vector2Int.x = 9;
+ }
+ m_selectedPiece[(int)m_selectedCategory] = vector2Int;
+ }
+ }
+
+ public void RightPiece()
+ {
+ if (m_availablePieces[(int)m_selectedCategory].Count > 1)
+ {
+ Vector2Int vector2Int = m_selectedPiece[(int)m_selectedCategory];
+ int x = vector2Int.x + 1;
+ vector2Int.x = x;
+ if (vector2Int.x >= 10)
+ {
+ vector2Int.x = 0;
+ }
+ m_selectedPiece[(int)m_selectedCategory] = vector2Int;
+ }
+ }
+
+ public void DownPiece()
+ {
+ if (m_availablePieces[(int)m_selectedCategory].Count > 1)
+ {
+ Vector2Int vector2Int = m_selectedPiece[(int)m_selectedCategory];
+ int y = vector2Int.y + 1;
+ vector2Int.y = y;
+ if (vector2Int.y >= 5)
+ {
+ vector2Int.y = 0;
+ }
+ m_selectedPiece[(int)m_selectedCategory] = vector2Int;
+ }
+ }
+
+ public void UpPiece()
+ {
+ if (m_availablePieces[(int)m_selectedCategory].Count > 1)
+ {
+ Vector2Int vector2Int = m_selectedPiece[(int)m_selectedCategory];
+ int y = vector2Int.y - 1;
+ vector2Int.y = y;
+ if (vector2Int.y < 0)
+ {
+ vector2Int.y = 4;
+ }
+ m_selectedPiece[(int)m_selectedCategory] = vector2Int;
+ }
+ }
+
+ public void NextCategory()
+ {
+ if (m_useCategories)
+ {
+ m_selectedCategory++;
+ if (m_selectedCategory == Piece.PieceCategory.Max)
+ {
+ m_selectedCategory = Piece.PieceCategory.Misc;
+ }
+ }
+ }
+
+ public void PrevCategory()
+ {
+ if (m_useCategories)
+ {
+ m_selectedCategory--;
+ if (m_selectedCategory < Piece.PieceCategory.Misc)
+ {
+ m_selectedCategory = Piece.PieceCategory.Furniture;
+ }
+ }
+ }
+
+ public void SetCategory(int index)
+ {
+ if (m_useCategories)
+ {
+ m_selectedCategory = (Piece.PieceCategory)index;
+ m_selectedCategory = (Piece.PieceCategory)Mathf.Clamp((int)m_selectedCategory, 0, 3);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Plant.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Plant.cs
new file mode 100644
index 0000000..bc11954
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Plant.cs
@@ -0,0 +1,243 @@
+using System;
+using UnityEngine;
+
+public class Plant : SlowUpdate, Hoverable
+{
+ private enum Status
+ {
+ Healthy,
+ NoSun,
+ NoSpace,
+ WrongBiome,
+ NotCultivated
+ }
+
+ public string m_name = "Plant";
+
+ public float m_growTime = 10f;
+
+ public float m_growTimeMax = 2000f;
+
+ public GameObject[] m_grownPrefabs = new GameObject[0];
+
+ public float m_minScale = 1f;
+
+ public float m_maxScale = 1f;
+
+ public float m_growRadius = 1f;
+
+ public bool m_needCultivatedGround;
+
+ public bool m_destroyIfCantGrow;
+
+ [SerializeField]
+ private GameObject m_healthy;
+
+ [SerializeField]
+ private GameObject m_unhealthy;
+
+ [SerializeField]
+ private GameObject m_healthyGrown;
+
+ [SerializeField]
+ private GameObject m_unhealthyGrown;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ public EffectList m_growEffect = new EffectList();
+
+ private Status m_status;
+
+ private ZNetView m_nview;
+
+ private float m_updateTime;
+
+ private float m_spawnTime;
+
+ private static int m_spaceMask;
+
+ private static int m_roofMask;
+
+ public override void Awake()
+ {
+ base.Awake();
+ m_nview = base.gameObject.GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong("plantTime", 0L) == 0L)
+ {
+ m_nview.GetZDO().Set("plantTime", ZNet.instance.GetTime().Ticks);
+ }
+ m_spawnTime = Time.time;
+ }
+ }
+
+ public string GetHoverText()
+ {
+ return m_status switch
+ {
+ Status.Healthy => Localization.instance.Localize(m_name + " ( $piece_plant_healthy )"),
+ Status.NoSpace => Localization.instance.Localize(m_name + " ( $piece_plant_nospace )"),
+ Status.NoSun => Localization.instance.Localize(m_name + " ( $piece_plant_nosun )"),
+ Status.WrongBiome => Localization.instance.Localize(m_name + " ( $piece_plant_wrongbiome )"),
+ Status.NotCultivated => Localization.instance.Localize(m_name + " ( $piece_plant_notcultivated )"),
+ _ => "",
+ };
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ private double TimeSincePlanted()
+ {
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("plantTime", ZNet.instance.GetTime().Ticks));
+ return (ZNet.instance.GetTime() - dateTime).TotalSeconds;
+ }
+
+ public override void SUpdate()
+ {
+ if (m_nview.IsValid() && !(Time.time - m_updateTime < 10f))
+ {
+ m_updateTime = Time.time;
+ double num = TimeSincePlanted();
+ UpdateHealth(num);
+ float growTime = GetGrowTime();
+ if ((bool)m_healthyGrown)
+ {
+ bool flag = num > (double)(growTime * 0.5f);
+ m_healthy.SetActive(!flag && m_status == Status.Healthy);
+ m_unhealthy.SetActive(!flag && m_status != Status.Healthy);
+ m_healthyGrown.SetActive(flag && m_status == Status.Healthy);
+ m_unhealthyGrown.SetActive(flag && m_status != Status.Healthy);
+ }
+ else
+ {
+ m_healthy.SetActive(m_status == Status.Healthy);
+ m_unhealthy.SetActive(m_status != Status.Healthy);
+ }
+ if (m_nview.IsOwner() && Time.time - m_spawnTime > 10f && num > (double)growTime)
+ {
+ Grow();
+ }
+ }
+ }
+
+ private float GetGrowTime()
+ {
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState((int)(m_nview.GetZDO().m_uid.id + m_nview.GetZDO().m_uid.userID));
+ float value = UnityEngine.Random.value;
+ UnityEngine.Random.state = state;
+ return Mathf.Lerp(m_growTime, m_growTimeMax, value);
+ }
+
+ private void Grow()
+ {
+ if (m_status != 0)
+ {
+ if (m_destroyIfCantGrow)
+ {
+ Destroy();
+ }
+ return;
+ }
+ GameObject original = m_grownPrefabs[UnityEngine.Random.Range(0, m_grownPrefabs.Length)];
+ Quaternion quaternion = Quaternion.Euler(0f, UnityEngine.Random.Range(0f, 360f), 0f);
+ GameObject obj = UnityEngine.Object.Instantiate(original, base.transform.position, quaternion);
+ ZNetView component = obj.GetComponent<ZNetView>();
+ float num = UnityEngine.Random.Range(m_minScale, m_maxScale);
+ component.SetLocalScale(new Vector3(num, num, num));
+ TreeBase component2 = obj.GetComponent<TreeBase>();
+ if ((bool)component2)
+ {
+ component2.Grow();
+ }
+ m_nview.Destroy();
+ m_growEffect.Create(base.transform.position, quaternion, null, num);
+ }
+
+ private void UpdateHealth(double timeSincePlanted)
+ {
+ if (timeSincePlanted < 10.0)
+ {
+ m_status = Status.Healthy;
+ return;
+ }
+ Heightmap heightmap = Heightmap.FindHeightmap(base.transform.position);
+ if ((bool)heightmap)
+ {
+ if ((heightmap.GetBiome(base.transform.position) & m_biome) == 0)
+ {
+ m_status = Status.WrongBiome;
+ return;
+ }
+ if (m_needCultivatedGround && !heightmap.IsCultivated(base.transform.position))
+ {
+ m_status = Status.NotCultivated;
+ return;
+ }
+ }
+ if (HaveRoof())
+ {
+ m_status = Status.NoSun;
+ }
+ else if (!HaveGrowSpace())
+ {
+ m_status = Status.NoSpace;
+ }
+ else
+ {
+ m_status = Status.Healthy;
+ }
+ }
+
+ private void Destroy()
+ {
+ IDestructible component = GetComponent<IDestructible>();
+ if (component != null)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 9999f;
+ component.Damage(hitData);
+ }
+ }
+
+ private bool HaveRoof()
+ {
+ if (m_roofMask == 0)
+ {
+ m_roofMask = LayerMask.GetMask("Default", "static_solid", "piece");
+ }
+ if (Physics.Raycast(base.transform.position, Vector3.up, 100f, m_roofMask))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private bool HaveGrowSpace()
+ {
+ if (m_spaceMask == 0)
+ {
+ m_spaceMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid");
+ }
+ Collider[] array = Physics.OverlapSphere(base.transform.position, m_growRadius, m_spaceMask);
+ for (int i = 0; i < array.Length; i++)
+ {
+ Plant component = array[i].GetComponent<Plant>();
+ if (!component || (!(component == this) && component.GetStatus() == Status.Healthy))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Status GetStatus()
+ {
+ return m_status;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Player.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Player.cs
new file mode 100644
index 0000000..da847cc
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Player.cs
@@ -0,0 +1,4732 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.Rendering;
+
+public class Player : Humanoid
+{
+ public enum RequirementMode
+ {
+ CanBuild,
+ IsKnown,
+ CanAlmostBuild
+ }
+
+ public class Food
+ {
+ public string m_name = "";
+
+ public ItemDrop.ItemData m_item;
+
+ public float m_health;
+
+ public float m_stamina;
+
+ public bool CanEatAgain()
+ {
+ return m_health < m_item.m_shared.m_food / 2f;
+ }
+ }
+
+ public class EquipQueueData
+ {
+ public ItemDrop.ItemData m_item;
+
+ public bool m_equip = true;
+
+ public float m_time;
+
+ public float m_duration;
+ }
+
+ private enum PlacementStatus
+ {
+ Valid,
+ Invalid,
+ BlockedbyPlayer,
+ NoBuildZone,
+ PrivateZone,
+ MoreSpace,
+ NoTeleportArea,
+ ExtensionMissingStation,
+ WrongBiome,
+ NeedCultivated,
+ NotInDungeon
+ }
+
+ private float m_rotatePieceTimer;
+
+ private float m_baseValueUpdatetimer;
+
+ private const int dataVersion = 24;
+
+ private float m_equipQueuePause;
+
+ public static Player m_localPlayer = null;
+
+ private static List<Player> m_players = new List<Player>();
+
+ public static bool m_debugMode = false;
+
+ [Header("Player")]
+ public float m_maxPlaceDistance = 5f;
+
+ public float m_maxInteractDistance = 5f;
+
+ public float m_scrollSens = 4f;
+
+ public float m_staminaRegen = 5f;
+
+ public float m_staminaRegenTimeMultiplier = 1f;
+
+ public float m_staminaRegenDelay = 1f;
+
+ public float m_runStaminaDrain = 10f;
+
+ public float m_sneakStaminaDrain = 5f;
+
+ public float m_swimStaminaDrainMinSkill = 5f;
+
+ public float m_swimStaminaDrainMaxSkill = 2f;
+
+ public float m_dodgeStaminaUsage = 10f;
+
+ public float m_weightStaminaFactor = 0.1f;
+
+ public float m_autoPickupRange = 2f;
+
+ public float m_maxCarryWeight = 300f;
+
+ public float m_encumberedStaminaDrain = 10f;
+
+ public float m_hardDeathCooldown = 10f;
+
+ public float m_baseCameraShake = 4f;
+
+ public EffectList m_spawnEffects = new EffectList();
+
+ public EffectList m_removeEffects = new EffectList();
+
+ public EffectList m_dodgeEffects = new EffectList();
+
+ public EffectList m_autopickupEffects = new EffectList();
+
+ public EffectList m_skillLevelupEffects = new EffectList();
+
+ public EffectList m_equipStartEffects = new EffectList();
+
+ public GameObject m_placeMarker;
+
+ public GameObject m_tombstone;
+
+ public GameObject m_valkyrie;
+
+ public Sprite m_textIcon;
+
+ private Skills m_skills;
+
+ private PieceTable m_buildPieces;
+
+ private bool m_noPlacementCost;
+
+ private bool m_hideUnavailable;
+
+ private HashSet<string> m_knownRecipes = new HashSet<string>();
+
+ private Dictionary<string, int> m_knownStations = new Dictionary<string, int>();
+
+ private HashSet<string> m_knownMaterial = new HashSet<string>();
+
+ private HashSet<string> m_shownTutorials = new HashSet<string>();
+
+ private HashSet<string> m_uniques = new HashSet<string>();
+
+ private HashSet<string> m_trophies = new HashSet<string>();
+
+ private HashSet<Heightmap.Biome> m_knownBiome = new HashSet<Heightmap.Biome>();
+
+ private Dictionary<string, string> m_knownTexts = new Dictionary<string, string>();
+
+ private float m_stationDiscoverTimer;
+
+ private bool m_debugFly;
+
+ private bool m_godMode;
+
+ private bool m_ghostMode;
+
+ private float m_lookPitch;
+
+ private const float m_baseHP = 25f;
+
+ private const float m_baseStamina = 75f;
+
+ private const int m_maxFoods = 3;
+
+ private const float m_foodDrainPerSec = 0.1f;
+
+ private float m_foodUpdateTimer;
+
+ private float m_foodRegenTimer;
+
+ private List<Food> m_foods = new List<Food>();
+
+ private float m_stamina = 100f;
+
+ private float m_maxStamina = 100f;
+
+ private float m_staminaRegenTimer;
+
+ private string m_guardianPower = "";
+
+ private float m_guardianPowerCooldown;
+
+ private StatusEffect m_guardianSE;
+
+ private GameObject m_placementMarkerInstance;
+
+ private GameObject m_placementGhost;
+
+ private PlacementStatus m_placementStatus = PlacementStatus.Invalid;
+
+ private int m_placeRotation;
+
+ private int m_placeRayMask;
+
+ private int m_placeGroundRayMask;
+
+ private int m_placeWaterRayMask;
+
+ private int m_removeRayMask;
+
+ private int m_interactMask;
+
+ private int m_autoPickupMask;
+
+ private List<EquipQueueData> m_equipQueue = new List<EquipQueueData>();
+
+ private GameObject m_hovering;
+
+ private Character m_hoveringCreature;
+
+ private float m_lastHoverInteractTime;
+
+ private bool m_pvp;
+
+ private float m_updateCoverTimer;
+
+ private float m_coverPercentage;
+
+ private bool m_underRoof = true;
+
+ private float m_nearFireTimer;
+
+ private bool m_isLoading;
+
+ private float m_queuedAttackTimer;
+
+ private float m_queuedSecondAttackTimer;
+
+ private float m_queuedDodgeTimer;
+
+ private Vector3 m_queuedDodgeDir = Vector3.zero;
+
+ private bool m_inDodge;
+
+ private bool m_dodgeInvincible;
+
+ private CraftingStation m_currentStation;
+
+ private Ragdoll m_ragdoll;
+
+ private Piece m_hoveringPiece;
+
+ private string m_emoteState = "";
+
+ private int m_emoteID;
+
+ private bool m_intro;
+
+ private bool m_firstSpawn = true;
+
+ private bool m_crouchToggled;
+
+ private bool m_autoRun;
+
+ private bool m_safeInHome;
+
+ private ShipControlls m_shipControl;
+
+ private bool m_attached;
+
+ private string m_attachAnimation = "";
+
+ private bool m_sleeping;
+
+ private Transform m_attachPoint;
+
+ private Vector3 m_detachOffset = Vector3.zero;
+
+ private int m_modelIndex;
+
+ private Vector3 m_skinColor = Vector3.one;
+
+ private Vector3 m_hairColor = Vector3.one;
+
+ private bool m_teleporting;
+
+ private bool m_distantTeleport;
+
+ private float m_teleportTimer;
+
+ private float m_teleportCooldown;
+
+ private Vector3 m_teleportFromPos;
+
+ private Quaternion m_teleportFromRot;
+
+ private Vector3 m_teleportTargetPos;
+
+ private Quaternion m_teleportTargetRot;
+
+ private Heightmap.Biome m_currentBiome;
+
+ private float m_biomeTimer;
+
+ private int m_baseValue;
+
+ private int m_comfortLevel;
+
+ private float m_drownDamageTimer;
+
+ private float m_timeSinceTargeted;
+
+ private float m_timeSinceSensed;
+
+ private float m_stealthFactorUpdateTimer;
+
+ private float m_stealthFactor;
+
+ private float m_stealthFactorTarget;
+
+ private Vector3 m_lastStealthPosition = Vector3.zero;
+
+ private float m_wakeupTimer = -1f;
+
+ private float m_timeSinceDeath = 999999f;
+
+ private float m_runSkillImproveTimer;
+
+ private float m_swimSkillImproveTimer;
+
+ private float m_sneakSkillImproveTimer;
+
+ private float m_equipmentMovementModifier;
+
+ private static int crouching = 0;
+
+ protected static int m_attackMask = 0;
+
+ protected static int m_animatorTagDodge = Animator.StringToHash("dodge");
+
+ protected static int m_animatorTagCutscene = Animator.StringToHash("cutscene");
+
+ protected static int m_animatorTagCrouch = Animator.StringToHash("crouch");
+
+ protected static int m_animatorTagMinorAction = Animator.StringToHash("minoraction");
+
+ protected static int m_animatorTagEmote = Animator.StringToHash("emote");
+
+ private List<PieceTable> m_tempOwnedPieceTables = new List<PieceTable>();
+
+ private List<Transform> m_tempSnapPoints1 = new List<Transform>();
+
+ private List<Transform> m_tempSnapPoints2 = new List<Transform>();
+
+ private List<Piece> m_tempPieces = new List<Piece>();
+
+ protected override void Awake()
+ {
+ base.Awake();
+ m_players.Add(this);
+ m_skills = GetComponent<Skills>();
+ SetupAwake();
+ if (m_nview.GetZDO() == null)
+ {
+ return;
+ }
+ m_placeRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle");
+ m_placeWaterRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "Water", "vehicle");
+ m_removeRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle");
+ m_interactMask = LayerMask.GetMask("item", "piece", "piece_nonsolid", "Default", "static_solid", "Default_small", "character", "character_net", "terrain", "vehicle");
+ m_autoPickupMask = LayerMask.GetMask("item");
+ Inventory inventory = m_inventory;
+ inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
+ if (m_attackMask == 0)
+ {
+ m_attackMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle");
+ }
+ if (crouching == 0)
+ {
+ crouching = ZSyncAnimation.GetHash("crouching");
+ }
+ m_nview.Register("OnDeath", RPC_OnDeath);
+ if (m_nview.IsOwner())
+ {
+ m_nview.Register<int, string, int>("Message", RPC_Message);
+ m_nview.Register<bool, bool>("OnTargeted", RPC_OnTargeted);
+ m_nview.Register<float>("UseStamina", RPC_UseStamina);
+ if ((bool)MusicMan.instance)
+ {
+ MusicMan.instance.TriggerMusic("Wakeup");
+ }
+ UpdateKnownRecipesList();
+ UpdateAvailablePiecesList();
+ SetupPlacementGhost();
+ }
+ }
+
+ public void SetLocalPlayer()
+ {
+ if (!(m_localPlayer == this))
+ {
+ m_localPlayer = this;
+ ZNet.instance.SetReferencePosition(base.transform.position);
+ EnvMan.instance.SetForceEnvironment("");
+ }
+ }
+
+ public void SetPlayerID(long playerID, string name)
+ {
+ if (m_nview.GetZDO() != null && GetPlayerID() == 0L)
+ {
+ m_nview.GetZDO().Set("playerID", playerID);
+ m_nview.GetZDO().Set("playerName", name);
+ }
+ }
+
+ public long GetPlayerID()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.GetZDO().GetLong("playerID", 0L);
+ }
+ return 0L;
+ }
+
+ public string GetPlayerName()
+ {
+ if (m_nview.IsValid())
+ {
+ return m_nview.GetZDO().GetString("playerName", "...");
+ }
+ return "";
+ }
+
+ public override string GetHoverText()
+ {
+ return "";
+ }
+
+ public override string GetHoverName()
+ {
+ return GetPlayerName();
+ }
+
+ protected override void Start()
+ {
+ base.Start();
+ m_nview.GetZDO();
+ }
+
+ public override void OnDestroy()
+ {
+ ZDO zDO = m_nview.GetZDO();
+ if (zDO != null && ZNet.instance != null)
+ {
+ ZLog.LogWarning(string.Concat("Player destroyed sec:", zDO.GetSector(), " pos:", base.transform.position, " zdopos:", zDO.GetPosition(), " ref ", ZNet.instance.GetReferencePosition()));
+ }
+ if ((bool)m_placementGhost)
+ {
+ UnityEngine.Object.Destroy(m_placementGhost);
+ m_placementGhost = null;
+ }
+ base.OnDestroy();
+ m_players.Remove(this);
+ if (m_localPlayer == this)
+ {
+ ZLog.LogWarning("Local player destroyed");
+ m_localPlayer = null;
+ }
+ }
+
+ protected override void FixedUpdate()
+ {
+ base.FixedUpdate();
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ UpdateAwake(fixedDeltaTime);
+ if (m_nview.GetZDO() == null)
+ {
+ return;
+ }
+ UpdateTargeted(fixedDeltaTime);
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ if (m_localPlayer != this)
+ {
+ ZLog.Log("Destroying old local player");
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ else if (!IsDead())
+ {
+ UpdateEquipQueue(fixedDeltaTime);
+ PlayerAttackInput(fixedDeltaTime);
+ UpdateAttach();
+ UpdateShipControl(fixedDeltaTime);
+ UpdateCrouch(fixedDeltaTime);
+ UpdateDodge(fixedDeltaTime);
+ UpdateCover(fixedDeltaTime);
+ UpdateStations(fixedDeltaTime);
+ UpdateGuardianPower(fixedDeltaTime);
+ UpdateBaseValue(fixedDeltaTime);
+ UpdateStats(fixedDeltaTime);
+ UpdateTeleport(fixedDeltaTime);
+ AutoPickup(fixedDeltaTime);
+ EdgeOfWorldKill(fixedDeltaTime);
+ UpdateBiome(fixedDeltaTime);
+ UpdateStealth(fixedDeltaTime);
+ if ((bool)GameCamera.instance && Vector3.Distance(GameCamera.instance.transform.position, base.transform.position) < 2f)
+ {
+ SetVisible(visible: false);
+ }
+ AudioMan.instance.SetIndoor(InShelter());
+ }
+ }
+
+ private void Update()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return;
+ }
+ bool flag = TakeInput();
+ UpdateHover();
+ if (flag)
+ {
+ if (m_debugMode && Console.instance.IsCheatsEnabled())
+ {
+ if (Input.GetKeyDown(KeyCode.Z))
+ {
+ m_debugFly = !m_debugFly;
+ m_nview.GetZDO().Set("DebugFly", m_debugFly);
+ Message(MessageHud.MessageType.TopLeft, "Debug fly:" + m_debugFly);
+ }
+ if (Input.GetKeyDown(KeyCode.B))
+ {
+ m_noPlacementCost = !m_noPlacementCost;
+ Message(MessageHud.MessageType.TopLeft, "No placement cost:" + m_noPlacementCost);
+ UpdateAvailablePiecesList();
+ }
+ if (Input.GetKeyDown(KeyCode.K))
+ {
+ int num = 0;
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (!allCharacter.IsPlayer())
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 99999f;
+ allCharacter.Damage(hitData);
+ num++;
+ }
+ }
+ Message(MessageHud.MessageType.TopLeft, "Killing all the monsters:" + num);
+ }
+ }
+ if (ZInput.GetButtonDown("Use") || ZInput.GetButtonDown("JoyUse"))
+ {
+ if ((bool)m_hovering)
+ {
+ Interact(m_hovering, hold: false);
+ }
+ else if ((bool)m_shipControl)
+ {
+ StopShipControl();
+ }
+ }
+ else if ((ZInput.GetButton("Use") || ZInput.GetButton("JoyUse")) && (bool)m_hovering)
+ {
+ Interact(m_hovering, hold: true);
+ }
+ if (ZInput.GetButtonDown("Hide") || ZInput.GetButtonDown("JoyHide"))
+ {
+ if (GetRightItem() != null || GetLeftItem() != null)
+ {
+ if (!InAttack())
+ {
+ HideHandItems();
+ }
+ }
+ else if (!IsSwiming() || IsOnGround())
+ {
+ ShowHandItems();
+ }
+ }
+ if (ZInput.GetButtonDown("ToggleWalk"))
+ {
+ SetWalk(!GetWalk());
+ if (GetWalk())
+ {
+ Message(MessageHud.MessageType.TopLeft, "$msg_walk 1");
+ }
+ else
+ {
+ Message(MessageHud.MessageType.TopLeft, "$msg_walk 0");
+ }
+ }
+ if (ZInput.GetButtonDown("Sit") || (!InPlaceMode() && ZInput.GetButtonDown("JoySit")))
+ {
+ if (InEmote() && IsSitting())
+ {
+ StopEmote();
+ }
+ else
+ {
+ StartEmote("sit", oneshot: false);
+ }
+ }
+ if (ZInput.GetButtonDown("GPower") || ZInput.GetButtonDown("JoyGPower"))
+ {
+ StartGuardianPower();
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha1))
+ {
+ UseHotbarItem(1);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha2))
+ {
+ UseHotbarItem(2);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha3))
+ {
+ UseHotbarItem(3);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha4))
+ {
+ UseHotbarItem(4);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha5))
+ {
+ UseHotbarItem(5);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha6))
+ {
+ UseHotbarItem(6);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha7))
+ {
+ UseHotbarItem(7);
+ }
+ if (Input.GetKeyDown(KeyCode.Alpha8))
+ {
+ UseHotbarItem(8);
+ }
+ }
+ UpdatePlacement(flag, Time.deltaTime);
+ }
+
+ private void UpdatePlacement(bool takeInput, float dt)
+ {
+ UpdateWearNTearHover();
+ if (InPlaceMode())
+ {
+ if (!takeInput)
+ {
+ return;
+ }
+ UpdateBuildGuiInput();
+ if (Hud.IsPieceSelectionVisible())
+ {
+ return;
+ }
+ ItemDrop.ItemData rightItem = GetRightItem();
+ if ((ZInput.GetButtonDown("Remove") || ZInput.GetButtonDown("JoyRemove")) && rightItem.m_shared.m_buildPieces.m_canRemovePieces)
+ {
+ if (HaveStamina(rightItem.m_shared.m_attack.m_attackStamina))
+ {
+ if (RemovePiece())
+ {
+ AddNoise(50f);
+ UseStamina(rightItem.m_shared.m_attack.m_attackStamina);
+ if (rightItem.m_shared.m_useDurability)
+ {
+ rightItem.m_durability -= rightItem.m_shared.m_useDurabilityDrain;
+ }
+ }
+ }
+ else
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ }
+ if (ZInput.GetButtonDown("Attack") || ZInput.GetButtonDown("JoyPlace"))
+ {
+ Piece selectedPiece = m_buildPieces.GetSelectedPiece();
+ if (selectedPiece != null)
+ {
+ if (HaveStamina(rightItem.m_shared.m_attack.m_attackStamina))
+ {
+ if (selectedPiece.m_repairPiece)
+ {
+ Repair(rightItem, selectedPiece);
+ }
+ else if (m_placementGhost != null)
+ {
+ if (m_noPlacementCost || HaveRequirements(selectedPiece, RequirementMode.CanBuild))
+ {
+ if (PlacePiece(selectedPiece))
+ {
+ ConsumeResources(selectedPiece.m_resources, 0);
+ UseStamina(rightItem.m_shared.m_attack.m_attackStamina);
+ if (rightItem.m_shared.m_useDurability)
+ {
+ rightItem.m_durability -= rightItem.m_shared.m_useDurabilityDrain;
+ }
+ }
+ }
+ else
+ {
+ Message(MessageHud.MessageType.Center, "$msg_missingrequirement");
+ }
+ }
+ }
+ else
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ }
+ }
+ if (Input.GetAxis("Mouse ScrollWheel") < 0f)
+ {
+ m_placeRotation--;
+ }
+ if (Input.GetAxis("Mouse ScrollWheel") > 0f)
+ {
+ m_placeRotation++;
+ }
+ float joyRightStickX = ZInput.GetJoyRightStickX();
+ if (ZInput.GetButton("JoyRotate") && Mathf.Abs(joyRightStickX) > 0.5f)
+ {
+ if (m_rotatePieceTimer == 0f)
+ {
+ if (joyRightStickX < 0f)
+ {
+ m_placeRotation++;
+ }
+ else
+ {
+ m_placeRotation--;
+ }
+ }
+ else if (m_rotatePieceTimer > 0.25f)
+ {
+ if (joyRightStickX < 0f)
+ {
+ m_placeRotation++;
+ }
+ else
+ {
+ m_placeRotation--;
+ }
+ m_rotatePieceTimer = 0.17f;
+ }
+ m_rotatePieceTimer += dt;
+ }
+ else
+ {
+ m_rotatePieceTimer = 0f;
+ }
+ }
+ else if ((bool)m_placementGhost)
+ {
+ m_placementGhost.SetActive(value: false);
+ }
+ }
+
+ private void UpdateBuildGuiInput()
+ {
+ if (Hud.instance.IsQuickPieceSelectEnabled())
+ {
+ if (!Hud.IsPieceSelectionVisible() && ZInput.GetButtonDown("BuildMenu"))
+ {
+ Hud.instance.TogglePieceSelection();
+ }
+ }
+ else if (ZInput.GetButtonDown("BuildMenu"))
+ {
+ Hud.instance.TogglePieceSelection();
+ }
+ if (ZInput.GetButtonDown("JoyUse"))
+ {
+ Hud.instance.TogglePieceSelection();
+ }
+ if (Hud.IsPieceSelectionVisible())
+ {
+ if (Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("JoyButtonB"))
+ {
+ Hud.HidePieceSelection();
+ }
+ if (ZInput.GetButtonDown("JoyTabLeft") || ZInput.GetButtonDown("BuildPrev") || Input.GetAxis("Mouse ScrollWheel") > 0f)
+ {
+ m_buildPieces.PrevCategory();
+ UpdateAvailablePiecesList();
+ }
+ if (ZInput.GetButtonDown("JoyTabRight") || ZInput.GetButtonDown("BuildNext") || Input.GetAxis("Mouse ScrollWheel") < 0f)
+ {
+ m_buildPieces.NextCategory();
+ UpdateAvailablePiecesList();
+ }
+ if (ZInput.GetButtonDown("JoyLStickLeft"))
+ {
+ m_buildPieces.LeftPiece();
+ SetupPlacementGhost();
+ }
+ if (ZInput.GetButtonDown("JoyLStickRight"))
+ {
+ m_buildPieces.RightPiece();
+ SetupPlacementGhost();
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ m_buildPieces.UpPiece();
+ SetupPlacementGhost();
+ }
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ m_buildPieces.DownPiece();
+ SetupPlacementGhost();
+ }
+ }
+ }
+
+ public void SetSelectedPiece(Vector2Int p)
+ {
+ if ((bool)m_buildPieces && m_buildPieces.GetSelectedIndex() != p)
+ {
+ m_buildPieces.SetSelected(p);
+ SetupPlacementGhost();
+ }
+ }
+
+ public Piece GetPiece(Vector2Int p)
+ {
+ if ((bool)m_buildPieces)
+ {
+ return m_buildPieces.GetPiece(p);
+ }
+ return null;
+ }
+
+ public bool IsPieceAvailable(Piece piece)
+ {
+ if ((bool)m_buildPieces)
+ {
+ return m_buildPieces.IsPieceAvailable(piece);
+ }
+ return false;
+ }
+
+ public Piece GetSelectedPiece()
+ {
+ if ((bool)m_buildPieces)
+ {
+ return m_buildPieces.GetSelectedPiece();
+ }
+ return null;
+ }
+
+ private void LateUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ UpdateEmote();
+ if (m_nview.IsOwner())
+ {
+ ZNet.instance.SetReferencePosition(base.transform.position);
+ UpdatePlacementGhost(flashGuardStone: false);
+ }
+ }
+ }
+
+ private void SetupAwake()
+ {
+ if (m_nview.GetZDO() == null)
+ {
+ m_animator.SetBool("wakeup", value: false);
+ return;
+ }
+ bool @bool = m_nview.GetZDO().GetBool("wakeup", defaultValue: true);
+ m_animator.SetBool("wakeup", @bool);
+ if (@bool)
+ {
+ m_wakeupTimer = 0f;
+ }
+ }
+
+ private void UpdateAwake(float dt)
+ {
+ if (!(m_wakeupTimer >= 0f))
+ {
+ return;
+ }
+ m_wakeupTimer += dt;
+ if (m_wakeupTimer > 1f)
+ {
+ m_wakeupTimer = -1f;
+ m_animator.SetBool("wakeup", value: false);
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("wakeup", value: false);
+ }
+ }
+ }
+
+ private void EdgeOfWorldKill(float dt)
+ {
+ if (!IsDead())
+ {
+ float magnitude = base.transform.position.magnitude;
+ float num = 10420f;
+ if (magnitude > num && (IsSwiming() || base.transform.position.y < ZoneSystem.instance.m_waterLevel))
+ {
+ Vector3 vector = Vector3.Normalize(base.transform.position);
+ float num2 = Utils.LerpStep(num, 10500f, magnitude) * 10f;
+ m_body.MovePosition(m_body.position + vector * num2 * dt);
+ }
+ if (magnitude > num && base.transform.position.y < ZoneSystem.instance.m_waterLevel - 40f)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 99999f;
+ Damage(hitData);
+ }
+ }
+ }
+
+ private void AutoPickup(float dt)
+ {
+ if (IsTeleporting())
+ {
+ return;
+ }
+ Vector3 vector = base.transform.position + Vector3.up;
+ Collider[] array = Physics.OverlapSphere(vector, m_autoPickupRange, m_autoPickupMask);
+ foreach (Collider collider in array)
+ {
+ if (!collider.attachedRigidbody)
+ {
+ continue;
+ }
+ ItemDrop component = collider.attachedRigidbody.GetComponent<ItemDrop>();
+ if (component == null || !component.m_autoPickup || HaveUniqueKey(component.m_itemData.m_shared.m_name) || !component.GetComponent<ZNetView>().IsValid())
+ {
+ continue;
+ }
+ if (!component.CanPickup())
+ {
+ component.RequestOwn();
+ }
+ else
+ {
+ if (!m_inventory.CanAddItem(component.m_itemData) || component.m_itemData.GetWeight() + m_inventory.GetTotalWeight() > GetMaxCarryWeight())
+ {
+ continue;
+ }
+ float num = Vector3.Distance(component.transform.position, vector);
+ if (!(num > m_autoPickupRange))
+ {
+ if (num < 0.3f)
+ {
+ Pickup(component.gameObject);
+ continue;
+ }
+ Vector3 vector2 = Vector3.Normalize(vector - component.transform.position);
+ float num2 = 15f;
+ component.transform.position = component.transform.position + vector2 * num2 * dt;
+ }
+ }
+ }
+ }
+
+ private void PlayerAttackInput(float dt)
+ {
+ if (InPlaceMode())
+ {
+ return;
+ }
+ ItemDrop.ItemData currentWeapon = GetCurrentWeapon();
+ if (currentWeapon != null && currentWeapon.m_shared.m_holdDurationMin > 0f)
+ {
+ if (m_blocking || InMinorAction())
+ {
+ m_attackDrawTime = -1f;
+ if (!string.IsNullOrEmpty(currentWeapon.m_shared.m_holdAnimationState))
+ {
+ m_zanim.SetBool(currentWeapon.m_shared.m_holdAnimationState, value: false);
+ }
+ return;
+ }
+ bool flag = currentWeapon.m_shared.m_holdStaminaDrain <= 0f || HaveStamina();
+ if (m_attackDrawTime < 0f)
+ {
+ if (!m_attackDraw)
+ {
+ m_attackDrawTime = 0f;
+ }
+ }
+ else if (m_attackDraw && flag && m_attackDrawTime >= 0f)
+ {
+ if (m_attackDrawTime == 0f)
+ {
+ if (!currentWeapon.m_shared.m_attack.StartDraw(this, currentWeapon))
+ {
+ m_attackDrawTime = -1f;
+ return;
+ }
+ currentWeapon.m_shared.m_holdStartEffect.Create(base.transform.position, Quaternion.identity, base.transform);
+ }
+ m_attackDrawTime += Time.fixedDeltaTime;
+ if (!string.IsNullOrEmpty(currentWeapon.m_shared.m_holdAnimationState))
+ {
+ m_zanim.SetBool(currentWeapon.m_shared.m_holdAnimationState, value: true);
+ }
+ UseStamina(currentWeapon.m_shared.m_holdStaminaDrain * dt);
+ }
+ else if (m_attackDrawTime > 0f)
+ {
+ if (flag)
+ {
+ StartAttack(null, secondaryAttack: false);
+ }
+ if (!string.IsNullOrEmpty(currentWeapon.m_shared.m_holdAnimationState))
+ {
+ m_zanim.SetBool(currentWeapon.m_shared.m_holdAnimationState, value: false);
+ }
+ m_attackDrawTime = 0f;
+ }
+ }
+ else
+ {
+ if (m_attack)
+ {
+ m_queuedAttackTimer = 0.5f;
+ m_queuedSecondAttackTimer = 0f;
+ }
+ if (m_secondaryAttack)
+ {
+ m_queuedSecondAttackTimer = 0.5f;
+ m_queuedAttackTimer = 0f;
+ }
+ m_queuedAttackTimer -= Time.fixedDeltaTime;
+ m_queuedSecondAttackTimer -= Time.fixedDeltaTime;
+ if (m_queuedAttackTimer > 0f && StartAttack(null, secondaryAttack: false))
+ {
+ m_queuedAttackTimer = 0f;
+ }
+ if (m_queuedSecondAttackTimer > 0f && StartAttack(null, secondaryAttack: true))
+ {
+ m_queuedSecondAttackTimer = 0f;
+ }
+ }
+ }
+
+ protected override bool HaveQueuedChain()
+ {
+ if (m_queuedAttackTimer > 0f && GetCurrentWeapon() != null && m_currentAttack != null)
+ {
+ return m_currentAttack.CanStartChainAttack();
+ }
+ return false;
+ }
+
+ private void UpdateBaseValue(float dt)
+ {
+ m_baseValueUpdatetimer += dt;
+ if (m_baseValueUpdatetimer > 2f)
+ {
+ m_baseValueUpdatetimer = 0f;
+ m_baseValue = EffectArea.GetBaseValue(base.transform.position, 20f);
+ m_nview.GetZDO().Set("baseValue", m_baseValue);
+ m_comfortLevel = SE_Rested.CalculateComfortLevel(this);
+ }
+ }
+
+ public int GetComfortLevel()
+ {
+ return m_comfortLevel;
+ }
+
+ public int GetBaseValue()
+ {
+ if (!m_nview.IsValid())
+ {
+ return 0;
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_baseValue;
+ }
+ return m_nview.GetZDO().GetInt("baseValue");
+ }
+
+ public bool IsSafeInHome()
+ {
+ return m_safeInHome;
+ }
+
+ private void UpdateBiome(float dt)
+ {
+ if (InIntro())
+ {
+ return;
+ }
+ m_biomeTimer += dt;
+ if (m_biomeTimer > 1f)
+ {
+ m_biomeTimer = 0f;
+ Heightmap.Biome biome = Heightmap.FindBiome(base.transform.position);
+ if (m_currentBiome != biome)
+ {
+ m_currentBiome = biome;
+ AddKnownBiome(biome);
+ }
+ }
+ }
+
+ public Heightmap.Biome GetCurrentBiome()
+ {
+ return m_currentBiome;
+ }
+
+ public override void RaiseSkill(Skills.SkillType skill, float value = 1f)
+ {
+ float multiplier = 1f;
+ m_seman.ModifyRaiseSkill(skill, ref multiplier);
+ value *= multiplier;
+ m_skills.RaiseSkill(skill, value);
+ }
+
+ private void UpdateStats(float dt)
+ {
+ if (InIntro() || IsTeleporting())
+ {
+ return;
+ }
+ m_timeSinceDeath += dt;
+ UpdateMovementModifier();
+ UpdateFood(dt, forceUpdate: false);
+ bool flag = IsEncumbered();
+ float maxStamina = GetMaxStamina();
+ float num = 1f;
+ if (IsBlocking())
+ {
+ num *= 0.8f;
+ }
+ if ((IsSwiming() && !IsOnGround()) || InAttack() || InDodge() || m_wallRunning || flag)
+ {
+ num = 0f;
+ }
+ float num2 = (m_staminaRegen + (1f - m_stamina / maxStamina) * m_staminaRegen * m_staminaRegenTimeMultiplier) * num;
+ float staminaMultiplier = 1f;
+ m_seman.ModifyStaminaRegen(ref staminaMultiplier);
+ num2 *= staminaMultiplier;
+ m_staminaRegenTimer -= dt;
+ if (m_stamina < maxStamina && m_staminaRegenTimer <= 0f)
+ {
+ m_stamina = Mathf.Min(maxStamina, m_stamina + num2 * dt);
+ }
+ m_nview.GetZDO().Set("stamina", m_stamina);
+ if (flag)
+ {
+ if (m_moveDir.magnitude > 0.1f)
+ {
+ UseStamina(m_encumberedStaminaDrain * dt);
+ }
+ m_seman.AddStatusEffect("Encumbered");
+ ShowTutorial("encumbered");
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("Encumbered");
+ }
+ if (!HardDeath())
+ {
+ m_seman.AddStatusEffect("SoftDeath");
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("SoftDeath");
+ }
+ UpdateEnvStatusEffects(dt);
+ }
+
+ private void UpdateEnvStatusEffects(float dt)
+ {
+ m_nearFireTimer += dt;
+ HitData.DamageModifiers damageModifiers = GetDamageModifiers();
+ bool flag = m_nearFireTimer < 0.25f;
+ bool flag2 = m_seman.HaveStatusEffect("Burning");
+ bool flag3 = InShelter();
+ HitData.DamageModifier modifier = damageModifiers.GetModifier(HitData.DamageType.Frost);
+ bool flag4 = EnvMan.instance.IsFreezing();
+ bool num = EnvMan.instance.IsCold();
+ bool flag5 = EnvMan.instance.IsWet();
+ bool flag6 = IsSensed();
+ bool flag7 = m_seman.HaveStatusEffect("Wet");
+ bool flag8 = IsSitting();
+ bool flag9 = flag4 && !flag && !flag3;
+ bool flag10 = (num && !flag) || (flag4 && flag && !flag3) || (flag4 && !flag && flag3);
+ if (modifier == HitData.DamageModifier.Resistant || modifier == HitData.DamageModifier.VeryResistant)
+ {
+ flag9 = false;
+ flag10 = false;
+ }
+ if (flag5 && !m_underRoof)
+ {
+ m_seman.AddStatusEffect("Wet", resetTime: true);
+ }
+ if (flag3)
+ {
+ m_seman.AddStatusEffect("Shelter");
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("Shelter");
+ }
+ if (flag)
+ {
+ m_seman.AddStatusEffect("CampFire");
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("CampFire");
+ }
+ bool flag11 = !flag6 && (flag8 || flag3) && !flag10 && !flag9 && !flag7 && !flag2 && flag;
+ if (flag11)
+ {
+ m_seman.AddStatusEffect("Resting");
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("Resting");
+ }
+ m_safeInHome = flag11 && flag3;
+ if (flag9)
+ {
+ if (!m_seman.RemoveStatusEffect("Cold", quiet: true))
+ {
+ m_seman.AddStatusEffect("Freezing");
+ }
+ }
+ else if (flag10)
+ {
+ if (!m_seman.RemoveStatusEffect("Freezing", quiet: true) && (bool)m_seman.AddStatusEffect("Cold"))
+ {
+ ShowTutorial("cold");
+ }
+ }
+ else
+ {
+ m_seman.RemoveStatusEffect("Cold");
+ m_seman.RemoveStatusEffect("Freezing");
+ }
+ }
+
+ private bool CanEat(ItemDrop.ItemData item, bool showMessages)
+ {
+ foreach (Food food in m_foods)
+ {
+ if (food.m_item.m_shared.m_name == item.m_shared.m_name)
+ {
+ if (food.CanEatAgain())
+ {
+ return true;
+ }
+ Message(MessageHud.MessageType.Center, Localization.instance.Localize("$msg_nomore", item.m_shared.m_name));
+ return false;
+ }
+ }
+ foreach (Food food2 in m_foods)
+ {
+ if (food2.CanEatAgain())
+ {
+ return true;
+ }
+ }
+ if (m_foods.Count >= 3)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_isfull");
+ return false;
+ }
+ return true;
+ }
+
+ private Food GetMostDepletedFood()
+ {
+ Food food = null;
+ foreach (Food food2 in m_foods)
+ {
+ if (food2.CanEatAgain() && (food == null || food2.m_health < food.m_health))
+ {
+ food = food2;
+ }
+ }
+ return food;
+ }
+
+ public void ClearFood()
+ {
+ m_foods.Clear();
+ }
+
+ private bool EatFood(ItemDrop.ItemData item)
+ {
+ if (!CanEat(item, showMessages: false))
+ {
+ return false;
+ }
+ foreach (Food food2 in m_foods)
+ {
+ if (food2.m_item.m_shared.m_name == item.m_shared.m_name)
+ {
+ if (food2.CanEatAgain())
+ {
+ food2.m_health = item.m_shared.m_food;
+ food2.m_stamina = item.m_shared.m_foodStamina;
+ UpdateFood(0f, forceUpdate: true);
+ return true;
+ }
+ return false;
+ }
+ }
+ if (m_foods.Count < 3)
+ {
+ Food food = new Food();
+ food.m_name = item.m_dropPrefab.name;
+ food.m_item = item;
+ food.m_health = item.m_shared.m_food;
+ food.m_stamina = item.m_shared.m_foodStamina;
+ m_foods.Add(food);
+ UpdateFood(0f, forceUpdate: true);
+ return true;
+ }
+ Food mostDepletedFood = GetMostDepletedFood();
+ if (mostDepletedFood != null)
+ {
+ mostDepletedFood.m_name = item.m_dropPrefab.name;
+ mostDepletedFood.m_item = item;
+ mostDepletedFood.m_health = item.m_shared.m_food;
+ mostDepletedFood.m_stamina = item.m_shared.m_foodStamina;
+ return true;
+ }
+ return false;
+ }
+
+ private void UpdateFood(float dt, bool forceUpdate)
+ {
+ m_foodUpdateTimer += dt;
+ if (m_foodUpdateTimer >= 1f || forceUpdate)
+ {
+ m_foodUpdateTimer = 0f;
+ foreach (Food food in m_foods)
+ {
+ food.m_health -= food.m_item.m_shared.m_food / food.m_item.m_shared.m_foodBurnTime;
+ food.m_stamina -= food.m_item.m_shared.m_foodStamina / food.m_item.m_shared.m_foodBurnTime;
+ if (food.m_health < 0f)
+ {
+ food.m_health = 0f;
+ }
+ if (food.m_stamina < 0f)
+ {
+ food.m_stamina = 0f;
+ }
+ if (food.m_health <= 0f)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_food_done");
+ m_foods.Remove(food);
+ break;
+ }
+ }
+ GetTotalFoodValue(out var hp, out var stamina);
+ SetMaxHealth(hp, flashBar: true);
+ SetMaxStamina(stamina, flashBar: true);
+ }
+ if (forceUpdate)
+ {
+ return;
+ }
+ m_foodRegenTimer += dt;
+ if (!(m_foodRegenTimer >= 10f))
+ {
+ return;
+ }
+ m_foodRegenTimer = 0f;
+ float num = 0f;
+ foreach (Food food2 in m_foods)
+ {
+ num += food2.m_item.m_shared.m_foodRegen;
+ }
+ if (num > 0f)
+ {
+ float regenMultiplier = 1f;
+ m_seman.ModifyHealthRegen(ref regenMultiplier);
+ num *= regenMultiplier;
+ Heal(num);
+ }
+ }
+
+ private void GetTotalFoodValue(out float hp, out float stamina)
+ {
+ hp = 25f;
+ stamina = 75f;
+ foreach (Food food in m_foods)
+ {
+ hp += food.m_health;
+ stamina += food.m_stamina;
+ }
+ }
+
+ public float GetBaseFoodHP()
+ {
+ return 25f;
+ }
+
+ public List<Food> GetFoods()
+ {
+ return m_foods;
+ }
+
+ public void OnSpawned()
+ {
+ m_spawnEffects.Create(base.transform.position, Quaternion.identity);
+ if (m_firstSpawn)
+ {
+ if (m_valkyrie != null)
+ {
+ UnityEngine.Object.Instantiate(m_valkyrie, base.transform.position, Quaternion.identity);
+ }
+ m_firstSpawn = false;
+ }
+ }
+
+ protected override bool CheckRun(Vector3 moveDir, float dt)
+ {
+ if (!base.CheckRun(moveDir, dt))
+ {
+ return false;
+ }
+ bool flag = HaveStamina();
+ float skillFactor = m_skills.GetSkillFactor(Skills.SkillType.Run);
+ float num = Mathf.Lerp(1f, 0.5f, skillFactor);
+ float drain = m_runStaminaDrain * num;
+ m_seman.ModifyRunStaminaDrain(drain, ref drain);
+ UseStamina(dt * drain);
+ if (HaveStamina())
+ {
+ m_runSkillImproveTimer += dt;
+ if (m_runSkillImproveTimer > 1f)
+ {
+ m_runSkillImproveTimer = 0f;
+ RaiseSkill(Skills.SkillType.Run);
+ }
+ AbortEquipQueue();
+ return true;
+ }
+ if (flag)
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ return false;
+ }
+
+ private void UpdateMovementModifier()
+ {
+ m_equipmentMovementModifier = 0f;
+ if (m_rightItem != null)
+ {
+ m_equipmentMovementModifier += m_rightItem.m_shared.m_movementModifier;
+ }
+ if (m_leftItem != null)
+ {
+ m_equipmentMovementModifier += m_leftItem.m_shared.m_movementModifier;
+ }
+ if (m_chestItem != null)
+ {
+ m_equipmentMovementModifier += m_chestItem.m_shared.m_movementModifier;
+ }
+ if (m_legItem != null)
+ {
+ m_equipmentMovementModifier += m_legItem.m_shared.m_movementModifier;
+ }
+ if (m_helmetItem != null)
+ {
+ m_equipmentMovementModifier += m_helmetItem.m_shared.m_movementModifier;
+ }
+ if (m_shoulderItem != null)
+ {
+ m_equipmentMovementModifier += m_shoulderItem.m_shared.m_movementModifier;
+ }
+ if (m_utilityItem != null)
+ {
+ m_equipmentMovementModifier += m_utilityItem.m_shared.m_movementModifier;
+ }
+ }
+
+ public void OnSkillLevelup(Skills.SkillType skill, float level)
+ {
+ m_skillLevelupEffects.Create(m_head.position, m_head.rotation, m_head);
+ }
+
+ protected override void OnJump()
+ {
+ AbortEquipQueue();
+ float staminaUse = m_jumpStaminaUsage - m_jumpStaminaUsage * m_equipmentMovementModifier;
+ m_seman.ModifyJumpStaminaUsage(staminaUse, ref staminaUse);
+ UseStamina(staminaUse);
+ }
+
+ protected override void OnSwiming(Vector3 targetVel, float dt)
+ {
+ base.OnSwiming(targetVel, dt);
+ if (targetVel.magnitude > 0.1f)
+ {
+ float skillFactor = m_skills.GetSkillFactor(Skills.SkillType.Swim);
+ float num = Mathf.Lerp(m_swimStaminaDrainMinSkill, m_swimStaminaDrainMaxSkill, skillFactor);
+ UseStamina(dt * num);
+ m_swimSkillImproveTimer += dt;
+ if (m_swimSkillImproveTimer > 1f)
+ {
+ m_swimSkillImproveTimer = 0f;
+ RaiseSkill(Skills.SkillType.Swim);
+ }
+ }
+ if (!HaveStamina())
+ {
+ m_drownDamageTimer += dt;
+ if (m_drownDamageTimer > 1f)
+ {
+ m_drownDamageTimer = 0f;
+ float damage = Mathf.Ceil(GetMaxHealth() / 20f);
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = damage;
+ hitData.m_point = GetCenterPoint();
+ hitData.m_dir = Vector3.down;
+ hitData.m_pushForce = 10f;
+ Damage(hitData);
+ }
+ }
+ }
+
+ protected override bool TakeInput()
+ {
+ bool result = (!Chat.instance || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible() && (!TextViewer.instance || !TextViewer.instance.IsVisible()) && !Minimap.IsOpen() && !GameCamera.InFreeFly();
+ if (IsDead() || InCutscene() || IsTeleporting())
+ {
+ result = false;
+ }
+ return result;
+ }
+
+ public void UseHotbarItem(int index)
+ {
+ ItemDrop.ItemData itemAt = m_inventory.GetItemAt(index - 1, 0);
+ if (itemAt != null)
+ {
+ UseItem(null, itemAt, fromInventoryGui: false);
+ }
+ }
+
+ public bool RequiredCraftingStation(Recipe recipe, int qualityLevel, bool checkLevel)
+ {
+ CraftingStation requiredStation = recipe.GetRequiredStation(qualityLevel);
+ if (requiredStation != null)
+ {
+ if (m_currentStation == null)
+ {
+ return false;
+ }
+ if (requiredStation.m_name != m_currentStation.m_name)
+ {
+ return false;
+ }
+ if (checkLevel)
+ {
+ int requiredStationLevel = recipe.GetRequiredStationLevel(qualityLevel);
+ if (m_currentStation.GetLevel() < requiredStationLevel)
+ {
+ return false;
+ }
+ }
+ }
+ else if (m_currentStation != null && !m_currentStation.m_showBasicRecipies)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool HaveRequirements(Recipe recipe, bool discover, int qualityLevel)
+ {
+ if (discover)
+ {
+ if ((bool)recipe.m_craftingStation && !KnowStationLevel(recipe.m_craftingStation.m_name, recipe.m_minStationLevel))
+ {
+ return false;
+ }
+ }
+ else if (!RequiredCraftingStation(recipe, qualityLevel, checkLevel: true))
+ {
+ return false;
+ }
+ if (recipe.m_item.m_itemData.m_shared.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(recipe.m_item.m_itemData.m_shared.m_dlc))
+ {
+ return false;
+ }
+ if (!HaveRequirements(recipe.m_resources, discover, qualityLevel))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool HaveRequirements(Piece.Requirement[] resources, bool discover, int qualityLevel)
+ {
+ foreach (Piece.Requirement requirement in resources)
+ {
+ if (!requirement.m_resItem)
+ {
+ continue;
+ }
+ if (discover)
+ {
+ if (requirement.m_amount > 0 && !m_knownMaterial.Contains(requirement.m_resItem.m_itemData.m_shared.m_name))
+ {
+ return false;
+ }
+ continue;
+ }
+ int amount = requirement.GetAmount(qualityLevel);
+ if (m_inventory.CountItems(requirement.m_resItem.m_itemData.m_shared.m_name) < amount)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public bool HaveRequirements(Piece piece, RequirementMode mode)
+ {
+ if ((bool)piece.m_craftingStation)
+ {
+ if (mode == RequirementMode.IsKnown || mode == RequirementMode.CanAlmostBuild)
+ {
+ if (!m_knownStations.ContainsKey(piece.m_craftingStation.m_name))
+ {
+ return false;
+ }
+ }
+ else if (!CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, base.transform.position))
+ {
+ return false;
+ }
+ }
+ if (piece.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(piece.m_dlc))
+ {
+ return false;
+ }
+ Piece.Requirement[] resources = piece.m_resources;
+ foreach (Piece.Requirement requirement in resources)
+ {
+ if (!requirement.m_resItem || requirement.m_amount <= 0)
+ {
+ continue;
+ }
+ switch (mode)
+ {
+ case RequirementMode.IsKnown:
+ if (!m_knownMaterial.Contains(requirement.m_resItem.m_itemData.m_shared.m_name))
+ {
+ return false;
+ }
+ break;
+ case RequirementMode.CanAlmostBuild:
+ if (!m_inventory.HaveItem(requirement.m_resItem.m_itemData.m_shared.m_name))
+ {
+ return false;
+ }
+ break;
+ case RequirementMode.CanBuild:
+ if (m_inventory.CountItems(requirement.m_resItem.m_itemData.m_shared.m_name) < requirement.m_amount)
+ {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ public void SetCraftingStation(CraftingStation station)
+ {
+ if (!(m_currentStation == station))
+ {
+ if ((bool)station)
+ {
+ AddKnownStation(station);
+ station.PokeInUse();
+ }
+ m_currentStation = station;
+ HideHandItems();
+ int value = (m_currentStation ? m_currentStation.m_useAnimation : 0);
+ m_zanim.SetInt("crafting", value);
+ }
+ }
+
+ public CraftingStation GetCurrentCraftingStation()
+ {
+ return m_currentStation;
+ }
+
+ public void ConsumeResources(Piece.Requirement[] requirements, int qualityLevel)
+ {
+ foreach (Piece.Requirement requirement in requirements)
+ {
+ if ((bool)requirement.m_resItem)
+ {
+ int amount = requirement.GetAmount(qualityLevel);
+ if (amount > 0)
+ {
+ m_inventory.RemoveItem(requirement.m_resItem.m_itemData.m_shared.m_name, amount);
+ }
+ }
+ }
+ }
+
+ private void UpdateHover()
+ {
+ if (InPlaceMode() || IsDead() || m_shipControl != null)
+ {
+ m_hovering = null;
+ m_hoveringCreature = null;
+ }
+ else
+ {
+ FindHoverObject(out m_hovering, out m_hoveringCreature);
+ }
+ }
+
+ private bool CheckCanRemovePiece(Piece piece)
+ {
+ if (!m_noPlacementCost && piece.m_craftingStation != null && !CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, base.transform.position))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_missingstation");
+ return false;
+ }
+ return true;
+ }
+
+ private bool RemovePiece()
+ {
+ if (Physics.Raycast(GameCamera.instance.transform.position, GameCamera.instance.transform.forward, out var hitInfo, 50f, m_removeRayMask) && Vector3.Distance(hitInfo.point, m_eye.position) < m_maxPlaceDistance)
+ {
+ Piece piece = hitInfo.collider.GetComponentInParent<Piece>();
+ if (piece == null && (bool)hitInfo.collider.GetComponent<Heightmap>())
+ {
+ piece = TerrainModifier.FindClosestModifierPieceInRange(hitInfo.point, 2.5f);
+ }
+ if ((bool)piece)
+ {
+ if (!piece.m_canBeRemoved)
+ {
+ return false;
+ }
+ if (Location.IsInsideNoBuildLocation(piece.transform.position))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_nobuildzone");
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(piece.transform.position))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_privatezone");
+ return false;
+ }
+ if (!CheckCanRemovePiece(piece))
+ {
+ return false;
+ }
+ ZNetView component = piece.GetComponent<ZNetView>();
+ if (component == null)
+ {
+ return false;
+ }
+ if (!piece.CanBeRemoved())
+ {
+ Message(MessageHud.MessageType.Center, "$msg_cantremovenow");
+ return false;
+ }
+ component.ClaimOwnership();
+ WearNTear component2 = piece.GetComponent<WearNTear>();
+ if ((bool)component2)
+ {
+ component2.Destroy();
+ }
+ else
+ {
+ piece.DropResources();
+ piece.m_placeEffect.Create(piece.transform.position, piece.transform.rotation, piece.gameObject.transform);
+ m_removeEffects.Create(piece.transform.position, Quaternion.identity);
+ ZNetScene.instance.Destroy(piece.gameObject);
+ }
+ ItemDrop.ItemData rightItem = GetRightItem();
+ if (rightItem != null)
+ {
+ FaceLookDirection();
+ m_zanim.SetTrigger(rightItem.m_shared.m_attack.m_attackAnimation);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void FaceLookDirection()
+ {
+ base.transform.rotation = GetLookYaw();
+ }
+
+ private bool PlacePiece(Piece piece)
+ {
+ UpdatePlacementGhost(flashGuardStone: true);
+ Vector3 position = m_placementGhost.transform.position;
+ Quaternion rotation = m_placementGhost.transform.rotation;
+ GameObject gameObject = piece.gameObject;
+ switch (m_placementStatus)
+ {
+ case PlacementStatus.NoBuildZone:
+ Message(MessageHud.MessageType.Center, "$msg_nobuildzone");
+ return false;
+ case PlacementStatus.BlockedbyPlayer:
+ Message(MessageHud.MessageType.Center, "$msg_blocked");
+ return false;
+ case PlacementStatus.PrivateZone:
+ Message(MessageHud.MessageType.Center, "$msg_privatezone");
+ return false;
+ case PlacementStatus.MoreSpace:
+ Message(MessageHud.MessageType.Center, "$msg_needspace");
+ return false;
+ case PlacementStatus.NoTeleportArea:
+ Message(MessageHud.MessageType.Center, "$msg_noteleportarea");
+ return false;
+ case PlacementStatus.Invalid:
+ Message(MessageHud.MessageType.Center, "$msg_invalidplacement");
+ return false;
+ case PlacementStatus.ExtensionMissingStation:
+ Message(MessageHud.MessageType.Center, "$msg_extensionmissingstation");
+ return false;
+ case PlacementStatus.WrongBiome:
+ Message(MessageHud.MessageType.Center, "$msg_wrongbiome");
+ return false;
+ case PlacementStatus.NeedCultivated:
+ Message(MessageHud.MessageType.Center, "$msg_needcultivated");
+ return false;
+ case PlacementStatus.NotInDungeon:
+ Message(MessageHud.MessageType.Center, "$msg_notindungeon");
+ return false;
+ default:
+ {
+ TerrainModifier.SetTriggerOnPlaced(trigger: true);
+ GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, position, rotation);
+ TerrainModifier.SetTriggerOnPlaced(trigger: false);
+ CraftingStation componentInChildren = gameObject2.GetComponentInChildren<CraftingStation>();
+ if ((bool)componentInChildren)
+ {
+ AddKnownStation(componentInChildren);
+ }
+ Piece component = gameObject2.GetComponent<Piece>();
+ if ((bool)component)
+ {
+ component.SetCreator(GetPlayerID());
+ }
+ PrivateArea component2 = gameObject2.GetComponent<PrivateArea>();
+ if ((bool)component2)
+ {
+ component2.Setup(Game.instance.GetPlayerProfile().GetName());
+ }
+ WearNTear component3 = gameObject2.GetComponent<WearNTear>();
+ if ((bool)component3)
+ {
+ component3.OnPlaced();
+ }
+ ItemDrop.ItemData rightItem = GetRightItem();
+ if (rightItem != null)
+ {
+ FaceLookDirection();
+ m_zanim.SetTrigger(rightItem.m_shared.m_attack.m_attackAnimation);
+ }
+ piece.m_placeEffect.Create(position, rotation, gameObject2.transform);
+ AddNoise(50f);
+ Game.instance.GetPlayerProfile().m_playerStats.m_builds++;
+ ZLog.Log("Placed " + gameObject.name);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "PlacedPiece", gameObject.name, 0L);
+ return true;
+ }
+ }
+ }
+
+ private void RemovePieces(Vector3 point, float range, string name, bool groundOnly)
+ {
+ Collider[] array = Physics.OverlapSphere(point, range + 3f);
+ Piece item = null;
+ float num = 0f;
+ List<Piece> list = new List<Piece>();
+ Collider[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ Piece componentInParent = array2[i].GetComponentInParent<Piece>();
+ if (!componentInParent || (!(componentInParent.m_name == name) && !(name == "")) || (groundOnly && !componentInParent.m_groundPiece) || !componentInParent.CanBeRemoved() || !PrivateArea.CheckAccess(componentInParent.transform.position) || componentInParent.gameObject == m_placementGhost)
+ {
+ continue;
+ }
+ float num2 = Utils.DistanceXZ(point, componentInParent.transform.position);
+ if (!(num2 > range))
+ {
+ if (num2 > num)
+ {
+ num = num2;
+ item = componentInParent;
+ }
+ list.Add(componentInParent);
+ }
+ }
+ list.Remove(item);
+ foreach (Piece item2 in list)
+ {
+ ZNetView component = item2.GetComponent<ZNetView>();
+ component.ClaimOwnership();
+ component.Destroy();
+ GoogleAnalyticsV4.instance.LogEvent("Game", "RemovedPiece", item2.gameObject.name, 0L);
+ }
+ }
+
+ public override bool IsPlayer()
+ {
+ return true;
+ }
+
+ public void GetBuildSelection(out Piece go, out Vector2Int id, out int total, out Piece.PieceCategory category, out bool useCategory)
+ {
+ category = m_buildPieces.m_selectedCategory;
+ useCategory = m_buildPieces.m_useCategories;
+ if (m_buildPieces.GetAvailablePiecesInSelectedCategory() == 0)
+ {
+ go = null;
+ id = Vector2Int.zero;
+ total = 0;
+ }
+ else
+ {
+ GameObject selectedPrefab = m_buildPieces.GetSelectedPrefab();
+ go = (selectedPrefab ? selectedPrefab.GetComponent<Piece>() : null);
+ id = m_buildPieces.GetSelectedIndex();
+ total = m_buildPieces.GetAvailablePiecesInSelectedCategory();
+ }
+ }
+
+ public List<Piece> GetBuildPieces()
+ {
+ if ((bool)m_buildPieces)
+ {
+ return m_buildPieces.GetPiecesInSelectedCategory();
+ }
+ return null;
+ }
+
+ public int GetAvailableBuildPiecesInCategory(Piece.PieceCategory cat)
+ {
+ if ((bool)m_buildPieces)
+ {
+ return m_buildPieces.GetAvailablePiecesInCategory(cat);
+ }
+ return 0;
+ }
+
+ private void RPC_OnDeath(long sender)
+ {
+ m_visual.SetActive(value: false);
+ }
+
+ private void CreateDeathEffects()
+ {
+ GameObject[] array = m_deathEffects.Create(base.transform.position, base.transform.rotation, base.transform);
+ for (int i = 0; i < array.Length; i++)
+ {
+ Ragdoll component = array[i].GetComponent<Ragdoll>();
+ if ((bool)component)
+ {
+ Vector3 velocity = m_body.velocity;
+ if (m_pushForce.magnitude * 0.5f > velocity.magnitude)
+ {
+ velocity = m_pushForce * 0.5f;
+ }
+ component.Setup(velocity, 0f, 0f, 0f, null);
+ OnRagdollCreated(component);
+ m_ragdoll = component;
+ }
+ }
+ }
+
+ public void UnequipDeathDropItems()
+ {
+ if (m_rightItem != null)
+ {
+ UnequipItem(m_rightItem, triggerEquipEffects: false);
+ }
+ if (m_leftItem != null)
+ {
+ UnequipItem(m_leftItem, triggerEquipEffects: false);
+ }
+ if (m_ammoItem != null)
+ {
+ UnequipItem(m_ammoItem, triggerEquipEffects: false);
+ }
+ if (m_utilityItem != null)
+ {
+ UnequipItem(m_utilityItem, triggerEquipEffects: false);
+ }
+ }
+
+ private void CreateTombStone()
+ {
+ if (m_inventory.NrOfItems() != 0)
+ {
+ UnequipAllItems();
+ GameObject obj = UnityEngine.Object.Instantiate(m_tombstone, GetCenterPoint(), base.transform.rotation);
+ obj.GetComponent<Container>().GetInventory().MoveInventoryToGrave(m_inventory);
+ TombStone component = obj.GetComponent<TombStone>();
+ PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
+ component.Setup(playerProfile.GetName(), playerProfile.GetPlayerID());
+ }
+ }
+
+ private bool HardDeath()
+ {
+ return m_timeSinceDeath > m_hardDeathCooldown;
+ }
+
+ protected override void OnDeath()
+ {
+ bool num = HardDeath();
+ m_nview.GetZDO().Set("dead", value: true);
+ m_nview.InvokeRPC(ZNetView.Everybody, "OnDeath");
+ Game.instance.GetPlayerProfile().m_playerStats.m_deaths++;
+ Game.instance.GetPlayerProfile().SetDeathPoint(base.transform.position);
+ CreateDeathEffects();
+ CreateTombStone();
+ m_foods.Clear();
+ if (num)
+ {
+ m_skills.OnDeath();
+ }
+ Game.instance.RequestRespawn(10f);
+ m_timeSinceDeath = 0f;
+ if (!num)
+ {
+ Message(MessageHud.MessageType.TopLeft, "$msg_softdeath");
+ }
+ Message(MessageHud.MessageType.Center, "$msg_youdied");
+ ShowTutorial("death");
+ string eventLabel = "biome:" + GetCurrentBiome();
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Death", eventLabel, 0L);
+ }
+
+ public void OnRespawn()
+ {
+ m_nview.GetZDO().Set("dead", value: false);
+ SetHealth(GetMaxHealth());
+ }
+
+ private void SetupPlacementGhost()
+ {
+ if ((bool)m_placementGhost)
+ {
+ UnityEngine.Object.Destroy(m_placementGhost);
+ m_placementGhost = null;
+ }
+ if (m_buildPieces == null)
+ {
+ return;
+ }
+ GameObject selectedPrefab = m_buildPieces.GetSelectedPrefab();
+ if (selectedPrefab == null || selectedPrefab.GetComponent<Piece>().m_repairPiece)
+ {
+ return;
+ }
+ bool flag = false;
+ TerrainModifier componentInChildren = selectedPrefab.GetComponentInChildren<TerrainModifier>();
+ if ((bool)componentInChildren)
+ {
+ flag = componentInChildren.enabled;
+ componentInChildren.enabled = false;
+ }
+ ZNetView.m_forceDisableInit = true;
+ m_placementGhost = UnityEngine.Object.Instantiate(selectedPrefab);
+ ZNetView.m_forceDisableInit = false;
+ m_placementGhost.name = selectedPrefab.name;
+ if ((bool)componentInChildren)
+ {
+ componentInChildren.enabled = flag;
+ }
+ Joint[] componentsInChildren = m_placementGhost.GetComponentsInChildren<Joint>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ UnityEngine.Object.Destroy(componentsInChildren[i]);
+ }
+ Rigidbody[] componentsInChildren2 = m_placementGhost.GetComponentsInChildren<Rigidbody>();
+ for (int i = 0; i < componentsInChildren2.Length; i++)
+ {
+ UnityEngine.Object.Destroy(componentsInChildren2[i]);
+ }
+ Collider[] componentsInChildren3 = m_placementGhost.GetComponentsInChildren<Collider>();
+ foreach (Collider collider in componentsInChildren3)
+ {
+ if (((1 << collider.gameObject.layer) & m_placeRayMask) == 0)
+ {
+ ZLog.Log("Disabling " + collider.gameObject.name + " " + LayerMask.LayerToName(collider.gameObject.layer));
+ collider.enabled = false;
+ }
+ }
+ Transform[] componentsInChildren4 = m_placementGhost.GetComponentsInChildren<Transform>();
+ int layer = LayerMask.NameToLayer("ghost");
+ Transform[] array = componentsInChildren4;
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i].gameObject.layer = layer;
+ }
+ TerrainModifier[] componentsInChildren5 = m_placementGhost.GetComponentsInChildren<TerrainModifier>();
+ for (int i = 0; i < componentsInChildren5.Length; i++)
+ {
+ UnityEngine.Object.Destroy(componentsInChildren5[i]);
+ }
+ GuidePoint[] componentsInChildren6 = m_placementGhost.GetComponentsInChildren<GuidePoint>();
+ for (int i = 0; i < componentsInChildren6.Length; i++)
+ {
+ UnityEngine.Object.Destroy(componentsInChildren6[i]);
+ }
+ Light[] componentsInChildren7 = m_placementGhost.GetComponentsInChildren<Light>();
+ for (int i = 0; i < componentsInChildren7.Length; i++)
+ {
+ UnityEngine.Object.Destroy(componentsInChildren7[i]);
+ }
+ AudioSource[] componentsInChildren8 = m_placementGhost.GetComponentsInChildren<AudioSource>();
+ for (int i = 0; i < componentsInChildren8.Length; i++)
+ {
+ componentsInChildren8[i].enabled = false;
+ }
+ ZSFX[] componentsInChildren9 = m_placementGhost.GetComponentsInChildren<ZSFX>();
+ for (int i = 0; i < componentsInChildren9.Length; i++)
+ {
+ componentsInChildren9[i].enabled = false;
+ }
+ Windmill componentInChildren2 = m_placementGhost.GetComponentInChildren<Windmill>();
+ if ((bool)componentInChildren2)
+ {
+ componentInChildren2.enabled = false;
+ }
+ ParticleSystem[] componentsInChildren10 = m_placementGhost.GetComponentsInChildren<ParticleSystem>();
+ for (int i = 0; i < componentsInChildren10.Length; i++)
+ {
+ componentsInChildren10[i].gameObject.SetActive(value: false);
+ }
+ Transform transform = m_placementGhost.transform.Find("_GhostOnly");
+ if ((bool)transform)
+ {
+ transform.gameObject.SetActive(value: true);
+ }
+ m_placementGhost.transform.position = base.transform.position;
+ m_placementGhost.transform.localScale = selectedPrefab.transform.localScale;
+ MeshRenderer[] componentsInChildren11 = m_placementGhost.GetComponentsInChildren<MeshRenderer>();
+ foreach (MeshRenderer meshRenderer in componentsInChildren11)
+ {
+ if (!(meshRenderer.sharedMaterial == null))
+ {
+ Material[] sharedMaterials = meshRenderer.sharedMaterials;
+ for (int j = 0; j < sharedMaterials.Length; j++)
+ {
+ Material material = new Material(sharedMaterials[j]);
+ material.SetFloat("_RippleDistance", 0f);
+ material.SetFloat("_ValueNoise", 0f);
+ sharedMaterials[j] = material;
+ }
+ meshRenderer.sharedMaterials = sharedMaterials;
+ meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
+ }
+ }
+ }
+
+ private void SetPlacementGhostValid(bool valid)
+ {
+ m_placementGhost.GetComponent<Piece>().SetInvalidPlacementHeightlight(!valid);
+ }
+
+ protected override void SetPlaceMode(PieceTable buildPieces)
+ {
+ base.SetPlaceMode(buildPieces);
+ m_buildPieces = buildPieces;
+ UpdateAvailablePiecesList();
+ }
+
+ public void SetBuildCategory(int index)
+ {
+ if (m_buildPieces != null)
+ {
+ m_buildPieces.SetCategory(index);
+ UpdateAvailablePiecesList();
+ }
+ }
+
+ public override bool InPlaceMode()
+ {
+ return m_buildPieces != null;
+ }
+
+ private void Repair(ItemDrop.ItemData toolItem, Piece repairPiece)
+ {
+ if (!InPlaceMode())
+ {
+ return;
+ }
+ Piece hoveringPiece = GetHoveringPiece();
+ if (!hoveringPiece || !CheckCanRemovePiece(hoveringPiece) || !PrivateArea.CheckAccess(hoveringPiece.transform.position))
+ {
+ return;
+ }
+ bool flag = false;
+ WearNTear component = hoveringPiece.GetComponent<WearNTear>();
+ if ((bool)component && component.Repair())
+ {
+ flag = true;
+ }
+ if (flag)
+ {
+ FaceLookDirection();
+ m_zanim.SetTrigger(toolItem.m_shared.m_attack.m_attackAnimation);
+ hoveringPiece.m_placeEffect.Create(hoveringPiece.transform.position, hoveringPiece.transform.rotation);
+ Message(MessageHud.MessageType.TopLeft, Localization.instance.Localize("$msg_repaired", hoveringPiece.m_name));
+ UseStamina(toolItem.m_shared.m_attack.m_attackStamina);
+ if (toolItem.m_shared.m_useDurability)
+ {
+ toolItem.m_durability -= toolItem.m_shared.m_useDurabilityDrain;
+ }
+ }
+ else
+ {
+ Message(MessageHud.MessageType.TopLeft, hoveringPiece.m_name + " $msg_doesnotneedrepair");
+ }
+ }
+
+ private void UpdateWearNTearHover()
+ {
+ if (!InPlaceMode())
+ {
+ m_hoveringPiece = null;
+ return;
+ }
+ m_hoveringPiece = null;
+ if (!Physics.Raycast(GameCamera.instance.transform.position, GameCamera.instance.transform.forward, out var hitInfo, 50f, m_removeRayMask) || !(Vector3.Distance(m_eye.position, hitInfo.point) < m_maxPlaceDistance))
+ {
+ return;
+ }
+ Piece piece = (m_hoveringPiece = hitInfo.collider.GetComponentInParent<Piece>());
+ if ((bool)piece)
+ {
+ WearNTear component = piece.GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ component.Highlight();
+ }
+ }
+ }
+
+ public Piece GetHoveringPiece()
+ {
+ if (InPlaceMode())
+ {
+ return m_hoveringPiece;
+ }
+ return null;
+ }
+
+ private void UpdatePlacementGhost(bool flashGuardStone)
+ {
+ if (m_placementGhost == null)
+ {
+ if ((bool)m_placementMarkerInstance)
+ {
+ m_placementMarkerInstance.SetActive(value: false);
+ }
+ return;
+ }
+ bool flag = ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyAltPlace");
+ Piece component = m_placementGhost.GetComponent<Piece>();
+ bool water = component.m_waterPiece || component.m_noInWater;
+ if (PieceRayTest(out var point, out var normal, out var piece, out var heightmap, out var waterSurface, water))
+ {
+ m_placementStatus = PlacementStatus.Valid;
+ if (m_placementMarkerInstance == null)
+ {
+ m_placementMarkerInstance = UnityEngine.Object.Instantiate(m_placeMarker, point, Quaternion.identity);
+ }
+ m_placementMarkerInstance.SetActive(value: true);
+ m_placementMarkerInstance.transform.position = point;
+ m_placementMarkerInstance.transform.rotation = Quaternion.LookRotation(normal);
+ if (component.m_groundOnly || component.m_groundPiece || component.m_cultivatedGroundOnly)
+ {
+ m_placementMarkerInstance.SetActive(value: false);
+ }
+ WearNTear wearNTear = ((piece != null) ? piece.GetComponent<WearNTear>() : null);
+ StationExtension component2 = component.GetComponent<StationExtension>();
+ if (component2 != null)
+ {
+ CraftingStation craftingStation = component2.FindClosestStationInRange(point);
+ if ((bool)craftingStation)
+ {
+ component2.StartConnectionEffect(craftingStation);
+ }
+ else
+ {
+ component2.StopConnectionEffect();
+ m_placementStatus = PlacementStatus.ExtensionMissingStation;
+ }
+ if (component2.OtherExtensionInRange(component.m_spaceRequirement))
+ {
+ m_placementStatus = PlacementStatus.MoreSpace;
+ }
+ }
+ if ((bool)wearNTear && !wearNTear.m_supports)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_waterPiece && waterSurface == null && !flag)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_noInWater && waterSurface != null)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_groundPiece && heightmap == null)
+ {
+ m_placementGhost.SetActive(value: false);
+ m_placementStatus = PlacementStatus.Invalid;
+ return;
+ }
+ if (component.m_groundOnly && heightmap == null)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_cultivatedGroundOnly && (heightmap == null || !heightmap.IsCultivated(point)))
+ {
+ m_placementStatus = PlacementStatus.NeedCultivated;
+ }
+ if (component.m_notOnWood && (bool)piece && (bool)wearNTear && wearNTear.m_materialType == WearNTear.MaterialType.Wood)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_notOnTiltingSurface && normal.y < 0.8f)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_inCeilingOnly && normal.y > -0.5f)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_notOnFloor && normal.y > 0.1f)
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ if (component.m_onlyInTeleportArea && !EffectArea.IsPointInsideArea(point, EffectArea.Type.Teleport))
+ {
+ m_placementStatus = PlacementStatus.NoTeleportArea;
+ }
+ if (!component.m_allowedInDungeons && InInterior())
+ {
+ m_placementStatus = PlacementStatus.NotInDungeon;
+ }
+ if ((bool)heightmap)
+ {
+ normal = Vector3.up;
+ }
+ m_placementGhost.SetActive(value: true);
+ Quaternion rotation = Quaternion.Euler(0f, 22.5f * (float)m_placeRotation, 0f);
+ if (((component.m_groundPiece || component.m_clipGround) && (bool)heightmap) || component.m_clipEverything)
+ {
+ if ((bool)m_buildPieces.GetSelectedPrefab().GetComponent<TerrainModifier>() && component.m_allowAltGroundPlacement && component.m_groundPiece && !ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyAltPlace"))
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ point.y = groundHeight;
+ }
+ m_placementGhost.transform.position = point;
+ m_placementGhost.transform.rotation = rotation;
+ }
+ else
+ {
+ Collider[] componentsInChildren = m_placementGhost.GetComponentsInChildren<Collider>();
+ if (componentsInChildren.Length != 0)
+ {
+ m_placementGhost.transform.position = point + normal * 50f;
+ m_placementGhost.transform.rotation = rotation;
+ Vector3 vector = Vector3.zero;
+ float num = 999999f;
+ Collider[] array = componentsInChildren;
+ foreach (Collider collider in array)
+ {
+ if (collider.isTrigger || !collider.enabled)
+ {
+ continue;
+ }
+ MeshCollider meshCollider = collider as MeshCollider;
+ if (!(meshCollider != null) || meshCollider.convex)
+ {
+ Vector3 vector2 = collider.ClosestPoint(point);
+ float num2 = Vector3.Distance(vector2, point);
+ if (num2 < num)
+ {
+ vector = vector2;
+ num = num2;
+ }
+ }
+ }
+ Vector3 vector3 = m_placementGhost.transform.position - vector;
+ if (component.m_waterPiece)
+ {
+ vector3.y = 3f;
+ }
+ m_placementGhost.transform.position = point + vector3;
+ m_placementGhost.transform.rotation = rotation;
+ }
+ }
+ if (!flag)
+ {
+ m_tempPieces.Clear();
+ if (FindClosestSnapPoints(m_placementGhost.transform, 0.5f, out var a, out var b, m_tempPieces))
+ {
+ _ = b.parent.position;
+ Vector3 vector4 = b.position - (a.position - m_placementGhost.transform.position);
+ if (!IsOverlapingOtherPiece(vector4, m_placementGhost.name, m_tempPieces))
+ {
+ m_placementGhost.transform.position = vector4;
+ }
+ }
+ }
+ if (Location.IsInsideNoBuildLocation(m_placementGhost.transform.position))
+ {
+ m_placementStatus = PlacementStatus.NoBuildZone;
+ }
+ float radius = (component.GetComponent<PrivateArea>() ? component.GetComponent<PrivateArea>().m_radius : 0f);
+ if (!PrivateArea.CheckAccess(m_placementGhost.transform.position, radius, flashGuardStone))
+ {
+ m_placementStatus = PlacementStatus.PrivateZone;
+ }
+ if (CheckPlacementGhostVSPlayers())
+ {
+ m_placementStatus = PlacementStatus.BlockedbyPlayer;
+ }
+ if (component.m_onlyInBiome != 0 && (Heightmap.FindBiome(m_placementGhost.transform.position) & component.m_onlyInBiome) == 0)
+ {
+ m_placementStatus = PlacementStatus.WrongBiome;
+ }
+ if (component.m_noClipping && TestGhostClipping(m_placementGhost, 0.2f))
+ {
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ }
+ else
+ {
+ if ((bool)m_placementMarkerInstance)
+ {
+ m_placementMarkerInstance.SetActive(value: false);
+ }
+ m_placementGhost.SetActive(value: false);
+ m_placementStatus = PlacementStatus.Invalid;
+ }
+ SetPlacementGhostValid(m_placementStatus == PlacementStatus.Valid);
+ }
+
+ private bool IsOverlapingOtherPiece(Vector3 p, string pieceName, List<Piece> pieces)
+ {
+ foreach (Piece tempPiece in m_tempPieces)
+ {
+ if (Vector3.Distance(p, tempPiece.transform.position) < 0.05f && tempPiece.gameObject.name.StartsWith(pieceName))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool FindClosestSnapPoints(Transform ghost, float maxSnapDistance, out Transform a, out Transform b, List<Piece> pieces)
+ {
+ m_tempSnapPoints1.Clear();
+ ghost.GetComponent<Piece>().GetSnapPoints(m_tempSnapPoints1);
+ m_tempSnapPoints2.Clear();
+ m_tempPieces.Clear();
+ Piece.GetSnapPoints(ghost.transform.position, 10f, m_tempSnapPoints2, m_tempPieces);
+ float num = 9999999f;
+ a = null;
+ b = null;
+ foreach (Transform item in m_tempSnapPoints1)
+ {
+ if (FindClosestSnappoint(item.position, m_tempSnapPoints2, maxSnapDistance, out var closest, out var distance) && distance < num)
+ {
+ num = distance;
+ a = item;
+ b = closest;
+ }
+ }
+ return a != null;
+ }
+
+ private bool FindClosestSnappoint(Vector3 p, List<Transform> snapPoints, float maxDistance, out Transform closest, out float distance)
+ {
+ closest = null;
+ distance = 999999f;
+ foreach (Transform snapPoint in snapPoints)
+ {
+ float num = Vector3.Distance(snapPoint.position, p);
+ if (!(num > maxDistance) && num < distance)
+ {
+ closest = snapPoint;
+ distance = num;
+ }
+ }
+ return closest != null;
+ }
+
+ private bool TestGhostClipping(GameObject ghost, float maxPenetration)
+ {
+ Collider[] componentsInChildren = ghost.GetComponentsInChildren<Collider>();
+ Collider[] array = Physics.OverlapSphere(ghost.transform.position, 10f, m_placeRayMask);
+ Collider[] array2 = componentsInChildren;
+ foreach (Collider collider in array2)
+ {
+ Collider[] array3 = array;
+ foreach (Collider collider2 in array3)
+ {
+ if (Physics.ComputePenetration(collider, collider.transform.position, collider.transform.rotation, collider2, collider2.transform.position, collider2.transform.rotation, out var _, out var distance) && distance > maxPenetration)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool CheckPlacementGhostVSPlayers()
+ {
+ if (m_placementGhost == null)
+ {
+ return false;
+ }
+ List<Character> list = new List<Character>();
+ Character.GetCharactersInRange(base.transform.position, 30f, list);
+ Collider[] componentsInChildren = m_placementGhost.GetComponentsInChildren<Collider>();
+ foreach (Collider collider in componentsInChildren)
+ {
+ if (collider.isTrigger || !collider.enabled)
+ {
+ continue;
+ }
+ MeshCollider meshCollider = collider as MeshCollider;
+ if (meshCollider != null && !meshCollider.convex)
+ {
+ continue;
+ }
+ foreach (Character item in list)
+ {
+ CapsuleCollider collider2 = item.GetCollider();
+ if (Physics.ComputePenetration(collider, collider.transform.position, collider.transform.rotation, collider2, collider2.transform.position, collider2.transform.rotation, out var _, out var _))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool PieceRayTest(out Vector3 point, out Vector3 normal, out Piece piece, out Heightmap heightmap, out Collider waterSurface, bool water)
+ {
+ int layerMask = m_placeRayMask;
+ if (water)
+ {
+ layerMask = m_placeWaterRayMask;
+ }
+ if (Physics.Raycast(GameCamera.instance.transform.position, GameCamera.instance.transform.forward, out var hitInfo, 50f, layerMask) && (bool)hitInfo.collider && !hitInfo.collider.attachedRigidbody && Vector3.Distance(m_eye.position, hitInfo.point) < m_maxPlaceDistance)
+ {
+ point = hitInfo.point;
+ normal = hitInfo.normal;
+ piece = hitInfo.collider.GetComponentInParent<Piece>();
+ heightmap = hitInfo.collider.GetComponent<Heightmap>();
+ if (hitInfo.collider.gameObject.layer == LayerMask.NameToLayer("Water"))
+ {
+ waterSurface = hitInfo.collider;
+ }
+ else
+ {
+ waterSurface = null;
+ }
+ return true;
+ }
+ point = Vector3.zero;
+ normal = Vector3.zero;
+ piece = null;
+ heightmap = null;
+ waterSurface = null;
+ return false;
+ }
+
+ private void FindHoverObject(out GameObject hover, out Character hoverCreature)
+ {
+ hover = null;
+ hoverCreature = null;
+ RaycastHit[] array = Physics.RaycastAll(GameCamera.instance.transform.position, GameCamera.instance.transform.forward, 50f, m_interactMask);
+ Array.Sort(array, (RaycastHit x, RaycastHit y) => x.distance.CompareTo(y.distance));
+ RaycastHit[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ RaycastHit raycastHit = array2[i];
+ if ((bool)raycastHit.collider.attachedRigidbody && raycastHit.collider.attachedRigidbody.gameObject == base.gameObject)
+ {
+ continue;
+ }
+ if (hoverCreature == null)
+ {
+ Character character = (raycastHit.collider.attachedRigidbody ? raycastHit.collider.attachedRigidbody.GetComponent<Character>() : raycastHit.collider.GetComponent<Character>());
+ if (character != null)
+ {
+ hoverCreature = character;
+ }
+ }
+ if (Vector3.Distance(m_eye.position, raycastHit.point) < m_maxInteractDistance)
+ {
+ if (raycastHit.collider.GetComponent<Hoverable>() != null)
+ {
+ hover = raycastHit.collider.gameObject;
+ }
+ else if ((bool)raycastHit.collider.attachedRigidbody)
+ {
+ hover = raycastHit.collider.attachedRigidbody.gameObject;
+ }
+ else
+ {
+ hover = raycastHit.collider.gameObject;
+ }
+ }
+ break;
+ }
+ }
+
+ private void Interact(GameObject go, bool hold)
+ {
+ if (InAttack() || InDodge() || (hold && Time.time - m_lastHoverInteractTime < 0.2f))
+ {
+ return;
+ }
+ Interactable componentInParent = go.GetComponentInParent<Interactable>();
+ if (componentInParent != null)
+ {
+ m_lastHoverInteractTime = Time.time;
+ if (componentInParent.Interact(this, hold))
+ {
+ Vector3 forward = go.transform.position - base.transform.position;
+ forward.y = 0f;
+ forward.Normalize();
+ base.transform.rotation = Quaternion.LookRotation(forward);
+ m_zanim.SetTrigger("interact");
+ }
+ }
+ }
+
+ private void UpdateStations(float dt)
+ {
+ m_stationDiscoverTimer += dt;
+ if (m_stationDiscoverTimer > 1f)
+ {
+ m_stationDiscoverTimer = 0f;
+ CraftingStation.UpdateKnownStationsInRange(this);
+ }
+ if (!(m_currentStation != null))
+ {
+ return;
+ }
+ if (!m_currentStation.InUseDistance(this))
+ {
+ InventoryGui.instance.Hide();
+ SetCraftingStation(null);
+ return;
+ }
+ if (!InventoryGui.IsVisible())
+ {
+ SetCraftingStation(null);
+ return;
+ }
+ m_currentStation.PokeInUse();
+ if ((bool)m_currentStation && !AlwaysRotateCamera())
+ {
+ Vector3 normalized = (m_currentStation.transform.position - base.transform.position).normalized;
+ normalized.y = 0f;
+ normalized.Normalize();
+ Quaternion to = Quaternion.LookRotation(normalized);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, to, m_turnSpeed * dt);
+ }
+ }
+
+ private void UpdateCover(float dt)
+ {
+ m_updateCoverTimer += dt;
+ if (m_updateCoverTimer > 1f)
+ {
+ m_updateCoverTimer = 0f;
+ Cover.GetCoverForPoint(GetCenterPoint(), out m_coverPercentage, out m_underRoof);
+ }
+ }
+
+ public Character GetHoverCreature()
+ {
+ return m_hoveringCreature;
+ }
+
+ public override GameObject GetHoverObject()
+ {
+ return m_hovering;
+ }
+
+ public override void OnNearFire(Vector3 point)
+ {
+ m_nearFireTimer = 0f;
+ }
+
+ public bool InShelter()
+ {
+ if (m_coverPercentage >= 0.8f)
+ {
+ return m_underRoof;
+ }
+ return false;
+ }
+
+ public float GetStamina()
+ {
+ return m_stamina;
+ }
+
+ public override float GetMaxStamina()
+ {
+ return m_maxStamina;
+ }
+
+ public override float GetStaminaPercentage()
+ {
+ return m_stamina / m_maxStamina;
+ }
+
+ public void SetGodMode(bool godMode)
+ {
+ m_godMode = godMode;
+ }
+
+ public override bool InGodMode()
+ {
+ return m_godMode;
+ }
+
+ public void SetGhostMode(bool ghostmode)
+ {
+ m_ghostMode = ghostmode;
+ }
+
+ public override bool InGhostMode()
+ {
+ return m_ghostMode;
+ }
+
+ public override bool IsDebugFlying()
+ {
+ if (m_nview.IsOwner())
+ {
+ return m_debugFly;
+ }
+ return m_nview.GetZDO().GetBool("DebugFly");
+ }
+
+ public override void AddStamina(float v)
+ {
+ m_stamina += v;
+ if (m_stamina > m_maxStamina)
+ {
+ m_stamina = m_maxStamina;
+ }
+ }
+
+ public override void UseStamina(float v)
+ {
+ if (v != 0f && m_nview.IsValid())
+ {
+ if (m_nview.IsOwner())
+ {
+ RPC_UseStamina(0L, v);
+ return;
+ }
+ m_nview.InvokeRPC("UseStamina", v);
+ }
+ }
+
+ private void RPC_UseStamina(long sender, float v)
+ {
+ if (v != 0f)
+ {
+ m_stamina -= v;
+ if (m_stamina < 0f)
+ {
+ m_stamina = 0f;
+ }
+ m_staminaRegenTimer = m_staminaRegenDelay;
+ }
+ }
+
+ public override bool HaveStamina(float amount = 0f)
+ {
+ if (m_nview.IsValid() && !m_nview.IsOwner())
+ {
+ return m_nview.GetZDO().GetFloat("stamina", m_maxStamina) > amount;
+ }
+ return m_stamina > amount;
+ }
+
+ public void Save(ZPackage pkg)
+ {
+ pkg.Write(24);
+ pkg.Write(GetMaxHealth());
+ pkg.Write(GetHealth());
+ pkg.Write(GetMaxStamina());
+ pkg.Write(m_firstSpawn);
+ pkg.Write(m_timeSinceDeath);
+ pkg.Write(m_guardianPower);
+ pkg.Write(m_guardianPowerCooldown);
+ m_inventory.Save(pkg);
+ pkg.Write(m_knownRecipes.Count);
+ foreach (string knownRecipe in m_knownRecipes)
+ {
+ pkg.Write(knownRecipe);
+ }
+ pkg.Write(m_knownStations.Count);
+ foreach (KeyValuePair<string, int> knownStation in m_knownStations)
+ {
+ pkg.Write(knownStation.Key);
+ pkg.Write(knownStation.Value);
+ }
+ pkg.Write(m_knownMaterial.Count);
+ foreach (string item in m_knownMaterial)
+ {
+ pkg.Write(item);
+ }
+ pkg.Write(m_shownTutorials.Count);
+ foreach (string shownTutorial in m_shownTutorials)
+ {
+ pkg.Write(shownTutorial);
+ }
+ pkg.Write(m_uniques.Count);
+ foreach (string unique in m_uniques)
+ {
+ pkg.Write(unique);
+ }
+ pkg.Write(m_trophies.Count);
+ foreach (string trophy in m_trophies)
+ {
+ pkg.Write(trophy);
+ }
+ pkg.Write(m_knownBiome.Count);
+ foreach (Heightmap.Biome item2 in m_knownBiome)
+ {
+ pkg.Write((int)item2);
+ }
+ pkg.Write(m_knownTexts.Count);
+ foreach (KeyValuePair<string, string> knownText in m_knownTexts)
+ {
+ pkg.Write(knownText.Key);
+ pkg.Write(knownText.Value);
+ }
+ pkg.Write(m_beardItem);
+ pkg.Write(m_hairItem);
+ pkg.Write(m_skinColor);
+ pkg.Write(m_hairColor);
+ pkg.Write(m_modelIndex);
+ pkg.Write(m_foods.Count);
+ foreach (Food food in m_foods)
+ {
+ pkg.Write(food.m_name);
+ pkg.Write(food.m_health);
+ pkg.Write(food.m_stamina);
+ }
+ m_skills.Save(pkg);
+ }
+
+ public void Load(ZPackage pkg)
+ {
+ m_isLoading = true;
+ UnequipAllItems();
+ int num = pkg.ReadInt();
+ if (num >= 7)
+ {
+ SetMaxHealth(pkg.ReadSingle(), flashBar: false);
+ }
+ float num2 = pkg.ReadSingle();
+ float maxHealth = GetMaxHealth();
+ if (num2 <= 0f || num2 > maxHealth || float.IsNaN(num2))
+ {
+ num2 = maxHealth;
+ }
+ SetHealth(num2);
+ if (num >= 10)
+ {
+ float stamina = pkg.ReadSingle();
+ SetMaxStamina(stamina, flashBar: false);
+ m_stamina = stamina;
+ }
+ if (num >= 8)
+ {
+ m_firstSpawn = pkg.ReadBool();
+ }
+ if (num >= 20)
+ {
+ m_timeSinceDeath = pkg.ReadSingle();
+ }
+ if (num >= 23)
+ {
+ string guardianPower = pkg.ReadString();
+ SetGuardianPower(guardianPower);
+ }
+ if (num >= 24)
+ {
+ m_guardianPowerCooldown = pkg.ReadSingle();
+ }
+ if (num == 2)
+ {
+ pkg.ReadZDOID();
+ }
+ m_inventory.Load(pkg);
+ int num3 = pkg.ReadInt();
+ for (int i = 0; i < num3; i++)
+ {
+ string item = pkg.ReadString();
+ m_knownRecipes.Add(item);
+ }
+ if (num < 15)
+ {
+ int num4 = pkg.ReadInt();
+ for (int j = 0; j < num4; j++)
+ {
+ pkg.ReadString();
+ }
+ }
+ else
+ {
+ int num5 = pkg.ReadInt();
+ for (int k = 0; k < num5; k++)
+ {
+ string key = pkg.ReadString();
+ int value = pkg.ReadInt();
+ m_knownStations.Add(key, value);
+ }
+ }
+ int num6 = pkg.ReadInt();
+ for (int l = 0; l < num6; l++)
+ {
+ string item2 = pkg.ReadString();
+ m_knownMaterial.Add(item2);
+ }
+ if (num < 19 || num >= 21)
+ {
+ int num7 = pkg.ReadInt();
+ for (int m = 0; m < num7; m++)
+ {
+ string item3 = pkg.ReadString();
+ m_shownTutorials.Add(item3);
+ }
+ }
+ if (num >= 6)
+ {
+ int num8 = pkg.ReadInt();
+ for (int n = 0; n < num8; n++)
+ {
+ string item4 = pkg.ReadString();
+ m_uniques.Add(item4);
+ }
+ }
+ if (num >= 9)
+ {
+ int num9 = pkg.ReadInt();
+ for (int num10 = 0; num10 < num9; num10++)
+ {
+ string item5 = pkg.ReadString();
+ m_trophies.Add(item5);
+ }
+ }
+ if (num >= 18)
+ {
+ int num11 = pkg.ReadInt();
+ for (int num12 = 0; num12 < num11; num12++)
+ {
+ Heightmap.Biome item6 = (Heightmap.Biome)pkg.ReadInt();
+ m_knownBiome.Add(item6);
+ }
+ }
+ if (num >= 22)
+ {
+ int num13 = pkg.ReadInt();
+ for (int num14 = 0; num14 < num13; num14++)
+ {
+ string key2 = pkg.ReadString();
+ string value2 = pkg.ReadString();
+ m_knownTexts.Add(key2, value2);
+ }
+ }
+ if (num >= 4)
+ {
+ string beard = pkg.ReadString();
+ string hair = pkg.ReadString();
+ SetBeard(beard);
+ SetHair(hair);
+ }
+ if (num >= 5)
+ {
+ Vector3 skinColor = pkg.ReadVector3();
+ Vector3 hairColor = pkg.ReadVector3();
+ SetSkinColor(skinColor);
+ SetHairColor(hairColor);
+ }
+ if (num >= 11)
+ {
+ int playerModel = pkg.ReadInt();
+ SetPlayerModel(playerModel);
+ }
+ if (num >= 12)
+ {
+ m_foods.Clear();
+ int num15 = pkg.ReadInt();
+ for (int num16 = 0; num16 < num15; num16++)
+ {
+ if (num >= 14)
+ {
+ Food food = new Food();
+ food.m_name = pkg.ReadString();
+ food.m_health = pkg.ReadSingle();
+ if (num >= 16)
+ {
+ food.m_stamina = pkg.ReadSingle();
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(food.m_name);
+ if (itemPrefab == null)
+ {
+ ZLog.LogWarning("FAiled to find food item " + food.m_name);
+ continue;
+ }
+ food.m_item = itemPrefab.GetComponent<ItemDrop>().m_itemData;
+ m_foods.Add(food);
+ }
+ else
+ {
+ pkg.ReadString();
+ pkg.ReadSingle();
+ pkg.ReadSingle();
+ pkg.ReadSingle();
+ pkg.ReadSingle();
+ pkg.ReadSingle();
+ pkg.ReadSingle();
+ if (num >= 13)
+ {
+ pkg.ReadSingle();
+ }
+ }
+ }
+ }
+ if (num >= 17)
+ {
+ m_skills.Load(pkg);
+ }
+ m_isLoading = false;
+ UpdateAvailablePiecesList();
+ EquipIventoryItems();
+ }
+
+ private void EquipIventoryItems()
+ {
+ foreach (ItemDrop.ItemData equipedtem in m_inventory.GetEquipedtems())
+ {
+ if (!EquipItem(equipedtem, triggerEquipEffects: false))
+ {
+ equipedtem.m_equiped = false;
+ }
+ }
+ }
+
+ public override bool CanMove()
+ {
+ if (m_teleporting)
+ {
+ return false;
+ }
+ if (InCutscene())
+ {
+ return false;
+ }
+ if (IsEncumbered() && !HaveStamina())
+ {
+ return false;
+ }
+ return base.CanMove();
+ }
+
+ public override bool IsEncumbered()
+ {
+ return m_inventory.GetTotalWeight() > GetMaxCarryWeight();
+ }
+
+ public float GetMaxCarryWeight()
+ {
+ float limit = m_maxCarryWeight;
+ m_seman.ModifyMaxCarryWeight(limit, ref limit);
+ return limit;
+ }
+
+ public override bool HaveUniqueKey(string name)
+ {
+ return m_uniques.Contains(name);
+ }
+
+ public override void AddUniqueKey(string name)
+ {
+ if (!m_uniques.Contains(name))
+ {
+ m_uniques.Add(name);
+ }
+ }
+
+ public bool IsBiomeKnown(Heightmap.Biome biome)
+ {
+ return m_knownBiome.Contains(biome);
+ }
+
+ public void AddKnownBiome(Heightmap.Biome biome)
+ {
+ if (!m_knownBiome.Contains(biome))
+ {
+ m_knownBiome.Add(biome);
+ if (biome != Heightmap.Biome.Meadows && biome != 0)
+ {
+ string text = "$biome_" + biome.ToString().ToLower();
+ MessageHud.instance.ShowBiomeFoundMsg(text, playStinger: true);
+ }
+ if (biome == Heightmap.Biome.BlackForest && !ZoneSystem.instance.GetGlobalKey("defeated_eikthyr"))
+ {
+ ShowTutorial("blackforest");
+ }
+ GoogleAnalyticsV4.instance.LogEvent("Game", "BiomeFound", biome.ToString(), 0L);
+ }
+ }
+
+ public bool IsRecipeKnown(string name)
+ {
+ return m_knownRecipes.Contains(name);
+ }
+
+ public void AddKnownRecipe(Recipe recipe)
+ {
+ if (!m_knownRecipes.Contains(recipe.m_item.m_itemData.m_shared.m_name))
+ {
+ m_knownRecipes.Add(recipe.m_item.m_itemData.m_shared.m_name);
+ MessageHud.instance.QueueUnlockMsg(recipe.m_item.m_itemData.GetIcon(), "$msg_newrecipe", recipe.m_item.m_itemData.m_shared.m_name);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "RecipeFound", recipe.m_item.m_itemData.m_shared.m_name, 0L);
+ }
+ }
+
+ public void AddKnownPiece(Piece piece)
+ {
+ if (!m_knownRecipes.Contains(piece.m_name))
+ {
+ m_knownRecipes.Add(piece.m_name);
+ MessageHud.instance.QueueUnlockMsg(piece.m_icon, "$msg_newpiece", piece.m_name);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "PieceFound", piece.m_name, 0L);
+ }
+ }
+
+ public void AddKnownStation(CraftingStation station)
+ {
+ int level = station.GetLevel();
+ if (m_knownStations.TryGetValue(station.m_name, out var value))
+ {
+ if (value < level)
+ {
+ m_knownStations[station.m_name] = level;
+ MessageHud.instance.QueueUnlockMsg(station.m_icon, "$msg_newstation_level", station.m_name + " $msg_level " + level);
+ UpdateKnownRecipesList();
+ }
+ }
+ else
+ {
+ m_knownStations.Add(station.m_name, level);
+ MessageHud.instance.QueueUnlockMsg(station.m_icon, "$msg_newstation", station.m_name);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "StationFound", station.m_name, 0L);
+ UpdateKnownRecipesList();
+ }
+ }
+
+ private bool KnowStationLevel(string name, int level)
+ {
+ if (m_knownStations.TryGetValue(name, out var value))
+ {
+ return value >= level;
+ }
+ return false;
+ }
+
+ public void AddKnownText(string label, string text)
+ {
+ if (label.Length == 0)
+ {
+ ZLog.LogWarning("Text " + text + " Is missing label");
+ }
+ else if (!m_knownTexts.ContainsKey(label))
+ {
+ m_knownTexts.Add(label, text);
+ Message(MessageHud.MessageType.TopLeft, Localization.instance.Localize("$msg_newtext", label), 0, m_textIcon);
+ }
+ }
+
+ public List<KeyValuePair<string, string>> GetKnownTexts()
+ {
+ return m_knownTexts.ToList();
+ }
+
+ public void AddKnownItem(ItemDrop.ItemData item)
+ {
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Trophie)
+ {
+ AddTrophie(item);
+ }
+ if (!m_knownMaterial.Contains(item.m_shared.m_name))
+ {
+ m_knownMaterial.Add(item.m_shared.m_name);
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Material)
+ {
+ MessageHud.instance.QueueUnlockMsg(item.GetIcon(), "$msg_newmaterial", item.m_shared.m_name);
+ }
+ else if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Trophie)
+ {
+ MessageHud.instance.QueueUnlockMsg(item.GetIcon(), "$msg_newtrophy", item.m_shared.m_name);
+ }
+ else
+ {
+ MessageHud.instance.QueueUnlockMsg(item.GetIcon(), "$msg_newitem", item.m_shared.m_name);
+ }
+ GoogleAnalyticsV4.instance.LogEvent("Game", "ItemFound", item.m_shared.m_name, 0L);
+ UpdateKnownRecipesList();
+ }
+ }
+
+ private void AddTrophie(ItemDrop.ItemData item)
+ {
+ if (item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Trophie && !m_trophies.Contains(item.m_dropPrefab.name))
+ {
+ m_trophies.Add(item.m_dropPrefab.name);
+ }
+ }
+
+ public List<string> GetTrophies()
+ {
+ List<string> list = new List<string>();
+ list.AddRange(m_trophies);
+ return list;
+ }
+
+ private void UpdateKnownRecipesList()
+ {
+ if (Game.instance == null)
+ {
+ return;
+ }
+ foreach (Recipe recipe in ObjectDB.instance.m_recipes)
+ {
+ if (recipe.m_enabled && !m_knownRecipes.Contains(recipe.m_item.m_itemData.m_shared.m_name) && HaveRequirements(recipe, discover: true, 0))
+ {
+ AddKnownRecipe(recipe);
+ }
+ }
+ m_tempOwnedPieceTables.Clear();
+ m_inventory.GetAllPieceTables(m_tempOwnedPieceTables);
+ bool flag = false;
+ foreach (PieceTable tempOwnedPieceTable in m_tempOwnedPieceTables)
+ {
+ foreach (GameObject piece in tempOwnedPieceTable.m_pieces)
+ {
+ Piece component = piece.GetComponent<Piece>();
+ if (component.m_enabled && !m_knownRecipes.Contains(component.m_name) && HaveRequirements(component, RequirementMode.IsKnown))
+ {
+ AddKnownPiece(component);
+ flag = true;
+ }
+ }
+ }
+ if (flag)
+ {
+ UpdateAvailablePiecesList();
+ }
+ }
+
+ private void UpdateAvailablePiecesList()
+ {
+ if (m_buildPieces != null)
+ {
+ m_buildPieces.UpdateAvailable(m_knownRecipes, this, m_hideUnavailable, m_noPlacementCost);
+ }
+ SetupPlacementGhost();
+ }
+
+ public override void Message(MessageHud.MessageType type, string msg, int amount = 0, Sprite icon = null)
+ {
+ if (m_nview == null || !m_nview.IsValid())
+ {
+ return;
+ }
+ if (m_nview.IsOwner())
+ {
+ if ((bool)MessageHud.instance)
+ {
+ MessageHud.instance.ShowMessage(type, msg, amount, icon);
+ }
+ }
+ else
+ {
+ m_nview.InvokeRPC("Message", (int)type, msg, amount);
+ }
+ }
+
+ private void RPC_Message(long sender, int type, string msg, int amount)
+ {
+ if (m_nview.IsOwner() && (bool)MessageHud.instance)
+ {
+ MessageHud.instance.ShowMessage((MessageHud.MessageType)type, msg, amount);
+ }
+ }
+
+ public static Player GetPlayer(long playerID)
+ {
+ foreach (Player player in m_players)
+ {
+ if (player.GetPlayerID() == playerID)
+ {
+ return player;
+ }
+ }
+ return null;
+ }
+
+ public static Player GetClosestPlayer(Vector3 point, float maxRange)
+ {
+ Player result = null;
+ float num = 999999f;
+ foreach (Player player in m_players)
+ {
+ float num2 = Vector3.Distance(player.transform.position, point);
+ if (num2 < num && num2 < maxRange)
+ {
+ num = num2;
+ result = player;
+ }
+ }
+ return result;
+ }
+
+ public static bool IsPlayerInRange(Vector3 point, float range, long playerID)
+ {
+ foreach (Player player in m_players)
+ {
+ if (player.GetPlayerID() == playerID)
+ {
+ return Utils.DistanceXZ(player.transform.position, point) < range;
+ }
+ }
+ return false;
+ }
+
+ public static void MessageAllInRange(Vector3 point, float range, MessageHud.MessageType type, string msg, Sprite icon = null)
+ {
+ foreach (Player player in m_players)
+ {
+ if (Vector3.Distance(player.transform.position, point) < range)
+ {
+ player.Message(type, msg, 0, icon);
+ }
+ }
+ }
+
+ public static int GetPlayersInRangeXZ(Vector3 point, float range)
+ {
+ int num = 0;
+ foreach (Player player in m_players)
+ {
+ if (Utils.DistanceXZ(player.transform.position, point) < range)
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ public static void GetPlayersInRange(Vector3 point, float range, List<Player> players)
+ {
+ foreach (Player player in m_players)
+ {
+ if (Vector3.Distance(player.transform.position, point) < range)
+ {
+ players.Add(player);
+ }
+ }
+ }
+
+ public static bool IsPlayerInRange(Vector3 point, float range)
+ {
+ foreach (Player player in m_players)
+ {
+ if (Vector3.Distance(player.transform.position, point) < range)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static bool IsPlayerInRange(Vector3 point, float range, float minNoise)
+ {
+ foreach (Player player in m_players)
+ {
+ if (Vector3.Distance(player.transform.position, point) < range)
+ {
+ float noiseRange = player.GetNoiseRange();
+ if (range <= noiseRange && noiseRange >= minNoise)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static Player GetPlayerNoiseRange(Vector3 point, float noiseRangeScale = 1f)
+ {
+ foreach (Player player in m_players)
+ {
+ float num = Vector3.Distance(player.transform.position, point);
+ float noiseRange = player.GetNoiseRange();
+ if (num < noiseRange * noiseRangeScale)
+ {
+ return player;
+ }
+ }
+ return null;
+ }
+
+ public static List<Player> GetAllPlayers()
+ {
+ return m_players;
+ }
+
+ public static Player GetRandomPlayer()
+ {
+ if (m_players.Count == 0)
+ {
+ return null;
+ }
+ return m_players[UnityEngine.Random.Range(0, m_players.Count)];
+ }
+
+ public void GetAvailableRecipes(ref List<Recipe> available)
+ {
+ available.Clear();
+ foreach (Recipe recipe in ObjectDB.instance.m_recipes)
+ {
+ if (recipe.m_enabled && (recipe.m_item.m_itemData.m_shared.m_dlc.Length <= 0 || DLCMan.instance.IsDLCInstalled(recipe.m_item.m_itemData.m_shared.m_dlc)) && (m_knownRecipes.Contains(recipe.m_item.m_itemData.m_shared.m_name) || m_noPlacementCost) && (RequiredCraftingStation(recipe, 1, checkLevel: false) || m_noPlacementCost))
+ {
+ available.Add(recipe);
+ }
+ }
+ }
+
+ private void OnInventoryChanged()
+ {
+ if (m_isLoading)
+ {
+ return;
+ }
+ foreach (ItemDrop.ItemData allItem in m_inventory.GetAllItems())
+ {
+ AddKnownItem(allItem);
+ if (allItem.m_shared.m_name == "$item_hammer")
+ {
+ ShowTutorial("hammer");
+ }
+ else if (allItem.m_shared.m_name == "$item_hoe")
+ {
+ ShowTutorial("hoe");
+ }
+ else if (allItem.m_shared.m_name == "$item_pickaxe_antler")
+ {
+ ShowTutorial("pickaxe");
+ }
+ if (allItem.m_shared.m_name == "$item_trophy_eikthyr")
+ {
+ ShowTutorial("boss_trophy");
+ }
+ if (allItem.m_shared.m_name == "$item_wishbone")
+ {
+ ShowTutorial("wishbone");
+ }
+ else if (allItem.m_shared.m_name == "$item_copperore" || allItem.m_shared.m_name == "$item_tinore")
+ {
+ ShowTutorial("ore");
+ }
+ else if (allItem.m_shared.m_food > 0f)
+ {
+ ShowTutorial("food");
+ }
+ }
+ UpdateKnownRecipesList();
+ UpdateAvailablePiecesList();
+ }
+
+ public bool InDebugFlyMode()
+ {
+ return m_debugFly;
+ }
+
+ public void ShowTutorial(string name, bool force = false)
+ {
+ if (!HaveSeenTutorial(name))
+ {
+ Tutorial.instance.ShowText(name, force);
+ }
+ }
+
+ public void SetSeenTutorial(string name)
+ {
+ if (name.Length != 0 && !m_shownTutorials.Contains(name))
+ {
+ m_shownTutorials.Add(name);
+ }
+ }
+
+ public bool HaveSeenTutorial(string name)
+ {
+ if (name.Length == 0)
+ {
+ return false;
+ }
+ return m_shownTutorials.Contains(name);
+ }
+
+ public static bool IsSeenTutorialsCleared()
+ {
+ if ((bool)m_localPlayer)
+ {
+ return m_localPlayer.m_shownTutorials.Count == 0;
+ }
+ return true;
+ }
+
+ public static void ResetSeenTutorials()
+ {
+ if ((bool)m_localPlayer)
+ {
+ m_localPlayer.m_shownTutorials.Clear();
+ }
+ }
+
+ public void SetMouseLook(Vector2 mouseLook)
+ {
+ m_lookYaw *= Quaternion.Euler(0f, mouseLook.x, 0f);
+ m_lookPitch = Mathf.Clamp(m_lookPitch - mouseLook.y, -89f, 89f);
+ UpdateEyeRotation();
+ m_lookDir = m_eye.forward;
+ }
+
+ protected override void UpdateEyeRotation()
+ {
+ m_eye.rotation = m_lookYaw * Quaternion.Euler(m_lookPitch, 0f, 0f);
+ }
+
+ public Ragdoll GetRagdoll()
+ {
+ return m_ragdoll;
+ }
+
+ public void OnDodgeMortal()
+ {
+ m_dodgeInvincible = false;
+ }
+
+ private void UpdateDodge(float dt)
+ {
+ m_queuedDodgeTimer -= dt;
+ if (m_queuedDodgeTimer > 0f && IsOnGround() && !IsDead() && !InAttack() && !IsEncumbered() && !InDodge())
+ {
+ float num = m_dodgeStaminaUsage - m_dodgeStaminaUsage * m_equipmentMovementModifier;
+ if (HaveStamina(num))
+ {
+ AbortEquipQueue();
+ m_queuedDodgeTimer = 0f;
+ m_dodgeInvincible = true;
+ base.transform.rotation = Quaternion.LookRotation(m_queuedDodgeDir);
+ m_body.rotation = base.transform.rotation;
+ m_zanim.SetTrigger("dodge");
+ AddNoise(5f);
+ UseStamina(num);
+ m_dodgeEffects.Create(base.transform.position, Quaternion.identity, base.transform);
+ }
+ else
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ }
+ AnimatorStateInfo currentAnimatorStateInfo = m_animator.GetCurrentAnimatorStateInfo(0);
+ AnimatorStateInfo nextAnimatorStateInfo = m_animator.GetNextAnimatorStateInfo(0);
+ bool flag = m_animator.IsInTransition(0);
+ bool flag2 = (currentAnimatorStateInfo.tagHash == m_animatorTagDodge && !flag) || (flag && nextAnimatorStateInfo.tagHash == m_animatorTagDodge);
+ bool value = flag2 && m_dodgeInvincible;
+ m_nview.GetZDO().Set("dodgeinv", value);
+ m_inDodge = flag2;
+ }
+
+ public override bool IsDodgeInvincible()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetBool("dodgeinv");
+ }
+
+ public override bool InDodge()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return false;
+ }
+ return m_inDodge;
+ }
+
+ public override bool IsDead()
+ {
+ return m_nview.GetZDO()?.GetBool("dead") ?? false;
+ }
+
+ protected void Dodge(Vector3 dodgeDir)
+ {
+ m_queuedDodgeTimer = 0.5f;
+ m_queuedDodgeDir = dodgeDir;
+ }
+
+ public override bool AlwaysRotateCamera()
+ {
+ if ((GetCurrentWeapon() != null && m_currentAttack != null && m_lastCombatTimer < 1f && m_currentAttack.m_attackType != Attack.AttackType.None && ZInput.IsMouseActive()) || IsHoldingAttack() || m_blocking)
+ {
+ return true;
+ }
+ if (InPlaceMode())
+ {
+ Vector3 from = GetLookYaw() * Vector3.forward;
+ Vector3 forward = base.transform.forward;
+ if (Vector3.Angle(from, forward) > 90f)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override bool TeleportTo(Vector3 pos, Quaternion rot, bool distantTeleport)
+ {
+ if (IsTeleporting())
+ {
+ return false;
+ }
+ if (m_teleportCooldown < 2f)
+ {
+ return false;
+ }
+ m_teleporting = true;
+ m_distantTeleport = distantTeleport;
+ m_teleportTimer = 0f;
+ m_teleportCooldown = 0f;
+ m_teleportFromPos = base.transform.position;
+ m_teleportFromRot = base.transform.rotation;
+ m_teleportTargetPos = pos;
+ m_teleportTargetRot = rot;
+ return true;
+ }
+
+ private void UpdateTeleport(float dt)
+ {
+ if (!m_teleporting)
+ {
+ m_teleportCooldown += dt;
+ return;
+ }
+ m_teleportCooldown = 0f;
+ m_teleportTimer += dt;
+ if (!(m_teleportTimer > 2f))
+ {
+ return;
+ }
+ Vector3 lookDir = m_teleportTargetRot * Vector3.forward;
+ base.transform.position = m_teleportTargetPos;
+ base.transform.rotation = m_teleportTargetRot;
+ m_body.velocity = Vector3.zero;
+ m_maxAirAltitude = base.transform.position.y;
+ SetLookDir(lookDir);
+ if ((!(m_teleportTimer > 8f) && m_distantTeleport) || !ZNetScene.instance.IsAreaReady(m_teleportTargetPos))
+ {
+ return;
+ }
+ float height = 0f;
+ if (ZoneSystem.instance.FindFloor(m_teleportTargetPos, out height))
+ {
+ m_teleportTimer = 0f;
+ m_teleporting = false;
+ ResetCloth();
+ }
+ else if (m_teleportTimer > 15f || !m_distantTeleport)
+ {
+ if (m_distantTeleport)
+ {
+ Vector3 position = base.transform.position;
+ position.y = ZoneSystem.instance.GetSolidHeight(m_teleportTargetPos) + 0.5f;
+ base.transform.position = position;
+ }
+ else
+ {
+ base.transform.rotation = m_teleportFromRot;
+ base.transform.position = m_teleportFromPos;
+ m_maxAirAltitude = base.transform.position.y;
+ Message(MessageHud.MessageType.Center, "$msg_portal_blocked");
+ }
+ m_teleportTimer = 0f;
+ m_teleporting = false;
+ ResetCloth();
+ }
+ }
+
+ public override bool IsTeleporting()
+ {
+ return m_teleporting;
+ }
+
+ public bool ShowTeleportAnimation()
+ {
+ if (m_teleporting)
+ {
+ return m_distantTeleport;
+ }
+ return false;
+ }
+
+ public void SetPlayerModel(int index)
+ {
+ if (m_modelIndex != index)
+ {
+ m_modelIndex = index;
+ m_visEquipment.SetModel(index);
+ }
+ }
+
+ public int GetPlayerModel()
+ {
+ return m_modelIndex;
+ }
+
+ public void SetSkinColor(Vector3 color)
+ {
+ if (!(color == m_skinColor))
+ {
+ m_skinColor = color;
+ m_visEquipment.SetSkinColor(m_skinColor);
+ }
+ }
+
+ public void SetHairColor(Vector3 color)
+ {
+ if (!(m_hairColor == color))
+ {
+ m_hairColor = color;
+ m_visEquipment.SetHairColor(m_hairColor);
+ }
+ }
+
+ protected override void SetupVisEquipment(VisEquipment visEq, bool isRagdoll)
+ {
+ base.SetupVisEquipment(visEq, isRagdoll);
+ visEq.SetModel(m_modelIndex);
+ visEq.SetSkinColor(m_skinColor);
+ visEq.SetHairColor(m_hairColor);
+ }
+
+ public override bool CanConsumeItem(ItemDrop.ItemData item)
+ {
+ if (item.m_shared.m_itemType != ItemDrop.ItemData.ItemType.Consumable)
+ {
+ return false;
+ }
+ if (item.m_shared.m_food > 0f && !CanEat(item, showMessages: true))
+ {
+ return false;
+ }
+ if ((bool)item.m_shared.m_consumeStatusEffect)
+ {
+ StatusEffect consumeStatusEffect = item.m_shared.m_consumeStatusEffect;
+ if (m_seman.HaveStatusEffect(item.m_shared.m_consumeStatusEffect.name) || m_seman.HaveStatusEffectCategory(consumeStatusEffect.m_category))
+ {
+ Message(MessageHud.MessageType.Center, "$msg_cantconsume");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public override bool ConsumeItem(Inventory inventory, ItemDrop.ItemData item)
+ {
+ if (!CanConsumeItem(item))
+ {
+ return false;
+ }
+ if ((bool)item.m_shared.m_consumeStatusEffect)
+ {
+ _ = item.m_shared.m_consumeStatusEffect;
+ m_seman.AddStatusEffect(item.m_shared.m_consumeStatusEffect, resetTime: true);
+ }
+ if (item.m_shared.m_food > 0f)
+ {
+ EatFood(item);
+ }
+ inventory.RemoveOneItem(item);
+ return true;
+ }
+
+ public void SetIntro(bool intro)
+ {
+ if (m_intro != intro)
+ {
+ m_intro = intro;
+ m_zanim.SetBool("intro", intro);
+ }
+ }
+
+ public override bool InIntro()
+ {
+ return m_intro;
+ }
+
+ public override bool InCutscene()
+ {
+ if (m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagCutscene)
+ {
+ return true;
+ }
+ if (InIntro())
+ {
+ return true;
+ }
+ if (m_sleeping)
+ {
+ return true;
+ }
+ return base.InCutscene();
+ }
+
+ public void SetMaxStamina(float stamina, bool flashBar)
+ {
+ if (flashBar && Hud.instance != null && stamina > m_maxStamina)
+ {
+ Hud.instance.StaminaBarUppgradeFlash();
+ }
+ m_maxStamina = stamina;
+ m_stamina = Mathf.Clamp(m_stamina, 0f, m_maxStamina);
+ }
+
+ public void SetMaxHealth(float health, bool flashBar)
+ {
+ if (flashBar && Hud.instance != null && health > GetMaxHealth())
+ {
+ Hud.instance.FlashHealthBar();
+ }
+ SetMaxHealth(health);
+ }
+
+ public override bool IsPVPEnabled()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_pvp;
+ }
+ return m_nview.GetZDO().GetBool("pvp");
+ }
+
+ public void SetPVP(bool enabled)
+ {
+ if (m_pvp != enabled)
+ {
+ m_pvp = enabled;
+ m_nview.GetZDO().Set("pvp", m_pvp);
+ if (m_pvp)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_pvpon");
+ }
+ else
+ {
+ Message(MessageHud.MessageType.Center, "$msg_pvpoff");
+ }
+ }
+ }
+
+ public bool CanSwitchPVP()
+ {
+ return m_lastCombatTimer > 10f;
+ }
+
+ public bool NoCostCheat()
+ {
+ return m_noPlacementCost;
+ }
+
+ public void StartEmote(string emote, bool oneshot = true)
+ {
+ if (CanMove() && !InAttack() && !IsHoldingAttack())
+ {
+ SetCrouch(crouch: false);
+ int @int = m_nview.GetZDO().GetInt("emoteID");
+ m_nview.GetZDO().Set("emoteID", @int + 1);
+ m_nview.GetZDO().Set("emote", emote);
+ m_nview.GetZDO().Set("emote_oneshot", oneshot);
+ }
+ }
+
+ protected override void StopEmote()
+ {
+ if (m_nview.GetZDO().GetString("emote") != "")
+ {
+ int @int = m_nview.GetZDO().GetInt("emoteID");
+ m_nview.GetZDO().Set("emoteID", @int + 1);
+ m_nview.GetZDO().Set("emote", "");
+ }
+ }
+
+ private void UpdateEmote()
+ {
+ if (m_nview.IsOwner() && InEmote() && m_moveDir != Vector3.zero)
+ {
+ StopEmote();
+ }
+ int @int = m_nview.GetZDO().GetInt("emoteID");
+ if (@int == m_emoteID)
+ {
+ return;
+ }
+ m_emoteID = @int;
+ if (!string.IsNullOrEmpty(m_emoteState))
+ {
+ m_animator.SetBool("emote_" + m_emoteState, value: false);
+ }
+ m_emoteState = "";
+ m_animator.SetTrigger("emote_stop");
+ string @string = m_nview.GetZDO().GetString("emote");
+ if (!string.IsNullOrEmpty(@string))
+ {
+ bool @bool = m_nview.GetZDO().GetBool("emote_oneshot");
+ m_animator.ResetTrigger("emote_stop");
+ if (@bool)
+ {
+ m_animator.SetTrigger("emote_" + @string);
+ return;
+ }
+ m_emoteState = @string;
+ m_animator.SetBool("emote_" + @string, value: true);
+ }
+ }
+
+ public override bool InEmote()
+ {
+ if (!string.IsNullOrEmpty(m_emoteState))
+ {
+ return true;
+ }
+ return m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagEmote;
+ }
+
+ public override bool IsCrouching()
+ {
+ return m_animator.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagCrouch;
+ }
+
+ private void UpdateCrouch(float dt)
+ {
+ if (m_crouchToggled)
+ {
+ if (!HaveStamina() || IsSwiming() || InBed() || InPlaceMode() || m_run || IsBlocking() || IsFlying())
+ {
+ SetCrouch(crouch: false);
+ }
+ bool flag = InAttack() || IsHoldingAttack();
+ m_zanim.SetBool(crouching, m_crouchToggled && !flag);
+ }
+ else
+ {
+ m_zanim.SetBool(crouching, value: false);
+ }
+ }
+
+ protected override void SetCrouch(bool crouch)
+ {
+ if (m_crouchToggled != crouch)
+ {
+ m_crouchToggled = crouch;
+ }
+ }
+
+ public void SetGuardianPower(string name)
+ {
+ m_guardianPower = name;
+ m_guardianSE = ObjectDB.instance.GetStatusEffect(m_guardianPower);
+ }
+
+ public string GetGuardianPowerName()
+ {
+ return m_guardianPower;
+ }
+
+ public void GetGuardianPowerHUD(out StatusEffect se, out float cooldown)
+ {
+ se = m_guardianSE;
+ cooldown = m_guardianPowerCooldown;
+ }
+
+ public bool StartGuardianPower()
+ {
+ if (m_guardianSE == null)
+ {
+ return false;
+ }
+ if ((InAttack() && !HaveQueuedChain()) || InDodge() || !CanMove() || IsKnockedBack() || IsStaggering() || InMinorAction())
+ {
+ return false;
+ }
+ if (m_guardianPowerCooldown > 0f)
+ {
+ Message(MessageHud.MessageType.Center, "$hud_powernotready");
+ return false;
+ }
+ m_zanim.SetTrigger("gpower");
+ return true;
+ }
+
+ public bool ActivateGuardianPower()
+ {
+ if (m_guardianPowerCooldown > 0f)
+ {
+ return false;
+ }
+ if (m_guardianSE == null)
+ {
+ return false;
+ }
+ List<Player> list = new List<Player>();
+ GetPlayersInRange(base.transform.position, 10f, list);
+ foreach (Player item in list)
+ {
+ item.GetSEMan().AddStatusEffect(m_guardianSE.name, resetTime: true);
+ }
+ m_guardianPowerCooldown = m_guardianSE.m_cooldown;
+ return false;
+ }
+
+ private void UpdateGuardianPower(float dt)
+ {
+ m_guardianPowerCooldown -= dt;
+ if (m_guardianPowerCooldown < 0f)
+ {
+ m_guardianPowerCooldown = 0f;
+ }
+ }
+
+ public override void AttachStart(Transform attachPoint, bool hideWeapons, bool isBed, string attachAnimation, Vector3 detachOffset)
+ {
+ if (!m_attached)
+ {
+ m_attached = true;
+ m_attachPoint = attachPoint;
+ m_detachOffset = detachOffset;
+ m_attachAnimation = attachAnimation;
+ m_zanim.SetBool(attachAnimation, value: true);
+ m_nview.GetZDO().Set("inBed", isBed);
+ if (hideWeapons)
+ {
+ HideHandItems();
+ }
+ ResetCloth();
+ }
+ }
+
+ private void UpdateAttach()
+ {
+ if (m_attached)
+ {
+ if (m_attachPoint != null)
+ {
+ base.transform.position = m_attachPoint.position;
+ base.transform.rotation = m_attachPoint.rotation;
+ Rigidbody componentInParent = m_attachPoint.GetComponentInParent<Rigidbody>();
+ m_body.useGravity = false;
+ m_body.velocity = (componentInParent ? componentInParent.GetPointVelocity(base.transform.position) : Vector3.zero);
+ m_body.angularVelocity = Vector3.zero;
+ m_maxAirAltitude = base.transform.position.y;
+ }
+ else
+ {
+ AttachStop();
+ }
+ }
+ }
+
+ public override bool IsAttached()
+ {
+ return m_attached;
+ }
+
+ public override bool InBed()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetBool("inBed");
+ }
+
+ public override void AttachStop()
+ {
+ if (!m_sleeping && m_attached)
+ {
+ if (m_attachPoint != null)
+ {
+ base.transform.position = m_attachPoint.TransformPoint(m_detachOffset);
+ }
+ m_body.useGravity = true;
+ m_attached = false;
+ m_attachPoint = null;
+ m_zanim.SetBool(m_attachAnimation, value: false);
+ m_nview.GetZDO().Set("inBed", value: false);
+ ResetCloth();
+ }
+ }
+
+ public void StartShipControl(ShipControlls shipControl)
+ {
+ m_shipControl = shipControl;
+ ZLog.Log("ship controlls set " + shipControl.GetShip().gameObject.name);
+ }
+
+ public void StopShipControl()
+ {
+ if (m_shipControl != null)
+ {
+ if ((bool)m_shipControl)
+ {
+ m_shipControl.OnUseStop(this);
+ }
+ ZLog.Log("Stop ship controlls");
+ m_shipControl = null;
+ }
+ }
+
+ private void SetShipControl(ref Vector3 moveDir)
+ {
+ m_shipControl.GetShip().ApplyMovementControlls(moveDir);
+ moveDir = Vector3.zero;
+ }
+
+ public Ship GetControlledShip()
+ {
+ if ((bool)m_shipControl)
+ {
+ return m_shipControl.GetShip();
+ }
+ return null;
+ }
+
+ public ShipControlls GetShipControl()
+ {
+ return m_shipControl;
+ }
+
+ private void UpdateShipControl(float dt)
+ {
+ if ((bool)m_shipControl)
+ {
+ Vector3 forward = m_shipControl.GetShip().transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ Quaternion to = Quaternion.LookRotation(forward);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, to, 100f * dt);
+ if (Vector3.Distance(m_shipControl.transform.position, base.transform.position) > m_maxInteractDistance)
+ {
+ StopShipControl();
+ }
+ }
+ }
+
+ public bool IsSleeping()
+ {
+ return m_sleeping;
+ }
+
+ public void SetSleeping(bool sleep)
+ {
+ if (m_sleeping != sleep)
+ {
+ m_sleeping = sleep;
+ if (!sleep)
+ {
+ Message(MessageHud.MessageType.Center, "$msg_goodmorning");
+ m_seman.AddStatusEffect("Rested", resetTime: true);
+ }
+ }
+ }
+
+ public void SetControls(Vector3 movedir, bool attack, bool attackHold, bool secondaryAttack, bool block, bool blockHold, bool jump, bool crouch, bool run, bool autoRun)
+ {
+ if ((movedir != Vector3.zero || attack || secondaryAttack || block || blockHold || jump || crouch) && GetControlledShip() == null)
+ {
+ StopEmote();
+ AttachStop();
+ }
+ if ((bool)m_shipControl)
+ {
+ SetShipControl(ref movedir);
+ if (jump)
+ {
+ StopShipControl();
+ }
+ }
+ if (run)
+ {
+ m_walk = false;
+ }
+ if (!m_autoRun)
+ {
+ Vector3 lookDir = m_lookDir;
+ lookDir.y = 0f;
+ lookDir.Normalize();
+ m_moveDir = movedir.z * lookDir + movedir.x * Vector3.Cross(Vector3.up, lookDir);
+ }
+ if (!m_autoRun && autoRun && !InPlaceMode())
+ {
+ m_autoRun = true;
+ SetCrouch(crouch: false);
+ m_moveDir = m_lookDir;
+ m_moveDir.y = 0f;
+ m_moveDir.Normalize();
+ }
+ else if (m_autoRun)
+ {
+ if (attack || jump || crouch || movedir != Vector3.zero || InPlaceMode() || attackHold)
+ {
+ m_autoRun = false;
+ }
+ else if (autoRun || blockHold)
+ {
+ m_moveDir = m_lookDir;
+ m_moveDir.y = 0f;
+ m_moveDir.Normalize();
+ blockHold = false;
+ block = false;
+ }
+ }
+ m_attack = attack;
+ m_attackDraw = attackHold;
+ m_secondaryAttack = secondaryAttack;
+ m_blocking = blockHold;
+ m_run = run;
+ if (crouch)
+ {
+ SetCrouch(!m_crouchToggled);
+ }
+ if (!jump)
+ {
+ return;
+ }
+ if (m_blocking)
+ {
+ Vector3 dodgeDir = m_moveDir;
+ if (dodgeDir.magnitude < 0.1f)
+ {
+ dodgeDir = -m_lookDir;
+ dodgeDir.y = 0f;
+ dodgeDir.Normalize();
+ }
+ Dodge(dodgeDir);
+ }
+ else if (IsCrouching() || m_crouchToggled)
+ {
+ Vector3 dodgeDir2 = m_moveDir;
+ if (dodgeDir2.magnitude < 0.1f)
+ {
+ dodgeDir2 = m_lookDir;
+ dodgeDir2.y = 0f;
+ dodgeDir2.Normalize();
+ }
+ Dodge(dodgeDir2);
+ }
+ else
+ {
+ Jump();
+ }
+ }
+
+ private void UpdateTargeted(float dt)
+ {
+ m_timeSinceTargeted += dt;
+ m_timeSinceSensed += dt;
+ }
+
+ public override void OnTargeted(bool sensed, bool alerted)
+ {
+ if (sensed)
+ {
+ if (m_timeSinceSensed > 0.5f)
+ {
+ m_timeSinceSensed = 0f;
+ m_nview.InvokeRPC("OnTargeted", sensed, alerted);
+ }
+ }
+ else if (m_timeSinceTargeted > 0.5f)
+ {
+ m_timeSinceTargeted = 0f;
+ m_nview.InvokeRPC("OnTargeted", sensed, alerted);
+ }
+ }
+
+ private void RPC_OnTargeted(long sender, bool sensed, bool alerted)
+ {
+ m_timeSinceTargeted = 0f;
+ if (sensed)
+ {
+ m_timeSinceSensed = 0f;
+ }
+ if (alerted)
+ {
+ MusicMan.instance.ResetCombatTimer();
+ }
+ }
+
+ protected override void OnDamaged(HitData hit)
+ {
+ base.OnDamaged(hit);
+ Hud.instance.DamageFlash();
+ }
+
+ public bool IsTargeted()
+ {
+ return m_timeSinceTargeted < 1f;
+ }
+
+ public bool IsSensed()
+ {
+ return m_timeSinceSensed < 1f;
+ }
+
+ protected override void ApplyArmorDamageMods(ref HitData.DamageModifiers mods)
+ {
+ if (m_chestItem != null)
+ {
+ mods.Apply(m_chestItem.m_shared.m_damageModifiers);
+ }
+ if (m_legItem != null)
+ {
+ mods.Apply(m_legItem.m_shared.m_damageModifiers);
+ }
+ if (m_helmetItem != null)
+ {
+ mods.Apply(m_helmetItem.m_shared.m_damageModifiers);
+ }
+ if (m_shoulderItem != null)
+ {
+ mods.Apply(m_shoulderItem.m_shared.m_damageModifiers);
+ }
+ }
+
+ public override float GetBodyArmor()
+ {
+ float num = 0f;
+ if (m_chestItem != null)
+ {
+ num += m_chestItem.GetArmor();
+ }
+ if (m_legItem != null)
+ {
+ num += m_legItem.GetArmor();
+ }
+ if (m_helmetItem != null)
+ {
+ num += m_helmetItem.GetArmor();
+ }
+ if (m_shoulderItem != null)
+ {
+ num += m_shoulderItem.GetArmor();
+ }
+ return num;
+ }
+
+ protected override void OnSneaking(float dt)
+ {
+ float t = Mathf.Pow(m_skills.GetSkillFactor(Skills.SkillType.Sneak), 0.5f);
+ float num = Mathf.Lerp(1f, 0.25f, t);
+ UseStamina(dt * m_sneakStaminaDrain * num);
+ if (!HaveStamina())
+ {
+ Hud.instance.StaminaBarNoStaminaFlash();
+ }
+ m_sneakSkillImproveTimer += dt;
+ if (m_sneakSkillImproveTimer > 1f)
+ {
+ m_sneakSkillImproveTimer = 0f;
+ if (BaseAI.InStealthRange(this))
+ {
+ RaiseSkill(Skills.SkillType.Sneak);
+ }
+ else
+ {
+ RaiseSkill(Skills.SkillType.Sneak, 0.1f);
+ }
+ }
+ }
+
+ private void UpdateStealth(float dt)
+ {
+ m_stealthFactorUpdateTimer += dt;
+ if (m_stealthFactorUpdateTimer > 0.5f)
+ {
+ m_stealthFactorUpdateTimer = 0f;
+ m_stealthFactorTarget = 0f;
+ if (IsCrouching())
+ {
+ m_lastStealthPosition = base.transform.position;
+ float skillFactor = m_skills.GetSkillFactor(Skills.SkillType.Sneak);
+ float lightFactor = StealthSystem.instance.GetLightFactor(GetCenterPoint());
+ m_stealthFactorTarget = Mathf.Lerp(0.25f + lightFactor * 0.75f, lightFactor * 0.3f, skillFactor);
+ m_stealthFactorTarget = Mathf.Clamp01(m_stealthFactorTarget);
+ m_seman.ModifyStealth(m_stealthFactorTarget, ref m_stealthFactorTarget);
+ m_stealthFactorTarget = Mathf.Clamp01(m_stealthFactorTarget);
+ }
+ else
+ {
+ m_stealthFactorTarget = 1f;
+ }
+ }
+ m_stealthFactor = Mathf.MoveTowards(m_stealthFactor, m_stealthFactorTarget, dt / 4f);
+ m_nview.GetZDO().Set("Stealth", m_stealthFactor);
+ }
+
+ public override float GetStealthFactor()
+ {
+ if (!m_nview.IsValid())
+ {
+ return 0f;
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_stealthFactor;
+ }
+ return m_nview.GetZDO().GetFloat("Stealth");
+ }
+
+ public override bool InAttack()
+ {
+ if (m_animator.IsInTransition(0))
+ {
+ if (m_animator.GetNextAnimatorStateInfo(0).tagHash == Humanoid.m_animatorTagAttack)
+ {
+ return true;
+ }
+ if (m_animator.GetNextAnimatorStateInfo(1).tagHash == Humanoid.m_animatorTagAttack)
+ {
+ return true;
+ }
+ return false;
+ }
+ if (m_animator.GetCurrentAnimatorStateInfo(0).tagHash == Humanoid.m_animatorTagAttack)
+ {
+ return true;
+ }
+ if (m_animator.GetCurrentAnimatorStateInfo(1).tagHash == Humanoid.m_animatorTagAttack)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public override float GetEquipmentMovementModifier()
+ {
+ return m_equipmentMovementModifier;
+ }
+
+ protected override float GetJogSpeedFactor()
+ {
+ return 1f + m_equipmentMovementModifier;
+ }
+
+ protected override float GetRunSpeedFactor()
+ {
+ float skillFactor = m_skills.GetSkillFactor(Skills.SkillType.Run);
+ return (1f + skillFactor * 0.25f) * (1f + m_equipmentMovementModifier * 1.5f);
+ }
+
+ public override bool InMinorAction()
+ {
+ return (m_animator.IsInTransition(1) ? m_animator.GetNextAnimatorStateInfo(1) : m_animator.GetCurrentAnimatorStateInfo(1)).tagHash == m_animatorTagMinorAction;
+ }
+
+ public override bool GetRelativePosition(out ZDOID parent, out Vector3 relativePos, out Vector3 relativeVel)
+ {
+ if (m_attached && (bool)m_attachPoint)
+ {
+ ZNetView componentInParent = m_attachPoint.GetComponentInParent<ZNetView>();
+ if ((bool)componentInParent && componentInParent.IsValid())
+ {
+ parent = componentInParent.GetZDO().m_uid;
+ relativePos = componentInParent.transform.InverseTransformPoint(base.transform.position);
+ relativeVel = Vector3.zero;
+ return true;
+ }
+ }
+ return base.GetRelativePosition(out parent, out relativePos, out relativeVel);
+ }
+
+ public override Skills GetSkills()
+ {
+ return m_skills;
+ }
+
+ public override float GetRandomSkillFactor(Skills.SkillType skill)
+ {
+ return m_skills.GetRandomSkillFactor(skill);
+ }
+
+ public override float GetSkillFactor(Skills.SkillType skill)
+ {
+ return m_skills.GetSkillFactor(skill);
+ }
+
+ protected override void DoDamageCameraShake(HitData hit)
+ {
+ if ((bool)GameCamera.instance && hit.GetTotalPhysicalDamage() > 0f)
+ {
+ float num = Mathf.Clamp01(hit.GetTotalPhysicalDamage() / GetMaxHealth());
+ GameCamera.instance.AddShake(base.transform.position, 50f, m_baseCameraShake * num, continous: false);
+ }
+ }
+
+ protected override bool ToggleEquiped(ItemDrop.ItemData item)
+ {
+ if (item.IsEquipable())
+ {
+ if (InAttack())
+ {
+ return true;
+ }
+ if (item.m_shared.m_equipDuration <= 0f)
+ {
+ if (IsItemEquiped(item))
+ {
+ UnequipItem(item);
+ }
+ else
+ {
+ EquipItem(item);
+ }
+ }
+ else if (IsItemEquiped(item))
+ {
+ QueueUnequipItem(item);
+ }
+ else
+ {
+ QueueEquipItem(item);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void GetActionProgress(out string name, out float progress)
+ {
+ if (m_equipQueue.Count > 0)
+ {
+ EquipQueueData equipQueueData = m_equipQueue[0];
+ if (equipQueueData.m_duration > 0.5f)
+ {
+ if (equipQueueData.m_equip)
+ {
+ name = "$hud_equipping " + equipQueueData.m_item.m_shared.m_name;
+ }
+ else
+ {
+ name = "$hud_unequipping " + equipQueueData.m_item.m_shared.m_name;
+ }
+ progress = Mathf.Clamp01(equipQueueData.m_time / equipQueueData.m_duration);
+ return;
+ }
+ }
+ name = null;
+ progress = 0f;
+ }
+
+ private void UpdateEquipQueue(float dt)
+ {
+ if (m_equipQueuePause > 0f)
+ {
+ m_equipQueuePause -= dt;
+ m_zanim.SetBool("equipping", value: false);
+ return;
+ }
+ m_zanim.SetBool("equipping", m_equipQueue.Count > 0);
+ if (m_equipQueue.Count == 0)
+ {
+ return;
+ }
+ EquipQueueData equipQueueData = m_equipQueue[0];
+ if (equipQueueData.m_time == 0f && equipQueueData.m_duration >= 1f)
+ {
+ m_equipStartEffects.Create(base.transform.position, Quaternion.identity);
+ }
+ equipQueueData.m_time += dt;
+ if (equipQueueData.m_time > equipQueueData.m_duration)
+ {
+ m_equipQueue.RemoveAt(0);
+ if (equipQueueData.m_equip)
+ {
+ EquipItem(equipQueueData.m_item);
+ }
+ else
+ {
+ UnequipItem(equipQueueData.m_item);
+ }
+ m_equipQueuePause = 0.3f;
+ }
+ }
+
+ private void QueueEquipItem(ItemDrop.ItemData item)
+ {
+ if (item != null)
+ {
+ if (IsItemQueued(item))
+ {
+ RemoveFromEquipQueue(item);
+ return;
+ }
+ EquipQueueData equipQueueData = new EquipQueueData();
+ equipQueueData.m_item = item;
+ equipQueueData.m_equip = true;
+ equipQueueData.m_duration = item.m_shared.m_equipDuration;
+ m_equipQueue.Add(equipQueueData);
+ }
+ }
+
+ private void QueueUnequipItem(ItemDrop.ItemData item)
+ {
+ if (item != null)
+ {
+ if (IsItemQueued(item))
+ {
+ RemoveFromEquipQueue(item);
+ return;
+ }
+ EquipQueueData equipQueueData = new EquipQueueData();
+ equipQueueData.m_item = item;
+ equipQueueData.m_equip = false;
+ equipQueueData.m_duration = item.m_shared.m_equipDuration;
+ m_equipQueue.Add(equipQueueData);
+ }
+ }
+
+ public override void AbortEquipQueue()
+ {
+ m_equipQueue.Clear();
+ }
+
+ public override void RemoveFromEquipQueue(ItemDrop.ItemData item)
+ {
+ if (item == null)
+ {
+ return;
+ }
+ foreach (EquipQueueData item2 in m_equipQueue)
+ {
+ if (item2.m_item == item)
+ {
+ m_equipQueue.Remove(item2);
+ break;
+ }
+ }
+ }
+
+ public bool IsItemQueued(ItemDrop.ItemData item)
+ {
+ if (item == null)
+ {
+ return false;
+ }
+ foreach (EquipQueueData item2 in m_equipQueue)
+ {
+ if (item2.m_item == item)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void ResetCharacter()
+ {
+ m_guardianPowerCooldown = 0f;
+ ResetSeenTutorials();
+ m_knownRecipes.Clear();
+ m_knownStations.Clear();
+ m_knownMaterial.Clear();
+ m_uniques.Clear();
+ m_trophies.Clear();
+ m_skills.Clear();
+ m_knownBiome.Clear();
+ m_knownTexts.Clear();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerController.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerController.cs
new file mode 100644
index 0000000..d589690
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerController.cs
@@ -0,0 +1,173 @@
+using UnityEngine;
+
+public class PlayerController : MonoBehaviour
+{
+ private Player m_character;
+
+ private ZNetView m_nview;
+
+ public static float m_mouseSens = 1f;
+
+ public static bool m_invertMouse = false;
+
+ public float m_minDodgeTime = 0.2f;
+
+ private bool m_attackWasPressed;
+
+ private bool m_secondAttackWasPressed;
+
+ private bool m_blockWasPressed;
+
+ private bool m_lastJump;
+
+ private bool m_lastCrouch;
+
+ private void Awake()
+ {
+ m_character = GetComponent<Player>();
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ return;
+ }
+ m_mouseSens = PlayerPrefs.GetFloat("MouseSensitivity", m_mouseSens);
+ m_invertMouse = PlayerPrefs.GetInt("InvertMouse", 0) == 1;
+ }
+
+ private void FixedUpdate()
+ {
+ if ((bool)m_nview && !m_nview.IsOwner())
+ {
+ return;
+ }
+ if (!TakeInput())
+ {
+ m_character.SetControls(Vector3.zero, attack: false, attackHold: false, secondaryAttack: false, block: false, blockHold: false, jump: false, crouch: false, run: false, autoRun: false);
+ return;
+ }
+ bool flag = InInventoryEtc();
+ Vector3 zero = Vector3.zero;
+ if (ZInput.GetButton("Forward"))
+ {
+ zero.z += 1f;
+ }
+ if (ZInput.GetButton("Backward"))
+ {
+ zero.z -= 1f;
+ }
+ if (ZInput.GetButton("Left"))
+ {
+ zero.x -= 1f;
+ }
+ if (ZInput.GetButton("Right"))
+ {
+ zero.x += 1f;
+ }
+ zero.x += ZInput.GetJoyLeftStickX();
+ zero.z += 0f - ZInput.GetJoyLeftStickY();
+ if (zero.magnitude > 1f)
+ {
+ zero.Normalize();
+ }
+ bool flag2 = (ZInput.GetButton("Attack") || ZInput.GetButton("JoyAttack")) && !flag;
+ bool attackHold = flag2;
+ bool attack = flag2 && !m_attackWasPressed;
+ m_attackWasPressed = flag2;
+ bool flag3 = (ZInput.GetButton("SecondAttack") || ZInput.GetButton("JoySecondAttack")) && !flag;
+ bool secondaryAttack = flag3 && !m_secondAttackWasPressed;
+ m_secondAttackWasPressed = flag3;
+ bool flag4 = (ZInput.GetButton("Block") || ZInput.GetButton("JoyBlock")) && !flag;
+ bool blockHold = flag4;
+ bool block = flag4 && !m_blockWasPressed;
+ m_blockWasPressed = flag4;
+ bool button = ZInput.GetButton("Jump");
+ bool jump = (button && !m_lastJump) || ZInput.GetButtonDown("JoyJump");
+ m_lastJump = button;
+ bool flag5 = InventoryGui.IsVisible();
+ bool flag6 = (ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) && !flag5;
+ bool crouch = flag6 && !m_lastCrouch;
+ m_lastCrouch = flag6;
+ bool run = ZInput.GetButton("Run") || ZInput.GetButton("JoyRun");
+ bool button2 = ZInput.GetButton("AutoRun");
+ m_character.SetControls(zero, attack, attackHold, secondaryAttack, block, blockHold, jump, crouch, run, button2);
+ }
+
+ private static bool DetectTap(bool pressed, float dt, float minPressTime, bool run, ref float pressTimer, ref float releasedTimer, ref bool tapPressed)
+ {
+ bool result = false;
+ if (pressed)
+ {
+ if ((releasedTimer > 0f && releasedTimer < minPressTime) & tapPressed)
+ {
+ tapPressed = false;
+ result = true;
+ }
+ pressTimer += dt;
+ releasedTimer = 0f;
+ }
+ else
+ {
+ if (pressTimer > 0f)
+ {
+ tapPressed = pressTimer < minPressTime;
+ if (run & tapPressed)
+ {
+ tapPressed = false;
+ result = true;
+ }
+ }
+ releasedTimer += dt;
+ pressTimer = 0f;
+ }
+ return result;
+ }
+
+ private bool TakeInput()
+ {
+ if (GameCamera.InFreeFly())
+ {
+ return false;
+ }
+ if ((!Chat.instance || !Chat.instance.HasFocus()) && !Menu.IsVisible() && !Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput() && (!ZInput.IsGamepadActive() || !Minimap.IsOpen()) && (!ZInput.IsGamepadActive() || !InventoryGui.IsVisible()) && (!ZInput.IsGamepadActive() || !StoreGui.IsVisible()))
+ {
+ if (ZInput.IsGamepadActive())
+ {
+ return !Hud.IsPieceSelectionVisible();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private bool InInventoryEtc()
+ {
+ if (!InventoryGui.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible())
+ {
+ return Hud.IsPieceSelectionVisible();
+ }
+ return true;
+ }
+
+ private void LateUpdate()
+ {
+ if (!TakeInput() || InInventoryEtc())
+ {
+ m_character.SetMouseLook(Vector2.zero);
+ return;
+ }
+ Vector2 zero = Vector2.zero;
+ zero.x = Input.GetAxis("Mouse X") * m_mouseSens;
+ zero.y = Input.GetAxis("Mouse Y") * m_mouseSens;
+ if (!m_character.InPlaceMode() || !ZInput.GetButton("JoyRotate"))
+ {
+ zero.x += ZInput.GetJoyRightStickX() * 110f * Time.deltaTime;
+ zero.y += (0f - ZInput.GetJoyRightStickY()) * 110f * Time.deltaTime;
+ }
+ if (m_invertMouse)
+ {
+ zero.y *= -1f;
+ }
+ m_character.SetMouseLook(zero);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerCustomizaton.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerCustomizaton.cs
new file mode 100644
index 0000000..6113453
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerCustomizaton.cs
@@ -0,0 +1,176 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class PlayerCustomizaton : MonoBehaviour
+{
+ public Color m_skinColor0 = Color.white;
+
+ public Color m_skinColor1 = Color.white;
+
+ public Color m_hairColor0 = Color.white;
+
+ public Color m_hairColor1 = Color.white;
+
+ public float m_hairMaxLevel = 1f;
+
+ public float m_hairMinLevel = 0.1f;
+
+ public Text m_selectedBeard;
+
+ public Text m_selectedHair;
+
+ public Slider m_skinHue;
+
+ public Slider m_hairLevel;
+
+ public Slider m_hairTone;
+
+ public RectTransform m_beardPanel;
+
+ public Toggle m_maleToggle;
+
+ public Toggle m_femaleToggle;
+
+ public ItemDrop m_noHair;
+
+ public ItemDrop m_noBeard;
+
+ private List<ItemDrop> m_beards;
+
+ private List<ItemDrop> m_hairs;
+
+ private void OnEnable()
+ {
+ m_maleToggle.isOn = true;
+ m_femaleToggle.isOn = false;
+ m_beardPanel.gameObject.SetActive(value: true);
+ m_beards = ObjectDB.instance.GetAllItems(ItemDrop.ItemData.ItemType.Customization, "Beard");
+ m_hairs = ObjectDB.instance.GetAllItems(ItemDrop.ItemData.ItemType.Customization, "Hair");
+ m_beards.Sort((ItemDrop x, ItemDrop y) => Localization.instance.Localize(x.m_itemData.m_shared.m_name).CompareTo(Localization.instance.Localize(y.m_itemData.m_shared.m_name)));
+ m_hairs.Sort((ItemDrop x, ItemDrop y) => Localization.instance.Localize(x.m_itemData.m_shared.m_name).CompareTo(Localization.instance.Localize(y.m_itemData.m_shared.m_name)));
+ m_beards.Remove(m_noBeard);
+ m_beards.Insert(0, m_noBeard);
+ m_hairs.Remove(m_noHair);
+ m_hairs.Insert(0, m_noHair);
+ }
+
+ private void Update()
+ {
+ if (!(GetPlayer() == null))
+ {
+ m_selectedHair.text = Localization.instance.Localize(GetHair());
+ m_selectedBeard.text = Localization.instance.Localize(GetBeard());
+ Color c = Color.Lerp(m_skinColor0, m_skinColor1, m_skinHue.value);
+ GetPlayer().SetSkinColor(Utils.ColorToVec3(c));
+ Color c2 = Color.Lerp(m_hairColor0, m_hairColor1, m_hairTone.value) * Mathf.Lerp(m_hairMinLevel, m_hairMaxLevel, m_hairLevel.value);
+ GetPlayer().SetHairColor(Utils.ColorToVec3(c2));
+ }
+ }
+
+ private Player GetPlayer()
+ {
+ return GetComponentInParent<FejdStartup>().GetPreviewPlayer();
+ }
+
+ public void OnHairHueChange(float v)
+ {
+ }
+
+ public void OnSkinHueChange(float v)
+ {
+ }
+
+ public void SetPlayerModel(int index)
+ {
+ GetPlayer().SetPlayerModel(index);
+ if (index == 1)
+ {
+ ResetBeard();
+ }
+ }
+
+ public void OnHairLeft()
+ {
+ SetHair(GetHairIndex() - 1);
+ }
+
+ public void OnHairRight()
+ {
+ SetHair(GetHairIndex() + 1);
+ }
+
+ public void OnBeardLeft()
+ {
+ if (GetPlayer().GetPlayerModel() != 1)
+ {
+ SetBeard(GetBeardIndex() - 1);
+ }
+ }
+
+ public void OnBeardRight()
+ {
+ if (GetPlayer().GetPlayerModel() != 1)
+ {
+ SetBeard(GetBeardIndex() + 1);
+ }
+ }
+
+ private void ResetBeard()
+ {
+ GetPlayer().SetBeard(m_noBeard.gameObject.name);
+ }
+
+ private void SetBeard(int index)
+ {
+ if (index >= 0 && index < m_beards.Count)
+ {
+ GetPlayer().SetBeard(m_beards[index].gameObject.name);
+ }
+ }
+
+ private void SetHair(int index)
+ {
+ ZLog.Log("Set hair " + index);
+ if (index >= 0 && index < m_hairs.Count)
+ {
+ GetPlayer().SetHair(m_hairs[index].gameObject.name);
+ }
+ }
+
+ private int GetBeardIndex()
+ {
+ string beard = GetPlayer().GetBeard();
+ for (int i = 0; i < m_beards.Count; i++)
+ {
+ if (m_beards[i].gameObject.name == beard)
+ {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private int GetHairIndex()
+ {
+ string hair = GetPlayer().GetHair();
+ for (int i = 0; i < m_hairs.Count; i++)
+ {
+ if (m_hairs[i].gameObject.name == hair)
+ {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private string GetHair()
+ {
+ return m_hairs[GetHairIndex()].m_itemData.m_shared.m_name;
+ }
+
+ private string GetBeard()
+ {
+ return m_beards[GetBeardIndex()].m_itemData.m_shared.m_name;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerProfile.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerProfile.cs
new file mode 100644
index 0000000..8ab7849
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PlayerProfile.cs
@@ -0,0 +1,444 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public class PlayerProfile
+{
+ private class WorldPlayerData
+ {
+ public Vector3 m_spawnPoint = Vector3.zero;
+
+ public bool m_haveCustomSpawnPoint;
+
+ public Vector3 m_logoutPoint = Vector3.zero;
+
+ public bool m_haveLogoutPoint;
+
+ public Vector3 m_deathPoint = Vector3.zero;
+
+ public bool m_haveDeathPoint;
+
+ public Vector3 m_homePoint = Vector3.zero;
+
+ public byte[] m_mapData;
+ }
+
+ public class PlayerStats
+ {
+ public int m_kills;
+
+ public int m_deaths;
+
+ public int m_crafts;
+
+ public int m_builds;
+ }
+
+ private string m_filename = "";
+
+ private string m_playerName = "";
+
+ private long m_playerID;
+
+ private string m_startSeed = "";
+
+ public static Vector3 m_originalSpawnPoint = new Vector3(-676f, 50f, 299f);
+
+ private Dictionary<long, WorldPlayerData> m_worldData = new Dictionary<long, WorldPlayerData>();
+
+ public PlayerStats m_playerStats = new PlayerStats();
+
+ private byte[] m_playerData;
+
+ public PlayerProfile(string filename = null)
+ {
+ m_filename = filename;
+ m_playerName = "Stranger";
+ m_playerID = Utils.GenerateUID();
+ }
+
+ public bool Load()
+ {
+ if (m_filename == null)
+ {
+ return false;
+ }
+ return LoadPlayerFromDisk();
+ }
+
+ public bool Save()
+ {
+ if (m_filename == null)
+ {
+ return false;
+ }
+ return SavePlayerToDisk();
+ }
+
+ public bool HaveIncompatiblPlayerData()
+ {
+ if (m_filename == null)
+ {
+ return false;
+ }
+ ZPackage zPackage = LoadPlayerDataFromDisk();
+ if (zPackage == null)
+ {
+ return false;
+ }
+ if (!Version.IsPlayerVersionCompatible(zPackage.ReadInt()))
+ {
+ ZLog.Log("Player data is not compatible, ignoring");
+ return true;
+ }
+ return false;
+ }
+
+ public void SavePlayerData(Player player)
+ {
+ ZPackage zPackage = new ZPackage();
+ player.Save(zPackage);
+ m_playerData = zPackage.GetArray();
+ }
+
+ public void LoadPlayerData(Player player)
+ {
+ player.SetPlayerID(m_playerID, m_playerName);
+ if (m_playerData != null)
+ {
+ ZPackage pkg = new ZPackage(m_playerData);
+ player.Load(pkg);
+ }
+ else
+ {
+ player.GiveDefaultItems();
+ }
+ }
+
+ public void SaveLogoutPoint()
+ {
+ if ((bool)Player.m_localPlayer && !Player.m_localPlayer.IsDead() && !Player.m_localPlayer.InIntro())
+ {
+ SetLogoutPoint(Player.m_localPlayer.transform.position);
+ }
+ }
+
+ private bool SavePlayerToDisk()
+ {
+ Directory.CreateDirectory(Application.persistentDataPath + "/characters");
+ string text = Application.persistentDataPath + "/characters/" + m_filename + ".fch";
+ string text2 = Application.persistentDataPath + "/characters/" + m_filename + ".fch.old";
+ string text3 = Application.persistentDataPath + "/characters/" + m_filename + ".fch.new";
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(Version.m_playerVersion);
+ zPackage.Write(m_playerStats.m_kills);
+ zPackage.Write(m_playerStats.m_deaths);
+ zPackage.Write(m_playerStats.m_crafts);
+ zPackage.Write(m_playerStats.m_builds);
+ zPackage.Write(m_worldData.Count);
+ foreach (KeyValuePair<long, WorldPlayerData> worldDatum in m_worldData)
+ {
+ zPackage.Write(worldDatum.Key);
+ zPackage.Write(worldDatum.Value.m_haveCustomSpawnPoint);
+ zPackage.Write(worldDatum.Value.m_spawnPoint);
+ zPackage.Write(worldDatum.Value.m_haveLogoutPoint);
+ zPackage.Write(worldDatum.Value.m_logoutPoint);
+ zPackage.Write(worldDatum.Value.m_haveDeathPoint);
+ zPackage.Write(worldDatum.Value.m_deathPoint);
+ zPackage.Write(worldDatum.Value.m_homePoint);
+ zPackage.Write(worldDatum.Value.m_mapData != null);
+ if (worldDatum.Value.m_mapData != null)
+ {
+ zPackage.Write(worldDatum.Value.m_mapData);
+ }
+ }
+ zPackage.Write(m_playerName);
+ zPackage.Write(m_playerID);
+ zPackage.Write(m_startSeed);
+ if (m_playerData != null)
+ {
+ zPackage.Write(data: true);
+ zPackage.Write(m_playerData);
+ }
+ else
+ {
+ zPackage.Write(data: false);
+ }
+ byte[] array = zPackage.GenerateHash();
+ FileStream fileStream = File.Create(text3);
+ BinaryWriter binaryWriter = new BinaryWriter(fileStream);
+ byte[] array2 = zPackage.GetArray();
+ binaryWriter.Write(array2.Length);
+ binaryWriter.Write(array2);
+ binaryWriter.Write(array.Length);
+ binaryWriter.Write(array);
+ fileStream.Dispose();
+ if (File.Exists(text))
+ {
+ if (File.Exists(text2))
+ {
+ File.Delete(text2);
+ }
+ File.Move(text, text2);
+ }
+ File.Move(text3, text);
+ return true;
+ }
+
+ private bool LoadPlayerFromDisk()
+ {
+ try
+ {
+ ZPackage zPackage = LoadPlayerDataFromDisk();
+ if (zPackage == null)
+ {
+ ZLog.LogWarning("No player data");
+ return false;
+ }
+ int num = zPackage.ReadInt();
+ if (!Version.IsPlayerVersionCompatible(num))
+ {
+ ZLog.Log("Player data is not compatible, ignoring");
+ return false;
+ }
+ if (num >= 28)
+ {
+ m_playerStats.m_kills = zPackage.ReadInt();
+ m_playerStats.m_deaths = zPackage.ReadInt();
+ m_playerStats.m_crafts = zPackage.ReadInt();
+ m_playerStats.m_builds = zPackage.ReadInt();
+ }
+ m_worldData.Clear();
+ int num2 = zPackage.ReadInt();
+ for (int i = 0; i < num2; i++)
+ {
+ long key = zPackage.ReadLong();
+ WorldPlayerData worldPlayerData = new WorldPlayerData();
+ worldPlayerData.m_haveCustomSpawnPoint = zPackage.ReadBool();
+ worldPlayerData.m_spawnPoint = zPackage.ReadVector3();
+ worldPlayerData.m_haveLogoutPoint = zPackage.ReadBool();
+ worldPlayerData.m_logoutPoint = zPackage.ReadVector3();
+ if (num >= 30)
+ {
+ worldPlayerData.m_haveDeathPoint = zPackage.ReadBool();
+ worldPlayerData.m_deathPoint = zPackage.ReadVector3();
+ }
+ worldPlayerData.m_homePoint = zPackage.ReadVector3();
+ if (num >= 29 && zPackage.ReadBool())
+ {
+ worldPlayerData.m_mapData = zPackage.ReadByteArray();
+ }
+ m_worldData.Add(key, worldPlayerData);
+ }
+ m_playerName = zPackage.ReadString();
+ m_playerID = zPackage.ReadLong();
+ m_startSeed = zPackage.ReadString();
+ if (zPackage.ReadBool())
+ {
+ m_playerData = zPackage.ReadByteArray();
+ }
+ else
+ {
+ m_playerData = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ ZLog.LogWarning("Exception while loading player profile:" + m_filename + " , " + ex.ToString());
+ }
+ return true;
+ }
+
+ private ZPackage LoadPlayerDataFromDisk()
+ {
+ string text = Application.persistentDataPath + "/characters/" + m_filename + ".fch";
+ FileStream fileStream;
+ try
+ {
+ fileStream = File.OpenRead(text);
+ }
+ catch
+ {
+ ZLog.Log(" failed to load " + text);
+ return null;
+ }
+ byte[] data;
+ try
+ {
+ BinaryReader binaryReader = new BinaryReader(fileStream);
+ int num = binaryReader.ReadInt32();
+ data = binaryReader.ReadBytes(num);
+ int num2 = binaryReader.ReadInt32();
+ binaryReader.ReadBytes(num2);
+ ZLog.Log("Data size:" + num + " hash size:" + num2);
+ }
+ catch
+ {
+ ZLog.LogError(" error loading player.dat");
+ fileStream.Dispose();
+ return null;
+ }
+ fileStream.Dispose();
+ return new ZPackage(data);
+ }
+
+ public void SetLogoutPoint(Vector3 point)
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_haveLogoutPoint = true;
+ GetWorldData(ZNet.instance.GetWorldUID()).m_logoutPoint = point;
+ }
+
+ public void SetDeathPoint(Vector3 point)
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_haveDeathPoint = true;
+ GetWorldData(ZNet.instance.GetWorldUID()).m_deathPoint = point;
+ }
+
+ public void SetMapData(byte[] data)
+ {
+ long worldUID = ZNet.instance.GetWorldUID();
+ if (worldUID != 0L)
+ {
+ GetWorldData(worldUID).m_mapData = data;
+ }
+ }
+
+ public byte[] GetMapData()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_mapData;
+ }
+
+ public void ClearLoguoutPoint()
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_haveLogoutPoint = false;
+ }
+
+ public bool HaveLogoutPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_haveLogoutPoint;
+ }
+
+ public Vector3 GetLogoutPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_logoutPoint;
+ }
+
+ public bool HaveDeathPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_haveDeathPoint;
+ }
+
+ public Vector3 GetDeathPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_deathPoint;
+ }
+
+ public void SetCustomSpawnPoint(Vector3 point)
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_haveCustomSpawnPoint = true;
+ GetWorldData(ZNet.instance.GetWorldUID()).m_spawnPoint = point;
+ }
+
+ public Vector3 GetCustomSpawnPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_spawnPoint;
+ }
+
+ public bool HaveCustomSpawnPoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_haveCustomSpawnPoint;
+ }
+
+ public void ClearCustomSpawnPoint()
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_haveCustomSpawnPoint = false;
+ }
+
+ public void SetHomePoint(Vector3 point)
+ {
+ GetWorldData(ZNet.instance.GetWorldUID()).m_homePoint = point;
+ }
+
+ public Vector3 GetHomePoint()
+ {
+ return GetWorldData(ZNet.instance.GetWorldUID()).m_homePoint;
+ }
+
+ public void SetName(string name)
+ {
+ m_playerName = name;
+ }
+
+ public string GetName()
+ {
+ return m_playerName;
+ }
+
+ public long GetPlayerID()
+ {
+ return m_playerID;
+ }
+
+ public static List<PlayerProfile> GetAllPlayerProfiles()
+ {
+ string[] array;
+ try
+ {
+ array = Directory.GetFiles(Application.persistentDataPath + "/characters", "*.fch");
+ }
+ catch
+ {
+ array = new string[0];
+ }
+ List<PlayerProfile> list = new List<PlayerProfile>();
+ string[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(array2[i]);
+ ZLog.Log("loading " + fileNameWithoutExtension);
+ PlayerProfile playerProfile = new PlayerProfile(fileNameWithoutExtension);
+ if (!playerProfile.Load())
+ {
+ ZLog.Log("Failed to load " + fileNameWithoutExtension);
+ }
+ else
+ {
+ list.Add(playerProfile);
+ }
+ }
+ return list;
+ }
+
+ public static void RemoveProfile(string name)
+ {
+ try
+ {
+ File.Delete(Application.persistentDataPath + "/characters/" + name + ".fch");
+ }
+ catch
+ {
+ }
+ }
+
+ public static bool HaveProfile(string name)
+ {
+ return File.Exists(Application.persistentDataPath + "/characters/" + name + ".fch");
+ }
+
+ public string GetFilename()
+ {
+ return m_filename;
+ }
+
+ private WorldPlayerData GetWorldData(long worldUID)
+ {
+ if (m_worldData.TryGetValue(worldUID, out var value))
+ {
+ return value;
+ }
+ value = new WorldPlayerData();
+ m_worldData.Add(worldUID, value);
+ return value;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PointGenerator.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PointGenerator.cs
new file mode 100644
index 0000000..ef338e7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PointGenerator.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PointGenerator
+{
+ private int m_amount;
+
+ private float m_gridSize = 8f;
+
+ private Vector2Int m_currentCenterGrid = new Vector2Int(99999, 99999);
+
+ private int m_currentGridWith;
+
+ private List<Vector3> m_points = new List<Vector3>();
+
+ public PointGenerator(int amount, float gridSize)
+ {
+ m_amount = amount;
+ m_gridSize = gridSize;
+ }
+
+ public void Update(Vector3 center, float radius, List<Vector3> newPoints, List<Vector3> removedPoints)
+ {
+ Vector2Int grid = GetGrid(center);
+ if (m_currentCenterGrid == grid)
+ {
+ newPoints.Clear();
+ removedPoints.Clear();
+ return;
+ }
+ int num = Mathf.CeilToInt(radius / m_gridSize);
+ if (m_currentCenterGrid != grid || m_currentGridWith != num)
+ {
+ RegeneratePoints(grid, num);
+ }
+ }
+
+ private void RegeneratePoints(Vector2Int centerGrid, int gridWith)
+ {
+ m_currentCenterGrid = centerGrid;
+ Random.State state = Random.state;
+ m_points.Clear();
+ for (int i = centerGrid.y - gridWith; i <= centerGrid.y + gridWith; i++)
+ {
+ for (int j = centerGrid.x - gridWith; j <= centerGrid.x + gridWith; j++)
+ {
+ Random.InitState(j + i * 100);
+ Vector3 gridPos = GetGridPos(new Vector2Int(j, i));
+ for (int k = 0; k < m_amount; k++)
+ {
+ Vector3 item = new Vector3(Random.Range(gridPos.x - m_gridSize, gridPos.x + m_gridSize), Random.Range(gridPos.z - m_gridSize, gridPos.z + m_gridSize));
+ m_points.Add(item);
+ }
+ }
+ }
+ Random.state = state;
+ }
+
+ public Vector2Int GetGrid(Vector3 point)
+ {
+ int x = Mathf.FloorToInt((point.x + m_gridSize / 2f) / m_gridSize);
+ int y = Mathf.FloorToInt((point.z + m_gridSize / 2f) / m_gridSize);
+ return new Vector2Int(x, y);
+ }
+
+ public Vector3 GetGridPos(Vector2Int grid)
+ {
+ return new Vector3((float)grid.x * m_gridSize, 0f, (float)grid.y * m_gridSize);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PrivateArea.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PrivateArea.cs
new file mode 100644
index 0000000..448f69c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/PrivateArea.cs
@@ -0,0 +1,546 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+
+public class PrivateArea : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "Guard stone";
+
+ public float m_radius = 10f;
+
+ public float m_updateConnectionsInterval = 5f;
+
+ public GameObject m_enabledEffect;
+
+ public CircleProjector m_areaMarker;
+
+ public EffectList m_flashEffect = new EffectList();
+
+ public EffectList m_activateEffect = new EffectList();
+
+ public EffectList m_deactivateEffect = new EffectList();
+
+ public EffectList m_addPermittedEffect = new EffectList();
+
+ public EffectList m_removedPermittedEffect = new EffectList();
+
+ public GameObject m_connectEffect;
+
+ public GameObject m_inRangeEffect;
+
+ public MeshRenderer m_model;
+
+ private ZNetView m_nview;
+
+ private Piece m_piece;
+
+ private bool m_flashAvailable = true;
+
+ private bool m_tempChecked;
+
+ private List<GameObject> m_connectionInstances = new List<GameObject>();
+
+ private float m_connectionUpdateTime = -1000f;
+
+ private List<PrivateArea> m_connectedAreas = new List<PrivateArea>();
+
+ private static List<PrivateArea> m_allAreas = new List<PrivateArea>();
+
+ private void Awake()
+ {
+ if ((bool)m_areaMarker)
+ {
+ m_areaMarker.m_radius = m_radius;
+ }
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.IsValid())
+ {
+ WearNTear component = GetComponent<WearNTear>();
+ component.m_onDamaged = (Action)Delegate.Combine(component.m_onDamaged, new Action(OnDamaged));
+ m_piece = GetComponent<Piece>();
+ if ((bool)m_areaMarker)
+ {
+ m_areaMarker.gameObject.SetActive(value: false);
+ }
+ if ((bool)m_inRangeEffect)
+ {
+ m_inRangeEffect.SetActive(value: false);
+ }
+ m_allAreas.Add(this);
+ InvokeRepeating("UpdateStatus", 0f, 1f);
+ m_nview.Register<long>("ToggleEnabled", RPC_ToggleEnabled);
+ m_nview.Register<long, string>("TogglePermitted", RPC_TogglePermitted);
+ m_nview.Register("FlashShield", RPC_FlashShield);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ m_allAreas.Remove(this);
+ }
+
+ private void UpdateStatus()
+ {
+ bool flag = IsEnabled();
+ m_enabledEffect.SetActive(flag);
+ m_flashAvailable = true;
+ Material[] materials = m_model.materials;
+ foreach (Material material in materials)
+ {
+ if (flag)
+ {
+ material.EnableKeyword("_EMISSION");
+ }
+ else
+ {
+ material.DisableKeyword("_EMISSION");
+ }
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (!m_nview.IsValid())
+ {
+ return "";
+ }
+ if (Player.m_localPlayer == null)
+ {
+ return "";
+ }
+ ShowAreaMarker();
+ StringBuilder stringBuilder = new StringBuilder(256);
+ if (m_piece.IsCreator())
+ {
+ if (IsEnabled())
+ {
+ stringBuilder.Append(m_name + " ( $piece_guardstone_active )");
+ stringBuilder.Append("\n$piece_guardstone_owner:" + GetCreatorName());
+ stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_guardstone_deactivate");
+ }
+ else
+ {
+ stringBuilder.Append(m_name + " ($piece_guardstone_inactive )");
+ stringBuilder.Append("\n$piece_guardstone_owner:" + GetCreatorName());
+ stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_guardstone_activate");
+ }
+ }
+ else if (IsEnabled())
+ {
+ stringBuilder.Append(m_name + " ( $piece_guardstone_active )");
+ stringBuilder.Append("\n$piece_guardstone_owner:" + GetCreatorName());
+ }
+ else
+ {
+ stringBuilder.Append(m_name + " ( $piece_guardstone_inactive )");
+ stringBuilder.Append("\n$piece_guardstone_owner:" + GetCreatorName());
+ if (IsPermitted(Player.m_localPlayer.GetPlayerID()))
+ {
+ stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_guardstone_remove");
+ }
+ else
+ {
+ stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_guardstone_add");
+ }
+ }
+ AddUserList(stringBuilder);
+ return Localization.instance.Localize(stringBuilder.ToString());
+ }
+
+ private void AddUserList(StringBuilder text)
+ {
+ List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers();
+ text.Append("\n$piece_guardstone_additional: ");
+ for (int i = 0; i < permittedPlayers.Count; i++)
+ {
+ text.Append(permittedPlayers[i].Value);
+ if (i != permittedPlayers.Count - 1)
+ {
+ text.Append(", ");
+ }
+ }
+ }
+
+ private void RemovePermitted(long playerID)
+ {
+ List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers();
+ if (permittedPlayers.RemoveAll((KeyValuePair<long, string> x) => x.Key == playerID) > 0)
+ {
+ SetPermittedPlayers(permittedPlayers);
+ m_removedPermittedEffect.Create(base.transform.position, base.transform.rotation);
+ }
+ }
+
+ private bool IsPermitted(long playerID)
+ {
+ foreach (KeyValuePair<long, string> permittedPlayer in GetPermittedPlayers())
+ {
+ if (permittedPlayer.Key == playerID)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void AddPermitted(long playerID, string playerName)
+ {
+ List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers();
+ foreach (KeyValuePair<long, string> item in permittedPlayers)
+ {
+ if (item.Key == playerID)
+ {
+ return;
+ }
+ }
+ permittedPlayers.Add(new KeyValuePair<long, string>(playerID, playerName));
+ SetPermittedPlayers(permittedPlayers);
+ m_addPermittedEffect.Create(base.transform.position, base.transform.rotation);
+ }
+
+ private void SetPermittedPlayers(List<KeyValuePair<long, string>> users)
+ {
+ m_nview.GetZDO().Set("permitted", users.Count);
+ for (int i = 0; i < users.Count; i++)
+ {
+ KeyValuePair<long, string> keyValuePair = users[i];
+ m_nview.GetZDO().Set("pu_id" + i, keyValuePair.Key);
+ m_nview.GetZDO().Set("pu_name" + i, keyValuePair.Value);
+ }
+ }
+
+ private List<KeyValuePair<long, string>> GetPermittedPlayers()
+ {
+ List<KeyValuePair<long, string>> list = new List<KeyValuePair<long, string>>();
+ int @int = m_nview.GetZDO().GetInt("permitted");
+ for (int i = 0; i < @int; i++)
+ {
+ long @long = m_nview.GetZDO().GetLong("pu_id" + i, 0L);
+ string @string = m_nview.GetZDO().GetString("pu_name" + i);
+ if (@long != 0L)
+ {
+ list.Add(new KeyValuePair<long, string>(@long, @string));
+ }
+ }
+ return list;
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid human, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ Player player = human as Player;
+ if (m_piece.IsCreator())
+ {
+ m_nview.InvokeRPC("ToggleEnabled", player.GetPlayerID());
+ return true;
+ }
+ if (IsEnabled())
+ {
+ return false;
+ }
+ m_nview.InvokeRPC("TogglePermitted", player.GetPlayerID(), player.GetPlayerName());
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void RPC_TogglePermitted(long uid, long playerID, string name)
+ {
+ if (m_nview.IsOwner() && !IsEnabled())
+ {
+ if (IsPermitted(playerID))
+ {
+ RemovePermitted(playerID);
+ }
+ else
+ {
+ AddPermitted(playerID, name);
+ }
+ }
+ }
+
+ private void RPC_ToggleEnabled(long uid, long playerID)
+ {
+ ZLog.Log("Toggle enabled from " + playerID + " creator is " + m_piece.GetCreator());
+ if (m_nview.IsOwner() && m_piece.GetCreator() == playerID)
+ {
+ SetEnabled(!IsEnabled());
+ }
+ }
+
+ public bool IsEnabled()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.GetZDO().GetBool("enabled");
+ }
+
+ private void SetEnabled(bool enabled)
+ {
+ m_nview.GetZDO().Set("enabled", enabled);
+ UpdateStatus();
+ if (enabled)
+ {
+ m_activateEffect.Create(base.transform.position, base.transform.rotation);
+ }
+ else
+ {
+ m_deactivateEffect.Create(base.transform.position, base.transform.rotation);
+ }
+ }
+
+ public void Setup(string name)
+ {
+ m_nview.GetZDO().Set("creatorName", name);
+ }
+
+ public void PokeAllAreasInRange()
+ {
+ foreach (PrivateArea allArea in m_allAreas)
+ {
+ if (!(allArea == this) && IsInside(allArea.transform.position, 0f))
+ {
+ allArea.StartInRangeEffect();
+ }
+ }
+ }
+
+ private void StartInRangeEffect()
+ {
+ m_inRangeEffect.SetActive(value: true);
+ CancelInvoke("StopInRangeEffect");
+ Invoke("StopInRangeEffect", 0.2f);
+ }
+
+ private void StopInRangeEffect()
+ {
+ m_inRangeEffect.SetActive(value: false);
+ }
+
+ public void PokeConnectionEffects()
+ {
+ List<PrivateArea> connectedAreas = GetConnectedAreas();
+ StartConnectionEffects();
+ foreach (PrivateArea item in connectedAreas)
+ {
+ item.StartConnectionEffects();
+ }
+ }
+
+ private void StartConnectionEffects()
+ {
+ List<PrivateArea> list = new List<PrivateArea>();
+ foreach (PrivateArea allArea in m_allAreas)
+ {
+ if (!(allArea == this) && IsInside(allArea.transform.position, 0f))
+ {
+ list.Add(allArea);
+ }
+ }
+ Vector3 vector = base.transform.position + Vector3.up * 1.4f;
+ if (m_connectionInstances.Count != list.Count)
+ {
+ StopConnectionEffects();
+ for (int i = 0; i < list.Count; i++)
+ {
+ GameObject item = UnityEngine.Object.Instantiate(m_connectEffect, vector, Quaternion.identity, base.transform);
+ m_connectionInstances.Add(item);
+ }
+ }
+ if (m_connectionInstances.Count != 0)
+ {
+ for (int j = 0; j < list.Count; j++)
+ {
+ Vector3 vector2 = list[j].transform.position + Vector3.up * 1.4f - vector;
+ Quaternion rotation = Quaternion.LookRotation(vector2.normalized);
+ GameObject obj = m_connectionInstances[j];
+ obj.transform.position = vector;
+ obj.transform.rotation = rotation;
+ obj.transform.localScale = new Vector3(1f, 1f, vector2.magnitude);
+ }
+ CancelInvoke("StopConnectionEffects");
+ Invoke("StopConnectionEffects", 0.3f);
+ }
+ }
+
+ private void StopConnectionEffects()
+ {
+ foreach (GameObject connectionInstance in m_connectionInstances)
+ {
+ UnityEngine.Object.Destroy(connectionInstance);
+ }
+ m_connectionInstances.Clear();
+ }
+
+ private string GetCreatorName()
+ {
+ return m_nview.GetZDO().GetString("creatorName");
+ }
+
+ public static bool CheckInPrivateArea(Vector3 point, bool flash = false)
+ {
+ foreach (PrivateArea allArea in m_allAreas)
+ {
+ if (allArea.IsEnabled() && allArea.IsInside(point, 0f))
+ {
+ if (flash)
+ {
+ allArea.FlashShield(flashConnected: false);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static bool CheckAccess(Vector3 point, float radius = 0f, bool flash = true)
+ {
+ bool flag = false;
+ List<PrivateArea> list = new List<PrivateArea>();
+ foreach (PrivateArea allArea in m_allAreas)
+ {
+ if (allArea.IsEnabled() && allArea.IsInside(point, radius))
+ {
+ if (allArea.HaveLocalAccess())
+ {
+ flag = true;
+ }
+ else
+ {
+ list.Add(allArea);
+ }
+ }
+ }
+ if (!flag && list.Count > 0)
+ {
+ if (flash)
+ {
+ foreach (PrivateArea item in list)
+ {
+ item.FlashShield(flashConnected: false);
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private bool HaveLocalAccess()
+ {
+ if (m_piece.IsCreator())
+ {
+ return true;
+ }
+ if (IsPermitted(Player.m_localPlayer.GetPlayerID()))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private List<PrivateArea> GetConnectedAreas(bool forceUpdate = false)
+ {
+ if (Time.time - m_connectionUpdateTime > m_updateConnectionsInterval || forceUpdate)
+ {
+ GetAllConnectedAreas(m_connectedAreas);
+ m_connectionUpdateTime = Time.time;
+ }
+ return m_connectedAreas;
+ }
+
+ private void GetAllConnectedAreas(List<PrivateArea> areas)
+ {
+ Queue<PrivateArea> queue = new Queue<PrivateArea>();
+ queue.Enqueue(this);
+ foreach (PrivateArea allArea in m_allAreas)
+ {
+ allArea.m_tempChecked = false;
+ }
+ m_tempChecked = true;
+ while (queue.Count > 0)
+ {
+ PrivateArea privateArea = queue.Dequeue();
+ foreach (PrivateArea allArea2 in m_allAreas)
+ {
+ if (!allArea2.m_tempChecked && allArea2.IsEnabled() && allArea2.IsInside(privateArea.transform.position, 0f))
+ {
+ allArea2.m_tempChecked = true;
+ queue.Enqueue(allArea2);
+ areas.Add(allArea2);
+ }
+ }
+ }
+ }
+
+ private void FlashShield(bool flashConnected)
+ {
+ if (!m_flashAvailable)
+ {
+ return;
+ }
+ m_flashAvailable = false;
+ m_nview.InvokeRPC(ZNetView.Everybody, "FlashShield");
+ if (!flashConnected)
+ {
+ return;
+ }
+ foreach (PrivateArea connectedArea in GetConnectedAreas())
+ {
+ if (connectedArea.m_nview.IsValid())
+ {
+ connectedArea.m_nview.InvokeRPC(ZNetView.Everybody, "FlashShield");
+ }
+ }
+ }
+
+ private void RPC_FlashShield(long uid)
+ {
+ m_flashEffect.Create(base.transform.position, Quaternion.identity);
+ }
+
+ private bool IsInside(Vector3 point, float radius)
+ {
+ return Utils.DistanceXZ(base.transform.position, point) < m_radius + radius;
+ }
+
+ public void ShowAreaMarker()
+ {
+ if ((bool)m_areaMarker)
+ {
+ m_areaMarker.gameObject.SetActive(value: true);
+ CancelInvoke("HideMarker");
+ Invoke("HideMarker", 0.5f);
+ }
+ }
+
+ private void HideMarker()
+ {
+ m_areaMarker.gameObject.SetActive(value: false);
+ }
+
+ private void OnDamaged()
+ {
+ if (IsEnabled())
+ {
+ FlashShield(flashConnected: false);
+ }
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Procreation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Procreation.cs
new file mode 100644
index 0000000..1ec5aa3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Procreation.cs
@@ -0,0 +1,144 @@
+using System;
+using UnityEngine;
+
+public class Procreation : MonoBehaviour
+{
+ public float m_updateInterval = 10f;
+
+ public float m_totalCheckRange = 10f;
+
+ public int m_maxCreatures = 4;
+
+ public float m_partnerCheckRange = 3f;
+
+ public float m_pregnancyChance = 0.5f;
+
+ public float m_pregnancyDuration = 10f;
+
+ public int m_requiredLovePoints = 4;
+
+ public GameObject m_offspring;
+
+ public int m_minOffspringLevel;
+
+ public float m_spawnOffset = 2f;
+
+ public EffectList m_birthEffects = new EffectList();
+
+ public EffectList m_loveEffects = new EffectList();
+
+ private GameObject m_myPrefab;
+
+ private GameObject m_offspringPrefab;
+
+ private ZNetView m_nview;
+
+ private BaseAI m_baseAI;
+
+ private Character m_character;
+
+ private Tameable m_tameable;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_baseAI = GetComponent<BaseAI>();
+ m_character = GetComponent<Character>();
+ m_tameable = GetComponent<Tameable>();
+ InvokeRepeating("Procreate", UnityEngine.Random.Range(m_updateInterval, m_updateInterval + m_updateInterval * 0.5f), m_updateInterval);
+ }
+
+ private void Procreate()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner() || !m_character.IsTamed())
+ {
+ return;
+ }
+ if (m_offspringPrefab == null)
+ {
+ string prefabName = ZNetView.GetPrefabName(m_offspring);
+ m_offspringPrefab = ZNetScene.instance.GetPrefab(prefabName);
+ int prefab = m_nview.GetZDO().GetPrefab();
+ m_myPrefab = ZNetScene.instance.GetPrefab(prefab);
+ }
+ if (IsPregnant())
+ {
+ if (IsDue())
+ {
+ ResetPregnancy();
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_offspringPrefab, base.transform.position - base.transform.forward * m_spawnOffset, Quaternion.LookRotation(-base.transform.forward, Vector3.up));
+ Character component = gameObject.GetComponent<Character>();
+ if ((bool)component)
+ {
+ component.SetTamed(m_character.IsTamed());
+ component.SetLevel(Mathf.Max(m_minOffspringLevel, m_character.GetLevel()));
+ }
+ m_birthEffects.Create(gameObject.transform.position, Quaternion.identity);
+ }
+ }
+ else
+ {
+ if (UnityEngine.Random.value <= m_pregnancyChance || m_baseAI.IsAlerted() || m_tameable.IsHungry())
+ {
+ return;
+ }
+ int nrOfInstances = SpawnSystem.GetNrOfInstances(m_myPrefab, base.transform.position, m_totalCheckRange);
+ int nrOfInstances2 = SpawnSystem.GetNrOfInstances(m_offspringPrefab, base.transform.position, m_totalCheckRange);
+ if (nrOfInstances + nrOfInstances2 < m_maxCreatures && SpawnSystem.GetNrOfInstances(m_myPrefab, base.transform.position, m_partnerCheckRange, eventCreaturesOnly: false, procreationOnly: true) >= 2)
+ {
+ m_loveEffects.Create(base.transform.position, Quaternion.identity);
+ int @int = m_nview.GetZDO().GetInt("lovePoints");
+ @int++;
+ m_nview.GetZDO().Set("lovePoints", @int);
+ if (@int >= m_requiredLovePoints)
+ {
+ m_nview.GetZDO().Set("lovePoints", 0);
+ MakePregnant();
+ }
+ }
+ }
+ }
+
+ public bool ReadyForProcreation()
+ {
+ if (m_character.IsTamed() && !IsPregnant())
+ {
+ return !m_tameable.IsHungry();
+ }
+ return false;
+ }
+
+ private void MakePregnant()
+ {
+ m_nview.GetZDO().Set("pregnant", ZNet.instance.GetTime().Ticks);
+ }
+
+ private void ResetPregnancy()
+ {
+ m_nview.GetZDO().Set("pregnant", 0L);
+ }
+
+ private bool IsDue()
+ {
+ long @long = m_nview.GetZDO().GetLong("pregnant", 0L);
+ if (@long == 0L)
+ {
+ return false;
+ }
+ DateTime dateTime = new DateTime(@long);
+ return (ZNet.instance.GetTime() - dateTime).TotalSeconds > (double)m_pregnancyDuration;
+ }
+
+ public bool IsPregnant()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ if (m_nview.GetZDO().GetLong("pregnant", 0L) == 0L)
+ {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Projectile.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Projectile.cs
new file mode 100644
index 0000000..e2f8eac
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Projectile.cs
@@ -0,0 +1,375 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Projectile : MonoBehaviour, IProjectile
+{
+ public HitData.DamageTypes m_damage;
+
+ public float m_aoe;
+
+ public bool m_dodgeable;
+
+ public bool m_blockable;
+
+ public float m_attackForce;
+
+ public float m_backstabBonus = 4f;
+
+ public string m_statusEffect = "";
+
+ public bool m_canHitWater;
+
+ public float m_ttl = 4f;
+
+ public float m_gravity;
+
+ public float m_rayRadius;
+
+ public float m_hitNoise = 50f;
+
+ public bool m_stayAfterHitStatic;
+
+ public GameObject m_hideOnHit;
+
+ public bool m_stopEmittersOnHit = true;
+
+ public EffectList m_hitEffects = new EffectList();
+
+ public EffectList m_hitWaterEffects = new EffectList();
+
+ [Header("Spawn on hit")]
+ public bool m_respawnItemOnHit;
+
+ public GameObject m_spawnOnHit;
+
+ [Range(0f, 1f)]
+ public float m_spawnOnHitChance = 1f;
+
+ public bool m_showBreakMessage;
+
+ public bool m_staticHitOnly;
+
+ public bool m_groundHitOnly;
+
+ public Vector3 m_spawnOffset = Vector3.zero;
+
+ public bool m_spawnRandomRotation;
+
+ public EffectList m_spawnOnHitEffects = new EffectList();
+
+ [Header("Rotate projectile")]
+ public float m_rotateVisual;
+
+ public GameObject m_visual;
+
+ private ZNetView m_nview;
+
+ private Vector3 m_vel = Vector3.zero;
+
+ private Character m_owner;
+
+ private Skills.SkillType m_skill;
+
+ private ItemDrop.ItemData m_spawnItem;
+
+ private bool m_didHit;
+
+ private static int m_rayMaskSolids;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_rayMaskSolids == 0)
+ {
+ m_rayMaskSolids = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle");
+ }
+ m_nview.Register("OnHit", RPC_OnHit);
+ }
+
+ public string GetTooltipString(int itemQuality)
+ {
+ return "";
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ UpdateRotation(Time.fixedDeltaTime);
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ if (!m_didHit)
+ {
+ Vector3 position = base.transform.position;
+ m_vel += Vector3.down * m_gravity * Time.fixedDeltaTime;
+ base.transform.position += m_vel * Time.fixedDeltaTime;
+ if (m_rotateVisual == 0f)
+ {
+ base.transform.rotation = Quaternion.LookRotation(m_vel);
+ }
+ if (m_canHitWater)
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(base.transform.position);
+ if (base.transform.position.y < waterLevel)
+ {
+ OnHit(null, base.transform.position, water: true);
+ }
+ }
+ if (!m_didHit)
+ {
+ Vector3 vector = base.transform.position - position;
+ RaycastHit[] array = Physics.SphereCastAll(position - vector, m_rayRadius, vector.normalized, vector.magnitude * 2f, m_rayMaskSolids);
+ for (int i = 0; i < array.Length; i++)
+ {
+ RaycastHit raycastHit = array[i];
+ OnHit(raycastHit.collider, raycastHit.point, water: false);
+ if (m_didHit)
+ {
+ break;
+ }
+ }
+ }
+ }
+ if (m_ttl > 0f)
+ {
+ m_ttl -= Time.fixedDeltaTime;
+ if (m_ttl <= 0f)
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ }
+ }
+
+ public Vector3 GetVelocity()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return Vector3.zero;
+ }
+ if (m_didHit)
+ {
+ return Vector3.zero;
+ }
+ return m_vel;
+ }
+
+ private void UpdateRotation(float dt)
+ {
+ if ((double)m_rotateVisual != 0.0 && !(m_visual == null))
+ {
+ m_visual.transform.Rotate(new Vector3(m_rotateVisual * dt, 0f, 0f));
+ }
+ }
+
+ public void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemDrop.ItemData item)
+ {
+ m_owner = owner;
+ m_vel = velocity;
+ if (hitNoise >= 0f)
+ {
+ m_hitNoise = hitNoise;
+ }
+ if (hitData != null)
+ {
+ m_damage = hitData.m_damage;
+ m_blockable = hitData.m_blockable;
+ m_dodgeable = hitData.m_dodgeable;
+ m_attackForce = hitData.m_pushForce;
+ m_backstabBonus = hitData.m_backstabBonus;
+ m_statusEffect = hitData.m_statusEffect;
+ m_skill = hitData.m_skill;
+ }
+ if (m_respawnItemOnHit)
+ {
+ m_spawnItem = item;
+ }
+ LineConnect component = GetComponent<LineConnect>();
+ if ((bool)component)
+ {
+ component.SetPeer(owner.GetZDOID());
+ }
+ }
+
+ private void DoAOE(Vector3 hitPoint, ref bool hitCharacter, ref bool didDamage)
+ {
+ Collider[] array = Physics.OverlapSphere(hitPoint, m_aoe, m_rayMaskSolids, QueryTriggerInteraction.UseGlobal);
+ HashSet<GameObject> hashSet = new HashSet<GameObject>();
+ Collider[] array2 = array;
+ foreach (Collider collider in array2)
+ {
+ GameObject gameObject = FindHitObject(collider);
+ IDestructible component = gameObject.GetComponent<IDestructible>();
+ if (component != null && !hashSet.Contains(gameObject))
+ {
+ hashSet.Add(gameObject);
+ if (IsValidTarget(component, ref hitCharacter))
+ {
+ Vector3 vector = collider.ClosestPointOnBounds(hitPoint);
+ Vector3 vector2 = ((Vector3.Distance(vector, hitPoint) > 0.1f) ? (vector - hitPoint) : m_vel);
+ vector2.y = 0f;
+ vector2.Normalize();
+ HitData hitData = new HitData();
+ hitData.m_hitCollider = collider;
+ hitData.m_damage = m_damage;
+ hitData.m_pushForce = m_attackForce;
+ hitData.m_backstabBonus = m_backstabBonus;
+ hitData.m_point = vector;
+ hitData.m_dir = vector2.normalized;
+ hitData.m_statusEffect = m_statusEffect;
+ hitData.m_dodgeable = m_dodgeable;
+ hitData.m_blockable = m_blockable;
+ hitData.m_skill = m_skill;
+ hitData.SetAttacker(m_owner);
+ component.Damage(hitData);
+ didDamage = true;
+ }
+ }
+ }
+ }
+
+ private bool IsValidTarget(IDestructible destr, ref bool hitCharacter)
+ {
+ Character character = destr as Character;
+ if ((bool)character)
+ {
+ if (character == m_owner)
+ {
+ return false;
+ }
+ if (m_owner != null && !m_owner.IsPlayer() && !BaseAI.IsEnemy(m_owner, character))
+ {
+ return false;
+ }
+ if (m_dodgeable && character.IsDodgeInvincible())
+ {
+ return false;
+ }
+ hitCharacter = true;
+ }
+ return true;
+ }
+
+ private void OnHit(Collider collider, Vector3 hitPoint, bool water)
+ {
+ GameObject gameObject = (collider ? FindHitObject(collider) : null);
+ bool didDamage = false;
+ bool hitCharacter = false;
+ if (m_aoe > 0f)
+ {
+ DoAOE(hitPoint, ref hitCharacter, ref didDamage);
+ }
+ else
+ {
+ IDestructible destructible = (gameObject ? gameObject.GetComponent<IDestructible>() : null);
+ if (destructible != null)
+ {
+ if (!IsValidTarget(destructible, ref hitCharacter))
+ {
+ return;
+ }
+ HitData hitData = new HitData();
+ hitData.m_hitCollider = collider;
+ hitData.m_damage = m_damage;
+ hitData.m_pushForce = m_attackForce;
+ hitData.m_backstabBonus = m_backstabBonus;
+ hitData.m_point = hitPoint;
+ hitData.m_dir = base.transform.forward;
+ hitData.m_statusEffect = m_statusEffect;
+ hitData.m_dodgeable = m_dodgeable;
+ hitData.m_blockable = m_blockable;
+ hitData.m_skill = m_skill;
+ hitData.SetAttacker(m_owner);
+ destructible.Damage(hitData);
+ didDamage = true;
+ }
+ }
+ if (water)
+ {
+ m_hitWaterEffects.Create(hitPoint, Quaternion.identity);
+ }
+ else
+ {
+ m_hitEffects.Create(hitPoint, Quaternion.identity);
+ }
+ if (m_spawnOnHit != null || m_spawnItem != null)
+ {
+ SpawnOnHit(gameObject, collider);
+ }
+ if (m_hitNoise > 0f && m_owner != null)
+ {
+ BaseAI.AlertAllInRange(base.transform.position, m_hitNoise, m_owner);
+ }
+ if (m_owner != null && didDamage && m_owner.IsPlayer())
+ {
+ (m_owner as Player).RaiseSkill(m_skill, hitCharacter ? 1f : 0.5f);
+ }
+ m_didHit = true;
+ base.transform.position = hitPoint;
+ m_nview.InvokeRPC("OnHit");
+ if (!m_stayAfterHitStatic)
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ else if ((bool)collider && collider.attachedRigidbody != null)
+ {
+ m_ttl = Mathf.Min(1f, m_ttl);
+ }
+ }
+
+ private void RPC_OnHit(long sender)
+ {
+ if ((bool)m_hideOnHit)
+ {
+ m_hideOnHit.SetActive(value: false);
+ }
+ if (m_stopEmittersOnHit)
+ {
+ ParticleSystem[] componentsInChildren = GetComponentsInChildren<ParticleSystem>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ ParticleSystem.EmissionModule emission = componentsInChildren[i].emission;
+ emission.enabled = false;
+ }
+ }
+ }
+
+ private void SpawnOnHit(GameObject go, Collider collider)
+ {
+ if ((!m_groundHitOnly || !(go.GetComponent<Heightmap>() == null)) && (!m_staticHitOnly || ((!collider || !(collider.attachedRigidbody != null)) && (!go || go.GetComponent<IDestructible>() == null))) && (!(m_spawnOnHitChance < 1f) || !(Random.value > m_spawnOnHitChance)))
+ {
+ Vector3 vector = base.transform.position + base.transform.TransformDirection(m_spawnOffset);
+ Quaternion rotation = base.transform.rotation;
+ if (m_spawnRandomRotation)
+ {
+ rotation = Quaternion.Euler(0f, Random.Range(0, 360), 0f);
+ }
+ if (m_spawnOnHit != null)
+ {
+ Object.Instantiate(m_spawnOnHit, vector, rotation).GetComponent<IProjectile>()?.Setup(m_owner, m_vel, m_hitNoise, null, null);
+ }
+ if (m_spawnItem != null)
+ {
+ ItemDrop.DropItem(m_spawnItem, 0, vector, base.transform.rotation);
+ }
+ m_spawnOnHitEffects.Create(vector, Quaternion.identity);
+ }
+ }
+
+ public static GameObject FindHitObject(Collider collider)
+ {
+ IDestructible componentInParent = collider.gameObject.GetComponentInParent<IDestructible>();
+ if (componentInParent != null)
+ {
+ return (componentInParent as MonoBehaviour).gameObject;
+ }
+ if ((bool)collider.attachedRigidbody)
+ {
+ return collider.attachedRigidbody.gameObject;
+ }
+ return collider.gameObject;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ragdoll.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ragdoll.cs
new file mode 100644
index 0000000..fd7b3a1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ragdoll.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Ragdoll : MonoBehaviour
+{
+ public float m_velMultiplier = 1f;
+
+ public float m_ttl;
+
+ public Renderer m_mainModel;
+
+ public EffectList m_removeEffect = new EffectList();
+
+ public Action<Vector3> m_onDestroyed;
+
+ public bool m_float;
+
+ public float m_floatOffset = -0.1f;
+
+ private const float m_floatForce = 20f;
+
+ private const float m_damping = 0.05f;
+
+ private ZNetView m_nview;
+
+ private Rigidbody[] m_bodies;
+
+ private const float m_dropOffset = 0.75f;
+
+ private const float m_dropArea = 0.5f;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_bodies = GetComponentsInChildren<Rigidbody>();
+ Invoke("RemoveInitVel", 2f);
+ if ((bool)m_mainModel)
+ {
+ float @float = m_nview.GetZDO().GetFloat("Hue");
+ float float2 = m_nview.GetZDO().GetFloat("Saturation");
+ float float3 = m_nview.GetZDO().GetFloat("Value");
+ m_mainModel.material.SetFloat("_Hue", @float);
+ m_mainModel.material.SetFloat("_Saturation", float2);
+ m_mainModel.material.SetFloat("_Value", float3);
+ }
+ if (m_ttl > 0f)
+ {
+ Invoke("DestroyNow", m_ttl);
+ }
+ }
+
+ public Vector3 GetAverageBodyPosition()
+ {
+ if (m_bodies.Length == 0)
+ {
+ return base.transform.position;
+ }
+ Vector3 zero = Vector3.zero;
+ Rigidbody[] bodies = m_bodies;
+ foreach (Rigidbody rigidbody in bodies)
+ {
+ zero += rigidbody.position;
+ }
+ return zero / m_bodies.Length;
+ }
+
+ private void DestroyNow()
+ {
+ if (m_nview.GetZDO().m_owner == 0L)
+ {
+ m_nview.ClaimOwnership();
+ }
+ if (m_nview.IsOwner())
+ {
+ Vector3 averageBodyPosition = GetAverageBodyPosition();
+ m_removeEffect.Create(averageBodyPosition, Quaternion.identity);
+ SpawnLoot(averageBodyPosition);
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ }
+
+ private void RemoveInitVel()
+ {
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("InitVel", Vector3.zero);
+ }
+ }
+
+ private void Start()
+ {
+ Vector3 vec = m_nview.GetZDO().GetVec3("InitVel", Vector3.zero);
+ if (vec != Vector3.zero)
+ {
+ vec.y = Mathf.Min(vec.y, 4f);
+ Rigidbody[] bodies = m_bodies;
+ for (int i = 0; i < bodies.Length; i++)
+ {
+ bodies[i].velocity = vec * UnityEngine.Random.value;
+ }
+ }
+ }
+
+ public void Setup(Vector3 velocity, float hue, float saturation, float value, CharacterDrop characterDrop)
+ {
+ velocity.x *= m_velMultiplier;
+ velocity.z *= m_velMultiplier;
+ m_nview.GetZDO().Set("InitVel", velocity);
+ m_nview.GetZDO().Set("Hue", hue);
+ m_nview.GetZDO().Set("Saturation", saturation);
+ m_nview.GetZDO().Set("Value", value);
+ if ((bool)m_mainModel)
+ {
+ m_mainModel.material.SetFloat("_Hue", hue);
+ m_mainModel.material.SetFloat("_Saturation", saturation);
+ m_mainModel.material.SetFloat("_Value", value);
+ }
+ if ((bool)characterDrop)
+ {
+ SaveLootList(characterDrop);
+ }
+ }
+
+ private void SaveLootList(CharacterDrop characterDrop)
+ {
+ List<KeyValuePair<GameObject, int>> list = characterDrop.GenerateDropList();
+ if (list.Count > 0)
+ {
+ ZDO zDO = m_nview.GetZDO();
+ zDO.Set("drops", list.Count);
+ for (int i = 0; i < list.Count; i++)
+ {
+ KeyValuePair<GameObject, int> keyValuePair = list[i];
+ int prefabHash = ZNetScene.instance.GetPrefabHash(keyValuePair.Key);
+ zDO.Set("drop_hash" + i, prefabHash);
+ zDO.Set("drop_amount" + i, keyValuePair.Value);
+ }
+ }
+ }
+
+ private void SpawnLoot(Vector3 center)
+ {
+ ZDO zDO = m_nview.GetZDO();
+ int @int = zDO.GetInt("drops");
+ if (@int <= 0)
+ {
+ return;
+ }
+ List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
+ for (int i = 0; i < @int; i++)
+ {
+ int int2 = zDO.GetInt("drop_hash" + i);
+ int int3 = zDO.GetInt("drop_amount" + i);
+ GameObject prefab = ZNetScene.instance.GetPrefab(int2);
+ if (prefab == null)
+ {
+ ZLog.LogWarning("Ragdoll: Missing prefab:" + int2 + " when dropping loot");
+ }
+ else
+ {
+ list.Add(new KeyValuePair<GameObject, int>(prefab, int3));
+ }
+ }
+ CharacterDrop.DropItems(list, center + Vector3.up * 0.75f, 0.5f);
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_float)
+ {
+ UpdateFloating(Time.fixedDeltaTime);
+ }
+ }
+
+ private void UpdateFloating(float dt)
+ {
+ Rigidbody[] bodies = m_bodies;
+ foreach (Rigidbody rigidbody in bodies)
+ {
+ Vector3 worldCenterOfMass = rigidbody.worldCenterOfMass;
+ worldCenterOfMass.y += m_floatOffset;
+ float waterLevel = WaterVolume.GetWaterLevel(worldCenterOfMass);
+ if (worldCenterOfMass.y < waterLevel)
+ {
+ float num = (waterLevel - worldCenterOfMass.y) / 0.5f;
+ Vector3 vector = Vector3.up * 20f * num;
+ rigidbody.AddForce(vector * dt, ForceMode.VelocityChange);
+ rigidbody.velocity -= rigidbody.velocity * 0.05f * num;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandEventSystem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandEventSystem.cs
new file mode 100644
index 0000000..e048ba7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandEventSystem.cs
@@ -0,0 +1,504 @@
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public class RandEventSystem : MonoBehaviour
+{
+ private static RandEventSystem m_instance;
+
+ public float m_eventIntervalMin = 1f;
+
+ public float m_eventChance = 25f;
+
+ public float m_randomEventRange = 200f;
+
+ private float m_eventTimer;
+
+ private float m_sendTimer;
+
+ public List<RandomEvent> m_events = new List<RandomEvent>();
+
+ private RandomEvent m_randomEvent;
+
+ private float m_forcedEventUpdateTimer;
+
+ private RandomEvent m_forcedEvent;
+
+ private RandomEvent m_activeEvent;
+
+ private float m_tempSaveEventTimer;
+
+ private string m_tempSaveRandomEvent;
+
+ private float m_tempSaveRandomEventTime;
+
+ private Vector3 m_tempSaveRandomEventPos;
+
+ public static RandEventSystem instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Start()
+ {
+ ZRoutedRpc.instance.Register<string, float, Vector3>("SetEvent", RPC_SetEvent);
+ }
+
+ private void FixedUpdate()
+ {
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ UpdateForcedEvents(fixedDeltaTime);
+ UpdateRandomEvent(fixedDeltaTime);
+ if (m_forcedEvent != null)
+ {
+ m_forcedEvent.Update(ZNet.instance.IsServer(), m_forcedEvent == m_activeEvent, playerInArea: true, fixedDeltaTime);
+ }
+ if (m_randomEvent != null && ZNet.instance.IsServer())
+ {
+ bool playerInArea = IsAnyPlayerInEventArea(m_randomEvent);
+ if (m_randomEvent.Update(server: true, m_randomEvent == m_activeEvent, playerInArea, fixedDeltaTime))
+ {
+ SetRandomEvent(null, Vector3.zero);
+ }
+ }
+ if (m_forcedEvent != null)
+ {
+ SetActiveEvent(m_forcedEvent);
+ }
+ else if (m_randomEvent != null && (bool)Player.m_localPlayer)
+ {
+ if (IsInsideRandomEventArea(m_randomEvent, Player.m_localPlayer.transform.position))
+ {
+ SetActiveEvent(m_randomEvent);
+ }
+ else
+ {
+ SetActiveEvent(null);
+ }
+ }
+ else
+ {
+ SetActiveEvent(null);
+ }
+ }
+
+ private bool IsInsideRandomEventArea(RandomEvent re, Vector3 position)
+ {
+ if (position.y > 3000f)
+ {
+ return false;
+ }
+ return Utils.DistanceXZ(position, re.m_pos) < m_randomEventRange;
+ }
+
+ private void UpdateRandomEvent(float dt)
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ return;
+ }
+ m_eventTimer += dt;
+ if (m_eventTimer > m_eventIntervalMin * 60f)
+ {
+ m_eventTimer = 0f;
+ if (Random.Range(0f, 100f) <= m_eventChance)
+ {
+ StartRandomEvent();
+ }
+ }
+ m_sendTimer += dt;
+ if (m_sendTimer > 2f)
+ {
+ m_sendTimer = 0f;
+ SendCurrentRandomEvent();
+ }
+ }
+
+ private void UpdateForcedEvents(float dt)
+ {
+ m_forcedEventUpdateTimer += dt;
+ if (m_forcedEventUpdateTimer > 2f)
+ {
+ m_forcedEventUpdateTimer = 0f;
+ string forcedEvent = GetForcedEvent();
+ SetForcedEvent(forcedEvent);
+ }
+ }
+
+ private void SetForcedEvent(string name)
+ {
+ if (m_forcedEvent != null && name != null && m_forcedEvent.m_name == name)
+ {
+ return;
+ }
+ if (m_forcedEvent != null)
+ {
+ if (m_forcedEvent == m_activeEvent)
+ {
+ SetActiveEvent(null, end: true);
+ }
+ m_forcedEvent.OnStop();
+ m_forcedEvent = null;
+ }
+ RandomEvent @event = GetEvent(name);
+ if (@event != null)
+ {
+ m_forcedEvent = @event.Clone();
+ m_forcedEvent.OnStart();
+ }
+ }
+
+ private string GetForcedEvent()
+ {
+ if (EnemyHud.instance != null)
+ {
+ Character activeBoss = EnemyHud.instance.GetActiveBoss();
+ if (activeBoss != null && activeBoss.m_bossEvent.Length > 0)
+ {
+ return activeBoss.m_bossEvent;
+ }
+ string @event = EventZone.GetEvent();
+ if (@event != null)
+ {
+ return @event;
+ }
+ }
+ return null;
+ }
+
+ private void SendCurrentRandomEvent()
+ {
+ if (m_randomEvent != null)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SetEvent", m_randomEvent.m_name, m_randomEvent.m_time, m_randomEvent.m_pos);
+ }
+ else
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SetEvent", "", 0f, Vector3.zero);
+ }
+ }
+
+ private void RPC_SetEvent(long sender, string eventName, float time, Vector3 pos)
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ if (m_randomEvent == null || m_randomEvent.m_name != eventName)
+ {
+ SetRandomEventByName(eventName, pos);
+ }
+ if (m_randomEvent != null)
+ {
+ m_randomEvent.m_time = time;
+ m_randomEvent.m_pos = pos;
+ }
+ }
+ }
+
+ public void StartRandomEvent()
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ return;
+ }
+ List<KeyValuePair<RandomEvent, Vector3>> possibleRandomEvents = GetPossibleRandomEvents();
+ ZLog.Log("Possible events:" + possibleRandomEvents.Count);
+ if (possibleRandomEvents.Count == 0)
+ {
+ return;
+ }
+ foreach (KeyValuePair<RandomEvent, Vector3> item in possibleRandomEvents)
+ {
+ ZLog.DevLog("Event " + item.Key.m_name);
+ }
+ KeyValuePair<RandomEvent, Vector3> keyValuePair = possibleRandomEvents[Random.Range(0, possibleRandomEvents.Count)];
+ SetRandomEvent(keyValuePair.Key, keyValuePair.Value);
+ }
+
+ private RandomEvent GetEvent(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ {
+ return null;
+ }
+ foreach (RandomEvent @event in m_events)
+ {
+ if (@event.m_name == name && @event.m_enabled)
+ {
+ return @event;
+ }
+ }
+ return null;
+ }
+
+ public void SetRandomEventByName(string name, Vector3 pos)
+ {
+ RandomEvent @event = GetEvent(name);
+ SetRandomEvent(@event, pos);
+ }
+
+ public void ResetRandomEvent()
+ {
+ SetRandomEvent(null, Vector3.zero);
+ }
+
+ public bool HaveEvent(string name)
+ {
+ return GetEvent(name) != null;
+ }
+
+ private void SetRandomEvent(RandomEvent ev, Vector3 pos)
+ {
+ if (m_randomEvent != null)
+ {
+ if (m_randomEvent == m_activeEvent)
+ {
+ SetActiveEvent(null, end: true);
+ }
+ m_randomEvent.OnStop();
+ m_randomEvent = null;
+ }
+ if (ev != null)
+ {
+ m_randomEvent = ev.Clone();
+ m_randomEvent.m_pos = pos;
+ m_randomEvent.OnStart();
+ ZLog.Log("Random event set:" + ev.m_name);
+ if ((bool)Player.m_localPlayer)
+ {
+ Player.m_localPlayer.ShowTutorial("randomevent");
+ }
+ }
+ if (ZNet.instance.IsServer())
+ {
+ SendCurrentRandomEvent();
+ }
+ }
+
+ private bool IsAnyPlayerInEventArea(RandomEvent re)
+ {
+ foreach (ZDO allCharacterZDO in ZNet.instance.GetAllCharacterZDOS())
+ {
+ if (IsInsideRandomEventArea(re, allCharacterZDO.GetPosition()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List<KeyValuePair<RandomEvent, Vector3>> GetPossibleRandomEvents()
+ {
+ List<KeyValuePair<RandomEvent, Vector3>> list = new List<KeyValuePair<RandomEvent, Vector3>>();
+ List<ZDO> allCharacterZDOS = ZNet.instance.GetAllCharacterZDOS();
+ foreach (RandomEvent @event in m_events)
+ {
+ if (@event.m_enabled && @event.m_random && HaveGlobalKeys(@event))
+ {
+ List<Vector3> validEventPoints = GetValidEventPoints(@event, allCharacterZDOS);
+ if (validEventPoints.Count != 0)
+ {
+ Vector3 value = validEventPoints[Random.Range(0, validEventPoints.Count)];
+ list.Add(new KeyValuePair<RandomEvent, Vector3>(@event, value));
+ }
+ }
+ }
+ return list;
+ }
+
+ private List<Vector3> GetValidEventPoints(RandomEvent ev, List<ZDO> characters)
+ {
+ List<Vector3> list = new List<Vector3>();
+ foreach (ZDO character in characters)
+ {
+ if (InValidBiome(ev, character) && CheckBase(ev, character) && !(character.GetPosition().y > 3000f))
+ {
+ list.Add(character.GetPosition());
+ }
+ }
+ return list;
+ }
+
+ private bool InValidBiome(RandomEvent ev, ZDO zdo)
+ {
+ if (ev.m_biome == Heightmap.Biome.None)
+ {
+ return true;
+ }
+ Vector3 position = zdo.GetPosition();
+ if ((WorldGenerator.instance.GetBiome(position) & ev.m_biome) != 0)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private bool CheckBase(RandomEvent ev, ZDO zdo)
+ {
+ if (ev.m_nearBaseOnly && zdo.GetInt("baseValue") >= 3)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private bool HaveGlobalKeys(RandomEvent ev)
+ {
+ foreach (string requiredGlobalKey in ev.m_requiredGlobalKeys)
+ {
+ if (!ZoneSystem.instance.GetGlobalKey(requiredGlobalKey))
+ {
+ return false;
+ }
+ }
+ foreach (string notRequiredGlobalKey in ev.m_notRequiredGlobalKeys)
+ {
+ if (ZoneSystem.instance.GetGlobalKey(notRequiredGlobalKey))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public List<SpawnSystem.SpawnData> GetCurrentSpawners()
+ {
+ if (m_activeEvent != null)
+ {
+ return m_activeEvent.m_spawn;
+ }
+ return null;
+ }
+
+ public string GetEnvOverride()
+ {
+ if (m_activeEvent != null && !string.IsNullOrEmpty(m_activeEvent.m_forceEnvironment) && m_activeEvent.InEventBiome())
+ {
+ return m_activeEvent.m_forceEnvironment;
+ }
+ return null;
+ }
+
+ public string GetMusicOverride()
+ {
+ if (m_activeEvent != null && !string.IsNullOrEmpty(m_activeEvent.m_forceMusic))
+ {
+ return m_activeEvent.m_forceMusic;
+ }
+ return null;
+ }
+
+ private void SetActiveEvent(RandomEvent ev, bool end = false)
+ {
+ if (ev != null && m_activeEvent != null && ev.m_name == m_activeEvent.m_name)
+ {
+ return;
+ }
+ if (m_activeEvent != null)
+ {
+ m_activeEvent.OnDeactivate(end);
+ m_activeEvent = null;
+ }
+ if (ev != null)
+ {
+ m_activeEvent = ev;
+ if (m_activeEvent != null)
+ {
+ m_activeEvent.OnActivate();
+ }
+ }
+ }
+
+ public static bool InEvent()
+ {
+ if (m_instance == null)
+ {
+ return false;
+ }
+ return m_instance.m_activeEvent != null;
+ }
+
+ public static bool HaveActiveEvent()
+ {
+ if (m_instance == null)
+ {
+ return false;
+ }
+ if (m_instance.m_activeEvent != null)
+ {
+ return true;
+ }
+ if (m_instance.m_randomEvent == null)
+ {
+ return m_instance.m_activeEvent != null;
+ }
+ return true;
+ }
+
+ public RandomEvent GetCurrentRandomEvent()
+ {
+ return m_randomEvent;
+ }
+
+ public RandomEvent GetActiveEvent()
+ {
+ return m_activeEvent;
+ }
+
+ public void PrepareSave()
+ {
+ m_tempSaveEventTimer = m_eventTimer;
+ if (m_randomEvent != null)
+ {
+ m_tempSaveRandomEvent = m_randomEvent.m_name;
+ m_tempSaveRandomEventTime = m_randomEvent.m_time;
+ m_tempSaveRandomEventPos = m_randomEvent.m_pos;
+ }
+ else
+ {
+ m_tempSaveRandomEvent = "";
+ m_tempSaveRandomEventTime = 0f;
+ m_tempSaveRandomEventPos = Vector3.zero;
+ }
+ }
+
+ public void SaveAsync(BinaryWriter writer)
+ {
+ writer.Write(m_tempSaveEventTimer);
+ writer.Write(m_tempSaveRandomEvent);
+ writer.Write(m_tempSaveRandomEventTime);
+ writer.Write(m_tempSaveRandomEventPos.x);
+ writer.Write(m_tempSaveRandomEventPos.y);
+ writer.Write(m_tempSaveRandomEventPos.z);
+ }
+
+ public void Load(BinaryReader reader, int version)
+ {
+ m_eventTimer = reader.ReadSingle();
+ if (version < 25)
+ {
+ return;
+ }
+ string value = reader.ReadString();
+ float time = reader.ReadSingle();
+ Vector3 pos = default(Vector3);
+ pos.x = reader.ReadSingle();
+ pos.y = reader.ReadSingle();
+ pos.z = reader.ReadSingle();
+ if (!string.IsNullOrEmpty(value))
+ {
+ SetRandomEventByName(value, pos);
+ if (m_randomEvent != null)
+ {
+ m_randomEvent.m_time = time;
+ m_randomEvent.m_pos = pos;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomAnimation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomAnimation.cs
new file mode 100644
index 0000000..4ed5f23
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomAnimation.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class RandomAnimation : MonoBehaviour
+{
+ [Serializable]
+ public class RandomValue
+ {
+ public string m_name;
+
+ public int m_values;
+
+ public float m_interval;
+
+ public bool m_floatValue;
+
+ public float m_floatTransition = 1f;
+
+ [NonSerialized]
+ public float m_timer;
+
+ [NonSerialized]
+ public int m_value;
+
+ [NonSerialized]
+ public int[] m_hashValues;
+ }
+
+ public List<RandomValue> m_values = new List<RandomValue>();
+
+ private Animator m_anim;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_anim = GetComponentInChildren<Animator>();
+ m_nview = GetComponent<ZNetView>();
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview != null && !m_nview.IsValid())
+ {
+ return;
+ }
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ for (int i = 0; i < m_values.Count; i++)
+ {
+ RandomValue randomValue = m_values[i];
+ if (m_nview == null || m_nview.IsOwner())
+ {
+ randomValue.m_timer += fixedDeltaTime;
+ if (randomValue.m_timer > randomValue.m_interval)
+ {
+ randomValue.m_timer = 0f;
+ randomValue.m_value = UnityEngine.Random.Range(0, randomValue.m_values);
+ if ((bool)m_nview)
+ {
+ m_nview.GetZDO().Set("RA_" + randomValue.m_name, randomValue.m_value);
+ }
+ if (!randomValue.m_floatValue)
+ {
+ m_anim.SetInteger(randomValue.m_name, randomValue.m_value);
+ }
+ }
+ }
+ if ((bool)m_nview && !m_nview.IsOwner())
+ {
+ int @int = m_nview.GetZDO().GetInt("RA_" + randomValue.m_name);
+ if (@int != randomValue.m_value)
+ {
+ randomValue.m_value = @int;
+ if (!randomValue.m_floatValue)
+ {
+ m_anim.SetInteger(randomValue.m_name, randomValue.m_value);
+ }
+ }
+ }
+ if (!randomValue.m_floatValue)
+ {
+ continue;
+ }
+ if (randomValue.m_hashValues == null || randomValue.m_hashValues.Length != randomValue.m_values)
+ {
+ randomValue.m_hashValues = new int[randomValue.m_values];
+ for (int j = 0; j < randomValue.m_values; j++)
+ {
+ randomValue.m_hashValues[j] = Animator.StringToHash(randomValue.m_name + j);
+ }
+ }
+ for (int k = 0; k < randomValue.m_values; k++)
+ {
+ float @float = m_anim.GetFloat(randomValue.m_hashValues[k]);
+ @float = ((k != randomValue.m_value) ? Mathf.MoveTowards(@float, 0f, fixedDeltaTime / randomValue.m_floatTransition) : Mathf.MoveTowards(@float, 1f, fixedDeltaTime / randomValue.m_floatTransition));
+ m_anim.SetFloat(randomValue.m_hashValues[k], @float);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomEvent.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomEvent.cs
new file mode 100644
index 0000000..8e6df2d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomEvent.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[Serializable]
+public class RandomEvent
+{
+ public string m_name = "";
+
+ public bool m_enabled = true;
+
+ public bool m_random = true;
+
+ public float m_duration = 60f;
+
+ public bool m_nearBaseOnly = true;
+
+ public bool m_pauseIfNoPlayerInArea = true;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ [Header("( Keys required to be TRUE )")]
+ public List<string> m_requiredGlobalKeys = new List<string>();
+
+ [Header("( Keys required to be FALSE )")]
+ public List<string> m_notRequiredGlobalKeys = new List<string>();
+
+ [Space(20f)]
+ public string m_startMessage = "";
+
+ public string m_endMessage = "";
+
+ public string m_forceMusic = "";
+
+ public string m_forceEnvironment = "";
+
+ public List<SpawnSystem.SpawnData> m_spawn = new List<SpawnSystem.SpawnData>();
+
+ private bool m_firstActivation = true;
+
+ private bool m_active;
+
+ [NonSerialized]
+ public float m_time;
+
+ [NonSerialized]
+ public Vector3 m_pos = Vector3.zero;
+
+ public RandomEvent Clone()
+ {
+ RandomEvent randomEvent = MemberwiseClone() as RandomEvent;
+ randomEvent.m_spawn = new List<SpawnSystem.SpawnData>();
+ foreach (SpawnSystem.SpawnData item in m_spawn)
+ {
+ randomEvent.m_spawn.Add(item.Clone());
+ }
+ return randomEvent;
+ }
+
+ public bool Update(bool server, bool active, bool playerInArea, float dt)
+ {
+ if (m_pauseIfNoPlayerInArea && !playerInArea)
+ {
+ return false;
+ }
+ m_time += dt;
+ if (m_duration > 0f && m_time > m_duration)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public void OnActivate()
+ {
+ m_active = true;
+ if (m_firstActivation)
+ {
+ m_firstActivation = false;
+ if (m_startMessage != "")
+ {
+ MessageHud.instance.ShowMessage(MessageHud.MessageType.Center, m_startMessage);
+ }
+ }
+ }
+
+ public void OnDeactivate(bool end)
+ {
+ m_active = false;
+ if (end && m_endMessage != "")
+ {
+ MessageHud.instance.ShowMessage(MessageHud.MessageType.Center, m_endMessage);
+ }
+ }
+
+ public string GetHudText()
+ {
+ return m_startMessage;
+ }
+
+ public void OnStart()
+ {
+ }
+
+ public void OnStop()
+ {
+ }
+
+ public bool InEventBiome()
+ {
+ return (EnvMan.instance.GetCurrentBiome() & m_biome) != 0;
+ }
+
+ public float GetTime()
+ {
+ return m_time;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomFlyingBird.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomFlyingBird.cs
new file mode 100644
index 0000000..a47db33
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomFlyingBird.cs
@@ -0,0 +1,273 @@
+using System;
+using UnityEngine;
+
+public class RandomFlyingBird : MonoBehaviour
+{
+ public float m_flyRange = 20f;
+
+ public float m_minAlt = 5f;
+
+ public float m_maxAlt = 20f;
+
+ public float m_speed = 10f;
+
+ public float m_turnRate = 10f;
+
+ public float m_wpDuration = 4f;
+
+ public float m_flapDuration = 2f;
+
+ public float m_sailDuration = 4f;
+
+ public float m_landChance = 0.5f;
+
+ public float m_landDuration = 2f;
+
+ public float m_avoidDangerDistance = 4f;
+
+ public bool m_noRandomFlightAtNight = true;
+
+ public float m_randomNoiseIntervalMin = 3f;
+
+ public float m_randomNoiseIntervalMax = 6f;
+
+ public bool m_noNoiseAtNight = true;
+
+ public EffectList m_randomNoise = new EffectList();
+
+ public GameObject m_flyingModel;
+
+ public GameObject m_landedModel;
+
+ private Vector3 m_spawnPoint;
+
+ private Vector3 m_waypoint;
+
+ private bool m_groundwp;
+
+ private float m_flyTimer;
+
+ private float m_modeTimer;
+
+ private float m_randomNoiseTimer;
+
+ private ZSyncAnimation m_anim;
+
+ private bool m_flapping = true;
+
+ private float m_landedTimer;
+
+ private static int flapping;
+
+ private ZNetView m_nview;
+
+ protected LODGroup m_lodGroup;
+
+ private Vector3 m_originalLocalRef;
+
+ private bool m_lodVisible = true;
+
+ private void Start()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_anim = GetComponentInChildren<ZSyncAnimation>();
+ m_lodGroup = GetComponent<LODGroup>();
+ m_landedModel.SetActive(value: true);
+ m_flyingModel.SetActive(value: true);
+ if (flapping == 0)
+ {
+ flapping = ZSyncAnimation.GetHash("flapping");
+ }
+ m_spawnPoint = m_nview.GetZDO().GetVec3("spawnpoint", base.transform.position);
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("spawnpoint", m_spawnPoint);
+ }
+ m_randomNoiseTimer = UnityEngine.Random.Range(m_randomNoiseIntervalMin, m_randomNoiseIntervalMax);
+ if (m_nview.IsOwner())
+ {
+ RandomizeWaypoint(ground: false);
+ }
+ if ((bool)m_lodGroup)
+ {
+ m_originalLocalRef = m_lodGroup.localReferencePoint;
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ bool flag = EnvMan.instance.IsDaylight();
+ m_randomNoiseTimer -= fixedDeltaTime;
+ if (m_randomNoiseTimer <= 0f)
+ {
+ if (flag || !m_noNoiseAtNight)
+ {
+ m_randomNoise.Create(base.transform.position, Quaternion.identity, base.transform);
+ }
+ m_randomNoiseTimer = UnityEngine.Random.Range(m_randomNoiseIntervalMin, m_randomNoiseIntervalMax);
+ }
+ bool @bool = m_nview.GetZDO().GetBool("landed");
+ m_landedModel.SetActive(@bool);
+ m_flyingModel.SetActive(!@bool);
+ SetVisible(m_nview.HasOwner());
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ m_flyTimer += fixedDeltaTime;
+ m_modeTimer += fixedDeltaTime;
+ if (@bool)
+ {
+ Vector3 forward = base.transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ base.transform.rotation = Quaternion.LookRotation(forward, Vector3.up);
+ m_landedTimer += fixedDeltaTime;
+ if (((flag || !m_noRandomFlightAtNight) && m_landedTimer > m_landDuration) || DangerNearby(base.transform.position))
+ {
+ m_nview.GetZDO().Set("landed", value: false);
+ RandomizeWaypoint(ground: false);
+ }
+ return;
+ }
+ if (m_flapping)
+ {
+ if (m_modeTimer > m_flapDuration)
+ {
+ m_modeTimer = 0f;
+ m_flapping = false;
+ }
+ }
+ else if (m_modeTimer > m_sailDuration)
+ {
+ m_flapping = true;
+ m_modeTimer = 0f;
+ }
+ m_anim.SetBool(flapping, m_flapping);
+ Vector3 vector = Vector3.Normalize(m_waypoint - base.transform.position);
+ float num = (m_groundwp ? (m_turnRate * 4f) : m_turnRate);
+ Vector3 vector2 = Vector3.RotateTowards(base.transform.forward, vector, num * ((float)Math.PI / 180f) * fixedDeltaTime, 1f);
+ float num2 = Vector3.SignedAngle(base.transform.forward, vector, Vector3.up);
+ Vector3 vector3 = Vector3.Cross(vector2, Vector3.up);
+ Vector3 up = Vector3.up;
+ if (num2 > 0f)
+ {
+ up += -vector3 * 1.5f * Utils.LerpStep(0f, 45f, num2);
+ }
+ else
+ {
+ up += vector3 * 1.5f * Utils.LerpStep(0f, 45f, 0f - num2);
+ }
+ float num3 = m_speed;
+ bool flag2 = false;
+ if (m_groundwp)
+ {
+ float num4 = Vector3.Distance(base.transform.position, m_waypoint);
+ if (num4 < 5f)
+ {
+ num3 *= Mathf.Clamp(num4 / 5f, 0.2f, 1f);
+ vector2.y = 0f;
+ vector2.Normalize();
+ up = Vector3.up;
+ flag2 = true;
+ }
+ if (num4 < 0.2f)
+ {
+ base.transform.position = m_waypoint;
+ m_nview.GetZDO().Set("landed", value: true);
+ m_landedTimer = 0f;
+ m_flapping = true;
+ m_modeTimer = 0f;
+ }
+ }
+ else if (m_flyTimer >= m_wpDuration)
+ {
+ bool ground = UnityEngine.Random.value < m_landChance;
+ RandomizeWaypoint(ground);
+ }
+ Quaternion to = Quaternion.LookRotation(vector2, up.normalized);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, to, 200f * fixedDeltaTime);
+ if (flag2)
+ {
+ base.transform.position += vector * num3 * fixedDeltaTime;
+ }
+ else
+ {
+ base.transform.position += base.transform.forward * num3 * fixedDeltaTime;
+ }
+ }
+
+ private void RandomizeWaypoint(bool ground)
+ {
+ m_flyTimer = 0f;
+ if (ground && FindLandingPoint(out var waypoint))
+ {
+ m_waypoint = waypoint;
+ m_groundwp = true;
+ return;
+ }
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * m_flyRange;
+ m_waypoint = m_spawnPoint + new Vector3(vector.x, 0f, vector.y);
+ if (ZoneSystem.instance.GetSolidHeight(m_waypoint, out var height))
+ {
+ float num = ZoneSystem.instance.m_waterLevel + 2f;
+ if (height < num)
+ {
+ height = num;
+ }
+ m_waypoint.y = height + UnityEngine.Random.Range(m_minAlt, m_maxAlt);
+ }
+ m_groundwp = false;
+ }
+
+ private bool FindLandingPoint(out Vector3 waypoint)
+ {
+ waypoint = new Vector3(0f, -999f, 0f);
+ bool result = false;
+ for (int i = 0; i < 10; i++)
+ {
+ Vector2 vector = UnityEngine.Random.insideUnitCircle * m_flyRange;
+ Vector3 vector2 = m_spawnPoint + new Vector3(vector.x, 0f, vector.y);
+ if (ZoneSystem.instance.GetSolidHeight(vector2, out var height) && height > ZoneSystem.instance.m_waterLevel && height > waypoint.y)
+ {
+ vector2.y = height;
+ if (!DangerNearby(vector2))
+ {
+ waypoint = vector2;
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ private bool DangerNearby(Vector3 p)
+ {
+ if (Player.IsPlayerInRange(p, m_avoidDangerDistance))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void SetVisible(bool visible)
+ {
+ if (!(m_lodGroup == null) && m_lodVisible != visible)
+ {
+ m_lodVisible = visible;
+ if (m_lodVisible)
+ {
+ m_lodGroup.localReferencePoint = m_originalLocalRef;
+ }
+ else
+ {
+ m_lodGroup.localReferencePoint = new Vector3(999999f, 999999f, 999999f);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomIdle.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomIdle.cs
new file mode 100644
index 0000000..ca1f094
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomIdle.cs
@@ -0,0 +1,48 @@
+using UnityEngine;
+
+public class RandomIdle : StateMachineBehaviour
+{
+ public int m_animations = 4;
+
+ public string m_valueName = "";
+
+ public int m_alertedIdle = -1;
+
+ private float m_last;
+
+ private bool m_haveSetup;
+
+ private BaseAI m_baseAI;
+
+ public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
+ {
+ int randomIdle = GetRandomIdle(animator);
+ animator.SetFloat(m_valueName, randomIdle);
+ m_last = stateInfo.normalizedTime % 1f;
+ }
+
+ public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
+ {
+ float num = stateInfo.normalizedTime % 1f;
+ if (num < m_last)
+ {
+ int randomIdle = GetRandomIdle(animator);
+ animator.SetFloat(m_valueName, randomIdle);
+ }
+ m_last = num;
+ }
+
+ private int GetRandomIdle(Animator animator)
+ {
+ if (!m_haveSetup)
+ {
+ m_haveSetup = true;
+ m_baseAI = animator.GetComponentInParent<BaseAI>();
+ }
+ if ((bool)m_baseAI && m_alertedIdle >= 0 && m_baseAI.IsAlerted())
+ {
+ return m_alertedIdle;
+ }
+ return Random.Range(0, m_animations);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomMovement.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomMovement.cs
new file mode 100644
index 0000000..6f273d2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomMovement.cs
@@ -0,0 +1,22 @@
+using UnityEngine;
+
+public class RandomMovement : MonoBehaviour
+{
+ public float m_frequency = 10f;
+
+ public float m_movement = 0.1f;
+
+ private Vector3 m_basePosition = Vector3.zero;
+
+ private void Start()
+ {
+ m_basePosition = base.transform.localPosition;
+ }
+
+ private void Update()
+ {
+ float num = Time.time * m_frequency;
+ Vector3 vector = new Vector3(Mathf.Sin(num) * Mathf.Sin(num * 0.56436f), Mathf.Sin(num * 0.56436f) * Mathf.Sin(num * 0.688742f), Mathf.Cos(num * 0.758348f) * Mathf.Cos(num * 0.4563696f)) * m_movement;
+ base.transform.localPosition = m_basePosition + vector;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpawn.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpawn.cs
new file mode 100644
index 0000000..9038073
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpawn.cs
@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class RandomSpawn : MonoBehaviour
+{
+ public GameObject m_OffObject;
+
+ [Range(0f, 100f)]
+ public float m_chanceToSpawn = 50f;
+
+ private List<ZNetView> m_childNetViews;
+
+ private ZNetView m_nview;
+
+ public void Randomize()
+ {
+ bool spawned = Random.Range(0f, 100f) <= m_chanceToSpawn;
+ SetSpawned(spawned);
+ }
+
+ public void Reset()
+ {
+ SetSpawned(doSpawn: true);
+ }
+
+ private void SetSpawned(bool doSpawn)
+ {
+ if (!doSpawn)
+ {
+ base.gameObject.SetActive(value: false);
+ foreach (ZNetView childNetView in m_childNetViews)
+ {
+ childNetView.gameObject.SetActive(value: false);
+ }
+ }
+ else if (m_nview == null)
+ {
+ base.gameObject.SetActive(value: true);
+ }
+ if (m_OffObject != null)
+ {
+ m_OffObject.SetActive(!doSpawn);
+ }
+ }
+
+ public void Prepare()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_childNetViews = new List<ZNetView>();
+ ZNetView[] componentsInChildren = base.gameObject.GetComponentsInChildren<ZNetView>(includeInactive: true);
+ foreach (ZNetView zNetView in componentsInChildren)
+ {
+ if (Utils.IsEnabledInheirarcy(zNetView.gameObject, base.gameObject))
+ {
+ m_childNetViews.Add(zNetView);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpeak.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpeak.cs
new file mode 100644
index 0000000..b879931
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RandomSpeak.cs
@@ -0,0 +1,45 @@
+using UnityEngine;
+
+public class RandomSpeak : MonoBehaviour
+{
+ public float m_interval = 5f;
+
+ public float m_chance = 0.5f;
+
+ public float m_triggerDistance = 5f;
+
+ public float m_cullDistance = 10f;
+
+ public float m_ttl = 10f;
+
+ public Vector3 m_offset = new Vector3(0f, 0f, 0f);
+
+ public EffectList m_speakEffects = new EffectList();
+
+ public bool m_useLargeDialog;
+
+ public bool m_onlyOnce;
+
+ public string m_topic = "";
+
+ public string[] m_texts = new string[0];
+
+ private void Start()
+ {
+ InvokeRepeating("Speak", Random.Range(0f, m_interval), m_interval);
+ }
+
+ private void Speak()
+ {
+ if (!(Random.value > m_chance) && m_texts.Length != 0 && !(Player.m_localPlayer == null) && !(Vector3.Distance(base.transform.position, Player.m_localPlayer.transform.position) > m_triggerDistance))
+ {
+ m_speakEffects.Create(base.transform.position, base.transform.rotation);
+ string text = m_texts[Random.Range(0, m_texts.Length)];
+ Chat.instance.SetNpcText(base.gameObject, m_offset, m_cullDistance, m_ttl, m_topic, text, m_useLargeDialog);
+ if (m_onlyOnce)
+ {
+ CancelInvoke("Speak");
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Raven.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Raven.cs
new file mode 100644
index 0000000..69335b7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Raven.cs
@@ -0,0 +1,563 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Raven : MonoBehaviour, Hoverable, Interactable, IDestructible
+{
+ [Serializable]
+ public class RavenText
+ {
+ public bool m_alwaysSpawn = true;
+
+ public bool m_munin;
+
+ public int m_priority;
+
+ public string m_key = "";
+
+ public string m_topic = "";
+
+ public string m_label = "";
+
+ [TextArea]
+ public string m_text = "";
+
+ [NonSerialized]
+ public bool m_static;
+
+ [NonSerialized]
+ public GuidePoint m_guidePoint;
+ }
+
+ public GameObject m_visual;
+
+ public GameObject m_exclamation;
+
+ public string m_name = "Name";
+
+ public bool m_isMunin;
+
+ public bool m_autoTalk = true;
+
+ public float m_idleEffectIntervalMin = 10f;
+
+ public float m_idleEffectIntervalMax = 20f;
+
+ public float m_spawnDistance = 15f;
+
+ public float m_despawnDistance = 20f;
+
+ public float m_autoTalkDistance = 3f;
+
+ public float m_enemyCheckDistance = 10f;
+
+ public float m_rotateSpeed = 10f;
+
+ public float m_minRotationAngle = 15f;
+
+ public float m_dialogVisibleTime = 10f;
+
+ public float m_longDialogVisibleTime = 10f;
+
+ public float m_dontFlyDistance = 3f;
+
+ public float m_textOffset = 1.5f;
+
+ public float m_textCullDistance = 20f;
+
+ public float m_randomTextInterval = 30f;
+
+ public float m_randomTextIntervalImportant = 10f;
+
+ public List<string> m_randomTextsImportant = new List<string>();
+
+ public List<string> m_randomTexts = new List<string>();
+
+ public EffectList m_idleEffect = new EffectList();
+
+ public EffectList m_despawnEffect = new EffectList();
+
+ private RavenText m_currentText;
+
+ private GameObject m_groundObject;
+
+ private Animator m_animator;
+
+ private Collider m_collider;
+
+ private bool m_hasTalked;
+
+ private float m_randomTextTimer = 9999f;
+
+ private float m_timeSinceTeleport = 9999f;
+
+ private static List<RavenText> m_tempTexts = new List<RavenText>();
+
+ private static List<RavenText> m_staticTexts = new List<RavenText>();
+
+ private static Raven m_instance = null;
+
+ public static bool IsInstantiated()
+ {
+ return m_instance != null;
+ }
+
+ private void Awake()
+ {
+ base.transform.position = new Vector3(0f, 100000f, 0f);
+ m_instance = this;
+ m_animator = m_visual.GetComponentInChildren<Animator>();
+ m_collider = GetComponent<Collider>();
+ InvokeRepeating("IdleEffect", UnityEngine.Random.Range(m_idleEffectIntervalMin, m_idleEffectIntervalMax), UnityEngine.Random.Range(m_idleEffectIntervalMin, m_idleEffectIntervalMax));
+ InvokeRepeating("CheckSpawn", 1f, 1f);
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (IsSpawned())
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $raven_interact");
+ }
+ return "";
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (m_hasTalked && Chat.instance.IsDialogVisible(base.gameObject))
+ {
+ Chat.instance.ClearNpcText(base.gameObject);
+ }
+ else
+ {
+ Talk();
+ }
+ return false;
+ }
+
+ private void Talk()
+ {
+ if ((bool)Player.m_localPlayer && m_currentText != null)
+ {
+ if (m_currentText.m_key.Length > 0)
+ {
+ Player.m_localPlayer.SetSeenTutorial(m_currentText.m_key);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Raven", m_currentText.m_key, 0L);
+ }
+ else
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Raven", m_currentText.m_topic, 0L);
+ }
+ m_hasTalked = true;
+ if (m_currentText.m_label.Length > 0)
+ {
+ Player.m_localPlayer.AddKnownText(m_currentText.m_label, m_currentText.m_text);
+ }
+ Say(m_currentText.m_topic, m_currentText.m_text, showName: false, longTimeout: true, large: true);
+ }
+ }
+
+ private void Say(string topic, string text, bool showName, bool longTimeout, bool large)
+ {
+ if (topic.Length > 0)
+ {
+ text = "<color=orange>" + topic + "</color>\n" + text;
+ }
+ Chat.instance.SetNpcText(base.gameObject, Vector3.up * m_textOffset, m_textCullDistance, longTimeout ? m_longDialogVisibleTime : m_dialogVisibleTime, showName ? m_name : "", text, large);
+ m_animator.SetTrigger("talk");
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void IdleEffect()
+ {
+ if (IsSpawned())
+ {
+ m_idleEffect.Create(base.transform.position, base.transform.rotation);
+ CancelInvoke("IdleEffect");
+ InvokeRepeating("IdleEffect", UnityEngine.Random.Range(m_idleEffectIntervalMin, m_idleEffectIntervalMax), UnityEngine.Random.Range(m_idleEffectIntervalMin, m_idleEffectIntervalMax));
+ }
+ }
+
+ private bool CanHide()
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return true;
+ }
+ if (Chat.instance.IsDialogVisible(base.gameObject))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void Update()
+ {
+ m_timeSinceTeleport += Time.deltaTime;
+ if (!IsAway() && !IsFlying() && (bool)Player.m_localPlayer)
+ {
+ Vector3 vector = Player.m_localPlayer.transform.position - base.transform.position;
+ vector.y = 0f;
+ vector.Normalize();
+ float f = Vector3.SignedAngle(base.transform.forward, vector, Vector3.up);
+ if (Mathf.Abs(f) > m_minRotationAngle)
+ {
+ m_animator.SetFloat("anglevel", m_rotateSpeed * Mathf.Sign(f), 0.4f, Time.deltaTime);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, Quaternion.LookRotation(vector), Time.deltaTime * m_rotateSpeed);
+ }
+ else
+ {
+ m_animator.SetFloat("anglevel", 0f, 0.4f, Time.deltaTime);
+ }
+ }
+ if (IsSpawned())
+ {
+ if (Player.m_localPlayer != null && !Chat.instance.IsDialogVisible(base.gameObject) && Vector3.Distance(Player.m_localPlayer.transform.position, base.transform.position) < m_autoTalkDistance)
+ {
+ m_randomTextTimer += Time.deltaTime;
+ float num = (m_hasTalked ? m_randomTextInterval : m_randomTextIntervalImportant);
+ if (m_randomTextTimer >= num)
+ {
+ m_randomTextTimer = 0f;
+ if (m_hasTalked)
+ {
+ Say("", m_randomTexts[UnityEngine.Random.Range(0, m_randomTexts.Count)], showName: false, longTimeout: false, large: false);
+ }
+ else
+ {
+ Say("", m_randomTextsImportant[UnityEngine.Random.Range(0, m_randomTextsImportant.Count)], showName: false, longTimeout: false, large: false);
+ }
+ }
+ }
+ if ((Player.m_localPlayer == null || Vector3.Distance(Player.m_localPlayer.transform.position, base.transform.position) > m_despawnDistance || EnemyNearby(base.transform.position) || RandEventSystem.InEvent() || m_currentText == null || m_groundObject == null || m_hasTalked) && CanHide())
+ {
+ bool forceTeleport = GetBestText() != null || m_groundObject == null;
+ FlyAway(forceTeleport);
+ RestartSpawnCheck(3f);
+ }
+ m_exclamation.SetActive(!m_hasTalked);
+ }
+ else
+ {
+ m_exclamation.SetActive(value: false);
+ }
+ }
+
+ private bool FindSpawnPoint(out Vector3 point, out GameObject landOn)
+ {
+ Vector3 position = Player.m_localPlayer.transform.position;
+ Vector3 forward = Utils.GetMainCamera().transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ point = new Vector3(0f, -999f, 0f);
+ landOn = null;
+ bool result = false;
+ for (int i = 0; i < 20; i++)
+ {
+ Vector3 vector = Quaternion.Euler(0f, UnityEngine.Random.Range(-30, 30), 0f) * forward;
+ Vector3 vector2 = position + vector * UnityEngine.Random.Range(m_spawnDistance - 5f, m_spawnDistance);
+ if (ZoneSystem.instance.GetSolidHeight(vector2, out var height, out var normal, out var go) && height > ZoneSystem.instance.m_waterLevel && height > point.y && height < 2000f && normal.y > 0.5f && Mathf.Abs(height - position.y) < 2f)
+ {
+ vector2.y = height;
+ point = vector2;
+ landOn = go;
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ private bool EnemyNearby(Vector3 point)
+ {
+ return LootSpawner.IsMonsterInRange(point, m_enemyCheckDistance);
+ }
+
+ private bool InState(string name)
+ {
+ if (!m_animator.isInitialized)
+ {
+ return false;
+ }
+ if (m_animator.GetCurrentAnimatorStateInfo(0).IsTag(name))
+ {
+ return true;
+ }
+ if (m_animator.GetNextAnimatorStateInfo(0).IsTag(name))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private RavenText GetBestText()
+ {
+ RavenText ravenText = GetTempText();
+ RavenText closestStaticText = GetClosestStaticText(m_spawnDistance);
+ if (closestStaticText != null && (ravenText == null || closestStaticText.m_priority >= ravenText.m_priority))
+ {
+ ravenText = closestStaticText;
+ }
+ return ravenText;
+ }
+
+ private RavenText GetTempText()
+ {
+ foreach (RavenText tempText in m_tempTexts)
+ {
+ if (tempText.m_munin == m_isMunin)
+ {
+ return tempText;
+ }
+ }
+ return null;
+ }
+
+ private RavenText GetClosestStaticText(float maxDistance)
+ {
+ if (Player.m_localPlayer == null)
+ {
+ return null;
+ }
+ RavenText ravenText = null;
+ float num = 9999f;
+ bool flag = false;
+ Vector3 position = Player.m_localPlayer.transform.position;
+ foreach (RavenText staticText in m_staticTexts)
+ {
+ if (staticText.m_munin != m_isMunin || !staticText.m_guidePoint)
+ {
+ continue;
+ }
+ float num2 = Vector3.Distance(position, staticText.m_guidePoint.transform.position);
+ if (!(num2 < maxDistance))
+ {
+ continue;
+ }
+ bool flag2 = staticText.m_key.Length > 0 && Player.m_localPlayer.HaveSeenTutorial(staticText.m_key);
+ if (!staticText.m_alwaysSpawn && flag2)
+ {
+ continue;
+ }
+ if (ravenText == null)
+ {
+ ravenText = staticText;
+ num = num2;
+ flag = flag2;
+ }
+ else if (flag2 == flag)
+ {
+ if (staticText.m_priority == ravenText.m_priority || flag2)
+ {
+ if (num2 < num)
+ {
+ ravenText = staticText;
+ num = num2;
+ flag = flag2;
+ }
+ }
+ else if (staticText.m_priority > ravenText.m_priority)
+ {
+ ravenText = staticText;
+ num = num2;
+ flag = flag2;
+ }
+ }
+ else if (!flag2 && flag)
+ {
+ ravenText = staticText;
+ num = num2;
+ flag = flag2;
+ }
+ }
+ return ravenText;
+ }
+
+ private void RemoveSeendTempTexts()
+ {
+ for (int i = 0; i < m_tempTexts.Count; i++)
+ {
+ if (Player.m_localPlayer.HaveSeenTutorial(m_tempTexts[i].m_key))
+ {
+ m_tempTexts.RemoveAt(i);
+ break;
+ }
+ }
+ }
+
+ private void FlyAway(bool forceTeleport = false)
+ {
+ Chat.instance.ClearNpcText(base.gameObject);
+ if (forceTeleport || IsUnderRoof())
+ {
+ m_animator.SetTrigger("poff");
+ m_timeSinceTeleport = 0f;
+ }
+ else
+ {
+ m_animator.SetTrigger("flyaway");
+ }
+ }
+
+ private void CheckSpawn()
+ {
+ if (!(Player.m_localPlayer == null))
+ {
+ RemoveSeendTempTexts();
+ RavenText bestText = GetBestText();
+ if (IsSpawned() && CanHide() && bestText != null && bestText != m_currentText)
+ {
+ FlyAway(forceTeleport: true);
+ m_currentText = null;
+ }
+ if (IsAway() && bestText != null && !EnemyNearby(base.transform.position) && !RandEventSystem.InEvent())
+ {
+ bool forceTeleport = m_timeSinceTeleport < 6f;
+ Spawn(bestText, forceTeleport);
+ }
+ }
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Character;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (IsSpawned())
+ {
+ m_animator.SetTrigger("poff");
+ RestartSpawnCheck(4f);
+ }
+ }
+
+ private void RestartSpawnCheck(float delay)
+ {
+ CancelInvoke("CheckSpawn");
+ InvokeRepeating("CheckSpawn", delay, 1f);
+ }
+
+ private bool IsSpawned()
+ {
+ return InState("visible");
+ }
+
+ public bool IsAway()
+ {
+ return InState("away");
+ }
+
+ public bool IsFlying()
+ {
+ return InState("flying");
+ }
+
+ private void Spawn(RavenText text, bool forceTeleport)
+ {
+ if (Utils.GetMainCamera() == null)
+ {
+ return;
+ }
+ if (text.m_static)
+ {
+ m_groundObject = text.m_guidePoint.gameObject;
+ base.transform.position = text.m_guidePoint.transform.position;
+ }
+ else
+ {
+ if (!FindSpawnPoint(out var point, out var landOn))
+ {
+ return;
+ }
+ base.transform.position = point;
+ m_groundObject = landOn;
+ }
+ m_currentText = text;
+ m_hasTalked = false;
+ m_randomTextTimer = 99999f;
+ if (m_currentText.m_key.Length > 0 && Player.m_localPlayer.HaveSeenTutorial(m_currentText.m_key))
+ {
+ m_hasTalked = true;
+ }
+ Vector3 forward = Player.m_localPlayer.transform.position - base.transform.position;
+ forward.y = 0f;
+ forward.Normalize();
+ base.transform.rotation = Quaternion.LookRotation(forward);
+ if (forceTeleport)
+ {
+ m_animator.SetTrigger("teleportin");
+ }
+ else if (text.m_static)
+ {
+ if (IsUnderRoof())
+ {
+ m_animator.SetTrigger("teleportin");
+ }
+ else
+ {
+ m_animator.SetTrigger("flyin");
+ }
+ }
+ else
+ {
+ m_animator.SetTrigger("flyin");
+ }
+ }
+
+ private bool IsUnderRoof()
+ {
+ return Physics.Raycast(base.transform.position + Vector3.up * 0.2f, Vector3.up, 20f, LayerMask.GetMask("Default", "static_solid", "piece"));
+ }
+
+ public static void RegisterStaticText(RavenText text)
+ {
+ m_staticTexts.Add(text);
+ }
+
+ public static void UnregisterStaticText(RavenText text)
+ {
+ m_staticTexts.Remove(text);
+ }
+
+ public static void AddTempText(string key, string topic, string text, string label, bool munin)
+ {
+ if (key.Length > 0)
+ {
+ foreach (RavenText tempText in m_tempTexts)
+ {
+ if (tempText.m_key == key)
+ {
+ return;
+ }
+ }
+ }
+ RavenText ravenText = new RavenText();
+ ravenText.m_key = key;
+ ravenText.m_topic = topic;
+ ravenText.m_label = label;
+ ravenText.m_text = text;
+ ravenText.m_static = false;
+ ravenText.m_munin = munin;
+ m_tempTexts.Add(ravenText);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Recipe.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Recipe.cs
new file mode 100644
index 0000000..c3d2bc0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Recipe.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+
+public class Recipe : ScriptableObject
+{
+ public ItemDrop m_item;
+
+ public int m_amount = 1;
+
+ public bool m_enabled = true;
+
+ [Header("Requirements")]
+ public CraftingStation m_craftingStation;
+
+ public CraftingStation m_repairStation;
+
+ public int m_minStationLevel = 1;
+
+ public Piece.Requirement[] m_resources = new Piece.Requirement[0];
+
+ public int GetRequiredStationLevel(int quality)
+ {
+ return Mathf.Max(1, m_minStationLevel) + (quality - 1);
+ }
+
+ public CraftingStation GetRequiredStation(int quality)
+ {
+ if ((bool)m_craftingStation)
+ {
+ return m_craftingStation;
+ }
+ if (quality > 1)
+ {
+ return m_repairStation;
+ }
+ return null;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ReflectionUpdate.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ReflectionUpdate.cs
new file mode 100644
index 0000000..d88d045
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ReflectionUpdate.cs
@@ -0,0 +1,84 @@
+using UnityEngine;
+
+public class ReflectionUpdate : MonoBehaviour
+{
+ private static ReflectionUpdate m_instance;
+
+ public ReflectionProbe m_probe1;
+
+ public ReflectionProbe m_probe2;
+
+ public float m_interval = 3f;
+
+ public float m_reflectionHeight = 5f;
+
+ public float m_transitionDuration = 3f;
+
+ public float m_power = 1f;
+
+ private ReflectionProbe m_current;
+
+ private int m_renderID;
+
+ private float m_updateTimer;
+
+ public static ReflectionUpdate instance => m_instance;
+
+ private void Start()
+ {
+ m_instance = this;
+ m_current = m_probe1;
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ public void UpdateReflection()
+ {
+ Vector3 referencePosition = ZNet.instance.GetReferencePosition();
+ referencePosition += Vector3.up * m_reflectionHeight;
+ m_current = ((m_current == m_probe1) ? m_probe2 : m_probe1);
+ m_current.transform.position = referencePosition;
+ m_renderID = m_current.RenderProbe();
+ }
+
+ private void Update()
+ {
+ float deltaTime = Time.deltaTime;
+ m_updateTimer += deltaTime;
+ if (m_updateTimer > m_interval)
+ {
+ m_updateTimer = 0f;
+ UpdateReflection();
+ }
+ if (m_current.IsFinishedRendering(m_renderID))
+ {
+ float f = Mathf.Clamp01(m_updateTimer / m_transitionDuration);
+ f = Mathf.Pow(f, m_power);
+ if (m_probe1 == m_current)
+ {
+ m_probe1.importance = 1;
+ m_probe2.importance = 0;
+ Vector3 size = m_probe1.size;
+ size.x = 2000f * f;
+ size.y = 1000f * f;
+ size.z = 2000f * f;
+ m_probe1.size = size;
+ m_probe2.size = new Vector3(2001f, 1001f, 2001f);
+ }
+ else
+ {
+ m_probe1.importance = 0;
+ m_probe2.importance = 1;
+ Vector3 size2 = m_probe2.size;
+ size2.x = 2000f * f;
+ size2.y = 1000f * f;
+ size2.z = 2000f * f;
+ m_probe2.size = size2;
+ m_probe1.size = new Vector3(2001f, 1001f, 2001f);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Room.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Room.cs
new file mode 100644
index 0000000..31dc7e6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Room.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Room : MonoBehaviour
+{
+ public enum Theme
+ {
+ Crypt = 1,
+ SunkenCrypt = 2,
+ Cave = 4,
+ ForestCrypt = 8,
+ GoblinCamp = 0x10,
+ MeadowsVillage = 0x20,
+ MeadowsFarm = 0x40
+ }
+
+ private static List<RoomConnection> tempConnections = new List<RoomConnection>();
+
+ public Vector3Int m_size = new Vector3Int(8, 4, 8);
+
+ [BitMask(typeof(Theme))]
+ public Theme m_theme = Theme.Crypt;
+
+ public bool m_enabled = true;
+
+ public bool m_entrance;
+
+ public bool m_endCap;
+
+ public int m_endCapPrio;
+
+ public int m_minPlaceOrder;
+
+ public float m_weight = 1f;
+
+ public bool m_faceCenter;
+
+ public bool m_perimeter;
+
+ [NonSerialized]
+ public int m_placeOrder;
+
+ private RoomConnection[] m_roomConnections;
+
+ private void OnDrawGizmos()
+ {
+ Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
+ Gizmos.matrix = Matrix4x4.TRS(base.transform.position, base.transform.rotation, new Vector3(1f, 1f, 1f));
+ Gizmos.DrawWireCube(Vector3.zero, new Vector3(m_size.x, m_size.y, m_size.z));
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+
+ public int GetHash()
+ {
+ return ZNetView.GetPrefabName(base.gameObject).GetStableHashCode();
+ }
+
+ private void OnEnable()
+ {
+ m_roomConnections = null;
+ }
+
+ public RoomConnection[] GetConnections()
+ {
+ if (m_roomConnections == null)
+ {
+ m_roomConnections = GetComponentsInChildren<RoomConnection>(includeInactive: false);
+ }
+ return m_roomConnections;
+ }
+
+ public RoomConnection GetConnection(RoomConnection other)
+ {
+ RoomConnection[] connections = GetConnections();
+ tempConnections.Clear();
+ RoomConnection[] array = connections;
+ foreach (RoomConnection roomConnection in array)
+ {
+ if (roomConnection.m_type == other.m_type)
+ {
+ tempConnections.Add(roomConnection);
+ }
+ }
+ if (tempConnections.Count == 0)
+ {
+ return null;
+ }
+ return tempConnections[UnityEngine.Random.Range(0, tempConnections.Count)];
+ }
+
+ public RoomConnection GetEntrance()
+ {
+ RoomConnection[] connections = GetConnections();
+ ZLog.Log("Connections " + connections.Length);
+ RoomConnection[] array = connections;
+ foreach (RoomConnection roomConnection in array)
+ {
+ if (roomConnection.m_entrance)
+ {
+ return roomConnection;
+ }
+ }
+ return null;
+ }
+
+ public bool HaveConnection(RoomConnection other)
+ {
+ RoomConnection[] connections = GetConnections();
+ for (int i = 0; i < connections.Length; i++)
+ {
+ if (connections[i].m_type == other.m_type)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoomConnection.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoomConnection.cs
new file mode 100644
index 0000000..36d0285
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoomConnection.cs
@@ -0,0 +1,35 @@
+using System;
+using UnityEngine;
+
+public class RoomConnection : MonoBehaviour
+{
+ public string m_type = "";
+
+ public bool m_entrance;
+
+ public bool m_allowDoor = true;
+
+ [NonSerialized]
+ public int m_placeOrder;
+
+ private void OnDrawGizmos()
+ {
+ if (m_entrance)
+ {
+ Gizmos.color = Color.white;
+ }
+ else
+ {
+ Gizmos.color = new Color(1f, 1f, 0f, 1f);
+ }
+ Gizmos.matrix = Matrix4x4.TRS(base.transform.position, base.transform.rotation, new Vector3(1f, 1f, 1f));
+ Gizmos.DrawCube(Vector3.zero, new Vector3(2f, 0.02f, 0.2f));
+ Gizmos.DrawCube(new Vector3(0f, 0f, 0.35f), new Vector3(0.2f, 0.02f, 0.5f));
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+
+ public bool TestContact(RoomConnection other)
+ {
+ return Vector3.Distance(base.transform.position, other.transform.position) < 0.1f;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RopeAttachment.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RopeAttachment.cs
new file mode 100644
index 0000000..893038a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RopeAttachment.cs
@@ -0,0 +1,66 @@
+using UnityEngine;
+
+public class RopeAttachment : MonoBehaviour, Interactable, Hoverable
+{
+ public string m_name = "Rope";
+
+ public string m_hoverText = "Pull";
+
+ public float m_pullDistance = 5f;
+
+ public float m_pullForce = 1f;
+
+ public float m_maxPullVel = 1f;
+
+ private Rigidbody m_boatBody;
+
+ private Character m_puller;
+
+ private void Awake()
+ {
+ m_boatBody = GetComponentInParent<Rigidbody>();
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if ((bool)m_puller)
+ {
+ m_puller = null;
+ ZLog.Log("Detached rope");
+ }
+ else
+ {
+ m_puller = character;
+ ZLog.Log("Attached rope");
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public string GetHoverText()
+ {
+ return m_hoverText;
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ private void FixedUpdate()
+ {
+ if ((bool)m_puller && Vector3.Distance(m_puller.transform.position, base.transform.position) > m_pullDistance)
+ {
+ Vector3 position = ((m_puller.transform.position - base.transform.position).normalized * m_maxPullVel - m_boatBody.GetPointVelocity(base.transform.position)) * m_pullForce;
+ m_boatBody.AddForceAtPosition(base.transform.position, position);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethod.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethod.cs
new file mode 100644
index 0000000..1db0574
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethod.cs
@@ -0,0 +1,74 @@
+using System;
+
+internal class RoutedMethod : RoutedMethodBase
+{
+ private Action<long> m_action;
+
+ public RoutedMethod(Action<long> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(long rpc, ZPackage pkg)
+ {
+ m_action(rpc);
+ }
+}
+internal class RoutedMethod<T> : RoutedMethodBase
+{
+ private Action<long, T> m_action;
+
+ public RoutedMethod(Action<long, T> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(long rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(ZNetView.Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+}
+internal class RoutedMethod<T, U> : RoutedMethodBase
+{
+ private Action<long, T, U> m_action;
+
+ public RoutedMethod(Action<long, T, U> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(long rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(ZNetView.Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+}
+internal class RoutedMethod<T, U, V> : RoutedMethodBase
+{
+ private Action<long, T, U, V> m_action;
+
+ public RoutedMethod(Action<long, T, U, V> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(long rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(ZNetView.Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+}
+public class RoutedMethod<T, U, V, B> : RoutedMethodBase
+{
+ public delegate void Method(long sender, T p0, U p1, V p2, B p3);
+
+ private Method m_action;
+
+ public RoutedMethod(Method action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(long rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(ZNetView.Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethodBase.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethodBase.cs
new file mode 100644
index 0000000..1039b5d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RoutedMethodBase.cs
@@ -0,0 +1,4 @@
+internal interface RoutedMethodBase
+{
+ void Invoke(long rpc, ZPackage pkg);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RuneStone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RuneStone.cs
new file mode 100644
index 0000000..c245a30
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/RuneStone.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class RuneStone : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public class RandomRuneText
+ {
+ public string m_topic = "";
+
+ public string m_label = "";
+
+ public string m_text = "";
+ }
+
+ public string m_name = "Rune stone";
+
+ public string m_topic = "";
+
+ public string m_label = "";
+
+ public string m_text = "";
+
+ public List<RandomRuneText> m_randomTexts;
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_rune_read");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ Player player = character as Player;
+ RandomRuneText randomText = GetRandomText();
+ if (randomText != null)
+ {
+ if (randomText.m_label.Length > 0)
+ {
+ player.AddKnownText(randomText.m_label, randomText.m_text);
+ }
+ TextViewer.instance.ShowText(TextViewer.Style.Rune, randomText.m_topic, randomText.m_text, autoHide: true);
+ }
+ else
+ {
+ if (m_label.Length > 0)
+ {
+ player.AddKnownText(m_label, m_text);
+ }
+ TextViewer.instance.ShowText(TextViewer.Style.Rune, m_topic, m_text, autoHide: true);
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private RandomRuneText GetRandomText()
+ {
+ if (m_randomTexts.Count == 0)
+ {
+ return null;
+ }
+ Vector3 position = base.transform.position;
+ int seed = (int)position.x * (int)position.z;
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(seed);
+ RandomRuneText result = m_randomTexts[UnityEngine.Random.Range(0, m_randomTexts.Count)];
+ UnityEngine.Random.state = state;
+ return result;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SEMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SEMan.cs
new file mode 100644
index 0000000..6788e8b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SEMan.cs
@@ -0,0 +1,321 @@
+using System.Collections.Generic;
+
+public class SEMan
+{
+ protected List<StatusEffect> m_statusEffects = new List<StatusEffect>();
+
+ private List<StatusEffect> m_removeStatusEffects = new List<StatusEffect>();
+
+ private int m_statusEffectAttributes;
+
+ private Character m_character;
+
+ private ZNetView m_nview;
+
+ public SEMan(Character character, ZNetView nview)
+ {
+ m_character = character;
+ m_nview = nview;
+ m_nview.Register<string, bool>("AddStatusEffect", RPC_AddStatusEffect);
+ }
+
+ public void OnDestroy()
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.OnDestroy();
+ }
+ m_statusEffects.Clear();
+ }
+
+ public void ApplyStatusEffectSpeedMods(ref float speed)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifySpeed(ref speed);
+ }
+ }
+
+ public void ApplyDamageMods(ref HitData.DamageModifiers mods)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyDamageMods(ref mods);
+ }
+ }
+
+ public void Update(float dt)
+ {
+ m_statusEffectAttributes = 0;
+ int count = m_statusEffects.Count;
+ for (int i = 0; i < count; i++)
+ {
+ StatusEffect statusEffect = m_statusEffects[i];
+ statusEffect.UpdateStatusEffect(dt);
+ if (statusEffect.IsDone())
+ {
+ m_removeStatusEffects.Add(statusEffect);
+ }
+ else
+ {
+ m_statusEffectAttributes |= (int)statusEffect.m_attributes;
+ }
+ }
+ if (m_removeStatusEffects.Count > 0)
+ {
+ foreach (StatusEffect removeStatusEffect in m_removeStatusEffects)
+ {
+ removeStatusEffect.Stop();
+ m_statusEffects.Remove(removeStatusEffect);
+ }
+ m_removeStatusEffects.Clear();
+ }
+ m_nview.GetZDO().Set("seAttrib", m_statusEffectAttributes);
+ }
+
+ public StatusEffect AddStatusEffect(string name, bool resetTime = false)
+ {
+ if (m_nview.IsOwner())
+ {
+ return Internal_AddStatusEffect(name, resetTime);
+ }
+ m_nview.InvokeRPC("AddStatusEffect", name, resetTime);
+ return null;
+ }
+
+ private void RPC_AddStatusEffect(long sender, string name, bool resetTime)
+ {
+ if (m_nview.IsOwner())
+ {
+ Internal_AddStatusEffect(name, resetTime);
+ }
+ }
+
+ private StatusEffect Internal_AddStatusEffect(string name, bool resetTime)
+ {
+ StatusEffect statusEffect = GetStatusEffect(name);
+ if ((bool)statusEffect)
+ {
+ if (resetTime)
+ {
+ statusEffect.ResetTime();
+ }
+ return null;
+ }
+ StatusEffect statusEffect2 = ObjectDB.instance.GetStatusEffect(name);
+ if (statusEffect2 == null)
+ {
+ return null;
+ }
+ return AddStatusEffect(statusEffect2);
+ }
+
+ public StatusEffect AddStatusEffect(StatusEffect statusEffect, bool resetTime = false)
+ {
+ StatusEffect statusEffect2 = GetStatusEffect(statusEffect.name);
+ if ((bool)statusEffect2)
+ {
+ if (resetTime)
+ {
+ statusEffect2.ResetTime();
+ }
+ return null;
+ }
+ if (!statusEffect.CanAdd(m_character))
+ {
+ return null;
+ }
+ StatusEffect statusEffect3 = statusEffect.Clone();
+ m_statusEffects.Add(statusEffect3);
+ statusEffect3.Setup(m_character);
+ if (m_character.IsPlayer())
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Game", "StatusEffect", statusEffect.name, 0L);
+ }
+ return statusEffect3;
+ }
+
+ public bool RemoveStatusEffect(StatusEffect se, bool quiet = false)
+ {
+ return RemoveStatusEffect(se.name, quiet);
+ }
+
+ public bool RemoveStatusEffect(string name, bool quiet = false)
+ {
+ for (int i = 0; i < m_statusEffects.Count; i++)
+ {
+ StatusEffect statusEffect = m_statusEffects[i];
+ if (statusEffect.name == name)
+ {
+ if (quiet)
+ {
+ statusEffect.m_stopMessage = "";
+ }
+ statusEffect.Stop();
+ m_statusEffects.Remove(statusEffect);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool HaveStatusEffectCategory(string cat)
+ {
+ if (cat.Length == 0)
+ {
+ return false;
+ }
+ for (int i = 0; i < m_statusEffects.Count; i++)
+ {
+ StatusEffect statusEffect = m_statusEffects[i];
+ if (statusEffect.m_category.Length > 0 && statusEffect.m_category == cat)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool HaveStatusAttribute(StatusEffect.StatusAttribute value)
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ if (m_nview.IsOwner())
+ {
+ return ((uint)m_statusEffectAttributes & (uint)value) != 0;
+ }
+ return ((uint)m_nview.GetZDO().GetInt("seAttrib") & (uint)value) != 0;
+ }
+
+ public bool HaveStatusEffect(string name)
+ {
+ for (int i = 0; i < m_statusEffects.Count; i++)
+ {
+ if (m_statusEffects[i].name == name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<StatusEffect> GetStatusEffects()
+ {
+ return m_statusEffects;
+ }
+
+ public StatusEffect GetStatusEffect(string name)
+ {
+ for (int i = 0; i < m_statusEffects.Count; i++)
+ {
+ StatusEffect statusEffect = m_statusEffects[i];
+ if (statusEffect.name == name)
+ {
+ return statusEffect;
+ }
+ }
+ return null;
+ }
+
+ public void GetHUDStatusEffects(List<StatusEffect> effects)
+ {
+ for (int i = 0; i < m_statusEffects.Count; i++)
+ {
+ StatusEffect statusEffect = m_statusEffects[i];
+ if ((bool)statusEffect.m_icon)
+ {
+ effects.Add(statusEffect);
+ }
+ }
+ }
+
+ public void ModifyNoise(float baseNoise, ref float noise)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyNoise(baseNoise, ref noise);
+ }
+ }
+
+ public void ModifyRaiseSkill(Skills.SkillType skill, ref float multiplier)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyRaiseSkill(skill, ref multiplier);
+ }
+ }
+
+ public void ModifyStaminaRegen(ref float staminaMultiplier)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyStaminaRegen(ref staminaMultiplier);
+ }
+ }
+
+ public void ModifyHealthRegen(ref float regenMultiplier)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyHealthRegen(ref regenMultiplier);
+ }
+ }
+
+ public void ModifyMaxCarryWeight(float baseLimit, ref float limit)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyMaxCarryWeight(baseLimit, ref limit);
+ }
+ }
+
+ public void ModifyStealth(float baseStealth, ref float stealth)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyStealth(baseStealth, ref stealth);
+ }
+ }
+
+ public void ModifyAttack(Skills.SkillType skill, ref HitData hitData)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyAttack(skill, ref hitData);
+ }
+ }
+
+ public void ModifyRunStaminaDrain(float baseDrain, ref float drain)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyRunStaminaDrain(baseDrain, ref drain);
+ }
+ if (drain < 0f)
+ {
+ drain = 0f;
+ }
+ }
+
+ public void ModifyJumpStaminaUsage(float baseStaminaUse, ref float staminaUse)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.ModifyJumpStaminaUsage(baseStaminaUse, ref staminaUse);
+ }
+ if (staminaUse < 0f)
+ {
+ staminaUse = 0f;
+ }
+ }
+
+ public void OnDamaged(HitData hit, Character attacker)
+ {
+ foreach (StatusEffect statusEffect in m_statusEffects)
+ {
+ statusEffect.OnDamaged(hit, attacker);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Burning.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Burning.cs
new file mode 100644
index 0000000..c49db65
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Burning.cs
@@ -0,0 +1,54 @@
+using UnityEngine;
+
+public class SE_Burning : StatusEffect
+{
+ [Header("SE_Burning")]
+ public float m_damageInterval = 1f;
+
+ private float m_timer;
+
+ private float m_totalDamage;
+
+ private HitData.DamageTypes m_damage;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (m_character.GetSEMan().HaveStatusEffect("Wet"))
+ {
+ m_time += dt * 5f;
+ }
+ m_timer -= dt;
+ if (m_timer <= 0f)
+ {
+ m_timer = m_damageInterval;
+ HitData hitData = new HitData();
+ hitData.m_point = m_character.GetCenterPoint();
+ hitData.m_damage = m_damage.Clone();
+ m_character.ApplyDamage(hitData, showDamageText: true, triggerEffects: false);
+ }
+ }
+
+ public void AddFireDamage(float damage)
+ {
+ m_totalDamage = Mathf.Max(m_totalDamage, damage);
+ int num = (int)(m_ttl / m_damageInterval);
+ float fire = m_totalDamage / (float)num;
+ m_damage.m_fire = fire;
+ ResetTime();
+ }
+
+ public void AddSpiritDamage(float damage)
+ {
+ m_totalDamage = Mathf.Max(m_totalDamage, damage);
+ int num = (int)(m_ttl / m_damageInterval);
+ float spirit = m_totalDamage / (float)num;
+ m_damage.m_spirit = spirit;
+ ResetTime();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Cozy.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Cozy.cs
new file mode 100644
index 0000000..20ecf8c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Cozy.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+
+public class SE_Cozy : SE_Stats
+{
+ [Header("__SE_Cozy__")]
+ public float m_delay = 10f;
+
+ public string m_statusEffect = "";
+
+ private int m_comfortLevel;
+
+ private float m_updateTimer;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ m_character.Message(MessageHud.MessageType.Center, "$se_resting_start");
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (m_time > m_delay)
+ {
+ m_character.GetSEMan().AddStatusEffect(m_statusEffect, resetTime: true);
+ }
+ }
+
+ public override string GetIconText()
+ {
+ Player player = m_character as Player;
+ return Localization.instance.Localize("$se_rested_comfort:" + player.GetComfortLevel());
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Finder.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Finder.cs
new file mode 100644
index 0000000..d38cb25
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Finder.cs
@@ -0,0 +1,71 @@
+using UnityEngine;
+
+public class SE_Finder : StatusEffect
+{
+ [Header("SE_Finder")]
+ public EffectList m_pingEffectNear = new EffectList();
+
+ public EffectList m_pingEffectMed = new EffectList();
+
+ public EffectList m_pingEffectFar = new EffectList();
+
+ public float m_closerTriggerDistance = 2f;
+
+ public float m_furtherTriggerDistance = 4f;
+
+ public float m_closeFrequency = 1f;
+
+ public float m_distantFrequency = 5f;
+
+ private float m_updateBeaconTimer;
+
+ private float m_pingTimer;
+
+ private Beacon m_beacon;
+
+ private float m_lastDistance;
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ m_updateBeaconTimer += dt;
+ if (m_updateBeaconTimer > 1f)
+ {
+ m_updateBeaconTimer = 0f;
+ Beacon beacon = Beacon.FindClosestBeaconInRange(m_character.transform.position);
+ if (beacon != m_beacon)
+ {
+ m_beacon = beacon;
+ if ((bool)m_beacon)
+ {
+ m_lastDistance = Utils.DistanceXZ(m_character.transform.position, m_beacon.transform.position);
+ m_pingTimer = 0f;
+ }
+ }
+ }
+ if (!(m_beacon != null))
+ {
+ return;
+ }
+ float num = Utils.DistanceXZ(m_character.transform.position, m_beacon.transform.position);
+ float num2 = Mathf.Clamp01(num / m_beacon.m_range);
+ float num3 = Mathf.Lerp(m_closeFrequency, m_distantFrequency, num2);
+ m_pingTimer += dt;
+ if (m_pingTimer > num3)
+ {
+ m_pingTimer = 0f;
+ if (num2 < 0.2f)
+ {
+ m_pingEffectNear.Create(m_character.transform.position, m_character.transform.rotation, m_character.transform);
+ }
+ else if (num2 < 0.6f)
+ {
+ m_pingEffectMed.Create(m_character.transform.position, m_character.transform.rotation, m_character.transform);
+ }
+ else
+ {
+ m_pingEffectFar.Create(m_character.transform.position, m_character.transform.rotation, m_character.transform);
+ }
+ m_lastDistance = num;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Frost.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Frost.cs
new file mode 100644
index 0000000..e988a7d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Frost.cs
@@ -0,0 +1,36 @@
+using UnityEngine;
+
+public class SE_Frost : StatusEffect
+{
+ [Header("SE_Frost")]
+ public float m_freezeTimeEnemy = 10f;
+
+ public float m_freezeTimePlayer = 10f;
+
+ public float m_minSpeedFactor = 0.1f;
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ }
+
+ public void AddDamage(float damage)
+ {
+ float num = (m_character.IsPlayer() ? m_freezeTimePlayer : m_freezeTimeEnemy);
+ float num2 = Mathf.Clamp01(damage / m_character.GetMaxHealth()) * num;
+ float num3 = m_ttl - m_time;
+ if (num2 > num3)
+ {
+ m_ttl = num2;
+ ResetTime();
+ TriggerStartEffects();
+ }
+ }
+
+ public override void ModifySpeed(ref float speed)
+ {
+ float f = Mathf.Clamp01(m_time / m_ttl);
+ f = Mathf.Pow(f, 2f);
+ speed *= Mathf.Clamp(f, m_minSpeedFactor, 1f);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Harpooned.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Harpooned.cs
new file mode 100644
index 0000000..b145556
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Harpooned.cs
@@ -0,0 +1,128 @@
+using UnityEngine;
+
+public class SE_Harpooned : StatusEffect
+{
+ [Header("SE_Harpooned")]
+ public float m_minForce = 2f;
+
+ public float m_maxForce = 10f;
+
+ public float m_minDistance = 6f;
+
+ public float m_maxDistance = 30f;
+
+ public float m_staminaDrain = 10f;
+
+ public float m_staminaDrainInterval = 0.1f;
+
+ public float m_maxMass = 50f;
+
+ private bool m_broken;
+
+ private Character m_attacker;
+
+ private float m_drainStaminaTimer;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ }
+
+ public override void SetAttacker(Character attacker)
+ {
+ ZLog.Log("Setting attacker " + attacker.m_name);
+ m_attacker = attacker;
+ m_time = 0f;
+ if (Vector3.Distance(m_attacker.transform.position, m_character.transform.position) > m_maxDistance)
+ {
+ m_attacker.Message(MessageHud.MessageType.Center, "Target too far");
+ m_broken = true;
+ return;
+ }
+ m_attacker.Message(MessageHud.MessageType.Center, m_character.m_name + " harpooned");
+ GameObject[] startEffectInstances = m_startEffectInstances;
+ foreach (GameObject gameObject in startEffectInstances)
+ {
+ if ((bool)gameObject)
+ {
+ LineConnect component = gameObject.GetComponent<LineConnect>();
+ if ((bool)component)
+ {
+ component.SetPeer(m_attacker.GetComponent<ZNetView>());
+ }
+ }
+ }
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (!m_attacker)
+ {
+ return;
+ }
+ Rigidbody component = m_character.GetComponent<Rigidbody>();
+ if (!component)
+ {
+ return;
+ }
+ Vector3 vector = m_attacker.transform.position - m_character.transform.position;
+ Vector3 normalized = vector.normalized;
+ float radius = m_character.GetRadius();
+ float magnitude = vector.magnitude;
+ float num = Mathf.Clamp01(Vector3.Dot(normalized, component.velocity));
+ float t = Utils.LerpStep(m_minDistance, m_maxDistance, magnitude);
+ float num2 = Mathf.Lerp(m_minForce, m_maxForce, t);
+ float num3 = Mathf.Clamp01(m_maxMass / component.mass);
+ float num4 = num2 * num3;
+ if (magnitude - radius > m_minDistance && num < num4)
+ {
+ normalized.y = 0f;
+ normalized.Normalize();
+ _ = (bool)m_character.GetStandingOnShip();
+ if (!m_character.IsAttached())
+ {
+ component.AddForce(normalized * num4, ForceMode.VelocityChange);
+ }
+ m_drainStaminaTimer += dt;
+ if (m_drainStaminaTimer > m_staminaDrainInterval)
+ {
+ m_drainStaminaTimer = 0f;
+ float num5 = 1f - Mathf.Clamp01(num / num2);
+ m_attacker.UseStamina(m_staminaDrain * num5);
+ }
+ }
+ if (magnitude > m_maxDistance)
+ {
+ m_broken = true;
+ m_attacker.Message(MessageHud.MessageType.Center, "Line broke");
+ }
+ if (!m_attacker.HaveStamina())
+ {
+ m_broken = true;
+ m_attacker.Message(MessageHud.MessageType.Center, m_character.m_name + " escaped");
+ }
+ }
+
+ public override bool IsDone()
+ {
+ if (base.IsDone())
+ {
+ return true;
+ }
+ if (m_broken)
+ {
+ return true;
+ }
+ if (!m_attacker)
+ {
+ return true;
+ }
+ if (m_time > 2f && (m_attacker.IsBlocking() || m_attacker.InAttack()))
+ {
+ m_attacker.Message(MessageHud.MessageType.Center, m_character.m_name + " released");
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs
new file mode 100644
index 0000000..a733ac9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs
@@ -0,0 +1,36 @@
+using UnityEngine;
+
+public class SE_HealthUpgrade : StatusEffect
+{
+ [Header("Health")]
+ public float m_moreHealth;
+
+ [Header("Stamina")]
+ public float m_moreStamina;
+
+ public EffectList m_upgradeEffect = new EffectList();
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ }
+
+ public override void Stop()
+ {
+ base.Stop();
+ Player player = m_character as Player;
+ if ((bool)player)
+ {
+ if (m_moreHealth > 0f)
+ {
+ player.SetMaxHealth(m_character.GetMaxHealth() + m_moreHealth, flashBar: true);
+ player.SetHealth(m_character.GetMaxHealth());
+ }
+ if (m_moreStamina > 0f)
+ {
+ player.SetMaxStamina(m_character.GetMaxStamina() + m_moreStamina, flashBar: true);
+ }
+ m_upgradeEffect.Create(m_character.transform.position, Quaternion.identity);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Poison.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Poison.cs
new file mode 100644
index 0000000..7da4506
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Poison.cs
@@ -0,0 +1,50 @@
+using UnityEngine;
+
+public class SE_Poison : StatusEffect
+{
+ [Header("SE_Poison")]
+ public float m_damageInterval = 1f;
+
+ public float m_baseTTL = 2f;
+
+ public float m_TTLPerDamagePlayer = 2f;
+
+ public float m_TTLPerDamage = 2f;
+
+ public float m_TTLPower = 0.5f;
+
+ private float m_timer;
+
+ private float m_damageLeft;
+
+ private float m_damagePerHit;
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ m_timer -= dt;
+ if (m_timer <= 0f)
+ {
+ m_timer = m_damageInterval;
+ HitData hitData = new HitData();
+ hitData.m_point = m_character.GetCenterPoint();
+ hitData.m_damage.m_poison = m_damagePerHit;
+ m_damageLeft -= m_damagePerHit;
+ m_character.ApplyDamage(hitData, showDamageText: true, triggerEffects: false);
+ }
+ }
+
+ public void AddDamage(float damage)
+ {
+ if (damage >= m_damageLeft)
+ {
+ m_damageLeft = damage;
+ float num = (m_character.IsPlayer() ? m_TTLPerDamagePlayer : m_TTLPerDamage);
+ m_ttl = m_baseTTL + Mathf.Pow(m_damageLeft * num, m_TTLPower);
+ int num2 = (int)(m_ttl / m_damageInterval);
+ m_damagePerHit = m_damageLeft / (float)num2;
+ ZLog.Log("Poison damage: " + m_damageLeft + " ttl:" + m_ttl + " hits:" + num2 + " dmg perhit:" + m_damagePerHit);
+ ResetTime();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Rested.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Rested.cs
new file mode 100644
index 0000000..8af611f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Rested.cs
@@ -0,0 +1,98 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SE_Rested : SE_Stats
+{
+ private static int ghostLayer = 0;
+
+ private static List<Piece> m_tempPieces = new List<Piece>();
+
+ [Header("__SE_Rested__")]
+ public float m_baseTTL = 300f;
+
+ public float m_TTLPerComfortLevel = 60f;
+
+ private const float m_comfortRadius = 10f;
+
+ private float m_timeSinceComfortUpdate;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ UpdateTTL();
+ Player player = m_character as Player;
+ m_character.Message(MessageHud.MessageType.Center, "$se_rested_start ($se_rested_comfort:" + player.GetComfortLevel() + ")");
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ m_timeSinceComfortUpdate -= dt;
+ }
+
+ public override void ResetTime()
+ {
+ UpdateTTL();
+ }
+
+ private void UpdateTTL()
+ {
+ Player player = m_character as Player;
+ float num = m_baseTTL + (float)(player.GetComfortLevel() - 1) * m_TTLPerComfortLevel;
+ float num2 = m_ttl - m_time;
+ if (num > num2)
+ {
+ m_ttl = num;
+ m_time = 0f;
+ }
+ }
+
+ private static int PieceComfortSort(Piece x, Piece y)
+ {
+ if (x.m_comfortGroup != y.m_comfortGroup)
+ {
+ return x.m_comfortGroup.CompareTo(y.m_comfortGroup);
+ }
+ if (x.m_comfort != y.m_comfort)
+ {
+ return x.m_comfort.CompareTo(y.m_comfort);
+ }
+ return y.m_name.CompareTo(x.m_name);
+ }
+
+ public static int CalculateComfortLevel(Player player)
+ {
+ if (ghostLayer == 0)
+ {
+ ghostLayer = LayerMask.NameToLayer("ghost");
+ }
+ List<Piece> nearbyPieces = GetNearbyPieces(player.transform.position);
+ nearbyPieces.Sort(PieceComfortSort);
+ int num = 1;
+ if (player.InShelter())
+ {
+ num++;
+ for (int i = 0; i < nearbyPieces.Count; i++)
+ {
+ Piece piece = nearbyPieces[i];
+ if (i > 0)
+ {
+ Piece piece2 = nearbyPieces[i - 1];
+ if (piece2.gameObject.layer == ghostLayer || (piece.m_comfortGroup != 0 && piece.m_comfortGroup == piece2.m_comfortGroup) || piece.m_name == piece2.m_name)
+ {
+ continue;
+ }
+ }
+ num += piece.m_comfort;
+ }
+ }
+ return num;
+ }
+
+ private static List<Piece> GetNearbyPieces(Vector3 point)
+ {
+ m_tempPieces.Clear();
+ Piece.GetAllPiecesInRadius(point, 10f, m_tempPieces);
+ return m_tempPieces;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Shield.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Shield.cs
new file mode 100644
index 0000000..0fd1124
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Shield.cs
@@ -0,0 +1,36 @@
+using UnityEngine;
+
+public class SE_Shield : StatusEffect
+{
+ [Header("__SE_Shield__")]
+ public float m_absorbDamage = 100f;
+
+ public EffectList m_breakEffects = new EffectList();
+
+ public EffectList m_hitEffects = new EffectList();
+
+ private float m_damage;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ }
+
+ public override bool IsDone()
+ {
+ if (m_damage > m_absorbDamage)
+ {
+ m_breakEffects.Create(m_character.GetCenterPoint(), m_character.transform.rotation, m_character.transform, m_character.GetRadius() * 2f);
+ return true;
+ }
+ return base.IsDone();
+ }
+
+ public override void OnDamaged(HitData hit, Character attacker)
+ {
+ float totalDamage = hit.GetTotalDamage();
+ m_damage += totalDamage;
+ hit.ApplyModifier(0f);
+ m_hitEffects.Create(hit.m_point, Quaternion.identity);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Smoke.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Smoke.cs
new file mode 100644
index 0000000..bc47a88
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Smoke.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+
+public class SE_Smoke : StatusEffect
+{
+ [Header("SE_Burning")]
+ public HitData.DamageTypes m_damage;
+
+ public float m_damageInterval = 1f;
+
+ private float m_timer;
+
+ public override bool CanAdd(Character character)
+ {
+ if (character.m_tolerateSmoke)
+ {
+ return false;
+ }
+ return base.CanAdd(character);
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ m_timer += dt;
+ if (m_timer > m_damageInterval)
+ {
+ m_timer = 0f;
+ HitData hitData = new HitData();
+ hitData.m_point = m_character.GetCenterPoint();
+ hitData.m_damage = m_damage;
+ m_character.ApplyDamage(hitData, showDamageText: true, triggerEffects: false);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Spawn.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Spawn.cs
new file mode 100644
index 0000000..0a8ec6c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Spawn.cs
@@ -0,0 +1,32 @@
+using UnityEngine;
+
+public class SE_Spawn : StatusEffect
+{
+ [Header("__SE_Spawn__")]
+ public float m_delay = 10f;
+
+ public GameObject m_prefab;
+
+ public Vector3 m_spawnOffset = new Vector3(0f, 0f, 0f);
+
+ public EffectList m_spawnEffect = new EffectList();
+
+ private bool m_spawned;
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (!m_spawned && m_time > m_delay)
+ {
+ m_spawned = true;
+ Vector3 position = m_character.transform.TransformVector(m_spawnOffset);
+ GameObject gameObject = Object.Instantiate(m_prefab, position, Quaternion.identity);
+ Projectile component = gameObject.GetComponent<Projectile>();
+ if ((bool)component)
+ {
+ component.Setup(m_character, Vector3.zero, -1f, null, null);
+ }
+ m_spawnEffect.Create(gameObject.transform.position, gameObject.transform.rotation);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Stats.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Stats.cs
new file mode 100644
index 0000000..91aab87
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Stats.cs
@@ -0,0 +1,322 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SE_Stats : StatusEffect
+{
+ [Header("__SE_Stats__")]
+ [Header("HP per tick")]
+ public float m_tickInterval;
+
+ public float m_healthPerTickMinHealthPercentage;
+
+ public float m_healthPerTick;
+
+ [Header("Health over time")]
+ public float m_healthOverTime;
+
+ public float m_healthOverTimeDuration;
+
+ public float m_healthOverTimeInterval = 5f;
+
+ [Header("Stamina")]
+ public float m_staminaOverTime;
+
+ public float m_staminaOverTimeDuration;
+
+ public float m_staminaDrainPerSec;
+
+ public float m_runStaminaDrainModifier;
+
+ public float m_jumpStaminaUseModifier;
+
+ [Header("Regen modifiers")]
+ public float m_healthRegenMultiplier = 1f;
+
+ public float m_staminaRegenMultiplier = 1f;
+
+ [Header("Modify raise skill")]
+ public Skills.SkillType m_raiseSkill;
+
+ public float m_raiseSkillModifier;
+
+ [Header("Hit modifier")]
+ public List<HitData.DamageModPair> m_mods = new List<HitData.DamageModPair>();
+
+ [Header("Attack")]
+ public Skills.SkillType m_modifyAttackSkill;
+
+ public float m_damageModifier = 1f;
+
+ [Header("Sneak")]
+ public float m_noiseModifier;
+
+ public float m_stealthModifier;
+
+ [Header("Carry weight")]
+ public float m_addMaxCarryWeight;
+
+ private float m_tickTimer;
+
+ private float m_healthOverTimeTimer;
+
+ private float m_healthOverTimeTicks;
+
+ private float m_healthOverTimeTickHP;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ if (m_healthOverTime > 0f && m_healthOverTimeInterval > 0f)
+ {
+ if (m_healthOverTimeDuration <= 0f)
+ {
+ m_healthOverTimeDuration = m_ttl;
+ }
+ m_healthOverTimeTicks = m_healthOverTimeDuration / m_healthOverTimeInterval;
+ m_healthOverTimeTickHP = m_healthOverTime / m_healthOverTimeTicks;
+ }
+ if (m_staminaOverTime > 0f && m_staminaOverTimeDuration <= 0f)
+ {
+ m_staminaOverTimeDuration = m_ttl;
+ }
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (m_tickInterval > 0f)
+ {
+ m_tickTimer += dt;
+ if (m_tickTimer >= m_tickInterval)
+ {
+ m_tickTimer = 0f;
+ if (m_character.GetHealthPercentage() >= m_healthPerTickMinHealthPercentage)
+ {
+ if (m_healthPerTick > 0f)
+ {
+ m_character.Heal(m_healthPerTick);
+ }
+ else
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_damage = 0f - m_healthPerTick;
+ hitData.m_point = m_character.GetTopPoint();
+ m_character.Damage(hitData);
+ }
+ }
+ }
+ }
+ if (m_healthOverTimeTicks > 0f)
+ {
+ m_healthOverTimeTimer += dt;
+ if (m_healthOverTimeTimer > m_healthOverTimeInterval)
+ {
+ m_healthOverTimeTimer = 0f;
+ m_healthOverTimeTicks -= 1f;
+ m_character.Heal(m_healthOverTimeTickHP);
+ }
+ }
+ if (m_staminaOverTime != 0f && m_time <= m_staminaOverTimeDuration)
+ {
+ float num = m_staminaOverTimeDuration / dt;
+ m_character.AddStamina(m_staminaOverTime / num);
+ }
+ if (m_staminaDrainPerSec > 0f)
+ {
+ m_character.UseStamina(m_staminaDrainPerSec * dt);
+ }
+ }
+
+ public override void ModifyHealthRegen(ref float regenMultiplier)
+ {
+ if (m_healthRegenMultiplier > 1f)
+ {
+ regenMultiplier += m_healthRegenMultiplier - 1f;
+ }
+ else
+ {
+ regenMultiplier *= m_healthRegenMultiplier;
+ }
+ }
+
+ public override void ModifyStaminaRegen(ref float staminaRegen)
+ {
+ if (m_staminaRegenMultiplier > 1f)
+ {
+ staminaRegen += m_staminaRegenMultiplier - 1f;
+ }
+ else
+ {
+ staminaRegen *= m_staminaRegenMultiplier;
+ }
+ }
+
+ public override void ModifyDamageMods(ref HitData.DamageModifiers modifiers)
+ {
+ modifiers.Apply(m_mods);
+ }
+
+ public override void ModifyRaiseSkill(Skills.SkillType skill, ref float value)
+ {
+ if (m_raiseSkill != 0 && (m_raiseSkill == Skills.SkillType.All || m_raiseSkill == skill))
+ {
+ value += m_raiseSkillModifier;
+ }
+ }
+
+ public override void ModifyNoise(float baseNoise, ref float noise)
+ {
+ noise += baseNoise * m_noiseModifier;
+ }
+
+ public override void ModifyStealth(float baseStealth, ref float stealth)
+ {
+ stealth += baseStealth * m_stealthModifier;
+ }
+
+ public override void ModifyMaxCarryWeight(float baseLimit, ref float limit)
+ {
+ limit += m_addMaxCarryWeight;
+ if (limit < 0f)
+ {
+ limit = 0f;
+ }
+ }
+
+ public override void ModifyAttack(Skills.SkillType skill, ref HitData hitData)
+ {
+ if (skill == m_modifyAttackSkill || m_modifyAttackSkill == Skills.SkillType.All)
+ {
+ hitData.m_damage.Modify(m_damageModifier);
+ }
+ }
+
+ public override void ModifyRunStaminaDrain(float baseDrain, ref float drain)
+ {
+ drain += baseDrain * m_runStaminaDrainModifier;
+ }
+
+ public override void ModifyJumpStaminaUsage(float baseStaminaUse, ref float staminaUse)
+ {
+ staminaUse += baseStaminaUse * m_jumpStaminaUseModifier;
+ }
+
+ public override string GetTooltipString()
+ {
+ string text = "";
+ if (m_tooltip.Length > 0)
+ {
+ text = text + m_tooltip + "\n";
+ }
+ if (m_jumpStaminaUseModifier != 0f)
+ {
+ text = text + "$se_jumpstamina: " + (m_jumpStaminaUseModifier * 100f).ToString("+0;-0") + "%\n";
+ }
+ if (m_runStaminaDrainModifier != 0f)
+ {
+ text = text + "$se_runstamina: " + (m_runStaminaDrainModifier * 100f).ToString("+0;-0") + "%\n";
+ }
+ if (m_healthOverTime != 0f)
+ {
+ text = text + "$se_health: " + m_healthOverTime + "\n";
+ }
+ if (m_staminaOverTime != 0f)
+ {
+ text = text + "$se_stamina: " + m_staminaOverTime + "\n";
+ }
+ if (m_healthRegenMultiplier != 1f)
+ {
+ text = text + "$se_healthregen " + ((m_healthRegenMultiplier - 1f) * 100f).ToString("+0;-0") + "%\n";
+ }
+ if (m_staminaRegenMultiplier != 1f)
+ {
+ text = text + "$se_staminaregen " + ((m_staminaRegenMultiplier - 1f) * 100f).ToString("+0;-0") + "%\n";
+ }
+ if (m_addMaxCarryWeight != 0f)
+ {
+ text = text + "$se_max_carryweight " + m_addMaxCarryWeight.ToString("+0;-0") + "\n";
+ }
+ if (m_mods.Count > 0)
+ {
+ text += GetDamageModifiersTooltipString(m_mods);
+ }
+ if (m_noiseModifier != 0f)
+ {
+ text = text + "$se_noisemod " + (m_noiseModifier * 100f).ToString("+0;-0") + "%\n";
+ }
+ if (m_stealthModifier != 0f)
+ {
+ text = text + "$se_sneakmod " + ((0f - m_stealthModifier) * 100f).ToString("+0;-0") + "%\n";
+ }
+ return text;
+ }
+
+ public static string GetDamageModifiersTooltipString(List<HitData.DamageModPair> mods)
+ {
+ if (mods.Count == 0)
+ {
+ return "";
+ }
+ string text = "";
+ foreach (HitData.DamageModPair mod in mods)
+ {
+ if (mod.m_modifier != HitData.DamageModifier.Ignore && mod.m_modifier != 0)
+ {
+ switch (mod.m_modifier)
+ {
+ case HitData.DamageModifier.Immune:
+ text += "\n$inventory_dmgmod: <color=orange>$inventory_immune</color> VS ";
+ break;
+ case HitData.DamageModifier.Resistant:
+ text += "\n$inventory_dmgmod: <color=orange>$inventory_resistant</color> VS ";
+ break;
+ case HitData.DamageModifier.VeryResistant:
+ text += "\n$inventory_dmgmod: <color=orange>$inventory_veryresistant</color> VS ";
+ break;
+ case HitData.DamageModifier.Weak:
+ text += "\n$inventory_dmgmod: <color=orange>$inventory_weak</color> VS ";
+ break;
+ case HitData.DamageModifier.VeryWeak:
+ text += "\n$inventory_dmgmod: <color=orange>$inventory_veryweak</color> VS ";
+ break;
+ }
+ text += "<color=orange>";
+ switch (mod.m_type)
+ {
+ case HitData.DamageType.Blunt:
+ text += "$inventory_blunt";
+ break;
+ case HitData.DamageType.Slash:
+ text += "$inventory_slash";
+ break;
+ case HitData.DamageType.Pierce:
+ text += "$inventory_pierce";
+ break;
+ case HitData.DamageType.Chop:
+ text += "$inventory_chop";
+ break;
+ case HitData.DamageType.Pickaxe:
+ text += "$inventory_pickaxe";
+ break;
+ case HitData.DamageType.Fire:
+ text += "$inventory_fire";
+ break;
+ case HitData.DamageType.Frost:
+ text += "$inventory_frost";
+ break;
+ case HitData.DamageType.Lightning:
+ text += "$inventory_lightning";
+ break;
+ case HitData.DamageType.Poison:
+ text += "$inventory_poison";
+ break;
+ case HitData.DamageType.Spirit:
+ text += "$inventory_spirit";
+ break;
+ }
+ text += "</color>";
+ }
+ }
+ return text;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Wet.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Wet.cs
new file mode 100644
index 0000000..a501d1b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SE_Wet.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+
+public class SE_Wet : SE_Stats
+{
+ [Header("__SE_Wet__")]
+ public float m_waterDamage;
+
+ public float m_damageInterval = 0.5f;
+
+ private float m_timer;
+
+ public override void Setup(Character character)
+ {
+ base.Setup(character);
+ }
+
+ public override void UpdateStatusEffect(float dt)
+ {
+ base.UpdateStatusEffect(dt);
+ if (!m_character.m_tolerateWater)
+ {
+ m_timer += dt;
+ if (m_timer > m_damageInterval)
+ {
+ m_timer = 0f;
+ HitData hitData = new HitData();
+ hitData.m_point = m_character.transform.position;
+ hitData.m_damage.m_damage = m_waterDamage;
+ m_character.Damage(hitData);
+ }
+ }
+ if (m_character.GetSEMan().HaveStatusEffect("CampFire"))
+ {
+ m_time += dt * 10f;
+ }
+ if (m_character.GetSEMan().HaveStatusEffect("Burning"))
+ {
+ m_time += dt * 50f;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SceneLoader.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SceneLoader.cs
new file mode 100644
index 0000000..c5f0faf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SceneLoader.cs
@@ -0,0 +1,23 @@
+using System.Collections;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class SceneLoader : MonoBehaviour
+{
+ public string m_scene = "";
+
+ private void Start()
+ {
+ StartCoroutine(LoadYourAsyncScene());
+ }
+
+ private IEnumerator LoadYourAsyncScene()
+ {
+ ZLog.Log("Starting to load scene:" + m_scene);
+ AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(m_scene, LoadSceneMode.Single);
+ while (!asyncLoad.isDone)
+ {
+ yield return null;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs
new file mode 100644
index 0000000..b0c807d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs
@@ -0,0 +1,93 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+[RequireComponent(typeof(ScrollRect))]
+public class ScrollRectEnsureVisible : MonoBehaviour
+{
+ private RectTransform maskTransform;
+
+ private ScrollRect mScrollRect;
+
+ private RectTransform mScrollTransform;
+
+ private RectTransform mContent;
+
+ private bool mInitialized;
+
+ private void Awake()
+ {
+ if (!mInitialized)
+ {
+ Initialize();
+ }
+ }
+
+ private void Initialize()
+ {
+ mScrollRect = GetComponent<ScrollRect>();
+ mScrollTransform = mScrollRect.transform as RectTransform;
+ mContent = mScrollRect.content;
+ Reset();
+ mInitialized = true;
+ }
+
+ public void CenterOnItem(RectTransform target)
+ {
+ if (!mInitialized)
+ {
+ Initialize();
+ }
+ Vector3 worldPointInWidget = GetWorldPointInWidget(mScrollTransform, GetWidgetWorldPoint(target));
+ Vector3 vector = GetWorldPointInWidget(mScrollTransform, GetWidgetWorldPoint(maskTransform)) - worldPointInWidget;
+ vector.z = 0f;
+ if (!mScrollRect.horizontal)
+ {
+ vector.x = 0f;
+ }
+ if (!mScrollRect.vertical)
+ {
+ vector.y = 0f;
+ }
+ Vector2 vector2 = new Vector2(vector.x / (mContent.rect.size.x - mScrollTransform.rect.size.x), vector.y / (mContent.rect.size.y - mScrollTransform.rect.size.y));
+ Vector2 normalizedPosition = mScrollRect.normalizedPosition - vector2;
+ if (mScrollRect.movementType != 0)
+ {
+ normalizedPosition.x = Mathf.Clamp01(normalizedPosition.x);
+ normalizedPosition.y = Mathf.Clamp01(normalizedPosition.y);
+ }
+ mScrollRect.normalizedPosition = normalizedPosition;
+ }
+
+ private void Reset()
+ {
+ if (!(maskTransform == null))
+ {
+ return;
+ }
+ Mask componentInChildren = GetComponentInChildren<Mask>(includeInactive: true);
+ if ((bool)componentInChildren)
+ {
+ maskTransform = componentInChildren.rectTransform;
+ }
+ if (maskTransform == null)
+ {
+ RectMask2D componentInChildren2 = GetComponentInChildren<RectMask2D>(includeInactive: true);
+ if ((bool)componentInChildren2)
+ {
+ maskTransform = componentInChildren2.rectTransform;
+ }
+ }
+ }
+
+ private Vector3 GetWidgetWorldPoint(RectTransform target)
+ {
+ Vector3 vector = new Vector3((0.5f - target.pivot.x) * target.rect.size.x, (0.5f - target.pivot.y) * target.rect.size.y, 0f);
+ Vector3 position = target.localPosition + vector;
+ return target.parent.TransformPoint(position);
+ }
+
+ private Vector3 GetWorldPointInWidget(RectTransform target, Vector3 worldPoint)
+ {
+ return target.InverseTransformPoint(worldPoint);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ServerCtrl.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ServerCtrl.cs
new file mode 100644
index 0000000..7ce8e7c
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ServerCtrl.cs
@@ -0,0 +1,53 @@
+using System.IO;
+using UnityEngine;
+
+public class ServerCtrl
+{
+ private static ServerCtrl m_instance;
+
+ private float m_checkTimer;
+
+ public static ServerCtrl instance => m_instance;
+
+ public static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new ServerCtrl();
+ }
+ }
+
+ private ServerCtrl()
+ {
+ ClearExitFile();
+ }
+
+ public void Update(float dt)
+ {
+ CheckExit(dt);
+ }
+
+ private void CheckExit(float dt)
+ {
+ m_checkTimer += dt;
+ if (m_checkTimer > 2f)
+ {
+ m_checkTimer = 0f;
+ if (File.Exists("server_exit.drp"))
+ {
+ Application.Quit();
+ }
+ }
+ }
+
+ private void ClearExitFile()
+ {
+ try
+ {
+ File.Delete("server_exit.drp");
+ }
+ catch
+ {
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Settings.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Settings.cs
new file mode 100644
index 0000000..066f8f6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Settings.cs
@@ -0,0 +1,582 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Audio;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class Settings : MonoBehaviour
+{
+ [Serializable]
+ public class KeySetting
+ {
+ public string m_keyName = "";
+
+ public RectTransform m_keyTransform;
+ }
+
+ private static Settings m_instance;
+
+ [Header("Inout")]
+ public Slider m_sensitivitySlider;
+
+ public Toggle m_invertMouse;
+
+ public Toggle m_gamepadEnabled;
+
+ public GameObject m_bindDialog;
+
+ public List<KeySetting> m_keys = new List<KeySetting>();
+
+ [Header("Misc")]
+ public Toggle m_cameraShake;
+
+ public Toggle m_shipCameraTilt;
+
+ public Toggle m_quickPieceSelect;
+
+ public Toggle m_showKeyHints;
+
+ public Slider m_guiScaleSlider;
+
+ public Text m_guiScaleText;
+
+ public Text m_language;
+
+ public Button m_resetTutorial;
+
+ [Header("Audio")]
+ public Slider m_volumeSlider;
+
+ public Slider m_sfxVolumeSlider;
+
+ public Slider m_musicVolumeSlider;
+
+ public Toggle m_continousMusic;
+
+ public AudioMixer m_masterMixer;
+
+ [Header("Graphics")]
+ public Toggle m_dofToggle;
+
+ public Toggle m_vsyncToggle;
+
+ public Toggle m_bloomToggle;
+
+ public Toggle m_ssaoToggle;
+
+ public Toggle m_sunshaftsToggle;
+
+ public Toggle m_aaToggle;
+
+ public Toggle m_caToggle;
+
+ public Toggle m_motionblurToggle;
+
+ public Toggle m_tesselationToggle;
+
+ public Toggle m_softPartToggle;
+
+ public Toggle m_fullscreenToggle;
+
+ public Slider m_shadowQuality;
+
+ public Text m_shadowQualityText;
+
+ public Slider m_lod;
+
+ public Text m_lodText;
+
+ public Slider m_lights;
+
+ public Text m_lightsText;
+
+ public Slider m_vegetation;
+
+ public Text m_vegetationText;
+
+ public Text m_resButtonText;
+
+ public GameObject m_resDialog;
+
+ public GameObject m_resListElement;
+
+ public RectTransform m_resListRoot;
+
+ public Scrollbar m_resListScroll;
+
+ public float m_resListSpace = 20f;
+
+ public GameObject m_resSwitchDialog;
+
+ public Text m_resSwitchCountdown;
+
+ public int m_minResWidth = 1280;
+
+ public int m_minResHeight = 720;
+
+ private string m_languageKey = "";
+
+ private bool m_oldFullscreen;
+
+ private Resolution m_oldRes;
+
+ private Resolution m_selectedRes;
+
+ private List<GameObject> m_resObjects = new List<GameObject>();
+
+ private List<Resolution> m_resolutions = new List<Resolution>();
+
+ private float m_resListBaseSize;
+
+ private bool m_modeApplied;
+
+ private float m_resCountdownTimer = 1f;
+
+ public static Settings instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_bindDialog.SetActive(value: false);
+ m_resDialog.SetActive(value: false);
+ m_resSwitchDialog.SetActive(value: false);
+ m_resListBaseSize = m_resListRoot.rect.height;
+ LoadSettings();
+ SetupKeys();
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void Update()
+ {
+ if (m_bindDialog.activeSelf)
+ {
+ UpdateBinding();
+ return;
+ }
+ UpdateResSwitch(Time.deltaTime);
+ AudioListener.volume = m_volumeSlider.value;
+ MusicMan.m_masterMusicVolume = m_musicVolumeSlider.value;
+ AudioMan.SetSFXVolume(m_sfxVolumeSlider.value);
+ SetQualityText(m_shadowQualityText, (int)m_shadowQuality.value);
+ SetQualityText(m_lodText, (int)m_lod.value);
+ SetQualityText(m_lightsText, (int)m_lights.value);
+ SetQualityText(m_vegetationText, (int)m_vegetation.value);
+ m_resButtonText.text = m_selectedRes.width + "x" + m_selectedRes.height + " " + m_selectedRes.refreshRate + "hz";
+ m_guiScaleText.text = m_guiScaleSlider.value + "%";
+ GuiScaler.SetScale(m_guiScaleSlider.value / 100f);
+ if (Input.GetKeyDown(KeyCode.Escape))
+ {
+ OnBack();
+ }
+ }
+
+ private void SetQualityText(Text text, int level)
+ {
+ switch (level)
+ {
+ case 0:
+ text.text = Localization.instance.Localize("[$settings_low]");
+ break;
+ case 1:
+ text.text = Localization.instance.Localize("[$settings_medium]");
+ break;
+ case 2:
+ text.text = Localization.instance.Localize("[$settings_high]");
+ break;
+ case 3:
+ text.text = Localization.instance.Localize("[$settings_veryhigh]");
+ break;
+ }
+ }
+
+ public void OnBack()
+ {
+ RevertMode();
+ LoadSettings();
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+
+ public void OnOk()
+ {
+ SaveSettings();
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+
+ private void SaveSettings()
+ {
+ PlayerPrefs.SetFloat("MasterVolume", m_volumeSlider.value);
+ PlayerPrefs.SetFloat("MouseSensitivity", m_sensitivitySlider.value);
+ PlayerPrefs.SetFloat("MusicVolume", m_musicVolumeSlider.value);
+ PlayerPrefs.SetFloat("SfxVolume", m_sfxVolumeSlider.value);
+ PlayerPrefs.SetInt("ContinousMusic", m_continousMusic.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("InvertMouse", m_invertMouse.isOn ? 1 : 0);
+ PlayerPrefs.SetFloat("GuiScale", m_guiScaleSlider.value / 100f);
+ PlayerPrefs.SetInt("CameraShake", m_cameraShake.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("ShipCameraTilt", m_shipCameraTilt.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("QuickPieceSelect", m_quickPieceSelect.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("KeyHints", m_showKeyHints.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("DOF", m_dofToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("VSync", m_vsyncToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("Bloom", m_bloomToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("SSAO", m_ssaoToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("SunShafts", m_sunshaftsToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("AntiAliasing", m_aaToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("ChromaticAberration", m_caToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("MotionBlur", m_motionblurToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("SoftPart", m_softPartToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("Tesselation", m_tesselationToggle.isOn ? 1 : 0);
+ PlayerPrefs.SetInt("ShadowQuality", (int)m_shadowQuality.value);
+ PlayerPrefs.SetInt("LodBias", (int)m_lod.value);
+ PlayerPrefs.SetInt("Lights", (int)m_lights.value);
+ PlayerPrefs.SetInt("ClutterQuality", (int)m_vegetation.value);
+ ZInput.SetGamepadEnabled(m_gamepadEnabled.isOn);
+ ZInput.instance.Save();
+ if ((bool)GameCamera.instance)
+ {
+ GameCamera.instance.ApplySettings();
+ }
+ if ((bool)CameraEffects.instance)
+ {
+ CameraEffects.instance.ApplySettings();
+ }
+ if ((bool)ClutterSystem.instance)
+ {
+ ClutterSystem.instance.ApplySettings();
+ }
+ if ((bool)MusicMan.instance)
+ {
+ MusicMan.instance.ApplySettings();
+ }
+ if ((bool)GameCamera.instance)
+ {
+ GameCamera.instance.ApplySettings();
+ }
+ if ((bool)KeyHints.instance)
+ {
+ KeyHints.instance.ApplySettings();
+ }
+ ApplyQualitySettings();
+ ApplyMode();
+ PlayerController.m_mouseSens = m_sensitivitySlider.value;
+ PlayerController.m_invertMouse = m_invertMouse.isOn;
+ Localization.instance.SetLanguage(m_languageKey);
+ GuiScaler.LoadGuiScale();
+ PlayerPrefs.Save();
+ }
+
+ public static void ApplyStartupSettings()
+ {
+ QualitySettings.vSyncCount = ((PlayerPrefs.GetInt("VSync", 0) == 1) ? 1 : 0);
+ ApplyQualitySettings();
+ }
+
+ private static void ApplyQualitySettings()
+ {
+ QualitySettings.softParticles = PlayerPrefs.GetInt("SoftPart", 1) == 1;
+ if (PlayerPrefs.GetInt("Tesselation", 1) == 1)
+ {
+ Shader.EnableKeyword("TESSELATION_ON");
+ }
+ else
+ {
+ Shader.DisableKeyword("TESSELATION_ON");
+ }
+ switch (PlayerPrefs.GetInt("LodBias", 2))
+ {
+ case 0:
+ QualitySettings.lodBias = 1f;
+ break;
+ case 1:
+ QualitySettings.lodBias = 1.5f;
+ break;
+ case 2:
+ QualitySettings.lodBias = 2f;
+ break;
+ case 3:
+ QualitySettings.lodBias = 5f;
+ break;
+ }
+ switch (PlayerPrefs.GetInt("Lights", 2))
+ {
+ case 0:
+ QualitySettings.pixelLightCount = 2;
+ break;
+ case 1:
+ QualitySettings.pixelLightCount = 4;
+ break;
+ case 2:
+ QualitySettings.pixelLightCount = 8;
+ break;
+ }
+ ApplyShadowQuality();
+ }
+
+ private static void ApplyShadowQuality()
+ {
+ switch (PlayerPrefs.GetInt("ShadowQuality", 2))
+ {
+ case 0:
+ QualitySettings.shadowCascades = 2;
+ QualitySettings.shadowDistance = 80f;
+ QualitySettings.shadowResolution = ShadowResolution.Low;
+ break;
+ case 1:
+ QualitySettings.shadowCascades = 3;
+ QualitySettings.shadowDistance = 120f;
+ QualitySettings.shadowResolution = ShadowResolution.Medium;
+ break;
+ case 2:
+ QualitySettings.shadowCascades = 4;
+ QualitySettings.shadowDistance = 150f;
+ QualitySettings.shadowResolution = ShadowResolution.High;
+ break;
+ }
+ }
+
+ private void LoadSettings()
+ {
+ ZInput.instance.Load();
+ AudioListener.volume = PlayerPrefs.GetFloat("MasterVolume", AudioListener.volume);
+ MusicMan.m_masterMusicVolume = PlayerPrefs.GetFloat("MusicVolume", 1f);
+ AudioMan.SetSFXVolume(PlayerPrefs.GetFloat("SfxVolume", 1f));
+ m_continousMusic.isOn = PlayerPrefs.GetInt("ContinousMusic", 0) == 1;
+ PlayerController.m_mouseSens = PlayerPrefs.GetFloat("MouseSensitivity", PlayerController.m_mouseSens);
+ PlayerController.m_invertMouse = PlayerPrefs.GetInt("InvertMouse", 0) == 1;
+ float @float = PlayerPrefs.GetFloat("GuiScale", 1f);
+ m_volumeSlider.value = AudioListener.volume;
+ m_sensitivitySlider.value = PlayerController.m_mouseSens;
+ m_sfxVolumeSlider.value = AudioMan.GetSFXVolume();
+ m_musicVolumeSlider.value = MusicMan.m_masterMusicVolume;
+ m_guiScaleSlider.value = @float * 100f;
+ m_invertMouse.isOn = PlayerController.m_invertMouse;
+ m_gamepadEnabled.isOn = ZInput.IsGamepadEnabled();
+ m_languageKey = Localization.instance.GetSelectedLanguage();
+ m_language.text = Localization.instance.Localize("$language_" + m_languageKey.ToLower());
+ m_cameraShake.isOn = PlayerPrefs.GetInt("CameraShake", 1) == 1;
+ m_shipCameraTilt.isOn = PlayerPrefs.GetInt("ShipCameraTilt", 1) == 1;
+ m_quickPieceSelect.isOn = PlayerPrefs.GetInt("QuickPieceSelect", 0) == 1;
+ m_showKeyHints.isOn = PlayerPrefs.GetInt("KeyHints", 1) == 1;
+ m_dofToggle.isOn = PlayerPrefs.GetInt("DOF", 1) == 1;
+ m_vsyncToggle.isOn = PlayerPrefs.GetInt("VSync", 0) == 1;
+ m_bloomToggle.isOn = PlayerPrefs.GetInt("Bloom", 1) == 1;
+ m_ssaoToggle.isOn = PlayerPrefs.GetInt("SSAO", 1) == 1;
+ m_sunshaftsToggle.isOn = PlayerPrefs.GetInt("SunShafts", 1) == 1;
+ m_aaToggle.isOn = PlayerPrefs.GetInt("AntiAliasing", 1) == 1;
+ m_caToggle.isOn = PlayerPrefs.GetInt("ChromaticAberration", 1) == 1;
+ m_motionblurToggle.isOn = PlayerPrefs.GetInt("MotionBlur", 1) == 1;
+ m_softPartToggle.isOn = PlayerPrefs.GetInt("SoftPart", 1) == 1;
+ m_tesselationToggle.isOn = PlayerPrefs.GetInt("Tesselation", 1) == 1;
+ m_shadowQuality.value = PlayerPrefs.GetInt("ShadowQuality", 2);
+ m_lod.value = PlayerPrefs.GetInt("LodBias", 2);
+ m_lights.value = PlayerPrefs.GetInt("Lights", 2);
+ m_vegetation.value = PlayerPrefs.GetInt("ClutterQuality", 2);
+ m_fullscreenToggle.isOn = Screen.fullScreen;
+ m_oldFullscreen = m_fullscreenToggle.isOn;
+ m_oldRes = Screen.currentResolution;
+ m_oldRes.width = Screen.width;
+ m_oldRes.height = Screen.height;
+ m_selectedRes = m_oldRes;
+ ZLog.Log("Current res " + Screen.currentResolution.width + "x" + Screen.currentResolution.height + " " + Screen.width + "x" + Screen.height);
+ }
+
+ private void SetupKeys()
+ {
+ foreach (KeySetting key in m_keys)
+ {
+ key.m_keyTransform.GetComponentInChildren<Button>().onClick.AddListener(OnKeySet);
+ }
+ UpdateBindings();
+ }
+
+ private void UpdateBindings()
+ {
+ foreach (KeySetting key in m_keys)
+ {
+ key.m_keyTransform.GetComponentInChildren<Button>().GetComponentInChildren<Text>().text = Localization.instance.GetBoundKeyString(key.m_keyName);
+ }
+ }
+
+ private void OnKeySet()
+ {
+ foreach (KeySetting key in m_keys)
+ {
+ if (key.m_keyTransform.GetComponentInChildren<Button>().gameObject == EventSystem.current.currentSelectedGameObject)
+ {
+ OpenBindDialog(key.m_keyName);
+ return;
+ }
+ }
+ ZLog.Log("NOT FOUND");
+ }
+
+ private void OpenBindDialog(string keyName)
+ {
+ ZLog.Log("BInding key " + keyName);
+ ZInput.instance.StartBindKey(keyName);
+ m_bindDialog.SetActive(value: true);
+ }
+
+ private void UpdateBinding()
+ {
+ if (m_bindDialog.activeSelf && ZInput.instance.EndBindKey())
+ {
+ m_bindDialog.SetActive(value: false);
+ UpdateBindings();
+ }
+ }
+
+ public void ResetBindings()
+ {
+ ZInput.instance.Reset();
+ UpdateBindings();
+ }
+
+ public void OnLanguageLeft()
+ {
+ m_languageKey = Localization.instance.GetPrevLanguage(m_languageKey);
+ m_language.text = Localization.instance.Localize("$language_" + m_languageKey.ToLower());
+ }
+
+ public void OnLanguageRight()
+ {
+ m_languageKey = Localization.instance.GetNextLanguage(m_languageKey);
+ m_language.text = Localization.instance.Localize("$language_" + m_languageKey.ToLower());
+ }
+
+ public void OnShowResList()
+ {
+ m_resDialog.SetActive(value: true);
+ FillResList();
+ }
+
+ private void UpdateValidResolutions()
+ {
+ Resolution[] array = Screen.resolutions;
+ if (array.Length == 0)
+ {
+ array = new Resolution[1] { m_oldRes };
+ }
+ m_resolutions.Clear();
+ Resolution[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ Resolution item = array2[i];
+ if ((item.width >= m_minResWidth && item.height >= m_minResHeight) || item.width == m_oldRes.width || item.height == m_oldRes.height)
+ {
+ m_resolutions.Add(item);
+ }
+ }
+ if (m_resolutions.Count == 0)
+ {
+ Resolution item2 = default(Resolution);
+ item2.width = 1280;
+ item2.height = 720;
+ item2.refreshRate = 60;
+ m_resolutions.Add(item2);
+ }
+ }
+
+ private void FillResList()
+ {
+ foreach (GameObject resObject in m_resObjects)
+ {
+ UnityEngine.Object.Destroy(resObject);
+ }
+ m_resObjects.Clear();
+ UpdateValidResolutions();
+ float num = 0f;
+ foreach (Resolution resolution in m_resolutions)
+ {
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_resListElement, m_resListRoot.transform);
+ gameObject.SetActive(value: true);
+ gameObject.GetComponentInChildren<Button>().onClick.AddListener(OnResClick);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, num * (0f - m_resListSpace));
+ gameObject.GetComponentInChildren<Text>().text = resolution.width + "x" + resolution.height + " " + resolution.refreshRate + "hz";
+ m_resObjects.Add(gameObject);
+ num += 1f;
+ }
+ float size = Mathf.Max(m_resListBaseSize, num * m_resListSpace);
+ m_resListRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ m_resListScroll.value = 1f;
+ }
+
+ public void OnResCancel()
+ {
+ m_resDialog.SetActive(value: false);
+ }
+
+ private void OnResClick()
+ {
+ m_resDialog.SetActive(value: false);
+ GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
+ for (int i = 0; i < m_resObjects.Count; i++)
+ {
+ if (currentSelectedGameObject == m_resObjects[i])
+ {
+ m_selectedRes = m_resolutions[i];
+ break;
+ }
+ }
+ }
+
+ public void OnApplyMode()
+ {
+ ApplyMode();
+ ShowResSwitchCountdown();
+ }
+
+ private void ApplyMode()
+ {
+ if (Screen.width != m_selectedRes.width || Screen.height != m_selectedRes.height || m_fullscreenToggle.isOn != Screen.fullScreen)
+ {
+ Screen.SetResolution(m_selectedRes.width, m_selectedRes.height, m_fullscreenToggle.isOn);
+ m_modeApplied = true;
+ }
+ }
+
+ private void RevertMode()
+ {
+ if (m_modeApplied)
+ {
+ m_modeApplied = false;
+ m_selectedRes = m_oldRes;
+ m_fullscreenToggle.isOn = m_oldFullscreen;
+ Screen.SetResolution(m_oldRes.width, m_oldRes.height, m_oldFullscreen);
+ }
+ }
+
+ private void ShowResSwitchCountdown()
+ {
+ m_resSwitchDialog.SetActive(value: true);
+ m_resCountdownTimer = 5f;
+ }
+
+ public void OnResSwitchOK()
+ {
+ m_resSwitchDialog.SetActive(value: false);
+ }
+
+ private void UpdateResSwitch(float dt)
+ {
+ if (m_resSwitchDialog.activeSelf)
+ {
+ m_resCountdownTimer -= dt;
+ m_resSwitchCountdown.text = Mathf.CeilToInt(m_resCountdownTimer).ToString();
+ if (m_resCountdownTimer <= 0f)
+ {
+ RevertMode();
+ m_resSwitchDialog.SetActive(value: false);
+ }
+ }
+ }
+
+ public void OnResetTutorial()
+ {
+ Player.ResetSeenTutorials();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ship.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ship.cs
new file mode 100644
index 0000000..7ad6482
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Ship.cs
@@ -0,0 +1,746 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Ship : MonoBehaviour
+{
+ public enum Speed
+ {
+ Stop,
+ Back,
+ Slow,
+ Half,
+ Full
+ }
+
+ private bool m_forwardPressed;
+
+ private bool m_backwardPressed;
+
+ private float m_sendRudderTime;
+
+ private Vector3 windChangeVelocity = Vector3.zero;
+
+ private bool sailWasInPosition;
+
+ [Header("Objects")]
+ public GameObject m_sailObject;
+
+ public GameObject m_mastObject;
+
+ public GameObject m_rudderObject;
+
+ public ShipControlls m_shipControlls;
+
+ public Transform m_controlGuiPos;
+
+ [Header("Misc")]
+ public BoxCollider m_floatCollider;
+
+ public float m_waterLevelOffset;
+
+ public float m_forceDistance = 1f;
+
+ public float m_force = 0.5f;
+
+ public float m_damping = 0.05f;
+
+ public float m_dampingSideway = 0.05f;
+
+ public float m_dampingForward = 0.01f;
+
+ public float m_angularDamping = 0.01f;
+
+ public float m_disableLevel = -0.5f;
+
+ public float m_sailForceOffset;
+
+ public float m_sailForceFactor = 0.1f;
+
+ public float m_rudderSpeed = 0.5f;
+
+ public float m_stearForceOffset = -10f;
+
+ public float m_stearForce = 0.5f;
+
+ public float m_stearVelForceFactor = 0.1f;
+
+ public float m_backwardForce = 50f;
+
+ public float m_rudderRotationMax = 30f;
+
+ public float m_rudderRotationSpeed = 30f;
+
+ public float m_minWaterImpactForce = 2.5f;
+
+ public float m_minWaterImpactInterval = 2f;
+
+ public float m_waterImpactDamage = 10f;
+
+ public float m_upsideDownDmgInterval = 1f;
+
+ public float m_upsideDownDmg = 20f;
+
+ public EffectList m_waterImpactEffect = new EffectList();
+
+ private Speed m_speed;
+
+ private float m_rudder;
+
+ private float m_rudderValue;
+
+ private Vector3 m_sailForce = Vector3.zero;
+
+ private List<Player> m_players = new List<Player>();
+
+ private static List<Ship> m_currentShips = new List<Ship>();
+
+ private Rigidbody m_body;
+
+ private ZNetView m_nview;
+
+ private Cloth m_sailCloth;
+
+ private float m_lastDepth = -9999f;
+
+ private float m_lastWaterImpactTime;
+
+ private float m_upsideDownDmgTimer;
+
+ private float m_rudderPaddleTimer;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ WearNTear component = GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
+ }
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ }
+ m_body.maxDepenetrationVelocity = 2f;
+ Heightmap.ForceGenerateAll();
+ m_sailCloth = m_sailObject.GetComponentInChildren<Cloth>();
+ }
+
+ public bool CanBeRemoved()
+ {
+ return m_players.Count == 0;
+ }
+
+ private void Start()
+ {
+ m_nview.Register("Stop", RPC_Stop);
+ m_nview.Register("Forward", RPC_Forward);
+ m_nview.Register("Backward", RPC_Backward);
+ m_nview.Register<float>("Rudder", RPC_Rudder);
+ InvokeRepeating("UpdateOwner", 2f, 2f);
+ }
+
+ private void PrintStats()
+ {
+ if (m_players.Count != 0)
+ {
+ ZLog.Log("Vel:" + m_body.velocity.magnitude.ToString("0.0"));
+ }
+ }
+
+ public void ApplyMovementControlls(Vector3 dir)
+ {
+ bool flag = (double)dir.z > 0.5;
+ bool flag2 = (double)dir.z < -0.5;
+ if (flag && !m_forwardPressed)
+ {
+ Forward();
+ }
+ if (flag2 && !m_backwardPressed)
+ {
+ Backward();
+ }
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ float num = Mathf.Lerp(0.5f, 1f, Mathf.Abs(m_rudderValue));
+ m_rudder = dir.x * num;
+ m_rudderValue += m_rudder * m_rudderSpeed * fixedDeltaTime;
+ m_rudderValue = Mathf.Clamp(m_rudderValue, -1f, 1f);
+ if (Time.time - m_sendRudderTime > 0.2f)
+ {
+ m_sendRudderTime = Time.time;
+ m_nview.InvokeRPC("Rudder", m_rudderValue);
+ }
+ m_forwardPressed = flag;
+ m_backwardPressed = flag2;
+ }
+
+ public void Forward()
+ {
+ m_nview.InvokeRPC("Forward");
+ }
+
+ public void Backward()
+ {
+ m_nview.InvokeRPC("Backward");
+ }
+
+ public void Rudder(float rudder)
+ {
+ m_nview.Invoke("Rudder", rudder);
+ }
+
+ private void RPC_Rudder(long sender, float value)
+ {
+ m_rudderValue = value;
+ }
+
+ public void Stop()
+ {
+ m_nview.InvokeRPC("Stop");
+ }
+
+ private void RPC_Stop(long sender)
+ {
+ m_speed = Speed.Stop;
+ }
+
+ private void RPC_Forward(long sender)
+ {
+ switch (m_speed)
+ {
+ case Speed.Stop:
+ m_speed = Speed.Slow;
+ break;
+ case Speed.Slow:
+ m_speed = Speed.Half;
+ break;
+ case Speed.Half:
+ m_speed = Speed.Full;
+ break;
+ case Speed.Back:
+ m_speed = Speed.Stop;
+ break;
+ case Speed.Full:
+ break;
+ }
+ }
+
+ private void RPC_Backward(long sender)
+ {
+ switch (m_speed)
+ {
+ case Speed.Stop:
+ m_speed = Speed.Back;
+ break;
+ case Speed.Slow:
+ m_speed = Speed.Stop;
+ break;
+ case Speed.Half:
+ m_speed = Speed.Slow;
+ break;
+ case Speed.Full:
+ m_speed = Speed.Half;
+ break;
+ case Speed.Back:
+ break;
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ bool flag = HaveControllingPlayer();
+ UpdateControlls(Time.fixedDeltaTime);
+ UpdateSail(Time.fixedDeltaTime);
+ UpdateRudder(Time.fixedDeltaTime, flag);
+ if ((bool)m_nview && !m_nview.IsOwner())
+ {
+ return;
+ }
+ UpdateUpsideDmg(Time.fixedDeltaTime);
+ if (m_players.Count == 0)
+ {
+ m_speed = Speed.Stop;
+ m_rudderValue = 0f;
+ }
+ if (!flag && (m_speed == Speed.Slow || m_speed == Speed.Back))
+ {
+ m_speed = Speed.Stop;
+ }
+ float waveFactor = 1f;
+ Vector3 worldCenterOfMass = m_body.worldCenterOfMass;
+ Vector3 vector = m_floatCollider.transform.position + m_floatCollider.transform.forward * m_floatCollider.size.z / 2f;
+ Vector3 vector2 = m_floatCollider.transform.position - m_floatCollider.transform.forward * m_floatCollider.size.z / 2f;
+ Vector3 vector3 = m_floatCollider.transform.position - m_floatCollider.transform.right * m_floatCollider.size.x / 2f;
+ Vector3 vector4 = m_floatCollider.transform.position + m_floatCollider.transform.right * m_floatCollider.size.x / 2f;
+ float waterLevel = WaterVolume.GetWaterLevel(worldCenterOfMass, waveFactor);
+ float waterLevel2 = WaterVolume.GetWaterLevel(vector3, waveFactor);
+ float waterLevel3 = WaterVolume.GetWaterLevel(vector4, waveFactor);
+ float waterLevel4 = WaterVolume.GetWaterLevel(vector, waveFactor);
+ float waterLevel5 = WaterVolume.GetWaterLevel(vector2, waveFactor);
+ float num = (waterLevel + waterLevel2 + waterLevel3 + waterLevel4 + waterLevel5) / 5f;
+ float num2 = worldCenterOfMass.y - num - m_waterLevelOffset;
+ if (!(num2 > m_disableLevel))
+ {
+ m_body.WakeUp();
+ UpdateWaterForce(num2, Time.fixedDeltaTime);
+ Vector3 vector5 = new Vector3(vector3.x, waterLevel2, vector3.z);
+ Vector3 vector6 = new Vector3(vector4.x, waterLevel3, vector4.z);
+ Vector3 vector7 = new Vector3(vector.x, waterLevel4, vector.z);
+ Vector3 vector8 = new Vector3(vector2.x, waterLevel5, vector2.z);
+ float fixedDeltaTime = Time.fixedDeltaTime;
+ float num3 = fixedDeltaTime * 50f;
+ float num4 = Mathf.Clamp01(Mathf.Abs(num2) / m_forceDistance);
+ Vector3 vector9 = Vector3.up * m_force * num4;
+ m_body.AddForceAtPosition(vector9 * num3, worldCenterOfMass, ForceMode.VelocityChange);
+ float num5 = Vector3.Dot(m_body.velocity, base.transform.forward);
+ float num6 = Vector3.Dot(m_body.velocity, base.transform.right);
+ Vector3 velocity = m_body.velocity;
+ velocity.y -= velocity.y * velocity.y * Mathf.Sign(velocity.y) * m_damping * num4;
+ velocity -= base.transform.forward * (num5 * num5 * Mathf.Sign(num5)) * m_dampingForward * num4;
+ velocity -= base.transform.right * (num6 * num6 * Mathf.Sign(num6)) * m_dampingSideway * num4;
+ if (velocity.magnitude > m_body.velocity.magnitude)
+ {
+ velocity = velocity.normalized * m_body.velocity.magnitude;
+ }
+ if (m_players.Count == 0)
+ {
+ velocity.x *= 0.1f;
+ velocity.z *= 0.1f;
+ }
+ m_body.velocity = velocity;
+ m_body.angularVelocity -= m_body.angularVelocity * m_angularDamping * num4;
+ float num7 = 0.15f;
+ float num8 = 0.5f;
+ float f = Mathf.Clamp((vector7.y - vector.y) * num7, 0f - num8, num8);
+ float f2 = Mathf.Clamp((vector8.y - vector2.y) * num7, 0f - num8, num8);
+ float f3 = Mathf.Clamp((vector5.y - vector3.y) * num7, 0f - num8, num8);
+ float f4 = Mathf.Clamp((vector6.y - vector4.y) * num7, 0f - num8, num8);
+ f = Mathf.Sign(f) * Mathf.Abs(Mathf.Pow(f, 2f));
+ f2 = Mathf.Sign(f2) * Mathf.Abs(Mathf.Pow(f2, 2f));
+ f3 = Mathf.Sign(f3) * Mathf.Abs(Mathf.Pow(f3, 2f));
+ f4 = Mathf.Sign(f4) * Mathf.Abs(Mathf.Pow(f4, 2f));
+ m_body.AddForceAtPosition(Vector3.up * f * num3, vector, ForceMode.VelocityChange);
+ m_body.AddForceAtPosition(Vector3.up * f2 * num3, vector2, ForceMode.VelocityChange);
+ m_body.AddForceAtPosition(Vector3.up * f3 * num3, vector3, ForceMode.VelocityChange);
+ m_body.AddForceAtPosition(Vector3.up * f4 * num3, vector4, ForceMode.VelocityChange);
+ float sailSize = 0f;
+ if (m_speed == Speed.Full)
+ {
+ sailSize = 1f;
+ }
+ else if (m_speed == Speed.Half)
+ {
+ sailSize = 0.5f;
+ }
+ Vector3 sailForce = GetSailForce(sailSize, fixedDeltaTime);
+ Vector3 position = worldCenterOfMass + base.transform.up * m_sailForceOffset;
+ m_body.AddForceAtPosition(sailForce, position, ForceMode.VelocityChange);
+ Vector3 position2 = base.transform.position + base.transform.forward * m_stearForceOffset;
+ float num9 = num5 * m_stearVelForceFactor;
+ m_body.AddForceAtPosition(base.transform.right * num9 * (0f - m_rudderValue) * fixedDeltaTime, position2, ForceMode.VelocityChange);
+ Vector3 zero = Vector3.zero;
+ switch (m_speed)
+ {
+ case Speed.Slow:
+ zero += base.transform.forward * m_backwardForce * (1f - Mathf.Abs(m_rudderValue));
+ break;
+ case Speed.Back:
+ zero += -base.transform.forward * m_backwardForce * (1f - Mathf.Abs(m_rudderValue));
+ break;
+ }
+ if (m_speed == Speed.Back || m_speed == Speed.Slow)
+ {
+ float num10 = ((m_speed != Speed.Back) ? 1 : (-1));
+ zero += base.transform.right * m_stearForce * (0f - m_rudderValue) * num10;
+ }
+ m_body.AddForceAtPosition(zero * fixedDeltaTime, position2, ForceMode.VelocityChange);
+ ApplyEdgeForce(Time.fixedDeltaTime);
+ }
+ }
+
+ private void UpdateUpsideDmg(float dt)
+ {
+ if (!(base.transform.up.y < 0f))
+ {
+ return;
+ }
+ m_upsideDownDmgTimer += dt;
+ if (m_upsideDownDmgTimer > m_upsideDownDmgInterval)
+ {
+ m_upsideDownDmgTimer = 0f;
+ IDestructible component = GetComponent<IDestructible>();
+ if (component != null)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_blunt = m_upsideDownDmg;
+ hitData.m_point = base.transform.position;
+ hitData.m_dir = Vector3.up;
+ component.Damage(hitData);
+ }
+ }
+ }
+
+ private Vector3 GetSailForce(float sailSize, float dt)
+ {
+ Vector3 windDir = EnvMan.instance.GetWindDir();
+ float windIntensity = EnvMan.instance.GetWindIntensity();
+ float num = Mathf.Lerp(0.25f, 1f, windIntensity);
+ float windAngleFactor = GetWindAngleFactor();
+ windAngleFactor *= num;
+ Vector3 target = Vector3.Normalize(windDir + base.transform.forward) * windAngleFactor * m_sailForceFactor * sailSize;
+ m_sailForce = Vector3.SmoothDamp(m_sailForce, target, ref windChangeVelocity, 1f, 99f);
+ return m_sailForce;
+ }
+
+ public float GetWindAngleFactor()
+ {
+ float num = Vector3.Dot(EnvMan.instance.GetWindDir(), -base.transform.forward);
+ float num2 = Mathf.Lerp(0.7f, 1f, 1f - Mathf.Abs(num));
+ float num3 = 1f - Utils.LerpStep(0.75f, 0.8f, num);
+ return num2 * num3;
+ }
+
+ private void UpdateWaterForce(float depth, float dt)
+ {
+ if (m_lastDepth == -9999f)
+ {
+ m_lastDepth = depth;
+ return;
+ }
+ float num = depth - m_lastDepth;
+ m_lastDepth = depth;
+ float num2 = num / dt;
+ if (num2 > 0f || !(Mathf.Abs(num2) > m_minWaterImpactForce) || !(Time.time - m_lastWaterImpactTime > m_minWaterImpactInterval))
+ {
+ return;
+ }
+ m_lastWaterImpactTime = Time.time;
+ m_waterImpactEffect.Create(base.transform.position, base.transform.rotation);
+ if (m_players.Count > 0)
+ {
+ IDestructible component = GetComponent<IDestructible>();
+ if (component != null)
+ {
+ HitData hitData = new HitData();
+ hitData.m_damage.m_blunt = m_waterImpactDamage;
+ hitData.m_point = base.transform.position;
+ hitData.m_dir = Vector3.up;
+ component.Damage(hitData);
+ }
+ }
+ }
+
+ private void ApplyEdgeForce(float dt)
+ {
+ float magnitude = base.transform.position.magnitude;
+ float num = 10420f;
+ if (magnitude > num)
+ {
+ Vector3 vector = Vector3.Normalize(base.transform.position);
+ float num2 = Utils.LerpStep(num, 10500f, magnitude) * 8f;
+ Vector3 vector2 = vector * num2;
+ m_body.AddForce(vector2 * dt, ForceMode.VelocityChange);
+ }
+ }
+
+ private void FixTilt()
+ {
+ float num = Mathf.Asin(base.transform.right.y);
+ float num2 = Mathf.Asin(base.transform.forward.y);
+ if (Mathf.Abs(num) > (float)Math.PI / 6f)
+ {
+ if (num > 0f)
+ {
+ base.transform.RotateAround(base.transform.position, base.transform.forward, (0f - Time.fixedDeltaTime) * 20f);
+ }
+ else
+ {
+ base.transform.RotateAround(base.transform.position, base.transform.forward, Time.fixedDeltaTime * 20f);
+ }
+ }
+ if (Mathf.Abs(num2) > (float)Math.PI / 6f)
+ {
+ if (num2 > 0f)
+ {
+ base.transform.RotateAround(base.transform.position, base.transform.right, (0f - Time.fixedDeltaTime) * 20f);
+ }
+ else
+ {
+ base.transform.RotateAround(base.transform.position, base.transform.right, Time.fixedDeltaTime * 20f);
+ }
+ }
+ }
+
+ private void UpdateControlls(float dt)
+ {
+ if (m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set("forward", (int)m_speed);
+ m_nview.GetZDO().Set("rudder", m_rudderValue);
+ return;
+ }
+ m_speed = (Speed)m_nview.GetZDO().GetInt("forward");
+ if (Time.time - m_sendRudderTime > 1f)
+ {
+ m_rudderValue = m_nview.GetZDO().GetFloat("rudder");
+ }
+ }
+
+ public bool IsSailUp()
+ {
+ if (m_speed != Speed.Half)
+ {
+ return m_speed == Speed.Full;
+ }
+ return true;
+ }
+
+ private void UpdateSail(float dt)
+ {
+ UpdateSailSize(dt);
+ Vector3 windDir = EnvMan.instance.GetWindDir();
+ windDir = Vector3.Cross(Vector3.Cross(windDir, base.transform.up), base.transform.up);
+ if (m_speed == Speed.Full || m_speed == Speed.Half)
+ {
+ float t = 0.5f + Vector3.Dot(base.transform.forward, windDir) * 0.5f;
+ Quaternion to = Quaternion.LookRotation(-Vector3.Lerp(windDir, Vector3.Normalize(windDir - base.transform.forward), t), base.transform.up);
+ m_mastObject.transform.rotation = Quaternion.RotateTowards(m_mastObject.transform.rotation, to, 30f * dt);
+ }
+ else if (m_speed == Speed.Back)
+ {
+ Quaternion from = Quaternion.LookRotation(-base.transform.forward, base.transform.up);
+ Quaternion to2 = Quaternion.LookRotation(-windDir, base.transform.up);
+ to2 = Quaternion.RotateTowards(from, to2, 80f);
+ m_mastObject.transform.rotation = Quaternion.RotateTowards(m_mastObject.transform.rotation, to2, 30f * dt);
+ }
+ }
+
+ private void UpdateRudder(float dt, bool haveControllingPlayer)
+ {
+ if (!m_rudderObject)
+ {
+ return;
+ }
+ Quaternion b = Quaternion.Euler(0f, m_rudderRotationMax * (0f - m_rudderValue), 0f);
+ if (haveControllingPlayer)
+ {
+ if (m_speed == Speed.Slow)
+ {
+ m_rudderPaddleTimer += dt;
+ b *= Quaternion.Euler(0f, Mathf.Sin(m_rudderPaddleTimer * 6f) * 20f, 0f);
+ }
+ else if (m_speed == Speed.Back)
+ {
+ m_rudderPaddleTimer += dt;
+ b *= Quaternion.Euler(0f, Mathf.Sin(m_rudderPaddleTimer * -3f) * 40f, 0f);
+ }
+ }
+ m_rudderObject.transform.localRotation = Quaternion.Slerp(m_rudderObject.transform.localRotation, b, 0.5f);
+ }
+
+ private void UpdateSailSize(float dt)
+ {
+ float num = 0f;
+ switch (m_speed)
+ {
+ case Speed.Back:
+ num = 0.1f;
+ break;
+ case Speed.Half:
+ num = 0.5f;
+ break;
+ case Speed.Full:
+ num = 1f;
+ break;
+ case Speed.Slow:
+ num = 0.1f;
+ break;
+ case Speed.Stop:
+ num = 0.1f;
+ break;
+ }
+ Vector3 localScale = m_sailObject.transform.localScale;
+ bool flag = Mathf.Abs(localScale.y - num) < 0.01f;
+ if (!flag)
+ {
+ localScale.y = Mathf.MoveTowards(localScale.y, num, dt);
+ m_sailObject.transform.localScale = localScale;
+ }
+ if ((bool)m_sailCloth)
+ {
+ if (m_speed == Speed.Stop || m_speed == Speed.Slow || m_speed == Speed.Back)
+ {
+ if (flag && m_sailCloth.enabled)
+ {
+ m_sailCloth.enabled = false;
+ }
+ }
+ else if (flag)
+ {
+ if (!sailWasInPosition)
+ {
+ m_sailCloth.enabled = false;
+ m_sailCloth.enabled = true;
+ }
+ }
+ else
+ {
+ m_sailCloth.enabled = true;
+ }
+ }
+ sailWasInPosition = flag;
+ }
+
+ private void UpdateOwner()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && !(Player.m_localPlayer == null) && m_players.Count > 0 && !IsPlayerInBoat(Player.m_localPlayer))
+ {
+ long owner = m_players[0].GetOwner();
+ m_nview.GetZDO().SetOwner(owner);
+ ZLog.Log("Changing ship owner to " + owner);
+ }
+ }
+
+ private void OnTriggerEnter(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if ((bool)component)
+ {
+ m_players.Add(component);
+ ZLog.Log("Player onboard, total onboard " + m_players.Count);
+ if (component == Player.m_localPlayer)
+ {
+ m_currentShips.Add(this);
+ }
+ }
+ }
+
+ private void OnTriggerExit(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if ((bool)component)
+ {
+ m_players.Remove(component);
+ ZLog.Log("Player over board, players left " + m_players.Count);
+ if (component == Player.m_localPlayer)
+ {
+ m_currentShips.Remove(this);
+ }
+ }
+ }
+
+ public bool IsPlayerInBoat(ZDOID zdoid)
+ {
+ foreach (Player player in m_players)
+ {
+ if (player.GetZDOID() == zdoid)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsPlayerInBoat(Player player)
+ {
+ return m_players.Contains(player);
+ }
+
+ public bool HasPlayerOnboard()
+ {
+ return m_players.Count > 0;
+ }
+
+ private void OnDestroyed()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ GoogleAnalyticsV4.instance.LogEvent("Game", "ShipDestroyed", base.gameObject.name, 0L);
+ }
+ m_currentShips.Remove(this);
+ }
+
+ public bool IsWindControllActive()
+ {
+ foreach (Player player in m_players)
+ {
+ if (player.GetSEMan().HaveStatusAttribute(StatusEffect.StatusAttribute.SailingPower))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Ship GetLocalShip()
+ {
+ if (m_currentShips.Count == 0)
+ {
+ return null;
+ }
+ return m_currentShips[m_currentShips.Count - 1];
+ }
+
+ public bool HaveControllingPlayer()
+ {
+ if (m_players.Count == 0)
+ {
+ return false;
+ }
+ return m_shipControlls.HaveValidUser();
+ }
+
+ public bool IsOwner()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.IsOwner();
+ }
+
+ public float GetSpeed()
+ {
+ return Vector3.Dot(m_body.velocity, base.transform.forward);
+ }
+
+ public Speed GetSpeedSetting()
+ {
+ return m_speed;
+ }
+
+ public float GetRudder()
+ {
+ return m_rudder;
+ }
+
+ public float GetRudderValue()
+ {
+ return m_rudderValue;
+ }
+
+ public float GetShipYawAngle()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return 0f;
+ }
+ return 0f - Utils.YawFromDirection(mainCamera.transform.InverseTransformDirection(base.transform.forward));
+ }
+
+ public float GetWindAngle()
+ {
+ Vector3 windDir = EnvMan.instance.GetWindDir();
+ return 0f - Utils.YawFromDirection(base.transform.InverseTransformDirection(windDir));
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.red;
+ Gizmos.DrawWireSphere(base.transform.position + base.transform.forward * m_stearForceOffset, 0.25f);
+ Gizmos.color = Color.yellow;
+ Gizmos.DrawWireSphere(base.transform.position + base.transform.up * m_sailForceOffset, 0.25f);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipConstructor.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipConstructor.cs
new file mode 100644
index 0000000..b754868
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipConstructor.cs
@@ -0,0 +1,58 @@
+using System;
+using UnityEngine;
+
+public class ShipConstructor : MonoBehaviour
+{
+ public GameObject m_shipPrefab;
+
+ public GameObject m_hideWhenConstructed;
+
+ public Transform m_spawnPoint;
+
+ public long m_constructionTimeMinutes = 1L;
+
+ private ZNetView m_nview;
+
+ private void Start()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (!(m_nview == null) && m_nview.GetZDO() != null)
+ {
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong("spawntime", 0L) == 0L)
+ {
+ m_nview.GetZDO().Set("spawntime", ZNet.instance.GetTime().Ticks);
+ }
+ InvokeRepeating("UpdateConstruction", 5f, 1f);
+ if (IsBuilt())
+ {
+ m_hideWhenConstructed.SetActive(value: false);
+ }
+ }
+ }
+
+ private bool IsBuilt()
+ {
+ return m_nview.GetZDO().GetBool("done");
+ }
+
+ private void UpdateConstruction()
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ if (IsBuilt())
+ {
+ m_hideWhenConstructed.SetActive(value: false);
+ return;
+ }
+ DateTime time = ZNet.instance.GetTime();
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("spawntime", 0L));
+ if ((time - dateTime).TotalMinutes > (double)m_constructionTimeMinutes)
+ {
+ m_hideWhenConstructed.SetActive(value: false);
+ UnityEngine.Object.Instantiate(m_shipPrefab, m_spawnPoint.position, m_spawnPoint.rotation);
+ m_nview.GetZDO().Set("done", value: true);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipControlls.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipControlls.cs
new file mode 100644
index 0000000..c8911ed
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipControlls.cs
@@ -0,0 +1,175 @@
+using UnityEngine;
+
+public class ShipControlls : MonoBehaviour, Interactable, Hoverable
+{
+ public string m_hoverText = "";
+
+ public Ship m_ship;
+
+ public float m_maxUseRange = 10f;
+
+ public Transform m_attachPoint;
+
+ public Vector3 m_detachOffset = new Vector3(0f, 0.5f, 0f);
+
+ public string m_attachAnimation = "attach_chair";
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = m_ship.GetComponent<ZNetView>();
+ m_nview.Register<ZDOID>("RequestControl", RPC_RequestControl);
+ m_nview.Register<ZDOID>("ReleaseControl", RPC_ReleaseControl);
+ m_nview.Register<bool>("RequestRespons", RPC_RequestRespons);
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public bool Interact(Humanoid character, bool repeat)
+ {
+ if (repeat)
+ {
+ return false;
+ }
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ if (!InUseDistance(character))
+ {
+ return false;
+ }
+ Player player = character as Player;
+ if (player == null)
+ {
+ return false;
+ }
+ if (player.IsEncumbered())
+ {
+ return false;
+ }
+ if (player.GetStandingOnShip() != m_ship)
+ {
+ return false;
+ }
+ m_nview.InvokeRPC("RequestControl", player.GetZDOID());
+ return false;
+ }
+
+ public Ship GetShip()
+ {
+ return m_ship;
+ }
+
+ public string GetHoverText()
+ {
+ if (!InUseDistance(Player.m_localPlayer))
+ {
+ return Localization.instance.Localize("<color=grey>$piece_toofar</color>");
+ }
+ return Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] " + m_hoverText);
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_hoverText);
+ }
+
+ private void RPC_RequestControl(long sender, ZDOID playerID)
+ {
+ if (m_nview.IsOwner() && m_ship.IsPlayerInBoat(playerID))
+ {
+ if (GetUser() == playerID || !HaveValidUser())
+ {
+ m_nview.GetZDO().Set("user", playerID);
+ m_nview.InvokeRPC(sender, "RequestRespons", true);
+ }
+ else
+ {
+ m_nview.InvokeRPC(sender, "RequestRespons", false);
+ }
+ }
+ }
+
+ private void RPC_ReleaseControl(long sender, ZDOID playerID)
+ {
+ if (m_nview.IsOwner() && GetUser() == playerID)
+ {
+ m_nview.GetZDO().Set("user", ZDOID.None);
+ }
+ }
+
+ private void RPC_RequestRespons(long sender, bool granted)
+ {
+ if (!Player.m_localPlayer)
+ {
+ return;
+ }
+ if (granted)
+ {
+ Player.m_localPlayer.StartShipControl(this);
+ if (m_attachPoint != null)
+ {
+ Player.m_localPlayer.AttachStart(m_attachPoint, hideWeapons: false, isBed: false, m_attachAnimation, m_detachOffset);
+ }
+ }
+ else
+ {
+ Player.m_localPlayer.Message(MessageHud.MessageType.Center, "$msg_inuse");
+ }
+ }
+
+ public void OnUseStop(Player player)
+ {
+ if (m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("ReleaseControl", player.GetZDOID());
+ if (m_attachPoint != null)
+ {
+ player.AttachStop();
+ }
+ }
+ }
+
+ public bool HaveValidUser()
+ {
+ ZDOID user = GetUser();
+ if (user.IsNone())
+ {
+ return false;
+ }
+ return m_ship.IsPlayerInBoat(user);
+ }
+
+ public bool IsLocalUser()
+ {
+ if (!Player.m_localPlayer)
+ {
+ return false;
+ }
+ ZDOID user = GetUser();
+ if (user.IsNone())
+ {
+ return false;
+ }
+ return user == Player.m_localPlayer.GetZDOID();
+ }
+
+ private ZDOID GetUser()
+ {
+ if (!m_nview.IsValid())
+ {
+ return ZDOID.None;
+ }
+ return m_nview.GetZDO().GetZDOID("user");
+ }
+
+ private bool InUseDistance(Humanoid human)
+ {
+ return Vector3.Distance(human.transform.position, m_attachPoint.position) < m_maxUseRange;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipEffects.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipEffects.cs
new file mode 100644
index 0000000..d7bf567
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShipEffects.cs
@@ -0,0 +1,150 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ShipEffects : MonoBehaviour
+{
+ public Transform m_shadow;
+
+ public float m_offset = 0.01f;
+
+ public float m_minimumWakeVel = 5f;
+
+ public GameObject m_speedWakeRoot;
+
+ public GameObject m_wakeSoundRoot;
+
+ public GameObject m_inWaterSoundRoot;
+
+ public float m_audioFadeDuration = 2f;
+
+ public AudioSource m_sailSound;
+
+ public float m_sailFadeDuration = 1f;
+
+ public GameObject m_splashEffects;
+
+ private float m_sailBaseVol = 1f;
+
+ private ParticleSystem[] m_wakeParticles;
+
+ private List<KeyValuePair<AudioSource, float>> m_wakeSounds = new List<KeyValuePair<AudioSource, float>>();
+
+ private List<KeyValuePair<AudioSource, float>> m_inWaterSounds = new List<KeyValuePair<AudioSource, float>>();
+
+ private Rigidbody m_body;
+
+ private Ship m_ship;
+
+ private void Awake()
+ {
+ ZNetView componentInParent = GetComponentInParent<ZNetView>();
+ if ((bool)componentInParent && componentInParent.GetZDO() == null)
+ {
+ base.enabled = false;
+ return;
+ }
+ m_body = GetComponentInParent<Rigidbody>();
+ m_ship = GetComponentInParent<Ship>();
+ if ((bool)m_speedWakeRoot)
+ {
+ m_wakeParticles = m_speedWakeRoot.GetComponentsInChildren<ParticleSystem>();
+ }
+ if ((bool)m_wakeSoundRoot)
+ {
+ AudioSource[] componentsInChildren = m_wakeSoundRoot.GetComponentsInChildren<AudioSource>();
+ foreach (AudioSource audioSource in componentsInChildren)
+ {
+ audioSource.pitch = Random.Range(0.9f, 1.1f);
+ m_wakeSounds.Add(new KeyValuePair<AudioSource, float>(audioSource, audioSource.volume));
+ }
+ }
+ if ((bool)m_inWaterSoundRoot)
+ {
+ AudioSource[] componentsInChildren = m_inWaterSoundRoot.GetComponentsInChildren<AudioSource>();
+ foreach (AudioSource audioSource2 in componentsInChildren)
+ {
+ audioSource2.pitch = Random.Range(0.9f, 1.1f);
+ m_inWaterSounds.Add(new KeyValuePair<AudioSource, float>(audioSource2, audioSource2.volume));
+ }
+ }
+ if ((bool)m_sailSound)
+ {
+ m_sailBaseVol = m_sailSound.volume;
+ m_sailSound.pitch = Random.Range(0.9f, 1.1f);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(base.transform.position);
+ Vector3 position = base.transform.position;
+ float deltaTime = Time.deltaTime;
+ if (position.y > waterLevel)
+ {
+ m_shadow.gameObject.SetActive(value: false);
+ SetWake(enabled: false, deltaTime);
+ FadeSounds(m_inWaterSounds, enabled: false, deltaTime);
+ return;
+ }
+ m_shadow.gameObject.SetActive(value: true);
+ bool flag = m_body.velocity.magnitude > m_minimumWakeVel;
+ FadeSounds(m_inWaterSounds, enabled: true, deltaTime);
+ SetWake(flag, deltaTime);
+ if ((bool)m_sailSound)
+ {
+ float target = (m_ship.IsSailUp() ? m_sailBaseVol : 0f);
+ FadeSound(m_sailSound, target, m_sailFadeDuration, deltaTime);
+ }
+ if (m_splashEffects != null)
+ {
+ m_splashEffects.SetActive(m_ship.HasPlayerOnboard());
+ }
+ }
+
+ private void SetWake(bool enabled, float dt)
+ {
+ ParticleSystem[] wakeParticles = m_wakeParticles;
+ for (int i = 0; i < wakeParticles.Length; i++)
+ {
+ ParticleSystem.EmissionModule emission = wakeParticles[i].emission;
+ emission.enabled = enabled;
+ }
+ FadeSounds(m_wakeSounds, enabled, dt);
+ }
+
+ private void FadeSounds(List<KeyValuePair<AudioSource, float>> sources, bool enabled, float dt)
+ {
+ foreach (KeyValuePair<AudioSource, float> source in sources)
+ {
+ if (enabled)
+ {
+ FadeSound(source.Key, source.Value, m_audioFadeDuration, dt);
+ }
+ else
+ {
+ FadeSound(source.Key, 0f, m_audioFadeDuration, dt);
+ }
+ }
+ }
+
+ private void FadeSound(AudioSource source, float target, float fadeDuration, float dt)
+ {
+ float maxDelta = dt / fadeDuration;
+ if (target > 0f)
+ {
+ if (!source.isPlaying)
+ {
+ source.Play();
+ }
+ source.volume = Mathf.MoveTowards(source.volume, target, maxDelta);
+ }
+ else if (source.isPlaying)
+ {
+ source.volume = Mathf.MoveTowards(source.volume, 0f, maxDelta);
+ if (source.volume <= 0f)
+ {
+ source.Stop();
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShuffleClass.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShuffleClass.cs
new file mode 100644
index 0000000..5787a18
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ShuffleClass.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+internal static class ShuffleClass
+{
+ private static Random rng = new Random();
+
+ public static void Shuffle<T>(this IList<T> list)
+ {
+ int num = list.Count;
+ while (num > 1)
+ {
+ num--;
+ int index = rng.Next(num + 1);
+ T value = list[index];
+ list[index] = list[num];
+ list[num] = value;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Sign.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Sign.cs
new file mode 100644
index 0000000..04e91d9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Sign.cs
@@ -0,0 +1,82 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Sign : MonoBehaviour, Hoverable, Interactable, TextReceiver
+{
+ public Text m_textWidget;
+
+ public string m_name = "Sign";
+
+ public string m_defaultText = "Sign";
+
+ public int m_characterLimit = 50;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() != null)
+ {
+ UpdateText();
+ InvokeRepeating("UpdateText", 2f, 2f);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (!PrivateArea.CheckAccess(base.transform.position, 0f, flash: false))
+ {
+ return "\"" + GetText() + "\"";
+ }
+ return "\"" + GetText() + "\"\n" + Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ return false;
+ }
+ TextInput.instance.RequestText(this, "$piece_sign_input", m_characterLimit);
+ return true;
+ }
+
+ private void UpdateText()
+ {
+ string text = GetText();
+ if (!(m_textWidget.text == text))
+ {
+ m_textWidget.text = text;
+ }
+ }
+
+ public string GetText()
+ {
+ return m_nview.GetZDO().GetString("text", m_defaultText);
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public void SetText(string text)
+ {
+ if (PrivateArea.CheckAccess(base.transform.position))
+ {
+ m_nview.ClaimOwnership();
+ m_textWidget.text = text;
+ m_nview.GetZDO().Set("text", text);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Skills.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Skills.cs
new file mode 100644
index 0000000..642f867
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Skills.cs
@@ -0,0 +1,333 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Skills : MonoBehaviour
+{
+ public enum SkillType
+ {
+ None = 0,
+ Swords = 1,
+ Knives = 2,
+ Clubs = 3,
+ Polearms = 4,
+ Spears = 5,
+ Blocking = 6,
+ Axes = 7,
+ Bows = 8,
+ FireMagic = 9,
+ FrostMagic = 10,
+ Unarmed = 11,
+ Pickaxes = 12,
+ WoodCutting = 13,
+ Jump = 100,
+ Sneak = 101,
+ Run = 102,
+ Swim = 103,
+ All = 999
+ }
+
+ [Serializable]
+ public class SkillDef
+ {
+ public SkillType m_skill = SkillType.Swords;
+
+ public Sprite m_icon;
+
+ public string m_description = "";
+
+ public float m_increseStep = 1f;
+ }
+
+ public class Skill
+ {
+ public SkillDef m_info;
+
+ public float m_level;
+
+ public float m_accumulator;
+
+ public Skill(SkillDef info)
+ {
+ m_info = info;
+ }
+
+ public bool Raise(float factor)
+ {
+ if (m_level >= 100f)
+ {
+ return false;
+ }
+ float num = m_info.m_increseStep * factor;
+ m_accumulator += num;
+ float nextLevelRequirement = GetNextLevelRequirement();
+ if (m_accumulator >= nextLevelRequirement)
+ {
+ m_level += 1f;
+ m_level = Mathf.Clamp(m_level, 0f, 100f);
+ m_accumulator = 0f;
+ return true;
+ }
+ return false;
+ }
+
+ private float GetNextLevelRequirement()
+ {
+ return Mathf.Pow(m_level + 1f, 1.5f) * 0.5f + 0.5f;
+ }
+
+ public float GetLevelPercentage()
+ {
+ if (m_level >= 100f)
+ {
+ return 0f;
+ }
+ float nextLevelRequirement = GetNextLevelRequirement();
+ return Mathf.Clamp01(m_accumulator / nextLevelRequirement);
+ }
+ }
+
+ private const int dataVersion = 2;
+
+ private const float randomSkillRange = 0.15f;
+
+ private const float randomSkillMin = 0.4f;
+
+ public const float m_maxSkillLevel = 100f;
+
+ public const float m_skillCurve = 2f;
+
+ public bool m_useSkillCap;
+
+ public float m_totalSkillCap = 600f;
+
+ public List<SkillDef> m_skills = new List<SkillDef>();
+
+ public float m_DeathLowerFactor = 0.25f;
+
+ private Dictionary<SkillType, Skill> m_skillData = new Dictionary<SkillType, Skill>();
+
+ private Player m_player;
+
+ public void Awake()
+ {
+ m_player = GetComponent<Player>();
+ }
+
+ public void Save(ZPackage pkg)
+ {
+ pkg.Write(2);
+ pkg.Write(m_skillData.Count);
+ foreach (KeyValuePair<SkillType, Skill> skillDatum in m_skillData)
+ {
+ pkg.Write((int)skillDatum.Value.m_info.m_skill);
+ pkg.Write(skillDatum.Value.m_level);
+ pkg.Write(skillDatum.Value.m_accumulator);
+ }
+ }
+
+ public void Load(ZPackage pkg)
+ {
+ int num = pkg.ReadInt();
+ m_skillData.Clear();
+ int num2 = pkg.ReadInt();
+ for (int i = 0; i < num2; i++)
+ {
+ SkillType skillType = (SkillType)pkg.ReadInt();
+ float level = pkg.ReadSingle();
+ float accumulator = ((num >= 2) ? pkg.ReadSingle() : 0f);
+ if (IsSkillValid(skillType))
+ {
+ Skill skill = GetSkill(skillType);
+ skill.m_level = level;
+ skill.m_accumulator = accumulator;
+ }
+ }
+ }
+
+ private bool IsSkillValid(SkillType type)
+ {
+ return Enum.IsDefined(typeof(SkillType), type);
+ }
+
+ public float GetSkillFactor(SkillType skillType)
+ {
+ if (skillType == SkillType.None)
+ {
+ return 0f;
+ }
+ return GetSkill(skillType).m_level / 100f;
+ }
+
+ public void GetRandomSkillRange(out float min, out float max, SkillType skillType)
+ {
+ float skillFactor = GetSkillFactor(skillType);
+ float num = Mathf.Lerp(0.4f, 1f, skillFactor);
+ min = Mathf.Clamp01(num - 0.15f);
+ max = Mathf.Clamp01(num + 0.15f);
+ }
+
+ public float GetRandomSkillFactor(SkillType skillType)
+ {
+ float skillFactor = GetSkillFactor(skillType);
+ float num = Mathf.Lerp(0.4f, 1f, skillFactor);
+ float a = Mathf.Clamp01(num - 0.15f);
+ float b = Mathf.Clamp01(num + 0.15f);
+ return Mathf.Lerp(a, b, UnityEngine.Random.value);
+ }
+
+ public void CheatRaiseSkill(string name, float value)
+ {
+ foreach (SkillType value2 in Enum.GetValues(typeof(SkillType)))
+ {
+ if (value2.ToString().ToLower() == name)
+ {
+ Skill skill = GetSkill(value2);
+ skill.m_level += value;
+ skill.m_level = Mathf.Clamp(skill.m_level, 0f, 100f);
+ if (m_useSkillCap)
+ {
+ RebalanceSkills(value2);
+ }
+ m_player.Message(MessageHud.MessageType.TopLeft, "Skill incresed " + skill.m_info.m_skill.ToString() + ": " + (int)skill.m_level, 0, skill.m_info.m_icon);
+ Console.instance.Print("Skill " + value2.ToString() + " = " + skill.m_level);
+ return;
+ }
+ }
+ Console.instance.Print("Skill not found " + name);
+ }
+
+ public void CheatResetSkill(string name)
+ {
+ foreach (SkillType value in Enum.GetValues(typeof(SkillType)))
+ {
+ if (value.ToString().ToLower() == name)
+ {
+ ResetSkill(value);
+ Console.instance.Print("Skill " + value.ToString() + " reset");
+ return;
+ }
+ }
+ Console.instance.Print("Skill not found " + name);
+ }
+
+ public void ResetSkill(SkillType skillType)
+ {
+ m_skillData.Remove(skillType);
+ }
+
+ public void RaiseSkill(SkillType skillType, float factor = 1f)
+ {
+ if (skillType == SkillType.None)
+ {
+ return;
+ }
+ Skill skill = GetSkill(skillType);
+ float level = skill.m_level;
+ if (skill.Raise(factor))
+ {
+ if (m_useSkillCap)
+ {
+ RebalanceSkills(skillType);
+ }
+ m_player.OnSkillLevelup(skillType, skill.m_level);
+ MessageHud.MessageType type = (((int)level != 0) ? MessageHud.MessageType.TopLeft : MessageHud.MessageType.Center);
+ m_player.Message(type, "$msg_skillup $skill_" + skill.m_info.m_skill.ToString().ToLower() + ": " + (int)skill.m_level, 0, skill.m_info.m_icon);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Levelup", skillType.ToString(), (int)skill.m_level);
+ }
+ }
+
+ private void RebalanceSkills(SkillType skillType)
+ {
+ if (GetTotalSkill() < m_totalSkillCap)
+ {
+ return;
+ }
+ float level = GetSkill(skillType).m_level;
+ float num = m_totalSkillCap - level;
+ float num2 = 0f;
+ foreach (KeyValuePair<SkillType, Skill> skillDatum in m_skillData)
+ {
+ if (skillDatum.Key != skillType)
+ {
+ num2 += skillDatum.Value.m_level;
+ }
+ }
+ foreach (KeyValuePair<SkillType, Skill> skillDatum2 in m_skillData)
+ {
+ if (skillDatum2.Key != skillType)
+ {
+ skillDatum2.Value.m_level = skillDatum2.Value.m_level / num2 * num;
+ }
+ }
+ }
+
+ public void Clear()
+ {
+ m_skillData.Clear();
+ }
+
+ public void OnDeath()
+ {
+ LowerAllSkills(m_DeathLowerFactor);
+ }
+
+ public void LowerAllSkills(float factor)
+ {
+ foreach (KeyValuePair<SkillType, Skill> skillDatum in m_skillData)
+ {
+ float num = skillDatum.Value.m_level * factor;
+ skillDatum.Value.m_level -= num;
+ skillDatum.Value.m_accumulator = 0f;
+ }
+ m_player.Message(MessageHud.MessageType.TopLeft, "$msg_skills_lowered");
+ }
+
+ private Skill GetSkill(SkillType skillType)
+ {
+ if (m_skillData.TryGetValue(skillType, out var value))
+ {
+ return value;
+ }
+ value = new Skill(GetSkillDef(skillType));
+ m_skillData.Add(skillType, value);
+ return value;
+ }
+
+ private SkillDef GetSkillDef(SkillType type)
+ {
+ foreach (SkillDef skill in m_skills)
+ {
+ if (skill.m_skill == type)
+ {
+ return skill;
+ }
+ }
+ return null;
+ }
+
+ public List<Skill> GetSkillList()
+ {
+ List<Skill> list = new List<Skill>();
+ foreach (KeyValuePair<SkillType, Skill> skillDatum in m_skillData)
+ {
+ list.Add(skillDatum.Value);
+ }
+ return list;
+ }
+
+ public float GetTotalSkill()
+ {
+ float num = 0f;
+ foreach (KeyValuePair<SkillType, Skill> skillDatum in m_skillData)
+ {
+ num += skillDatum.Value.m_level;
+ }
+ return num;
+ }
+
+ public float GetTotalSkillCap()
+ {
+ return m_totalSkillCap;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SkillsDialog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SkillsDialog.cs
new file mode 100644
index 0000000..01f8e66
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SkillsDialog.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class SkillsDialog : MonoBehaviour
+{
+ public RectTransform m_listRoot;
+
+ public GameObject m_elementPrefab;
+
+ public Text m_totalSkillText;
+
+ public float m_spacing = 80f;
+
+ private float m_baseListSize;
+
+ private List<GameObject> m_elements = new List<GameObject>();
+
+ private void Awake()
+ {
+ m_baseListSize = m_listRoot.rect.height;
+ }
+
+ public void Setup(Player player)
+ {
+ base.gameObject.SetActive(value: true);
+ foreach (GameObject element in m_elements)
+ {
+ Object.Destroy(element);
+ }
+ m_elements.Clear();
+ List<Skills.Skill> skillList = player.GetSkills().GetSkillList();
+ for (int i = 0; i < skillList.Count; i++)
+ {
+ Skills.Skill skill = skillList[i];
+ GameObject gameObject = Object.Instantiate(m_elementPrefab, Vector3.zero, Quaternion.identity, m_listRoot);
+ gameObject.SetActive(value: true);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)(-i) * m_spacing);
+ gameObject.GetComponentInChildren<UITooltip>().m_text = skill.m_info.m_description;
+ Utils.FindChild(gameObject.transform, "icon").GetComponent<Image>().sprite = skill.m_info.m_icon;
+ Utils.FindChild(gameObject.transform, "name").GetComponent<Text>().text = Localization.instance.Localize("$skill_" + skill.m_info.m_skill.ToString().ToLower());
+ Utils.FindChild(gameObject.transform, "leveltext").GetComponent<Text>().text = ((int)skill.m_level).ToString();
+ Utils.FindChild(gameObject.transform, "levelbar").GetComponent<GuiBar>().SetValue(skill.m_level / 100f);
+ Utils.FindChild(gameObject.transform, "currentlevel").GetComponent<GuiBar>().SetValue(skill.GetLevelPercentage());
+ m_elements.Add(gameObject);
+ }
+ float size = Mathf.Max(m_baseListSize, (float)skillList.Count * m_spacing);
+ m_listRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ m_totalSkillText.text = "<color=orange>" + player.GetSkills().GetTotalSkill().ToString("0") + "</color><color=white> / </color><color=orange>" + player.GetSkills().GetTotalSkillCap().ToString("0") + "</color>";
+ }
+
+ public void OnClose()
+ {
+ base.gameObject.SetActive(value: false);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SleepText.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SleepText.cs
new file mode 100644
index 0000000..1566d30
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SleepText.cs
@@ -0,0 +1,43 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class SleepText : MonoBehaviour
+{
+ public Text m_textField;
+
+ public Text m_dreamField;
+
+ public DreamTexts m_dreamTexts;
+
+ private void OnEnable()
+ {
+ m_textField.canvasRenderer.SetAlpha(0f);
+ m_textField.CrossFadeAlpha(1f, 1f, ignoreTimeScale: true);
+ m_dreamField.enabled = false;
+ Invoke("HideZZZ", 2f);
+ Invoke("ShowDreamText", 4f);
+ }
+
+ private void HideZZZ()
+ {
+ m_textField.CrossFadeAlpha(0f, 2f, ignoreTimeScale: true);
+ }
+
+ private void ShowDreamText()
+ {
+ DreamTexts.DreamText randomDreamText = m_dreamTexts.GetRandomDreamText();
+ if (randomDreamText != null)
+ {
+ m_dreamField.enabled = true;
+ m_dreamField.canvasRenderer.SetAlpha(0f);
+ m_dreamField.CrossFadeAlpha(1f, 1.5f, ignoreTimeScale: true);
+ m_dreamField.text = Localization.instance.Localize(randomDreamText.m_text);
+ Invoke("HideDreamText", 6.5f);
+ }
+ }
+
+ private void HideDreamText()
+ {
+ m_dreamField.CrossFadeAlpha(0f, 1.5f, ignoreTimeScale: true);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdate.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdate.cs
new file mode 100644
index 0000000..2871f3d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdate.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SlowUpdate : MonoBehaviour
+{
+ private static List<SlowUpdate> m_allInstances = new List<SlowUpdate>();
+
+ private int m_myIndex = -1;
+
+ public virtual void Awake()
+ {
+ m_allInstances.Add(this);
+ m_myIndex = m_allInstances.Count - 1;
+ }
+
+ public virtual void OnDestroy()
+ {
+ if (m_myIndex != -1)
+ {
+ m_allInstances[m_myIndex] = m_allInstances[m_allInstances.Count - 1];
+ m_allInstances[m_myIndex].m_myIndex = m_myIndex;
+ m_allInstances.RemoveAt(m_allInstances.Count - 1);
+ }
+ }
+
+ public virtual void SUpdate()
+ {
+ }
+
+ public static List<SlowUpdate> GetAllInstaces()
+ {
+ return m_allInstances;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdater.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdater.cs
new file mode 100644
index 0000000..b97b1ee
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SlowUpdater.cs
@@ -0,0 +1,41 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SlowUpdater : MonoBehaviour
+{
+ private const int m_updatesPerFrame = 100;
+
+ private void Awake()
+ {
+ StartCoroutine("UpdateLoop");
+ }
+
+ private IEnumerator UpdateLoop()
+ {
+ while (true)
+ {
+ List<SlowUpdate> instances = SlowUpdate.GetAllInstaces();
+ int index = 0;
+ while (index < instances.Count)
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ if (instances.Count == 0)
+ {
+ break;
+ }
+ if (index >= instances.Count)
+ {
+ break;
+ }
+ instances[index].SUpdate();
+ int num = index + 1;
+ index = num;
+ }
+ yield return null;
+ }
+ yield return new WaitForSeconds(0.1f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smelter.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smelter.cs
new file mode 100644
index 0000000..c35b772
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smelter.cs
@@ -0,0 +1,519 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Smelter : MonoBehaviour
+{
+ [Serializable]
+ public class ItemConversion
+ {
+ public ItemDrop m_from;
+
+ public ItemDrop m_to;
+ }
+
+ public string m_name = "Smelter";
+
+ public string m_addOreTooltip = "$piece_smelter_additem";
+
+ public string m_emptyOreTooltip = "$piece_smelter_empty";
+
+ public Switch m_addWoodSwitch;
+
+ public Switch m_addOreSwitch;
+
+ public Switch m_emptyOreSwitch;
+
+ public Transform m_outputPoint;
+
+ public Transform m_roofCheckPoint;
+
+ public GameObject m_enabledObject;
+
+ public Animator[] m_animators;
+
+ public ItemDrop m_fuelItem;
+
+ public int m_maxOre = 10;
+
+ public int m_maxFuel = 10;
+
+ public int m_fuelPerProduct = 4;
+
+ public float m_secPerProduct = 10f;
+
+ public bool m_spawnStack;
+
+ public bool m_requiresRoof;
+
+ public Windmill m_windmill;
+
+ public List<ItemConversion> m_conversion = new List<ItemConversion>();
+
+ public EffectList m_oreAddedEffects = new EffectList();
+
+ public EffectList m_fuelAddedEffects = new EffectList();
+
+ public EffectList m_produceEffects = new EffectList();
+
+ private ZNetView m_nview;
+
+ private bool m_haveRoof;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (!(m_nview == null) && m_nview.GetZDO() != null)
+ {
+ Switch addOreSwitch = m_addOreSwitch;
+ addOreSwitch.m_onUse = (Switch.Callback)Delegate.Combine(addOreSwitch.m_onUse, new Switch.Callback(OnAddOre));
+ if ((bool)m_addWoodSwitch)
+ {
+ Switch addWoodSwitch = m_addWoodSwitch;
+ addWoodSwitch.m_onUse = (Switch.Callback)Delegate.Combine(addWoodSwitch.m_onUse, new Switch.Callback(OnAddFuel));
+ }
+ if ((bool)m_emptyOreSwitch)
+ {
+ Switch emptyOreSwitch = m_emptyOreSwitch;
+ emptyOreSwitch.m_onUse = (Switch.Callback)Delegate.Combine(emptyOreSwitch.m_onUse, new Switch.Callback(OnEmpty));
+ }
+ m_nview.Register<string>("AddOre", RPC_AddOre);
+ m_nview.Register("AddFuel", RPC_AddFuel);
+ m_nview.Register("EmptyProcessed", RPC_EmptyProcessed);
+ WearNTear component = GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
+ }
+ InvokeRepeating("UpdateSmelter", 1f, 1f);
+ }
+ }
+
+ private void DropAllItems()
+ {
+ SpawnProcessed();
+ if (m_fuelItem != null)
+ {
+ float @float = m_nview.GetZDO().GetFloat("fuel");
+ for (int i = 0; i < (int)@float; i++)
+ {
+ Vector3 position = base.transform.position + Vector3.up + UnityEngine.Random.insideUnitSphere * 0.3f;
+ Quaternion rotation = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ UnityEngine.Object.Instantiate(m_fuelItem.gameObject, position, rotation);
+ }
+ }
+ while (GetQueueSize() > 0)
+ {
+ string queuedOre = GetQueuedOre();
+ RemoveOneOre();
+ ItemConversion itemConversion = GetItemConversion(queuedOre);
+ if (itemConversion != null)
+ {
+ Vector3 position2 = base.transform.position + Vector3.up + UnityEngine.Random.insideUnitSphere * 0.3f;
+ Quaternion rotation2 = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f);
+ UnityEngine.Object.Instantiate(itemConversion.m_from.gameObject, position2, rotation2);
+ }
+ else
+ {
+ ZLog.Log("Invalid ore in smelter " + queuedOre);
+ }
+ }
+ }
+
+ private void OnDestroyed()
+ {
+ if (m_nview.IsOwner())
+ {
+ DropAllItems();
+ }
+ }
+
+ private bool IsItemAllowed(ItemDrop.ItemData item)
+ {
+ return IsItemAllowed(item.m_dropPrefab.name);
+ }
+
+ private bool IsItemAllowed(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ItemDrop.ItemData FindCookableItem(Inventory inventory)
+ {
+ foreach (ItemConversion item2 in m_conversion)
+ {
+ ItemDrop.ItemData item = inventory.GetItem(item2.m_from.m_itemData.m_shared.m_name);
+ if (item != null)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private bool OnAddOre(Switch sw, Humanoid user, ItemDrop.ItemData item)
+ {
+ if (item == null)
+ {
+ item = FindCookableItem(user.GetInventory());
+ if (item == null)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_noprocessableitems");
+ return false;
+ }
+ }
+ if (!IsItemAllowed(item.m_dropPrefab.name))
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_wontwork");
+ return false;
+ }
+ ZLog.Log("trying to add " + item.m_shared.m_name);
+ if (GetQueueSize() >= m_maxOre)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_itsfull");
+ return false;
+ }
+ user.Message(MessageHud.MessageType.Center, "$msg_added " + item.m_shared.m_name);
+ user.GetInventory().RemoveItem(item, 1);
+ m_nview.InvokeRPC("AddOre", item.m_dropPrefab.name);
+ return true;
+ }
+
+ private float GetBakeTimer()
+ {
+ return m_nview.GetZDO().GetFloat("bakeTimer");
+ }
+
+ private void SetBakeTimer(float t)
+ {
+ m_nview.GetZDO().Set("bakeTimer", t);
+ }
+
+ private float GetFuel()
+ {
+ return m_nview.GetZDO().GetFloat("fuel");
+ }
+
+ private void SetFuel(float fuel)
+ {
+ m_nview.GetZDO().Set("fuel", fuel);
+ }
+
+ private int GetQueueSize()
+ {
+ return m_nview.GetZDO().GetInt("queued");
+ }
+
+ private void RPC_AddOre(long sender, string name)
+ {
+ if (m_nview.IsOwner())
+ {
+ if (!IsItemAllowed(name))
+ {
+ ZLog.Log("Item not allowed " + name);
+ return;
+ }
+ QueueOre(name);
+ m_oreAddedEffects.Create(base.transform.position, base.transform.rotation);
+ ZLog.Log("Added ore " + name);
+ }
+ }
+
+ private void QueueOre(string name)
+ {
+ int queueSize = GetQueueSize();
+ m_nview.GetZDO().Set("item" + queueSize, name);
+ m_nview.GetZDO().Set("queued", queueSize + 1);
+ }
+
+ private string GetQueuedOre()
+ {
+ if (GetQueueSize() == 0)
+ {
+ return "";
+ }
+ return m_nview.GetZDO().GetString("item0");
+ }
+
+ private void RemoveOneOre()
+ {
+ int queueSize = GetQueueSize();
+ if (queueSize != 0)
+ {
+ for (int i = 0; i < queueSize; i++)
+ {
+ string @string = m_nview.GetZDO().GetString("item" + (i + 1));
+ m_nview.GetZDO().Set("item" + i, @string);
+ }
+ m_nview.GetZDO().Set("queued", queueSize - 1);
+ }
+ }
+
+ private bool OnEmpty(Switch sw, Humanoid user, ItemDrop.ItemData item)
+ {
+ if (GetProcessedQueueSize() <= 0)
+ {
+ return false;
+ }
+ m_nview.InvokeRPC("EmptyProcessed");
+ return true;
+ }
+
+ private void RPC_EmptyProcessed(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ SpawnProcessed();
+ }
+ }
+
+ private bool OnAddFuel(Switch sw, Humanoid user, ItemDrop.ItemData item)
+ {
+ if (item != null && item.m_shared.m_name != m_fuelItem.m_itemData.m_shared.m_name)
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_wrongitem");
+ return false;
+ }
+ if (GetFuel() > (float)(m_maxFuel - 1))
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_itsfull");
+ return false;
+ }
+ if (!user.GetInventory().HaveItem(m_fuelItem.m_itemData.m_shared.m_name))
+ {
+ user.Message(MessageHud.MessageType.Center, "$msg_donthaveany " + m_fuelItem.m_itemData.m_shared.m_name);
+ return false;
+ }
+ user.Message(MessageHud.MessageType.Center, "$msg_added " + m_fuelItem.m_itemData.m_shared.m_name);
+ user.GetInventory().RemoveItem(m_fuelItem.m_itemData.m_shared.m_name, 1);
+ m_nview.InvokeRPC("AddFuel");
+ return true;
+ }
+
+ private void RPC_AddFuel(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ float fuel = GetFuel();
+ SetFuel(fuel + 1f);
+ m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation, base.transform);
+ }
+ }
+
+ private double GetDeltaTime()
+ {
+ DateTime time = ZNet.instance.GetTime();
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("StartTime", time.Ticks));
+ double totalSeconds = (time - dateTime).TotalSeconds;
+ m_nview.GetZDO().Set("StartTime", time.Ticks);
+ return totalSeconds;
+ }
+
+ private float GetAccumulator()
+ {
+ return m_nview.GetZDO().GetFloat("accTime");
+ }
+
+ private void SetAccumulator(float t)
+ {
+ m_nview.GetZDO().Set("accTime", t);
+ }
+
+ private void UpdateRoof()
+ {
+ if (m_requiresRoof)
+ {
+ m_haveRoof = Cover.IsUnderRoof(m_roofCheckPoint.position);
+ }
+ }
+
+ private void UpdateSmelter()
+ {
+ UpdateRoof();
+ if (!m_nview.IsValid() || !m_nview.IsOwner())
+ {
+ return;
+ }
+ double deltaTime = GetDeltaTime();
+ float accumulator = GetAccumulator();
+ accumulator += (float)deltaTime;
+ float num = (m_windmill ? m_windmill.GetPowerOutput() : 1f);
+ while (accumulator >= 1f)
+ {
+ accumulator -= 1f;
+ float fuel = GetFuel();
+ string queuedOre = GetQueuedOre();
+ if ((m_maxFuel != 0 && !(fuel > 0f)) || !(queuedOre != "") || !(m_secPerProduct > 0f) || (m_requiresRoof && !m_haveRoof))
+ {
+ continue;
+ }
+ float num2 = 1f * num;
+ if (m_maxFuel > 0)
+ {
+ float num3 = m_secPerProduct / (float)m_fuelPerProduct;
+ fuel -= num2 / num3;
+ if (fuel < 0f)
+ {
+ fuel = 0f;
+ }
+ SetFuel(fuel);
+ }
+ float bakeTimer = GetBakeTimer();
+ bakeTimer += num2;
+ SetBakeTimer(bakeTimer);
+ if (bakeTimer > m_secPerProduct)
+ {
+ SetBakeTimer(0f);
+ RemoveOneOre();
+ QueueProcessed(queuedOre);
+ }
+ }
+ if (GetQueuedOre() == "" || ((float)m_maxFuel > 0f && GetFuel() == 0f))
+ {
+ SpawnProcessed();
+ }
+ SetAccumulator(accumulator);
+ }
+
+ private void QueueProcessed(string ore)
+ {
+ if (!m_spawnStack)
+ {
+ Spawn(ore, 1);
+ return;
+ }
+ string @string = m_nview.GetZDO().GetString("SpawnOre");
+ int @int = m_nview.GetZDO().GetInt("SpawnAmount");
+ if (@string.Length > 0)
+ {
+ if (@string != ore)
+ {
+ SpawnProcessed();
+ m_nview.GetZDO().Set("SpawnOre", ore);
+ m_nview.GetZDO().Set("SpawnAmount", 1);
+ return;
+ }
+ @int++;
+ ItemConversion itemConversion = GetItemConversion(ore);
+ if (itemConversion == null || @int >= itemConversion.m_to.m_itemData.m_shared.m_maxStackSize)
+ {
+ Spawn(ore, @int);
+ m_nview.GetZDO().Set("SpawnOre", "");
+ m_nview.GetZDO().Set("SpawnAmount", 0);
+ }
+ else
+ {
+ m_nview.GetZDO().Set("SpawnAmount", @int);
+ }
+ }
+ else
+ {
+ m_nview.GetZDO().Set("SpawnOre", ore);
+ m_nview.GetZDO().Set("SpawnAmount", 1);
+ }
+ }
+
+ private void SpawnProcessed()
+ {
+ int @int = m_nview.GetZDO().GetInt("SpawnAmount");
+ if (@int > 0)
+ {
+ string @string = m_nview.GetZDO().GetString("SpawnOre");
+ Spawn(@string, @int);
+ m_nview.GetZDO().Set("SpawnOre", "");
+ m_nview.GetZDO().Set("SpawnAmount", 0);
+ }
+ }
+
+ private int GetProcessedQueueSize()
+ {
+ return m_nview.GetZDO().GetInt("SpawnAmount");
+ }
+
+ private void Spawn(string ore, int stack)
+ {
+ ItemConversion itemConversion = GetItemConversion(ore);
+ if (itemConversion != null)
+ {
+ m_produceEffects.Create(base.transform.position, base.transform.rotation);
+ UnityEngine.Object.Instantiate(itemConversion.m_to.gameObject, m_outputPoint.position, m_outputPoint.rotation).GetComponent<ItemDrop>().m_itemData.m_stack = stack;
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ UpdateState();
+ UpdateHoverTexts();
+ }
+ }
+
+ private ItemConversion GetItemConversion(string itemName)
+ {
+ foreach (ItemConversion item in m_conversion)
+ {
+ if (item.m_from.gameObject.name == itemName)
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private void UpdateState()
+ {
+ bool flag = IsActive();
+ m_enabledObject.SetActive(flag);
+ Animator[] animators = m_animators;
+ foreach (Animator animator in animators)
+ {
+ if (animator.gameObject.activeInHierarchy)
+ {
+ animator.SetBool("active", flag);
+ }
+ }
+ }
+
+ public bool IsActive()
+ {
+ if ((m_maxFuel == 0 || GetFuel() > 0f) && GetQueueSize() > 0)
+ {
+ if (m_requiresRoof)
+ {
+ return m_haveRoof;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void UpdateHoverTexts()
+ {
+ if ((bool)m_addWoodSwitch)
+ {
+ float fuel = GetFuel();
+ m_addWoodSwitch.m_hoverText = m_name + " (" + m_fuelItem.m_itemData.m_shared.m_name + " " + Mathf.Ceil(fuel) + "/" + m_maxFuel + ")\n[<color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add " + m_fuelItem.m_itemData.m_shared.m_name;
+ }
+ if ((bool)m_emptyOreSwitch && m_spawnStack)
+ {
+ int processedQueueSize = GetProcessedQueueSize();
+ m_emptyOreSwitch.m_hoverText = m_name + " (" + processedQueueSize + " $piece_smelter_ready \n[<color=yellow><b>$KEY_Use</b></color>] " + m_emptyOreTooltip;
+ }
+ int queueSize = GetQueueSize();
+ m_addOreSwitch.m_hoverText = m_name + " (" + queueSize + "/" + m_maxOre + ") ";
+ if (m_requiresRoof && !m_haveRoof && Mathf.Sin(Time.time * 10f) > 0f)
+ {
+ m_addOreSwitch.m_hoverText += " <color=yellow>$piece_smelter_reqroof</color>";
+ }
+ Switch addOreSwitch = m_addOreSwitch;
+ addOreSwitch.m_hoverText = addOreSwitch.m_hoverText + "\n[<color=yellow><b>$KEY_Use</b></color>] " + m_addOreTooltip;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smoke.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smoke.cs
new file mode 100644
index 0000000..01dfa2e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Smoke.cs
@@ -0,0 +1,128 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Smoke : MonoBehaviour
+{
+ public Vector3 m_vel = Vector3.up;
+
+ public float m_randomVel = 0.1f;
+
+ public float m_force = 0.1f;
+
+ public float m_ttl = 10f;
+
+ public float m_fadetime = 3f;
+
+ private Rigidbody m_body;
+
+ private float m_time;
+
+ private float m_fadeTimer = -1f;
+
+ private bool m_added;
+
+ private MeshRenderer m_mr;
+
+ private static List<Smoke> m_smoke = new List<Smoke>();
+
+ private void Awake()
+ {
+ m_body = GetComponent<Rigidbody>();
+ m_smoke.Add(this);
+ m_added = true;
+ m_mr = GetComponent<MeshRenderer>();
+ m_vel += Quaternion.Euler(0f, Random.Range(0, 360), 0f) * Vector3.forward * m_randomVel;
+ }
+
+ private void OnDestroy()
+ {
+ if (m_added)
+ {
+ m_smoke.Remove(this);
+ m_added = false;
+ }
+ }
+
+ public void StartFadeOut()
+ {
+ if (!(m_fadeTimer >= 0f))
+ {
+ if (m_added)
+ {
+ m_smoke.Remove(this);
+ m_added = false;
+ }
+ m_fadeTimer = 0f;
+ }
+ }
+
+ public static int GetTotalSmoke()
+ {
+ return m_smoke.Count;
+ }
+
+ public static void FadeOldest()
+ {
+ if (m_smoke.Count != 0)
+ {
+ m_smoke[0].StartFadeOut();
+ }
+ }
+
+ public static void FadeMostDistant()
+ {
+ if (m_smoke.Count == 0)
+ {
+ return;
+ }
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return;
+ }
+ Vector3 position = mainCamera.transform.position;
+ int num = -1;
+ float num2 = 0f;
+ for (int i = 0; i < m_smoke.Count; i++)
+ {
+ float num3 = Vector3.Distance(m_smoke[i].transform.position, position);
+ if (num3 > num2)
+ {
+ num = i;
+ num2 = num3;
+ }
+ }
+ if (num != -1)
+ {
+ m_smoke[num].StartFadeOut();
+ }
+ }
+
+ private void Update()
+ {
+ m_time += Time.deltaTime;
+ if (m_time > m_ttl && m_fadeTimer < 0f)
+ {
+ StartFadeOut();
+ }
+ float num = 1f - Mathf.Clamp01(m_time / m_ttl);
+ m_body.mass = num * num;
+ Vector3 velocity = m_body.velocity;
+ Vector3 vel = m_vel;
+ vel.y *= num;
+ Vector3 vector = vel - velocity;
+ m_body.AddForce(vector * m_force * Time.deltaTime, ForceMode.VelocityChange);
+ if (m_fadeTimer >= 0f)
+ {
+ m_fadeTimer += Time.deltaTime;
+ float a = 1f - Mathf.Clamp01(m_fadeTimer / m_fadetime);
+ Color color = m_mr.material.color;
+ color.a = a;
+ m_mr.material.color = color;
+ if (m_fadeTimer >= m_fadetime)
+ {
+ Object.Destroy(base.gameObject);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeLod.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeLod.cs
new file mode 100644
index 0000000..2ae82c0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeLod.cs
@@ -0,0 +1,5 @@
+using UnityEngine;
+
+public class SmokeLod : MonoBehaviour
+{
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeRenderer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeRenderer.cs
new file mode 100644
index 0000000..474f921
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeRenderer.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SmokeRenderer : MonoBehaviour
+{
+ private InstanceRenderer m_instanceRenderer;
+
+ private List<Vector4> tempTransforms = new List<Vector4>();
+
+ private void Start()
+ {
+ m_instanceRenderer = GetComponent<InstanceRenderer>();
+ }
+
+ private void Update()
+ {
+ if (!(Utils.GetMainCamera() == null))
+ {
+ UpdateInstances();
+ }
+ }
+
+ private void UpdateInstances()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeSpawner.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeSpawner.cs
new file mode 100644
index 0000000..8787c56
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SmokeSpawner.cs
@@ -0,0 +1,73 @@
+using UnityEngine;
+
+public class SmokeSpawner : MonoBehaviour
+{
+ private const float m_minPlayerDistance = 64f;
+
+ private const int m_maxGlobalSmoke = 100;
+
+ private const float m_blockedMinTime = 4f;
+
+ public GameObject m_smokePrefab;
+
+ public float m_interval = 0.5f;
+
+ public LayerMask m_testMask;
+
+ public float m_testRadius = 0.5f;
+
+ private float m_lastSpawnTime;
+
+ private float m_time;
+
+ private void Start()
+ {
+ m_time = Random.Range(0f, m_interval);
+ }
+
+ private void Update()
+ {
+ m_time += Time.deltaTime;
+ if (m_time > m_interval)
+ {
+ m_time = 0f;
+ Spawn();
+ }
+ }
+
+ private void Spawn()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null || Vector3.Distance(localPlayer.transform.position, base.transform.position) > 64f)
+ {
+ m_lastSpawnTime = Time.time;
+ }
+ else if (!TestBlocked())
+ {
+ if (Smoke.GetTotalSmoke() > 100)
+ {
+ Smoke.FadeOldest();
+ }
+ Object.Instantiate(m_smokePrefab, base.transform.position, Random.rotation);
+ m_lastSpawnTime = Time.time;
+ }
+ }
+
+ private bool TestBlocked()
+ {
+ if (Physics.CheckSphere(base.transform.position, m_testRadius, m_testMask.value))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsBlocked()
+ {
+ if (!base.gameObject.activeInHierarchy)
+ {
+ return TestBlocked();
+ }
+ return Time.time - m_lastSpawnTime > 4f;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SnapToGround.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SnapToGround.cs
new file mode 100644
index 0000000..2aa1ad8
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SnapToGround.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class SnapToGround : MonoBehaviour
+{
+ public float m_offset;
+
+ private static List<SnapToGround> m_allSnappers = new List<SnapToGround>();
+
+ private bool m_inList;
+
+ private void Awake()
+ {
+ m_allSnappers.Add(this);
+ m_inList = true;
+ }
+
+ private void OnDestroy()
+ {
+ if (m_inList)
+ {
+ m_allSnappers.Remove(this);
+ m_inList = false;
+ }
+ }
+
+ private void Snap()
+ {
+ if (!(ZoneSystem.instance == null))
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + m_offset;
+ base.transform.position = position;
+ ZNetView component = GetComponent<ZNetView>();
+ if (component != null && component.IsOwner())
+ {
+ component.GetZDO().SetPosition(position);
+ }
+ }
+ }
+
+ public bool HaveUnsnapped()
+ {
+ return m_allSnappers.Count > 0;
+ }
+
+ public static void SnappAll()
+ {
+ if (m_allSnappers.Count == 0)
+ {
+ return;
+ }
+ Heightmap.ForceGenerateAll();
+ foreach (SnapToGround allSnapper in m_allSnappers)
+ {
+ allSnapper.Snap();
+ allSnapper.m_inList = false;
+ }
+ m_allSnappers.Clear();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnAbility.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnAbility.cs
new file mode 100644
index 0000000..f71dfcf
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnAbility.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class SpawnAbility : MonoBehaviour, IProjectile
+{
+ public enum TargetType
+ {
+ ClosestEnemy,
+ RandomEnemy,
+ Caster,
+ Position
+ }
+
+ [Header("Spawn")]
+ public GameObject[] m_spawnPrefab;
+
+ public bool m_alertSpawnedCreature = true;
+
+ public bool m_spawnAtTarget = true;
+
+ public int m_minToSpawn = 1;
+
+ public int m_maxToSpawn = 1;
+
+ public int m_maxSpawned = 3;
+
+ public float m_spawnRadius = 3f;
+
+ public bool m_snapToTerrain = true;
+
+ public float m_spawnGroundOffset;
+
+ public float m_spawnDelay;
+
+ public TargetType m_targetType;
+
+ public float m_maxTargetRange = 40f;
+
+ public EffectList m_spawnEffects = new EffectList();
+
+ [Header("Projectile")]
+ public float m_projectileVelocity = 10f;
+
+ public float m_projectileAccuracy = 10f;
+
+ private Character m_owner;
+
+ public void Setup(Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemDrop.ItemData item)
+ {
+ m_owner = owner;
+ StartCoroutine("Spawn");
+ }
+
+ public string GetTooltipString(int itemQuality)
+ {
+ return "";
+ }
+
+ private IEnumerator Spawn()
+ {
+ int toSpawn = UnityEngine.Random.Range(m_minToSpawn, m_maxToSpawn);
+ int i = 0;
+ while (i < toSpawn)
+ {
+ if (FindTarget(out var point))
+ {
+ Vector3 vector = (m_spawnAtTarget ? point : base.transform.position);
+ Vector2 vector2 = UnityEngine.Random.insideUnitCircle * m_spawnRadius;
+ Vector3 vector3 = vector + new Vector3(vector2.x, 0f, vector2.y);
+ if (m_snapToTerrain)
+ {
+ float solidHeight = ZoneSystem.instance.GetSolidHeight(vector3);
+ vector3.y = solidHeight;
+ }
+ vector3.y += m_spawnGroundOffset;
+ if (!(Mathf.Abs(vector3.y - vector.y) > 100f))
+ {
+ GameObject gameObject = m_spawnPrefab[UnityEngine.Random.Range(0, m_spawnPrefab.Length)];
+ if (m_maxSpawned <= 0 || SpawnSystem.GetNrOfInstances(gameObject) < m_maxSpawned)
+ {
+ GameObject obj = UnityEngine.Object.Instantiate(gameObject, vector3, Quaternion.Euler(0f, UnityEngine.Random.value * (float)Math.PI * 2f, 0f));
+ Projectile component = obj.GetComponent<Projectile>();
+ if ((bool)component)
+ {
+ SetupProjectile(component, point);
+ }
+ BaseAI component2 = obj.GetComponent<BaseAI>();
+ if (component2 != null && m_alertSpawnedCreature)
+ {
+ component2.Alert();
+ }
+ m_spawnEffects.Create(vector3, Quaternion.identity);
+ if (m_spawnDelay > 0f)
+ {
+ yield return new WaitForSeconds(m_spawnDelay);
+ }
+ }
+ }
+ }
+ int num = i + 1;
+ i = num;
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+
+ private void SetupProjectile(Projectile projectile, Vector3 targetPoint)
+ {
+ Vector3 normalized = (targetPoint - projectile.transform.position).normalized;
+ Vector3 axis = Vector3.Cross(normalized, Vector3.up);
+ Quaternion quaternion = Quaternion.AngleAxis(UnityEngine.Random.Range(0f - m_projectileAccuracy, m_projectileAccuracy), Vector3.up);
+ normalized = Quaternion.AngleAxis(UnityEngine.Random.Range(0f - m_projectileAccuracy, m_projectileAccuracy), axis) * normalized;
+ normalized = quaternion * normalized;
+ projectile.Setup(m_owner, normalized * m_projectileVelocity, -1f, null, null);
+ }
+
+ private bool FindTarget(out Vector3 point)
+ {
+ point = Vector3.zero;
+ switch (m_targetType)
+ {
+ case TargetType.ClosestEnemy:
+ {
+ if (m_owner == null)
+ {
+ return false;
+ }
+ Character character2 = BaseAI.FindClosestEnemy(m_owner, base.transform.position, m_maxTargetRange);
+ if (character2 != null)
+ {
+ point = character2.transform.position;
+ return true;
+ }
+ return false;
+ }
+ case TargetType.RandomEnemy:
+ {
+ if (m_owner == null)
+ {
+ return false;
+ }
+ Character character = BaseAI.FindRandomEnemy(m_owner, base.transform.position, m_maxTargetRange);
+ if (character != null)
+ {
+ point = character.transform.position;
+ return true;
+ }
+ return false;
+ }
+ case TargetType.Position:
+ point = base.transform.position;
+ return true;
+ case TargetType.Caster:
+ if (m_owner == null)
+ {
+ return false;
+ }
+ point = m_owner.transform.position;
+ return true;
+ default:
+ return false;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnArea.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnArea.cs
new file mode 100644
index 0000000..1a052fa
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnArea.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SpawnArea : MonoBehaviour
+{
+ [Serializable]
+ public class SpawnData
+ {
+ public GameObject m_prefab;
+
+ public float m_weight;
+
+ [Header("Level")]
+ public int m_maxLevel = 1;
+
+ public int m_minLevel = 1;
+ }
+
+ private const float dt = 2f;
+
+ public List<SpawnData> m_prefabs = new List<SpawnData>();
+
+ public float m_levelupChance = 15f;
+
+ public float m_spawnIntervalSec = 30f;
+
+ public float m_triggerDistance = 256f;
+
+ public bool m_setPatrolSpawnPoint = true;
+
+ public float m_spawnRadius = 2f;
+
+ public float m_nearRadius = 10f;
+
+ public float m_farRadius = 1000f;
+
+ public int m_maxNear = 3;
+
+ public int m_maxTotal = 20;
+
+ public bool m_onGroundOnly;
+
+ public EffectList m_spawnEffects = new EffectList();
+
+ private ZNetView m_nview;
+
+ private float m_spawnTimer;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ InvokeRepeating("UpdateSpawn", 2f, 2f);
+ }
+
+ private void UpdateSpawn()
+ {
+ if (m_nview.IsOwner() && !ZNetScene.instance.OutsideActiveArea(base.transform.position) && Player.IsPlayerInRange(base.transform.position, m_triggerDistance))
+ {
+ m_spawnTimer += 2f;
+ if (m_spawnTimer > m_spawnIntervalSec)
+ {
+ m_spawnTimer = 0f;
+ SpawnOne();
+ }
+ }
+ }
+
+ private bool SpawnOne()
+ {
+ GetInstances(out var near, out var total);
+ if (near >= m_maxNear || total >= m_maxTotal)
+ {
+ return false;
+ }
+ SpawnData spawnData = SelectWeightedPrefab();
+ if (spawnData == null)
+ {
+ return false;
+ }
+ if (!FindSpawnPoint(spawnData.m_prefab, out var point))
+ {
+ return false;
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(spawnData.m_prefab, point, Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f));
+ if (m_setPatrolSpawnPoint)
+ {
+ BaseAI component = gameObject.GetComponent<BaseAI>();
+ if (component != null)
+ {
+ component.SetPatrolPoint();
+ }
+ }
+ Character component2 = gameObject.GetComponent<Character>();
+ if (spawnData.m_maxLevel > 1)
+ {
+ int i;
+ for (i = spawnData.m_minLevel; i < spawnData.m_maxLevel; i++)
+ {
+ if (!(UnityEngine.Random.Range(0f, 100f) <= m_levelupChance))
+ {
+ break;
+ }
+ }
+ if (i > 1)
+ {
+ component2.SetLevel(i);
+ }
+ }
+ Vector3 centerPoint = component2.GetCenterPoint();
+ m_spawnEffects.Create(centerPoint, Quaternion.identity);
+ return true;
+ }
+
+ private bool FindSpawnPoint(GameObject prefab, out Vector3 point)
+ {
+ prefab.GetComponent<BaseAI>();
+ for (int i = 0; i < 10; i++)
+ {
+ Vector3 vector = base.transform.position + Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward * UnityEngine.Random.Range(0f, m_spawnRadius);
+ if (ZoneSystem.instance.FindFloor(vector, out var height) && (!m_onGroundOnly || !ZoneSystem.instance.IsBlocked(vector)))
+ {
+ vector.y = height + 0.1f;
+ point = vector;
+ return true;
+ }
+ }
+ point = Vector3.zero;
+ return false;
+ }
+
+ private SpawnData SelectWeightedPrefab()
+ {
+ if (m_prefabs.Count == 0)
+ {
+ return null;
+ }
+ float num = 0f;
+ foreach (SpawnData prefab in m_prefabs)
+ {
+ num += prefab.m_weight;
+ }
+ float num2 = UnityEngine.Random.Range(0f, num);
+ float num3 = 0f;
+ foreach (SpawnData prefab2 in m_prefabs)
+ {
+ num3 += prefab2.m_weight;
+ if (num2 <= num3)
+ {
+ return prefab2;
+ }
+ }
+ return m_prefabs[m_prefabs.Count - 1];
+ }
+
+ private void GetInstances(out int near, out int total)
+ {
+ near = 0;
+ total = 0;
+ Vector3 position = base.transform.position;
+ foreach (BaseAI allInstance in BaseAI.GetAllInstances())
+ {
+ if (IsSpawnPrefab(allInstance.gameObject))
+ {
+ float num = Utils.DistanceXZ(allInstance.transform.position, position);
+ if (num < m_nearRadius)
+ {
+ near++;
+ }
+ if (num < m_farRadius)
+ {
+ total++;
+ }
+ }
+ }
+ }
+
+ private bool IsSpawnPrefab(GameObject go)
+ {
+ string text = go.name;
+ foreach (SpawnData prefab in m_prefabs)
+ {
+ if (text.StartsWith(prefab.m_prefab.name))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.color = Color.red;
+ Gizmos.DrawWireSphere(base.transform.position, m_spawnRadius);
+ Gizmos.color = Color.yellow;
+ Gizmos.DrawWireSphere(base.transform.position, m_nearRadius);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnOnDamaged.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnOnDamaged.cs
new file mode 100644
index 0000000..a334005
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnOnDamaged.cs
@@ -0,0 +1,29 @@
+using System;
+using UnityEngine;
+
+public class SpawnOnDamaged : MonoBehaviour
+{
+ public GameObject m_spawnOnDamage;
+
+ private void Start()
+ {
+ WearNTear component = GetComponent<WearNTear>();
+ if ((bool)component)
+ {
+ component.m_onDamaged = (Action)Delegate.Combine(component.m_onDamaged, new Action(OnDamaged));
+ }
+ Destructible component2 = GetComponent<Destructible>();
+ if ((bool)component2)
+ {
+ component2.m_onDamaged = (Action)Delegate.Combine(component2.m_onDamaged, new Action(OnDamaged));
+ }
+ }
+
+ private void OnDamaged()
+ {
+ if ((bool)m_spawnOnDamage)
+ {
+ UnityEngine.Object.Instantiate(m_spawnOnDamage, base.transform.position, Quaternion.identity);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnSystem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnSystem.cs
new file mode 100644
index 0000000..8b5fa4a
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SpawnSystem.cs
@@ -0,0 +1,510 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SpawnSystem : MonoBehaviour
+{
+ [Serializable]
+ public class SpawnData
+ {
+ public string m_name = "";
+
+ public bool m_enabled = true;
+
+ public GameObject m_prefab;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ [BitMask(typeof(Heightmap.BiomeArea))]
+ public Heightmap.BiomeArea m_biomeArea = Heightmap.BiomeArea.Everything;
+
+ [Header("Total nr of instances (if near player is set, only instances within the max spawn radius is counted)")]
+ public int m_maxSpawned = 1;
+
+ [Header("How often do we spawn")]
+ public float m_spawnInterval = 4f;
+
+ [Header("Chanse to spawn each spawn interval")]
+ [Range(0f, 100f)]
+ public float m_spawnChance = 100f;
+
+ [Header("Minimum distance to another instance")]
+ public float m_spawnDistance = 10f;
+
+ [Header("Spawn range ( 0 = use global setting )")]
+ public float m_spawnRadiusMin;
+
+ public float m_spawnRadiusMax;
+
+ [Header("Only spawn if this key is set")]
+ public string m_requiredGlobalKey = "";
+
+ [Header("Only spawn if this environment is active")]
+ public List<string> m_requiredEnvironments = new List<string>();
+
+ [Header("Group spawning")]
+ public int m_groupSizeMin = 1;
+
+ public int m_groupSizeMax = 1;
+
+ public float m_groupRadius = 3f;
+
+ [Header("Time of day")]
+ public bool m_spawnAtNight = true;
+
+ public bool m_spawnAtDay = true;
+
+ [Header("Altitude")]
+ public float m_minAltitude = -1000f;
+
+ public float m_maxAltitude = 1000f;
+
+ [Header("Terrain tilt")]
+ public float m_minTilt;
+
+ public float m_maxTilt = 35f;
+
+ [Header("Forest")]
+ public bool m_inForest = true;
+
+ public bool m_outsideForest = true;
+
+ [Header("Ocean depth ")]
+ public float m_minOceanDepth;
+
+ public float m_maxOceanDepth;
+
+ [Header("States")]
+ public bool m_huntPlayer;
+
+ public float m_groundOffset = 0.5f;
+
+ [Header("Level")]
+ public int m_maxLevel = 1;
+
+ public int m_minLevel = 1;
+
+ public float m_levelUpMinCenterDistance;
+
+ [HideInInspector]
+ public bool m_foldout;
+
+ public SpawnData Clone()
+ {
+ SpawnData obj = MemberwiseClone() as SpawnData;
+ obj.m_requiredEnvironments = new List<string>(m_requiredEnvironments);
+ return obj;
+ }
+ }
+
+ private static List<SpawnSystem> m_instances = new List<SpawnSystem>();
+
+ private const float m_spawnDistanceMin = 40f;
+
+ private const float m_spawnDistanceMax = 80f;
+
+ public List<SpawnData> m_spawners = new List<SpawnData>();
+
+ public float m_levelupChance = 10f;
+
+ [HideInInspector]
+ public List<Heightmap.Biome> m_biomeFolded = new List<Heightmap.Biome>();
+
+ private List<Player> m_nearPlayers = new List<Player>();
+
+ private ZNetView m_nview;
+
+ private Heightmap m_heightmap;
+
+ private void Awake()
+ {
+ m_instances.Add(this);
+ m_nview = GetComponent<ZNetView>();
+ m_heightmap = Heightmap.FindHeightmap(base.transform.position);
+ InvokeRepeating("UpdateSpawning", 4f, 4f);
+ }
+
+ private void OnDestroy()
+ {
+ m_instances.Remove(this);
+ }
+
+ private void UpdateSpawning()
+ {
+ if (!m_nview.IsValid() || !m_nview.IsOwner() || Player.m_localPlayer == null)
+ {
+ return;
+ }
+ m_nearPlayers.Clear();
+ GetPlayersInZone(m_nearPlayers);
+ if (m_nearPlayers.Count != 0)
+ {
+ DateTime time = ZNet.instance.GetTime();
+ UpdateSpawnList(m_spawners, time, eventSpawners: false);
+ List<SpawnData> currentSpawners = RandEventSystem.instance.GetCurrentSpawners();
+ if (currentSpawners != null)
+ {
+ UpdateSpawnList(currentSpawners, time, eventSpawners: true);
+ }
+ }
+ }
+
+ private void UpdateSpawnList(List<SpawnData> spawners, DateTime currentTime, bool eventSpawners)
+ {
+ string text = (eventSpawners ? "e_" : "b_");
+ int num = 0;
+ foreach (SpawnData spawner in spawners)
+ {
+ num++;
+ if (!spawner.m_enabled || !m_heightmap.HaveBiome(spawner.m_biome))
+ {
+ continue;
+ }
+ int stableHashCode = (text + spawner.m_prefab.name + num).GetStableHashCode();
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong(stableHashCode, 0L));
+ TimeSpan timeSpan = currentTime - dateTime;
+ int num2 = Mathf.Min(spawner.m_maxSpawned, (int)(timeSpan.TotalSeconds / (double)spawner.m_spawnInterval));
+ if (num2 > 0)
+ {
+ m_nview.GetZDO().Set(stableHashCode, currentTime.Ticks);
+ }
+ for (int i = 0; i < num2; i++)
+ {
+ if (UnityEngine.Random.Range(0f, 100f) > spawner.m_spawnChance)
+ {
+ continue;
+ }
+ if ((!string.IsNullOrEmpty(spawner.m_requiredGlobalKey) && !ZoneSystem.instance.GetGlobalKey(spawner.m_requiredGlobalKey)) || (spawner.m_requiredEnvironments.Count > 0 && !EnvMan.instance.IsEnvironment(spawner.m_requiredEnvironments)) || (!spawner.m_spawnAtDay && EnvMan.instance.IsDay()) || (!spawner.m_spawnAtNight && EnvMan.instance.IsNight()) || GetNrOfInstances(spawner.m_prefab, Vector3.zero, 0f, eventSpawners) >= spawner.m_maxSpawned)
+ {
+ break;
+ }
+ if (!FindBaseSpawnPoint(spawner, m_nearPlayers, out var spawnCenter, out var _) || (spawner.m_spawnDistance > 0f && HaveInstanceInRange(spawner.m_prefab, spawnCenter, spawner.m_spawnDistance)))
+ {
+ continue;
+ }
+ int num3 = UnityEngine.Random.Range(spawner.m_groupSizeMin, spawner.m_groupSizeMax + 1);
+ float num4 = ((num3 > 1) ? spawner.m_groupRadius : 0f);
+ int num5 = 0;
+ for (int j = 0; j < num3 * 2; j++)
+ {
+ Vector2 insideUnitCircle = UnityEngine.Random.insideUnitCircle;
+ Vector3 spawnPoint = spawnCenter + new Vector3(insideUnitCircle.x, 0f, insideUnitCircle.y) * num4;
+ if (IsSpawnPointGood(spawner, ref spawnPoint))
+ {
+ Spawn(spawner, spawnPoint + Vector3.up * spawner.m_groundOffset, eventSpawners);
+ num5++;
+ if (num5 >= num3)
+ {
+ break;
+ }
+ }
+ }
+ ZLog.Log("Spawned " + spawner.m_prefab.name + " x " + num5);
+ }
+ }
+ }
+
+ private void Spawn(SpawnData critter, Vector3 spawnPoint, bool eventSpawner)
+ {
+ GameObject gameObject = UnityEngine.Object.Instantiate(critter.m_prefab, spawnPoint, Quaternion.identity);
+ BaseAI component = gameObject.GetComponent<BaseAI>();
+ if (!(component != null))
+ {
+ return;
+ }
+ if (critter.m_huntPlayer)
+ {
+ component.SetHuntPlayer(hunt: true);
+ }
+ if (critter.m_maxLevel > 1 && (critter.m_levelUpMinCenterDistance <= 0f || spawnPoint.magnitude > critter.m_levelUpMinCenterDistance))
+ {
+ Character component2 = gameObject.GetComponent<Character>();
+ if ((bool)component2)
+ {
+ int i;
+ for (i = critter.m_minLevel; i < critter.m_maxLevel; i++)
+ {
+ if (!(UnityEngine.Random.Range(0f, 100f) <= m_levelupChance))
+ {
+ break;
+ }
+ }
+ if (i > 1)
+ {
+ component2.SetLevel(i);
+ }
+ }
+ }
+ MonsterAI monsterAI = component as MonsterAI;
+ if ((bool)monsterAI)
+ {
+ if (!critter.m_spawnAtDay)
+ {
+ monsterAI.SetDespawnInDay(despawn: true);
+ }
+ if (eventSpawner)
+ {
+ monsterAI.SetEventCreature(despawn: true);
+ }
+ }
+ }
+
+ private bool IsSpawnPointGood(SpawnData spawn, ref Vector3 spawnPoint)
+ {
+ ZoneSystem.instance.GetGroundData(ref spawnPoint, out var normal, out var biome, out var biomeArea, out var hmap);
+ if ((spawn.m_biome & biome) == 0)
+ {
+ return false;
+ }
+ if ((spawn.m_biomeArea & biomeArea) == 0)
+ {
+ return false;
+ }
+ if (ZoneSystem.instance.IsBlocked(spawnPoint))
+ {
+ return false;
+ }
+ float num = spawnPoint.y - ZoneSystem.instance.m_waterLevel;
+ if (num < spawn.m_minAltitude || num > spawn.m_maxAltitude)
+ {
+ return false;
+ }
+ float num2 = Mathf.Cos((float)Math.PI / 180f * spawn.m_maxTilt);
+ float num3 = Mathf.Cos((float)Math.PI / 180f * spawn.m_minTilt);
+ if (normal.y < num2 || normal.y > num3)
+ {
+ return false;
+ }
+ float range = ((spawn.m_spawnRadiusMin > 0f) ? spawn.m_spawnRadiusMin : 40f);
+ if (Player.IsPlayerInRange(spawnPoint, range))
+ {
+ return false;
+ }
+ if ((bool)EffectArea.IsPointInsideArea(spawnPoint, EffectArea.Type.PlayerBase))
+ {
+ return false;
+ }
+ if (!spawn.m_inForest || !spawn.m_outsideForest)
+ {
+ bool flag = WorldGenerator.InForest(spawnPoint);
+ if (!spawn.m_inForest && flag)
+ {
+ return false;
+ }
+ if (!spawn.m_outsideForest && !flag)
+ {
+ return false;
+ }
+ }
+ if (spawn.m_minOceanDepth != spawn.m_maxOceanDepth && hmap != null)
+ {
+ float oceanDepth = hmap.GetOceanDepth(spawnPoint);
+ if (oceanDepth < spawn.m_minOceanDepth || oceanDepth > spawn.m_maxOceanDepth)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool FindBaseSpawnPoint(SpawnData spawn, List<Player> allPlayers, out Vector3 spawnCenter, out Player targetPlayer)
+ {
+ float min = ((spawn.m_spawnRadiusMin > 0f) ? spawn.m_spawnRadiusMin : 40f);
+ float max = ((spawn.m_spawnRadiusMax > 0f) ? spawn.m_spawnRadiusMax : 80f);
+ for (int i = 0; i < 20; i++)
+ {
+ Player player = allPlayers[UnityEngine.Random.Range(0, allPlayers.Count)];
+ Vector3 vector = Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f) * Vector3.forward;
+ Vector3 spawnPoint = player.transform.position + vector * UnityEngine.Random.Range(min, max);
+ if (IsSpawnPointGood(spawn, ref spawnPoint))
+ {
+ spawnCenter = spawnPoint;
+ targetPlayer = player;
+ return true;
+ }
+ }
+ spawnCenter = Vector3.zero;
+ targetPlayer = null;
+ return false;
+ }
+
+ private int GetNrOfInstances(string prefabName)
+ {
+ List<Character> allCharacters = Character.GetAllCharacters();
+ int num = 0;
+ foreach (Character item in allCharacters)
+ {
+ if (item.gameObject.name.StartsWith(prefabName) && InsideZone(item.transform.position))
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ private void GetPlayersInZone(List<Player> players)
+ {
+ foreach (Player allPlayer in Player.GetAllPlayers())
+ {
+ if (InsideZone(allPlayer.transform.position))
+ {
+ players.Add(allPlayer);
+ }
+ }
+ }
+
+ private void GetPlayersNearZone(List<Player> players, float marginDistance)
+ {
+ foreach (Player allPlayer in Player.GetAllPlayers())
+ {
+ if (InsideZone(allPlayer.transform.position, marginDistance))
+ {
+ players.Add(allPlayer);
+ }
+ }
+ }
+
+ private bool IsPlayerTooClose(List<Player> players, Vector3 point, float minDistance)
+ {
+ foreach (Player player in players)
+ {
+ if (Vector3.Distance(player.transform.position, point) < minDistance)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool InPlayerRange(List<Player> players, Vector3 point, float minDistance, float maxDistance)
+ {
+ bool result = false;
+ foreach (Player player in players)
+ {
+ float num = Utils.DistanceXZ(player.transform.position, point);
+ if (num < minDistance)
+ {
+ return false;
+ }
+ if (num < maxDistance)
+ {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ private static bool HaveInstanceInRange(GameObject prefab, Vector3 centerPoint, float minDistance)
+ {
+ string value = prefab.name;
+ if (prefab.GetComponent<BaseAI>() != null)
+ {
+ foreach (BaseAI allInstance in BaseAI.GetAllInstances())
+ {
+ if (allInstance.gameObject.name.StartsWith(value) && Utils.DistanceXZ(allInstance.transform.position, centerPoint) < minDistance)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ GameObject[] array = GameObject.FindGameObjectsWithTag("spawned");
+ foreach (GameObject gameObject in array)
+ {
+ if (gameObject.gameObject.name.StartsWith(value) && Utils.DistanceXZ(gameObject.transform.position, centerPoint) < minDistance)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static int GetNrOfInstances(GameObject prefab)
+ {
+ return GetNrOfInstances(prefab, Vector3.zero, 0f);
+ }
+
+ public static int GetNrOfInstances(GameObject prefab, Vector3 center, float maxRange, bool eventCreaturesOnly = false, bool procreationOnly = false)
+ {
+ string text = prefab.name + "(Clone)";
+ if (prefab.GetComponent<BaseAI>() != null)
+ {
+ List<BaseAI> allInstances = BaseAI.GetAllInstances();
+ int num = 0;
+ {
+ foreach (BaseAI item in allInstances)
+ {
+ if (item.gameObject.name != text || (maxRange > 0f && Vector3.Distance(center, item.transform.position) > maxRange))
+ {
+ continue;
+ }
+ if (eventCreaturesOnly)
+ {
+ MonsterAI monsterAI = item as MonsterAI;
+ if ((bool)monsterAI && !monsterAI.IsEventCreature())
+ {
+ continue;
+ }
+ }
+ if (procreationOnly)
+ {
+ Procreation component = item.GetComponent<Procreation>();
+ if ((bool)component && !component.ReadyForProcreation())
+ {
+ continue;
+ }
+ }
+ num++;
+ }
+ return num;
+ }
+ }
+ GameObject[] array = GameObject.FindGameObjectsWithTag("spawned");
+ int num2 = 0;
+ GameObject[] array2 = array;
+ foreach (GameObject gameObject in array2)
+ {
+ if (gameObject.name.StartsWith(text) && (!(maxRange > 0f) || !(Vector3.Distance(center, gameObject.transform.position) > maxRange)))
+ {
+ num2++;
+ }
+ }
+ return num2;
+ }
+
+ public void GetSpawners(Heightmap.Biome biome, List<SpawnData> spawners)
+ {
+ foreach (SpawnData spawner in m_spawners)
+ {
+ if ((spawner.m_biome & biome) != 0 || spawner.m_biome == biome)
+ {
+ spawners.Add(spawner);
+ }
+ }
+ }
+
+ private bool InsideZone(Vector3 point, float extra = 0f)
+ {
+ float num = ZoneSystem.instance.m_zoneSize * 0.5f + extra;
+ Vector3 position = base.transform.position;
+ if (point.x < position.x - num || point.x > position.x + num)
+ {
+ return false;
+ }
+ if (point.z < position.z - num || point.z > position.z + num)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool HaveGlobalKeys(SpawnData ev)
+ {
+ if (!string.IsNullOrEmpty(ev.m_requiredGlobalKey))
+ {
+ return ZoneSystem.instance.GetGlobalKey(ev.m_requiredGlobalKey);
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StateController.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StateController.cs
new file mode 100644
index 0000000..1e97056
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StateController.cs
@@ -0,0 +1,53 @@
+using UnityEngine;
+
+public class StateController : StateMachineBehaviour
+{
+ public string m_effectJoint = "";
+
+ public EffectList m_enterEffect = new EffectList();
+
+ public bool m_enterDisableChildren;
+
+ public bool m_enterEnableChildren;
+
+ public GameObject[] m_enterDisable = new GameObject[0];
+
+ public GameObject[] m_enterEnable = new GameObject[0];
+
+ private Transform m_effectJoinT;
+
+ public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
+ {
+ if (m_enterEffect.HasEffects())
+ {
+ m_enterEffect.Create(GetEffectPos(animator), animator.transform.rotation);
+ }
+ if (m_enterDisableChildren)
+ {
+ for (int i = 0; i < animator.transform.childCount; i++)
+ {
+ animator.transform.GetChild(i).gameObject.SetActive(value: false);
+ }
+ }
+ if (m_enterEnableChildren)
+ {
+ for (int j = 0; j < animator.transform.childCount; j++)
+ {
+ animator.transform.GetChild(j).gameObject.SetActive(value: true);
+ }
+ }
+ }
+
+ private Vector3 GetEffectPos(Animator animator)
+ {
+ if (m_effectJoint.Length == 0)
+ {
+ return animator.transform.position;
+ }
+ if (m_effectJoinT == null)
+ {
+ m_effectJoinT = Utils.FindChild(animator.transform, m_effectJoint);
+ }
+ return m_effectJoinT.position;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticPhysics.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticPhysics.cs
new file mode 100644
index 0000000..47a4685
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticPhysics.cs
@@ -0,0 +1,122 @@
+using UnityEngine;
+
+public class StaticPhysics : SlowUpdate
+{
+ public bool m_pushUp = true;
+
+ public bool m_fall = true;
+
+ public bool m_checkSolids;
+
+ public float m_fallCheckRadius;
+
+ private ZNetView m_nview;
+
+ private const float m_fallSpeed = 4f;
+
+ private const float m_fallStep = 0.05f;
+
+ private float m_createTime;
+
+ private bool m_falling;
+
+ public override void Awake()
+ {
+ base.Awake();
+ m_nview = GetComponent<ZNetView>();
+ m_createTime = Time.time;
+ }
+
+ private bool ShouldUpdate()
+ {
+ return Time.time - m_createTime > 20f;
+ }
+
+ public override void SUpdate()
+ {
+ if (ShouldUpdate() && !ZNetScene.instance.OutsideActiveArea(base.transform.position) && !m_falling)
+ {
+ if (m_fall)
+ {
+ CheckFall();
+ }
+ if (m_pushUp)
+ {
+ PushUp();
+ }
+ }
+ }
+
+ private void CheckFall()
+ {
+ float fallHeight = GetFallHeight();
+ if (base.transform.position.y > fallHeight + 0.05f)
+ {
+ Fall();
+ }
+ }
+
+ private float GetFallHeight()
+ {
+ if (m_checkSolids)
+ {
+ if (ZoneSystem.instance.GetSolidHeight(base.transform.position, m_fallCheckRadius, out var height, base.transform))
+ {
+ return height;
+ }
+ return base.transform.position.y;
+ }
+ if (ZoneSystem.instance.GetGroundHeight(base.transform.position, out var height2))
+ {
+ return height2;
+ }
+ return base.transform.position.y;
+ }
+
+ private void Fall()
+ {
+ m_falling = true;
+ base.gameObject.isStatic = false;
+ InvokeRepeating("FallUpdate", 0.05f, 0.05f);
+ }
+
+ private void FallUpdate()
+ {
+ float fallHeight = GetFallHeight();
+ Vector3 position = base.transform.position;
+ position.y -= 0.2f;
+ if (position.y <= fallHeight)
+ {
+ position.y = fallHeight;
+ StopFalling();
+ }
+ base.transform.position = position;
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ m_nview.GetZDO().SetPosition(base.transform.position);
+ }
+ }
+
+ private void StopFalling()
+ {
+ base.gameObject.isStatic = true;
+ m_falling = false;
+ CancelInvoke("FallUpdate");
+ }
+
+ private void PushUp()
+ {
+ if (ZoneSystem.instance.GetGroundHeight(base.transform.position, out var height) && base.transform.position.y < height - 0.05f)
+ {
+ base.gameObject.isStatic = false;
+ Vector3 position = base.transform.position;
+ position.y = height;
+ base.transform.position = position;
+ base.gameObject.isStatic = true;
+ if (m_nview.IsValid() && m_nview.IsOwner())
+ {
+ m_nview.GetZDO().SetPosition(base.transform.position);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticTarget.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticTarget.cs
new file mode 100644
index 0000000..a538dc5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StaticTarget.cs
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class StaticTarget : MonoBehaviour
+{
+ public bool m_primaryTarget;
+
+ public bool m_randomTarget = true;
+
+ private List<Collider> m_colliders;
+
+ private Vector3 m_center;
+
+ private bool m_haveCenter;
+
+ public virtual bool IsValidMonsterTarget()
+ {
+ return true;
+ }
+
+ public Vector3 GetCenter()
+ {
+ if (!m_haveCenter)
+ {
+ List<Collider> allColliders = GetAllColliders();
+ m_center = Vector3.zero;
+ foreach (Collider item in allColliders)
+ {
+ if ((bool)item)
+ {
+ m_center += item.bounds.center;
+ }
+ }
+ m_center /= (float)m_colliders.Count;
+ }
+ return m_center;
+ }
+
+ public List<Collider> GetAllColliders()
+ {
+ if (m_colliders == null)
+ {
+ Collider[] componentsInChildren = GetComponentsInChildren<Collider>();
+ m_colliders = new List<Collider>();
+ m_colliders.Capacity = componentsInChildren.Length;
+ Collider[] array = componentsInChildren;
+ foreach (Collider collider in array)
+ {
+ if (collider.enabled && collider.gameObject.activeInHierarchy && !collider.isTrigger)
+ {
+ m_colliders.Add(collider);
+ }
+ }
+ }
+ return m_colliders;
+ }
+
+ public Vector3 FindClosestPoint(Vector3 point)
+ {
+ List<Collider> allColliders = GetAllColliders();
+ if (allColliders.Count == 0)
+ {
+ return base.transform.position;
+ }
+ float num = 9999999f;
+ Vector3 result = Vector3.zero;
+ foreach (Collider item in allColliders)
+ {
+ MeshCollider meshCollider = item as MeshCollider;
+ Vector3 vector = (((bool)meshCollider && !meshCollider.convex) ? item.ClosestPointOnBounds(point) : item.ClosestPoint(point));
+ float num2 = Vector3.Distance(point, vector);
+ if (num2 < num)
+ {
+ result = vector;
+ num = num2;
+ }
+ }
+ return result;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StationExtension.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StationExtension.cs
new file mode 100644
index 0000000..321c548
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StationExtension.cs
@@ -0,0 +1,158 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class StationExtension : MonoBehaviour, Hoverable
+{
+ public CraftingStation m_craftingStation;
+
+ public float m_maxStationDistance = 5f;
+
+ public GameObject m_connectionPrefab;
+
+ private GameObject m_connection;
+
+ private Piece m_piece;
+
+ private Collider[] m_colliders;
+
+ private static List<StationExtension> m_allExtensions = new List<StationExtension>();
+
+ private void Awake()
+ {
+ if (GetComponent<ZNetView>().GetZDO() != null)
+ {
+ m_piece = GetComponent<Piece>();
+ m_allExtensions.Add(this);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if ((bool)m_connection)
+ {
+ Object.Destroy(m_connection);
+ m_connection = null;
+ }
+ m_allExtensions.Remove(this);
+ }
+
+ public string GetHoverText()
+ {
+ PokeEffect();
+ return Localization.instance.Localize(m_piece.m_name);
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_piece.m_name);
+ }
+
+ public string GetExtensionName()
+ {
+ return m_piece.m_name;
+ }
+
+ public static void FindExtensions(CraftingStation station, Vector3 pos, List<StationExtension> extensions)
+ {
+ foreach (StationExtension allExtension in m_allExtensions)
+ {
+ if (Vector3.Distance(allExtension.transform.position, pos) < allExtension.m_maxStationDistance && allExtension.m_craftingStation.m_name == station.m_name && !ExtensionInList(extensions, allExtension))
+ {
+ extensions.Add(allExtension);
+ }
+ }
+ }
+
+ private static bool ExtensionInList(List<StationExtension> extensions, StationExtension extension)
+ {
+ foreach (StationExtension extension2 in extensions)
+ {
+ if (extension2.GetExtensionName() == extension.GetExtensionName())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool OtherExtensionInRange(float radius)
+ {
+ foreach (StationExtension allExtension in m_allExtensions)
+ {
+ if (!(allExtension == this) && Vector3.Distance(allExtension.transform.position, base.transform.position) < radius)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<CraftingStation> FindStationsInRange(Vector3 center)
+ {
+ List<CraftingStation> list = new List<CraftingStation>();
+ CraftingStation.FindStationsInRange(m_craftingStation.m_name, center, m_maxStationDistance, list);
+ return list;
+ }
+
+ public CraftingStation FindClosestStationInRange(Vector3 center)
+ {
+ return CraftingStation.FindClosestStationInRange(m_craftingStation.m_name, center, m_maxStationDistance);
+ }
+
+ private void PokeEffect()
+ {
+ CraftingStation craftingStation = FindClosestStationInRange(base.transform.position);
+ if ((bool)craftingStation)
+ {
+ StartConnectionEffect(craftingStation);
+ }
+ }
+
+ public void StartConnectionEffect(CraftingStation station)
+ {
+ StartConnectionEffect(station.GetConnectionEffectPoint());
+ }
+
+ public void StartConnectionEffect(Vector3 targetPos)
+ {
+ Vector3 center = GetCenter();
+ if (m_connection == null)
+ {
+ m_connection = Object.Instantiate(m_connectionPrefab, center, Quaternion.identity);
+ }
+ Vector3 vector = targetPos - center;
+ Quaternion rotation = Quaternion.LookRotation(vector.normalized);
+ m_connection.transform.position = center;
+ m_connection.transform.rotation = rotation;
+ m_connection.transform.localScale = new Vector3(1f, 1f, vector.magnitude);
+ CancelInvoke("StopConnectionEffect");
+ Invoke("StopConnectionEffect", 1f);
+ }
+
+ public void StopConnectionEffect()
+ {
+ if ((bool)m_connection)
+ {
+ Object.Destroy(m_connection);
+ m_connection = null;
+ }
+ }
+
+ private Vector3 GetCenter()
+ {
+ if (m_colliders == null)
+ {
+ m_colliders = GetComponentsInChildren<Collider>();
+ }
+ Vector3 position = base.transform.position;
+ Collider[] colliders = m_colliders;
+ foreach (Collider collider in colliders)
+ {
+ if (collider.bounds.max.y > position.y)
+ {
+ position.y = collider.bounds.max.y;
+ }
+ }
+ return position;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StatusEffect.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StatusEffect.cs
new file mode 100644
index 0000000..40ba74b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StatusEffect.cs
@@ -0,0 +1,268 @@
+using System;
+using UnityEngine;
+
+public class StatusEffect : ScriptableObject
+{
+ public enum StatusAttribute
+ {
+ None = 0,
+ ColdResistance = 1,
+ DoubleImpactDamage = 2,
+ SailingPower = 4
+ }
+
+ [Header("__Common__")]
+ public string m_name = "";
+
+ public string m_category = "";
+
+ public Sprite m_icon;
+
+ public bool m_flashIcon;
+
+ public bool m_cooldownIcon;
+
+ [TextArea]
+ public string m_tooltip = "";
+
+ [BitMask(typeof(StatusAttribute))]
+ public StatusAttribute m_attributes;
+
+ public MessageHud.MessageType m_startMessageType = MessageHud.MessageType.TopLeft;
+
+ public string m_startMessage = "";
+
+ public MessageHud.MessageType m_stopMessageType = MessageHud.MessageType.TopLeft;
+
+ public string m_stopMessage = "";
+
+ public MessageHud.MessageType m_repeatMessageType = MessageHud.MessageType.TopLeft;
+
+ public string m_repeatMessage = "";
+
+ public float m_repeatInterval;
+
+ public float m_ttl;
+
+ public EffectList m_startEffects = new EffectList();
+
+ public EffectList m_stopEffects = new EffectList();
+
+ [Header("__Guardian power__")]
+ public float m_cooldown;
+
+ public string m_activationAnimation = "gpower";
+
+ [NonSerialized]
+ public bool m_isNew = true;
+
+ private float m_msgTimer;
+
+ protected Character m_character;
+
+ protected float m_time;
+
+ protected GameObject[] m_startEffectInstances;
+
+ public StatusEffect Clone()
+ {
+ return MemberwiseClone() as StatusEffect;
+ }
+
+ public virtual bool CanAdd(Character character)
+ {
+ return true;
+ }
+
+ public virtual void Setup(Character character)
+ {
+ m_character = character;
+ if (!string.IsNullOrEmpty(m_startMessage))
+ {
+ m_character.Message(m_startMessageType, m_startMessage);
+ }
+ TriggerStartEffects();
+ }
+
+ public virtual void SetAttacker(Character attacker)
+ {
+ }
+
+ public virtual string GetTooltipString()
+ {
+ return m_tooltip;
+ }
+
+ private void OnApplicationQuit()
+ {
+ m_startEffectInstances = null;
+ }
+
+ public virtual void OnDestroy()
+ {
+ RemoveStartEffects();
+ }
+
+ protected void TriggerStartEffects()
+ {
+ RemoveStartEffects();
+ float radius = m_character.GetRadius();
+ m_startEffectInstances = m_startEffects.Create(m_character.GetCenterPoint(), m_character.transform.rotation, m_character.transform, radius * 2f);
+ }
+
+ private void RemoveStartEffects()
+ {
+ if (m_startEffectInstances == null || !(ZNetScene.instance != null))
+ {
+ return;
+ }
+ GameObject[] startEffectInstances = m_startEffectInstances;
+ foreach (GameObject gameObject in startEffectInstances)
+ {
+ if ((bool)gameObject)
+ {
+ ZNetView component = gameObject.GetComponent<ZNetView>();
+ if (component.IsValid())
+ {
+ component.ClaimOwnership();
+ component.Destroy();
+ }
+ }
+ }
+ m_startEffectInstances = null;
+ }
+
+ public virtual void Stop()
+ {
+ RemoveStartEffects();
+ m_stopEffects.Create(m_character.transform.position, m_character.transform.rotation);
+ if (!string.IsNullOrEmpty(m_stopMessage))
+ {
+ m_character.Message(m_stopMessageType, m_stopMessage);
+ }
+ }
+
+ public virtual void UpdateStatusEffect(float dt)
+ {
+ m_time += dt;
+ if (m_repeatInterval > 0f && !string.IsNullOrEmpty(m_repeatMessage))
+ {
+ m_msgTimer += dt;
+ if (m_msgTimer > m_repeatInterval)
+ {
+ m_msgTimer = 0f;
+ m_character.Message(m_repeatMessageType, m_repeatMessage);
+ }
+ }
+ }
+
+ public virtual bool IsDone()
+ {
+ if (m_ttl > 0f && m_time > m_ttl)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public virtual void ResetTime()
+ {
+ m_time = 0f;
+ }
+
+ public float GetDuration()
+ {
+ return m_time;
+ }
+
+ public float GetRemaningTime()
+ {
+ return m_ttl - m_time;
+ }
+
+ public virtual string GetIconText()
+ {
+ if (m_ttl > 0f)
+ {
+ return GetTimeString(m_ttl - GetDuration());
+ }
+ return "";
+ }
+
+ public static string GetTimeString(float time, bool sufix = false, bool alwaysShowMinutes = false)
+ {
+ if (time > 0f)
+ {
+ int num = Mathf.CeilToInt(time);
+ int num2 = (int)((float)num / 60f);
+ int num3 = Mathf.Max(0, num - num2 * 60);
+ if (sufix)
+ {
+ if (num2 > 0 || alwaysShowMinutes)
+ {
+ return num2 + "m:" + num3.ToString("00") + "s";
+ }
+ return num3 + "s";
+ }
+ if (num2 > 0 || alwaysShowMinutes)
+ {
+ return num2 + ":" + num3.ToString("00");
+ }
+ return num3.ToString();
+ }
+ return "";
+ }
+
+ public virtual void ModifyAttack(Skills.SkillType skill, ref HitData hitData)
+ {
+ }
+
+ public virtual void ModifyHealthRegen(ref float regenMultiplier)
+ {
+ }
+
+ public virtual void ModifyStaminaRegen(ref float staminaRegen)
+ {
+ }
+
+ public virtual void ModifyDamageMods(ref HitData.DamageModifiers modifiers)
+ {
+ }
+
+ public virtual void ModifyRaiseSkill(Skills.SkillType skill, ref float value)
+ {
+ }
+
+ public virtual void ModifySpeed(ref float speed)
+ {
+ }
+
+ public virtual void ModifyNoise(float baseNoise, ref float noise)
+ {
+ }
+
+ public virtual void ModifyStealth(float baseStealth, ref float stealth)
+ {
+ }
+
+ public virtual void ModifyMaxCarryWeight(float baseLimit, ref float limit)
+ {
+ }
+
+ public virtual void ModifyRunStaminaDrain(float baseDrain, ref float drain)
+ {
+ }
+
+ public virtual void ModifyJumpStaminaUsage(float baseStaminaUse, ref float staminaUse)
+ {
+ }
+
+ public virtual void OnDamaged(HitData hit, Character attacker)
+ {
+ }
+
+ public bool HaveAttribute(StatusAttribute value)
+ {
+ return (m_attributes & value) != 0;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StealthSystem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StealthSystem.cs
new file mode 100644
index 0000000..774ca07
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StealthSystem.cs
@@ -0,0 +1,83 @@
+using UnityEngine;
+
+public class StealthSystem : MonoBehaviour
+{
+ private static StealthSystem m_instance;
+
+ public LayerMask m_shadowTestMask;
+
+ public float m_minLightLevel = 0.2f;
+
+ public float m_maxLightLevel = 1.6f;
+
+ private Light[] m_allLights;
+
+ private float m_lastLightListUpdate;
+
+ private const float m_lightUpdateInterval = 1f;
+
+ public static StealthSystem instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ public float GetLightFactor(Vector3 point)
+ {
+ float lightLevel = GetLightLevel(point);
+ return Utils.LerpStep(m_minLightLevel, m_maxLightLevel, lightLevel);
+ }
+
+ public float GetLightLevel(Vector3 point)
+ {
+ if (Time.time - m_lastLightListUpdate > 1f)
+ {
+ m_lastLightListUpdate = Time.time;
+ m_allLights = Object.FindObjectsOfType<Light>();
+ }
+ float num = RenderSettings.ambientIntensity * RenderSettings.ambientLight.grayscale;
+ Light[] allLights = m_allLights;
+ foreach (Light light in allLights)
+ {
+ if (light == null)
+ {
+ continue;
+ }
+ if (light.type == LightType.Directional)
+ {
+ float num2 = 1f;
+ if (light.shadows != 0 && (Physics.Raycast(point - light.transform.forward * 1000f, light.transform.forward, 1000f, m_shadowTestMask) || Physics.Raycast(point, -light.transform.forward, 1000f, m_shadowTestMask)))
+ {
+ num2 = 1f - light.shadowStrength;
+ }
+ float num3 = light.intensity * light.color.grayscale * num2;
+ num += num3;
+ continue;
+ }
+ float num4 = Vector3.Distance(light.transform.position, point);
+ if (num4 > light.range)
+ {
+ continue;
+ }
+ float num5 = 1f;
+ if (light.shadows != 0)
+ {
+ Vector3 vector = point - light.transform.position;
+ if (Physics.Raycast(light.transform.position, vector.normalized, vector.magnitude, m_shadowTestMask) || Physics.Raycast(point, -vector.normalized, vector.magnitude, m_shadowTestMask))
+ {
+ num5 = 1f - light.shadowStrength;
+ }
+ }
+ float num6 = 1f - num4 / light.range;
+ float num7 = light.intensity * light.color.grayscale * num6 * num5;
+ num += num7;
+ }
+ return num;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SteamManager.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SteamManager.cs
new file mode 100644
index 0000000..7866906
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/SteamManager.cs
@@ -0,0 +1,166 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Steamworks;
+using UnityEngine;
+
+[DisallowMultipleComponent]
+public class SteamManager : MonoBehaviour
+{
+ public static uint[] ACCEPTED_APPIDs = new uint[2] { 1223920u, 892970u };
+
+ public static uint APP_ID = 0u;
+
+ private static int m_serverPort = 2456;
+
+ private static SteamManager s_instance;
+
+ private static bool s_EverInialized;
+
+ private bool m_bInitialized;
+
+ private SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook;
+
+ public static SteamManager instance => s_instance;
+
+ public static bool Initialized
+ {
+ get
+ {
+ if (s_instance != null)
+ {
+ return s_instance.m_bInitialized;
+ }
+ return false;
+ }
+ }
+
+ public static bool Initialize()
+ {
+ if (s_instance == null)
+ {
+ new GameObject("SteamManager").AddComponent<SteamManager>();
+ }
+ return Initialized;
+ }
+
+ private static void SteamAPIDebugTextHook(int nSeverity, StringBuilder pchDebugText)
+ {
+ Debug.LogWarning(pchDebugText);
+ }
+
+ public static void SetServerPort(int port)
+ {
+ m_serverPort = port;
+ }
+
+ private uint LoadAPPID()
+ {
+ string environmentVariable = Environment.GetEnvironmentVariable("SteamAppId");
+ if (environmentVariable != null)
+ {
+ ZLog.Log("Using environment steamid " + environmentVariable);
+ return uint.Parse(environmentVariable);
+ }
+ try
+ {
+ string s = File.ReadAllText("steam_appid.txt");
+ ZLog.Log("Using steam_appid.txt");
+ return uint.Parse(s);
+ }
+ catch
+ {
+ }
+ ZLog.LogWarning("Failed to find APPID");
+ return 0u;
+ }
+
+ private void Awake()
+ {
+ if (s_instance != null)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ return;
+ }
+ s_instance = this;
+ APP_ID = LoadAPPID();
+ ZLog.Log("Using steam APPID:" + APP_ID);
+ if (!ACCEPTED_APPIDs.Contains(APP_ID))
+ {
+ ZLog.Log("Invalid APPID");
+ Application.Quit();
+ return;
+ }
+ if (s_EverInialized)
+ {
+ throw new Exception("Tried to Initialize the SteamAPI twice in one session!");
+ }
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ if (!Packsize.Test())
+ {
+ Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this);
+ }
+ if (!DllCheck.Test())
+ {
+ Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this);
+ }
+ try
+ {
+ if (SteamAPI.RestartAppIfNecessary((AppId_t)APP_ID))
+ {
+ Application.Quit();
+ return;
+ }
+ }
+ catch (DllNotFoundException ex)
+ {
+ Debug.LogError("[Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.\n" + ex, this);
+ Application.Quit();
+ return;
+ }
+ m_bInitialized = SteamAPI.Init();
+ if (!m_bInitialized)
+ {
+ Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this);
+ }
+ else
+ {
+ s_EverInialized = true;
+ }
+ }
+
+ private void OnEnable()
+ {
+ if (s_instance == null)
+ {
+ s_instance = this;
+ }
+ if (m_bInitialized && m_SteamAPIWarningMessageHook == null)
+ {
+ m_SteamAPIWarningMessageHook = SteamAPIDebugTextHook;
+ SteamClient.SetWarningMessageHook(m_SteamAPIWarningMessageHook);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ ZLog.Log("Steam manager on destroy");
+ if (!(s_instance != this))
+ {
+ s_instance = null;
+ if (m_bInitialized)
+ {
+ SteamAPI.Shutdown();
+ }
+ }
+ }
+
+ private void Update()
+ {
+ if (m_bInitialized)
+ {
+ SteamAPI.RunCallbacks();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StoreGui.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StoreGui.cs
new file mode 100644
index 0000000..8ea6962
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/StoreGui.cs
@@ -0,0 +1,354 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class StoreGui : MonoBehaviour
+{
+ private static StoreGui m_instance;
+
+ public GameObject m_rootPanel;
+
+ public Button m_buyButton;
+
+ public Button m_sellButton;
+
+ public RectTransform m_listRoot;
+
+ public GameObject m_listElement;
+
+ public Scrollbar m_listScroll;
+
+ public ScrollRectEnsureVisible m_itemEnsureVisible;
+
+ public Text m_coinText;
+
+ public EffectList m_buyEffects = new EffectList();
+
+ public EffectList m_sellEffects = new EffectList();
+
+ public float m_hideDistance = 5f;
+
+ public float m_itemSpacing = 64f;
+
+ public ItemDrop m_coinPrefab;
+
+ private List<GameObject> m_itemList = new List<GameObject>();
+
+ private Trader.TradeItem m_selectedItem;
+
+ private Trader m_trader;
+
+ private float m_itemlistBaseSize;
+
+ private int m_hiddenFrames;
+
+ private List<ItemDrop.ItemData> m_tempItems = new List<ItemDrop.ItemData>();
+
+ public static StoreGui instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_rootPanel.SetActive(value: false);
+ m_itemlistBaseSize = m_listRoot.rect.height;
+ }
+
+ private void OnDestroy()
+ {
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ private void Update()
+ {
+ if (!m_rootPanel.activeSelf)
+ {
+ m_hiddenFrames++;
+ return;
+ }
+ m_hiddenFrames = 0;
+ if (!m_trader)
+ {
+ Hide();
+ return;
+ }
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null || localPlayer.IsDead() || localPlayer.InCutscene())
+ {
+ Hide();
+ return;
+ }
+ if (Vector3.Distance(m_trader.transform.position, Player.m_localPlayer.transform.position) > m_hideDistance)
+ {
+ Hide();
+ return;
+ }
+ if (InventoryGui.IsVisible() || Minimap.IsOpen())
+ {
+ Hide();
+ return;
+ }
+ if ((Chat.instance == null || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && (bool)TextViewer.instance && !TextViewer.instance.IsVisible() && !localPlayer.InCutscene() && (ZInput.GetButtonDown("JoyButtonB") || Input.GetKeyDown(KeyCode.Escape) || ZInput.GetButtonDown("Use")))
+ {
+ ZInput.ResetButtonStatus("JoyButtonB");
+ Hide();
+ }
+ UpdateBuyButton();
+ UpdateSellButton();
+ UpdateRecipeGamepadInput();
+ m_coinText.text = GetPlayerCoins().ToString();
+ }
+
+ public void Show(Trader trader)
+ {
+ if (!(m_trader == trader) || !IsVisible())
+ {
+ m_trader = trader;
+ m_rootPanel.SetActive(value: true);
+ FillList();
+ }
+ }
+
+ public void Hide()
+ {
+ m_trader = null;
+ m_rootPanel.SetActive(value: false);
+ }
+
+ public static bool IsVisible()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_hiddenFrames <= 1;
+ }
+ return false;
+ }
+
+ public void OnBuyItem()
+ {
+ BuySelectedItem();
+ }
+
+ private void BuySelectedItem()
+ {
+ if (m_selectedItem != null && CanAfford(m_selectedItem))
+ {
+ int stack = Mathf.Min(m_selectedItem.m_stack, m_selectedItem.m_prefab.m_itemData.m_shared.m_maxStackSize);
+ int quality = m_selectedItem.m_prefab.m_itemData.m_quality;
+ int variant = m_selectedItem.m_prefab.m_itemData.m_variant;
+ if (Player.m_localPlayer.GetInventory().AddItem(m_selectedItem.m_prefab.name, stack, quality, variant, 0L, "") != null)
+ {
+ Player.m_localPlayer.GetInventory().RemoveItem(m_coinPrefab.m_itemData.m_shared.m_name, m_selectedItem.m_price);
+ m_trader.OnBought(m_selectedItem);
+ m_buyEffects.Create(base.transform.position, Quaternion.identity);
+ Player.m_localPlayer.ShowPickupMessage(m_selectedItem.m_prefab.m_itemData, m_selectedItem.m_prefab.m_itemData.m_stack);
+ FillList();
+ GoogleAnalyticsV4.instance.LogEvent("Game", "BoughtItem", m_selectedItem.m_prefab.name, 0L);
+ }
+ }
+ }
+
+ public void OnSellItem()
+ {
+ SellItem();
+ }
+
+ private void SellItem()
+ {
+ ItemDrop.ItemData sellableItem = GetSellableItem();
+ if (sellableItem != null)
+ {
+ int stack = sellableItem.m_shared.m_value * sellableItem.m_stack;
+ Player.m_localPlayer.GetInventory().RemoveItem(sellableItem);
+ Player.m_localPlayer.GetInventory().AddItem(m_coinPrefab.gameObject.name, stack, m_coinPrefab.m_itemData.m_quality, m_coinPrefab.m_itemData.m_variant, 0L, "");
+ string text = "";
+ text = ((sellableItem.m_stack <= 1) ? sellableItem.m_shared.m_name : (sellableItem.m_stack + "x" + sellableItem.m_shared.m_name));
+ m_sellEffects.Create(base.transform.position, Quaternion.identity);
+ Player.m_localPlayer.Message(MessageHud.MessageType.TopLeft, Localization.instance.Localize("$msg_sold", text, stack.ToString()), 0, sellableItem.m_shared.m_icons[0]);
+ m_trader.OnSold();
+ FillList();
+ GoogleAnalyticsV4.instance.LogEvent("Game", "SoldItem", text, 0L);
+ }
+ }
+
+ private int GetPlayerCoins()
+ {
+ return Player.m_localPlayer.GetInventory().CountItems(m_coinPrefab.m_itemData.m_shared.m_name);
+ }
+
+ private bool CanAfford(Trader.TradeItem item)
+ {
+ int playerCoins = GetPlayerCoins();
+ return item.m_price <= playerCoins;
+ }
+
+ private void FillList()
+ {
+ int playerCoins = GetPlayerCoins();
+ int num = GetSelectedItemIndex();
+ List<Trader.TradeItem> items = m_trader.m_items;
+ foreach (GameObject item in m_itemList)
+ {
+ Object.Destroy(item);
+ }
+ m_itemList.Clear();
+ float b = (float)items.Count * m_itemSpacing;
+ b = Mathf.Max(m_itemlistBaseSize, b);
+ m_listRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, b);
+ for (int i = 0; i < items.Count; i++)
+ {
+ Trader.TradeItem tradeItem = items[i];
+ GameObject element = Object.Instantiate(m_listElement, m_listRoot);
+ element.SetActive(value: true);
+ (element.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)i * (0f - m_itemSpacing));
+ bool flag = tradeItem.m_price <= playerCoins;
+ Image component = element.transform.Find("icon").GetComponent<Image>();
+ component.sprite = tradeItem.m_prefab.m_itemData.m_shared.m_icons[0];
+ component.color = (flag ? Color.white : new Color(1f, 0f, 1f, 0f));
+ string text = Localization.instance.Localize(tradeItem.m_prefab.m_itemData.m_shared.m_name);
+ if (tradeItem.m_stack > 1)
+ {
+ text = text + " x" + tradeItem.m_stack;
+ }
+ Text component2 = element.transform.Find("name").GetComponent<Text>();
+ component2.text = text;
+ component2.color = (flag ? Color.white : Color.grey);
+ UITooltip component3 = element.GetComponent<UITooltip>();
+ component3.m_topic = tradeItem.m_prefab.m_itemData.m_shared.m_name;
+ component3.m_text = tradeItem.m_prefab.m_itemData.GetTooltip();
+ Text component4 = Utils.FindChild(element.transform, "price").GetComponent<Text>();
+ component4.text = tradeItem.m_price.ToString();
+ if (!flag)
+ {
+ component4.color = Color.grey;
+ }
+ element.GetComponent<Button>().onClick.AddListener(delegate
+ {
+ OnSelectedItem(element);
+ });
+ m_itemList.Add(element);
+ }
+ if (num < 0)
+ {
+ num = 0;
+ }
+ SelectItem(num, center: false);
+ }
+
+ private void OnSelectedItem(GameObject button)
+ {
+ int index = FindSelectedRecipe(button);
+ SelectItem(index, center: false);
+ }
+
+ private int FindSelectedRecipe(GameObject button)
+ {
+ for (int i = 0; i < m_itemList.Count; i++)
+ {
+ if (m_itemList[i] == button)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void SelectItem(int index, bool center)
+ {
+ ZLog.Log("Setting selected recipe " + index);
+ for (int i = 0; i < m_itemList.Count; i++)
+ {
+ bool active = i == index;
+ m_itemList[i].transform.Find("selected").gameObject.SetActive(active);
+ }
+ if (center && index >= 0)
+ {
+ m_itemEnsureVisible.CenterOnItem(m_itemList[index].transform as RectTransform);
+ }
+ if (index < 0)
+ {
+ m_selectedItem = null;
+ }
+ else
+ {
+ m_selectedItem = m_trader.m_items[index];
+ }
+ }
+
+ private void UpdateSellButton()
+ {
+ m_sellButton.interactable = GetSellableItem() != null;
+ }
+
+ private ItemDrop.ItemData GetSellableItem()
+ {
+ m_tempItems.Clear();
+ Player.m_localPlayer.GetInventory().GetValuableItems(m_tempItems);
+ foreach (ItemDrop.ItemData tempItem in m_tempItems)
+ {
+ if (tempItem.m_shared.m_name != m_coinPrefab.m_itemData.m_shared.m_name)
+ {
+ return tempItem;
+ }
+ }
+ return null;
+ }
+
+ private int GetSelectedItemIndex()
+ {
+ int result = 0;
+ for (int i = 0; i < m_trader.m_items.Count; i++)
+ {
+ if (m_trader.m_items[i] == m_selectedItem)
+ {
+ result = i;
+ }
+ }
+ return result;
+ }
+
+ private void UpdateBuyButton()
+ {
+ UITooltip component = m_buyButton.GetComponent<UITooltip>();
+ if (m_selectedItem != null)
+ {
+ bool flag = CanAfford(m_selectedItem);
+ bool flag2 = Player.m_localPlayer.GetInventory().HaveEmptySlot();
+ m_buyButton.interactable = flag && flag2;
+ if (!flag)
+ {
+ component.m_text = Localization.instance.Localize("$msg_missingrequirement");
+ }
+ else if (!flag2)
+ {
+ component.m_text = Localization.instance.Localize("$inventory_full");
+ }
+ else
+ {
+ component.m_text = "";
+ }
+ }
+ else
+ {
+ m_buyButton.interactable = false;
+ component.m_text = "";
+ }
+ }
+
+ private void UpdateRecipeGamepadInput()
+ {
+ if (m_itemList.Count > 0)
+ {
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ SelectItem(Mathf.Min(m_itemList.Count - 1, GetSelectedItemIndex() + 1), center: true);
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ SelectItem(Mathf.Max(0, GetSelectedItemIndex() - 1), center: true);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Switch.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Switch.cs
new file mode 100644
index 0000000..9b18b0d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Switch.cs
@@ -0,0 +1,56 @@
+using UnityEngine;
+
+public class Switch : MonoBehaviour, Interactable, Hoverable
+{
+ public delegate bool Callback(Switch caller, Humanoid user, ItemDrop.ItemData item);
+
+ public Callback m_onUse;
+
+ public string m_hoverText = "";
+
+ public string m_name = "";
+
+ public float m_holdRepeatInterval = -1f;
+
+ private float m_lastUseTime;
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ if (m_holdRepeatInterval <= 0f)
+ {
+ return false;
+ }
+ if (Time.time - m_lastUseTime < m_holdRepeatInterval)
+ {
+ return false;
+ }
+ }
+ m_lastUseTime = Time.time;
+ if (m_onUse != null)
+ {
+ return m_onUse(this, character, null);
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ if (m_onUse != null)
+ {
+ return m_onUse(this, user, item);
+ }
+ return false;
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_hoverText);
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tail.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tail.cs
new file mode 100644
index 0000000..ab17b28
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tail.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Tail : MonoBehaviour
+{
+ private class TailSegment
+ {
+ public Transform transform;
+
+ public Vector3 pos;
+
+ public Quaternion rot;
+
+ public float distance;
+ }
+
+ public List<Transform> m_tailJoints = new List<Transform>();
+
+ public float m_yMovementDistance = 0.5f;
+
+ public float m_yMovementFreq = 0.5f;
+
+ public float m_yMovementOffset = 0.2f;
+
+ public float m_maxAngle = 80f;
+
+ public float m_gravity = 2f;
+
+ public float m_gravityInWater = 0.1f;
+
+ public bool m_waterSurfaceCheck;
+
+ public bool m_groundCheck;
+
+ public float m_smoothness = 0.1f;
+
+ public float m_tailRadius;
+
+ public Character m_character;
+
+ public Rigidbody m_characterBody;
+
+ public Rigidbody m_tailBody;
+
+ private List<TailSegment> m_positions = new List<TailSegment>();
+
+ private void Awake()
+ {
+ foreach (Transform tailJoint in m_tailJoints)
+ {
+ float distance = Vector3.Distance(tailJoint.parent.position, tailJoint.position);
+ Vector3 position = tailJoint.position;
+ TailSegment tailSegment = new TailSegment();
+ tailSegment.transform = tailJoint;
+ tailSegment.pos = position;
+ tailSegment.rot = tailJoint.rotation;
+ tailSegment.distance = distance;
+ m_positions.Add(tailSegment);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ float deltaTime = Time.deltaTime;
+ if ((bool)m_character)
+ {
+ m_character.IsSwiming();
+ }
+ for (int i = 0; i < m_positions.Count; i++)
+ {
+ TailSegment tailSegment = m_positions[i];
+ if (m_waterSurfaceCheck)
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(tailSegment.pos);
+ if (tailSegment.pos.y + m_tailRadius > waterLevel)
+ {
+ tailSegment.pos.y -= m_gravity * deltaTime;
+ }
+ else
+ {
+ tailSegment.pos.y -= m_gravityInWater * deltaTime;
+ }
+ }
+ else
+ {
+ tailSegment.pos.y -= m_gravity * deltaTime;
+ }
+ Vector3 vector = tailSegment.transform.parent.position + tailSegment.transform.parent.up * tailSegment.distance * 0.5f;
+ Vector3 vector2 = Vector3.RotateTowards(target: Vector3.Normalize(vector - tailSegment.pos), current: -tailSegment.transform.parent.up, maxRadiansDelta: (float)Math.PI / 180f * m_maxAngle, maxMagnitudeDelta: 1f);
+ Vector3 vector3 = vector - vector2 * tailSegment.distance * 0.5f;
+ if (m_groundCheck)
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(vector3);
+ if (vector3.y - m_tailRadius < groundHeight)
+ {
+ vector3.y = groundHeight + m_tailRadius;
+ }
+ }
+ vector3 = Vector3.Lerp(tailSegment.pos, vector3, m_smoothness);
+ Vector3 normalized = (vector - vector3).normalized;
+ Vector3 rhs = Vector3.Cross(Vector3.up, -normalized);
+ Quaternion b = Quaternion.LookRotation(Vector3.Cross(-normalized, rhs), -normalized);
+ b = Quaternion.Slerp(tailSegment.rot, b, m_smoothness);
+ tailSegment.transform.position = vector3;
+ tailSegment.transform.rotation = b;
+ tailSegment.pos = vector3;
+ tailSegment.rot = b;
+ }
+ if ((bool)m_tailBody)
+ {
+ m_tailBody.velocity = Vector3.zero;
+ m_tailBody.angularVelocity = Vector3.zero;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Talker.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Talker.cs
new file mode 100644
index 0000000..7d1c361
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Talker.cs
@@ -0,0 +1,60 @@
+using UnityEngine;
+
+public class Talker : MonoBehaviour
+{
+ public enum Type
+ {
+ Whisper,
+ Normal,
+ Shout,
+ Ping
+ }
+
+ public float m_visperDistance = 4f;
+
+ public float m_normalDistance = 15f;
+
+ public float m_shoutDistance = 70f;
+
+ private ZNetView m_nview;
+
+ private Character m_character;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_character = GetComponent<Character>();
+ m_nview.Register<int, string, string>("Say", RPC_Say);
+ }
+
+ public void Say(Type type, string text)
+ {
+ ZLog.Log(string.Concat("Saying ", type, " ", text));
+ m_nview.InvokeRPC(ZNetView.Everybody, "Say", (int)type, Game.instance.GetPlayerProfile().GetName(), text);
+ }
+
+ private void RPC_Say(long sender, int ctype, string user, string text)
+ {
+ if (!(Player.m_localPlayer == null))
+ {
+ float num = 0f;
+ switch (ctype)
+ {
+ case 0:
+ num = m_visperDistance;
+ break;
+ case 1:
+ num = m_normalDistance;
+ break;
+ case 2:
+ num = m_shoutDistance;
+ break;
+ }
+ if (Vector3.Distance(base.transform.position, Player.m_localPlayer.transform.position) < num && (bool)Chat.instance)
+ {
+ Vector3 headPoint = m_character.GetHeadPoint();
+ Chat.instance.OnNewChatMessage(base.gameObject, sender, headPoint, (Type)ctype, user, text);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tameable.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tameable.cs
new file mode 100644
index 0000000..3f418c0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tameable.cs
@@ -0,0 +1,239 @@
+using System;
+using UnityEngine;
+
+public class Tameable : MonoBehaviour, Interactable
+{
+ private const float m_playerMaxDistance = 15f;
+
+ private const float m_tameDeltaTime = 3f;
+
+ public float m_fedDuration = 30f;
+
+ public float m_tamingTime = 1800f;
+
+ public EffectList m_tamedEffect = new EffectList();
+
+ public EffectList m_sootheEffect = new EffectList();
+
+ public EffectList m_petEffect = new EffectList();
+
+ public bool m_commandable;
+
+ private Character m_character;
+
+ private MonsterAI m_monsterAI;
+
+ private ZNetView m_nview;
+
+ private float m_lastPetTime;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_character = GetComponent<Character>();
+ m_monsterAI = GetComponent<MonsterAI>();
+ MonsterAI monsterAI = m_monsterAI;
+ monsterAI.m_onConsumedItem = (Action<ItemDrop>)Delegate.Combine(monsterAI.m_onConsumedItem, new Action<ItemDrop>(OnConsumedItem));
+ if (m_nview.IsValid())
+ {
+ m_nview.Register<ZDOID>("Command", RPC_Command);
+ InvokeRepeating("TamingUpdate", 3f, 3f);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ if (!m_nview.IsValid())
+ {
+ return "";
+ }
+ string text = Localization.instance.Localize(m_character.m_name);
+ if (m_character.IsTamed())
+ {
+ text += Localization.instance.Localize(" ( $hud_tame, " + GetStatusString() + " )");
+ return text + Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $hud_pet");
+ }
+ int tameness = GetTameness();
+ if (tameness <= 0)
+ {
+ return text + Localization.instance.Localize(" ( $hud_wild, " + GetStatusString() + " )");
+ }
+ return text + Localization.instance.Localize(" ( $hud_tameness " + tameness + "%, " + GetStatusString() + " )");
+ }
+
+ private string GetStatusString()
+ {
+ if (m_monsterAI.IsAlerted())
+ {
+ return "$hud_tamefrightened";
+ }
+ if (IsHungry())
+ {
+ return "$hud_tamehungry";
+ }
+ if (m_character.IsTamed())
+ {
+ return "$hud_tamehappy";
+ }
+ return "$hud_tameinprogress";
+ }
+
+ public bool Interact(Humanoid user, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ string hoverName = m_character.GetHoverName();
+ if (m_character.IsTamed())
+ {
+ if (Time.time - m_lastPetTime > 1f)
+ {
+ m_lastPetTime = Time.time;
+ m_petEffect.Create(m_character.GetCenterPoint(), Quaternion.identity);
+ if (m_commandable)
+ {
+ Command(user);
+ }
+ else
+ {
+ user.Message(MessageHud.MessageType.Center, hoverName + " $hud_tamelove");
+ }
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void TamingUpdate()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && !m_character.IsTamed() && !IsHungry() && !m_monsterAI.IsAlerted())
+ {
+ DecreaseRemainingTime(3f);
+ if (GetRemainingTime() <= 0f)
+ {
+ Tame();
+ }
+ else
+ {
+ m_sootheEffect.Create(m_character.GetCenterPoint(), Quaternion.identity);
+ }
+ }
+ }
+
+ public void Tame()
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && !m_character.IsTamed())
+ {
+ m_monsterAI.MakeTame();
+ m_tamedEffect.Create(m_character.GetCenterPoint(), Quaternion.identity);
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 30f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.Message(MessageHud.MessageType.Center, m_character.m_name + " $hud_tamedone");
+ }
+ }
+ }
+
+ public static void TameAllInArea(Vector3 point, float radius)
+ {
+ foreach (Character allCharacter in Character.GetAllCharacters())
+ {
+ if (!allCharacter.IsPlayer())
+ {
+ Tameable component = allCharacter.GetComponent<Tameable>();
+ if ((bool)component)
+ {
+ component.Tame();
+ }
+ }
+ }
+ }
+
+ private void Command(Humanoid user)
+ {
+ m_nview.InvokeRPC("Command", user.GetZDOID());
+ }
+
+ private Player GetPlayer(ZDOID characterID)
+ {
+ GameObject gameObject = ZNetScene.instance.FindInstance(characterID);
+ if ((bool)gameObject)
+ {
+ return gameObject.GetComponent<Player>();
+ }
+ return null;
+ }
+
+ private void RPC_Command(long sender, ZDOID characterID)
+ {
+ Player player = GetPlayer(characterID);
+ if (!(player == null))
+ {
+ if ((bool)m_monsterAI.GetFollowTarget())
+ {
+ m_monsterAI.SetFollowTarget(null);
+ m_monsterAI.SetPatrolPoint();
+ player.Message(MessageHud.MessageType.Center, m_character.GetHoverName() + " $hud_tamestay");
+ }
+ else
+ {
+ m_monsterAI.ResetPatrolPoint();
+ m_monsterAI.SetFollowTarget(player.gameObject);
+ player.Message(MessageHud.MessageType.Center, m_character.GetHoverName() + " $hud_tamefollow");
+ }
+ }
+ }
+
+ public bool IsHungry()
+ {
+ DateTime dateTime = new DateTime(m_nview.GetZDO().GetLong("TameLastFeeding", 0L));
+ return (ZNet.instance.GetTime() - dateTime).TotalSeconds > (double)m_fedDuration;
+ }
+
+ private void ResetFeedingTimer()
+ {
+ m_nview.GetZDO().Set("TameLastFeeding", ZNet.instance.GetTime().Ticks);
+ }
+
+ private int GetTameness()
+ {
+ float remainingTime = GetRemainingTime();
+ return (int)((1f - Mathf.Clamp01(remainingTime / m_tamingTime)) * 100f);
+ }
+
+ private void OnConsumedItem(ItemDrop item)
+ {
+ if (IsHungry())
+ {
+ m_sootheEffect.Create(m_character.GetCenterPoint(), Quaternion.identity);
+ }
+ ResetFeedingTimer();
+ }
+
+ private void DecreaseRemainingTime(float time)
+ {
+ float remainingTime = GetRemainingTime();
+ remainingTime -= time;
+ if (remainingTime < 0f)
+ {
+ remainingTime = 0f;
+ }
+ m_nview.GetZDO().Set("TameTimeLeft", remainingTime);
+ }
+
+ private float GetRemainingTime()
+ {
+ return m_nview.GetZDO().GetFloat("TameTimeLeft", m_tamingTime);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Teleport.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Teleport.cs
new file mode 100644
index 0000000..a395fb7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Teleport.cs
@@ -0,0 +1,64 @@
+using UnityEngine;
+
+public class Teleport : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_hoverText = "$location_enter";
+
+ public string m_enterText = "";
+
+ public Teleport m_targetPoint;
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] " + m_hoverText);
+ }
+
+ public string GetHoverName()
+ {
+ return "";
+ }
+
+ private void OnTriggerEnter(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ Interact(component, hold: false);
+ }
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (m_targetPoint == null)
+ {
+ return false;
+ }
+ if (character.TeleportTo(m_targetPoint.GetTeleportPoint(), m_targetPoint.transform.rotation, distantTeleport: false))
+ {
+ if (m_enterText.Length > 0)
+ {
+ MessageHud.instance.ShowBiomeFoundMsg(m_enterText, playStinger: false);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private Vector3 GetTeleportPoint()
+ {
+ return base.transform.position + base.transform.forward - base.transform.up;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void OnDrawGizmos()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportHome.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportHome.cs
new file mode 100644
index 0000000..fc411a3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportHome.cs
@@ -0,0 +1,13 @@
+using UnityEngine;
+
+public class TeleportHome : MonoBehaviour
+{
+ private void OnTriggerEnter(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ Game.instance.RequestRespawn(0f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorld.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorld.cs
new file mode 100644
index 0000000..e5be540
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorld.cs
@@ -0,0 +1,159 @@
+using UnityEngine;
+
+public class TeleportWorld : MonoBehaviour, Hoverable, Interactable, TextReceiver
+{
+ public float m_activationRange = 5f;
+
+ public float m_exitDistance = 1f;
+
+ public Transform m_proximityRoot;
+
+ [ColorUsage(true, true)]
+ public Color m_colorUnconnected = Color.white;
+
+ [ColorUsage(true, true)]
+ public Color m_colorTargetfound = Color.white;
+
+ public EffectFade m_target_found;
+
+ public MeshRenderer m_model;
+
+ public EffectList m_connected;
+
+ private ZNetView m_nview;
+
+ private bool m_hadTarget;
+
+ private float m_colorAlpha;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ return;
+ }
+ m_hadTarget = HaveTarget();
+ m_nview.Register<string>("SetTag", RPC_SetTag);
+ InvokeRepeating("UpdatePortal", 0.5f, 0.5f);
+ }
+
+ public string GetHoverText()
+ {
+ string text = GetText();
+ string text2 = (HaveTarget() ? "$piece_portal_connected" : "$piece_portal_unconnected");
+ return Localization.instance.Localize("$piece_portal $piece_portal_tag:\"" + text + "\" [" + text2 + "]\n[<color=yellow><b>$KEY_Use</b></color>] $piece_portal_settag");
+ }
+
+ public string GetHoverName()
+ {
+ return "Teleport";
+ }
+
+ public bool Interact(Humanoid human, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!PrivateArea.CheckAccess(base.transform.position))
+ {
+ human.Message(MessageHud.MessageType.Center, "$piece_noaccess");
+ return true;
+ }
+ TextInput.instance.RequestText(this, "$piece_portal_tag", 10);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void UpdatePortal()
+ {
+ if (m_nview.IsValid())
+ {
+ Player closestPlayer = Player.GetClosestPlayer(m_proximityRoot.position, m_activationRange);
+ bool flag = HaveTarget();
+ if (flag && !m_hadTarget)
+ {
+ m_connected.Create(base.transform.position, base.transform.rotation);
+ }
+ m_hadTarget = flag;
+ m_target_found.SetActive((bool)closestPlayer && closestPlayer.IsTeleportable() && TargetFound());
+ }
+ }
+
+ private void Update()
+ {
+ m_colorAlpha = Mathf.MoveTowards(m_colorAlpha, m_hadTarget ? 1f : 0f, Time.deltaTime);
+ m_model.material.SetColor("_EmissionColor", Color.Lerp(m_colorUnconnected, m_colorTargetfound, m_colorAlpha));
+ }
+
+ public void Teleport(Player player)
+ {
+ if (!TargetFound())
+ {
+ return;
+ }
+ if (!player.IsTeleportable())
+ {
+ player.Message(MessageHud.MessageType.Center, "$msg_noteleport");
+ return;
+ }
+ ZLog.Log("Teleporting " + player.GetPlayerName());
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID("target");
+ if (!(zDOID == ZDOID.None))
+ {
+ ZDO zDO = ZDOMan.instance.GetZDO(zDOID);
+ Vector3 position = zDO.GetPosition();
+ Quaternion rotation = zDO.GetRotation();
+ Vector3 vector = rotation * Vector3.forward;
+ Vector3 pos = position + vector * m_exitDistance + Vector3.up;
+ player.TeleportTo(pos, rotation, distantTeleport: true);
+ }
+ }
+
+ public string GetText()
+ {
+ return m_nview.GetZDO().GetString("tag");
+ }
+
+ public void SetText(string text)
+ {
+ if (m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("SetTag", text);
+ }
+ }
+
+ private void RPC_SetTag(long sender, string tag)
+ {
+ if (m_nview.IsValid() && m_nview.IsOwner() && !(GetText() == tag))
+ {
+ m_nview.GetZDO().Set("tag", tag);
+ }
+ }
+
+ private bool HaveTarget()
+ {
+ return m_nview.GetZDO().GetZDOID("target") != ZDOID.None;
+ }
+
+ private bool TargetFound()
+ {
+ ZDOID zDOID = m_nview.GetZDO().GetZDOID("target");
+ if (zDOID == ZDOID.None)
+ {
+ return false;
+ }
+ if (ZDOMan.instance.GetZDO(zDOID) == null)
+ {
+ ZDOMan.instance.RequestZDO(zDOID);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs
new file mode 100644
index 0000000..97f28a7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs
@@ -0,0 +1,21 @@
+using UnityEngine;
+
+public class TeleportWorldTrigger : MonoBehaviour
+{
+ private TeleportWorld m_tp;
+
+ private void Awake()
+ {
+ m_tp = GetComponentInParent<TeleportWorld>();
+ }
+
+ private void OnTriggerEnter(Collider collider)
+ {
+ Player component = collider.GetComponent<Player>();
+ if (!(component == null) && !(Player.m_localPlayer != component))
+ {
+ ZLog.Log("TRIGGER");
+ m_tp.Teleport(component);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainLod.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainLod.cs
new file mode 100644
index 0000000..99402d7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainLod.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+
+public class TerrainLod : MonoBehaviour
+{
+ public float m_updateStepDistance = 256f;
+
+ private Heightmap m_hmap;
+
+ private Vector3 m_lastPoint = new Vector3(99999f, 0f, 99999f);
+
+ private bool m_needRebuild = true;
+
+ private void Awake()
+ {
+ m_hmap = GetComponent<Heightmap>();
+ }
+
+ private void Update()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (!(mainCamera == null) && ZNet.GetConnectionStatus() == ZNet.ConnectionStatus.Connected)
+ {
+ Vector3 position = mainCamera.transform.position;
+ if (Utils.DistanceXZ(position, m_lastPoint) > m_updateStepDistance)
+ {
+ m_lastPoint = new Vector3(Mathf.Round(position.x / m_hmap.m_scale) * m_hmap.m_scale, 0f, Mathf.Round(position.z / m_hmap.m_scale) * m_hmap.m_scale);
+ m_needRebuild = true;
+ }
+ if (m_needRebuild && HeightmapBuilder.instance.IsTerrainReady(m_lastPoint, m_hmap.m_width, m_hmap.m_scale, m_hmap.m_isDistantLod, WorldGenerator.instance))
+ {
+ base.transform.position = m_lastPoint;
+ m_hmap.Regenerate();
+ m_needRebuild = false;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainModifier.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainModifier.cs
new file mode 100644
index 0000000..9804830
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TerrainModifier.cs
@@ -0,0 +1,246 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[ExecuteInEditMode]
+public class TerrainModifier : MonoBehaviour
+{
+ public enum PaintType
+ {
+ Dirt,
+ Cultivate,
+ Paved,
+ Reset
+ }
+
+ private static bool m_triggerOnPlaced = false;
+
+ public int m_sortOrder;
+
+ public bool m_playerModifiction;
+
+ public float m_levelOffset;
+
+ [Header("Level")]
+ public bool m_level;
+
+ public float m_levelRadius = 2f;
+
+ public bool m_square = true;
+
+ [Header("Smooth")]
+ public bool m_smooth;
+
+ public float m_smoothRadius = 2f;
+
+ public float m_smoothPower = 3f;
+
+ [Header("Paint")]
+ public bool m_paintCleared = true;
+
+ public bool m_paintHeightCheck;
+
+ public PaintType m_paintType;
+
+ public float m_paintRadius = 2f;
+
+ [Header("Effects")]
+ public EffectList m_onPlacedEffect = new EffectList();
+
+ [Header("Spawn items")]
+ public GameObject m_spawnOnPlaced;
+
+ public float m_chanceToSpawn = 1f;
+
+ public int m_maxSpawned = 1;
+
+ public bool m_spawnAtMaxLevelDepth = true;
+
+ private bool m_wasEnabled;
+
+ private ZNetView m_nview;
+
+ private static List<TerrainModifier> m_instances = new List<TerrainModifier>();
+
+ private static bool m_needsSorting = false;
+
+ private void Awake()
+ {
+ m_instances.Add(this);
+ m_needsSorting = true;
+ m_nview = GetComponent<ZNetView>();
+ m_wasEnabled = base.enabled;
+ if (base.enabled)
+ {
+ if (m_triggerOnPlaced)
+ {
+ OnPlaced();
+ }
+ PokeHeightmaps();
+ }
+ }
+
+ private void OnDestroy()
+ {
+ m_instances.Remove(this);
+ m_needsSorting = true;
+ if (m_wasEnabled)
+ {
+ PokeHeightmaps();
+ }
+ }
+
+ private void PokeHeightmaps()
+ {
+ bool delayed = !m_triggerOnPlaced;
+ foreach (Heightmap allHeightmap in Heightmap.GetAllHeightmaps())
+ {
+ if (allHeightmap.TerrainVSModifier(this))
+ {
+ allHeightmap.Poke(delayed);
+ }
+ }
+ if ((bool)ClutterSystem.instance)
+ {
+ ClutterSystem.instance.ResetGrass(base.transform.position, GetRadius());
+ }
+ }
+
+ public float GetRadius()
+ {
+ float num = 0f;
+ if (m_level && m_levelRadius > num)
+ {
+ num = m_levelRadius;
+ }
+ if (m_smooth && m_smoothRadius > num)
+ {
+ num = m_smoothRadius;
+ }
+ if (m_paintCleared && m_paintRadius > num)
+ {
+ num = m_paintRadius;
+ }
+ return num;
+ }
+
+ public static void SetTriggerOnPlaced(bool trigger)
+ {
+ m_triggerOnPlaced = trigger;
+ }
+
+ private void OnPlaced()
+ {
+ RemoveOthers(base.transform.position, GetRadius() / 4f);
+ m_onPlacedEffect.Create(base.transform.position, Quaternion.identity);
+ if ((bool)m_spawnOnPlaced && (m_spawnAtMaxLevelDepth || !Heightmap.AtMaxLevelDepth(base.transform.position + Vector3.up * m_levelOffset)) && Random.value <= m_chanceToSpawn)
+ {
+ Vector3 vector = Random.insideUnitCircle * 0.2f;
+ GameObject obj = Object.Instantiate(m_spawnOnPlaced, base.transform.position + Vector3.up * 0.5f + vector, Quaternion.identity);
+ obj.GetComponent<ItemDrop>().m_itemData.m_stack = Random.Range(1, m_maxSpawned + 1);
+ obj.GetComponent<Rigidbody>().velocity = Vector3.up * 4f;
+ }
+ }
+
+ private static void GetModifiers(Vector3 point, float range, List<TerrainModifier> modifiers, TerrainModifier ignore = null)
+ {
+ foreach (TerrainModifier instance in m_instances)
+ {
+ if (!(instance == ignore) && Utils.DistanceXZ(point, instance.transform.position) < range)
+ {
+ modifiers.Add(instance);
+ }
+ }
+ }
+
+ public static Piece FindClosestModifierPieceInRange(Vector3 point, float range)
+ {
+ float num = 999999f;
+ TerrainModifier terrainModifier = null;
+ foreach (TerrainModifier instance in m_instances)
+ {
+ if (!(instance.m_nview == null))
+ {
+ float num2 = Utils.DistanceXZ(point, instance.transform.position);
+ if (!(num2 > range) && !(num2 > num))
+ {
+ num = num2;
+ terrainModifier = instance;
+ }
+ }
+ }
+ if ((bool)terrainModifier)
+ {
+ return terrainModifier.GetComponent<Piece>();
+ }
+ return null;
+ }
+
+ private void RemoveOthers(Vector3 point, float range)
+ {
+ List<TerrainModifier> list = new List<TerrainModifier>();
+ GetModifiers(point, range, list, this);
+ int num = 0;
+ foreach (TerrainModifier item in list)
+ {
+ if ((m_level || !item.m_level) && (!m_paintCleared || m_paintType != PaintType.Reset || (item.m_paintCleared && item.m_paintType == PaintType.Reset)) && (bool)item.m_nview)
+ {
+ num++;
+ item.m_nview.ClaimOwnership();
+ item.m_nview.Destroy();
+ }
+ }
+ }
+
+ private static int SortByModifiers(TerrainModifier a, TerrainModifier b)
+ {
+ if (a.m_playerModifiction == b.m_playerModifiction)
+ {
+ if (a.m_sortOrder == b.m_sortOrder)
+ {
+ return a.GetCreationTime().CompareTo(b.GetCreationTime());
+ }
+ return a.m_sortOrder.CompareTo(b.m_sortOrder);
+ }
+ return a.m_playerModifiction.CompareTo(b.m_playerModifiction);
+ }
+
+ public static List<TerrainModifier> GetAllInstances()
+ {
+ if (m_needsSorting)
+ {
+ m_instances.Sort(SortByModifiers);
+ m_needsSorting = false;
+ }
+ return m_instances;
+ }
+
+ private void OnDrawGizmosSelected()
+ {
+ Gizmos.matrix = Matrix4x4.TRS(base.transform.position + Vector3.up * m_levelOffset, Quaternion.identity, new Vector3(1f, 0f, 1f));
+ if (m_level)
+ {
+ Gizmos.color = Color.green;
+ Gizmos.DrawWireSphere(Vector3.zero, m_levelRadius);
+ }
+ if (m_smooth)
+ {
+ Gizmos.color = Color.blue;
+ Gizmos.DrawWireSphere(Vector3.zero, m_smoothRadius);
+ }
+ if (m_paintCleared)
+ {
+ Gizmos.color = Color.yellow;
+ Gizmos.DrawWireSphere(Vector3.zero, m_paintRadius);
+ }
+ Gizmos.matrix = Matrix4x4.identity;
+ }
+
+ public long GetCreationTime()
+ {
+ if ((bool)m_nview && m_nview.GetZDO() != null)
+ {
+ return m_nview.GetZDO().m_timeCreated;
+ }
+ return 0L;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestCollision.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestCollision.cs
new file mode 100644
index 0000000..29ca07f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestCollision.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+public class TestCollision : MonoBehaviour
+{
+ private void Start()
+ {
+ }
+
+ private void Update()
+ {
+ }
+
+ public void OnCollisionEnter(Collision info)
+ {
+ ZLog.Log("Hit by " + info.rigidbody.gameObject.name);
+ ZLog.Log(string.Concat("rel vel ", info.relativeVelocity, " ", info.relativeVelocity));
+ ZLog.Log(string.Concat("Vel ", info.rigidbody.velocity, " ", info.rigidbody.angularVelocity));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneCharacter.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneCharacter.cs
new file mode 100644
index 0000000..95f1742
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneCharacter.cs
@@ -0,0 +1,82 @@
+using System.Threading;
+using UnityEngine;
+
+public class TestSceneCharacter : MonoBehaviour
+{
+ public float m_speed = 5f;
+
+ public float m_cameraDistance = 10f;
+
+ private Rigidbody m_body;
+
+ private Quaternion m_lookYaw = Quaternion.identity;
+
+ private float m_lookPitch;
+
+ private void Start()
+ {
+ m_body = GetComponent<Rigidbody>();
+ }
+
+ private void Update()
+ {
+ Thread.Sleep(30);
+ HandleInput(Time.deltaTime);
+ }
+
+ private void HandleInput(float dt)
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (mainCamera == null)
+ {
+ return;
+ }
+ Vector2 zero = Vector2.zero;
+ zero.x = Input.GetAxis("Mouse X");
+ zero.y = Input.GetAxis("Mouse Y");
+ if (Input.GetKey(KeyCode.Mouse1) || Cursor.lockState != 0)
+ {
+ m_lookYaw *= Quaternion.Euler(0f, zero.x, 0f);
+ m_lookPitch = Mathf.Clamp(m_lookPitch - zero.y, -89f, 89f);
+ }
+ if (Input.GetKeyDown(KeyCode.F1))
+ {
+ if (Cursor.lockState == CursorLockMode.None)
+ {
+ Cursor.lockState = CursorLockMode.Locked;
+ }
+ else
+ {
+ Cursor.lockState = CursorLockMode.None;
+ }
+ }
+ Vector3 zero2 = Vector3.zero;
+ if (Input.GetKey(KeyCode.A))
+ {
+ zero2 -= base.transform.right * m_speed;
+ }
+ if (Input.GetKey(KeyCode.D))
+ {
+ zero2 += base.transform.right * m_speed;
+ }
+ if (Input.GetKey(KeyCode.W))
+ {
+ zero2 += base.transform.forward * m_speed;
+ }
+ if (Input.GetKey(KeyCode.S))
+ {
+ zero2 -= base.transform.forward * m_speed;
+ }
+ if (Input.GetKeyDown(KeyCode.Space))
+ {
+ m_body.AddForce(Vector3.up * 10f, ForceMode.VelocityChange);
+ }
+ Vector3 force = zero2 - m_body.velocity;
+ force.y = 0f;
+ m_body.AddForce(force, ForceMode.VelocityChange);
+ base.transform.rotation = m_lookYaw;
+ Quaternion quaternion = m_lookYaw * Quaternion.Euler(m_lookPitch, 0f, 0f);
+ mainCamera.transform.position = base.transform.position - quaternion * Vector3.forward * m_cameraDistance;
+ mainCamera.transform.LookAt(base.transform.position + Vector3.up);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneSetup.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneSetup.cs
new file mode 100644
index 0000000..e8cc282
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TestSceneSetup.cs
@@ -0,0 +1,13 @@
+using UnityEngine;
+
+public class TestSceneSetup : MonoBehaviour
+{
+ private void Awake()
+ {
+ WorldGenerator.Initialize(World.GetMenuWorld());
+ }
+
+ private void Update()
+ {
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextInput.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextInput.cs
new file mode 100644
index 0000000..419d21f
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextInput.cs
@@ -0,0 +1,93 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+public class TextInput : MonoBehaviour
+{
+ private static TextInput m_instance;
+
+ public GameObject m_panel;
+
+ public InputField m_textField;
+
+ public Text m_topic;
+
+ private TextReceiver m_queuedSign;
+
+ private bool m_visibleFrame;
+
+ public static TextInput instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_panel.SetActive(value: false);
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ public static bool IsVisible()
+ {
+ if ((bool)m_instance)
+ {
+ return m_instance.m_visibleFrame;
+ }
+ return false;
+ }
+
+ private void Update()
+ {
+ m_visibleFrame = m_instance.m_panel.gameObject.activeSelf;
+ if (!m_visibleFrame || Console.IsVisible() || Chat.instance.HasFocus())
+ {
+ return;
+ }
+ if (Input.GetKeyDown(KeyCode.Escape))
+ {
+ Hide();
+ return;
+ }
+ if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
+ {
+ string text = m_textField.text;
+ OnEnter(text);
+ Hide();
+ }
+ if (!m_textField.isFocused)
+ {
+ EventSystem.current.SetSelectedGameObject(m_textField.gameObject);
+ }
+ }
+
+ private void OnEnter(string text)
+ {
+ if (m_queuedSign != null)
+ {
+ m_queuedSign.SetText(text);
+ m_queuedSign = null;
+ }
+ }
+
+ public void RequestText(TextReceiver sign, string topic, int charLimit)
+ {
+ m_queuedSign = sign;
+ Show(topic, sign.GetText(), charLimit);
+ }
+
+ private void Show(string topic, string text, int charLimit)
+ {
+ m_panel.SetActive(value: true);
+ m_textField.text = text;
+ m_topic.text = Localization.instance.Localize(topic);
+ m_textField.ActivateInputField();
+ m_textField.characterLimit = charLimit;
+ }
+
+ public void Hide()
+ {
+ m_panel.SetActive(value: false);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextReceiver.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextReceiver.cs
new file mode 100644
index 0000000..33507c5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextReceiver.cs
@@ -0,0 +1,6 @@
+public interface TextReceiver
+{
+ string GetText();
+
+ void SetText(string text);
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextViewer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextViewer.cs
new file mode 100644
index 0000000..9e41172
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextViewer.cs
@@ -0,0 +1,155 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TextViewer : MonoBehaviour
+{
+ public enum Style
+ {
+ Rune,
+ Intro,
+ Raven
+ }
+
+ private static TextViewer m_instance;
+
+ private Animator m_animator;
+
+ private Animator m_animatorIntro;
+
+ private Animator m_animatorRaven;
+
+ [Header("Rune")]
+ public GameObject m_root;
+
+ public Text m_topic;
+
+ public Text m_text;
+
+ public Text m_runeText;
+
+ public GameObject m_closeText;
+
+ [Header("Intro")]
+ public GameObject m_introRoot;
+
+ public Text m_introTopic;
+
+ public Text m_introText;
+
+ [Header("Raven")]
+ public GameObject m_ravenRoot;
+
+ public Text m_ravenTopic;
+
+ public Text m_ravenText;
+
+ private static int m_visibleID = Animator.StringToHash("visible");
+
+ private static int m_animatorTagVisible = Animator.StringToHash("visible");
+
+ private float m_showTime;
+
+ private bool m_autoHide;
+
+ private Vector3 m_openPlayerPos = Vector3.zero;
+
+ public static TextViewer instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_root.SetActive(value: true);
+ m_introRoot.SetActive(value: true);
+ m_ravenRoot.SetActive(value: true);
+ m_animator = m_root.GetComponent<Animator>();
+ m_animatorIntro = m_introRoot.GetComponent<Animator>();
+ m_animatorRaven = m_ravenRoot.GetComponent<Animator>();
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void LateUpdate()
+ {
+ if (!IsVisible())
+ {
+ return;
+ }
+ m_showTime += Time.deltaTime;
+ if (m_showTime > 0.2f)
+ {
+ if (m_autoHide && (bool)Player.m_localPlayer && Vector3.Distance(Player.m_localPlayer.transform.position, m_openPlayerPos) > 3f)
+ {
+ Hide();
+ }
+ if (ZInput.GetButtonDown("Use") || ZInput.GetButtonDown("JoyUse") || Input.GetKeyDown(KeyCode.Escape))
+ {
+ Hide();
+ }
+ }
+ }
+
+ public void ShowText(Style style, string topic, string text, bool autoHide)
+ {
+ if (!(Player.m_localPlayer == null))
+ {
+ topic = Localization.instance.Localize(topic);
+ text = Localization.instance.Localize(text);
+ switch (style)
+ {
+ case Style.Rune:
+ m_topic.text = topic;
+ m_text.text = text;
+ m_runeText.text = text;
+ m_animator.SetBool(m_visibleID, value: true);
+ break;
+ case Style.Intro:
+ m_introTopic.text = topic;
+ m_introText.text = text;
+ m_animatorIntro.SetTrigger("play");
+ ZLog.Log("Show intro " + Time.frameCount);
+ break;
+ case Style.Raven:
+ m_ravenTopic.text = topic;
+ m_ravenText.text = text;
+ m_animatorRaven.SetBool(m_visibleID, value: true);
+ break;
+ }
+ m_autoHide = autoHide;
+ m_openPlayerPos = Player.m_localPlayer.transform.position;
+ m_showTime = 0f;
+ ZLog.Log("Show text " + topic + ":" + text);
+ }
+ }
+
+ public void Hide()
+ {
+ m_autoHide = false;
+ m_animator.SetBool(m_visibleID, value: false);
+ m_animatorRaven.SetBool(m_visibleID, value: false);
+ }
+
+ public bool IsVisible()
+ {
+ if (m_instance.m_animatorIntro.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagVisible)
+ {
+ return true;
+ }
+ if (!m_animator.GetBool(m_visibleID) && !m_animatorIntro.GetBool(m_visibleID))
+ {
+ return m_animatorRaven.GetBool(m_visibleID);
+ }
+ return true;
+ }
+
+ public static bool IsShowingIntro()
+ {
+ if (m_instance != null)
+ {
+ return m_instance.m_animatorIntro.GetCurrentAnimatorStateInfo(0).tagHash == m_animatorTagVisible;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextsDialog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextsDialog.cs
new file mode 100644
index 0000000..da3a792
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TextsDialog.cs
@@ -0,0 +1,196 @@
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TextsDialog : MonoBehaviour
+{
+ public class TextInfo
+ {
+ public string m_topic;
+
+ public string m_text;
+
+ public GameObject m_listElement;
+
+ public GameObject m_selected;
+
+ public TextInfo(string topic, string text)
+ {
+ m_topic = topic;
+ m_text = text;
+ }
+ }
+
+ public RectTransform m_listRoot;
+
+ public GameObject m_elementPrefab;
+
+ public Text m_totalSkillText;
+
+ public float m_spacing = 80f;
+
+ public Text m_textAreaTopic;
+
+ public Text m_textArea;
+
+ public ScrollRectEnsureVisible m_recipeEnsureVisible;
+
+ private List<TextInfo> m_texts = new List<TextInfo>();
+
+ private float m_baseListSize;
+
+ private void Awake()
+ {
+ m_baseListSize = m_listRoot.rect.height;
+ }
+
+ public void Setup(Player player)
+ {
+ base.gameObject.SetActive(value: true);
+ FillTextList();
+ if (m_texts.Count > 0)
+ {
+ ShowText(m_texts[0]);
+ return;
+ }
+ m_textAreaTopic.text = "";
+ m_textArea.text = "";
+ }
+
+ private void Update()
+ {
+ UpdateGamepadInput();
+ }
+
+ private void FillTextList()
+ {
+ foreach (TextInfo text2 in m_texts)
+ {
+ Object.Destroy(text2.m_listElement);
+ }
+ m_texts.Clear();
+ UpdateTextsList();
+ for (int i = 0; i < m_texts.Count; i++)
+ {
+ TextInfo text = m_texts[i];
+ GameObject gameObject = Object.Instantiate(m_elementPrefab, Vector3.zero, Quaternion.identity, m_listRoot);
+ gameObject.SetActive(value: true);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2(0f, (float)(-i) * m_spacing);
+ Utils.FindChild(gameObject.transform, "name").GetComponent<Text>().text = Localization.instance.Localize(text.m_topic);
+ text.m_listElement = gameObject;
+ text.m_selected = Utils.FindChild(gameObject.transform, "selected").gameObject;
+ text.m_selected.SetActive(value: false);
+ gameObject.GetComponent<Button>().onClick.AddListener(delegate
+ {
+ OnSelectText(text);
+ });
+ }
+ float size = Mathf.Max(m_baseListSize, (float)m_texts.Count * m_spacing);
+ m_listRoot.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size);
+ if (m_texts.Count > 0)
+ {
+ m_recipeEnsureVisible.CenterOnItem(m_texts[0].m_listElement.transform as RectTransform);
+ }
+ }
+
+ private void UpdateGamepadInput()
+ {
+ if (m_texts.Count > 0)
+ {
+ if (ZInput.GetButtonDown("JoyLStickDown"))
+ {
+ ShowText(Mathf.Min(m_texts.Count - 1, GetSelectedText() + 1));
+ }
+ if (ZInput.GetButtonDown("JoyLStickUp"))
+ {
+ ShowText(Mathf.Max(0, GetSelectedText() - 1));
+ }
+ }
+ }
+
+ private void OnSelectText(TextInfo text)
+ {
+ ShowText(text);
+ }
+
+ private int GetSelectedText()
+ {
+ for (int i = 0; i < m_texts.Count; i++)
+ {
+ if (m_texts[i].m_selected.activeSelf)
+ {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private void ShowText(int i)
+ {
+ ShowText(m_texts[i]);
+ }
+
+ private void ShowText(TextInfo text)
+ {
+ m_textAreaTopic.text = Localization.instance.Localize(text.m_topic);
+ m_textArea.text = Localization.instance.Localize(text.m_text);
+ foreach (TextInfo text2 in m_texts)
+ {
+ text2.m_selected.SetActive(value: false);
+ }
+ text.m_selected.SetActive(value: true);
+ }
+
+ public void OnClose()
+ {
+ base.gameObject.SetActive(value: false);
+ }
+
+ private void UpdateTextsList()
+ {
+ m_texts.Clear();
+ foreach (KeyValuePair<string, string> knownText in Player.m_localPlayer.GetKnownTexts())
+ {
+ m_texts.Add(new TextInfo(Localization.instance.Localize(knownText.Key), Localization.instance.Localize(knownText.Value)));
+ }
+ m_texts.Sort((TextInfo a, TextInfo b) => a.m_topic.CompareTo(b.m_topic));
+ AddLog();
+ AddActiveEffects();
+ }
+
+ private void AddLog()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ foreach (string item in MessageHud.instance.GetLog())
+ {
+ stringBuilder.Append(item + "\n\n");
+ }
+ m_texts.Insert(0, new TextInfo(Localization.instance.Localize("$inventory_logs"), stringBuilder.ToString()));
+ }
+
+ private void AddActiveEffects()
+ {
+ if (!Player.m_localPlayer)
+ {
+ return;
+ }
+ List<StatusEffect> list = new List<StatusEffect>();
+ Player.m_localPlayer.GetSEMan().GetHUDStatusEffects(list);
+ StringBuilder stringBuilder = new StringBuilder(256);
+ foreach (StatusEffect item in list)
+ {
+ stringBuilder.Append("<color=orange>" + Localization.instance.Localize(item.m_name) + "</color>\n");
+ stringBuilder.Append(Localization.instance.Localize(item.GetTooltipString()));
+ stringBuilder.Append("\n\n");
+ }
+ Player.m_localPlayer.GetGuardianPowerHUD(out var se, out var _);
+ if ((bool)se)
+ {
+ stringBuilder.Append("<color=yellow>" + Localization.instance.Localize("$inventory_selectedgp") + "</color>\n");
+ stringBuilder.Append("<color=orange>" + Localization.instance.Localize(se.m_name) + "</color>\n");
+ stringBuilder.Append(Localization.instance.Localize(se.GetTooltipString()));
+ }
+ m_texts.Insert(0, new TextInfo(Localization.instance.Localize("$inventory_activeeffects"), stringBuilder.ToString()));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ThorFly.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ThorFly.cs
new file mode 100644
index 0000000..a24de60
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ThorFly.cs
@@ -0,0 +1,24 @@
+using UnityEngine;
+
+public class ThorFly : MonoBehaviour
+{
+ public float m_speed = 100f;
+
+ public float m_ttl = 10f;
+
+ private float m_timer;
+
+ private void Start()
+ {
+ }
+
+ private void Update()
+ {
+ base.transform.position = base.transform.position + base.transform.forward * m_speed * Time.deltaTime;
+ m_timer += Time.deltaTime;
+ if (m_timer > m_ttl)
+ {
+ Object.Destroy(base.gameObject);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Thunder.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Thunder.cs
new file mode 100644
index 0000000..6b7198e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Thunder.cs
@@ -0,0 +1,133 @@
+using System;
+using UnityEngine;
+
+public class Thunder : MonoBehaviour
+{
+ public float m_strikeIntervalMin = 3f;
+
+ public float m_strikeIntervalMax = 10f;
+
+ public float m_thunderDelayMin = 3f;
+
+ public float m_thunderDelayMax = 5f;
+
+ public float m_flashDistanceMin = 50f;
+
+ public float m_flashDistanceMax = 200f;
+
+ public float m_flashAltitude = 100f;
+
+ public EffectList m_flashEffect = new EffectList();
+
+ public EffectList m_thunderEffect = new EffectList();
+
+ [Header("Thor")]
+ public bool m_spawnThor;
+
+ public string m_requiredGlobalKey = "";
+
+ public GameObject m_thorPrefab;
+
+ public float m_thorSpawnDistance = 300f;
+
+ public float m_thorSpawnAltitudeMax = 100f;
+
+ public float m_thorSpawnAltitudeMin = 100f;
+
+ public float m_thorInterval = 10f;
+
+ public float m_thorChance = 1f;
+
+ private Vector3 m_flashPos = Vector3.zero;
+
+ private float m_strikeTimer = -1f;
+
+ private float m_thunderTimer = -1f;
+
+ private float m_thorTimer;
+
+ private void Start()
+ {
+ m_strikeTimer = UnityEngine.Random.Range(m_strikeIntervalMin, m_strikeIntervalMax);
+ }
+
+ private void Update()
+ {
+ if (m_strikeTimer > 0f)
+ {
+ m_strikeTimer -= Time.deltaTime;
+ if (m_strikeTimer <= 0f)
+ {
+ DoFlash();
+ }
+ }
+ if (m_thunderTimer > 0f)
+ {
+ m_thunderTimer -= Time.deltaTime;
+ if (m_thunderTimer <= 0f)
+ {
+ DoThunder();
+ m_strikeTimer = UnityEngine.Random.Range(m_strikeIntervalMin, m_strikeIntervalMax);
+ }
+ }
+ if (!m_spawnThor)
+ {
+ return;
+ }
+ m_thorTimer += Time.deltaTime;
+ if (m_thorTimer > m_thorInterval)
+ {
+ m_thorTimer = 0f;
+ if (UnityEngine.Random.value <= m_thorChance && (m_requiredGlobalKey == "" || ZoneSystem.instance.GetGlobalKey(m_requiredGlobalKey)))
+ {
+ SpawnThor();
+ }
+ }
+ }
+
+ private void SpawnThor()
+ {
+ float num = UnityEngine.Random.value * ((float)Math.PI * 2f);
+ Vector3 vector = base.transform.position + new Vector3(Mathf.Sin(num), 0f, Mathf.Cos(num)) * m_thorSpawnDistance;
+ vector.y += UnityEngine.Random.Range(m_thorSpawnAltitudeMin, m_thorSpawnAltitudeMax);
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(vector);
+ if (vector.y < groundHeight)
+ {
+ vector.y = groundHeight + 50f;
+ }
+ float f = num + 180f + (float)UnityEngine.Random.Range(-45, 45);
+ Vector3 vector2 = base.transform.position + new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f)) * m_thorSpawnDistance;
+ vector2.y += UnityEngine.Random.Range(m_thorSpawnAltitudeMin, m_thorSpawnAltitudeMax);
+ float groundHeight2 = ZoneSystem.instance.GetGroundHeight(vector2);
+ if (vector.y < groundHeight2)
+ {
+ vector.y = groundHeight2 + 50f;
+ }
+ Vector3 normalized = (vector2 - vector).normalized;
+ UnityEngine.Object.Instantiate(m_thorPrefab, vector, Quaternion.LookRotation(normalized));
+ }
+
+ private void DoFlash()
+ {
+ float f = UnityEngine.Random.value * ((float)Math.PI * 2f);
+ float num = UnityEngine.Random.Range(m_flashDistanceMin, m_flashDistanceMax);
+ m_flashPos = base.transform.position + new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f)) * num;
+ m_flashPos.y += m_flashAltitude;
+ Quaternion rotation = Quaternion.LookRotation((base.transform.position - m_flashPos).normalized);
+ GameObject[] array = m_flashEffect.Create(m_flashPos, Quaternion.identity);
+ for (int i = 0; i < array.Length; i++)
+ {
+ Light[] componentsInChildren = array[i].GetComponentsInChildren<Light>();
+ for (int j = 0; j < componentsInChildren.Length; j++)
+ {
+ componentsInChildren[j].transform.rotation = rotation;
+ }
+ }
+ m_thunderTimer = UnityEngine.Random.Range(m_thunderDelayMin, m_thunderDelayMax);
+ }
+
+ private void DoThunder()
+ {
+ m_thunderEffect.Create(m_flashPos, Quaternion.identity);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TimedDestruction.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TimedDestruction.cs
new file mode 100644
index 0000000..55f4e73
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TimedDestruction.cs
@@ -0,0 +1,51 @@
+using UnityEngine;
+
+public class TimedDestruction : MonoBehaviour
+{
+ public float m_timeout = 1f;
+
+ public bool m_triggerOnAwake;
+
+ private ZNetView m_nview;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_triggerOnAwake)
+ {
+ Trigger();
+ }
+ }
+
+ public void Trigger()
+ {
+ Invoke("DestroyNow", m_timeout);
+ }
+
+ public void Trigger(float timeout)
+ {
+ Invoke("DestroyNow", timeout);
+ }
+
+ private void DestroyNow()
+ {
+ if ((bool)m_nview)
+ {
+ if (m_nview.IsValid())
+ {
+ if (m_nview.GetZDO().m_owner == 0L)
+ {
+ m_nview.ClaimOwnership();
+ }
+ if (m_nview.IsOwner())
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+ }
+ }
+ else
+ {
+ Object.Destroy(base.gameObject);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleImage.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleImage.cs
new file mode 100644
index 0000000..6c0f5c6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleImage.cs
@@ -0,0 +1,30 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ToggleImage : MonoBehaviour
+{
+ private Toggle m_toggle;
+
+ public Image m_targetImage;
+
+ public Sprite m_onImage;
+
+ public Sprite m_offImage;
+
+ private void Awake()
+ {
+ m_toggle = GetComponent<Toggle>();
+ }
+
+ private void Update()
+ {
+ if (m_toggle.isOn)
+ {
+ m_targetImage.sprite = m_onImage;
+ }
+ else
+ {
+ m_targetImage.sprite = m_offImage;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleSwitch.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleSwitch.cs
new file mode 100644
index 0000000..bc0f4aa
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ToggleSwitch.cs
@@ -0,0 +1,53 @@
+using System;
+using UnityEngine;
+
+public class ToggleSwitch : MonoBehaviour, Interactable, Hoverable
+{
+ public MeshRenderer m_renderer;
+
+ public Material m_enableMaterial;
+
+ public Material m_disableMaterial;
+
+ public Action<ToggleSwitch, Humanoid> m_onUse;
+
+ public string m_hoverText = "";
+
+ public string m_name = "";
+
+ private bool m_state;
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (m_onUse != null)
+ {
+ m_onUse(this, character);
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public string GetHoverText()
+ {
+ return m_hoverText;
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public void SetState(bool enabled)
+ {
+ m_state = enabled;
+ m_renderer.material = (m_state ? m_enableMaterial : m_disableMaterial);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TombStone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TombStone.cs
new file mode 100644
index 0000000..dd74763
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TombStone.cs
@@ -0,0 +1,217 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TombStone : MonoBehaviour, Hoverable, Interactable
+{
+ private static float m_updateDt = 2f;
+
+ public string m_text = "$piece_tombstone";
+
+ public GameObject m_floater;
+
+ public Text m_worldText;
+
+ public float m_spawnUpVel = 5f;
+
+ public StatusEffect m_lootStatusEffect;
+
+ public EffectList m_removeEffect = new EffectList();
+
+ private Container m_container;
+
+ private ZNetView m_nview;
+
+ private Floating m_floating;
+
+ private Rigidbody m_body;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_container = GetComponent<Container>();
+ m_floating = GetComponent<Floating>();
+ m_body = GetComponent<Rigidbody>();
+ m_body.maxDepenetrationVelocity = 1f;
+ Container container = m_container;
+ container.m_onTakeAllSuccess = (Action)Delegate.Combine(container.m_onTakeAllSuccess, new Action(OnTakeAllSuccess));
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetLong("timeOfDeath", 0L) == 0L)
+ {
+ m_nview.GetZDO().Set("timeOfDeath", ZNet.instance.GetTime().Ticks);
+ }
+ InvokeRepeating("UpdateDespawn", m_updateDt, m_updateDt);
+ }
+
+ private void Start()
+ {
+ string @string = m_nview.GetZDO().GetString("ownerName");
+ GetComponent<Container>().m_name = @string;
+ m_worldText.text = @string;
+ }
+
+ public string GetHoverText()
+ {
+ if (!m_nview.IsValid())
+ {
+ return "";
+ }
+ string @string = m_nview.GetZDO().GetString("ownerName");
+ string text = m_text + " " + @string;
+ if (m_container.GetInventory().NrOfItems() == 0)
+ {
+ return "";
+ }
+ return Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open");
+ }
+
+ public string GetHoverName()
+ {
+ return "";
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (m_container.GetInventory().NrOfItems() == 0)
+ {
+ return false;
+ }
+ if (IsOwner())
+ {
+ Player player = character as Player;
+ if (EasyFitInInventory(player))
+ {
+ ZLog.Log("Grave should fit in inventory, loot all");
+ m_container.TakeAll(character);
+ return true;
+ }
+ }
+ return m_container.Interact(character, hold: false);
+ }
+
+ private void OnTakeAllSuccess()
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if ((bool)localPlayer)
+ {
+ localPlayer.m_pickupEffects.Create(localPlayer.transform.position, Quaternion.identity);
+ localPlayer.Message(MessageHud.MessageType.Center, "$piece_tombstone_recovered");
+ }
+ }
+
+ private bool EasyFitInInventory(Player player)
+ {
+ int emptySlots = player.GetInventory().GetEmptySlots();
+ if (m_container.GetInventory().NrOfItems() > emptySlots)
+ {
+ return false;
+ }
+ if (player.GetInventory().GetTotalWeight() + m_container.GetInventory().GetTotalWeight() > player.GetMaxCarryWeight())
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public void Setup(string ownerName, long ownerUID)
+ {
+ m_nview.GetZDO().Set("ownerName", ownerName);
+ m_nview.GetZDO().Set("owner", ownerUID);
+ if ((bool)m_body)
+ {
+ m_body.velocity = new Vector3(0f, m_spawnUpVel, 0f);
+ }
+ }
+
+ public long GetOwner()
+ {
+ if (!m_nview.IsValid())
+ {
+ return 0L;
+ }
+ return m_nview.GetZDO().GetLong("owner", 0L);
+ }
+
+ public bool IsOwner()
+ {
+ long owner = GetOwner();
+ long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
+ return owner == playerID;
+ }
+
+ private void UpdateDespawn()
+ {
+ if (m_floater != null)
+ {
+ UpdateFloater();
+ }
+ if (m_nview.IsOwner())
+ {
+ UnderWorldCheck();
+ if (!m_container.IsInUse() && m_container.GetInventory().NrOfItems() <= 0)
+ {
+ GiveBoost();
+ m_removeEffect.Create(base.transform.position, base.transform.rotation);
+ m_nview.Destroy();
+ }
+ }
+ }
+
+ private void GiveBoost()
+ {
+ if (!(m_lootStatusEffect == null))
+ {
+ Player player = FindOwner();
+ if ((bool)player)
+ {
+ player.GetSEMan().AddStatusEffect(m_lootStatusEffect, resetTime: true);
+ }
+ }
+ }
+
+ private Player FindOwner()
+ {
+ long owner = GetOwner();
+ if (owner == 0L)
+ {
+ return null;
+ }
+ return Player.GetPlayer(owner);
+ }
+
+ private void UnderWorldCheck()
+ {
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ if (base.transform.position.y < groundHeight - 1f)
+ {
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + 0.5f;
+ base.transform.position = position;
+ m_body.position = position;
+ m_body.velocity = Vector3.zero;
+ }
+ }
+
+ private void UpdateFloater()
+ {
+ if (m_nview.IsOwner())
+ {
+ bool flag = m_floating.BeenInWater();
+ m_nview.GetZDO().Set("inWater", flag);
+ m_floater.SetActive(flag);
+ }
+ else
+ {
+ bool @bool = m_nview.GetZDO().GetBool("inWater");
+ m_floater.SetActive(@bool);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tracker.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tracker.cs
new file mode 100644
index 0000000..f9aaed8
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tracker.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+
+public class Tracker : MonoBehaviour
+{
+ private bool m_active;
+
+ private void Awake()
+ {
+ ZNetView component = GetComponent<ZNetView>();
+ if ((bool)component && component.IsOwner())
+ {
+ m_active = true;
+ ZNet.instance.SetReferencePosition(base.transform.position);
+ }
+ }
+
+ public void SetActive(bool active)
+ {
+ m_active = active;
+ }
+
+ private void OnDestroy()
+ {
+ m_active = false;
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_active)
+ {
+ ZNet.instance.SetReferencePosition(base.transform.position);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Trader.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Trader.cs
new file mode 100644
index 0000000..cb5289e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Trader.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Trader : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public class TradeItem
+ {
+ public ItemDrop m_prefab;
+
+ public int m_stack = 1;
+
+ public int m_price = 100;
+ }
+
+ public string m_name = "Haldor";
+
+ public float m_standRange = 15f;
+
+ public float m_greetRange = 5f;
+
+ public float m_byeRange = 5f;
+
+ public List<TradeItem> m_items = new List<TradeItem>();
+
+ [Header("Dialog")]
+ public float m_hideDialogDelay = 5f;
+
+ public float m_randomTalkInterval = 30f;
+
+ public List<string> m_randomTalk = new List<string>();
+
+ public List<string> m_randomGreets = new List<string>();
+
+ public List<string> m_randomGoodbye = new List<string>();
+
+ public List<string> m_randomStartTrade = new List<string>();
+
+ public List<string> m_randomBuy = new List<string>();
+
+ public List<string> m_randomSell = new List<string>();
+
+ public EffectList m_randomTalkFX = new EffectList();
+
+ public EffectList m_randomGreetFX = new EffectList();
+
+ public EffectList m_randomGoodbyeFX = new EffectList();
+
+ public EffectList m_randomStartTradeFX = new EffectList();
+
+ public EffectList m_randomBuyFX = new EffectList();
+
+ public EffectList m_randomSellFX = new EffectList();
+
+ private bool m_didGreet;
+
+ private bool m_didGoodbye;
+
+ private Animator m_animator;
+
+ private LookAt m_lookAt;
+
+ private void Start()
+ {
+ m_animator = GetComponentInChildren<Animator>();
+ m_lookAt = GetComponentInChildren<LookAt>();
+ InvokeRepeating("RandomTalk", m_randomTalkInterval, m_randomTalkInterval);
+ }
+
+ private void Update()
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, m_standRange);
+ if ((bool)closestPlayer)
+ {
+ m_animator.SetBool("Stand", value: true);
+ m_lookAt.SetLoockAtTarget(closestPlayer.GetHeadPoint());
+ float num = Vector3.Distance(closestPlayer.transform.position, base.transform.position);
+ if (!m_didGreet && num < m_greetRange)
+ {
+ m_didGreet = true;
+ Say(m_randomGreets, "Greet");
+ m_randomGreetFX.Create(base.transform.position, Quaternion.identity);
+ }
+ if (m_didGreet && !m_didGoodbye && num > m_byeRange)
+ {
+ m_didGoodbye = true;
+ Say(m_randomGoodbye, "Greet");
+ m_randomGoodbyeFX.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+ else
+ {
+ m_animator.SetBool("Stand", value: false);
+ m_lookAt.ResetTarget();
+ }
+ }
+
+ private void RandomTalk()
+ {
+ if (m_animator.GetBool("Stand") && !StoreGui.IsVisible() && Player.IsPlayerInRange(base.transform.position, m_greetRange))
+ {
+ Say(m_randomTalk, "Talk");
+ m_randomTalkFX.Create(base.transform.position, Quaternion.identity);
+ }
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] $raven_interact");
+ }
+
+ public string GetHoverName()
+ {
+ return Localization.instance.Localize(m_name);
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ StoreGui.instance.Show(this);
+ Say(m_randomStartTrade, "Talk");
+ m_randomStartTradeFX.Create(base.transform.position, Quaternion.identity);
+ return false;
+ }
+
+ private void DiscoverItems(Player player)
+ {
+ foreach (TradeItem item in m_items)
+ {
+ player.AddKnownItem(item.m_prefab.m_itemData);
+ }
+ }
+
+ private void Say(List<string> texts, string trigger)
+ {
+ Say(texts[UnityEngine.Random.Range(0, texts.Count)], trigger);
+ }
+
+ private void Say(string text, string trigger)
+ {
+ Chat.instance.SetNpcText(base.gameObject, Vector3.up * 1.5f, 20f, m_hideDialogDelay, "", text, large: false);
+ if (trigger.Length > 0)
+ {
+ m_animator.SetTrigger(trigger);
+ }
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ public void OnBought(TradeItem item)
+ {
+ Say(m_randomBuy, "Buy");
+ m_randomBuyFX.Create(base.transform.position, Quaternion.identity);
+ }
+
+ public void OnSold()
+ {
+ Say(m_randomSell, "Sell");
+ m_randomSellFX.Create(base.transform.position, Quaternion.identity);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeBase.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeBase.cs
new file mode 100644
index 0000000..4126c97
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeBase.cs
@@ -0,0 +1,183 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class TreeBase : MonoBehaviour, IDestructible
+{
+ private ZNetView m_nview;
+
+ public float m_health = 1f;
+
+ public HitData.DamageModifiers m_damageModifiers;
+
+ public int m_minToolTier;
+
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public EffectList m_respawnEffect = new EffectList();
+
+ public GameObject m_trunk;
+
+ public GameObject m_stubPrefab;
+
+ public GameObject m_logPrefab;
+
+ public Transform m_logSpawnPoint;
+
+ [Header("Drops")]
+ public DropTable m_dropWhenDestroyed = new DropTable();
+
+ public float m_spawnYOffset = 0.5f;
+
+ public float m_spawnYStep = 0.3f;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_nview.Register<HitData>("Damage", RPC_Damage);
+ m_nview.Register("Grow", RPC_Grow);
+ m_nview.Register("Shake", RPC_Shake);
+ if (m_nview.IsOwner() && m_nview.GetZDO().GetFloat("health", m_health) <= 0f)
+ {
+ m_nview.Destroy();
+ }
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Tree;
+ }
+
+ public void Damage(HitData hit)
+ {
+ m_nview.InvokeRPC("Damage", hit);
+ }
+
+ public void Grow()
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "Grow");
+ }
+
+ private void RPC_Grow(long uid)
+ {
+ StartCoroutine("GrowAnimation");
+ }
+
+ private IEnumerator GrowAnimation()
+ {
+ GameObject animatedTrunk = Object.Instantiate(m_trunk, m_trunk.transform.position, m_trunk.transform.rotation, base.transform);
+ animatedTrunk.isStatic = false;
+ LODGroup component = base.transform.GetComponent<LODGroup>();
+ if ((bool)component)
+ {
+ component.fadeMode = LODFadeMode.None;
+ }
+ m_trunk.SetActive(value: false);
+ for (float t = 0f; t < 0.3f; t += Time.deltaTime)
+ {
+ float num = Mathf.Clamp01(t / 0.3f);
+ animatedTrunk.transform.localScale = m_trunk.transform.localScale * num;
+ yield return null;
+ }
+ Object.Destroy(animatedTrunk);
+ m_trunk.SetActive(value: true);
+ if (m_nview.IsOwner())
+ {
+ m_respawnEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ }
+ }
+
+ private void RPC_Damage(long sender, HitData hit)
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ float @float = m_nview.GetZDO().GetFloat("health", m_health);
+ if (@float <= 0f)
+ {
+ m_nview.Destroy();
+ return;
+ }
+ hit.ApplyResistance(m_damageModifiers, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if (hit.m_toolTier < m_minToolTier)
+ {
+ DamageText.instance.ShowText(DamageText.TextType.TooHard, hit.m_point, 0f);
+ return;
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return;
+ }
+ @float -= totalDamage;
+ m_nview.GetZDO().Set("health", @float);
+ Shake();
+ m_hitEffect.Create(hit.m_point, Quaternion.identity, base.transform);
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(100f);
+ }
+ if (@float <= 0f)
+ {
+ m_destroyedEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ SpawnLog(hit.m_dir);
+ List<GameObject> dropList = m_dropWhenDestroyed.GetDropList();
+ for (int i = 0; i < dropList.Count; i++)
+ {
+ Vector2 vector = Random.insideUnitCircle * 0.5f;
+ Vector3 position = base.transform.position + Vector3.up * m_spawnYOffset + new Vector3(vector.x, m_spawnYStep * (float)i, vector.y);
+ Quaternion rotation = Quaternion.Euler(0f, Random.Range(0, 360), 0f);
+ Object.Instantiate(dropList[i], position, rotation);
+ }
+ base.gameObject.SetActive(value: false);
+ m_nview.Destroy();
+ }
+ }
+
+ private void Shake()
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "Shake");
+ }
+
+ private void RPC_Shake(long uid)
+ {
+ StopCoroutine("ShakeAnimation");
+ StartCoroutine("ShakeAnimation");
+ }
+
+ private IEnumerator ShakeAnimation()
+ {
+ m_trunk.gameObject.isStatic = false;
+ float t = Time.time;
+ while (Time.time - t < 1f)
+ {
+ float time = Time.time;
+ float num = 1f - Mathf.Clamp01((time - t) / 1f);
+ float num2 = num * num * num * 1.5f;
+ Quaternion localRotation = Quaternion.Euler(Mathf.Sin(time * 40f) * num2, 0f, Mathf.Cos(time * 0.9f * 40f) * num2);
+ m_trunk.transform.localRotation = localRotation;
+ yield return null;
+ }
+ m_trunk.transform.localRotation = Quaternion.identity;
+ m_trunk.gameObject.isStatic = true;
+ }
+
+ private void SpawnLog(Vector3 hitDir)
+ {
+ GameObject gameObject = Object.Instantiate(m_logPrefab, m_logSpawnPoint.position, m_logSpawnPoint.rotation);
+ gameObject.GetComponent<ZNetView>().SetLocalScale(base.transform.localScale);
+ Rigidbody component = gameObject.GetComponent<Rigidbody>();
+ component.mass *= base.transform.localScale.x;
+ component.ResetInertiaTensor();
+ component.AddForceAtPosition(hitDir * 0.2f, gameObject.transform.position + Vector3.up * 4f * base.transform.localScale.y, ForceMode.VelocityChange);
+ if ((bool)m_stubPrefab)
+ {
+ Object.Instantiate(m_stubPrefab, base.transform.position, base.transform.rotation).GetComponent<ZNetView>().SetLocalScale(base.transform.localScale);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeLog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeLog.cs
new file mode 100644
index 0000000..a2ec07b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/TreeLog.cs
@@ -0,0 +1,139 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class TreeLog : MonoBehaviour, IDestructible
+{
+ public float m_health = 60f;
+
+ public HitData.DamageModifiers m_damages;
+
+ public int m_minToolTier;
+
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public DropTable m_dropWhenDestroyed = new DropTable();
+
+ public GameObject m_subLogPrefab;
+
+ public Transform[] m_subLogPoints = new Transform[0];
+
+ public float m_spawnDistance = 2f;
+
+ public float m_hitNoise = 100f;
+
+ private Rigidbody m_body;
+
+ private ZNetView m_nview;
+
+ private bool m_firstFrame = true;
+
+ private void Awake()
+ {
+ m_body = GetComponent<Rigidbody>();
+ m_body.maxDepenetrationVelocity = 1f;
+ m_nview = GetComponent<ZNetView>();
+ m_nview.Register<HitData>("Damage", RPC_Damage);
+ if (m_nview.IsOwner())
+ {
+ float @float = m_nview.GetZDO().GetFloat("health", -1f);
+ if (@float == -1f)
+ {
+ m_nview.GetZDO().Set("health", m_health);
+ }
+ else if (@float <= 0f)
+ {
+ m_nview.Destroy();
+ }
+ }
+ Invoke("EnableDamage", 0.2f);
+ }
+
+ private void EnableDamage()
+ {
+ m_firstFrame = false;
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Tree;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (!m_firstFrame && m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("Damage", hit);
+ }
+ }
+
+ private void RPC_Damage(long sender, HitData hit)
+ {
+ if (!m_nview.IsOwner())
+ {
+ return;
+ }
+ float @float = m_nview.GetZDO().GetFloat("health");
+ if (@float <= 0f)
+ {
+ return;
+ }
+ hit.ApplyResistance(m_damages, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if (hit.m_toolTier < m_minToolTier)
+ {
+ DamageText.instance.ShowText(DamageText.TextType.TooHard, hit.m_point, 0f);
+ return;
+ }
+ if ((bool)m_body)
+ {
+ m_body.AddForceAtPosition(hit.m_dir * hit.m_pushForce * 2f, hit.m_point, ForceMode.Impulse);
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return;
+ }
+ @float -= totalDamage;
+ if (@float < 0f)
+ {
+ @float = 0f;
+ }
+ m_nview.GetZDO().Set("health", @float);
+ m_hitEffect.Create(hit.m_point, Quaternion.identity, base.transform);
+ if (m_hitNoise > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(m_hitNoise);
+ }
+ }
+ if (@float <= 0f)
+ {
+ Destroy();
+ }
+ }
+
+ private void Destroy()
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ m_destroyedEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ List<GameObject> dropList = m_dropWhenDestroyed.GetDropList();
+ for (int i = 0; i < dropList.Count; i++)
+ {
+ Vector3 position = base.transform.position + base.transform.up * Random.Range(0f - m_spawnDistance, m_spawnDistance) + Vector3.up * 0.3f * i;
+ Quaternion rotation = Quaternion.Euler(0f, Random.Range(0, 360), 0f);
+ Object.Instantiate(dropList[i], position, rotation);
+ }
+ if (m_subLogPrefab != null)
+ {
+ Transform[] subLogPoints = m_subLogPoints;
+ foreach (Transform transform in subLogPoints)
+ {
+ Object.Instantiate(m_subLogPrefab, transform.position, base.transform.rotation).GetComponent<ZNetView>().SetLocalScale(base.transform.localScale);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tutorial.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tutorial.cs
new file mode 100644
index 0000000..564d399
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Tutorial.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Tutorial : MonoBehaviour
+{
+ [Serializable]
+ public class TutorialText
+ {
+ public string m_name;
+
+ public string m_topic = "";
+
+ public string m_label = "";
+
+ [TextArea]
+ public string m_text = "";
+ }
+
+ public List<TutorialText> m_texts = new List<TutorialText>();
+
+ public RectTransform m_windowRoot;
+
+ public Text m_topic;
+
+ public Text m_text;
+
+ public GameObject m_ravenPrefab;
+
+ private static Tutorial m_instance;
+
+ private Queue<string> m_tutQueue = new Queue<string>();
+
+ public static Tutorial instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_windowRoot.gameObject.SetActive(value: false);
+ }
+
+ private void Update()
+ {
+ }
+
+ public void ShowText(string name, bool force)
+ {
+ TutorialText tutorialText = m_texts.Find((TutorialText x) => x.m_name == name);
+ if (tutorialText != null)
+ {
+ SpawnRaven(tutorialText.m_name, tutorialText.m_topic, tutorialText.m_text, tutorialText.m_label);
+ }
+ }
+
+ private void SpawnRaven(string key, string topic, string text, string label)
+ {
+ if (!Raven.IsInstantiated())
+ {
+ UnityEngine.Object.Instantiate(m_ravenPrefab, new Vector3(0f, 0f, 0f), Quaternion.identity);
+ }
+ Raven.AddTempText(key, topic, text, label, munin: false);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vagon.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vagon.cs
new file mode 100644
index 0000000..8539bf3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vagon.cs
@@ -0,0 +1,333 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class Vagon : MonoBehaviour, Hoverable, Interactable
+{
+ [Serializable]
+ public class LoadData
+ {
+ public GameObject m_gameobject;
+
+ public float m_minPercentage;
+ }
+
+ private static List<Vagon> m_instances = new List<Vagon>();
+
+ public Transform m_attachPoint;
+
+ public string m_name = "Wagon";
+
+ public float m_detachDistance = 2f;
+
+ public Vector3 m_attachOffset = new Vector3(0f, 0.8f, 0f);
+
+ public Container m_container;
+
+ public Transform m_lineAttachPoints0;
+
+ public Transform m_lineAttachPoints1;
+
+ public Vector3 m_lineAttachOffset = new Vector3(0f, 1f, 0f);
+
+ public float m_breakForce = 10000f;
+
+ public float m_spring = 5000f;
+
+ public float m_springDamping = 1000f;
+
+ public float m_baseMass = 20f;
+
+ public float m_itemWeightMassFactor = 1f;
+
+ public AudioSource[] m_wheelLoops;
+
+ public float m_minPitch = 1f;
+
+ public float m_maxPitch = 1.5f;
+
+ public float m_maxPitchVel = 10f;
+
+ public float m_maxVol = 1f;
+
+ public float m_maxVolVel = 10f;
+
+ public float m_audioChangeSpeed = 2f;
+
+ public Rigidbody[] m_wheels = new Rigidbody[0];
+
+ public List<LoadData> m_loadVis = new List<LoadData>();
+
+ private ZNetView m_nview;
+
+ private ConfigurableJoint m_attachJoin;
+
+ private Rigidbody m_body;
+
+ private LineRenderer m_lineRenderer;
+
+ private Rigidbody[] m_bodies;
+
+ private Humanoid m_useRequester;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ return;
+ }
+ m_instances.Add(this);
+ Heightmap.ForceGenerateAll();
+ m_body = GetComponent<Rigidbody>();
+ m_bodies = GetComponentsInChildren<Rigidbody>();
+ m_lineRenderer = GetComponent<LineRenderer>();
+ Rigidbody[] bodies = m_bodies;
+ for (int i = 0; i < bodies.Length; i++)
+ {
+ bodies[i].maxDepenetrationVelocity = 2f;
+ }
+ m_nview.Register("RequestOwn", RPC_RequestOwn);
+ m_nview.Register("RequestDenied", RPC_RequestDenied);
+ InvokeRepeating("UpdateMass", 0f, 5f);
+ InvokeRepeating("UpdateLoadVisualization", 0f, 3f);
+ }
+
+ private void OnDestroy()
+ {
+ m_instances.Remove(this);
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] Use");
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ m_useRequester = character;
+ if (!m_nview.IsOwner())
+ {
+ m_nview.InvokeRPC("RequestOwn");
+ }
+ return false;
+ }
+
+ public void RPC_RequestOwn(long sender)
+ {
+ if (m_nview.IsOwner())
+ {
+ if (InUse())
+ {
+ ZLog.Log("Requested use, but is already in use");
+ m_nview.InvokeRPC(sender, "RequestDenied");
+ }
+ else
+ {
+ m_nview.GetZDO().SetOwner(sender);
+ }
+ }
+ }
+
+ private void RPC_RequestDenied(long sender)
+ {
+ ZLog.Log("Got request denied");
+ if ((bool)m_useRequester)
+ {
+ m_useRequester.Message(MessageHud.MessageType.Center, m_name + " is in use by someone else");
+ m_useRequester = null;
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ UpdateAudio(Time.fixedDeltaTime);
+ if (m_nview.IsOwner())
+ {
+ if ((bool)m_useRequester)
+ {
+ if (IsAttached())
+ {
+ Detach();
+ }
+ else if (CanAttach(m_useRequester.gameObject))
+ {
+ AttachTo(m_useRequester.gameObject);
+ }
+ else
+ {
+ m_useRequester.Message(MessageHud.MessageType.Center, "Not in the right position");
+ }
+ m_useRequester = null;
+ }
+ if (IsAttached() && !CanAttach(m_attachJoin.connectedBody.gameObject))
+ {
+ Detach();
+ }
+ }
+ else if (IsAttached())
+ {
+ Detach();
+ }
+ }
+
+ private void LateUpdate()
+ {
+ if (IsAttached())
+ {
+ m_lineRenderer.enabled = true;
+ m_lineRenderer.SetPosition(0, m_lineAttachPoints0.position);
+ m_lineRenderer.SetPosition(1, m_attachJoin.connectedBody.transform.position + m_lineAttachOffset);
+ m_lineRenderer.SetPosition(2, m_lineAttachPoints1.position);
+ }
+ else
+ {
+ m_lineRenderer.enabled = false;
+ }
+ }
+
+ public bool IsAttached(Character character)
+ {
+ if ((bool)m_attachJoin && m_attachJoin.connectedBody.gameObject == character.gameObject)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool InUse()
+ {
+ if ((bool)m_container && m_container.IsInUse())
+ {
+ return true;
+ }
+ return IsAttached();
+ }
+
+ private bool IsAttached()
+ {
+ return m_attachJoin != null;
+ }
+
+ private bool CanAttach(GameObject go)
+ {
+ if (base.transform.up.y < 0.1f)
+ {
+ return false;
+ }
+ Humanoid component = go.GetComponent<Humanoid>();
+ if ((bool)component && component.InDodge())
+ {
+ return false;
+ }
+ return Vector3.Distance(go.transform.position + m_attachOffset, m_attachPoint.position) < m_detachDistance;
+ }
+
+ private void AttachTo(GameObject go)
+ {
+ DetachAll();
+ m_attachJoin = base.gameObject.AddComponent<ConfigurableJoint>();
+ m_attachJoin.autoConfigureConnectedAnchor = false;
+ m_attachJoin.anchor = m_attachPoint.localPosition;
+ m_attachJoin.connectedAnchor = m_attachOffset;
+ m_attachJoin.breakForce = m_breakForce;
+ m_attachJoin.xMotion = ConfigurableJointMotion.Limited;
+ m_attachJoin.yMotion = ConfigurableJointMotion.Limited;
+ m_attachJoin.zMotion = ConfigurableJointMotion.Limited;
+ SoftJointLimit linearLimit = default(SoftJointLimit);
+ linearLimit.limit = 0.001f;
+ m_attachJoin.linearLimit = linearLimit;
+ SoftJointLimitSpring linearLimitSpring = default(SoftJointLimitSpring);
+ linearLimitSpring.spring = m_spring;
+ linearLimitSpring.damper = m_springDamping;
+ m_attachJoin.linearLimitSpring = linearLimitSpring;
+ m_attachJoin.zMotion = ConfigurableJointMotion.Locked;
+ m_attachJoin.connectedBody = go.GetComponent<Rigidbody>();
+ }
+
+ private static void DetachAll()
+ {
+ foreach (Vagon instance in m_instances)
+ {
+ instance.Detach();
+ }
+ }
+
+ private void Detach()
+ {
+ if ((bool)m_attachJoin)
+ {
+ UnityEngine.Object.Destroy(m_attachJoin);
+ m_attachJoin = null;
+ m_body.WakeUp();
+ m_body.AddForce(0f, 1f, 0f);
+ }
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void UpdateMass()
+ {
+ if (m_nview.IsOwner() && !(m_container == null))
+ {
+ float totalWeight = m_container.GetInventory().GetTotalWeight();
+ float mass = m_baseMass + totalWeight * m_itemWeightMassFactor;
+ SetMass(mass);
+ }
+ }
+
+ private void SetMass(float mass)
+ {
+ float mass2 = mass / (float)m_bodies.Length;
+ Rigidbody[] bodies = m_bodies;
+ for (int i = 0; i < bodies.Length; i++)
+ {
+ bodies[i].mass = mass2;
+ }
+ }
+
+ private void UpdateLoadVisualization()
+ {
+ if (m_container == null)
+ {
+ return;
+ }
+ float num = m_container.GetInventory().SlotsUsedPercentage();
+ foreach (LoadData loadVi in m_loadVis)
+ {
+ loadVi.m_gameobject.SetActive(num >= loadVi.m_minPercentage);
+ }
+ }
+
+ private void UpdateAudio(float dt)
+ {
+ float num = 0f;
+ Rigidbody[] wheels = m_wheels;
+ foreach (Rigidbody rigidbody in wheels)
+ {
+ num += rigidbody.angularVelocity.magnitude;
+ }
+ num /= (float)m_wheels.Length;
+ float target = Mathf.Lerp(m_minPitch, m_maxPitch, Mathf.Clamp01(num / m_maxPitchVel));
+ float target2 = m_maxVol * Mathf.Clamp01(num / m_maxVolVel);
+ AudioSource[] wheelLoops = m_wheelLoops;
+ foreach (AudioSource obj in wheelLoops)
+ {
+ obj.volume = Mathf.MoveTowards(obj.volume, target2, m_audioChangeSpeed * dt);
+ obj.pitch = Mathf.MoveTowards(obj.pitch, target, m_audioChangeSpeed * dt);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.csproj b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.csproj
new file mode 100644
index 0000000..4168504
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.csproj
@@ -0,0 +1,273 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_valheim</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net46</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup>
+ <Reference Include="assembly_googleanalytics">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_googleanalytics.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_guiutils">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_guiutils.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_lux">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_lux.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_postprocessing">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_postprocessing.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_simplemeshcombine">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_simplemeshcombine.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_steamworks">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_steamworks.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_sunshafts">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_sunshafts.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_utils">
+ <HintPath>..\..\Game\valheim_Data\Managed\assembly_utils.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Security">
+ <HintPath>..\..\Game\valheim_Data\Managed\Mono.Security.dll</HintPath>
+ </Reference>
+ <Reference Include="mscorlib">
+ <HintPath>..\Valheim\valheim_Data\Managed\mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="netstandard">
+ <HintPath>..\..\Game\valheim_Data\Managed\netstandard.dll</HintPath>
+ </Reference>
+ <Reference Include="System.ComponentModel.Composition">
+ <HintPath>..\Valheim\valheim_Data\Managed\System.ComponentModel.Composition.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Configuration">
+ <HintPath>..\Valheim\valheim_Data\Managed\System.Configuration.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Core" />
+ <Reference Include="System.Diagnostics.StackTrace">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.Diagnostics.StackTrace.dll</HintPath>
+ </Reference>
+ <Reference Include="System.EnterpriseServices">
+ <HintPath>..\Valheim\valheim_Data\Managed\System.EnterpriseServices.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Globalization.Extensions">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.Globalization.Extensions.dll</HintPath>
+ </Reference>
+ <Reference Include="System.IO.Compression">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.IO.Compression.dll</HintPath>
+ </Reference>
+ <Reference Include="System.IO.Compression.FileSystem">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.IO.Compression.FileSystem.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.Net.Http.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Runtime.Serialization.Xml">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.Runtime.Serialization.Xml.dll</HintPath>
+ </Reference>
+ <Reference Include="System.ServiceModel.Internals">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.ServiceModel.Internals.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Transactions">
+ <HintPath>..\Valheim\valheim_Data\Managed\System.Transactions.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml.XPath.XDocument">
+ <HintPath>..\..\Game\valheim_Data\Managed\System.Xml.XPath.XDocument.dll</HintPath>
+ </Reference>
+ <Reference Include="Unity.TextMeshPro">
+ <HintPath>..\..\Game\valheim_Data\Managed\Unity.TextMeshPro.dll</HintPath>
+ </Reference>
+ <Reference Include="Unity.Timeline">
+ <HintPath>..\..\Game\valheim_Data\Managed\Unity.Timeline.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AccessibilityModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AndroidJNIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AndroidJNIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AnimationModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ARModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ARModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AssetBundleModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AudioModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClothModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ClothModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClusterInputModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ClusterInputModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClusterRendererModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ClusterRendererModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.CrashReportingModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.CrashReportingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.DirectorModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.DirectorModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.DSPGraphModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.DSPGraphModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.GameCenterModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.GameCenterModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.GridModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.GridModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.HotReloadModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.HotReloadModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ImageConversionModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.IMGUIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.InputModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.JSONSerializeModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.JSONSerializeModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.LocalizationModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.LocalizationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ParticleSystemModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PerformanceReportingModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.PerformanceReportingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.Physics2DModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PhysicsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ProfilerModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ProfilerModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ScreenCaptureModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SharedInternalsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.SharedInternalsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SpriteMaskModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SpriteShapeModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.SpriteShapeModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.StreamingModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.StreamingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SubstanceModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.SubstanceModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SubsystemsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.SubsystemsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TerrainModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TerrainModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TerrainPhysicsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TerrainPhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TextCoreModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TextRenderingModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TilemapModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TilemapModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TLSModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UI">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UI.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UIElementsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UIModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UmbraModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UmbraModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UNETModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityAnalyticsModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityConnectModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityConnectModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityTestProtocolModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityTestProtocolModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestAssetBundleModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestAudioModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestTextureModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestWWWModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VehiclesModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.VehiclesModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VFXModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.VFXModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VideoModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VRModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.VRModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.WindModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.WindModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.XRModule">
+ <HintPath>..\..\Game\valheim_Data\Managed\UnityEngine.XRModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.sln b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.sln
new file mode 100644
index 0000000..f4adca7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valheim.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33213.308
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Valheim", "Valheim.csproj", "{876E5906-A8FC-4313-9555-D7B33E28A73D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {876E5906-A8FC-4313-9555-D7B33E28A73D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {876E5906-A8FC-4313-9555-D7B33E28A73D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {876E5906-A8FC-4313-9555-D7B33E28A73D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {876E5906-A8FC-4313-9555-D7B33E28A73D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F47B53F2-7311-4FAB-9D8C-F70D295285F0}
+ EndGlobalSection
+EndGlobal
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valkyrie.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valkyrie.cs
new file mode 100644
index 0000000..ee2aa56
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Valkyrie.cs
@@ -0,0 +1,192 @@
+using System;
+using UnityEngine;
+
+public class Valkyrie : MonoBehaviour
+{
+ public float m_startPause = 10f;
+
+ public float m_speed = 10f;
+
+ public float m_turnRate = 5f;
+
+ public float m_dropHeight = 10f;
+
+ public float m_startAltitude = 500f;
+
+ public float m_descentAltitude = 100f;
+
+ public float m_startDistance = 500f;
+
+ public float m_startDescentDistance = 200f;
+
+ public Vector3 m_attachOffset = new Vector3(0f, 0f, 1f);
+
+ public float m_textDuration = 5f;
+
+ public string m_introTopic = "";
+
+ [TextArea]
+ public string m_introText = "";
+
+ public Transform m_attachPoint;
+
+ private Vector3 m_targetPoint;
+
+ private Vector3 m_descentStart;
+
+ private Vector3 m_flyAwayPoint;
+
+ private bool m_descent;
+
+ private bool m_droppedPlayer;
+
+ private Animator m_animator;
+
+ private ZNetView m_nview;
+
+ private float m_timer;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_animator = GetComponentInChildren<Animator>();
+ if (!m_nview.IsOwner())
+ {
+ base.enabled = false;
+ return;
+ }
+ ZLog.Log("Setting up valkyrie ");
+ float f = UnityEngine.Random.value * (float)Math.PI * 2f;
+ Vector3 vector = new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f));
+ Vector3 vector2 = Vector3.Cross(vector, Vector3.up);
+ Player.m_localPlayer.SetIntro(intro: true);
+ m_targetPoint = Player.m_localPlayer.transform.position + new Vector3(0f, m_dropHeight, 0f);
+ Vector3 position = m_targetPoint + vector * m_startDistance;
+ position.y = m_startAltitude;
+ base.transform.position = position;
+ m_descentStart = m_targetPoint + vector * m_startDescentDistance + vector2 * 200f;
+ m_descentStart.y = m_descentAltitude;
+ Vector3 vector3 = m_targetPoint - m_descentStart;
+ vector3.y = 0f;
+ vector3.Normalize();
+ m_flyAwayPoint = m_targetPoint + vector3 * m_startDescentDistance;
+ m_flyAwayPoint.y = m_startAltitude;
+ ShowText();
+ SyncPlayer(doNetworkSync: true);
+ ZLog.Log(string.Concat("World pos ", base.transform.position, " ", ZNet.instance.GetReferencePosition()));
+ }
+
+ private void ShowText()
+ {
+ TextViewer.instance.ShowText(TextViewer.Style.Intro, m_introTopic, m_introText, autoHide: false);
+ }
+
+ private void HideText()
+ {
+ }
+
+ private void OnDestroy()
+ {
+ ZLog.Log("Destroying valkyrie");
+ }
+
+ private void FixedUpdate()
+ {
+ UpdateValkyrie(Time.fixedDeltaTime);
+ if (!m_droppedPlayer)
+ {
+ SyncPlayer(doNetworkSync: true);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ if (!m_droppedPlayer)
+ {
+ SyncPlayer(doNetworkSync: false);
+ }
+ }
+
+ private void UpdateValkyrie(float dt)
+ {
+ m_timer += dt;
+ if (m_timer < m_startPause)
+ {
+ return;
+ }
+ Vector3 vector = (m_droppedPlayer ? m_flyAwayPoint : ((!m_descent) ? m_descentStart : m_targetPoint));
+ if (Utils.DistanceXZ(vector, base.transform.position) < 0.5f)
+ {
+ if (!m_descent)
+ {
+ m_descent = true;
+ ZLog.Log("Starting descent");
+ }
+ else if (!m_droppedPlayer)
+ {
+ ZLog.Log("We are here");
+ DropPlayer();
+ }
+ else
+ {
+ m_nview.Destroy();
+ }
+ }
+ Vector3 normalized = (vector - base.transform.position).normalized;
+ Vector3 vector2 = base.transform.position + normalized * 25f;
+ if (ZoneSystem.instance.GetGroundHeight(vector2, out var height))
+ {
+ vector2.y = Mathf.Max(vector2.y, height + m_dropHeight);
+ }
+ Vector3 normalized2 = (vector2 - base.transform.position).normalized;
+ Quaternion quaternion = Quaternion.LookRotation(normalized2);
+ Vector3 to = normalized2;
+ to.y = 0f;
+ to.Normalize();
+ Vector3 forward = base.transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ float num = Mathf.Clamp(Vector3.SignedAngle(forward, to, Vector3.up), -30f, 30f) / 30f;
+ quaternion = Quaternion.Euler(0f, 0f, num * 45f) * quaternion;
+ float num2 = (m_droppedPlayer ? (m_turnRate * 4f) : m_turnRate);
+ base.transform.rotation = Quaternion.RotateTowards(base.transform.rotation, quaternion, num2 * dt);
+ Vector3 vector3 = base.transform.forward * m_speed;
+ Vector3 vector4 = base.transform.position + vector3 * dt;
+ if (ZoneSystem.instance.GetGroundHeight(vector4, out var height2))
+ {
+ vector4.y = Mathf.Max(vector4.y, height2 + m_dropHeight);
+ }
+ base.transform.position = vector4;
+ }
+
+ private void DropPlayer()
+ {
+ ZLog.Log("We are here");
+ m_droppedPlayer = true;
+ Vector3 forward = base.transform.forward;
+ forward.y = 0f;
+ forward.Normalize();
+ Player.m_localPlayer.transform.rotation = Quaternion.LookRotation(forward);
+ Player.m_localPlayer.SetIntro(intro: false);
+ m_animator.SetBool("dropped", value: true);
+ }
+
+ private void SyncPlayer(bool doNetworkSync)
+ {
+ Player localPlayer = Player.m_localPlayer;
+ if (localPlayer == null)
+ {
+ ZLog.LogWarning("No local player");
+ return;
+ }
+ localPlayer.transform.rotation = m_attachPoint.rotation;
+ localPlayer.transform.position = m_attachPoint.position - localPlayer.transform.TransformVector(m_attachOffset);
+ localPlayer.GetComponent<Rigidbody>().position = localPlayer.transform.position;
+ if (doNetworkSync)
+ {
+ ZNet.instance.SetReferencePosition(localPlayer.transform.position);
+ localPlayer.GetComponent<ZSyncTransform>().SyncNow();
+ GetComponent<ZSyncTransform>().SyncNow();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VariantDialog.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VariantDialog.cs
new file mode 100644
index 0000000..30f3ea6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VariantDialog.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class VariantDialog : MonoBehaviour
+{
+ public Transform m_listRoot;
+
+ public GameObject m_elementPrefab;
+
+ public float m_spacing = 70f;
+
+ public int m_gridWidth = 5;
+
+ private List<GameObject> m_elements = new List<GameObject>();
+
+ public Action<int> m_selected;
+
+ public void Setup(ItemDrop.ItemData item)
+ {
+ base.gameObject.SetActive(value: true);
+ foreach (GameObject element in m_elements)
+ {
+ UnityEngine.Object.Destroy(element);
+ }
+ m_elements.Clear();
+ for (int i = 0; i < item.m_shared.m_variants; i++)
+ {
+ Sprite sprite = item.m_shared.m_icons[i];
+ int num = i / m_gridWidth;
+ int num2 = i % m_gridWidth;
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_elementPrefab, Vector3.zero, Quaternion.identity, m_listRoot);
+ gameObject.SetActive(value: true);
+ (gameObject.transform as RectTransform).anchoredPosition = new Vector2((float)num2 * m_spacing, (float)(-num) * m_spacing);
+ Button component = gameObject.transform.Find("Button").GetComponent<Button>();
+ int buttonIndex = i;
+ component.onClick.AddListener(delegate
+ {
+ OnClicked(buttonIndex);
+ });
+ component.GetComponent<Image>().sprite = sprite;
+ m_elements.Add(gameObject);
+ }
+ }
+
+ public void OnClose()
+ {
+ base.gameObject.SetActive(value: false);
+ }
+
+ private void OnClicked(int index)
+ {
+ ZLog.Log("Clicked button " + index);
+ base.gameObject.SetActive(value: false);
+ m_selected(index);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vegvisir.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vegvisir.cs
new file mode 100644
index 0000000..7e8ccb3
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Vegvisir.cs
@@ -0,0 +1,38 @@
+using UnityEngine;
+
+public class Vegvisir : MonoBehaviour, Hoverable, Interactable
+{
+ public string m_name = "$piece_vegvisir";
+
+ public string m_locationName = "";
+
+ public string m_pinName = "Pin";
+
+ public Minimap.PinType m_pinType;
+
+ public string GetHoverText()
+ {
+ return Localization.instance.Localize(m_name + " " + m_pinName + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_register_location ");
+ }
+
+ public string GetHoverName()
+ {
+ return m_name;
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ Game.instance.DiscoverClosestLocation(m_locationName, base.transform.position, m_pinName, (int)m_pinType);
+ GoogleAnalyticsV4.instance.LogEvent("Game", "Vegvisir", m_locationName, 0L);
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Version.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Version.cs
new file mode 100644
index 0000000..9c05fc7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Version.cs
@@ -0,0 +1,101 @@
+using UnityEngine;
+
+internal class Version
+{
+ public static int m_major = 0;
+
+ public static int m_minor = 141;
+
+ public static int m_patch = 2;
+
+ public static int m_playerVersion = 32;
+
+ public static int[] m_compatiblePlayerVersions = new int[5] { 31, 30, 29, 28, 27 };
+
+ public static int m_worldVersion = 26;
+
+ public static int[] m_compatibleWorldVersions = new int[16]
+ {
+ 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 11, 10, 9
+ };
+
+ public static int m_worldGenVersion = 1;
+
+ public static string GetVersionString()
+ {
+ return CombineVersion(m_major, m_minor, m_patch);
+ }
+
+ public static bool IsVersionNewer(int major, int minor, int patch)
+ {
+ if (major > m_major)
+ {
+ return true;
+ }
+ if (major == m_major && minor > m_minor)
+ {
+ return true;
+ }
+ if (major == m_major && minor == m_minor)
+ {
+ if (m_patch >= 0)
+ {
+ return patch > m_patch;
+ }
+ if (patch >= 0)
+ {
+ return true;
+ }
+ return patch < m_patch;
+ }
+ return false;
+ }
+
+ public static string CombineVersion(int major, int minor, int patch)
+ {
+ if (patch == 0)
+ {
+ return major + "." + minor;
+ }
+ if (patch < 0)
+ {
+ return major + "." + minor + ".rc" + Mathf.Abs(patch);
+ }
+ return major + "." + minor + "." + patch;
+ }
+
+ public static bool IsWorldVersionCompatible(int version)
+ {
+ if (version == m_worldVersion)
+ {
+ return true;
+ }
+ int[] compatibleWorldVersions = m_compatibleWorldVersions;
+ foreach (int num in compatibleWorldVersions)
+ {
+ if (version == num)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static bool IsPlayerVersionCompatible(int version)
+ {
+ if (version == m_playerVersion)
+ {
+ return true;
+ }
+ int[] compatiblePlayerVersions = m_compatiblePlayerVersions;
+ foreach (int num in compatiblePlayerVersions)
+ {
+ if (version == num)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VisEquipment.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VisEquipment.cs
new file mode 100644
index 0000000..7eba531
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/VisEquipment.cs
@@ -0,0 +1,1022 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+//player װ
+public class VisEquipment : MonoBehaviour
+{
+ [Serializable]
+ public class PlayerModel
+ {
+ public Mesh m_mesh;
+
+ public Material m_baseMaterial;
+ }
+
+ public SkinnedMeshRenderer m_bodyModel;
+
+ [Header("Attachment points")]
+ public Transform m_leftHand;
+
+ public Transform m_rightHand;
+
+ public Transform m_helmet;
+
+ public Transform m_backShield;
+
+ public Transform m_backMelee;
+
+ public Transform m_backTwohandedMelee;
+
+ public Transform m_backBow;
+
+ public Transform m_backTool;
+
+ public Transform m_backAtgeir;
+
+ public CapsuleCollider[] m_clothColliders = new CapsuleCollider[0];
+
+ public PlayerModel[] m_models = new PlayerModel[0];
+
+ public bool m_isPlayer;
+
+ public bool m_useAllTrails;
+
+ private string m_leftItem = "";
+
+ private string m_rightItem = "";
+
+ private string m_chestItem = "";
+
+ private string m_legItem = "";
+
+ private string m_helmetItem = "";
+
+ private string m_shoulderItem = "";
+
+ private string m_beardItem = "";
+
+ private string m_hairItem = "";
+
+ private string m_utilityItem = "";
+
+ private string m_leftBackItem = "";
+
+ private string m_rightBackItem = "";
+
+ private int m_shoulderItemVariant;
+
+ private int m_leftItemVariant;
+
+ private int m_leftBackItemVariant;
+
+ private GameObject m_leftItemInstance;
+
+ private GameObject m_rightItemInstance;
+
+ private GameObject m_helmetItemInstance;
+
+ private List<GameObject> m_chestItemInstances;
+
+ private List<GameObject> m_legItemInstances;
+
+ private List<GameObject> m_shoulderItemInstances;
+
+ private List<GameObject> m_utilityItemInstances;
+
+ private GameObject m_beardItemInstance;
+
+ private GameObject m_hairItemInstance;
+
+ private GameObject m_leftBackItemInstance;
+
+ private GameObject m_rightBackItemInstance;
+
+ private int m_currentLeftItemHash;
+
+ private int m_currentRightItemHash;
+
+ private int m_currentChestItemHash;
+
+ private int m_currentLegItemHash;
+
+ private int m_currentHelmetItemHash;
+
+ private int m_currentShoulderItemHash;
+
+ private int m_currentBeardItemHash;
+
+ private int m_currentHairItemHash;
+
+ private int m_currentUtilityItemHash;
+
+ private int m_currentLeftBackItemHash;
+
+ private int m_currentRightBackItemHash;
+
+ private int m_currenShoulderItemVariant;
+
+ private int m_currentLeftItemVariant;
+
+ private int m_currentLeftBackItemVariant;
+
+ private bool m_helmetHideHair;
+
+ private Texture m_emptyBodyTexture;
+
+ private int m_modelIndex;
+
+ private Vector3 m_skinColor = Vector3.one;
+
+ private Vector3 m_hairColor = Vector3.one;
+
+ private int m_currentModelIndex;
+
+ private ZNetView m_nview;
+
+ private GameObject m_visual;
+
+ private LODGroup m_lodGroup;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ Transform transform = base.transform.Find("Visual");
+ if (transform == null)
+ {
+ transform = base.transform;
+ }
+ m_visual = transform.gameObject;
+ m_lodGroup = m_visual.GetComponentInChildren<LODGroup>();
+ if (m_bodyModel != null && m_bodyModel.material.HasProperty("_ChestTex"))
+ {
+ m_emptyBodyTexture = m_bodyModel.material.GetTexture("_ChestTex");
+ }
+ }
+
+ private void Start()
+ {
+ UpdateVisuals();
+ }
+
+ public void SetWeaponTrails(bool enabled)
+ {
+ if (m_useAllTrails)
+ {
+ MeleeWeaponTrail[] componentsInChildren = base.gameObject.GetComponentsInChildren<MeleeWeaponTrail>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].Emit = enabled;
+ }
+ }
+ else if ((bool)m_rightItemInstance)
+ {
+ MeleeWeaponTrail[] componentsInChildren = m_rightItemInstance.GetComponentsInChildren<MeleeWeaponTrail>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].Emit = enabled;
+ }
+ }
+ }
+
+ public void SetModel(int index)
+ {
+ if (m_modelIndex != index && index >= 0 && index < m_models.Length)
+ {
+ ZLog.Log("Vis equip model set to " + index);
+ m_modelIndex = index;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("ModelIndex", m_modelIndex);
+ }
+ }
+ }
+
+ public void SetSkinColor(Vector3 color)
+ {
+ if (!(color == m_skinColor))
+ {
+ m_skinColor = color;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("SkinColor", m_skinColor);
+ }
+ }
+ }
+
+ public void SetHairColor(Vector3 color)
+ {
+ if (!(m_hairColor == color))
+ {
+ m_hairColor = color;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("HairColor", m_hairColor);
+ }
+ }
+ }
+
+ public void SetLeftItem(string name, int variant)
+ {
+ if (!(m_leftItem == name) || m_leftItemVariant != variant)
+ {
+ m_leftItem = name;
+ m_leftItemVariant = variant;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("LeftItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ m_nview.GetZDO().Set("LeftItemVariant", variant);
+ }
+ }
+ }
+
+ public void SetRightItem(string name)
+ {
+ if (!(m_rightItem == name))
+ {
+ m_rightItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("RightItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetLeftBackItem(string name, int variant)
+ {
+ if (!(m_leftBackItem == name) || m_leftBackItemVariant != variant)
+ {
+ m_leftBackItem = name;
+ m_leftBackItemVariant = variant;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("LeftBackItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ m_nview.GetZDO().Set("LeftBackItemVariant", variant);
+ }
+ }
+ }
+
+ public void SetRightBackItem(string name)
+ {
+ if (!(m_rightBackItem == name))
+ {
+ m_rightBackItem = name;
+ ZLog.Log("Right back item " + name);
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("RightBackItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetChestItem(string name)
+ {
+ if (!(m_chestItem == name))
+ {
+ m_chestItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("ChestItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetLegItem(string name)
+ {
+ if (!(m_legItem == name))
+ {
+ m_legItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("LegItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetHelmetItem(string name)
+ {
+ if (!(m_helmetItem == name))
+ {
+ m_helmetItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("HelmetItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetShoulderItem(string name, int variant)
+ {
+ if (!(m_shoulderItem == name) || m_shoulderItemVariant != variant)
+ {
+ m_shoulderItem = name;
+ m_shoulderItemVariant = variant;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("ShoulderItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ m_nview.GetZDO().Set("ShoulderItemVariant", variant);
+ }
+ }
+ }
+
+ public void SetBeardItem(string name)
+ {
+ if (!(m_beardItem == name))
+ {
+ m_beardItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("BeardItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetHairItem(string name)
+ {
+ if (!(m_hairItem == name))
+ {
+ m_hairItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("HairItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ public void SetUtilityItem(string name)
+ {
+ if (!(m_utilityItem == name))
+ {
+ m_utilityItem = name;
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.GetZDO().Set("UtilityItem", (!string.IsNullOrEmpty(name)) ? name.GetStableHashCode() : 0);
+ }
+ }
+ }
+
+ private void Update()
+ {
+ UpdateVisuals();
+ }
+
+ private void UpdateVisuals()
+ {
+ UpdateEquipmentVisuals();
+ if (m_isPlayer)
+ {
+ UpdateBaseModel();
+ UpdateColors();
+ }
+ }
+
+ private void UpdateColors()
+ {
+ Color value = Utils.Vec3ToColor(m_skinColor);
+ Color value2 = Utils.Vec3ToColor(m_hairColor);
+ if (m_nview.GetZDO() != null)
+ {
+ value = Utils.Vec3ToColor(m_nview.GetZDO().GetVec3("SkinColor", Vector3.one));
+ value2 = Utils.Vec3ToColor(m_nview.GetZDO().GetVec3("HairColor", Vector3.one));
+ }
+ m_bodyModel.materials[0].SetColor("_SkinColor", value);
+ m_bodyModel.materials[1].SetColor("_SkinColor", value2);
+ if ((bool)m_beardItemInstance)
+ {
+ Renderer[] componentsInChildren = m_beardItemInstance.GetComponentsInChildren<Renderer>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].material.SetColor("_SkinColor", value2);
+ }
+ }
+ if ((bool)m_hairItemInstance)
+ {
+ Renderer[] componentsInChildren = m_hairItemInstance.GetComponentsInChildren<Renderer>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].material.SetColor("_SkinColor", value2);
+ }
+ }
+ }
+
+ private void UpdateBaseModel()
+ {
+ if (m_models.Length != 0)
+ {
+ int num = m_modelIndex;
+ if (m_nview.GetZDO() != null)
+ {
+ num = m_nview.GetZDO().GetInt("ModelIndex");
+ }
+ if (m_currentModelIndex != num || m_bodyModel.sharedMesh != m_models[num].m_mesh)
+ {
+ m_currentModelIndex = num;
+ m_bodyModel.sharedMesh = m_models[num].m_mesh;
+ m_bodyModel.materials[0].SetTexture("_MainTex", m_models[num].m_baseMaterial.GetTexture("_MainTex"));
+ m_bodyModel.materials[0].SetTexture("_SkinBumpMap", m_models[num].m_baseMaterial.GetTexture("_SkinBumpMap"));
+ }
+ }
+ }
+
+ private void UpdateEquipmentVisuals()
+ {
+ int hash = 0;
+ int rightHandEquiped = 0;
+ int chestEquiped = 0;
+ int legEquiped = 0;
+ int hash2 = 0;
+ int beardEquiped = 0;
+ int num = 0;
+ int hash3 = 0;
+ int utilityEquiped = 0;
+ int leftItem = 0;
+ int rightItem = 0;
+ int variant = m_shoulderItemVariant;
+ int variant2 = m_leftItemVariant;
+ int leftVariant = m_leftBackItemVariant;
+ ZDO zDO = m_nview.GetZDO();
+ if (zDO != null)
+ {
+ hash = zDO.GetInt("LeftItem");
+ rightHandEquiped = zDO.GetInt("RightItem");
+ chestEquiped = zDO.GetInt("ChestItem");
+ legEquiped = zDO.GetInt("LegItem");
+ hash2 = zDO.GetInt("HelmetItem");
+ hash3 = zDO.GetInt("ShoulderItem");
+ utilityEquiped = zDO.GetInt("UtilityItem");
+ if (m_isPlayer)
+ {
+ beardEquiped = zDO.GetInt("BeardItem");
+ num = zDO.GetInt("HairItem");
+ leftItem = zDO.GetInt("LeftBackItem");
+ rightItem = zDO.GetInt("RightBackItem");
+ variant = zDO.GetInt("ShoulderItemVariant");
+ variant2 = zDO.GetInt("LeftItemVariant");
+ leftVariant = zDO.GetInt("LeftBackItemVariant");
+ }
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(m_leftItem))
+ {
+ hash = m_leftItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_rightItem))
+ {
+ rightHandEquiped = m_rightItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_chestItem))
+ {
+ chestEquiped = m_chestItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_legItem))
+ {
+ legEquiped = m_legItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_helmetItem))
+ {
+ hash2 = m_helmetItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_shoulderItem))
+ {
+ hash3 = m_shoulderItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_utilityItem))
+ {
+ utilityEquiped = m_utilityItem.GetStableHashCode();
+ }
+ if (m_isPlayer)
+ {
+ if (!string.IsNullOrEmpty(m_beardItem))
+ {
+ beardEquiped = m_beardItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_hairItem))
+ {
+ num = m_hairItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_leftBackItem))
+ {
+ leftItem = m_leftBackItem.GetStableHashCode();
+ }
+ if (!string.IsNullOrEmpty(m_rightBackItem))
+ {
+ rightItem = m_rightBackItem.GetStableHashCode();
+ }
+ }
+ }
+ bool flag = false;
+ flag = SetRightHandEquiped(rightHandEquiped) || flag;
+ flag = SetLeftHandEquiped(hash, variant2) || flag;
+ flag = SetChestEquiped(chestEquiped) || flag;
+ flag = SetLegEquiped(legEquiped) || flag;
+ flag = SetHelmetEquiped(hash2, num) || flag;
+ flag = SetShoulderEquiped(hash3, variant) || flag;
+ flag = SetUtilityEquiped(utilityEquiped) || flag;
+ if (m_isPlayer)
+ {
+ flag = SetBeardEquiped(beardEquiped) || flag;
+ flag = SetBackEquiped(leftItem, rightItem, leftVariant) || flag;
+ if (m_helmetHideHair)
+ {
+ num = 0;
+ }
+ flag = SetHairEquiped(num) || flag;
+ }
+ if (flag)
+ {
+ UpdateLodgroup();
+ }
+ }
+
+ protected void UpdateLodgroup()
+ {
+ if (!(m_lodGroup == null))
+ {
+ Renderer[] componentsInChildren = m_visual.GetComponentsInChildren<Renderer>();
+ LOD[] lODs = m_lodGroup.GetLODs();
+ lODs[0].renderers = componentsInChildren;
+ m_lodGroup.SetLODs(lODs);
+ }
+ }
+
+ private bool SetRightHandEquiped(int hash)
+ {
+ if (m_currentRightItemHash == hash)
+ {
+ return false;
+ }
+ if ((bool)m_rightItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_rightItemInstance);
+ m_rightItemInstance = null;
+ }
+ m_currentRightItemHash = hash;
+ if (hash != 0)
+ {
+ m_rightItemInstance = AttachItem(hash, 0, m_rightHand);
+ }
+ return true;
+ }
+
+ private bool SetLeftHandEquiped(int hash, int variant)
+ {
+ if (m_currentLeftItemHash == hash && m_currentLeftItemVariant == variant)
+ {
+ return false;
+ }
+ if ((bool)m_leftItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_leftItemInstance);
+ m_leftItemInstance = null;
+ }
+ m_currentLeftItemHash = hash;
+ m_currentLeftItemVariant = variant;
+ if (hash != 0)
+ {
+ m_leftItemInstance = AttachItem(hash, variant, m_leftHand);
+ }
+ return true;
+ }
+
+ private bool SetBackEquiped(int leftItem, int rightItem, int leftVariant)
+ {
+ if (m_currentLeftBackItemHash == leftItem && m_currentRightBackItemHash == rightItem && m_currentLeftBackItemVariant == leftVariant)
+ {
+ return false;
+ }
+ if ((bool)m_leftBackItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_leftBackItemInstance);
+ m_leftBackItemInstance = null;
+ }
+ if ((bool)m_rightBackItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_rightBackItemInstance);
+ m_rightBackItemInstance = null;
+ }
+ m_currentLeftBackItemHash = leftItem;
+ m_currentRightBackItemHash = rightItem;
+ m_currentLeftBackItemVariant = leftVariant;
+ if (m_currentLeftBackItemHash != 0)
+ {
+ m_leftBackItemInstance = AttachBackItem(leftItem, leftVariant, rightHand: false);
+ }
+ if (m_currentRightBackItemHash != 0)
+ {
+ m_rightBackItemInstance = AttachBackItem(rightItem, 0, rightHand: true);
+ }
+ return true;
+ }
+
+ private GameObject AttachBackItem(int hash, int variant, bool rightHand)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Missing back attach item prefab: " + hash);
+ return null;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ switch ((component.m_itemData.m_shared.m_attachOverride != 0) ? component.m_itemData.m_shared.m_attachOverride : component.m_itemData.m_shared.m_itemType)
+ {
+ case ItemDrop.ItemData.ItemType.Torch:
+ if (rightHand)
+ {
+ return AttachItem(hash, variant, m_backMelee, enableEquipEffects: false);
+ }
+ return AttachItem(hash, variant, m_backTool, enableEquipEffects: false);
+ case ItemDrop.ItemData.ItemType.Bow:
+ return AttachItem(hash, variant, m_backBow);
+ case ItemDrop.ItemData.ItemType.Tool:
+ return AttachItem(hash, variant, m_backTool);
+ case ItemDrop.ItemData.ItemType.Attach_Atgeir:
+ return AttachItem(hash, variant, m_backAtgeir);
+ case ItemDrop.ItemData.ItemType.OneHandedWeapon:
+ return AttachItem(hash, variant, m_backMelee);
+ case ItemDrop.ItemData.ItemType.TwoHandedWeapon:
+ return AttachItem(hash, variant, m_backTwohandedMelee);
+ case ItemDrop.ItemData.ItemType.Shield:
+ return AttachItem(hash, variant, m_backShield);
+ default:
+ return null;
+ }
+ }
+
+ private bool SetChestEquiped(int hash)
+ {
+ if (m_currentChestItemHash == hash)
+ {
+ return false;
+ }
+ m_currentChestItemHash = hash;
+ if (m_bodyModel == null)
+ {
+ return true;
+ }
+ if (m_chestItemInstances != null)
+ {
+ foreach (GameObject chestItemInstance in m_chestItemInstances)
+ {
+ if ((bool)m_lodGroup)
+ {
+ Utils.RemoveFromLodgroup(m_lodGroup, chestItemInstance);
+ }
+ UnityEngine.Object.Destroy(chestItemInstance);
+ }
+ m_chestItemInstances = null;
+ m_bodyModel.material.SetTexture("_ChestTex", m_emptyBodyTexture);
+ m_bodyModel.material.SetTexture("_ChestBumpMap", null);
+ m_bodyModel.material.SetTexture("_ChestMetal", null);
+ }
+ if (m_currentChestItemHash == 0)
+ {
+ return true;
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Missing chest item " + hash);
+ return true;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ if ((bool)component.m_itemData.m_shared.m_armorMaterial)
+ {
+ m_bodyModel.material.SetTexture("_ChestTex", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_ChestTex"));
+ m_bodyModel.material.SetTexture("_ChestBumpMap", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_ChestBumpMap"));
+ m_bodyModel.material.SetTexture("_ChestMetal", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_ChestMetal"));
+ }
+ m_chestItemInstances = AttachArmor(hash);
+ return true;
+ }
+
+ private bool SetShoulderEquiped(int hash, int variant)
+ {
+ if (m_currentShoulderItemHash == hash && m_currenShoulderItemVariant == variant)
+ {
+ return false;
+ }
+ m_currentShoulderItemHash = hash;
+ m_currenShoulderItemVariant = variant;
+ if (m_bodyModel == null)
+ {
+ return true;
+ }
+ if (m_shoulderItemInstances != null)
+ {
+ foreach (GameObject shoulderItemInstance in m_shoulderItemInstances)
+ {
+ if ((bool)m_lodGroup)
+ {
+ Utils.RemoveFromLodgroup(m_lodGroup, shoulderItemInstance);
+ }
+ UnityEngine.Object.Destroy(shoulderItemInstance);
+ }
+ m_shoulderItemInstances = null;
+ }
+ if (m_currentShoulderItemHash == 0)
+ {
+ return true;
+ }
+ if (ObjectDB.instance.GetItemPrefab(hash) == null)
+ {
+ ZLog.Log("Missing shoulder item " + hash);
+ return true;
+ }
+ m_shoulderItemInstances = AttachArmor(hash, variant);
+ return true;
+ }
+
+ private bool SetLegEquiped(int hash)
+ {
+ if (m_currentLegItemHash == hash)
+ {
+ return false;
+ }
+ m_currentLegItemHash = hash;
+ if (m_bodyModel == null)
+ {
+ return true;
+ }
+ if (m_legItemInstances != null)
+ {
+ foreach (GameObject legItemInstance in m_legItemInstances)
+ {
+ UnityEngine.Object.Destroy(legItemInstance);
+ }
+ m_legItemInstances = null;
+ m_bodyModel.material.SetTexture("_LegsTex", m_emptyBodyTexture);
+ m_bodyModel.material.SetTexture("_LegsBumpMap", null);
+ m_bodyModel.material.SetTexture("_LegsMetal", null);
+ }
+ if (m_currentLegItemHash == 0)
+ {
+ return true;
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Missing legs item " + hash);
+ return true;
+ }
+ ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
+ if ((bool)component.m_itemData.m_shared.m_armorMaterial)
+ {
+ m_bodyModel.material.SetTexture("_LegsTex", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_LegsTex"));
+ m_bodyModel.material.SetTexture("_LegsBumpMap", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_LegsBumpMap"));
+ m_bodyModel.material.SetTexture("_LegsMetal", component.m_itemData.m_shared.m_armorMaterial.GetTexture("_LegsMetal"));
+ }
+ m_legItemInstances = AttachArmor(hash);
+ return true;
+ }
+
+ private bool SetBeardEquiped(int hash)
+ {
+ if (m_currentBeardItemHash == hash)
+ {
+ return false;
+ }
+ if ((bool)m_beardItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_beardItemInstance);
+ m_beardItemInstance = null;
+ }
+ m_currentBeardItemHash = hash;
+ if (hash != 0)
+ {
+ m_beardItemInstance = AttachItem(hash, 0, m_helmet);
+ }
+ return true;
+ }
+
+ private bool SetHairEquiped(int hash)
+ {
+ if (m_currentHairItemHash == hash)
+ {
+ return false;
+ }
+ if ((bool)m_hairItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_hairItemInstance);
+ m_hairItemInstance = null;
+ }
+ m_currentHairItemHash = hash;
+ if (hash != 0)
+ {
+ m_hairItemInstance = AttachItem(hash, 0, m_helmet);
+ }
+ return true;
+ }
+
+ private bool SetHelmetEquiped(int hash, int hairHash)
+ {
+ if (m_currentHelmetItemHash == hash)
+ {
+ return false;
+ }
+ if ((bool)m_helmetItemInstance)
+ {
+ UnityEngine.Object.Destroy(m_helmetItemInstance);
+ m_helmetItemInstance = null;
+ }
+ m_currentHelmetItemHash = hash;
+ m_helmetHideHair = HelmetHidesHair(hash);
+ if (hash != 0)
+ {
+ m_helmetItemInstance = AttachItem(hash, 0, m_helmet);
+ }
+ return true;
+ }
+
+ private bool SetUtilityEquiped(int hash)
+ {
+ if (m_currentUtilityItemHash == hash)
+ {
+ return false;
+ }
+ if (m_utilityItemInstances != null)
+ {
+ foreach (GameObject utilityItemInstance in m_utilityItemInstances)
+ {
+ if ((bool)m_lodGroup)
+ {
+ Utils.RemoveFromLodgroup(m_lodGroup, utilityItemInstance);
+ }
+ UnityEngine.Object.Destroy(utilityItemInstance);
+ }
+ m_utilityItemInstances = null;
+ }
+ m_currentUtilityItemHash = hash;
+ if (hash != 0)
+ {
+ m_utilityItemInstances = AttachArmor(hash);
+ }
+ return true;
+ }
+
+ private bool HelmetHidesHair(int itemHash)
+ {
+ if (itemHash == 0)
+ {
+ return false;
+ }
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash);
+ if (itemPrefab == null)
+ {
+ return false;
+ }
+ return itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_helmetHideHair;
+ }
+
+ private List<GameObject> AttachArmor(int itemHash, int variant = -1)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Missing attach item: " + itemHash + " ob:" + base.gameObject.name);
+ return null;
+ }
+ List<GameObject> list = new List<GameObject>();
+ int childCount = itemPrefab.transform.childCount;
+ for (int i = 0; i < childCount; i++)
+ {
+ Transform child = itemPrefab.transform.GetChild(i);
+ if (!child.gameObject.name.StartsWith("attach_"))
+ {
+ continue;
+ }
+ string text = child.gameObject.name.Substring(7);
+ GameObject gameObject;
+ if (text == "skin")
+ {
+ gameObject = UnityEngine.Object.Instantiate(child.gameObject, m_bodyModel.transform.position, m_bodyModel.transform.parent.rotation, m_bodyModel.transform.parent);
+ gameObject.SetActive(value: true);
+ SkinnedMeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
+ foreach (SkinnedMeshRenderer obj in componentsInChildren)
+ {
+ obj.rootBone = m_bodyModel.rootBone;
+ obj.bones = m_bodyModel.bones;
+ }
+ Cloth[] componentsInChildren2 = gameObject.GetComponentsInChildren<Cloth>();
+ foreach (Cloth cloth in componentsInChildren2)
+ {
+ if (m_clothColliders.Length != 0)
+ {
+ if (cloth.capsuleColliders.Length != 0)
+ {
+ List<CapsuleCollider> list2 = new List<CapsuleCollider>(m_clothColliders);
+ list2.AddRange(cloth.capsuleColliders);
+ cloth.capsuleColliders = list2.ToArray();
+ }
+ else
+ {
+ cloth.capsuleColliders = m_clothColliders;
+ }
+ }
+ }
+ }
+ else
+ {
+ Transform transform = Utils.FindChild(m_visual.transform, text);
+ if (transform == null)
+ {
+ ZLog.LogWarning("Missing joint " + text + " in item " + itemPrefab.name);
+ continue;
+ }
+ gameObject = UnityEngine.Object.Instantiate(child.gameObject);
+ gameObject.SetActive(value: true);
+ gameObject.transform.SetParent(transform);
+ gameObject.transform.localPosition = Vector3.zero;
+ gameObject.transform.localRotation = Quaternion.identity;
+ }
+ if (variant >= 0)
+ {
+ gameObject.GetComponentInChildren<IEquipmentVisual>()?.Setup(variant);
+ }
+ CleanupInstance(gameObject);
+ EnableEquipedEffects(gameObject);
+ list.Add(gameObject);
+ }
+ return list;
+ }
+
+ protected GameObject AttachItem(int itemHash, int variant, Transform joint, bool enableEquipEffects = true)
+ {
+ GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemHash);
+ if (itemPrefab == null)
+ {
+ ZLog.Log("Missing attach item: " + itemHash + " ob:" + base.gameObject.name + " joint:" + (joint ? joint.name : "none"));
+ return null;
+ }
+ GameObject gameObject = null;
+ int childCount = itemPrefab.transform.childCount;
+ for (int i = 0; i < childCount; i++)
+ {
+ Transform child = itemPrefab.transform.GetChild(i);
+ if (child.gameObject.name == "attach" || child.gameObject.name == "attach_skin")
+ {
+ gameObject = child.gameObject;
+ break;
+ }
+ }
+ if (gameObject == null)
+ {
+ return null;
+ }
+ GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject);
+ gameObject2.SetActive(value: true);
+ CleanupInstance(gameObject2);
+ if (enableEquipEffects)
+ {
+ EnableEquipedEffects(gameObject2);
+ }
+ if (gameObject.name == "attach_skin")
+ {
+ gameObject2.transform.SetParent(m_bodyModel.transform.parent);
+ gameObject2.transform.localPosition = Vector3.zero;
+ gameObject2.transform.localRotation = Quaternion.identity;
+ SkinnedMeshRenderer[] componentsInChildren = gameObject2.GetComponentsInChildren<SkinnedMeshRenderer>();
+ foreach (SkinnedMeshRenderer obj in componentsInChildren)
+ {
+ obj.rootBone = m_bodyModel.rootBone;
+ obj.bones = m_bodyModel.bones;
+ }
+ }
+ else
+ {
+ gameObject2.transform.SetParent(joint);
+ gameObject2.transform.localPosition = Vector3.zero;
+ gameObject2.transform.localRotation = Quaternion.identity;
+ }
+ gameObject2.GetComponentInChildren<IEquipmentVisual>()?.Setup(variant);
+ return gameObject2;
+ }
+
+ private void CleanupInstance(GameObject instance)
+ {
+ Collider[] componentsInChildren = instance.GetComponentsInChildren<Collider>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].enabled = false;
+ }
+ }
+
+ private void EnableEquipedEffects(GameObject instance)
+ {
+ Transform transform = instance.transform.Find("equiped");
+ if ((bool)transform)
+ {
+ transform.gameObject.SetActive(value: true);
+ }
+ }
+
+ public int GetModelIndex()
+ {
+ int result = m_modelIndex;
+ if (m_nview.IsValid())
+ {
+ result = m_nview.GetZDO().GetInt("ModelIndex");
+ }
+ return result;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterMark.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterMark.cs
new file mode 100644
index 0000000..92bf3f9
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterMark.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class WaterMark : MonoBehaviour
+{
+ public Text m_text;
+
+ private void Awake()
+ {
+ m_text.text = "Version: " + Version.GetVersionString();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterTrigger.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterTrigger.cs
new file mode 100644
index 0000000..4d100a6
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterTrigger.cs
@@ -0,0 +1,24 @@
+using UnityEngine;
+
+public class WaterTrigger : MonoBehaviour
+{
+ public EffectList m_effects = new EffectList();
+
+ public float m_cooldownDelay = 2f;
+
+ private float m_cooldownTimer;
+
+ private void Update()
+ {
+ m_cooldownTimer += Time.deltaTime;
+ if (m_cooldownTimer > m_cooldownDelay)
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(base.transform.position);
+ if (base.transform.position.y < waterLevel)
+ {
+ m_effects.Create(base.transform.position, base.transform.rotation, base.transform);
+ m_cooldownTimer = 0f;
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterVolume.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterVolume.cs
new file mode 100644
index 0000000..40187f2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WaterVolume.cs
@@ -0,0 +1,237 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class WaterVolume : MonoBehaviour
+{
+ private static Collider[] tempColliderArray = new Collider[256];
+
+ private float[] m_normalizedDepth = new float[4];
+
+ private BoxCollider m_collider;
+
+ public MeshRenderer m_waterSurface;
+
+ public Heightmap m_heightmap;
+
+ public float m_forceDepth = -1f;
+
+ public bool m_menuWater;
+
+ public bool m_useGlobalWind = true;
+
+ private static float m_waterTime = 0f;
+
+ private static int m_waterUpdateFrame = 0;
+
+ private static int m_waterVolumeMask = 0;
+
+ private static int _WaterTime = Shader.PropertyToID("_WaterTime");
+
+ private static int _depth = Shader.PropertyToID("_depth");
+
+ private static int _UseGlobalWind = Shader.PropertyToID("_UseGlobalWind");
+
+ private List<IWaterInteractable> m_inWater = new List<IWaterInteractable>();
+
+ private void Awake()
+ {
+ m_collider = GetComponent<BoxCollider>();
+ }
+
+ private void Start()
+ {
+ DetectWaterDepth();
+ SetupMaterial();
+ }
+
+ private void DetectWaterDepth()
+ {
+ if ((bool)m_heightmap)
+ {
+ float[] oceanDepth = m_heightmap.GetOceanDepth();
+ m_normalizedDepth[0] = Mathf.Clamp01(oceanDepth[0] / 10f);
+ m_normalizedDepth[1] = Mathf.Clamp01(oceanDepth[1] / 10f);
+ m_normalizedDepth[2] = Mathf.Clamp01(oceanDepth[2] / 10f);
+ m_normalizedDepth[3] = Mathf.Clamp01(oceanDepth[3] / 10f);
+ }
+ else
+ {
+ m_normalizedDepth[0] = m_forceDepth;
+ m_normalizedDepth[1] = m_forceDepth;
+ m_normalizedDepth[2] = m_forceDepth;
+ m_normalizedDepth[3] = m_forceDepth;
+ }
+ }
+
+ private void Update()
+ {
+ if (m_waterUpdateFrame != Time.frameCount)
+ {
+ m_waterUpdateFrame = Time.frameCount;
+ UpdateWaterTime(Time.deltaTime);
+ }
+ UpdateFloaters();
+ m_waterSurface.material.SetFloat(_WaterTime, m_waterTime);
+ }
+
+ private void UpdateWaterTime(float dt)
+ {
+ float num = (m_menuWater ? Time.time : ZNet.instance.GetWrappedDayTimeSeconds());
+ m_waterTime += dt;
+ if (Mathf.Abs(num - m_waterTime) > 10f)
+ {
+ m_waterTime = num;
+ }
+ m_waterTime = Mathf.Lerp(m_waterTime, num, 0.05f);
+ }
+
+ private void SetupMaterial()
+ {
+ if (m_forceDepth >= 0f)
+ {
+ m_waterSurface.material.SetFloatArray(_depth, new float[4] { m_forceDepth, m_forceDepth, m_forceDepth, m_forceDepth });
+ }
+ else
+ {
+ m_waterSurface.material.SetFloatArray(_depth, m_normalizedDepth);
+ }
+ m_waterSurface.material.SetFloat(_UseGlobalWind, m_useGlobalWind ? 1f : 0f);
+ }
+
+ public static float GetWaterLevel(Vector3 p, float waveFactor = 1f)
+ {
+ if (m_waterVolumeMask == 0)
+ {
+ m_waterVolumeMask = LayerMask.GetMask("WaterVolume");
+ }
+ int num = Physics.OverlapSphereNonAlloc(p, 0f, tempColliderArray, m_waterVolumeMask);
+ for (int i = 0; i < num; i++)
+ {
+ WaterVolume component = tempColliderArray[i].GetComponent<WaterVolume>();
+ if ((bool)component)
+ {
+ return component.GetWaterSurface(p, waveFactor);
+ }
+ }
+ return -10000f;
+ }
+
+ private float GetWaterSurface(Vector3 point, float waveFactor = 1f)
+ {
+ float wrappedDayTimeSeconds = ZNet.instance.GetWrappedDayTimeSeconds();
+ float depth = Depth(point);
+ float num = CalcWave(point, depth, wrappedDayTimeSeconds, waveFactor);
+ float num2 = base.transform.position.y + num;
+ if (Utils.LengthXZ(point) > 10500f && m_forceDepth < 0f)
+ {
+ num2 -= 100f;
+ }
+ return num2;
+ }
+
+ private float TrochSin(float x, float k)
+ {
+ return Mathf.Sin(x - Mathf.Cos(x) * k) * 0.5f + 0.5f;
+ }
+
+ private float CreateWave(Vector3 worldPos, float time, float waveSpeed, float waveLength, float waveHeight, Vector2 dir2d, float sharpness)
+ {
+ Vector3 normalized = new Vector3(dir2d.x, 0f, dir2d.y).normalized;
+ Vector3 vector = Vector3.Cross(normalized, Vector3.up);
+ Vector3 vector2 = -(worldPos.z * normalized + worldPos.x * vector);
+ return (TrochSin(time * waveSpeed + vector2.z * waveLength, sharpness) * TrochSin(time * waveSpeed * 0.123f + vector2.x * 0.13123f * waveLength, sharpness) - 0.2f) * waveHeight;
+ }
+
+ private float CalcWave(Vector3 worldPos, float depth, Vector4 wind, float _WaterTime, float waveFactor)
+ {
+ Vector3 vector = new Vector3(wind.x, wind.y, wind.z);
+ float w = wind.w;
+ float num = Mathf.Lerp(0f, w, depth);
+ float time = _WaterTime / 20f;
+ float num2 = CreateWave(worldPos, time, 10f, 0.04f, 8f, new Vector2(vector.x, vector.z), 0.5f);
+ float num3 = CreateWave(worldPos, time, 14.123f, 0.08f, 6f, new Vector2(1.0312f, 0.312f), 0.5f);
+ float num4 = CreateWave(worldPos, time, 22.312f, 0.1f, 4f, new Vector2(-0.123f, 1.12f), 0.5f);
+ float num5 = CreateWave(worldPos, time, 31.42f, 0.2f, 2f, new Vector2(0.423f, 0.124f), 0.5f);
+ float num6 = CreateWave(worldPos, time, 35.42f, 0.4f, 1f, new Vector2(0.123f, -0.64f), 0.5f);
+ float num7 = CreateWave(worldPos, time, 38.1223f, 1f, 0.8f, new Vector2(-0.523f, -0.64f), 0.7f);
+ float num8 = CreateWave(worldPos, time, 41.1223f, 1.2f, 0.6f * waveFactor, new Vector2(0.223f, 0.74f), 0.8f);
+ float num9 = CreateWave(worldPos, time, 51.5123f, 1.3f, 0.4f * waveFactor, new Vector2(0.923f, -0.24f), 0.9f);
+ float num10 = CreateWave(worldPos, time, 54.2f, 1.3f, 0.3f * waveFactor, new Vector2(-0.323f, 0.44f), 0.9f);
+ float num11 = CreateWave(worldPos, time, 56.123f, 1.5f, 0.2f * waveFactor, new Vector2(0.5312f, -0.812f), 0.9f);
+ return (num2 + num3 + num4 + num5 + num6 + num7 + num8 + num9 + num10 + num11) * num;
+ }
+
+ private float CalcWave(Vector3 worldPos, float depth, float _WaterTime, float waveFactor)
+ {
+ Vector4 wind = new Vector4(1f, 0f, 0f, 0f);
+ Vector4 wind2 = new Vector4(1f, 0f, 0f, 0f);
+ float alpha = 0f;
+ if (m_useGlobalWind)
+ {
+ EnvMan.instance.GetWindData(out wind, out wind2, out alpha);
+ }
+ float a = CalcWave(worldPos, depth, wind, _WaterTime, waveFactor);
+ float b = CalcWave(worldPos, depth, wind2, _WaterTime, waveFactor);
+ return Mathf.Lerp(a, b, alpha);
+ }
+
+ private float Depth(Vector3 point)
+ {
+ Vector3 vector = base.transform.InverseTransformPoint(point);
+ float value = (vector.x + m_collider.bounds.size.x / 2f) / m_collider.bounds.size.x;
+ float value2 = (vector.z + m_collider.bounds.size.z / 2f) / m_collider.bounds.size.z;
+ value = Mathf.Clamp01(value);
+ value2 = Mathf.Clamp01(value2);
+ float a = Mathf.Lerp(m_normalizedDepth[3], m_normalizedDepth[2], value);
+ float b = Mathf.Lerp(m_normalizedDepth[0], m_normalizedDepth[1], value);
+ return Mathf.Lerp(a, b, value2);
+ }
+
+ private void OnTriggerEnter(Collider collider)
+ {
+ IWaterInteractable component = collider.attachedRigidbody.GetComponent<IWaterInteractable>();
+ if (component != null && !m_inWater.Contains(component))
+ {
+ m_inWater.Add(component);
+ }
+ }
+
+ private void UpdateFloaters()
+ {
+ if (m_inWater.Count == 0)
+ {
+ return;
+ }
+ IWaterInteractable waterInteractable = null;
+ foreach (IWaterInteractable item in m_inWater)
+ {
+ if (item.IsOwner())
+ {
+ Transform transform = item.GetTransform();
+ if ((bool)transform)
+ {
+ float waterSurface = GetWaterSurface(transform.position);
+ item.SetInWater(waterSurface);
+ }
+ else
+ {
+ waterInteractable = item;
+ }
+ }
+ }
+ if (waterInteractable != null)
+ {
+ m_inWater.Remove(waterInteractable);
+ }
+ }
+
+ private void OnTriggerExit(Collider collider)
+ {
+ IWaterInteractable component = collider.attachedRigidbody.GetComponent<IWaterInteractable>();
+ if (component != null)
+ {
+ component.SetInWater(-10000f);
+ m_inWater.Remove(component);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WayStone.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WayStone.cs
new file mode 100644
index 0000000..21f0be7
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WayStone.cs
@@ -0,0 +1,71 @@
+using UnityEngine;
+
+public class WayStone : MonoBehaviour, Hoverable, Interactable
+{
+ [TextArea]
+ public string m_activateMessage = "You touch the cold stone surface and you think of home.";
+
+ public GameObject m_activeObject;
+
+ public EffectList m_activeEffect;
+
+ private void Awake()
+ {
+ m_activeObject.SetActive(value: false);
+ }
+
+ public string GetHoverText()
+ {
+ if (m_activeObject.activeSelf)
+ {
+ return "Activated waystone";
+ }
+ return Localization.instance.Localize("Waystone\n[<color=yellow><b>$KEY_Use</b></color>] Activate");
+ }
+
+ public string GetHoverName()
+ {
+ return "Waystone";
+ }
+
+ public bool Interact(Humanoid character, bool hold)
+ {
+ if (hold)
+ {
+ return false;
+ }
+ if (!m_activeObject.activeSelf)
+ {
+ character.Message(MessageHud.MessageType.Center, m_activateMessage);
+ m_activeObject.SetActive(value: true);
+ m_activeEffect.Create(base.gameObject.transform.position, base.gameObject.transform.rotation);
+ }
+ return true;
+ }
+
+ public bool UseItem(Humanoid user, ItemDrop.ItemData item)
+ {
+ return false;
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_activeObject.activeSelf && Game.instance != null)
+ {
+ Vector3 forward = GetSpawnPoint() - base.transform.position;
+ forward.y = 0f;
+ forward.Normalize();
+ m_activeObject.transform.rotation = Quaternion.LookRotation(forward);
+ }
+ }
+
+ private Vector3 GetSpawnPoint()
+ {
+ PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
+ if (playerProfile.HaveCustomSpawnPoint())
+ {
+ return playerProfile.GetCustomSpawnPoint();
+ }
+ return playerProfile.GetHomePoint();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTear.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTear.cs
new file mode 100644
index 0000000..118ba82
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTear.cs
@@ -0,0 +1,792 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class WearNTear : MonoBehaviour, IDestructible
+{
+ public enum MaterialType
+ {
+ Wood,
+ Stone,
+ Iron,
+ HardWood
+ }
+
+ private struct BoundData
+ {
+ public Vector3 m_pos;
+
+ public Quaternion m_rot;
+
+ public Vector3 m_size;
+ }
+
+ private struct OldMeshData
+ {
+ public Renderer m_renderer;
+
+ public Material[] m_materials;
+
+ public Color[] m_color;
+
+ public Color[] m_emissiveColor;
+ }
+
+ public static bool m_randomInitialDamage = false;
+
+ public Action m_onDestroyed;
+
+ public Action m_onDamaged;
+
+ [Header("Wear")]
+ public GameObject m_new;
+
+ public GameObject m_worn;
+
+ public GameObject m_broken;
+
+ public GameObject m_wet;
+
+ public bool m_noRoofWear = true;
+
+ public bool m_noSupportWear = true;
+
+ public MaterialType m_materialType;
+
+ public bool m_supports = true;
+
+ public Vector3 m_comOffset = Vector3.zero;
+
+ [Header("Destruction")]
+ public float m_health = 100f;
+
+ public HitData.DamageModifiers m_damages;
+
+ public float m_minDamageTreshold;
+
+ public float m_hitNoise;
+
+ public float m_destroyNoise;
+
+ [Header("Effects")]
+ public EffectList m_destroyedEffect = new EffectList();
+
+ public EffectList m_hitEffect = new EffectList();
+
+ public EffectList m_switchEffect = new EffectList();
+
+ public bool m_autoCreateFragments = true;
+
+ public GameObject[] m_fragmentRoots;
+
+ private const float m_noFireDrain = 0.0049603176f;
+
+ private const float m_noSupportDrain = 25f;
+
+ private const float m_rainDamageTime = 60f;
+
+ private const float m_rainDamage = 5f;
+
+ private const float m_comTestWidth = 0.2f;
+
+ private const float m_comMinAngle = 100f;
+
+ private const float m_minFireDistance = 20f;
+
+ private const int m_wearUpdateIntervalMinutes = 60;
+
+ private const float m_privateAreaModifier = 0.5f;
+
+ private static RaycastHit[] m_raycastHits = new RaycastHit[128];
+
+ private static Collider[] m_tempColliders = new Collider[128];
+
+ private static int m_rayMask = 0;
+
+ private static List<WearNTear> m_allInstances = new List<WearNTear>();
+
+ private static List<Vector3> m_tempSupportPoints = new List<Vector3>();
+
+ private static List<float> m_tempSupportPointValues = new List<float>();
+
+ private ZNetView m_nview;
+
+ private Collider[] m_colliders;
+
+ private float m_support = 1f;
+
+ private float m_createTime;
+
+ private int m_myIndex = -1;
+
+ private float m_rainTimer;
+
+ private Piece m_piece;
+
+ private List<BoundData> m_bounds;
+
+ private List<OldMeshData> m_oldMaterials;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_piece = GetComponent<Piece>();
+ if (m_nview.GetZDO() != null)
+ {
+ m_nview.Register<HitData>("WNTDamage", RPC_Damage);
+ m_nview.Register<float>("WNTHealthChanged", RPC_HealthChanged);
+ if (m_autoCreateFragments)
+ {
+ m_nview.Register("WNTCreateFragments", RPC_CreateFragments);
+ }
+ if (m_rayMask == 0)
+ {
+ m_rayMask = LayerMask.GetMask("piece", "Default", "static_solid", "Default_small", "terrain");
+ }
+ m_allInstances.Add(this);
+ m_myIndex = m_allInstances.Count - 1;
+ m_createTime = Time.time;
+ m_support = GetMaxSupport();
+ if (m_randomInitialDamage)
+ {
+ float value = UnityEngine.Random.Range(0.1f * m_health, m_health * 0.6f);
+ m_nview.GetZDO().Set("health", value);
+ }
+ UpdateVisual(triggerEffects: false);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (m_myIndex != -1)
+ {
+ m_allInstances[m_myIndex] = m_allInstances[m_allInstances.Count - 1];
+ m_allInstances[m_myIndex].m_myIndex = m_myIndex;
+ m_allInstances.RemoveAt(m_allInstances.Count - 1);
+ }
+ }
+
+ public bool Repair()
+ {
+ if (m_nview.GetZDO().GetFloat("health", m_health) >= m_health)
+ {
+ return false;
+ }
+ m_nview.ClaimOwnership();
+ m_nview.GetZDO().Set("health", m_health);
+ m_nview.InvokeRPC(ZNetView.Everybody, "WNTHealthChanged", m_health);
+ return true;
+ }
+
+ private float GetSupport()
+ {
+ if (!m_nview.IsValid())
+ {
+ return GetMaxSupport();
+ }
+ if (!m_nview.HasOwner())
+ {
+ return GetMaxSupport();
+ }
+ if (m_nview.IsOwner())
+ {
+ return m_support;
+ }
+ return m_nview.GetZDO().GetFloat("support", GetMaxSupport());
+ }
+
+ private float GetSupportColorValue()
+ {
+ float support = GetSupport();
+ GetMaterialProperties(out var maxSupport, out var minSupport, out var _, out var _);
+ if (support >= maxSupport)
+ {
+ return -1f;
+ }
+ support -= minSupport;
+ return Mathf.Clamp01(support / (maxSupport * 0.5f - minSupport));
+ }
+
+ public void OnPlaced()
+ {
+ m_createTime = -1f;
+ }
+
+ private List<Renderer> GetHighlightRenderers()
+ {
+ MeshRenderer[] componentsInChildren = GetComponentsInChildren<MeshRenderer>(includeInactive: true);
+ SkinnedMeshRenderer[] componentsInChildren2 = GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
+ List<Renderer> list = new List<Renderer>();
+ list.AddRange(componentsInChildren);
+ list.AddRange(componentsInChildren2);
+ return list;
+ }
+
+ public void Highlight()
+ {
+ if (m_oldMaterials == null)
+ {
+ m_oldMaterials = new List<OldMeshData>();
+ foreach (Renderer highlightRenderer in GetHighlightRenderers())
+ {
+ OldMeshData item = default(OldMeshData);
+ item.m_materials = highlightRenderer.sharedMaterials;
+ item.m_color = new Color[item.m_materials.Length];
+ item.m_emissiveColor = new Color[item.m_materials.Length];
+ for (int i = 0; i < item.m_materials.Length; i++)
+ {
+ if (item.m_materials[i].HasProperty("_Color"))
+ {
+ item.m_color[i] = item.m_materials[i].GetColor("_Color");
+ }
+ if (item.m_materials[i].HasProperty("_EmissionColor"))
+ {
+ item.m_emissiveColor[i] = item.m_materials[i].GetColor("_EmissionColor");
+ }
+ }
+ item.m_renderer = highlightRenderer;
+ m_oldMaterials.Add(item);
+ }
+ }
+ float supportColorValue = GetSupportColorValue();
+ Color color = new Color(0.6f, 0.8f, 1f);
+ if (supportColorValue >= 0f)
+ {
+ color = Color.Lerp(new Color(1f, 0f, 0f), new Color(0f, 1f, 0f), supportColorValue);
+ Color.RGBToHSV(color, out var H, out var S, out var V);
+ S = Mathf.Lerp(1f, 0.5f, supportColorValue);
+ V = Mathf.Lerp(1.2f, 0.9f, supportColorValue);
+ color = Color.HSVToRGB(H, S, V);
+ }
+ foreach (OldMeshData oldMaterial in m_oldMaterials)
+ {
+ if ((bool)oldMaterial.m_renderer)
+ {
+ Material[] materials = oldMaterial.m_renderer.materials;
+ foreach (Material obj in materials)
+ {
+ obj.SetColor("_EmissionColor", color * 0.4f);
+ obj.color = color;
+ }
+ }
+ }
+ CancelInvoke("ResetHighlight");
+ Invoke("ResetHighlight", 0.2f);
+ }
+
+ private void ResetHighlight()
+ {
+ if (m_oldMaterials == null)
+ {
+ return;
+ }
+ foreach (OldMeshData oldMaterial in m_oldMaterials)
+ {
+ if (!oldMaterial.m_renderer)
+ {
+ continue;
+ }
+ Material[] materials = oldMaterial.m_renderer.materials;
+ if (materials.Length == 0)
+ {
+ continue;
+ }
+ if (materials[0] == oldMaterial.m_materials[0])
+ {
+ if (materials.Length != oldMaterial.m_color.Length)
+ {
+ continue;
+ }
+ for (int i = 0; i < materials.Length; i++)
+ {
+ if (materials[i].HasProperty("_Color"))
+ {
+ materials[i].SetColor("_Color", oldMaterial.m_color[i]);
+ }
+ if (materials[i].HasProperty("_EmissionColor"))
+ {
+ materials[i].SetColor("_EmissionColor", oldMaterial.m_emissiveColor[i]);
+ }
+ }
+ }
+ else if (materials.Length == oldMaterial.m_materials.Length)
+ {
+ oldMaterial.m_renderer.materials = oldMaterial.m_materials;
+ }
+ }
+ m_oldMaterials = null;
+ }
+
+ private void SetupColliders()
+ {
+ m_colliders = GetComponentsInChildren<Collider>(includeInactive: true);
+ m_bounds = new List<BoundData>();
+ Collider[] colliders = m_colliders;
+ foreach (Collider collider in colliders)
+ {
+ if (!collider.isTrigger)
+ {
+ BoundData item = default(BoundData);
+ if (collider is BoxCollider)
+ {
+ BoxCollider boxCollider = collider as BoxCollider;
+ item.m_rot = boxCollider.transform.rotation;
+ item.m_pos = boxCollider.transform.position + boxCollider.transform.TransformVector(boxCollider.center);
+ item.m_size = new Vector3(boxCollider.transform.lossyScale.x * boxCollider.size.x, boxCollider.transform.lossyScale.y * boxCollider.size.y, boxCollider.transform.lossyScale.z * boxCollider.size.z);
+ }
+ else
+ {
+ item.m_rot = Quaternion.identity;
+ item.m_pos = collider.bounds.center;
+ item.m_size = collider.bounds.size;
+ }
+ item.m_size.x += 0.3f;
+ item.m_size.y += 0.3f;
+ item.m_size.z += 0.3f;
+ item.m_size *= 0.5f;
+ m_bounds.Add(item);
+ }
+ }
+ }
+
+ private bool ShouldUpdate()
+ {
+ if (!(m_createTime < 0f))
+ {
+ return Time.time - m_createTime > 30f;
+ }
+ return true;
+ }
+
+ public void UpdateWear()
+ {
+ if (!m_nview.IsValid())
+ {
+ return;
+ }
+ if (m_nview.IsOwner() && ShouldUpdate())
+ {
+ if (ZNetScene.instance.OutsideActiveArea(base.transform.position))
+ {
+ m_support = GetMaxSupport();
+ m_nview.GetZDO().Set("support", m_support);
+ return;
+ }
+ float num = 0f;
+ bool flag = HaveRoof();
+ bool flag2 = EnvMan.instance.IsWet() && !flag;
+ if ((bool)m_wet)
+ {
+ m_wet.SetActive(flag2);
+ }
+ if (m_noRoofWear && GetHealthPercentage() > 0.5f)
+ {
+ if (flag2 || IsUnderWater())
+ {
+ if (m_rainTimer == 0f)
+ {
+ m_rainTimer = Time.time;
+ }
+ else if (Time.time - m_rainTimer > 60f)
+ {
+ m_rainTimer = Time.time;
+ num += 5f;
+ }
+ }
+ else
+ {
+ m_rainTimer = 0f;
+ }
+ }
+ if (m_noSupportWear)
+ {
+ UpdateSupport();
+ if (!HaveSupport())
+ {
+ num = 100f;
+ }
+ }
+ if (num > 0f && !CanBeRemoved())
+ {
+ num = 0f;
+ }
+ if (num > 0f)
+ {
+ float damage = num / 100f * m_health;
+ ApplyDamage(damage);
+ }
+ }
+ UpdateVisual(triggerEffects: true);
+ }
+
+ private Vector3 GetCOM()
+ {
+ return base.transform.position + base.transform.rotation * m_comOffset;
+ }
+
+ private void UpdateSupport()
+ {
+ if (m_colliders == null)
+ {
+ SetupColliders();
+ }
+ GetMaterialProperties(out var maxSupport, out var _, out var horizontalLoss, out var verticalLoss);
+ m_tempSupportPoints.Clear();
+ m_tempSupportPointValues.Clear();
+ Vector3 cOM = GetCOM();
+ float a = 0f;
+ foreach (BoundData bound in m_bounds)
+ {
+ int num = Physics.OverlapBoxNonAlloc(bound.m_pos, bound.m_size, m_tempColliders, bound.m_rot, m_rayMask);
+ for (int i = 0; i < num; i++)
+ {
+ Collider collider = m_tempColliders[i];
+ if (m_colliders.Contains(collider) || collider.attachedRigidbody != null || collider.isTrigger)
+ {
+ continue;
+ }
+ WearNTear componentInParent = collider.GetComponentInParent<WearNTear>();
+ if (componentInParent == null)
+ {
+ m_support = maxSupport;
+ m_nview.GetZDO().Set("support", m_support);
+ return;
+ }
+ if (!componentInParent.m_supports)
+ {
+ continue;
+ }
+ float num2 = Vector3.Distance(cOM, componentInParent.transform.position) + 0.1f;
+ float support = componentInParent.GetSupport();
+ a = Mathf.Max(a, support - horizontalLoss * num2 * support);
+ Vector3 vector = FindSupportPoint(cOM, componentInParent, collider);
+ if (vector.y < cOM.y + 0.05f)
+ {
+ Vector3 normalized = (vector - cOM).normalized;
+ if (normalized.y < 0f)
+ {
+ float t = Mathf.Acos(1f - Mathf.Abs(normalized.y)) / ((float)Math.PI / 2f);
+ float num3 = Mathf.Lerp(horizontalLoss, verticalLoss, t);
+ float b = support - num3 * num2 * support;
+ a = Mathf.Max(a, b);
+ }
+ float item = support - verticalLoss * num2 * support;
+ m_tempSupportPoints.Add(vector);
+ m_tempSupportPointValues.Add(item);
+ }
+ }
+ }
+ if (m_tempSupportPoints.Count > 0 && m_tempSupportPoints.Count >= 2)
+ {
+ for (int j = 0; j < m_tempSupportPoints.Count; j++)
+ {
+ Vector3 from = m_tempSupportPoints[j] - cOM;
+ from.y = 0f;
+ for (int k = 0; k < m_tempSupportPoints.Count; k++)
+ {
+ if (j != k)
+ {
+ Vector3 to = m_tempSupportPoints[k] - cOM;
+ to.y = 0f;
+ if (Vector3.Angle(from, to) >= 100f)
+ {
+ float b2 = (m_tempSupportPointValues[j] + m_tempSupportPointValues[k]) * 0.5f;
+ a = Mathf.Max(a, b2);
+ }
+ }
+ }
+ }
+ }
+ m_support = Mathf.Min(a, maxSupport);
+ m_nview.GetZDO().Set("support", m_support);
+ }
+
+ private Vector3 FindSupportPoint(Vector3 com, WearNTear wnt, Collider otherCollider)
+ {
+ MeshCollider meshCollider = otherCollider as MeshCollider;
+ if (meshCollider != null && !meshCollider.convex)
+ {
+ if (meshCollider.Raycast(new Ray(com, Vector3.down), out var hitInfo, 10f))
+ {
+ return hitInfo.point;
+ }
+ return (com + wnt.GetCOM()) * 0.5f;
+ }
+ return otherCollider.ClosestPoint(com);
+ }
+
+ private bool HaveSupport()
+ {
+ return m_support >= GetMinSupport();
+ }
+
+ private bool IsUnderWater()
+ {
+ float waterLevel = WaterVolume.GetWaterLevel(base.transform.position);
+ return base.transform.position.y < waterLevel;
+ }
+
+ private bool HaveRoof()
+ {
+ int num = Physics.SphereCastNonAlloc(base.transform.position, 0.1f, Vector3.up, m_raycastHits, 100f, m_rayMask);
+ for (int i = 0; i < num; i++)
+ {
+ RaycastHit raycastHit = m_raycastHits[i];
+ if (!raycastHit.collider.gameObject.CompareTag("leaky"))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void RPC_HealthChanged(long peer, float health)
+ {
+ float health2 = health / m_health;
+ SetHealthVisual(health2, triggerEffects: true);
+ }
+
+ private void UpdateVisual(bool triggerEffects)
+ {
+ if (m_nview.IsValid())
+ {
+ SetHealthVisual(GetHealthPercentage(), triggerEffects);
+ }
+ }
+
+ private void SetHealthVisual(float health, bool triggerEffects)
+ {
+ if (m_worn == null && m_broken == null && m_new == null)
+ {
+ return;
+ }
+ if (health > 0.75f)
+ {
+ if (m_worn != m_new)
+ {
+ m_worn.SetActive(value: false);
+ }
+ if (m_broken != m_new)
+ {
+ m_broken.SetActive(value: false);
+ }
+ m_new.SetActive(value: true);
+ }
+ else if (health > 0.25f)
+ {
+ if (triggerEffects && !m_worn.activeSelf)
+ {
+ m_switchEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ }
+ if (m_new != m_worn)
+ {
+ m_new.SetActive(value: false);
+ }
+ if (m_broken != m_worn)
+ {
+ m_broken.SetActive(value: false);
+ }
+ m_worn.SetActive(value: true);
+ }
+ else
+ {
+ if (triggerEffects && !m_broken.activeSelf)
+ {
+ m_switchEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ }
+ if (m_new != m_broken)
+ {
+ m_new.SetActive(value: false);
+ }
+ if (m_worn != m_broken)
+ {
+ m_worn.SetActive(value: false);
+ }
+ m_broken.SetActive(value: true);
+ }
+ }
+
+ public float GetHealthPercentage()
+ {
+ if (!m_nview.IsValid())
+ {
+ return 1f;
+ }
+ return Mathf.Clamp01(m_nview.GetZDO().GetFloat("health", m_health) / m_health);
+ }
+
+ public DestructibleType GetDestructibleType()
+ {
+ return DestructibleType.Default;
+ }
+
+ public void Damage(HitData hit)
+ {
+ if (m_nview.IsValid())
+ {
+ m_nview.InvokeRPC("WNTDamage", hit);
+ }
+ }
+
+ private bool CanBeRemoved()
+ {
+ if ((bool)m_piece)
+ {
+ return m_piece.CanBeRemoved();
+ }
+ return true;
+ }
+
+ private void RPC_Damage(long sender, HitData hit)
+ {
+ if (!m_nview.IsOwner() || m_nview.GetZDO().GetFloat("health", m_health) <= 0f)
+ {
+ return;
+ }
+ hit.ApplyResistance(m_damages, out var significantModifier);
+ float totalDamage = hit.GetTotalDamage();
+ if ((bool)m_piece && m_piece.IsPlacedByPlayer())
+ {
+ PrivateArea.CheckInPrivateArea(base.transform.position, flash: true);
+ }
+ DamageText.instance.ShowText(significantModifier, hit.m_point, totalDamage);
+ if (totalDamage <= 0f)
+ {
+ return;
+ }
+ ApplyDamage(totalDamage);
+ m_hitEffect.Create(hit.m_point, Quaternion.identity, base.transform);
+ if (m_hitNoise > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(hit.m_point, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(m_hitNoise);
+ }
+ }
+ if (m_onDamaged != null)
+ {
+ m_onDamaged();
+ }
+ }
+
+ public bool ApplyDamage(float damage)
+ {
+ float @float = m_nview.GetZDO().GetFloat("health", m_health);
+ if (@float <= 0f)
+ {
+ return false;
+ }
+ @float -= damage;
+ m_nview.GetZDO().Set("health", @float);
+ if (@float <= 0f)
+ {
+ Destroy();
+ }
+ else
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "WNTHealthChanged", @float);
+ }
+ return true;
+ }
+
+ public void Destroy()
+ {
+ m_nview.GetZDO().Set("health", 0f);
+ if ((bool)m_piece)
+ {
+ m_piece.DropResources();
+ }
+ if (m_onDestroyed != null)
+ {
+ m_onDestroyed();
+ }
+ if (m_destroyNoise > 0f)
+ {
+ Player closestPlayer = Player.GetClosestPlayer(base.transform.position, 10f);
+ if ((bool)closestPlayer)
+ {
+ closestPlayer.AddNoise(m_destroyNoise);
+ }
+ }
+ m_destroyedEffect.Create(base.transform.position, base.transform.rotation, base.transform);
+ if (m_autoCreateFragments)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "WNTCreateFragments");
+ }
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+
+ private void RPC_CreateFragments(long peer)
+ {
+ ResetHighlight();
+ if (m_fragmentRoots != null && m_fragmentRoots.Length != 0)
+ {
+ GameObject[] fragmentRoots = m_fragmentRoots;
+ foreach (GameObject obj in fragmentRoots)
+ {
+ obj.SetActive(value: true);
+ Destructible.CreateFragments(obj, visibleOnly: false);
+ }
+ }
+ else
+ {
+ Destructible.CreateFragments(base.gameObject);
+ }
+ }
+
+ private float GetMaxSupport()
+ {
+ GetMaterialProperties(out var maxSupport, out var _, out var _, out var _);
+ return maxSupport;
+ }
+
+ private float GetMinSupport()
+ {
+ GetMaterialProperties(out var _, out var minSupport, out var _, out var _);
+ return minSupport;
+ }
+
+ private void GetMaterialProperties(out float maxSupport, out float minSupport, out float horizontalLoss, out float verticalLoss)
+ {
+ switch (m_materialType)
+ {
+ case MaterialType.Wood:
+ maxSupport = 100f;
+ minSupport = 10f;
+ verticalLoss = 0.125f;
+ horizontalLoss = 0.2f;
+ break;
+ case MaterialType.HardWood:
+ maxSupport = 140f;
+ minSupport = 10f;
+ verticalLoss = 0.1f;
+ horizontalLoss = 1f / 6f;
+ break;
+ case MaterialType.Stone:
+ maxSupport = 1000f;
+ minSupport = 100f;
+ verticalLoss = 0.125f;
+ horizontalLoss = 1f;
+ break;
+ case MaterialType.Iron:
+ maxSupport = 1500f;
+ minSupport = 20f;
+ verticalLoss = 1f / 13f;
+ horizontalLoss = 1f / 13f;
+ break;
+ default:
+ maxSupport = 0f;
+ minSupport = 0f;
+ verticalLoss = 0f;
+ horizontalLoss = 0f;
+ break;
+ }
+ }
+
+ public static List<WearNTear> GetAllInstaces()
+ {
+ return m_allInstances;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTearUpdater.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTearUpdater.cs
new file mode 100644
index 0000000..8225e2e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WearNTearUpdater.cs
@@ -0,0 +1,41 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class WearNTearUpdater : MonoBehaviour
+{
+ private const int m_updatesPerFrame = 50;
+
+ private void Awake()
+ {
+ StartCoroutine("UpdateWear");
+ }
+
+ private IEnumerator UpdateWear()
+ {
+ while (true)
+ {
+ List<WearNTear> instances = WearNTear.GetAllInstaces();
+ int index = 0;
+ while (index < instances.Count)
+ {
+ for (int i = 0; i < 50; i++)
+ {
+ if (instances.Count == 0)
+ {
+ break;
+ }
+ if (index >= instances.Count)
+ {
+ break;
+ }
+ instances[index].UpdateWear();
+ int num = index + 1;
+ index = num;
+ }
+ yield return null;
+ }
+ yield return new WaitForSeconds(0.5f);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Windmill.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Windmill.cs
new file mode 100644
index 0000000..1420e82
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/Windmill.cs
@@ -0,0 +1,91 @@
+using UnityEngine;
+
+public class Windmill : MonoBehaviour
+{
+ public Transform m_propeller;
+
+ public Transform m_grindstone;
+
+ public Transform m_bom;
+
+ public AudioSource[] m_sfxLoops;
+
+ public GameObject m_propellerAOE;
+
+ public float m_minAOEPropellerSpeed = 5f;
+
+ public float m_bomRotationSpeed = 10f;
+
+ public float m_propellerRotationSpeed = 10f;
+
+ public float m_grindstoneRotationSpeed = 10f;
+
+ public float m_minWindSpeed = 0.1f;
+
+ public float m_minPitch = 1f;
+
+ public float m_maxPitch = 1.5f;
+
+ public float m_maxPitchVel = 10f;
+
+ public float m_maxVol = 1f;
+
+ public float m_maxVolVel = 10f;
+
+ public float m_audioChangeSpeed = 2f;
+
+ private float m_cover;
+
+ private float m_propAngle;
+
+ private float m_grindStoneAngle;
+
+ private Smelter m_smelter;
+
+ private void Start()
+ {
+ m_smelter = GetComponent<Smelter>();
+ InvokeRepeating("CheckCover", 0.1f, 5f);
+ }
+
+ private void Update()
+ {
+ Quaternion to = Quaternion.LookRotation(-EnvMan.instance.GetWindDir());
+ float powerOutput = GetPowerOutput();
+ m_bom.rotation = Quaternion.RotateTowards(m_bom.rotation, to, m_bomRotationSpeed * powerOutput * Time.deltaTime);
+ float num = powerOutput * m_propellerRotationSpeed;
+ m_propAngle += num * Time.deltaTime;
+ m_propeller.localRotation = Quaternion.Euler(0f, 0f, m_propAngle);
+ if (m_smelter == null || m_smelter.IsActive())
+ {
+ m_grindStoneAngle += powerOutput * m_grindstoneRotationSpeed * Time.deltaTime;
+ }
+ m_grindstone.localRotation = Quaternion.Euler(0f, m_grindStoneAngle, 0f);
+ m_propellerAOE.SetActive(Mathf.Abs(num) > m_minAOEPropellerSpeed);
+ UpdateAudio(Time.deltaTime);
+ }
+
+ public float GetPowerOutput()
+ {
+ float num = Utils.LerpStep(m_minWindSpeed, 1f, EnvMan.instance.GetWindIntensity());
+ return (1f - m_cover) * num;
+ }
+
+ private void CheckCover()
+ {
+ Cover.GetCoverForPoint(m_propeller.transform.position, out m_cover, out var _);
+ }
+
+ private void UpdateAudio(float dt)
+ {
+ float powerOutput = GetPowerOutput();
+ float target = Mathf.Lerp(m_minPitch, m_maxPitch, Mathf.Clamp01(powerOutput / m_maxPitchVel));
+ float target2 = m_maxVol * Mathf.Clamp01(powerOutput / m_maxVolVel);
+ AudioSource[] sfxLoops = m_sfxLoops;
+ foreach (AudioSource obj in sfxLoops)
+ {
+ obj.volume = Mathf.MoveTowards(obj.volume, target2, m_audioChangeSpeed * dt);
+ obj.pitch = Mathf.MoveTowards(obj.pitch, target, m_audioChangeSpeed * dt);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/World.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/World.cs
new file mode 100644
index 0000000..6fb1408
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/World.cs
@@ -0,0 +1,236 @@
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public class World
+{
+ public string m_name = "";
+
+ public string m_seedName = "";
+
+ public int m_seed;
+
+ public long m_uid;
+
+ public int m_worldGenVersion;
+
+ public bool m_menu;
+
+ public bool m_loadError;
+
+ public bool m_versionError;
+
+ private string m_worldSavePath = "";
+
+ public World()
+ {
+ m_worldSavePath = GetWorldSavePath();
+ }
+
+ public World(string name, bool loadError, bool versionError)
+ {
+ m_name = name;
+ m_loadError = loadError;
+ m_versionError = versionError;
+ m_worldSavePath = GetWorldSavePath();
+ }
+
+ public World(string name, string seed)
+ {
+ m_name = name;
+ m_seedName = seed;
+ m_seed = ((!(m_seedName == "")) ? m_seedName.GetStableHashCode() : 0);
+ m_uid = name.GetStableHashCode() + Utils.GenerateUID();
+ m_worldGenVersion = Version.m_worldGenVersion;
+ m_worldSavePath = GetWorldSavePath();
+ }
+
+ private static string GetWorldSavePath()
+ {
+ return Application.persistentDataPath + "/worlds";
+ }
+
+ public static List<World> GetWorldList()
+ {
+ string[] array;
+ try
+ {
+ array = Directory.GetFiles(GetWorldSavePath(), "*.fwl");
+ }
+ catch
+ {
+ array = new string[0];
+ }
+ List<World> list = new List<World>();
+ string[] array2 = array;
+ for (int i = 0; i < array2.Length; i++)
+ {
+ World world = LoadWorld(Path.GetFileNameWithoutExtension(array2[i]));
+ if (world != null)
+ {
+ list.Add(world);
+ }
+ }
+ return list;
+ }
+
+ public static void RemoveWorld(string name)
+ {
+ try
+ {
+ string text = GetWorldSavePath() + "/" + name;
+ File.Delete(text + ".fwl");
+ File.Delete(text + ".db");
+ }
+ catch
+ {
+ }
+ }
+
+ public string GetDBPath()
+ {
+ return m_worldSavePath + "/" + m_name + ".db";
+ }
+
+ public string GetMetaPath()
+ {
+ return m_worldSavePath + "/" + m_name + ".fwl";
+ }
+
+ public static string GetMetaPath(string name)
+ {
+ return GetWorldSavePath() + "/" + name + ".fwl";
+ }
+
+ public static bool HaveWorld(string name)
+ {
+ return File.Exists(string.Concat(GetWorldSavePath() + "/" + name, ".fwl"));
+ }
+
+ public static World GetMenuWorld()
+ {
+ return new World("menu", "")
+ {
+ m_menu = true
+ };
+ }
+
+ public static World GetEditorWorld()
+ {
+ return new World("editor", "");
+ }
+
+ public static string GenerateSeed()
+ {
+ string text = "";
+ for (int i = 0; i < 10; i++)
+ {
+ text += "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ023456789"[Random.Range(0, "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ023456789".Length)];
+ }
+ return text;
+ }
+
+ public static World GetCreateWorld(string name)
+ {
+ ZLog.Log("Get create world " + name);
+ World world = LoadWorld(name);
+ if (!world.m_loadError && !world.m_versionError)
+ {
+ return world;
+ }
+ ZLog.Log(" creating");
+ world = new World(name, GenerateSeed());
+ world.SaveWorldMetaData();
+ return world;
+ }
+
+ public static World GetDevWorld()
+ {
+ World world = LoadWorld("DevWorld");
+ if (!world.m_loadError && !world.m_versionError)
+ {
+ return world;
+ }
+ world = new World("DevWorld", "");
+ world.SaveWorldMetaData();
+ return world;
+ }
+
+ public void SaveWorldMetaData()
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(Version.m_worldVersion);
+ zPackage.Write(m_name);
+ zPackage.Write(m_seedName);
+ zPackage.Write(m_seed);
+ zPackage.Write(m_uid);
+ zPackage.Write(m_worldGenVersion);
+ Directory.CreateDirectory(m_worldSavePath);
+ string metaPath = GetMetaPath();
+ string text = metaPath + ".new";
+ string text2 = metaPath + ".old";
+ FileStream fileStream = File.Create(text);
+ BinaryWriter binaryWriter = new BinaryWriter(fileStream);
+ byte[] array = zPackage.GetArray();
+ binaryWriter.Write(array.Length);
+ binaryWriter.Write(array);
+ fileStream.Dispose();
+ if (File.Exists(metaPath))
+ {
+ if (File.Exists(text2))
+ {
+ File.Delete(text2);
+ }
+ File.Move(metaPath, text2);
+ }
+ File.Move(text, metaPath);
+ }
+
+ public static World LoadWorld(string name)
+ {
+ FileStream fileStream = null;
+ try
+ {
+ fileStream = File.OpenRead(GetMetaPath(name));
+ }
+ catch
+ {
+ fileStream?.Dispose();
+ ZLog.Log(" failed to load " + name);
+ return new World(name, loadError: true, versionError: false);
+ }
+ byte[] data;
+ try
+ {
+ BinaryReader binaryReader = new BinaryReader(fileStream);
+ int count = binaryReader.ReadInt32();
+ data = binaryReader.ReadBytes(count);
+ }
+ catch
+ {
+ ZLog.LogWarning(" error loading world " + name);
+ return new World(name, loadError: true, versionError: false);
+ }
+ finally
+ {
+ fileStream?.Dispose();
+ }
+ ZPackage zPackage = new ZPackage(data);
+ int num = zPackage.ReadInt();
+ if (!Version.IsWorldVersionCompatible(num))
+ {
+ ZLog.Log("incompatible world version " + num);
+ return new World(name, loadError: false, versionError: true);
+ }
+ World world = new World();
+ world.m_name = zPackage.ReadString();
+ world.m_seedName = zPackage.ReadString();
+ world.m_seed = zPackage.ReadInt();
+ world.m_uid = zPackage.ReadLong();
+ if (num >= 26)
+ {
+ world.m_worldGenVersion = zPackage.ReadInt();
+ }
+ return world;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WorldGenerator.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WorldGenerator.cs
new file mode 100644
index 0000000..7d96344
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/WorldGenerator.cs
@@ -0,0 +1,1069 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using UnityEngine;
+
+public class WorldGenerator
+{
+ public class River
+ {
+ public Vector2 p0;
+
+ public Vector2 p1;
+
+ public Vector2 center;
+
+ public float widthMin;
+
+ public float widthMax;
+
+ public float curveWidth;
+
+ public float curveWavelength;
+ }
+
+ public struct RiverPoint
+ {
+ public Vector2 p;
+
+ public float w;
+
+ public float w2;
+
+ public RiverPoint(Vector2 p_p, float p_w)
+ {
+ p = p_p;
+ w = p_w;
+ w2 = p_w * p_w;
+ }
+ }
+
+ private const float m_waterTreshold = 0.05f;
+
+ private static WorldGenerator m_instance;
+
+ private World m_world;
+
+ private int m_version;
+
+ private float m_offset0;
+
+ private float m_offset1;
+
+ private float m_offset2;
+
+ private float m_offset3;
+
+ private float m_offset4;
+
+ private int m_riverSeed;
+
+ private int m_streamSeed;
+
+ private List<Vector2> m_mountains;
+
+ private List<Vector2> m_lakes;
+
+ private List<River> m_rivers = new List<River>();
+
+ private List<River> m_streams = new List<River>();
+
+ private Dictionary<Vector2i, RiverPoint[]> m_riverPoints = new Dictionary<Vector2i, RiverPoint[]>();
+
+ private RiverPoint[] m_cachedRiverPoints;
+
+ private Vector2i m_cachedRiverGrid = new Vector2i(-999999, -999999);
+
+ private ReaderWriterLockSlim m_riverCacheLock = new ReaderWriterLockSlim();
+
+ private List<Heightmap.Biome> m_biomes = new List<Heightmap.Biome>();
+
+ private const float riverGridSize = 64f;
+
+ private const float minRiverWidth = 60f;
+
+ private const float maxRiverWidth = 100f;
+
+ private const float minRiverCurveWidth = 50f;
+
+ private const float maxRiverCurveWidth = 80f;
+
+ private const float minRiverCurveWaveLength = 50f;
+
+ private const float maxRiverCurveWaveLength = 70f;
+
+ private const int streams = 3000;
+
+ private const float streamWidth = 20f;
+
+ private const float meadowsMaxDistance = 5000f;
+
+ private const float minDeepForestNoise = 0.4f;
+
+ private const float minDeepForestDistance = 600f;
+
+ private const float maxDeepForestDistance = 6000f;
+
+ private const float deepForestForestFactorMax = 0.9f;
+
+ private const float marshBiomeScale = 0.001f;
+
+ private const float minMarshNoise = 0.6f;
+
+ private const float minMarshDistance = 2000f;
+
+ private const float maxMarshDistance = 8000f;
+
+ private const float minMarshHeight = 0.05f;
+
+ private const float maxMarshHeight = 0.25f;
+
+ private const float heathBiomeScale = 0.001f;
+
+ private const float minHeathNoise = 0.4f;
+
+ private const float minHeathDistance = 3000f;
+
+ private const float maxHeathDistance = 8000f;
+
+ private const float darklandBiomeScale = 0.001f;
+
+ private const float minDarklandNoise = 0.5f;
+
+ private const float minDarklandDistance = 6000f;
+
+ private const float maxDarklandDistance = 10000f;
+
+ private const float oceanBiomeScale = 0.0005f;
+
+ private const float oceanBiomeMinNoise = 0.4f;
+
+ private const float oceanBiomeMaxNoise = 0.6f;
+
+ private const float oceanBiomeMinDistance = 1000f;
+
+ private const float oceanBiomeMinDistanceBuffer = 256f;
+
+ private float m_minMountainDistance = 1000f;
+
+ private const float mountainBaseHeightMin = 0.4f;
+
+ private const float deepNorthMinDistance = 12000f;
+
+ private const float deepNorthYOffset = 4000f;
+
+ private const float ashlandsMinDistance = 12000f;
+
+ private const float ashlandsYOffset = -4000f;
+
+ public const float worldSize = 10000f;
+
+ public const float waterEdge = 10500f;
+
+ public static WorldGenerator instance => m_instance;
+
+ public static void Initialize(World world)
+ {
+ m_instance = new WorldGenerator(world);
+ }
+
+ public static void Deitialize()
+ {
+ m_instance = null;
+ }
+
+ private WorldGenerator(World world)
+ {
+ m_world = world;
+ ZLog.Log("Initializing world generator seed:" + m_world.m_seedName + " ( " + m_world.m_seed + " ) menu:" + m_world.m_menu.ToString() + " worldgen version:" + m_world.m_worldGenVersion);
+ m_version = m_world.m_worldGenVersion;
+ VersionSetup(m_version);
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(m_world.m_seed);
+ m_offset0 = UnityEngine.Random.Range(-10000, 10000);
+ m_offset1 = UnityEngine.Random.Range(-10000, 10000);
+ m_offset2 = UnityEngine.Random.Range(-10000, 10000);
+ m_offset3 = UnityEngine.Random.Range(-10000, 10000);
+ m_riverSeed = UnityEngine.Random.Range(int.MinValue, int.MaxValue);
+ m_streamSeed = UnityEngine.Random.Range(int.MinValue, int.MaxValue);
+ m_offset4 = UnityEngine.Random.Range(-10000, 10000);
+ if (!m_world.m_menu)
+ {
+ Pregenerate();
+ }
+ UnityEngine.Random.state = state;
+ }
+
+ private void VersionSetup(int version)
+ {
+ if (version < 1)
+ {
+ m_minMountainDistance = 1500f;
+ }
+ ZLog.Log("Using mountain distance: " + m_minMountainDistance);
+ }
+
+ private void Pregenerate()
+ {
+ FindMountains();
+ FindLakes();
+ m_rivers = PlaceRivers();
+ m_streams = PlaceStreams();
+ }
+
+ public List<Vector2> GetMountains()
+ {
+ return m_mountains;
+ }
+
+ public List<Vector2> GetLakes()
+ {
+ return m_lakes;
+ }
+
+ public List<River> GetRivers()
+ {
+ return m_rivers;
+ }
+
+ public List<River> GetStreams()
+ {
+ return m_streams;
+ }
+
+ private void FindMountains()
+ {
+ DateTime now = DateTime.Now;
+ List<Vector2> list = new List<Vector2>();
+ for (float num = -10000f; num <= 10000f; num += 128f)
+ {
+ for (float num2 = -10000f; num2 <= 10000f; num2 += 128f)
+ {
+ if (!(new Vector2(num2, num).magnitude > 10000f) && GetBaseHeight(num2, num, menuTerrain: false) > 0.45f)
+ {
+ list.Add(new Vector2(num2, num));
+ }
+ }
+ }
+ ZLog.Log("Found " + list.Count + " mountain points");
+ m_mountains = MergePoints(list, 800f);
+ ZLog.Log("Remaining mountains:" + m_mountains.Count);
+ ZLog.Log("Calc time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ }
+
+ private void FindLakes()
+ {
+ DateTime now = DateTime.Now;
+ List<Vector2> list = new List<Vector2>();
+ for (float num = -10000f; num <= 10000f; num += 128f)
+ {
+ for (float num2 = -10000f; num2 <= 10000f; num2 += 128f)
+ {
+ if (!(new Vector2(num2, num).magnitude > 10000f) && GetBaseHeight(num2, num, menuTerrain: false) < 0.05f)
+ {
+ list.Add(new Vector2(num2, num));
+ }
+ }
+ }
+ ZLog.Log("Found " + list.Count + " lake points");
+ m_lakes = MergePoints(list, 800f);
+ ZLog.Log("Remaining lakes:" + m_lakes.Count);
+ ZLog.Log("Calc time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ }
+
+ private List<Vector2> MergePoints(List<Vector2> points, float range)
+ {
+ List<Vector2> list = new List<Vector2>();
+ while (points.Count > 0)
+ {
+ Vector2 vector = points[0];
+ points.RemoveAt(0);
+ while (points.Count > 0)
+ {
+ int num = FindClosest(points, vector, range);
+ if (num == -1)
+ {
+ break;
+ }
+ vector = (vector + points[num]) * 0.5f;
+ points[num] = points[points.Count - 1];
+ points.RemoveAt(points.Count - 1);
+ }
+ list.Add(vector);
+ }
+ return list;
+ }
+
+ private int FindClosest(List<Vector2> points, Vector2 p, float maxDistance)
+ {
+ int result = -1;
+ float num = 99999f;
+ for (int i = 0; i < points.Count; i++)
+ {
+ if (!(points[i] == p))
+ {
+ float num2 = Vector2.Distance(p, points[i]);
+ if (num2 < maxDistance && num2 < num)
+ {
+ result = i;
+ num = num2;
+ }
+ }
+ }
+ return result;
+ }
+
+ private List<River> PlaceStreams()
+ {
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(m_streamSeed);
+ List<River> list = new List<River>();
+ int num = 0;
+ DateTime now = DateTime.Now;
+ for (int i = 0; i < 3000; i++)
+ {
+ if (FindStreamStartPoint(100, 26f, 31f, out var p, out var _) && FindStreamEndPoint(100, 36f, 44f, p, 80f, 200f, out var end))
+ {
+ Vector2 center = (p + end) * 0.5f;
+ float height = GetHeight(center.x, center.y);
+ if (!(height < 26f) && !(height > 44f))
+ {
+ River river = new River();
+ river.p0 = p;
+ river.p1 = end;
+ river.center = center;
+ river.widthMax = 20f;
+ river.widthMin = 20f;
+ float num2 = Vector2.Distance(river.p0, river.p1);
+ river.curveWidth = num2 / 15f;
+ river.curveWavelength = num2 / 20f;
+ list.Add(river);
+ num++;
+ }
+ }
+ }
+ RenderRivers(list);
+ UnityEngine.Random.state = state;
+ ZLog.Log("Placed " + num + " streams");
+ ZLog.Log("Stream Calc time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ return list;
+ }
+
+ private bool FindStreamEndPoint(int iterations, float minHeight, float maxHeight, Vector2 start, float minLength, float maxLength, out Vector2 end)
+ {
+ float num = (maxLength - minLength) / (float)iterations;
+ float num2 = maxLength;
+ for (int i = 0; i < iterations; i++)
+ {
+ num2 -= num;
+ float f = UnityEngine.Random.Range(0f, (float)Math.PI * 2f);
+ Vector2 vector = start + new Vector2(Mathf.Sin(f), Mathf.Cos(f)) * num2;
+ float height = GetHeight(vector.x, vector.y);
+ if (height > minHeight && height < maxHeight)
+ {
+ end = vector;
+ return true;
+ }
+ }
+ end = Vector2.zero;
+ return false;
+ }
+
+ private bool FindStreamStartPoint(int iterations, float minHeight, float maxHeight, out Vector2 p, out float starth)
+ {
+ for (int i = 0; i < iterations; i++)
+ {
+ float num = UnityEngine.Random.Range(-10000f, 10000f);
+ float num2 = UnityEngine.Random.Range(-10000f, 10000f);
+ float height = GetHeight(num, num2);
+ if (height > minHeight && height < maxHeight)
+ {
+ p = new Vector2(num, num2);
+ starth = height;
+ return true;
+ }
+ }
+ p = Vector2.zero;
+ starth = 0f;
+ return false;
+ }
+
+ private List<River> PlaceRivers()
+ {
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ UnityEngine.Random.InitState(m_riverSeed);
+ DateTime now = DateTime.Now;
+ List<River> list = new List<River>();
+ List<Vector2> list2 = new List<Vector2>(m_lakes);
+ while (list2.Count > 1)
+ {
+ Vector2 vector = list2[0];
+ int num = FindRandomRiverEnd(list, m_lakes, vector, 2000f, 0.4f, 128f);
+ if (num == -1 && !HaveRiver(list, vector))
+ {
+ num = FindRandomRiverEnd(list, m_lakes, vector, 5000f, 0.4f, 128f);
+ }
+ if (num != -1)
+ {
+ River river = new River();
+ river.p0 = vector;
+ river.p1 = m_lakes[num];
+ river.center = (river.p0 + river.p1) * 0.5f;
+ river.widthMax = UnityEngine.Random.Range(60f, 100f);
+ river.widthMin = UnityEngine.Random.Range(60f, river.widthMax);
+ float num2 = Vector2.Distance(river.p0, river.p1);
+ river.curveWidth = num2 / 15f;
+ river.curveWavelength = num2 / 20f;
+ list.Add(river);
+ }
+ else
+ {
+ list2.RemoveAt(0);
+ }
+ }
+ ZLog.Log("Rivers:" + list.Count);
+ RenderRivers(list);
+ ZLog.Log("River Calc time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ UnityEngine.Random.state = state;
+ return list;
+ }
+
+ private int FindClosestRiverEnd(List<River> rivers, List<Vector2> points, Vector2 p, float maxDistance, float heightLimit, float checkStep)
+ {
+ int result = -1;
+ float num = 99999f;
+ for (int i = 0; i < points.Count; i++)
+ {
+ if (!(points[i] == p))
+ {
+ float num2 = Vector2.Distance(p, points[i]);
+ if (num2 < maxDistance && num2 < num && !HaveRiver(rivers, p, points[i]) && IsRiverAllowed(p, points[i], checkStep, heightLimit))
+ {
+ result = i;
+ num = num2;
+ }
+ }
+ }
+ return result;
+ }
+
+ private int FindRandomRiverEnd(List<River> rivers, List<Vector2> points, Vector2 p, float maxDistance, float heightLimit, float checkStep)
+ {
+ List<int> list = new List<int>();
+ for (int i = 0; i < points.Count; i++)
+ {
+ if (!(points[i] == p) && Vector2.Distance(p, points[i]) < maxDistance && !HaveRiver(rivers, p, points[i]) && IsRiverAllowed(p, points[i], checkStep, heightLimit))
+ {
+ list.Add(i);
+ }
+ }
+ if (list.Count == 0)
+ {
+ return -1;
+ }
+ return list[UnityEngine.Random.Range(0, list.Count)];
+ }
+
+ private bool HaveRiver(List<River> rivers, Vector2 p0)
+ {
+ foreach (River river in rivers)
+ {
+ if (river.p0 == p0 || river.p1 == p0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool HaveRiver(List<River> rivers, Vector2 p0, Vector2 p1)
+ {
+ foreach (River river in rivers)
+ {
+ if ((river.p0 == p0 && river.p1 == p1) || (river.p0 == p1 && river.p1 == p0))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsRiverAllowed(Vector2 p0, Vector2 p1, float step, float heightLimit)
+ {
+ float num = Vector2.Distance(p0, p1);
+ Vector2 normalized = (p1 - p0).normalized;
+ bool flag = true;
+ for (float num2 = step; num2 <= num - step; num2 += step)
+ {
+ Vector2 vector = p0 + normalized * num2;
+ float baseHeight = GetBaseHeight(vector.x, vector.y, menuTerrain: false);
+ if (baseHeight > heightLimit)
+ {
+ return false;
+ }
+ if (baseHeight > 0.05f)
+ {
+ flag = false;
+ }
+ }
+ if (flag)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void RenderRivers(List<River> rivers)
+ {
+ DateTime now = DateTime.Now;
+ Dictionary<Vector2i, List<RiverPoint>> dictionary = new Dictionary<Vector2i, List<RiverPoint>>();
+ foreach (River river in rivers)
+ {
+ float num = river.widthMin / 8f;
+ Vector2 normalized = (river.p1 - river.p0).normalized;
+ Vector2 vector = new Vector2(0f - normalized.y, normalized.x);
+ float num2 = Vector2.Distance(river.p0, river.p1);
+ for (float num3 = 0f; num3 <= num2; num3 += num)
+ {
+ float num4 = num3 / river.curveWavelength;
+ float num5 = Mathf.Sin(num4) * Mathf.Sin(num4 * 0.63412f) * Mathf.Sin(num4 * 0.33412f) * river.curveWidth;
+ float r = UnityEngine.Random.Range(river.widthMin, river.widthMax);
+ Vector2 p = river.p0 + normalized * num3 + vector * num5;
+ AddRiverPoint(dictionary, p, r, river);
+ }
+ }
+ foreach (KeyValuePair<Vector2i, List<RiverPoint>> item in dictionary)
+ {
+ if (m_riverPoints.TryGetValue(item.Key, out var value))
+ {
+ List<RiverPoint> list = new List<RiverPoint>(value);
+ list.AddRange(item.Value);
+ m_riverPoints[item.Key] = list.ToArray();
+ }
+ else
+ {
+ RiverPoint[] value2 = item.Value.ToArray();
+ m_riverPoints.Add(item.Key, value2);
+ }
+ }
+ ZLog.Log("River buckets " + m_riverPoints.Count);
+ ZLog.Log("River render time " + (DateTime.Now - now).TotalMilliseconds + " ms");
+ }
+
+ private void AddRiverPoint(Dictionary<Vector2i, List<RiverPoint>> riverPoints, Vector2 p, float r, River river)
+ {
+ Vector2i riverGrid = GetRiverGrid(p.x, p.y);
+ int num = Mathf.CeilToInt(r / 64f);
+ for (int i = riverGrid.y - num; i <= riverGrid.y + num; i++)
+ {
+ for (int j = riverGrid.x - num; j <= riverGrid.x + num; j++)
+ {
+ Vector2i grid = new Vector2i(j, i);
+ if (InsideRiverGrid(grid, p, r))
+ {
+ AddRiverPoint(riverPoints, grid, p, r, river);
+ }
+ }
+ }
+ }
+
+ private void AddRiverPoint(Dictionary<Vector2i, List<RiverPoint>> riverPoints, Vector2i grid, Vector2 p, float r, River river)
+ {
+ if (riverPoints.TryGetValue(grid, out var value))
+ {
+ value.Add(new RiverPoint(p, r));
+ return;
+ }
+ value = new List<RiverPoint>();
+ value.Add(new RiverPoint(p, r));
+ riverPoints.Add(grid, value);
+ }
+
+ public bool InsideRiverGrid(Vector2i grid, Vector2 p, float r)
+ {
+ Vector2 vector = new Vector2((float)grid.x * 64f, (float)grid.y * 64f);
+ Vector2 vector2 = p - vector;
+ if (Mathf.Abs(vector2.x) < r + 32f)
+ {
+ return Mathf.Abs(vector2.y) < r + 32f;
+ }
+ return false;
+ }
+
+ public Vector2i GetRiverGrid(float wx, float wy)
+ {
+ int x = Mathf.FloorToInt((wx + 32f) / 64f);
+ int y = Mathf.FloorToInt((wy + 32f) / 64f);
+ return new Vector2i(x, y);
+ }
+
+ private void GetRiverWeight(float wx, float wy, out float weight, out float width)
+ {
+ Vector2i riverGrid = GetRiverGrid(wx, wy);
+ m_riverCacheLock.EnterReadLock();
+ if (riverGrid == m_cachedRiverGrid)
+ {
+ if (m_cachedRiverPoints != null)
+ {
+ GetWeight(m_cachedRiverPoints, wx, wy, out weight, out width);
+ m_riverCacheLock.ExitReadLock();
+ }
+ else
+ {
+ weight = 0f;
+ width = 0f;
+ m_riverCacheLock.ExitReadLock();
+ }
+ return;
+ }
+ m_riverCacheLock.ExitReadLock();
+ if (m_riverPoints.TryGetValue(riverGrid, out var value))
+ {
+ GetWeight(value, wx, wy, out weight, out width);
+ m_riverCacheLock.EnterWriteLock();
+ m_cachedRiverGrid = riverGrid;
+ m_cachedRiverPoints = value;
+ m_riverCacheLock.ExitWriteLock();
+ }
+ else
+ {
+ m_riverCacheLock.EnterWriteLock();
+ m_cachedRiverGrid = riverGrid;
+ m_cachedRiverPoints = null;
+ m_riverCacheLock.ExitWriteLock();
+ weight = 0f;
+ width = 0f;
+ }
+ }
+
+ private void GetWeight(RiverPoint[] points, float wx, float wy, out float weight, out float width)
+ {
+ Vector2 vector = new Vector2(wx, wy);
+ weight = 0f;
+ width = 0f;
+ float num = 0f;
+ float num2 = 0f;
+ for (int i = 0; i < points.Length; i++)
+ {
+ RiverPoint riverPoint = points[i];
+ float num3 = Vector2.SqrMagnitude(riverPoint.p - vector);
+ if (num3 < riverPoint.w2)
+ {
+ float num4 = Mathf.Sqrt(num3);
+ float num5 = 1f - num4 / riverPoint.w;
+ if (num5 > weight)
+ {
+ weight = num5;
+ }
+ num += riverPoint.w * num5;
+ num2 += num5;
+ }
+ }
+ if (num2 > 0f)
+ {
+ width = num / num2;
+ }
+ }
+
+ private void GenerateBiomes()
+ {
+ m_biomes = new List<Heightmap.Biome>();
+ int num = 400000000;
+ for (int i = 0; i < num; i++)
+ {
+ m_biomes[i] = Heightmap.Biome.Meadows;
+ }
+ }
+
+ public Heightmap.BiomeArea GetBiomeArea(Vector3 point)
+ {
+ Heightmap.Biome biome = GetBiome(point);
+ Heightmap.Biome biome2 = GetBiome(point - new Vector3(-64f, 0f, -64f));
+ Heightmap.Biome biome3 = GetBiome(point - new Vector3(64f, 0f, -64f));
+ Heightmap.Biome biome4 = GetBiome(point - new Vector3(64f, 0f, 64f));
+ Heightmap.Biome biome5 = GetBiome(point - new Vector3(-64f, 0f, 64f));
+ Heightmap.Biome biome6 = GetBiome(point - new Vector3(-64f, 0f, 0f));
+ Heightmap.Biome biome7 = GetBiome(point - new Vector3(64f, 0f, 0f));
+ Heightmap.Biome biome8 = GetBiome(point - new Vector3(0f, 0f, -64f));
+ Heightmap.Biome biome9 = GetBiome(point - new Vector3(0f, 0f, 64f));
+ if (biome == biome2 && biome == biome3 && biome == biome4 && biome == biome5 && biome == biome6 && biome == biome7 && biome == biome8 && biome == biome9)
+ {
+ return Heightmap.BiomeArea.Median;
+ }
+ return Heightmap.BiomeArea.Edge;
+ }
+
+ public Heightmap.Biome GetBiome(Vector3 point)
+ {
+ return GetBiome(point.x, point.z);
+ }
+
+ public Heightmap.Biome GetBiome(float wx, float wy)
+ {
+ if (m_world.m_menu)
+ {
+ if (GetBaseHeight(wx, wy, menuTerrain: true) >= 0.4f)
+ {
+ return Heightmap.Biome.Mountain;
+ }
+ return Heightmap.Biome.BlackForest;
+ }
+ float magnitude = new Vector2(wx, wy).magnitude;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ float num = WorldAngle(wx, wy) * 100f;
+ if (new Vector2(wx, wy + -4000f).magnitude > 12000f + num)
+ {
+ return Heightmap.Biome.AshLands;
+ }
+ if ((double)baseHeight <= 0.02)
+ {
+ return Heightmap.Biome.Ocean;
+ }
+ if (new Vector2(wx, wy + 4000f).magnitude > 12000f + num)
+ {
+ if (baseHeight > 0.4f)
+ {
+ return Heightmap.Biome.Mountain;
+ }
+ return Heightmap.Biome.DeepNorth;
+ }
+ if (baseHeight > 0.4f)
+ {
+ return Heightmap.Biome.Mountain;
+ }
+ if (Mathf.PerlinNoise((m_offset0 + wx) * 0.001f, (m_offset0 + wy) * 0.001f) > 0.6f && magnitude > 2000f && magnitude < 8000f && baseHeight > 0.05f && baseHeight < 0.25f)
+ {
+ return Heightmap.Biome.Swamp;
+ }
+ if (Mathf.PerlinNoise((m_offset4 + wx) * 0.001f, (m_offset4 + wy) * 0.001f) > 0.5f && magnitude > 6000f + num && magnitude < 10000f)
+ {
+ return Heightmap.Biome.Mistlands;
+ }
+ if (Mathf.PerlinNoise((m_offset1 + wx) * 0.001f, (m_offset1 + wy) * 0.001f) > 0.4f && magnitude > 3000f + num && magnitude < 8000f)
+ {
+ return Heightmap.Biome.Plains;
+ }
+ if (Mathf.PerlinNoise((m_offset2 + wx) * 0.001f, (m_offset2 + wy) * 0.001f) > 0.4f && magnitude > 600f + num && magnitude < 6000f)
+ {
+ return Heightmap.Biome.BlackForest;
+ }
+ if (magnitude > 5000f + num)
+ {
+ return Heightmap.Biome.BlackForest;
+ }
+ return Heightmap.Biome.Meadows;
+ }
+
+ private float WorldAngle(float wx, float wy)
+ {
+ return Mathf.Sin(Mathf.Atan2(wx, wy) * 20f);
+ }
+
+ private float GetBaseHeight(float wx, float wy, bool menuTerrain)
+ {
+ if (menuTerrain)
+ {
+ wx += 100000f + m_offset0;
+ wy += 100000f + m_offset1;
+ float num = 0f;
+ num += Mathf.PerlinNoise(wx * 0.002f * 0.5f, wy * 0.002f * 0.5f) * Mathf.PerlinNoise(wx * 0.003f * 0.5f, wy * 0.003f * 0.5f) * 1f;
+ num += Mathf.PerlinNoise(wx * 0.002f * 1f, wy * 0.002f * 1f) * Mathf.PerlinNoise(wx * 0.003f * 1f, wy * 0.003f * 1f) * num * 0.9f;
+ num += Mathf.PerlinNoise(wx * 0.005f * 1f, wy * 0.005f * 1f) * Mathf.PerlinNoise(wx * 0.01f * 1f, wy * 0.01f * 1f) * 0.5f * num;
+ return num - 0.07f;
+ }
+ float num2 = Utils.Length(wx, wy);
+ wx += 100000f + m_offset0;
+ wy += 100000f + m_offset1;
+ float num3 = 0f;
+ num3 += Mathf.PerlinNoise(wx * 0.002f * 0.5f, wy * 0.002f * 0.5f) * Mathf.PerlinNoise(wx * 0.003f * 0.5f, wy * 0.003f * 0.5f) * 1f;
+ num3 += Mathf.PerlinNoise(wx * 0.002f * 1f, wy * 0.002f * 1f) * Mathf.PerlinNoise(wx * 0.003f * 1f, wy * 0.003f * 1f) * num3 * 0.9f;
+ num3 += Mathf.PerlinNoise(wx * 0.005f * 1f, wy * 0.005f * 1f) * Mathf.PerlinNoise(wx * 0.01f * 1f, wy * 0.01f * 1f) * 0.5f * num3;
+ num3 -= 0.07f;
+ float num4 = Mathf.PerlinNoise(wx * 0.002f * 0.25f + 0.123f, wy * 0.002f * 0.25f + 0.15123f);
+ float num5 = Mathf.PerlinNoise(wx * 0.002f * 0.25f + 0.321f, wy * 0.002f * 0.25f + 0.231f);
+ float v = Mathf.Abs(num4 - num5);
+ float num6 = 1f - Utils.LerpStep(0.02f, 0.12f, v);
+ num6 *= Utils.SmoothStep(744f, 1000f, num2);
+ num3 *= 1f - num6;
+ if (num2 > 10000f)
+ {
+ float t = Utils.LerpStep(10000f, 10500f, num2);
+ num3 = Mathf.Lerp(num3, -0.2f, t);
+ float num7 = 10490f;
+ if (num2 > num7)
+ {
+ float t2 = Utils.LerpStep(num7, 10500f, num2);
+ num3 = Mathf.Lerp(num3, -2f, t2);
+ }
+ }
+ if (num2 < m_minMountainDistance && num3 > 0.28f)
+ {
+ float t3 = Mathf.Clamp01((num3 - 0.28f) / 0.099999994f);
+ num3 = Mathf.Lerp(Mathf.Lerp(0.28f, 0.38f, t3), num3, Utils.LerpStep(m_minMountainDistance - 400f, m_minMountainDistance, num2));
+ }
+ return num3;
+ }
+
+ private float AddRivers(float wx, float wy, float h)
+ {
+ GetRiverWeight(wx, wy, out var weight, out var width);
+ if (weight <= 0f)
+ {
+ return h;
+ }
+ float t = Utils.LerpStep(20f, 60f, width);
+ float num = Mathf.Lerp(0.14f, 0.12f, t);
+ float num2 = Mathf.Lerp(0.139f, 0.128f, t);
+ if (h > num)
+ {
+ h = Mathf.Lerp(h, num, weight);
+ }
+ if (h > num2)
+ {
+ float t2 = Utils.LerpStep(0.85f, 1f, weight);
+ h = Mathf.Lerp(h, num2, t2);
+ }
+ return h;
+ }
+
+ public float GetHeight(float wx, float wy)
+ {
+ Heightmap.Biome biome = GetBiome(wx, wy);
+ return GetBiomeHeight(biome, wx, wy);
+ }
+
+ public float GetBiomeHeight(Heightmap.Biome biome, float wx, float wy)
+ {
+ if (m_world.m_menu)
+ {
+ if (biome == Heightmap.Biome.Mountain)
+ {
+ return GetSnowMountainHeight(wx, wy, menu: true) * 200f;
+ }
+ return GetMenuHeight(wx, wy) * 200f;
+ }
+ return biome switch
+ {
+ Heightmap.Biome.Swamp => GetMarshHeight(wx, wy) * 200f,
+ Heightmap.Biome.DeepNorth => GetDeepNorthHeight(wx, wy) * 200f,
+ Heightmap.Biome.Mountain => GetSnowMountainHeight(wx, wy, menu: false) * 200f,
+ Heightmap.Biome.BlackForest => GetForestHeight(wx, wy) * 200f,
+ Heightmap.Biome.Ocean => GetOceanHeight(wx, wy) * 200f,
+ Heightmap.Biome.AshLands => GetAshlandsHeight(wx, wy) * 200f,
+ Heightmap.Biome.Plains => GetPlainsHeight(wx, wy) * 200f,
+ Heightmap.Biome.Meadows => GetMeadowsHeight(wx, wy) * 200f,
+ Heightmap.Biome.Mistlands => GetForestHeight(wx, wy) * 200f,
+ _ => 0f,
+ };
+ }
+
+ private float GetMarshHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float num = 0.137f;
+ wx += 100000f;
+ wy += 100000f;
+ float num2 = Mathf.PerlinNoise(wx * 0.04f, wy * 0.04f) * Mathf.PerlinNoise(wx * 0.08f, wy * 0.08f);
+ num += num2 * 0.03f;
+ num = AddRivers(wx2, wy2, num);
+ num += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ return num + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ private float GetMeadowsHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num * 0.5f;
+ float num2 = baseHeight;
+ num2 += num * 0.1f;
+ float num3 = 0.15f;
+ float num4 = num2 - num3;
+ float num5 = Mathf.Clamp01(baseHeight / 0.4f);
+ if (num4 > 0f)
+ {
+ num2 -= num4 * (1f - num5) * 0.75f;
+ }
+ num2 = AddRivers(wx2, wy2, num2);
+ num2 += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ return num2 + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ private float GetForestHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num * 0.5f;
+ baseHeight += num * 0.1f;
+ baseHeight = AddRivers(wx2, wy2, baseHeight);
+ baseHeight += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ return baseHeight + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ private float GetPlainsHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num * 0.5f;
+ float num2 = baseHeight;
+ num2 += num * 0.1f;
+ float num3 = 0.15f;
+ float num4 = num2 - num3;
+ float num5 = Mathf.Clamp01(baseHeight / 0.4f);
+ if (num4 > 0f)
+ {
+ num2 -= num4 * (1f - num5) * 0.75f;
+ }
+ num2 = AddRivers(wx2, wy2, num2);
+ num2 += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ return num2 + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ private float GetMenuHeight(float wx, float wy)
+ {
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: true);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num * 0.5f;
+ return baseHeight + num * 0.1f + Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ private float GetAshlandsHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num * 0.5f;
+ baseHeight += num * 0.1f;
+ baseHeight += 0.1f;
+ baseHeight += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ baseHeight += Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ return AddRivers(wx2, wy2, baseHeight);
+ }
+
+ private float GetEdgeHeight(float wx, float wy)
+ {
+ float magnitude = new Vector2(wx, wy).magnitude;
+ float num = 10490f;
+ if (magnitude > num)
+ {
+ float num2 = Utils.LerpStep(num, 10500f, magnitude);
+ return -2f * num2;
+ }
+ float t = Utils.LerpStep(10000f, 10100f, magnitude);
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ baseHeight = Mathf.Lerp(baseHeight, 0f, t);
+ return AddRivers(wx, wy, baseHeight);
+ }
+
+ private float GetOceanHeight(float wx, float wy)
+ {
+ return GetBaseHeight(wx, wy, menuTerrain: false);
+ }
+
+ private float BaseHeightTilt(float wx, float wy)
+ {
+ float baseHeight = GetBaseHeight(wx - 1f, wy, menuTerrain: false);
+ float baseHeight2 = GetBaseHeight(wx + 1f, wy, menuTerrain: false);
+ float baseHeight3 = GetBaseHeight(wx, wy - 1f, menuTerrain: false);
+ float baseHeight4 = GetBaseHeight(wx, wy + 1f, menuTerrain: false);
+ return Mathf.Abs(baseHeight2 - baseHeight) + Mathf.Abs(baseHeight3 - baseHeight4);
+ }
+
+ private float GetSnowMountainHeight(float wx, float wy, bool menu)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menu);
+ float num = BaseHeightTilt(wx, wy);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num2 = baseHeight - 0.4f;
+ baseHeight += num2;
+ float num3 = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num3 += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num3 * 0.5f;
+ baseHeight += num3 * 0.2f;
+ baseHeight = AddRivers(wx2, wy2, baseHeight);
+ baseHeight += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ baseHeight += Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ return baseHeight + Mathf.PerlinNoise(wx * 0.2f, wy * 0.2f) * 2f * num;
+ }
+
+ private float GetDeepNorthHeight(float wx, float wy)
+ {
+ float wx2 = wx;
+ float wy2 = wy;
+ float baseHeight = GetBaseHeight(wx, wy, menuTerrain: false);
+ wx += 100000f + m_offset3;
+ wy += 100000f + m_offset3;
+ float num = Mathf.Max(0f, baseHeight - 0.4f);
+ baseHeight += num;
+ float num2 = Mathf.PerlinNoise(wx * 0.01f, wy * 0.01f) * Mathf.PerlinNoise(wx * 0.02f, wy * 0.02f);
+ num2 += Mathf.PerlinNoise(wx * 0.05f, wy * 0.05f) * Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * num2 * 0.5f;
+ baseHeight += num2 * 0.2f;
+ baseHeight *= 1.2f;
+ baseHeight = AddRivers(wx2, wy2, baseHeight);
+ baseHeight += Mathf.PerlinNoise(wx * 0.1f, wy * 0.1f) * 0.01f;
+ return baseHeight + Mathf.PerlinNoise(wx * 0.4f, wy * 0.4f) * 0.003f;
+ }
+
+ public static bool InForest(Vector3 pos)
+ {
+ return GetForestFactor(pos) < 1.15f;
+ }
+
+ public static float GetForestFactor(Vector3 pos)
+ {
+ float num = 0.4f;
+ return Utils.Fbm(pos * 0.01f * num, 3, 1.6f, 0.7f);
+ }
+
+ public void GetTerrainDelta(Vector3 center, float radius, out float delta, out Vector3 slopeDirection)
+ {
+ int num = 10;
+ float num2 = -999999f;
+ float num3 = 999999f;
+ Vector3 vector = center;
+ Vector3 vector2 = center;
+ for (int i = 0; i < num; i++)
+ {
+ Vector2 vector3 = UnityEngine.Random.insideUnitCircle * radius;
+ Vector3 vector4 = center + new Vector3(vector3.x, 0f, vector3.y);
+ float height = GetHeight(vector4.x, vector4.z);
+ if (height < num3)
+ {
+ num3 = height;
+ vector2 = vector4;
+ }
+ if (height > num2)
+ {
+ num2 = height;
+ vector = vector4;
+ }
+ }
+ delta = num2 - num3;
+ slopeDirection = Vector3.Normalize(vector2 - vector);
+ }
+
+ public int GetSeed()
+ {
+ return m_world.m_seed;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZBroastcast.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZBroastcast.cs
new file mode 100644
index 0000000..a33eb77
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZBroastcast.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+public class ZBroastcast : IDisposable
+{
+ public class HostData
+ {
+ public string m_host;
+
+ public int m_port;
+
+ public float m_timeout;
+ }
+
+ private List<HostData> m_hosts = new List<HostData>();
+
+ private static ZBroastcast m_instance;
+
+ private const int m_port = 6542;
+
+ private const float m_pingInterval = 5f;
+
+ private const float m_hostTimeout = 10f;
+
+ private float m_timer;
+
+ private int m_myPort;
+
+ private Socket m_socket;
+
+ private UdpClient m_listner;
+
+ private Mutex m_lock = new Mutex();
+
+ public static ZBroastcast instance => m_instance;
+
+ public static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new ZBroastcast();
+ }
+ }
+
+ private ZBroastcast()
+ {
+ ZLog.Log("opening zbroadcast");
+ m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ m_socket.EnableBroadcast = true;
+ try
+ {
+ m_listner = new UdpClient(6542);
+ m_listner.EnableBroadcast = true;
+ m_listner.BeginReceive(GotPackage, null);
+ }
+ catch (Exception ex)
+ {
+ m_listner = null;
+ ZLog.Log("Error creating zbroadcast socket " + ex.ToString());
+ }
+ }
+
+ public void SetServerPort(int port)
+ {
+ m_myPort = port;
+ }
+
+ public void Dispose()
+ {
+ ZLog.Log("Clozing zbroadcast");
+ if (m_listner != null)
+ {
+ m_listner.Close();
+ }
+ m_socket.Close();
+ m_lock.Close();
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void Update(float dt)
+ {
+ m_timer -= dt;
+ if (m_timer <= 0f)
+ {
+ m_timer = 5f;
+ if (m_myPort != 0)
+ {
+ Ping();
+ }
+ }
+ TimeoutHosts(dt);
+ }
+
+ private void GotPackage(IAsyncResult ar)
+ {
+ IPEndPoint remoteEP = new IPEndPoint(0L, 0);
+ byte[] array;
+ try
+ {
+ array = m_listner.EndReceive(ar, ref remoteEP);
+ }
+ catch (ObjectDisposedException)
+ {
+ return;
+ }
+ if (array.Length >= 5)
+ {
+ ZPackage zPackage = new ZPackage(array);
+ if (zPackage.ReadChar() == 'F' && zPackage.ReadChar() == 'E' && zPackage.ReadChar() == 'J' && zPackage.ReadChar() == 'D')
+ {
+ int port = zPackage.ReadInt();
+ m_lock.WaitOne();
+ AddHost(remoteEP.Address.ToString(), port);
+ m_lock.ReleaseMutex();
+ m_listner.BeginReceive(GotPackage, null);
+ }
+ }
+ }
+
+ private void Ping()
+ {
+ IPEndPoint remoteEP = new IPEndPoint(IPAddress.Broadcast, 6542);
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write('F');
+ zPackage.Write('E');
+ zPackage.Write('J');
+ zPackage.Write('D');
+ zPackage.Write(m_myPort);
+ m_socket.SendTo(zPackage.GetArray(), remoteEP);
+ }
+
+ private void AddHost(string host, int port)
+ {
+ foreach (HostData host2 in m_hosts)
+ {
+ if (host2.m_port == port && host2.m_host == host)
+ {
+ host2.m_timeout = 0f;
+ return;
+ }
+ }
+ HostData hostData = new HostData();
+ hostData.m_host = host;
+ hostData.m_port = port;
+ hostData.m_timeout = 0f;
+ m_hosts.Add(hostData);
+ }
+
+ private void TimeoutHosts(float dt)
+ {
+ m_lock.WaitOne();
+ foreach (HostData host in m_hosts)
+ {
+ host.m_timeout += dt;
+ if (host.m_timeout > 10f)
+ {
+ m_hosts.Remove(host);
+ return;
+ }
+ }
+ m_lock.ReleaseMutex();
+ }
+
+ public void GetHostList(List<HostData> hosts)
+ {
+ hosts.AddRange(m_hosts);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector.cs
new file mode 100644
index 0000000..9c23678
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+public class ZConnector : IDisposable
+{
+ private Socket m_socket;
+
+ private IAsyncResult m_result;
+
+ private IPEndPoint m_endPoint;
+
+ private string m_host;
+
+ private int m_port;
+
+ private bool m_dnsError;
+
+ private bool m_abort;
+
+ private float m_timer;
+
+ private static float m_timeout = 5f;
+
+ public ZConnector(string host, int port)
+ {
+ m_host = host;
+ m_port = port;
+ ZLog.Log("Zconnect " + host + " " + port);
+ Dns.BeginGetHostEntry(host, OnHostLookupDone, null);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ private void Close()
+ {
+ if (m_socket != null)
+ {
+ try
+ {
+ if (m_socket.Connected)
+ {
+ m_socket.Shutdown(SocketShutdown.Both);
+ }
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Some excepetion when shuting down ZConnector socket, ignoring:" + ex);
+ }
+ m_socket.Close();
+ m_socket = null;
+ }
+ m_abort = true;
+ }
+
+ public bool IsPeer(string host, int port)
+ {
+ if (m_host == host && m_port == port)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool UpdateStatus(float dt, bool logErrors = false)
+ {
+ if (m_abort)
+ {
+ ZLog.Log("ZConnector - Abort");
+ return true;
+ }
+ if (m_dnsError)
+ {
+ ZLog.Log("ZConnector - dns error");
+ return true;
+ }
+ if (m_result != null && m_result.IsCompleted)
+ {
+ ZLog.Log("ZConnector - result completed");
+ return true;
+ }
+ m_timer += dt;
+ if (m_timer > m_timeout)
+ {
+ ZLog.Log("ZConnector - timeout");
+ Close();
+ return true;
+ }
+ return false;
+ }
+
+ public ZSocket Complete()
+ {
+ if (m_socket != null && m_socket.Connected)
+ {
+ ZSocket result = new ZSocket(m_socket, m_host);
+ m_socket = null;
+ return result;
+ }
+ Close();
+ return null;
+ }
+
+ public bool CompareEndPoint(IPEndPoint endpoint)
+ {
+ return m_endPoint.Equals(endpoint);
+ }
+
+ private void OnHostLookupDone(IAsyncResult res)
+ {
+ IPHostEntry iPHostEntry = Dns.EndGetHostEntry(res);
+ if (m_abort)
+ {
+ ZLog.Log("Host lookup abort");
+ return;
+ }
+ if (iPHostEntry.AddressList.Length == 0)
+ {
+ m_dnsError = true;
+ ZLog.Log("Host lookup adress list empty");
+ return;
+ }
+ ZLog.Log("Host lookup done , addresses: " + iPHostEntry.AddressList.Length);
+ IPAddress[] addressList = iPHostEntry.AddressList;
+ foreach (IPAddress iPAddress in addressList)
+ {
+ ZLog.Log(" " + iPAddress);
+ }
+ m_socket = ZSocket.CreateSocket();
+ m_result = m_socket.BeginConnect(iPHostEntry.AddressList, m_port, null, null);
+ }
+
+ public string GetEndPointString()
+ {
+ return m_host + ":" + m_port;
+ }
+
+ public string GetHostName()
+ {
+ return m_host;
+ }
+
+ public int GetHostPort()
+ {
+ return m_port;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector2.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector2.cs
new file mode 100644
index 0000000..0643547
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZConnector2.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+public class ZConnector2 : IDisposable
+{
+ private TcpClient m_socket;
+
+ private IAsyncResult m_result;
+
+ private IPEndPoint m_endPoint;
+
+ private string m_host;
+
+ private int m_port;
+
+ private bool m_dnsError;
+
+ private bool m_abort;
+
+ private float m_timer;
+
+ private static float m_timeout = 5f;
+
+ public ZConnector2(string host, int port)
+ {
+ m_host = host;
+ m_port = port;
+ Dns.BeginGetHostEntry(host, OnHostLookupDone, null);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ private void Close()
+ {
+ if (m_socket != null)
+ {
+ m_socket.Close();
+ m_socket = null;
+ }
+ m_abort = true;
+ }
+
+ public bool IsPeer(string host, int port)
+ {
+ if (m_host == host && m_port == port)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool UpdateStatus(float dt, bool logErrors = false)
+ {
+ if (m_abort)
+ {
+ ZLog.Log("ZConnector - Abort");
+ return true;
+ }
+ if (m_dnsError)
+ {
+ ZLog.Log("ZConnector - dns error");
+ return true;
+ }
+ if (m_result != null && m_result.IsCompleted)
+ {
+ return true;
+ }
+ m_timer += dt;
+ if (m_timer > m_timeout)
+ {
+ Close();
+ return true;
+ }
+ return false;
+ }
+
+ public ZSocket2 Complete()
+ {
+ if (m_socket != null && m_socket.Connected)
+ {
+ ZSocket2 result = new ZSocket2(m_socket, m_host);
+ m_socket = null;
+ return result;
+ }
+ Close();
+ return null;
+ }
+
+ public bool CompareEndPoint(IPEndPoint endpoint)
+ {
+ return m_endPoint.Equals(endpoint);
+ }
+
+ private void OnHostLookupDone(IAsyncResult res)
+ {
+ IPHostEntry iPHostEntry = Dns.EndGetHostEntry(res);
+ if (m_abort)
+ {
+ ZLog.Log("Host lookup abort");
+ }
+ else if (iPHostEntry.AddressList.Length == 0)
+ {
+ m_dnsError = true;
+ ZLog.Log("Host lookup adress list empty");
+ }
+ else
+ {
+ m_socket = ZSocket2.CreateSocket();
+ m_result = m_socket.BeginConnect(iPHostEntry.AddressList, m_port, null, null);
+ }
+ }
+
+ public string GetEndPointString()
+ {
+ return m_host + ":" + m_port;
+ }
+
+ public string GetHostName()
+ {
+ return m_host;
+ }
+
+ public int GetHostPort()
+ {
+ return m_port;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDO.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDO.cs
new file mode 100644
index 0000000..d592aab
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDO.cs
@@ -0,0 +1,1076 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ZDO : IEquatable<ZDO>
+{
+ public enum ObjectType
+ {
+ Default,
+ Prioritized,
+ Solid
+ }
+
+ public ZDOID m_uid;
+
+ public bool m_persistent;
+
+ public bool m_distant;
+
+ public long m_owner;
+
+ public long m_timeCreated;
+
+ public uint m_ownerRevision;
+
+ public uint m_dataRevision;
+
+ public int m_pgwVersion;
+
+ public ObjectType m_type;
+
+ public float m_tempSortValue;
+
+ public bool m_tempHaveRevision;
+
+ public int m_tempRemoveEarmark = -1;
+
+ public int m_tempCreateEarmark = -1;
+
+ private int m_prefab;
+
+ private Vector2i m_sector = Vector2i.zero;
+
+ private Vector3 m_position = Vector3.zero;
+
+ private Quaternion m_rotation = Quaternion.identity;
+
+ private Dictionary<int, float> m_floats;
+
+ private Dictionary<int, Vector3> m_vec3;
+
+ private Dictionary<int, Quaternion> m_quats;
+
+ private Dictionary<int, int> m_ints;
+
+ private Dictionary<int, long> m_longs;
+
+ private Dictionary<int, string> m_strings;
+
+ private ZDOMan m_zdoMan;
+
+ public void Initialize(ZDOMan man, ZDOID id, Vector3 position)
+ {
+ m_zdoMan = man;
+ m_uid = id;
+ m_position = position;
+ m_sector = ZoneSystem.instance.GetZone(m_position);
+ m_zdoMan.AddToSector(this, m_sector);
+ }
+
+ public void Initialize(ZDOMan man)
+ {
+ m_zdoMan = man;
+ }
+
+ public bool IsValid()
+ {
+ return m_zdoMan != null;
+ }
+
+ public void Reset()
+ {
+ m_uid = ZDOID.None;
+ m_persistent = false;
+ m_owner = 0L;
+ m_timeCreated = 0L;
+ m_ownerRevision = 0u;
+ m_dataRevision = 0u;
+ m_pgwVersion = 0;
+ m_distant = false;
+ m_tempSortValue = 0f;
+ m_tempHaveRevision = false;
+ m_prefab = 0;
+ m_sector = Vector2i.zero;
+ m_position = Vector3.zero;
+ m_rotation = Quaternion.identity;
+ ReleaseFloats();
+ ReleaseVec3();
+ ReleaseQuats();
+ ReleaseInts();
+ ReleaseLongs();
+ ReleaseStrings();
+ m_zdoMan = null;
+ }
+
+ public ZDO Clone()
+ {
+ ZDO zDO = MemberwiseClone() as ZDO;
+ zDO.m_floats = null;
+ zDO.m_vec3 = null;
+ zDO.m_quats = null;
+ zDO.m_ints = null;
+ zDO.m_longs = null;
+ zDO.m_strings = null;
+ if (m_floats != null && m_floats.Count > 0)
+ {
+ zDO.InitFloats();
+ zDO.m_floats.Copy(m_floats);
+ }
+ if (m_vec3 != null && m_vec3.Count > 0)
+ {
+ zDO.InitVec3();
+ zDO.m_vec3.Copy(m_vec3);
+ }
+ if (m_quats != null && m_quats.Count > 0)
+ {
+ zDO.InitQuats();
+ zDO.m_quats.Copy(m_quats);
+ }
+ if (m_ints != null && m_ints.Count > 0)
+ {
+ zDO.InitInts();
+ zDO.m_ints.Copy(m_ints);
+ }
+ if (m_longs != null && m_longs.Count > 0)
+ {
+ zDO.InitLongs();
+ zDO.m_longs.Copy(m_longs);
+ }
+ if (m_strings != null && m_strings.Count > 0)
+ {
+ zDO.InitStrings();
+ zDO.m_strings.Copy(m_strings);
+ }
+ return zDO;
+ }
+
+ public bool Equals(ZDO other)
+ {
+ return this == other;
+ }
+
+ public void Set(KeyValuePair<int, int> hashPair, ZDOID id)
+ {
+ Set(hashPair.Key, id.userID);
+ Set(hashPair.Value, id.id);
+ }
+
+ public static KeyValuePair<int, int> GetHashZDOID(string name)
+ {
+ return new KeyValuePair<int, int>((name + "_u").GetStableHashCode(), (name + "_i").GetStableHashCode());
+ }
+
+ public void Set(string name, ZDOID id)
+ {
+ Set(GetHashZDOID(name), id);
+ }
+
+ public ZDOID GetZDOID(KeyValuePair<int, int> hashPair)
+ {
+ long @long = GetLong(hashPair.Key, 0L);
+ uint num = (uint)GetLong(hashPair.Value, 0L);
+ if (@long == 0L || num == 0)
+ {
+ return ZDOID.None;
+ }
+ return new ZDOID(@long, num);
+ }
+
+ public ZDOID GetZDOID(string name)
+ {
+ return GetZDOID(GetHashZDOID(name));
+ }
+
+ public void Set(string name, float value)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ Set(stableHashCode, value);
+ }
+
+ public void Set(int hash, float value)
+ {
+ InitFloats();
+ if (!m_floats.TryGetValue(hash, out var value2) || value2 != value)
+ {
+ m_floats[hash] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void Set(string name, Vector3 value)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ Set(stableHashCode, value);
+ }
+
+ public void Set(int hash, Vector3 value)
+ {
+ InitVec3();
+ if (!m_vec3.TryGetValue(hash, out var value2) || !(value2 == value))
+ {
+ m_vec3[hash] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void Set(string name, Quaternion value)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ Set(stableHashCode, value);
+ }
+
+ public void Set(int hash, Quaternion value)
+ {
+ InitQuats();
+ if (!m_quats.TryGetValue(hash, out var value2) || !(value2 == value))
+ {
+ m_quats[hash] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void Set(string name, int value)
+ {
+ Set(name.GetStableHashCode(), value);
+ }
+
+ public void Set(int hash, int value)
+ {
+ InitInts();
+ if (!m_ints.TryGetValue(hash, out var value2) || value2 != value)
+ {
+ m_ints[hash] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void Set(string name, bool value)
+ {
+ Set(name, value ? 1 : 0);
+ }
+
+ public void Set(int hash, bool value)
+ {
+ Set(hash, value ? 1 : 0);
+ }
+
+ public void Set(string name, long value)
+ {
+ Set(name.GetStableHashCode(), value);
+ }
+
+ public void Set(int hash, long value)
+ {
+ InitLongs();
+ if (!m_longs.TryGetValue(hash, out var value2) || value2 != value)
+ {
+ m_longs[hash] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void Set(string name, byte[] bytes)
+ {
+ string value = Convert.ToBase64String(bytes);
+ Set(name, value);
+ }
+
+ public byte[] GetByteArray(string name)
+ {
+ string @string = GetString(name);
+ if (@string.Length > 0)
+ {
+ return Convert.FromBase64String(@string);
+ }
+ return null;
+ }
+
+ public void Set(string name, string value)
+ {
+ InitStrings();
+ int stableHashCode = name.GetStableHashCode();
+ if (!m_strings.TryGetValue(stableHashCode, out var value2) || !(value2 == value))
+ {
+ m_strings[stableHashCode] = value;
+ IncreseDataRevision();
+ }
+ }
+
+ public void SetPosition(Vector3 pos)
+ {
+ InternalSetPosition(pos);
+ }
+
+ public void InternalSetPosition(Vector3 pos)
+ {
+ if (!(m_position == pos))
+ {
+ m_position = pos;
+ SetSector(ZoneSystem.instance.GetZone(m_position));
+ if (IsOwner())
+ {
+ IncreseDataRevision();
+ }
+ }
+ }
+
+ private void SetSector(Vector2i sector)
+ {
+ if (!(m_sector == sector))
+ {
+ m_zdoMan.RemoveFromSector(this, m_sector);
+ m_sector = sector;
+ m_zdoMan.AddToSector(this, m_sector);
+ m_zdoMan.ZDOSectorInvalidated(this);
+ }
+ }
+
+ public Vector2i GetSector()
+ {
+ return m_sector;
+ }
+
+ public void SetRotation(Quaternion rot)
+ {
+ if (!(m_rotation == rot))
+ {
+ m_rotation = rot;
+ IncreseDataRevision();
+ }
+ }
+
+ public void SetType(ObjectType type)
+ {
+ if (m_type != type)
+ {
+ m_type = type;
+ IncreseDataRevision();
+ }
+ }
+
+ public void SetDistant(bool distant)
+ {
+ if (m_distant != distant)
+ {
+ m_distant = distant;
+ IncreseDataRevision();
+ }
+ }
+
+ public void SetPrefab(int prefab)
+ {
+ if (m_prefab != prefab)
+ {
+ m_prefab = prefab;
+ IncreseDataRevision();
+ }
+ }
+
+ public int GetPrefab()
+ {
+ return m_prefab;
+ }
+
+ public Vector3 GetPosition()
+ {
+ return m_position;
+ }
+
+ public Quaternion GetRotation()
+ {
+ return m_rotation;
+ }
+
+ private void IncreseDataRevision()
+ {
+ m_dataRevision++;
+ if (!ZNet.instance.IsServer())
+ {
+ ZDOMan.instance.ClientChanged(m_uid);
+ }
+ }
+
+ private void IncreseOwnerRevision()
+ {
+ m_ownerRevision++;
+ if (!ZNet.instance.IsServer())
+ {
+ ZDOMan.instance.ClientChanged(m_uid);
+ }
+ }
+
+ public float GetFloat(string name, float defaultValue = 0f)
+ {
+ return GetFloat(name.GetStableHashCode(), defaultValue);
+ }
+
+ public float GetFloat(int hash, float defaultValue = 0f)
+ {
+ if (m_floats == null)
+ {
+ return defaultValue;
+ }
+ if (m_floats.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public Vector3 GetVec3(string name, Vector3 defaultValue)
+ {
+ return GetVec3(name.GetStableHashCode(), defaultValue);
+ }
+
+ public Vector3 GetVec3(int hash, Vector3 defaultValue)
+ {
+ if (m_vec3 == null)
+ {
+ return defaultValue;
+ }
+ if (m_vec3.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public Quaternion GetQuaternion(string name, Quaternion defaultValue)
+ {
+ return GetQuaternion(name.GetStableHashCode(), defaultValue);
+ }
+
+ public Quaternion GetQuaternion(int hash, Quaternion defaultValue)
+ {
+ if (m_quats == null)
+ {
+ return defaultValue;
+ }
+ if (m_quats.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public int GetInt(string name, int defaultValue = 0)
+ {
+ return GetInt(name.GetStableHashCode(), defaultValue);
+ }
+
+ public int GetInt(int hash, int defaultValue = 0)
+ {
+ if (m_ints == null)
+ {
+ return defaultValue;
+ }
+ if (m_ints.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public bool GetBool(string name, bool defaultValue = false)
+ {
+ return GetBool(name.GetStableHashCode(), defaultValue);
+ }
+
+ public bool GetBool(int hash, bool defaultValue = false)
+ {
+ if (m_ints == null)
+ {
+ return defaultValue;
+ }
+ if (m_ints.TryGetValue(hash, out var value))
+ {
+ return value != 0;
+ }
+ return defaultValue;
+ }
+
+ public long GetLong(string name, long defaultValue = 0L)
+ {
+ return GetLong(name.GetStableHashCode(), defaultValue);
+ }
+
+ public long GetLong(int hash, long defaultValue = 0L)
+ {
+ if (m_longs == null)
+ {
+ return defaultValue;
+ }
+ if (m_longs.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public string GetString(string name, string defaultValue = "")
+ {
+ if (m_strings == null)
+ {
+ return defaultValue;
+ }
+ if (m_strings.TryGetValue(name.GetStableHashCode(), out var value))
+ {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ public void Serialize(ZPackage pkg)
+ {
+ pkg.Write(m_persistent);
+ pkg.Write(m_distant);
+ pkg.Write(m_timeCreated);
+ pkg.Write(m_pgwVersion);
+ pkg.Write((sbyte)m_type);
+ pkg.Write(m_prefab);
+ pkg.Write(m_rotation);
+ int num = 0;
+ if (m_floats != null && m_floats.Count > 0)
+ {
+ num |= 1;
+ }
+ if (m_vec3 != null && m_vec3.Count > 0)
+ {
+ num |= 2;
+ }
+ if (m_quats != null && m_quats.Count > 0)
+ {
+ num |= 4;
+ }
+ if (m_ints != null && m_ints.Count > 0)
+ {
+ num |= 8;
+ }
+ if (m_strings != null && m_strings.Count > 0)
+ {
+ num |= 0x10;
+ }
+ if (m_longs != null && m_longs.Count > 0)
+ {
+ num |= 0x40;
+ }
+ pkg.Write(num);
+ if (m_floats != null && m_floats.Count > 0)
+ {
+ pkg.Write((byte)m_floats.Count);
+ foreach (KeyValuePair<int, float> @float in m_floats)
+ {
+ pkg.Write(@float.Key);
+ pkg.Write(@float.Value);
+ }
+ }
+ if (m_vec3 != null && m_vec3.Count > 0)
+ {
+ pkg.Write((byte)m_vec3.Count);
+ foreach (KeyValuePair<int, Vector3> item in m_vec3)
+ {
+ pkg.Write(item.Key);
+ pkg.Write(item.Value);
+ }
+ }
+ if (m_quats != null && m_quats.Count > 0)
+ {
+ pkg.Write((byte)m_quats.Count);
+ foreach (KeyValuePair<int, Quaternion> quat in m_quats)
+ {
+ pkg.Write(quat.Key);
+ pkg.Write(quat.Value);
+ }
+ }
+ if (m_ints != null && m_ints.Count > 0)
+ {
+ pkg.Write((byte)m_ints.Count);
+ foreach (KeyValuePair<int, int> @int in m_ints)
+ {
+ pkg.Write(@int.Key);
+ pkg.Write(@int.Value);
+ }
+ }
+ if (m_longs != null && m_longs.Count > 0)
+ {
+ pkg.Write((byte)m_longs.Count);
+ foreach (KeyValuePair<int, long> @long in m_longs)
+ {
+ pkg.Write(@long.Key);
+ pkg.Write(@long.Value);
+ }
+ }
+ if (m_strings == null || m_strings.Count <= 0)
+ {
+ return;
+ }
+ pkg.Write((byte)m_strings.Count);
+ foreach (KeyValuePair<int, string> @string in m_strings)
+ {
+ pkg.Write(@string.Key);
+ pkg.Write(@string.Value);
+ }
+ }
+
+ public void Deserialize(ZPackage pkg)
+ {
+ m_persistent = pkg.ReadBool();
+ m_distant = pkg.ReadBool();
+ m_timeCreated = pkg.ReadLong();
+ m_pgwVersion = pkg.ReadInt();
+ m_type = (ObjectType)pkg.ReadSByte();
+ m_prefab = pkg.ReadInt();
+ m_rotation = pkg.ReadQuaternion();
+ int num = pkg.ReadInt();
+ if (((uint)num & (true ? 1u : 0u)) != 0)
+ {
+ InitFloats();
+ int num2 = pkg.ReadByte();
+ for (int i = 0; i < num2; i++)
+ {
+ int key = pkg.ReadInt();
+ m_floats[key] = pkg.ReadSingle();
+ }
+ }
+ else
+ {
+ ReleaseFloats();
+ }
+ if (((uint)num & 2u) != 0)
+ {
+ InitVec3();
+ int num3 = pkg.ReadByte();
+ for (int j = 0; j < num3; j++)
+ {
+ int key2 = pkg.ReadInt();
+ m_vec3[key2] = pkg.ReadVector3();
+ }
+ }
+ else
+ {
+ ReleaseVec3();
+ }
+ if (((uint)num & 4u) != 0)
+ {
+ InitQuats();
+ int num4 = pkg.ReadByte();
+ for (int k = 0; k < num4; k++)
+ {
+ int key3 = pkg.ReadInt();
+ m_quats[key3] = pkg.ReadQuaternion();
+ }
+ }
+ else
+ {
+ ReleaseQuats();
+ }
+ if (((uint)num & 8u) != 0)
+ {
+ InitInts();
+ int num5 = pkg.ReadByte();
+ for (int l = 0; l < num5; l++)
+ {
+ int key4 = pkg.ReadInt();
+ m_ints[key4] = pkg.ReadInt();
+ }
+ }
+ else
+ {
+ ReleaseInts();
+ }
+ if (((uint)num & 0x40u) != 0)
+ {
+ InitLongs();
+ int num6 = pkg.ReadByte();
+ for (int m = 0; m < num6; m++)
+ {
+ int key5 = pkg.ReadInt();
+ m_longs[key5] = pkg.ReadLong();
+ }
+ }
+ else
+ {
+ ReleaseLongs();
+ }
+ if (((uint)num & 0x10u) != 0)
+ {
+ InitStrings();
+ int num7 = pkg.ReadByte();
+ for (int n = 0; n < num7; n++)
+ {
+ int key6 = pkg.ReadInt();
+ m_strings[key6] = pkg.ReadString();
+ }
+ }
+ else
+ {
+ ReleaseStrings();
+ }
+ }
+
+ public void Save(ZPackage pkg)
+ {
+ pkg.Write(m_ownerRevision);
+ pkg.Write(m_dataRevision);
+ pkg.Write(m_persistent);
+ pkg.Write(m_owner);
+ pkg.Write(m_timeCreated);
+ pkg.Write(m_pgwVersion);
+ pkg.Write((sbyte)m_type);
+ pkg.Write(m_distant);
+ pkg.Write(m_prefab);
+ pkg.Write(m_sector);
+ pkg.Write(m_position);
+ pkg.Write(m_rotation);
+ if (m_floats != null)
+ {
+ pkg.Write((char)m_floats.Count);
+ foreach (KeyValuePair<int, float> @float in m_floats)
+ {
+ pkg.Write(@float.Key);
+ pkg.Write(@float.Value);
+ }
+ }
+ else
+ {
+ pkg.Write('\0');
+ }
+ if (m_vec3 != null)
+ {
+ pkg.Write((char)m_vec3.Count);
+ foreach (KeyValuePair<int, Vector3> item in m_vec3)
+ {
+ pkg.Write(item.Key);
+ pkg.Write(item.Value);
+ }
+ }
+ else
+ {
+ pkg.Write('\0');
+ }
+ if (m_quats != null)
+ {
+ pkg.Write((char)m_quats.Count);
+ foreach (KeyValuePair<int, Quaternion> quat in m_quats)
+ {
+ pkg.Write(quat.Key);
+ pkg.Write(quat.Value);
+ }
+ }
+ else
+ {
+ pkg.Write('\0');
+ }
+ if (m_ints != null)
+ {
+ pkg.Write((char)m_ints.Count);
+ foreach (KeyValuePair<int, int> @int in m_ints)
+ {
+ pkg.Write(@int.Key);
+ pkg.Write(@int.Value);
+ }
+ }
+ else
+ {
+ pkg.Write('\0');
+ }
+ if (m_longs != null)
+ {
+ pkg.Write((char)m_longs.Count);
+ foreach (KeyValuePair<int, long> @long in m_longs)
+ {
+ pkg.Write(@long.Key);
+ pkg.Write(@long.Value);
+ }
+ }
+ else
+ {
+ pkg.Write('\0');
+ }
+ if (m_strings != null)
+ {
+ pkg.Write((char)m_strings.Count);
+ {
+ foreach (KeyValuePair<int, string> @string in m_strings)
+ {
+ pkg.Write(@string.Key);
+ pkg.Write(@string.Value);
+ }
+ return;
+ }
+ }
+ pkg.Write('\0');
+ }
+
+ public void Load(ZPackage pkg, int version)
+ {
+ m_ownerRevision = pkg.ReadUInt();
+ m_dataRevision = pkg.ReadUInt();
+ m_persistent = pkg.ReadBool();
+ m_owner = pkg.ReadLong();
+ m_timeCreated = pkg.ReadLong();
+ m_pgwVersion = pkg.ReadInt();
+ if (version >= 16 && version < 24)
+ {
+ pkg.ReadInt();
+ }
+ if (version >= 23)
+ {
+ m_type = (ObjectType)pkg.ReadSByte();
+ }
+ if (version >= 22)
+ {
+ m_distant = pkg.ReadBool();
+ }
+ if (version < 13)
+ {
+ pkg.ReadChar();
+ pkg.ReadChar();
+ }
+ if (version >= 17)
+ {
+ m_prefab = pkg.ReadInt();
+ }
+ m_sector = pkg.ReadVector2i();
+ m_position = pkg.ReadVector3();
+ m_rotation = pkg.ReadQuaternion();
+ int num = pkg.ReadChar();
+ if (num > 0)
+ {
+ InitFloats();
+ for (int i = 0; i < num; i++)
+ {
+ int key = pkg.ReadInt();
+ m_floats[key] = pkg.ReadSingle();
+ }
+ }
+ else
+ {
+ ReleaseFloats();
+ }
+ int num2 = pkg.ReadChar();
+ if (num2 > 0)
+ {
+ InitVec3();
+ for (int j = 0; j < num2; j++)
+ {
+ int key2 = pkg.ReadInt();
+ m_vec3[key2] = pkg.ReadVector3();
+ }
+ }
+ else
+ {
+ ReleaseVec3();
+ }
+ int num3 = pkg.ReadChar();
+ if (num3 > 0)
+ {
+ InitQuats();
+ for (int k = 0; k < num3; k++)
+ {
+ int key3 = pkg.ReadInt();
+ m_quats[key3] = pkg.ReadQuaternion();
+ }
+ }
+ else
+ {
+ ReleaseQuats();
+ }
+ int num4 = pkg.ReadChar();
+ if (num4 > 0)
+ {
+ InitInts();
+ for (int l = 0; l < num4; l++)
+ {
+ int key4 = pkg.ReadInt();
+ m_ints[key4] = pkg.ReadInt();
+ }
+ }
+ else
+ {
+ ReleaseInts();
+ }
+ int num5 = pkg.ReadChar();
+ if (num5 > 0)
+ {
+ InitLongs();
+ for (int m = 0; m < num5; m++)
+ {
+ int key5 = pkg.ReadInt();
+ m_longs[key5] = pkg.ReadLong();
+ }
+ }
+ else
+ {
+ ReleaseLongs();
+ }
+ int num6 = pkg.ReadChar();
+ if (num6 > 0)
+ {
+ InitStrings();
+ for (int n = 0; n < num6; n++)
+ {
+ int key6 = pkg.ReadInt();
+ m_strings[key6] = pkg.ReadString();
+ }
+ }
+ else
+ {
+ ReleaseStrings();
+ }
+ if (version < 17)
+ {
+ m_prefab = GetInt("prefab");
+ }
+ }
+
+ public bool IsOwner()
+ {
+ return m_owner == m_zdoMan.GetMyID();
+ }
+
+ public bool HasOwner()
+ {
+ return m_owner != 0;
+ }
+
+ public void Print()
+ {
+ ZLog.Log("UID:" + m_uid);
+ ZLog.Log("Persistent:" + m_persistent);
+ ZLog.Log("Owner:" + m_owner);
+ ZLog.Log("Revision:" + m_ownerRevision);
+ foreach (KeyValuePair<int, float> @float in m_floats)
+ {
+ ZLog.Log("F:" + @float.Key + " = " + @float.Value);
+ }
+ }
+
+ public void SetOwner(long uid)
+ {
+ if (m_owner != uid)
+ {
+ m_owner = uid;
+ IncreseOwnerRevision();
+ }
+ }
+
+ public void SetPGWVersion(int version)
+ {
+ m_pgwVersion = version;
+ }
+
+ public int GetPGWVersion()
+ {
+ return m_pgwVersion;
+ }
+
+ private void InitFloats()
+ {
+ if (m_floats == null)
+ {
+ m_floats = Pool<Dictionary<int, float>>.Create();
+ m_floats.Clear();
+ }
+ }
+
+ private void InitVec3()
+ {
+ if (m_vec3 == null)
+ {
+ m_vec3 = Pool<Dictionary<int, Vector3>>.Create();
+ m_vec3.Clear();
+ }
+ }
+
+ private void InitQuats()
+ {
+ if (m_quats == null)
+ {
+ m_quats = Pool<Dictionary<int, Quaternion>>.Create();
+ m_quats.Clear();
+ }
+ }
+
+ private void InitInts()
+ {
+ if (m_ints == null)
+ {
+ m_ints = Pool<Dictionary<int, int>>.Create();
+ m_ints.Clear();
+ }
+ }
+
+ private void InitLongs()
+ {
+ if (m_longs == null)
+ {
+ m_longs = Pool<Dictionary<int, long>>.Create();
+ m_longs.Clear();
+ }
+ }
+
+ private void InitStrings()
+ {
+ if (m_strings == null)
+ {
+ m_strings = Pool<Dictionary<int, string>>.Create();
+ m_strings.Clear();
+ }
+ }
+
+ private void ReleaseFloats()
+ {
+ if (m_floats != null)
+ {
+ Pool<Dictionary<int, float>>.Release(m_floats);
+ m_floats = null;
+ }
+ }
+
+ private void ReleaseVec3()
+ {
+ if (m_vec3 != null)
+ {
+ Pool<Dictionary<int, Vector3>>.Release(m_vec3);
+ m_vec3 = null;
+ }
+ }
+
+ private void ReleaseQuats()
+ {
+ if (m_quats != null)
+ {
+ Pool<Dictionary<int, Quaternion>>.Release(m_quats);
+ m_quats = null;
+ }
+ }
+
+ private void ReleaseInts()
+ {
+ if (m_ints != null)
+ {
+ Pool<Dictionary<int, int>>.Release(m_ints);
+ m_ints = null;
+ }
+ }
+
+ private void ReleaseLongs()
+ {
+ if (m_longs != null)
+ {
+ Pool<Dictionary<int, long>>.Release(m_longs);
+ m_longs = null;
+ }
+ }
+
+ private void ReleaseStrings()
+ {
+ if (m_strings != null)
+ {
+ Pool<Dictionary<int, string>>.Release(m_strings);
+ m_strings = null;
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOComparer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOComparer.cs
new file mode 100644
index 0000000..68aad96
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOComparer.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+internal class ZDOComparer : IEqualityComparer<ZDO>
+{
+ public bool Equals(ZDO a, ZDO b)
+ {
+ return a == b;
+ }
+
+ public int GetHashCode(ZDO a)
+ {
+ return a.GetHashCode();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOID.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOID.cs
new file mode 100644
index 0000000..6814e25
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOID.cs
@@ -0,0 +1,105 @@
+using System;
+using System.IO;
+
+public struct ZDOID : IEquatable<ZDOID>
+{
+ public static ZDOID None = new ZDOID(0L, 0u);
+
+ private long m_userID;
+
+ private uint m_id;
+
+ private int m_hash;
+
+ public long userID => m_userID;
+
+ public uint id => m_id;
+
+ public ZDOID(BinaryReader reader)
+ {
+ m_userID = reader.ReadInt64();
+ m_id = reader.ReadUInt32();
+ m_hash = 0;
+ }
+
+ public ZDOID(long userID, uint id)
+ {
+ m_userID = userID;
+ m_id = id;
+ m_hash = 0;
+ }
+
+ public ZDOID(ZDOID other)
+ {
+ m_userID = other.m_userID;
+ m_id = other.m_id;
+ m_hash = other.m_hash;
+ }
+
+ public override string ToString()
+ {
+ return m_userID + ":" + m_id;
+ }
+
+ public static bool operator ==(ZDOID a, ZDOID b)
+ {
+ if (a.m_userID == b.m_userID)
+ {
+ return a.m_id == b.m_id;
+ }
+ return false;
+ }
+
+ public static bool operator !=(ZDOID a, ZDOID b)
+ {
+ if (a.m_userID == b.m_userID)
+ {
+ return a.m_id != b.m_id;
+ }
+ return true;
+ }
+
+ public bool Equals(ZDOID other)
+ {
+ if (other.m_userID == m_userID)
+ {
+ return other.m_id == m_id;
+ }
+ return false;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj is ZDOID zDOID)
+ {
+ if (zDOID.m_userID == m_userID)
+ {
+ return zDOID.m_id == m_id;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ if (m_hash == 0)
+ {
+ m_hash = m_userID.GetHashCode() ^ m_id.GetHashCode();
+ }
+ return m_hash;
+ }
+
+ public bool IsNone()
+ {
+ if (m_userID == 0L)
+ {
+ return m_id == 0;
+ }
+ return false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOMan.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOMan.cs
new file mode 100644
index 0000000..7544039
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOMan.cs
@@ -0,0 +1,1207 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using UnityEngine;
+
+public class ZDOMan
+{
+ private class ZDOPeer
+ {
+ public struct PeerZDOInfo
+ {
+ public uint m_dataRevision;
+
+ public long m_ownerRevision;
+
+ public float m_syncTime;
+
+ public PeerZDOInfo(uint dataRevision, uint ownerRevision, float syncTime)
+ {
+ m_dataRevision = dataRevision;
+ m_ownerRevision = ownerRevision;
+ m_syncTime = syncTime;
+ }
+ }
+
+ public ZNetPeer m_peer;
+
+ public Dictionary<ZDOID, PeerZDOInfo> m_zdos = new Dictionary<ZDOID, PeerZDOInfo>();
+
+ public HashSet<ZDOID> m_forceSend = new HashSet<ZDOID>();
+
+ public int m_sendIndex;
+
+ public void ZDOSectorInvalidated(ZDOID uid)
+ {
+ if (m_zdos.ContainsKey(uid))
+ {
+ ForceSendZDO(uid);
+ }
+ }
+
+ public void ForceSendZDO(ZDOID id)
+ {
+ m_forceSend.Add(id);
+ }
+
+ public bool ShouldSend(ZDO zdo)
+ {
+ if (m_zdos.TryGetValue(zdo.m_uid, out var value))
+ {
+ if (zdo.m_ownerRevision <= value.m_ownerRevision)
+ {
+ return zdo.m_dataRevision > value.m_dataRevision;
+ }
+ return true;
+ }
+ return true;
+ }
+ }
+
+ private class SaveData
+ {
+ public long m_myid;
+
+ public uint m_nextUid = 1u;
+
+ public List<ZDO> m_zdos;
+
+ public Dictionary<ZDOID, long> m_deadZDOs;
+ }
+
+ private static long compareReceiver;
+
+ public Action<ZDO> m_onZDODestroyed;
+
+ private Dictionary<ZDOID, ZDO> m_objectsByID = new Dictionary<ZDOID, ZDO>();
+
+ private List<ZDO>[] m_objectsBySector;
+
+ private Dictionary<Vector2i, List<ZDO>> m_objectsByOutsideSector = new Dictionary<Vector2i, List<ZDO>>();
+
+ private List<ZDOPeer> m_peers = new List<ZDOPeer>();
+
+ private const int m_maxDeadZDOs = 100000;
+
+ private Dictionary<ZDOID, long> m_deadZDOs = new Dictionary<ZDOID, long>();
+
+ private List<ZDOID> m_destroySendList = new List<ZDOID>();
+
+ private HashSet<ZDOID> m_clientChangeQueue = new HashSet<ZDOID>();
+
+ private long m_myid;
+
+ private uint m_nextUid = 1u;
+
+ private int m_width;
+
+ private int m_halfWidth;
+
+ private int m_dataPerSec = 61440;
+
+ private float m_sendTimer;
+
+ private const float m_sendFPS = 20f;
+
+ private float m_releaseZDOTimer;
+
+ private static ZDOMan m_instance;
+
+ private int m_zdosSent;
+
+ private int m_zdosRecv;
+
+ private int m_zdosSentLastSec;
+
+ private int m_zdosRecvLastSec;
+
+ private float m_statTimer;
+
+ private List<ZDO> m_tempToSync = new List<ZDO>();
+
+ private List<ZDO> m_tempToSyncDistant = new List<ZDO>();
+
+ private List<ZDO> m_tempNearObjects = new List<ZDO>();
+
+ private List<ZDOID> m_tempRemoveList = new List<ZDOID>();
+
+ private SaveData m_saveData;
+
+ public static ZDOMan instance => m_instance;
+
+ public ZDOMan(int width)
+ {
+ m_instance = this;
+ m_myid = Utils.GenerateUID();
+ ZRoutedRpc.instance.Register<ZPackage>("DestroyZDO", RPC_DestroyZDO);
+ ZRoutedRpc.instance.Register<ZDOID>("RequestZDO", RPC_RequestZDO);
+ m_width = width;
+ m_halfWidth = m_width / 2;
+ ResetSectorArray();
+ }
+
+ private void ResetSectorArray()
+ {
+ m_objectsBySector = new List<ZDO>[m_width * m_width];
+ m_objectsByOutsideSector.Clear();
+ }
+
+ public void ShutDown()
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ int num = FlushClientObjects();
+ ZLog.Log("Flushed " + num + " objects");
+ }
+ ZDOPool.Release(m_objectsByID);
+ m_objectsByID.Clear();
+ m_tempToSync.Clear();
+ m_tempToSyncDistant.Clear();
+ m_tempNearObjects.Clear();
+ m_tempRemoveList.Clear();
+ m_peers.Clear();
+ ResetSectorArray();
+ GC.Collect();
+ }
+
+ public void PrepareSave()
+ {
+ m_saveData = new SaveData();
+ m_saveData.m_myid = m_myid;
+ m_saveData.m_nextUid = m_nextUid;
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ m_saveData.m_zdos = GetSaveClone();
+ ZLog.Log("clone " + stopwatch.ElapsedMilliseconds);
+ m_saveData.m_deadZDOs = new Dictionary<ZDOID, long>(m_deadZDOs);
+ }
+
+ public void SaveAsync(BinaryWriter writer)
+ {
+ writer.Write(m_saveData.m_myid);
+ writer.Write(m_saveData.m_nextUid);
+ ZPackage zPackage = new ZPackage();
+ writer.Write(m_saveData.m_zdos.Count);
+ foreach (ZDO zdo in m_saveData.m_zdos)
+ {
+ writer.Write(zdo.m_uid.userID);
+ writer.Write(zdo.m_uid.id);
+ zPackage.Clear();
+ zdo.Save(zPackage);
+ byte[] array = zPackage.GetArray();
+ writer.Write(array.Length);
+ writer.Write(array);
+ }
+ writer.Write(m_saveData.m_deadZDOs.Count);
+ foreach (KeyValuePair<ZDOID, long> deadZDO in m_saveData.m_deadZDOs)
+ {
+ writer.Write(deadZDO.Key.userID);
+ writer.Write(deadZDO.Key.id);
+ writer.Write(deadZDO.Value);
+ }
+ ZLog.Log("Saved " + m_saveData.m_zdos.Count + " zdos");
+ m_saveData = null;
+ }
+
+ public void Load(BinaryReader reader, int version)
+ {
+ try
+ {
+ reader.ReadInt64();
+ uint num = reader.ReadUInt32();
+ int num2 = reader.ReadInt32();
+ ZDOPool.Release(m_objectsByID);
+ m_objectsByID.Clear();
+ ResetSectorArray();
+ ZLog.Log("Loading " + num2 + " zdos , my id " + m_myid + " data version:" + version);
+ ZPackage zPackage = new ZPackage();
+ for (int i = 0; i < num2; i++)
+ {
+ ZDO zDO = ZDOPool.Create(this);
+ zDO.m_uid = new ZDOID(reader);
+ int count = reader.ReadInt32();
+ byte[] data = reader.ReadBytes(count);
+ zPackage.Load(data);
+ zDO.Load(zPackage, version);
+ zDO.SetOwner(0L);
+ m_objectsByID.Add(zDO.m_uid, zDO);
+ AddToSector(zDO, zDO.GetSector());
+ if (zDO.m_uid.userID == m_myid && zDO.m_uid.id >= num)
+ {
+ num = zDO.m_uid.id + 1;
+ }
+ }
+ m_deadZDOs.Clear();
+ int num3 = reader.ReadInt32();
+ for (int j = 0; j < num3; j++)
+ {
+ ZDOID key = new ZDOID(reader.ReadInt64(), reader.ReadUInt32());
+ long value = reader.ReadInt64();
+ m_deadZDOs.Add(key, value);
+ if (key.userID == m_myid && key.id >= num)
+ {
+ num = key.id + 1;
+ }
+ }
+ CapDeadZDOList();
+ ZLog.Log("Loaded " + m_deadZDOs.Count + " dead zdos");
+ RemoveOldGeneratedZDOS();
+ m_nextUid = num;
+ }
+ catch (Exception ex)
+ {
+ ZLog.LogError("Exception while loading ZDO data:" + ex.ToString());
+ ZDOPool.Release(m_objectsByID);
+ m_objectsByID.Clear();
+ ResetSectorArray();
+ m_deadZDOs.Clear();
+ m_myid = Utils.GenerateUID();
+ m_nextUid = 1u;
+ }
+ }
+
+ private void RemoveOldGeneratedZDOS()
+ {
+ List<ZDOID> list = new List<ZDOID>();
+ foreach (KeyValuePair<ZDOID, ZDO> item in m_objectsByID)
+ {
+ int pGWVersion = item.Value.GetPGWVersion();
+ if (pGWVersion != 0 && pGWVersion != ZoneSystem.instance.m_pgwVersion)
+ {
+ list.Add(item.Key);
+ RemoveFromSector(item.Value, item.Value.GetSector());
+ ZDOPool.Release(item.Value);
+ }
+ }
+ foreach (ZDOID item2 in list)
+ {
+ m_objectsByID.Remove(item2);
+ }
+ ZLog.Log("Removed " + list.Count + " OLD generated ZDOS");
+ }
+
+ private void CapDeadZDOList()
+ {
+ if (m_deadZDOs.Count > 100000)
+ {
+ List<KeyValuePair<ZDOID, long>> list = m_deadZDOs.ToList();
+ list.Sort((KeyValuePair<ZDOID, long> a, KeyValuePair<ZDOID, long> b) => a.Value.CompareTo(b.Value));
+ int num = list.Count - 100000;
+ for (int i = 0; i < num; i++)
+ {
+ m_deadZDOs.Remove(list[i].Key);
+ }
+ }
+ }
+
+ public ZDO CreateNewZDO(Vector3 position)
+ {
+ ZDOID zDOID = new ZDOID(m_myid, m_nextUid++);
+ while (GetZDO(zDOID) != null)
+ {
+ zDOID = new ZDOID(m_myid, m_nextUid++);
+ }
+ return CreateNewZDO(zDOID, position);
+ }
+
+ public ZDO CreateNewZDO(ZDOID uid, Vector3 position)
+ {
+ ZDO zDO = ZDOPool.Create(this, uid, position);
+ zDO.m_owner = m_myid;
+ zDO.m_timeCreated = ZNet.instance.GetTime().Ticks;
+ m_objectsByID.Add(uid, zDO);
+ return zDO;
+ }
+
+ public void AddToSector(ZDO zdo, Vector2i sector)
+ {
+ int num = SectorToIndex(sector);
+ List<ZDO> value;
+ if (num >= 0 && num < m_objectsBySector.Length)
+ {
+ if (m_objectsBySector[num] != null)
+ {
+ m_objectsBySector[num].Add(zdo);
+ return;
+ }
+ List<ZDO> list = new List<ZDO>();
+ list.Add(zdo);
+ m_objectsBySector[num] = list;
+ }
+ else if (m_objectsByOutsideSector.TryGetValue(sector, out value))
+ {
+ value.Add(zdo);
+ }
+ else
+ {
+ value = new List<ZDO>();
+ value.Add(zdo);
+ m_objectsByOutsideSector.Add(sector, value);
+ }
+ }
+
+ public void ZDOSectorInvalidated(ZDO zdo)
+ {
+ ZDOID uid = zdo.m_uid;
+ foreach (ZDOPeer peer in m_peers)
+ {
+ peer.ZDOSectorInvalidated(uid);
+ }
+ }
+
+ public void RemoveFromSector(ZDO zdo, Vector2i sector)
+ {
+ int num = SectorToIndex(sector);
+ List<ZDO> value;
+ if (num >= 0 && num < m_objectsBySector.Length)
+ {
+ if (m_objectsBySector[num] != null)
+ {
+ m_objectsBySector[num].Remove(zdo);
+ }
+ }
+ else if (m_objectsByOutsideSector.TryGetValue(sector, out value))
+ {
+ value.Remove(zdo);
+ }
+ }
+
+ public ZDO GetZDO(ZDOID id)
+ {
+ if (id == ZDOID.None)
+ {
+ return null;
+ }
+ if (m_objectsByID.TryGetValue(id, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ public void AddPeer(ZNetPeer netPeer)
+ {
+ ZDOPeer zDOPeer = new ZDOPeer();
+ zDOPeer.m_peer = netPeer;
+ m_peers.Add(zDOPeer);
+ zDOPeer.m_peer.m_rpc.Register<ZPackage>("ZDOData", RPC_ZDOData);
+ }
+
+ public void RemovePeer(ZNetPeer netPeer)
+ {
+ ZDOPeer zDOPeer = FindPeer(netPeer);
+ if (zDOPeer != null)
+ {
+ m_peers.Remove(zDOPeer);
+ if (ZNet.instance.IsServer())
+ {
+ RemoveOrphanNonPersistentZDOS();
+ }
+ }
+ }
+
+ private ZDOPeer FindPeer(ZNetPeer netPeer)
+ {
+ foreach (ZDOPeer peer in m_peers)
+ {
+ if (peer.m_peer == netPeer)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ private ZDOPeer FindPeer(ZRpc rpc)
+ {
+ foreach (ZDOPeer peer in m_peers)
+ {
+ if (peer.m_peer.m_rpc == rpc)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public void Update(float dt)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ ReleaseZDOS(dt);
+ }
+ SendZDOToPeers(dt);
+ SendDestroyed();
+ UpdateStats(dt);
+ }
+
+ private void UpdateStats(float dt)
+ {
+ m_statTimer += dt;
+ if (m_statTimer >= 1f)
+ {
+ m_statTimer = 0f;
+ m_zdosSentLastSec = m_zdosSent;
+ m_zdosRecvLastSec = m_zdosRecv;
+ m_zdosRecv = 0;
+ m_zdosSent = 0;
+ }
+ }
+
+ private void SendZDOToPeers(float dt)
+ {
+ int num = 0;
+ m_sendTimer += dt;
+ if (m_sendTimer > 0.05f)
+ {
+ m_sendTimer = 0f;
+ foreach (ZDOPeer peer in m_peers)
+ {
+ num += SendZDOs(peer, flush: false);
+ }
+ }
+ m_zdosSent += num;
+ }
+
+ private int FlushClientObjects()
+ {
+ int num = 0;
+ foreach (ZDOPeer peer in m_peers)
+ {
+ num += SendZDOs(peer, flush: true);
+ }
+ return num;
+ }
+
+ private void ReleaseZDOS(float dt)
+ {
+ m_releaseZDOTimer += dt;
+ if (!(m_releaseZDOTimer > 2f))
+ {
+ return;
+ }
+ m_releaseZDOTimer = 0f;
+ ReleaseNearbyZDOS(ZNet.instance.GetReferencePosition(), m_myid);
+ foreach (ZDOPeer peer in m_peers)
+ {
+ ReleaseNearbyZDOS(peer.m_peer.m_refPos, peer.m_peer.m_uid);
+ }
+ }
+
+ private bool IsInPeerActiveArea(Vector2i sector, long uid)
+ {
+ if (uid == m_myid)
+ {
+ return ZNetScene.instance.InActiveArea(sector, ZNet.instance.GetReferencePosition());
+ }
+ ZNetPeer peer = ZNet.instance.GetPeer(uid);
+ if (peer == null)
+ {
+ return false;
+ }
+ return ZNetScene.instance.InActiveArea(sector, peer.GetRefPos());
+ }
+
+ private void ReleaseNearbyZDOS(Vector3 refPosition, long uid)
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(refPosition);
+ m_tempNearObjects.Clear();
+ FindSectorObjects(zone, ZoneSystem.instance.m_activeArea, 0, m_tempNearObjects);
+ foreach (ZDO tempNearObject in m_tempNearObjects)
+ {
+ if (!tempNearObject.m_persistent)
+ {
+ continue;
+ }
+ if (tempNearObject.m_owner == uid)
+ {
+ if (!ZNetScene.instance.InActiveArea(tempNearObject.GetSector(), zone))
+ {
+ tempNearObject.SetOwner(0L);
+ }
+ }
+ else if ((tempNearObject.m_owner == 0L || !IsInPeerActiveArea(tempNearObject.GetSector(), tempNearObject.m_owner)) && ZNetScene.instance.InActiveArea(tempNearObject.GetSector(), zone))
+ {
+ tempNearObject.SetOwner(uid);
+ }
+ }
+ }
+
+ public void DestroyZDO(ZDO zdo)
+ {
+ if (zdo.IsOwner())
+ {
+ m_destroySendList.Add(zdo.m_uid);
+ }
+ }
+
+ private void SendDestroyed()
+ {
+ if (m_destroySendList.Count == 0)
+ {
+ return;
+ }
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(m_destroySendList.Count);
+ foreach (ZDOID destroySend in m_destroySendList)
+ {
+ zPackage.Write(destroySend);
+ }
+ m_destroySendList.Clear();
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "DestroyZDO", zPackage);
+ }
+
+ private void RPC_DestroyZDO(long sender, ZPackage pkg)
+ {
+ int num = pkg.ReadInt();
+ for (int i = 0; i < num; i++)
+ {
+ ZDOID uid = pkg.ReadZDOID();
+ HandleDestroyedZDO(uid);
+ }
+ }
+
+ private void HandleDestroyedZDO(ZDOID uid)
+ {
+ if (uid.userID == m_myid && uid.id >= m_nextUid)
+ {
+ m_nextUid = uid.id + 1;
+ }
+ ZDO zDO = GetZDO(uid);
+ if (zDO == null)
+ {
+ return;
+ }
+ if (m_onZDODestroyed != null)
+ {
+ m_onZDODestroyed(zDO);
+ }
+ RemoveFromSector(zDO, zDO.GetSector());
+ m_objectsByID.Remove(zDO.m_uid);
+ ZDOPool.Release(zDO);
+ foreach (ZDOPeer peer in m_peers)
+ {
+ peer.m_zdos.Remove(uid);
+ }
+ if (ZNet.instance.IsServer())
+ {
+ long ticks = ZNet.instance.GetTime().Ticks;
+ m_deadZDOs[uid] = ticks;
+ }
+ }
+
+ private int SendZDOs(ZDOPeer peer, bool flush)
+ {
+ if (!flush && peer.m_peer.m_socket.IsSending())
+ {
+ return 0;
+ }
+ float time = Time.time;
+ m_tempToSync.Clear();
+ CreateSyncList(peer, m_tempToSync);
+ if (m_tempToSync.Count <= 0)
+ {
+ return 0;
+ }
+ int num = m_dataPerSec / 20;
+ ZPackage zPackage = new ZPackage();
+ ZPackage zPackage2 = new ZPackage();
+ int num2 = 0;
+ for (int i = 0; i < m_tempToSync.Count; i++)
+ {
+ ZDO zDO = m_tempToSync[i];
+ peer.m_forceSend.Remove(zDO.m_uid);
+ if (!ZNet.instance.IsServer())
+ {
+ m_clientChangeQueue.Remove(zDO.m_uid);
+ }
+ if (peer.ShouldSend(zDO))
+ {
+ zPackage.Write(zDO.m_uid);
+ zPackage.Write(zDO.m_ownerRevision);
+ zPackage.Write(zDO.m_dataRevision);
+ zPackage.Write(zDO.m_owner);
+ zPackage.Write(zDO.GetPosition());
+ zPackage2.Clear();
+ zDO.Serialize(zPackage2);
+ zPackage.Write(zPackage2);
+ peer.m_zdos[zDO.m_uid] = new ZDOPeer.PeerZDOInfo(zDO.m_dataRevision, zDO.m_ownerRevision, time);
+ num2++;
+ if (!flush && zPackage.Size() > num)
+ {
+ break;
+ }
+ }
+ }
+ if (num2 > 0)
+ {
+ zPackage.Write(ZDOID.None);
+ peer.m_peer.m_rpc.Invoke("ZDOData", zPackage);
+ }
+ return num2;
+ }
+
+ private void RPC_ZDOData(ZRpc rpc, ZPackage pkg)
+ {
+ ZDOPeer zDOPeer = FindPeer(rpc);
+ if (zDOPeer == null)
+ {
+ ZLog.Log("ZDO data from unkown host, ignoring");
+ return;
+ }
+ float time = Time.time;
+ int num = 0;
+ ZPackage pkg2 = new ZPackage();
+ while (true)
+ {
+ ZDOID zDOID = pkg.ReadZDOID();
+ if (zDOID.IsNone())
+ {
+ break;
+ }
+ num++;
+ uint num2 = pkg.ReadUInt();
+ uint num3 = pkg.ReadUInt();
+ long owner = pkg.ReadLong();
+ Vector3 vector = pkg.ReadVector3();
+ pkg.ReadPackage(ref pkg2);
+ ZDO zDO = GetZDO(zDOID);
+ bool flag = false;
+ if (zDO != null)
+ {
+ if (num3 <= zDO.m_dataRevision)
+ {
+ if (num2 > zDO.m_ownerRevision)
+ {
+ zDO.m_owner = owner;
+ zDO.m_ownerRevision = num2;
+ zDOPeer.m_zdos[zDOID] = new ZDOPeer.PeerZDOInfo(num3, num2, time);
+ }
+ continue;
+ }
+ }
+ else
+ {
+ zDO = CreateNewZDO(zDOID, vector);
+ flag = true;
+ }
+ zDO.m_ownerRevision = num2;
+ zDO.m_dataRevision = num3;
+ zDO.m_owner = owner;
+ zDO.InternalSetPosition(vector);
+ zDOPeer.m_zdos[zDOID] = new ZDOPeer.PeerZDOInfo(zDO.m_dataRevision, zDO.m_ownerRevision, time);
+ zDO.Deserialize(pkg2);
+ if (ZNet.instance.IsServer() && flag && m_deadZDOs.ContainsKey(zDOID))
+ {
+ zDO.SetOwner(m_myid);
+ DestroyZDO(zDO);
+ }
+ }
+ m_zdosRecv += num;
+ }
+
+ public void FindSectorObjects(Vector2i sector, int area, int distantArea, List<ZDO> sectorObjects, List<ZDO> distantSectorObjects = null)
+ {
+ FindObjects(sector, sectorObjects);
+ for (int i = 1; i <= area; i++)
+ {
+ for (int j = sector.x - i; j <= sector.x + i; j++)
+ {
+ FindObjects(new Vector2i(j, sector.y - i), sectorObjects);
+ FindObjects(new Vector2i(j, sector.y + i), sectorObjects);
+ }
+ for (int k = sector.y - i + 1; k <= sector.y + i - 1; k++)
+ {
+ FindObjects(new Vector2i(sector.x - i, k), sectorObjects);
+ FindObjects(new Vector2i(sector.x + i, k), sectorObjects);
+ }
+ }
+ List<ZDO> objects = ((distantSectorObjects != null) ? distantSectorObjects : sectorObjects);
+ for (int l = area + 1; l <= area + distantArea; l++)
+ {
+ for (int m = sector.x - l; m <= sector.x + l; m++)
+ {
+ FindDistantObjects(new Vector2i(m, sector.y - l), objects);
+ FindDistantObjects(new Vector2i(m, sector.y + l), objects);
+ }
+ for (int n = sector.y - l + 1; n <= sector.y + l - 1; n++)
+ {
+ FindDistantObjects(new Vector2i(sector.x - l, n), objects);
+ FindDistantObjects(new Vector2i(sector.x + l, n), objects);
+ }
+ }
+ }
+
+ public void FindSectorObjects(Vector2i sector, int area, List<ZDO> sectorObjects)
+ {
+ for (int i = sector.y - area; i <= sector.y + area; i++)
+ {
+ for (int j = sector.x - area; j <= sector.x + area; j++)
+ {
+ Vector2i sector2 = new Vector2i(j, i);
+ FindObjects(sector2, sectorObjects);
+ }
+ }
+ }
+
+ private void CreateSyncList(ZDOPeer peer, List<ZDO> toSync)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ Vector3 refPos = peer.m_peer.GetRefPos();
+ Vector2i zone = ZoneSystem.instance.GetZone(refPos);
+ m_tempToSyncDistant.Clear();
+ FindSectorObjects(zone, ZoneSystem.instance.m_activeArea, ZoneSystem.instance.m_activeDistantArea, toSync, m_tempToSyncDistant);
+ ServerSortSendZDOS(toSync, refPos, peer);
+ toSync.AddRange(m_tempToSyncDistant);
+ AddForceSendZdos(peer, toSync);
+ return;
+ }
+ m_tempRemoveList.Clear();
+ foreach (ZDOID item in m_clientChangeQueue)
+ {
+ ZDO zDO = GetZDO(item);
+ if (zDO != null)
+ {
+ toSync.Add(zDO);
+ }
+ else
+ {
+ m_tempRemoveList.Add(item);
+ }
+ }
+ foreach (ZDOID tempRemove in m_tempRemoveList)
+ {
+ m_clientChangeQueue.Remove(tempRemove);
+ }
+ ClientSortSendZDOS(toSync, peer);
+ AddForceSendZdos(peer, toSync);
+ }
+
+ private void AddForceSendZdos(ZDOPeer peer, List<ZDO> syncList)
+ {
+ if (peer.m_forceSend.Count <= 0)
+ {
+ return;
+ }
+ m_tempRemoveList.Clear();
+ foreach (ZDOID item in peer.m_forceSend)
+ {
+ ZDO zDO = GetZDO(item);
+ if (zDO != null)
+ {
+ syncList.Insert(0, zDO);
+ }
+ else
+ {
+ m_tempRemoveList.Add(item);
+ }
+ }
+ foreach (ZDOID tempRemove in m_tempRemoveList)
+ {
+ peer.m_forceSend.Remove(tempRemove);
+ }
+ }
+
+ private static int ServerSendCompare(ZDO x, ZDO y)
+ {
+ bool flag = x.m_owner != compareReceiver;
+ bool flag2 = y.m_owner != compareReceiver;
+ if (flag && flag2)
+ {
+ if (x.m_type == y.m_type)
+ {
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+ if (x.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return -1;
+ }
+ if (y.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return 1;
+ }
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+ if (flag != flag2)
+ {
+ if (flag && x.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return -1;
+ }
+ if (flag2 && y.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return 1;
+ }
+ }
+ if (x.m_type == y.m_type)
+ {
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+ if (x.m_type == ZDO.ObjectType.Solid)
+ {
+ return -1;
+ }
+ if (y.m_type == ZDO.ObjectType.Solid)
+ {
+ return 1;
+ }
+ if (x.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return -1;
+ }
+ if (y.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return 1;
+ }
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+
+ private void ServerSortSendZDOS(List<ZDO> objects, Vector3 refPos, ZDOPeer peer)
+ {
+ float time = Time.time;
+ for (int i = 0; i < objects.Count; i++)
+ {
+ ZDO zDO = objects[i];
+ Vector3 position = zDO.GetPosition();
+ zDO.m_tempSortValue = Vector3.Distance(position, refPos);
+ float num = 100f;
+ if (peer.m_zdos.TryGetValue(zDO.m_uid, out var value))
+ {
+ num = Mathf.Clamp(time - value.m_syncTime, 0f, 100f);
+ zDO.m_tempHaveRevision = true;
+ }
+ else
+ {
+ zDO.m_tempHaveRevision = false;
+ }
+ zDO.m_tempSortValue -= num * 1.5f;
+ }
+ compareReceiver = peer.m_peer.m_uid;
+ objects.Sort(ServerSendCompare);
+ }
+
+ private static int ClientSendCompare(ZDO x, ZDO y)
+ {
+ if (x.m_type == y.m_type)
+ {
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+ if (x.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return -1;
+ }
+ if (y.m_type == ZDO.ObjectType.Prioritized)
+ {
+ return 1;
+ }
+ return x.m_tempSortValue.CompareTo(y.m_tempSortValue);
+ }
+
+ private void ClientSortSendZDOS(List<ZDO> objects, ZDOPeer peer)
+ {
+ float time = Time.time;
+ for (int i = 0; i < objects.Count; i++)
+ {
+ ZDO zDO = objects[i];
+ zDO.m_tempSortValue = 0f;
+ float num = 100f;
+ if (peer.m_zdos.TryGetValue(zDO.m_uid, out var value))
+ {
+ num = Mathf.Clamp(time - value.m_syncTime, 0f, 100f);
+ }
+ zDO.m_tempSortValue -= num * 1.5f;
+ }
+ objects.Sort(ClientSendCompare);
+ }
+
+ private void PrintZdoList(List<ZDO> zdos)
+ {
+ ZLog.Log("Sync list " + zdos.Count);
+ foreach (ZDO zdo in zdos)
+ {
+ string text = "";
+ int prefab = zdo.GetPrefab();
+ if (prefab != 0)
+ {
+ GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
+ if ((bool)prefab2)
+ {
+ text = prefab2.name;
+ }
+ }
+ ZLog.Log(" " + zdo.m_uid.ToString() + " " + zdo.m_ownerRevision + " prefab:" + text);
+ }
+ }
+
+ private void AddDistantObjects(ZDOPeer peer, int maxItems, List<ZDO> toSync)
+ {
+ if (peer.m_sendIndex >= m_objectsByID.Count)
+ {
+ peer.m_sendIndex = 0;
+ }
+ IEnumerable<KeyValuePair<ZDOID, ZDO>> enumerable = m_objectsByID.Skip(peer.m_sendIndex).Take(maxItems);
+ peer.m_sendIndex += maxItems;
+ foreach (KeyValuePair<ZDOID, ZDO> item in enumerable)
+ {
+ toSync.Add(item.Value);
+ }
+ }
+
+ public long GetMyID()
+ {
+ return m_myid;
+ }
+
+ private int SectorToIndex(Vector2i s)
+ {
+ return (s.y + m_halfWidth) * m_width + (s.x + m_halfWidth);
+ }
+
+ private void FindObjects(Vector2i sector, List<ZDO> objects)
+ {
+ int num = SectorToIndex(sector);
+ List<ZDO> value;
+ if (num >= 0 && num < m_objectsBySector.Length)
+ {
+ if (m_objectsBySector[num] != null)
+ {
+ objects.AddRange(m_objectsBySector[num]);
+ }
+ }
+ else if (m_objectsByOutsideSector.TryGetValue(sector, out value))
+ {
+ objects.AddRange(value);
+ }
+ }
+
+ private void FindDistantObjects(Vector2i sector, List<ZDO> objects)
+ {
+ int num = SectorToIndex(sector);
+ if (num >= 0 && num < m_objectsBySector.Length)
+ {
+ List<ZDO> list = m_objectsBySector[num];
+ if (list == null)
+ {
+ return;
+ }
+ for (int i = 0; i < list.Count; i++)
+ {
+ ZDO zDO = list[i];
+ if (zDO.m_distant)
+ {
+ objects.Add(zDO);
+ }
+ }
+ }
+ else
+ {
+ if (!m_objectsByOutsideSector.TryGetValue(sector, out var value))
+ {
+ return;
+ }
+ for (int j = 0; j < value.Count; j++)
+ {
+ ZDO zDO2 = value[j];
+ if (zDO2.m_distant)
+ {
+ objects.Add(zDO2);
+ }
+ }
+ }
+ }
+
+ private void RemoveOrphanNonPersistentZDOS()
+ {
+ foreach (KeyValuePair<ZDOID, ZDO> item in m_objectsByID)
+ {
+ ZDO value = item.Value;
+ if (!value.m_persistent && (value.m_owner == 0L || !IsPeerConnected(value.m_owner)))
+ {
+ ZLog.Log(string.Concat("Destroying abandoned non persistent zdo ", value.m_uid, " owner ", value.m_owner));
+ value.SetOwner(m_myid);
+ DestroyZDO(value);
+ }
+ }
+ }
+
+ private bool IsPeerConnected(long uid)
+ {
+ if (m_myid == uid)
+ {
+ return true;
+ }
+ foreach (ZDOPeer peer in m_peers)
+ {
+ if (peer.m_peer.m_uid == uid)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void GetAllZDOsWithPrefab(string prefab, List<ZDO> zdos)
+ {
+ int stableHashCode = prefab.GetStableHashCode();
+ foreach (ZDO value in m_objectsByID.Values)
+ {
+ if (value.GetPrefab() == stableHashCode)
+ {
+ zdos.Add(value);
+ }
+ }
+ }
+
+ private static bool InvalidZDO(ZDO zdo)
+ {
+ return !zdo.IsValid();
+ }
+
+ public bool GetAllZDOsWithPrefabIterative(string prefab, List<ZDO> zdos, ref int index)
+ {
+ int stableHashCode = prefab.GetStableHashCode();
+ if (index >= m_objectsBySector.Length)
+ {
+ foreach (List<ZDO> value in m_objectsByOutsideSector.Values)
+ {
+ foreach (ZDO item in value)
+ {
+ if (item.GetPrefab() == stableHashCode)
+ {
+ zdos.Add(item);
+ }
+ }
+ }
+ zdos.RemoveAll(InvalidZDO);
+ return true;
+ }
+ int num = 0;
+ while (index < m_objectsBySector.Length)
+ {
+ List<ZDO> list = m_objectsBySector[index];
+ if (list != null)
+ {
+ foreach (ZDO item2 in list)
+ {
+ if (item2.GetPrefab() == stableHashCode)
+ {
+ zdos.Add(item2);
+ }
+ }
+ num++;
+ if (num > 400)
+ {
+ break;
+ }
+ }
+ index++;
+ }
+ return false;
+ }
+
+ private List<ZDO> GetSaveClone()
+ {
+ List<ZDO> list = new List<ZDO>();
+ for (int i = 0; i < m_objectsBySector.Length; i++)
+ {
+ if (m_objectsBySector[i] == null)
+ {
+ continue;
+ }
+ foreach (ZDO item in m_objectsBySector[i])
+ {
+ if (item.m_persistent)
+ {
+ list.Add(item.Clone());
+ }
+ }
+ }
+ foreach (List<ZDO> value in m_objectsByOutsideSector.Values)
+ {
+ foreach (ZDO item2 in value)
+ {
+ if (item2.m_persistent)
+ {
+ list.Add(item2.Clone());
+ }
+ }
+ }
+ return list;
+ }
+
+ public int NrOfObjects()
+ {
+ return m_objectsByID.Count;
+ }
+
+ public int GetSentZDOs()
+ {
+ return m_zdosSentLastSec;
+ }
+
+ public int GetRecvZDOs()
+ {
+ return m_zdosRecvLastSec;
+ }
+
+ public void GetAverageStats(out float sentZdos, out float recvZdos)
+ {
+ sentZdos = (float)m_zdosSentLastSec / 20f;
+ recvZdos = (float)m_zdosRecvLastSec / 20f;
+ }
+
+ public int GetClientChangeQueue()
+ {
+ return m_clientChangeQueue.Count;
+ }
+
+ public void RequestZDO(ZDOID id)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC("RequestZDO", id);
+ }
+
+ private void RPC_RequestZDO(long sender, ZDOID id)
+ {
+ GetPeer(sender)?.ForceSendZDO(id);
+ }
+
+ private ZDOPeer GetPeer(long uid)
+ {
+ foreach (ZDOPeer peer in m_peers)
+ {
+ if (peer.m_peer.m_uid == uid)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public void ForceSendZDO(ZDOID id)
+ {
+ foreach (ZDOPeer peer in m_peers)
+ {
+ peer.ForceSendZDO(id);
+ }
+ }
+
+ public void ForceSendZDO(long peerID, ZDOID id)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ GetPeer(peerID)?.ForceSendZDO(id);
+ return;
+ }
+ foreach (ZDOPeer peer in m_peers)
+ {
+ peer.ForceSendZDO(id);
+ }
+ }
+
+ public void ClientChanged(ZDOID id)
+ {
+ m_clientChangeQueue.Add(id);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOPool.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOPool.cs
new file mode 100644
index 0000000..57c477e
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZDOPool.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ZDOPool
+{
+ private static int BATCH_SIZE = 64;
+
+ private static Stack<ZDO> m_free = new Stack<ZDO>();
+
+ private static int m_active = 0;
+
+ public static ZDO Create(ZDOMan man, ZDOID id, Vector3 position)
+ {
+ ZDO zDO = Get();
+ zDO.Initialize(man, id, position);
+ return zDO;
+ }
+
+ public static ZDO Create(ZDOMan man)
+ {
+ ZDO zDO = Get();
+ zDO.Initialize(man);
+ return zDO;
+ }
+
+ public static void Release(Dictionary<ZDOID, ZDO> objects)
+ {
+ foreach (ZDO value in objects.Values)
+ {
+ Release(value);
+ }
+ }
+
+ public static void Release(ZDO zdo)
+ {
+ zdo.Reset();
+ m_free.Push(zdo);
+ m_active--;
+ }
+
+ private static ZDO Get()
+ {
+ if (m_free.Count <= 0)
+ {
+ for (int i = 0; i < BATCH_SIZE; i++)
+ {
+ ZDO item = new ZDO();
+ m_free.Push(item);
+ }
+ }
+ m_active++;
+ return m_free.Pop();
+ }
+
+ public static int GetPoolSize()
+ {
+ return m_free.Count;
+ }
+
+ public static int GetPoolActive()
+ {
+ return m_active;
+ }
+
+ public static int GetPoolTotal()
+ {
+ return m_active + m_free.Count;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNat.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNat.cs
new file mode 100644
index 0000000..058cb86
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNat.cs
@@ -0,0 +1,32 @@
+using System;
+using System.IO;
+
+public class ZNat : IDisposable
+{
+ private FileStream m_output;
+
+ private bool m_mappingOK;
+
+ private int m_port;
+
+ public void Dispose()
+ {
+ }
+
+ public void SetPort(int port)
+ {
+ if (m_port != port)
+ {
+ m_port = port;
+ }
+ }
+
+ public void Update(float dt)
+ {
+ }
+
+ public bool GetStatus()
+ {
+ return m_mappingOK;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNet.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNet.cs
new file mode 100644
index 0000000..9306206
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNet.cs
@@ -0,0 +1,1488 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using Steamworks;
+using UnityEngine;
+using UnityEngine.Rendering;
+using UnityEngine.UI;
+
+public class ZNet : MonoBehaviour
+{
+ public enum ConnectionStatus
+ {
+ None,
+ Connecting,
+ Connected,
+ ErrorVersion,
+ ErrorDisconnected,
+ ErrorConnectFailed,
+ ErrorPassword,
+ ErrorAlreadyConnected,
+ ErrorBanned,
+ ErrorFull
+ }
+
+ public struct PlayerInfo
+ {
+ public string m_name;
+
+ public string m_host;
+
+ public ZDOID m_characterID;
+
+ public bool m_publicPosition;
+
+ public Vector3 m_position;
+ }
+
+ private float m_banlistTimer;
+
+ private static ZNet m_instance;
+
+ public int m_hostPort = 2456;
+
+ public RectTransform m_passwordDialog;
+
+ public float m_badConnectionPing = 5f;
+
+ public int m_zdoSectorsWidth = 512;
+
+ public int m_serverPlayerLimit = 10;
+
+ private ZConnector2 m_serverConnector;
+
+ private ISocket m_hostSocket;
+
+ private List<ZNetPeer> m_peers = new List<ZNetPeer>();
+
+ private Thread m_saveThread;
+
+ private float m_saveStartTime;
+
+ private float m_saveThreadStartTime;
+
+ private ZDOMan m_zdoMan;
+
+ private ZRoutedRpc m_routedRpc;
+
+ private ZNat m_nat;
+
+ private double m_netTime = 2040.0;
+
+ private ZDOID m_characterID = ZDOID.None;
+
+ private Vector3 m_referencePosition = Vector3.zero;
+
+ private bool m_publicReferencePosition;
+
+ private float m_periodicSendTimer;
+
+ private float m_statTimer;
+
+ private int m_totalSent;
+
+ private int m_totalRecv;
+
+ private bool m_haveStoped;
+
+ private static bool m_isServer = true;
+
+ private static World m_world = null;
+
+ private static string m_serverHost = "";
+
+ private static int m_serverHostPort = 0;
+
+ private static ulong m_serverSteamID = 0uL;
+
+ private static bool m_openServer = true;
+
+ private static bool m_publicServer = true;
+
+ private static string m_serverPassword = "";
+
+ private static string m_ServerName = "";
+
+ private static ConnectionStatus m_connectionStatus = ConnectionStatus.None;
+
+ private SyncedList m_adminList;
+
+ private SyncedList m_bannedList;
+
+ private SyncedList m_permittedList;
+
+ private List<PlayerInfo> m_players = new List<PlayerInfo>();
+
+ private ZRpc m_tempPasswordRPC;
+
+ public static ZNet instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_routedRpc = new ZRoutedRpc(m_isServer);
+ m_zdoMan = new ZDOMan(m_zdoSectorsWidth);
+ m_passwordDialog.gameObject.SetActive(value: false);
+ WorldGenerator.Deitialize();
+ if (!SteamManager.Initialize())
+ {
+ return;
+ }
+ string personaName = SteamFriends.GetPersonaName();
+ ZLog.Log("Steam initialized, persona:" + personaName);
+ ZSteamMatchmaking.Initialize();
+ if (m_isServer)
+ {
+ m_adminList = new SyncedList(Application.persistentDataPath + "/adminlist.txt", "List admin players ID ONE per line");
+ m_bannedList = new SyncedList(Application.persistentDataPath + "/bannedlist.txt", "List banned players ID ONE per line");
+ m_permittedList = new SyncedList(Application.persistentDataPath + "/permittedlist.txt", "List permitted players ID ONE per line");
+ if (m_world == null)
+ {
+ m_publicServer = false;
+ m_world = World.GetDevWorld();
+ }
+ if (m_openServer)
+ {
+ ZSteamSocket zSteamSocket = new ZSteamSocket();
+ zSteamSocket.StartHost();
+ m_hostSocket = zSteamSocket;
+ bool password = m_serverPassword != "";
+ string versionString = Version.GetVersionString();
+ ZSteamMatchmaking.instance.RegisterServer(m_ServerName, password, versionString, m_publicServer, m_world.m_seedName);
+ }
+ WorldGenerator.Initialize(m_world);
+ LoadWorld();
+ m_connectionStatus = ConnectionStatus.Connected;
+ }
+ else
+ {
+ ZLog.Log("Connecting to server " + m_serverSteamID);
+ Connect(new CSteamID(m_serverSteamID));
+ }
+ m_routedRpc.SetUID(m_zdoMan.GetMyID());
+ if (IsServer())
+ {
+ SendPlayerList();
+ }
+ }
+
+ private string GetPublicIP()
+ {
+ try
+ {
+ string input = Utils.DownloadString("http://checkip.dyndns.org/");
+ input = new Regex("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}").Matches(input)[0].ToString();
+ ZLog.Log("Got public ip respons:" + input);
+ return input;
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Failed to get public ip:" + ex.ToString());
+ return "";
+ }
+ }
+
+ public void Shutdown()
+ {
+ ZLog.Log("ZNet Shutdown");
+ Save();
+ StopAll();
+ base.enabled = false;
+ }
+
+ private void StopAll()
+ {
+ if (m_haveStoped)
+ {
+ return;
+ }
+ m_haveStoped = true;
+ if (m_saveThread != null && m_saveThread.IsAlive)
+ {
+ m_saveThread.Join();
+ m_saveThread = null;
+ }
+ m_zdoMan.ShutDown();
+ SendDisconnect();
+ ZSteamMatchmaking.instance.ReleaseSessionTicket();
+ ZSteamMatchmaking.instance.UnregisterServer();
+ if (m_hostSocket != null)
+ {
+ m_hostSocket.Dispose();
+ }
+ if (m_serverConnector != null)
+ {
+ m_serverConnector.Dispose();
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ peer.Dispose();
+ }
+ m_peers.Clear();
+ }
+
+ private void OnDestroy()
+ {
+ ZLog.Log("ZNet OnDestroy");
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void Connect(CSteamID hostID)
+ {
+ ZNetPeer peer = new ZNetPeer(new ZSteamSocket(hostID), server: true);
+ OnNewConnection(peer);
+ m_connectionStatus = ConnectionStatus.Connecting;
+ }
+
+ public void Connect(string host, int port)
+ {
+ m_serverConnector = new ZConnector2(host, port);
+ m_connectionStatus = ConnectionStatus.Connecting;
+ }
+
+ private void UpdateClientConnector(float dt)
+ {
+ if (m_serverConnector != null && m_serverConnector.UpdateStatus(dt, logErrors: true))
+ {
+ ZSocket2 zSocket = m_serverConnector.Complete();
+ if (zSocket != null)
+ {
+ ZLog.Log("Connection established to " + m_serverConnector.GetEndPointString());
+ ZNetPeer peer = new ZNetPeer(zSocket, server: true);
+ OnNewConnection(peer);
+ }
+ else
+ {
+ m_connectionStatus = ConnectionStatus.ErrorConnectFailed;
+ ZLog.Log("Failed to connect to server");
+ }
+ m_serverConnector.Dispose();
+ m_serverConnector = null;
+ }
+ }
+
+ private void OnNewConnection(ZNetPeer peer)
+ {
+ m_peers.Add(peer);
+ peer.m_rpc.Register<ZPackage>("PeerInfo", RPC_PeerInfo);
+ peer.m_rpc.Register("Disconnect", RPC_Disconnect);
+ if (m_isServer)
+ {
+ peer.m_rpc.Register("ServerHandshake", RPC_ServerHandshake);
+ return;
+ }
+ peer.m_rpc.Register<int>("Error", RPC_Error);
+ peer.m_rpc.Register<bool>("ClientHandshake", RPC_ClientHandshake);
+ peer.m_rpc.Invoke("ServerHandshake");
+ }
+
+ private void RPC_ServerHandshake(ZRpc rpc)
+ {
+ ZNetPeer peer = GetPeer(rpc);
+ if (peer != null)
+ {
+ ZLog.Log("Got handshake from client " + peer.m_socket.GetEndPointString());
+ ClearPlayerData(peer);
+ bool flag = !string.IsNullOrEmpty(m_serverPassword);
+ peer.m_rpc.Invoke("ClientHandshake", flag);
+ }
+ }
+
+ private void UpdatePassword()
+ {
+ if (m_passwordDialog.gameObject.activeSelf)
+ {
+ m_passwordDialog.GetComponentInChildren<InputField>().ActivateInputField();
+ }
+ }
+
+ public bool InPasswordDialog()
+ {
+ return m_passwordDialog.gameObject.activeSelf;
+ }
+
+ private void RPC_ClientHandshake(ZRpc rpc, bool needPassword)
+ {
+ if (needPassword)
+ {
+ m_passwordDialog.gameObject.SetActive(value: true);
+ InputField componentInChildren = m_passwordDialog.GetComponentInChildren<InputField>();
+ componentInChildren.text = "";
+ componentInChildren.ActivateInputField();
+ m_passwordDialog.GetComponentInChildren<InputFieldSubmit>().m_onSubmit = OnPasswordEnter;
+ m_tempPasswordRPC = rpc;
+ }
+ else
+ {
+ SendPeerInfo(rpc);
+ }
+ }
+
+ private void OnPasswordEnter(string pwd)
+ {
+ if (m_tempPasswordRPC.IsConnected())
+ {
+ m_passwordDialog.gameObject.SetActive(value: false);
+ SendPeerInfo(m_tempPasswordRPC, pwd);
+ m_tempPasswordRPC = null;
+ }
+ }
+
+ private void SendPeerInfo(ZRpc rpc, string password = "")
+ {
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(GetUID());
+ zPackage.Write(Version.GetVersionString());
+ zPackage.Write(m_referencePosition);
+ zPackage.Write(Game.instance.GetPlayerProfile().GetName());
+ if (IsServer())
+ {
+ zPackage.Write(m_world.m_name);
+ zPackage.Write(m_world.m_seed);
+ zPackage.Write(m_world.m_seedName);
+ zPackage.Write(m_world.m_uid);
+ zPackage.Write(m_world.m_worldGenVersion);
+ zPackage.Write(m_netTime);
+ }
+ else
+ {
+ string data = (string.IsNullOrEmpty(password) ? "" : HashPassword(password));
+ zPackage.Write(data);
+ byte[] array = ZSteamMatchmaking.instance.RequestSessionTicket();
+ if (array == null)
+ {
+ m_connectionStatus = ConnectionStatus.ErrorConnectFailed;
+ return;
+ }
+ zPackage.Write(array);
+ }
+ rpc.Invoke("PeerInfo", zPackage);
+ }
+
+ private void RPC_PeerInfo(ZRpc rpc, ZPackage pkg)
+ {
+ ZNetPeer peer = GetPeer(rpc);
+ if (peer == null)
+ {
+ return;
+ }
+ long num = pkg.ReadLong();
+ string text = pkg.ReadString();
+ string endPointString = peer.m_socket.GetEndPointString();
+ string hostName = peer.m_socket.GetHostName();
+ ZLog.Log("VERSION check their:" + text + " mine:" + Version.GetVersionString());
+ if (text != Version.GetVersionString())
+ {
+ if (m_isServer)
+ {
+ rpc.Invoke("Error", 3);
+ }
+ else
+ {
+ m_connectionStatus = ConnectionStatus.ErrorVersion;
+ }
+ ZLog.Log("Peer " + endPointString + " has incompatible version, mine:" + Version.GetVersionString() + " remote " + text);
+ return;
+ }
+ Vector3 refPos = pkg.ReadVector3();
+ string text2 = pkg.ReadString();
+ if (m_isServer)
+ {
+ if (!IsAllowed(hostName, text2))
+ {
+ rpc.Invoke("Error", 8);
+ ZLog.Log("Player " + text2 + " : " + hostName + " is blacklisted or not in whitelist.");
+ return;
+ }
+ string text3 = pkg.ReadString();
+ ZSteamSocket zSteamSocket = peer.m_socket as ZSteamSocket;
+ byte[] ticket = pkg.ReadByteArray();
+ if (!ZSteamMatchmaking.instance.VerifySessionTicket(ticket, zSteamSocket.GetPeerID()))
+ {
+ ZLog.Log("Peer " + endPointString + " has invalid session ticket");
+ rpc.Invoke("Error", 8);
+ return;
+ }
+ if (GetNrOfPlayers() >= m_serverPlayerLimit)
+ {
+ rpc.Invoke("Error", 9);
+ ZLog.Log("Peer " + endPointString + " disconnected due to server is full");
+ return;
+ }
+ if (m_serverPassword != text3)
+ {
+ rpc.Invoke("Error", 6);
+ ZLog.Log("Peer " + endPointString + " has wrong password");
+ return;
+ }
+ if (IsConnected(num))
+ {
+ rpc.Invoke("Error", 7);
+ ZLog.Log("Already connected to peer with UID:" + num + " " + endPointString);
+ return;
+ }
+ }
+ else
+ {
+ m_world = new World();
+ m_world.m_name = pkg.ReadString();
+ m_world.m_seed = pkg.ReadInt();
+ m_world.m_seedName = pkg.ReadString();
+ m_world.m_uid = pkg.ReadLong();
+ m_world.m_worldGenVersion = pkg.ReadInt();
+ WorldGenerator.Initialize(m_world);
+ m_netTime = pkg.ReadDouble();
+ }
+ peer.m_refPos = refPos;
+ peer.m_uid = num;
+ peer.m_playerName = text2;
+ rpc.Register<Vector3, bool>("RefPos", RPC_RefPos);
+ rpc.Register<ZPackage>("PlayerList", RPC_PlayerList);
+ rpc.Register<string>("RemotePrint", RPC_RemotePrint);
+ if (m_isServer)
+ {
+ rpc.Register<ZDOID>("CharacterID", RPC_CharacterID);
+ rpc.Register<string>("Kick", RPC_Kick);
+ rpc.Register<string>("Ban", RPC_Ban);
+ rpc.Register<string>("Unban", RPC_Unban);
+ rpc.Register("PrintBanned", RPC_PrintBanned);
+ }
+ else
+ {
+ rpc.Register<double>("NetTime", RPC_NetTime);
+ }
+ if (m_isServer)
+ {
+ SendPeerInfo(rpc);
+ SendPlayerList();
+ }
+ else
+ {
+ m_connectionStatus = ConnectionStatus.Connected;
+ }
+ m_zdoMan.AddPeer(peer);
+ m_routedRpc.AddPeer(peer);
+ }
+
+ private void SendDisconnect()
+ {
+ ZLog.Log("Sending disconnect msg");
+ foreach (ZNetPeer peer in m_peers)
+ {
+ SendDisconnect(peer);
+ }
+ }
+
+ private void SendDisconnect(ZNetPeer peer)
+ {
+ if (peer.m_rpc != null)
+ {
+ ZLog.Log("Sent to " + peer.m_socket.GetEndPointString());
+ peer.m_rpc.Invoke("Disconnect");
+ }
+ }
+
+ private void RPC_Disconnect(ZRpc rpc)
+ {
+ ZLog.Log("RPC_Disconnect ");
+ ZNetPeer peer = GetPeer(rpc);
+ if (peer != null)
+ {
+ if (peer.m_server)
+ {
+ m_connectionStatus = ConnectionStatus.ErrorDisconnected;
+ }
+ Disconnect(peer);
+ }
+ }
+
+ private void RPC_Error(ZRpc rpc, int error)
+ {
+ ZLog.Log("Got connectoin error msg " + (m_connectionStatus = (ConnectionStatus)error));
+ }
+
+ public bool IsConnected(long uid)
+ {
+ if (uid == GetUID())
+ {
+ return true;
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.m_uid == uid)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void ClearPlayerData(ZNetPeer peer)
+ {
+ m_routedRpc.RemovePeer(peer);
+ m_zdoMan.RemovePeer(peer);
+ }
+
+ public void Disconnect(ZNetPeer peer)
+ {
+ ClearPlayerData(peer);
+ m_peers.Remove(peer);
+ peer.Dispose();
+ if (m_isServer)
+ {
+ SendPlayerList();
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ UpdateNetTime(Time.fixedDeltaTime);
+ }
+
+ private void Update()
+ {
+ float deltaTime = Time.deltaTime;
+ ZSteamSocket.Update();
+ if (IsServer())
+ {
+ UpdateBanList(deltaTime);
+ }
+ CheckForIncommingServerConnections();
+ UpdatePeers(deltaTime);
+ UpdateStats(deltaTime);
+ SendPeriodicData(deltaTime);
+ m_zdoMan.Update(deltaTime);
+ UpdateSave();
+ UpdatePassword();
+ }
+
+ private void UpdateNetTime(float dt)
+ {
+ if (IsServer())
+ {
+ if (GetNrOfPlayers() > 0)
+ {
+ m_netTime += dt;
+ }
+ }
+ else
+ {
+ m_netTime += dt;
+ }
+ }
+
+ private void UpdateBanList(float dt)
+ {
+ m_banlistTimer += dt;
+ if (!(m_banlistTimer > 5f))
+ {
+ return;
+ }
+ m_banlistTimer = 0f;
+ CheckWhiteList();
+ foreach (string item in m_bannedList.GetList())
+ {
+ InternalKick(item);
+ }
+ }
+
+ private void CheckWhiteList()
+ {
+ if (m_permittedList.Count() == 0)
+ {
+ return;
+ }
+ bool flag = false;
+ while (!flag)
+ {
+ flag = true;
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ string hostName = peer.m_socket.GetHostName();
+ if (!m_permittedList.Contains(hostName))
+ {
+ ZLog.Log("Kicking player not in permitted list " + peer.m_playerName + " host: " + hostName);
+ InternalKick(peer);
+ flag = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public bool IsSaving()
+ {
+ return m_saveThread != null;
+ }
+
+ private void UpdateStats(float dt)
+ {
+ m_statTimer += dt;
+ if (!(m_statTimer >= 1f))
+ {
+ return;
+ }
+ m_statTimer = 0f;
+ m_totalRecv = 0;
+ m_totalSent = 0;
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.m_socket != null)
+ {
+ peer.m_socket.GetAndResetStats(out var totalSent, out var totalRecv);
+ m_totalRecv += totalRecv;
+ m_totalSent += totalSent;
+ }
+ }
+ }
+
+ public void Save()
+ {
+ if (ZoneSystem.instance.SkipSaving() || DungeonDB.instance.SkipSaving())
+ {
+ ZLog.LogWarning("Skipping world save");
+ }
+ else if (m_isServer && m_world != null)
+ {
+ SaveWorldAsync();
+ }
+ }
+
+ private void SendPeriodicData(float dt)
+ {
+ m_periodicSendTimer += dt;
+ if (!(m_periodicSendTimer >= 2f))
+ {
+ return;
+ }
+ m_periodicSendTimer = 0f;
+ if (IsServer())
+ {
+ SendNetTime();
+ SendPlayerList();
+ return;
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ peer.m_rpc.Invoke("RefPos", m_referencePosition, m_publicReferencePosition);
+ }
+ }
+ }
+
+ private void SendNetTime()
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ peer.m_rpc.Invoke("NetTime", m_netTime);
+ }
+ }
+ }
+
+ private void RPC_NetTime(ZRpc rpc, double time)
+ {
+ m_netTime = time;
+ }
+
+ private void RPC_RefPos(ZRpc rpc, Vector3 pos, bool publicRefPos)
+ {
+ ZNetPeer peer = GetPeer(rpc);
+ if (peer != null)
+ {
+ peer.m_refPos = pos;
+ peer.m_publicRefPos = publicRefPos;
+ }
+ }
+
+ private void UpdatePeers(float dt)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (!peer.m_rpc.IsConnected())
+ {
+ if (peer.m_server)
+ {
+ m_connectionStatus = ConnectionStatus.ErrorDisconnected;
+ }
+ Disconnect(peer);
+ break;
+ }
+ }
+ ZNetPeer[] array = m_peers.ToArray();
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i].m_rpc.Update(dt);
+ }
+ }
+
+ private void CheckForIncommingServerConnections()
+ {
+ if (m_hostSocket == null)
+ {
+ return;
+ }
+ ISocket socket = m_hostSocket.Accept();
+ if (socket != null)
+ {
+ if (!socket.IsConnected())
+ {
+ socket.Dispose();
+ return;
+ }
+ ZNetPeer peer = new ZNetPeer(socket, server: false);
+ OnNewConnection(peer);
+ }
+ }
+
+ public ZNetPeer GetPeerByPlayerName(string name)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady() && peer.m_playerName == name)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public ZNetPeer GetPeerByHostName(string endpoint)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady() && peer.m_socket.GetHostName() == endpoint)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public ZNetPeer GetPeer(long uid)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.m_uid == uid)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ private ZNetPeer GetPeer(ZRpc rpc)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.m_rpc == rpc)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public List<ZNetPeer> GetConnectedPeers()
+ {
+ return new List<ZNetPeer>(m_peers);
+ }
+
+ private void SaveWorldAsync()
+ {
+ if (m_saveThread != null && m_saveThread.IsAlive)
+ {
+ m_saveThread.Join();
+ m_saveThread = null;
+ }
+ m_saveStartTime = Time.realtimeSinceStartup;
+ m_zdoMan.PrepareSave();
+ ZoneSystem.instance.PrepareSave();
+ RandEventSystem.instance.PrepareSave();
+ m_saveThreadStartTime = Time.realtimeSinceStartup;
+ m_saveThread = new Thread(SaveWorldThread);
+ m_saveThread.Start();
+ }
+
+ private void UpdateSave()
+ {
+ if (m_saveThread != null && !m_saveThread.IsAlive)
+ {
+ m_saveThread = null;
+ float num = m_saveThreadStartTime - m_saveStartTime;
+ float num2 = Time.realtimeSinceStartup - m_saveThreadStartTime;
+ MessageHud.instance.ShowMessage(MessageHud.MessageType.TopLeft, "$msg_worldsaved ( " + num.ToString("0.00") + "+" + num2.ToString("0.00") + "s )");
+ }
+ }
+
+ private void SaveWorldThread()
+ {
+ DateTime now = DateTime.Now;
+ string dBPath = m_world.GetDBPath();
+ string text = dBPath + ".new";
+ string text2 = dBPath + ".old";
+ FileStream fileStream = File.Create(text);
+ BinaryWriter binaryWriter = new BinaryWriter(fileStream);
+ binaryWriter.Write(Version.m_worldVersion);
+ binaryWriter.Write(m_netTime);
+ m_zdoMan.SaveAsync(binaryWriter);
+ ZoneSystem.instance.SaveASync(binaryWriter);
+ RandEventSystem.instance.SaveAsync(binaryWriter);
+ binaryWriter.Close();
+ fileStream.Dispose();
+ m_world.SaveWorldMetaData();
+ if (File.Exists(dBPath))
+ {
+ if (File.Exists(text2))
+ {
+ File.Delete(text2);
+ }
+ File.Move(dBPath, text2);
+ }
+ File.Move(text, dBPath);
+ ZLog.Log("World saved ( " + (DateTime.Now - now).TotalMilliseconds + "ms )");
+ }
+
+ private bool LoadWorld()
+ {
+ ZLog.Log("Load world " + m_world.m_name);
+ string dBPath = m_world.GetDBPath();
+ FileStream fileStream;
+ try
+ {
+ fileStream = File.OpenRead(dBPath);
+ }
+ catch
+ {
+ ZLog.Log(" missing world.dat");
+ return false;
+ }
+ BinaryReader binaryReader = new BinaryReader(fileStream);
+ if (!CheckDataVersion(binaryReader, out var version))
+ {
+ ZLog.Log(" incompatible data version " + version);
+ binaryReader.Close();
+ fileStream.Dispose();
+ return false;
+ }
+ if (version >= 4)
+ {
+ m_netTime = binaryReader.ReadDouble();
+ }
+ m_zdoMan.Load(binaryReader, version);
+ if (version >= 12)
+ {
+ ZoneSystem.instance.Load(binaryReader, version);
+ }
+ if (version >= 15)
+ {
+ RandEventSystem.instance.Load(binaryReader, version);
+ }
+ binaryReader.Close();
+ fileStream.Dispose();
+ GC.Collect();
+ return true;
+ }
+
+ private bool CheckDataVersion(BinaryReader reader, out int version)
+ {
+ try
+ {
+ version = reader.ReadInt32();
+ if (!Version.IsWorldVersionCompatible(version))
+ {
+ return false;
+ }
+ }
+ catch
+ {
+ version = 0;
+ return false;
+ }
+ return true;
+ }
+
+ public int GetHostPort()
+ {
+ if (m_hostSocket != null)
+ {
+ return m_hostSocket.GetHostPort();
+ }
+ return 0;
+ }
+
+ public long GetUID()
+ {
+ return m_zdoMan.GetMyID();
+ }
+
+ public long GetWorldUID()
+ {
+ return m_world.m_uid;
+ }
+
+ public string GetWorldName()
+ {
+ if (m_world != null)
+ {
+ return m_world.m_name;
+ }
+ return null;
+ }
+
+ public void SetCharacterID(ZDOID id)
+ {
+ m_characterID = id;
+ if (!m_isServer)
+ {
+ m_peers[0].m_rpc.Invoke("CharacterID", id);
+ }
+ }
+
+ private void RPC_CharacterID(ZRpc rpc, ZDOID characterID)
+ {
+ ZNetPeer peer = GetPeer(rpc);
+ if (peer != null)
+ {
+ peer.m_characterID = characterID;
+ ZLog.Log("Got character ZDOID from " + peer.m_playerName + " : " + characterID);
+ }
+ }
+
+ public void SetPublicReferencePosition(bool pub)
+ {
+ m_publicReferencePosition = pub;
+ }
+
+ public bool IsReferencePositionPublic()
+ {
+ return m_publicReferencePosition;
+ }
+
+ public void SetReferencePosition(Vector3 pos)
+ {
+ m_referencePosition = pos;
+ }
+
+ public Vector3 GetReferencePosition()
+ {
+ return m_referencePosition;
+ }
+
+ public List<ZDO> GetAllCharacterZDOS()
+ {
+ List<ZDO> list = new List<ZDO>();
+ ZDO zDO = m_zdoMan.GetZDO(m_characterID);
+ if (zDO != null)
+ {
+ list.Add(zDO);
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady() && !peer.m_characterID.IsNone())
+ {
+ ZDO zDO2 = m_zdoMan.GetZDO(peer.m_characterID);
+ if (zDO2 != null)
+ {
+ list.Add(zDO2);
+ }
+ }
+ }
+ return list;
+ }
+
+ public int GetPeerConnections()
+ {
+ int num = 0;
+ for (int i = 0; i < m_peers.Count; i++)
+ {
+ if (m_peers[i].IsReady())
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ public ZNat GetZNat()
+ {
+ return m_nat;
+ }
+
+ public static void SetServer(bool server, bool openServer, bool publicServer, string serverName, string password, World world)
+ {
+ m_isServer = server;
+ m_openServer = openServer;
+ m_publicServer = publicServer;
+ m_serverPassword = (string.IsNullOrEmpty(password) ? "" : HashPassword(password));
+ m_ServerName = serverName;
+ m_world = world;
+ }
+
+ private static string HashPassword(string password)
+ {
+ byte[] bytes = Encoding.ASCII.GetBytes(password);
+ byte[] bytes2 = new MD5CryptoServiceProvider().ComputeHash(bytes);
+ return Encoding.ASCII.GetString(bytes2);
+ }
+
+ public static void SetServerHost(ulong serverID)
+ {
+ m_serverHost = "";
+ m_serverHostPort = 0;
+ m_serverSteamID = serverID;
+ }
+
+ public static void SetServerHost(string host, int port)
+ {
+ m_serverHost = host;
+ m_serverHostPort = port;
+ m_serverSteamID = 0uL;
+ }
+
+ public static string GetServerString()
+ {
+ return m_serverHost + ":" + m_serverHostPort;
+ }
+
+ public bool IsServer()
+ {
+ return m_isServer;
+ }
+
+ public bool IsDedicated()
+ {
+ return false;
+ }
+
+ private void UpdatePlayerList()
+ {
+ m_players.Clear();
+ if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null)
+ {
+ PlayerInfo item = default(PlayerInfo);
+ item.m_name = Game.instance.GetPlayerProfile().GetName();
+ item.m_host = "";
+ item.m_characterID = m_characterID;
+ item.m_publicPosition = m_publicReferencePosition;
+ if (item.m_publicPosition)
+ {
+ item.m_position = m_referencePosition;
+ }
+ m_players.Add(item);
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ PlayerInfo item2 = default(PlayerInfo);
+ item2.m_characterID = peer.m_characterID;
+ item2.m_name = peer.m_playerName;
+ item2.m_host = peer.m_socket.GetHostName();
+ item2.m_publicPosition = peer.m_publicRefPos;
+ if (item2.m_publicPosition)
+ {
+ item2.m_position = peer.m_refPos;
+ }
+ m_players.Add(item2);
+ }
+ }
+ }
+
+ private void SendPlayerList()
+ {
+ UpdatePlayerList();
+ if (m_peers.Count <= 0)
+ {
+ return;
+ }
+ ZPackage zPackage = new ZPackage();
+ zPackage.Write(m_players.Count);
+ foreach (PlayerInfo player in m_players)
+ {
+ zPackage.Write(player.m_name);
+ zPackage.Write(player.m_host);
+ zPackage.Write(player.m_characterID);
+ zPackage.Write(player.m_publicPosition);
+ if (player.m_publicPosition)
+ {
+ zPackage.Write(player.m_position);
+ }
+ }
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ peer.m_rpc.Invoke("PlayerList", zPackage);
+ }
+ }
+ }
+
+ private void RPC_PlayerList(ZRpc rpc, ZPackage pkg)
+ {
+ m_players.Clear();
+ int num = pkg.ReadInt();
+ for (int i = 0; i < num; i++)
+ {
+ PlayerInfo item = default(PlayerInfo);
+ item.m_name = pkg.ReadString();
+ item.m_host = pkg.ReadString();
+ item.m_characterID = pkg.ReadZDOID();
+ item.m_publicPosition = pkg.ReadBool();
+ if (item.m_publicPosition)
+ {
+ item.m_position = pkg.ReadVector3();
+ }
+ m_players.Add(item);
+ }
+ }
+
+ public List<PlayerInfo> GetPlayerList()
+ {
+ return m_players;
+ }
+
+ public void GetOtherPublicPlayers(List<PlayerInfo> playerList)
+ {
+ foreach (PlayerInfo player in m_players)
+ {
+ if (player.m_publicPosition)
+ {
+ ZDOID characterID = player.m_characterID;
+ if (!characterID.IsNone() && !(player.m_characterID == m_characterID))
+ {
+ playerList.Add(player);
+ }
+ }
+ }
+ }
+
+ public int GetNrOfPlayers()
+ {
+ return m_players.Count;
+ }
+
+ public void GetNetStats(out int totalSent, out int totalRecv)
+ {
+ totalSent = m_totalSent;
+ totalRecv = m_totalRecv;
+ }
+
+ public void SetNetTime(double time)
+ {
+ m_netTime = time;
+ }
+
+ public DateTime GetTime()
+ {
+ long ticks = (long)(m_netTime * 1000.0 * 10000.0);
+ return new DateTime(ticks);
+ }
+
+ public float GetWrappedDayTimeSeconds()
+ {
+ return (float)(m_netTime % 86400.0);
+ }
+
+ public double GetTimeSeconds()
+ {
+ return m_netTime;
+ }
+
+ public static ConnectionStatus GetConnectionStatus()
+ {
+ if (m_instance != null && m_instance.IsServer())
+ {
+ return ConnectionStatus.Connected;
+ }
+ return m_connectionStatus;
+ }
+
+ public bool HasBadConnection()
+ {
+ return GetServerPing() > m_badConnectionPing;
+ }
+
+ public float GetServerPing()
+ {
+ if (IsServer())
+ {
+ return 0f;
+ }
+ if (m_connectionStatus == ConnectionStatus.Connecting || m_connectionStatus == ConnectionStatus.None)
+ {
+ return 0f;
+ }
+ if (m_connectionStatus == ConnectionStatus.Connected)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ return peer.m_rpc.GetTimeSinceLastData();
+ }
+ }
+ }
+ return 0f;
+ }
+
+ public ZNetPeer GetServerPeer()
+ {
+ if (IsServer())
+ {
+ return null;
+ }
+ if (m_connectionStatus == ConnectionStatus.Connecting || m_connectionStatus == ConnectionStatus.None)
+ {
+ return null;
+ }
+ if (m_connectionStatus == ConnectionStatus.Connected)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.IsReady())
+ {
+ return peer;
+ }
+ }
+ }
+ return null;
+ }
+
+ public ZRpc GetServerRPC()
+ {
+ return GetServerPeer()?.m_rpc;
+ }
+
+ public List<ZNetPeer> GetPeers()
+ {
+ return m_peers;
+ }
+
+ public void RemotePrint(ZRpc rpc, string text)
+ {
+ if (rpc == null)
+ {
+ if ((bool)Console.instance)
+ {
+ Console.instance.Print(text);
+ }
+ }
+ else
+ {
+ rpc.Invoke("RemotePrint", text);
+ }
+ }
+
+ private void RPC_RemotePrint(ZRpc rpc, string text)
+ {
+ if ((bool)Console.instance)
+ {
+ Console.instance.Print(text);
+ }
+ }
+
+ public void Kick(string user)
+ {
+ if (IsServer())
+ {
+ InternalKick(user);
+ return;
+ }
+ GetServerRPC()?.Invoke("Kick", user);
+ }
+
+ private void RPC_Kick(ZRpc rpc, string user)
+ {
+ if (ServerCtrl.instance != null)
+ {
+ if (!m_adminList.Contains(rpc.GetSocket().GetHostName()))
+ {
+ RemotePrint(rpc, "You are not admin");
+ return;
+ }
+ RemotePrint(rpc, "Kicking user " + user);
+ InternalKick(user);
+ }
+ }
+
+ private void InternalKick(string user)
+ {
+ if (!(user == ""))
+ {
+ ZNetPeer zNetPeer = GetPeerByHostName(user);
+ if (zNetPeer == null)
+ {
+ zNetPeer = GetPeerByPlayerName(user);
+ }
+ if (zNetPeer != null)
+ {
+ InternalKick(zNetPeer);
+ }
+ }
+ }
+
+ private void InternalKick(ZNetPeer peer)
+ {
+ if (IsServer() && peer != null)
+ {
+ ZLog.Log("Kicking " + peer.m_playerName);
+ SendDisconnect(peer);
+ Disconnect(peer);
+ }
+ }
+
+ public bool IsAllowed(string hostName, string playerName)
+ {
+ if (m_bannedList.Contains(hostName) || m_bannedList.Contains(playerName))
+ {
+ return false;
+ }
+ if (m_permittedList.Count() > 0 && !m_permittedList.Contains(hostName))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public void Ban(string user)
+ {
+ if (IsServer())
+ {
+ InternalBan(null, user);
+ return;
+ }
+ GetServerRPC()?.Invoke("Ban", user);
+ }
+
+ private void RPC_Ban(ZRpc rpc, string user)
+ {
+ if (ServerCtrl.instance != null)
+ {
+ if (!m_adminList.Contains(rpc.GetSocket().GetHostName()))
+ {
+ RemotePrint(rpc, "You are not admin");
+ }
+ else
+ {
+ InternalBan(rpc, user);
+ }
+ }
+ }
+
+ private void InternalBan(ZRpc rpc, string user)
+ {
+ if (IsServer() && !(user == ""))
+ {
+ ZNetPeer peerByPlayerName = GetPeerByPlayerName(user);
+ if (peerByPlayerName != null)
+ {
+ user = peerByPlayerName.m_socket.GetHostName();
+ }
+ RemotePrint(rpc, "Banning user " + user);
+ m_bannedList.Add(user);
+ }
+ }
+
+ public void Unban(string user)
+ {
+ if (IsServer())
+ {
+ InternalUnban(null, user);
+ return;
+ }
+ GetServerRPC()?.Invoke("Unban", user);
+ }
+
+ private void RPC_Unban(ZRpc rpc, string user)
+ {
+ if (ServerCtrl.instance != null)
+ {
+ if (!m_adminList.Contains(rpc.GetSocket().GetHostName()))
+ {
+ RemotePrint(rpc, "You are not admin");
+ }
+ else
+ {
+ InternalUnban(rpc, user);
+ }
+ }
+ }
+
+ private void InternalUnban(ZRpc rpc, string user)
+ {
+ if (IsServer() && !(user == ""))
+ {
+ RemotePrint(rpc, "Unbanning user " + user);
+ m_bannedList.Remove(user);
+ }
+ }
+
+ public void PrintBanned()
+ {
+ if (IsServer())
+ {
+ InternalPrintBanned(null);
+ }
+ else
+ {
+ GetServerRPC()?.Invoke("PrintBanned");
+ }
+ }
+
+ private void RPC_PrintBanned(ZRpc rpc)
+ {
+ if (ServerCtrl.instance != null)
+ {
+ if (!m_adminList.Contains(rpc.GetSocket().GetHostName()))
+ {
+ RemotePrint(rpc, "You are not admin");
+ }
+ else
+ {
+ InternalPrintBanned(rpc);
+ }
+ }
+ }
+
+ private void InternalPrintBanned(ZRpc rpc)
+ {
+ RemotePrint(rpc, "Banned users");
+ List<string> list = m_bannedList.GetList();
+ if (list.Count == 0)
+ {
+ RemotePrint(rpc, "-");
+ }
+ else
+ {
+ for (int i = 0; i < list.Count; i++)
+ {
+ RemotePrint(rpc, i + ": " + list[i]);
+ }
+ }
+ RemotePrint(rpc, "");
+ RemotePrint(rpc, "Permitted users");
+ List<string> list2 = m_permittedList.GetList();
+ if (list2.Count == 0)
+ {
+ RemotePrint(rpc, "All");
+ return;
+ }
+ for (int j = 0; j < list2.Count; j++)
+ {
+ RemotePrint(rpc, j + ": " + list2[j]);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetPeer.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetPeer.cs
new file mode 100644
index 0000000..a2c2482
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetPeer.cs
@@ -0,0 +1,44 @@
+using System;
+using UnityEngine;
+
+public class ZNetPeer : IDisposable
+{
+ public ZRpc m_rpc;
+
+ public ISocket m_socket;
+
+ public long m_uid;
+
+ public bool m_server;
+
+ public Vector3 m_refPos = Vector3.zero;
+
+ public bool m_publicRefPos;
+
+ public ZDOID m_characterID = ZDOID.None;
+
+ public string m_playerName = "";
+
+ public ZNetPeer(ISocket socket, bool server)
+ {
+ m_socket = socket;
+ m_rpc = new ZRpc(m_socket);
+ m_server = server;
+ }
+
+ public void Dispose()
+ {
+ m_socket.Dispose();
+ m_rpc.Dispose();
+ }
+
+ public bool IsReady()
+ {
+ return m_uid != 0;
+ }
+
+ public Vector3 GetRefPos()
+ {
+ return m_refPos;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetScene.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetScene.cs
new file mode 100644
index 0000000..ae853c5
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetScene.cs
@@ -0,0 +1,423 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class ZNetScene : MonoBehaviour
+{
+ private static ZNetScene m_instance;
+
+ private const int m_maxCreatedPerFrame = 10;
+
+ private const int m_maxDestroyedPerFrame = 20;
+
+ private const float m_createDestroyFps = 30f;
+
+ public List<GameObject> m_prefabs = new List<GameObject>();
+
+ public List<GameObject> m_nonNetViewPrefabs = new List<GameObject>();
+
+ private Dictionary<int, GameObject> m_namedPrefabs = new Dictionary<int, GameObject>();
+
+ private Dictionary<ZDO, ZNetView> m_instances = new Dictionary<ZDO, ZNetView>(new ZDOComparer());
+
+ private GameObject m_netSceneRoot;
+
+ private List<ZDO> m_tempCurrentObjects = new List<ZDO>();
+
+ private List<ZDO> m_tempCurrentObjects2 = new List<ZDO>();
+
+ private List<ZDO> m_tempCurrentDistantObjects = new List<ZDO>();
+
+ private List<ZNetView> m_tempRemoved = new List<ZNetView>();
+
+ private HashSet<ZDO> m_tempActiveZDOs = new HashSet<ZDO>(new ZDOComparer());
+
+ private float m_createDestroyTimer;
+
+ public static ZNetScene instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ foreach (GameObject prefab in m_prefabs)
+ {
+ m_namedPrefabs.Add(prefab.name.GetStableHashCode(), prefab);
+ }
+ foreach (GameObject nonNetViewPrefab in m_nonNetViewPrefabs)
+ {
+ m_namedPrefabs.Add(nonNetViewPrefab.name.GetStableHashCode(), nonNetViewPrefab);
+ }
+ ZDOMan zDOMan = ZDOMan.instance;
+ zDOMan.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(zDOMan.m_onZDODestroyed, new Action<ZDO>(OnZDODestroyed));
+ m_netSceneRoot = new GameObject("_NetSceneRoot");
+ ZRoutedRpc.instance.Register<Vector3, Quaternion, int>("SpawnObject", RPC_SpawnObject);
+ }
+
+ private void OnDestroy()
+ {
+ ZLog.Log("Net scene destroyed");
+ if (m_instance == this)
+ {
+ m_instance = null;
+ }
+ }
+
+ public void Shutdown()
+ {
+ foreach (KeyValuePair<ZDO, ZNetView> instance in m_instances)
+ {
+ if ((bool)instance.Value)
+ {
+ instance.Value.ResetZDO();
+ UnityEngine.Object.Destroy(instance.Value.gameObject);
+ }
+ }
+ m_instances.Clear();
+ base.enabled = false;
+ }
+
+ public void AddInstance(ZDO zdo, ZNetView nview)
+ {
+ m_instances[zdo] = nview;
+ if (nview.transform.parent == null)
+ {
+ nview.transform.SetParent(m_netSceneRoot.transform);
+ }
+ }
+
+ private bool IsPrefabZDOValid(ZDO zdo)
+ {
+ int prefab = zdo.GetPrefab();
+ if (prefab == 0)
+ {
+ return false;
+ }
+ if (GetPrefab(prefab) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private GameObject CreateObject(ZDO zdo)
+ {
+ int prefab = zdo.GetPrefab();
+ if (prefab == 0)
+ {
+ return null;
+ }
+ GameObject prefab2 = GetPrefab(prefab);
+ if (prefab2 == null)
+ {
+ return null;
+ }
+ Vector3 position = zdo.GetPosition();
+ Quaternion rotation = zdo.GetRotation();
+ ZNetView.m_initZDO = zdo;
+ GameObject result = UnityEngine.Object.Instantiate(prefab2, position, rotation);
+ ZNetView.m_initZDO = null;
+ return result;
+ }
+
+ public void Destroy(GameObject go)
+ {
+ ZNetView component = go.GetComponent<ZNetView>();
+ if ((bool)component && component.GetZDO() != null)
+ {
+ ZDO zDO = component.GetZDO();
+ component.ResetZDO();
+ m_instances.Remove(zDO);
+ if (zDO.IsOwner())
+ {
+ ZDOMan.instance.DestroyZDO(zDO);
+ }
+ }
+ UnityEngine.Object.Destroy(go);
+ }
+
+ public GameObject GetPrefab(int hash)
+ {
+ if (m_namedPrefabs.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ public GameObject GetPrefab(string name)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ return GetPrefab(stableHashCode);
+ }
+
+ public int GetPrefabHash(GameObject go)
+ {
+ return go.name.GetStableHashCode();
+ }
+
+ public bool IsAreaReady(Vector3 point)
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(point);
+ if (!ZoneSystem.instance.IsZoneLoaded(zone))
+ {
+ return false;
+ }
+ m_tempCurrentObjects.Clear();
+ ZDOMan.instance.FindSectorObjects(zone, 1, 0, m_tempCurrentObjects);
+ foreach (ZDO tempCurrentObject in m_tempCurrentObjects)
+ {
+ if (IsPrefabZDOValid(tempCurrentObject) && !FindInstance(tempCurrentObject))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool InLoadingScreen()
+ {
+ if (Player.m_localPlayer == null || Player.m_localPlayer.IsTeleporting())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void CreateObjects(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
+ {
+ int maxCreatedPerFrame = 10;
+ if (InLoadingScreen())
+ {
+ maxCreatedPerFrame = 100;
+ }
+ int frameCount = Time.frameCount;
+ foreach (ZDO key in m_instances.Keys)
+ {
+ key.m_tempCreateEarmark = frameCount;
+ }
+ int created = 0;
+ CreateObjectsSorted(currentNearObjects, maxCreatedPerFrame, ref created);
+ CreateDistantObjects(currentDistantObjects, maxCreatedPerFrame, ref created);
+ }
+
+ private void CreateObjectsSorted(List<ZDO> currentNearObjects, int maxCreatedPerFrame, ref int created)
+ {
+ m_tempCurrentObjects2.Clear();
+ int frameCount = Time.frameCount;
+ foreach (ZDO currentNearObject in currentNearObjects)
+ {
+ if (currentNearObject.m_tempCreateEarmark != frameCount && (currentNearObject.m_distant || ZoneSystem.instance.IsZoneLoaded(currentNearObject.GetSector())))
+ {
+ m_tempCurrentObjects2.Add(currentNearObject);
+ }
+ }
+ foreach (ZDO item in m_tempCurrentObjects2.OrderByDescending((ZDO item) => item.m_type))
+ {
+ if (CreateObject(item) != null)
+ {
+ created++;
+ if (created > maxCreatedPerFrame)
+ {
+ break;
+ }
+ }
+ else if (ZNet.instance.IsServer())
+ {
+ item.SetOwner(ZDOMan.instance.GetMyID());
+ ZLog.Log("Destroyed invalid predab ZDO:" + item.m_uid);
+ ZDOMan.instance.DestroyZDO(item);
+ }
+ }
+ }
+
+ private void CreateDistantObjects(List<ZDO> objects, int maxCreatedPerFrame, ref int created)
+ {
+ if (created > maxCreatedPerFrame)
+ {
+ return;
+ }
+ int frameCount = Time.frameCount;
+ foreach (ZDO @object in objects)
+ {
+ if (@object.m_tempCreateEarmark == frameCount)
+ {
+ continue;
+ }
+ if (CreateObject(@object) != null)
+ {
+ created++;
+ if (created > maxCreatedPerFrame)
+ {
+ break;
+ }
+ }
+ else if (ZNet.instance.IsServer())
+ {
+ @object.SetOwner(ZDOMan.instance.GetMyID());
+ ZLog.Log(string.Concat("Destroyed invalid predab ZDO:", @object.m_uid, " prefab hash:", @object.GetPrefab()));
+ ZDOMan.instance.DestroyZDO(@object);
+ }
+ }
+ }
+
+ private void OnZDODestroyed(ZDO zdo)
+ {
+ if (m_instances.TryGetValue(zdo, out var value))
+ {
+ value.ResetZDO();
+ UnityEngine.Object.Destroy(value.gameObject);
+ m_instances.Remove(zdo);
+ }
+ }
+
+ private void RemoveObjects(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
+ {
+ int frameCount = Time.frameCount;
+ foreach (ZDO currentNearObject in currentNearObjects)
+ {
+ currentNearObject.m_tempRemoveEarmark = frameCount;
+ }
+ foreach (ZDO currentDistantObject in currentDistantObjects)
+ {
+ currentDistantObject.m_tempRemoveEarmark = frameCount;
+ }
+ m_tempRemoved.Clear();
+ foreach (ZNetView value in m_instances.Values)
+ {
+ if (value.GetZDO().m_tempRemoveEarmark != frameCount)
+ {
+ m_tempRemoved.Add(value);
+ }
+ }
+ for (int i = 0; i < m_tempRemoved.Count; i++)
+ {
+ ZNetView zNetView = m_tempRemoved[i];
+ ZDO zDO = zNetView.GetZDO();
+ zNetView.ResetZDO();
+ UnityEngine.Object.Destroy(zNetView.gameObject);
+ if (!zDO.m_persistent && zDO.IsOwner())
+ {
+ ZDOMan.instance.DestroyZDO(zDO);
+ }
+ m_instances.Remove(zDO);
+ }
+ }
+
+ public ZNetView FindInstance(ZDO zdo)
+ {
+ if (m_instances.TryGetValue(zdo, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ public bool HaveInstance(ZDO zdo)
+ {
+ return m_instances.ContainsKey(zdo);
+ }
+
+ public GameObject FindInstance(ZDOID id)
+ {
+ ZDO zDO = ZDOMan.instance.GetZDO(id);
+ if (zDO != null)
+ {
+ ZNetView zNetView = FindInstance(zDO);
+ if ((bool)zNetView)
+ {
+ return zNetView.gameObject;
+ }
+ }
+ return null;
+ }
+
+ private void Update()
+ {
+ float deltaTime = Time.deltaTime;
+ m_createDestroyTimer += deltaTime;
+ if (m_createDestroyTimer >= 1f / 30f)
+ {
+ m_createDestroyTimer = 0f;
+ CreateDestroyObjects();
+ }
+ }
+
+ private void CreateDestroyObjects()
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(ZNet.instance.GetReferencePosition());
+ m_tempCurrentObjects.Clear();
+ m_tempCurrentDistantObjects.Clear();
+ ZDOMan.instance.FindSectorObjects(zone, ZoneSystem.instance.m_activeArea, ZoneSystem.instance.m_activeDistantArea, m_tempCurrentObjects, m_tempCurrentDistantObjects);
+ CreateObjects(m_tempCurrentObjects, m_tempCurrentDistantObjects);
+ RemoveObjects(m_tempCurrentObjects, m_tempCurrentDistantObjects);
+ }
+
+ public bool InActiveArea(Vector2i zone, Vector3 refPoint)
+ {
+ Vector2i zone2 = ZoneSystem.instance.GetZone(refPoint);
+ return InActiveArea(zone, zone2);
+ }
+
+ public bool InActiveArea(Vector2i zone, Vector2i refCenterZone)
+ {
+ int num = ZoneSystem.instance.m_activeArea - 1;
+ if (zone.x >= refCenterZone.x - num && zone.x <= refCenterZone.x + num && zone.y <= refCenterZone.y + num)
+ {
+ return zone.y >= refCenterZone.y - num;
+ }
+ return false;
+ }
+
+ public bool OutsideActiveArea(Vector3 point)
+ {
+ return OutsideActiveArea(point, ZNet.instance.GetReferencePosition());
+ }
+
+ public bool OutsideActiveArea(Vector3 point, Vector3 refPoint)
+ {
+ Vector2i zone = ZoneSystem.instance.GetZone(refPoint);
+ Vector2i zone2 = ZoneSystem.instance.GetZone(point);
+ if (zone2.x > zone.x - ZoneSystem.instance.m_activeArea && zone2.x < zone.x + ZoneSystem.instance.m_activeArea && zone2.y < zone.y + ZoneSystem.instance.m_activeArea)
+ {
+ return zone2.y <= zone.y - ZoneSystem.instance.m_activeArea;
+ }
+ return true;
+ }
+
+ public bool HaveInstanceInSector(Vector2i sector)
+ {
+ foreach (KeyValuePair<ZDO, ZNetView> instance in m_instances)
+ {
+ if ((bool)instance.Value && !instance.Value.m_distant && ZoneSystem.instance.GetZone(instance.Value.transform.position) == sector)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int NrOfInstances()
+ {
+ return m_instances.Count;
+ }
+
+ public void SpawnObject(Vector3 pos, Quaternion rot, GameObject prefab)
+ {
+ int prefabHash = GetPrefabHash(prefab);
+ ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SpawnObject", pos, rot, prefabHash);
+ }
+
+ private void RPC_SpawnObject(long spawner, Vector3 pos, Quaternion rot, int prefabHash)
+ {
+ GameObject prefab = GetPrefab(prefabHash);
+ if (prefab == null)
+ {
+ ZLog.Log("Missing prefab " + prefabHash);
+ }
+ else
+ {
+ UnityEngine.Object.Instantiate(prefab, pos, rot);
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetView.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetView.cs
new file mode 100644
index 0000000..c5879ae
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNetView.cs
@@ -0,0 +1,226 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+public class ZNetView : MonoBehaviour
+{
+ public static long Everybody;
+
+ public bool m_persistent;
+
+ public bool m_distant;
+
+ public ZDO.ObjectType m_type;
+
+ public bool m_syncInitialScale;
+
+ private ZDO m_zdo;
+
+ private Rigidbody m_body;
+
+ private Dictionary<int, RoutedMethodBase> m_functions = new Dictionary<int, RoutedMethodBase>();
+
+ private bool m_ghost;
+
+ public static ZDO m_initZDO;
+
+ public static bool m_forceDisableInit;
+
+ private static bool m_ghostInit;
+
+ private void Awake()
+ {
+ if (m_forceDisableInit)
+ {
+ UnityEngine.Object.Destroy(this);
+ return;
+ }
+ m_body = GetComponent<Rigidbody>();
+ if (m_initZDO != null)
+ {
+ m_zdo = m_initZDO;
+ if (m_zdo.m_type != m_type && m_zdo.IsOwner())
+ {
+ m_zdo.SetType(m_type);
+ }
+ if (m_zdo.m_distant != m_distant && m_zdo.IsOwner())
+ {
+ m_zdo.SetDistant(m_distant);
+ }
+ if (m_syncInitialScale)
+ {
+ Vector3 vec = m_zdo.GetVec3("scale", base.transform.localScale);
+ base.transform.localScale = vec;
+ }
+ if ((bool)m_body)
+ {
+ m_body.Sleep();
+ }
+ }
+ else
+ {
+ string prefabName = GetPrefabName();
+ m_zdo = ZDOMan.instance.CreateNewZDO(base.transform.position);
+ m_zdo.m_persistent = m_persistent;
+ m_zdo.m_type = m_type;
+ m_zdo.m_distant = m_distant;
+ m_zdo.SetPrefab(prefabName.GetStableHashCode());
+ m_zdo.SetRotation(base.transform.rotation);
+ if (m_syncInitialScale)
+ {
+ m_zdo.Set("scale", base.transform.localScale);
+ }
+ if (m_ghostInit)
+ {
+ m_ghost = true;
+ return;
+ }
+ }
+ ZNetScene.instance.AddInstance(m_zdo, this);
+ }
+
+ public void SetLocalScale(Vector3 scale)
+ {
+ base.transform.localScale = scale;
+ if (m_zdo != null && m_syncInitialScale && IsOwner())
+ {
+ m_zdo.Set("scale", base.transform.localScale);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ _ = (bool)ZNetScene.instance;
+ }
+
+ public void SetPersistent(bool persistent)
+ {
+ m_zdo.m_persistent = persistent;
+ }
+
+ public string GetPrefabName()
+ {
+ return GetPrefabName(base.gameObject);
+ }
+
+ public static string GetPrefabName(GameObject gameObject)
+ {
+ string text = gameObject.name;
+ char[] anyOf = new char[2] { '(', ' ' };
+ int num = text.IndexOfAny(anyOf);
+ if (num != -1)
+ {
+ return text.Remove(num);
+ }
+ return text;
+ }
+
+ public void Destroy()
+ {
+ ZNetScene.instance.Destroy(base.gameObject);
+ }
+
+ public bool IsOwner()
+ {
+ return m_zdo.IsOwner();
+ }
+
+ public bool HasOwner()
+ {
+ return m_zdo.HasOwner();
+ }
+
+ public void ClaimOwnership()
+ {
+ if (!IsOwner())
+ {
+ m_zdo.SetOwner(ZDOMan.instance.GetMyID());
+ }
+ }
+
+ public ZDO GetZDO()
+ {
+ return m_zdo;
+ }
+
+ public bool IsValid()
+ {
+ if (m_zdo != null)
+ {
+ return m_zdo.IsValid();
+ }
+ return false;
+ }
+
+ public void ResetZDO()
+ {
+ m_zdo = null;
+ }
+
+ public void Register(string name, Action<long> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod(f));
+ }
+
+ public void Register<T>(string name, Action<long, T> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T>(f));
+ }
+
+ public void Register<T, U>(string name, Action<long, T, U> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T, U>(f));
+ }
+
+ public void Register<T, U, V>(string name, Action<long, T, U, V> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T, U, V>(f));
+ }
+
+ public void Unregister(string name)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ }
+
+ public void HandleRoutedRPC(ZRoutedRpc.RoutedRPCData rpcData)
+ {
+ if (m_functions.TryGetValue(rpcData.m_methodHash, out var value))
+ {
+ value.Invoke(rpcData.m_senderPeerID, rpcData.m_parameters);
+ }
+ else
+ {
+ ZLog.LogWarning("Failed to find rpc method " + rpcData.m_methodHash);
+ }
+ }
+
+ public void InvokeRPC(long targetID, string method, params object[] parameters)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(targetID, m_zdo.m_uid, method, parameters);
+ }
+
+ public void InvokeRPC(string method, params object[] parameters)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC(m_zdo.m_owner, m_zdo.m_uid, method, parameters);
+ }
+
+ public static object[] Deserialize(long callerID, ParameterInfo[] paramInfo, ZPackage pkg)
+ {
+ List<object> parameters = new List<object>();
+ parameters.Add(callerID);
+ ZRpc.Deserialize(paramInfo, pkg, ref parameters);
+ return parameters.ToArray();
+ }
+
+ public static void StartGhostInit()
+ {
+ m_ghostInit = true;
+ }
+
+ public static void FinishGhostInit()
+ {
+ m_ghostInit = false;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNtp.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNtp.cs
new file mode 100644
index 0000000..f04cb95
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZNtp.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+public class ZNtp : IDisposable
+{
+ private static ZNtp m_instance;
+
+ private DateTime m_ntpTime;
+
+ private bool m_status;
+
+ private bool m_stop;
+
+ private Thread m_ntpThread;
+
+ private Mutex m_lock = new Mutex();
+
+ public static ZNtp instance => m_instance;
+
+ public ZNtp()
+ {
+ m_instance = this;
+ m_ntpTime = DateTime.UtcNow;
+ m_ntpThread = new Thread(NtpThread);
+ m_ntpThread.Start();
+ }
+
+ public void Dispose()
+ {
+ if (m_ntpThread != null)
+ {
+ ZLog.Log("Stoping ntp thread");
+ m_lock.WaitOne();
+ m_stop = true;
+ m_ntpThread.Abort();
+ m_lock.ReleaseMutex();
+ m_ntpThread = null;
+ }
+ if (m_lock != null)
+ {
+ m_lock.Close();
+ m_lock = null;
+ }
+ }
+
+ public bool GetStatus()
+ {
+ return m_status;
+ }
+
+ public void Update(float dt)
+ {
+ m_lock.WaitOne();
+ m_ntpTime = m_ntpTime.AddSeconds(dt);
+ m_lock.ReleaseMutex();
+ }
+
+ private void NtpThread()
+ {
+ while (!m_stop)
+ {
+ if (GetNetworkTime("pool.ntp.org", out var time))
+ {
+ m_status = true;
+ m_lock.WaitOne();
+ m_ntpTime = time;
+ m_lock.ReleaseMutex();
+ }
+ else
+ {
+ m_status = false;
+ }
+ Thread.Sleep(60000);
+ }
+ }
+
+ public DateTime GetTime()
+ {
+ return m_ntpTime;
+ }
+
+ private bool GetNetworkTime(string ntpServer, out DateTime time)
+ {
+ byte[] array = new byte[48];
+ array[0] = 27;
+ IPAddress[] addressList;
+ try
+ {
+ addressList = Dns.GetHostEntry(ntpServer).AddressList;
+ if (addressList.Length == 0)
+ {
+ ZLog.Log("Dns lookup failed");
+ time = DateTime.UtcNow;
+ return false;
+ }
+ }
+ catch
+ {
+ ZLog.Log("Failed ntp dns lookup");
+ time = DateTime.UtcNow;
+ return false;
+ }
+ IPEndPoint remoteEP = new IPEndPoint(addressList[0], 123);
+ Socket socket = null;
+ try
+ {
+ socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.ReceiveTimeout = 3000;
+ socket.SendTimeout = 3000;
+ socket.Connect(remoteEP);
+ if (!socket.Connected)
+ {
+ ZLog.Log("Failed to connect to ntp");
+ time = DateTime.UtcNow;
+ socket.Close();
+ return false;
+ }
+ socket.Send(array);
+ socket.Receive(array);
+ socket.Shutdown(SocketShutdown.Both);
+ socket.Close();
+ }
+ catch
+ {
+ socket?.Close();
+ time = DateTime.UtcNow;
+ return false;
+ }
+ ulong num = ((ulong)array[40] << 24) | ((ulong)array[41] << 16) | ((ulong)array[42] << 8) | array[43];
+ ulong num2 = ((ulong)array[44] << 24) | ((ulong)array[45] << 16) | ((ulong)array[46] << 8) | array[47];
+ ulong num3 = num * 1000 + num2 * 1000 / 4294967296uL;
+ time = new DateTime(1900, 1, 1).AddMilliseconds((long)num3);
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZPackage.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZPackage.cs
new file mode 100644
index 0000000..2151732
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZPackage.cs
@@ -0,0 +1,293 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using UnityEngine;
+
+public class ZPackage
+{
+ private MemoryStream m_stream = new MemoryStream();
+
+ private BinaryWriter m_writer;
+
+ private BinaryReader m_reader;
+
+ public ZPackage()
+ {
+ m_writer = new BinaryWriter(m_stream);
+ m_reader = new BinaryReader(m_stream);
+ }
+
+ public ZPackage(string base64String)
+ {
+ m_writer = new BinaryWriter(m_stream);
+ m_reader = new BinaryReader(m_stream);
+ if (!string.IsNullOrEmpty(base64String))
+ {
+ byte[] array = Convert.FromBase64String(base64String);
+ m_stream.Write(array, 0, array.Length);
+ m_stream.Position = 0L;
+ }
+ }
+
+ public ZPackage(byte[] data)
+ {
+ m_writer = new BinaryWriter(m_stream);
+ m_reader = new BinaryReader(m_stream);
+ m_stream.Write(data, 0, data.Length);
+ m_stream.Position = 0L;
+ }
+
+ public ZPackage(byte[] data, int dataSize)
+ {
+ m_writer = new BinaryWriter(m_stream);
+ m_reader = new BinaryReader(m_stream);
+ m_stream.Write(data, 0, dataSize);
+ m_stream.Position = 0L;
+ }
+
+ public void Load(byte[] data)
+ {
+ Clear();
+ m_stream.Write(data, 0, data.Length);
+ m_stream.Position = 0L;
+ }
+
+ public void Write(ZPackage pkg)
+ {
+ m_writer.Write(pkg.Size());
+ m_writer.Write(pkg.GetArray());
+ }
+
+ public void Write(byte[] array)
+ {
+ m_writer.Write(array.Length);
+ m_writer.Write(array);
+ }
+
+ public void Write(byte data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(sbyte data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(char data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(bool data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(int data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(uint data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(ulong data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(long data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(float data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(double data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(string data)
+ {
+ m_writer.Write(data);
+ }
+
+ public void Write(ZDOID id)
+ {
+ m_writer.Write(id.userID);
+ m_writer.Write(id.id);
+ }
+
+ public void Write(Vector3 v3)
+ {
+ m_writer.Write(v3.x);
+ m_writer.Write(v3.y);
+ m_writer.Write(v3.z);
+ }
+
+ public void Write(Vector2i v2)
+ {
+ m_writer.Write(v2.x);
+ m_writer.Write(v2.y);
+ }
+
+ public void Write(Quaternion q)
+ {
+ m_writer.Write(q.x);
+ m_writer.Write(q.y);
+ m_writer.Write(q.z);
+ m_writer.Write(q.w);
+ }
+
+ public ZDOID ReadZDOID()
+ {
+ return new ZDOID(m_reader.ReadInt64(), m_reader.ReadUInt32());
+ }
+
+ public bool ReadBool()
+ {
+ return m_reader.ReadBoolean();
+ }
+
+ public char ReadChar()
+ {
+ return m_reader.ReadChar();
+ }
+
+ public byte ReadByte()
+ {
+ return m_reader.ReadByte();
+ }
+
+ public sbyte ReadSByte()
+ {
+ return m_reader.ReadSByte();
+ }
+
+ public int ReadInt()
+ {
+ return m_reader.ReadInt32();
+ }
+
+ public uint ReadUInt()
+ {
+ return m_reader.ReadUInt32();
+ }
+
+ public long ReadLong()
+ {
+ return m_reader.ReadInt64();
+ }
+
+ public ulong ReadULong()
+ {
+ return m_reader.ReadUInt64();
+ }
+
+ public float ReadSingle()
+ {
+ return m_reader.ReadSingle();
+ }
+
+ public double ReadDouble()
+ {
+ return m_reader.ReadDouble();
+ }
+
+ public string ReadString()
+ {
+ return m_reader.ReadString();
+ }
+
+ public Vector3 ReadVector3()
+ {
+ Vector3 result = default(Vector3);
+ result.x = m_reader.ReadSingle();
+ result.y = m_reader.ReadSingle();
+ result.z = m_reader.ReadSingle();
+ return result;
+ }
+
+ public Vector2i ReadVector2i()
+ {
+ Vector2i result = default(Vector2i);
+ result.x = m_reader.ReadInt32();
+ result.y = m_reader.ReadInt32();
+ return result;
+ }
+
+ public Quaternion ReadQuaternion()
+ {
+ Quaternion result = default(Quaternion);
+ result.x = m_reader.ReadSingle();
+ result.y = m_reader.ReadSingle();
+ result.z = m_reader.ReadSingle();
+ result.w = m_reader.ReadSingle();
+ return result;
+ }
+
+ public ZPackage ReadPackage()
+ {
+ int count = m_reader.ReadInt32();
+ return new ZPackage(m_reader.ReadBytes(count));
+ }
+
+ public void ReadPackage(ref ZPackage pkg)
+ {
+ int count = m_reader.ReadInt32();
+ byte[] array = m_reader.ReadBytes(count);
+ pkg.Clear();
+ pkg.m_stream.Write(array, 0, array.Length);
+ pkg.m_stream.Position = 0L;
+ }
+
+ public byte[] ReadByteArray()
+ {
+ int count = m_reader.ReadInt32();
+ return m_reader.ReadBytes(count);
+ }
+
+ public string GetBase64()
+ {
+ return Convert.ToBase64String(GetArray());
+ }
+
+ public byte[] GetArray()
+ {
+ return m_stream.ToArray();
+ }
+
+ public void SetPos(int pos)
+ {
+ m_stream.Position = pos;
+ }
+
+ public int GetPos()
+ {
+ return (int)m_stream.Position;
+ }
+
+ public int Size()
+ {
+ return (int)m_stream.Length;
+ }
+
+ public void Clear()
+ {
+ m_stream.SetLength(0L);
+ m_stream.Position = 0L;
+ }
+
+ public byte[] GenerateHash()
+ {
+ byte[] buffer = m_stream.ToArray();
+ return SHA512.Create().ComputeHash(buffer);
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRoutedRpc.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRoutedRpc.cs
new file mode 100644
index 0000000..8a9536b
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRoutedRpc.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+
+public class ZRoutedRpc
+{
+ public class RoutedRPCData
+ {
+ public long m_msgID;
+
+ public long m_senderPeerID;
+
+ public long m_targetPeerID;
+
+ public ZDOID m_targetZDO;
+
+ public int m_methodHash;
+
+ public ZPackage m_parameters = new ZPackage();
+
+ public void Serialize(ZPackage pkg)
+ {
+ pkg.Write(m_msgID);
+ pkg.Write(m_senderPeerID);
+ pkg.Write(m_targetPeerID);
+ pkg.Write(m_targetZDO);
+ pkg.Write(m_methodHash);
+ pkg.Write(m_parameters);
+ }
+
+ public void Deserialize(ZPackage pkg)
+ {
+ m_msgID = pkg.ReadLong();
+ m_senderPeerID = pkg.ReadLong();
+ m_targetPeerID = pkg.ReadLong();
+ m_targetZDO = pkg.ReadZDOID();
+ m_methodHash = pkg.ReadInt();
+ m_parameters = pkg.ReadPackage();
+ }
+ }
+
+ public static long Everybody;
+
+ public Action<long> m_onNewPeer;
+
+ private int m_rpcMsgID = 1;
+
+ private bool m_server;
+
+ private long m_id;
+
+ private List<ZNetPeer> m_peers = new List<ZNetPeer>();
+
+ private Dictionary<int, RoutedMethodBase> m_functions = new Dictionary<int, RoutedMethodBase>();
+
+ private static ZRoutedRpc m_instance;
+
+ public static ZRoutedRpc instance => m_instance;
+
+ public ZRoutedRpc(bool server)
+ {
+ m_instance = this;
+ m_server = server;
+ }
+
+ public void SetUID(long uid)
+ {
+ m_id = uid;
+ }
+
+ public void AddPeer(ZNetPeer peer)
+ {
+ m_peers.Add(peer);
+ peer.m_rpc.Register<ZPackage>("RoutedRPC", RPC_RoutedRPC);
+ if (m_onNewPeer != null)
+ {
+ m_onNewPeer(peer.m_uid);
+ }
+ }
+
+ public void RemovePeer(ZNetPeer peer)
+ {
+ m_peers.Remove(peer);
+ }
+
+ private ZNetPeer GetPeer(long uid)
+ {
+ foreach (ZNetPeer peer in m_peers)
+ {
+ if (peer.m_uid == uid)
+ {
+ return peer;
+ }
+ }
+ return null;
+ }
+
+ public void InvokeRoutedRPC(long targetPeerID, string methodName, params object[] parameters)
+ {
+ InvokeRoutedRPC(targetPeerID, ZDOID.None, methodName, parameters);
+ }
+
+ public void InvokeRoutedRPC(string methodName, params object[] parameters)
+ {
+ InvokeRoutedRPC(GetServerPeerID(), methodName, parameters);
+ }
+
+ private long GetServerPeerID()
+ {
+ if (m_server)
+ {
+ return m_id;
+ }
+ if (m_peers.Count > 0)
+ {
+ return m_peers[0].m_uid;
+ }
+ return 0L;
+ }
+
+ public void InvokeRoutedRPC(long targetPeerID, ZDOID targetZDO, string methodName, params object[] parameters)
+ {
+ RoutedRPCData routedRPCData = new RoutedRPCData();
+ routedRPCData.m_msgID = m_id + m_rpcMsgID++;
+ routedRPCData.m_senderPeerID = m_id;
+ routedRPCData.m_targetPeerID = targetPeerID;
+ routedRPCData.m_targetZDO = targetZDO;
+ routedRPCData.m_methodHash = methodName.GetStableHashCode();
+ ZRpc.Serialize(parameters, ref routedRPCData.m_parameters);
+ routedRPCData.m_parameters.SetPos(0);
+ if (targetPeerID == m_id || targetPeerID == 0L)
+ {
+ HandleRoutedRPC(routedRPCData);
+ }
+ if (targetPeerID != m_id)
+ {
+ RouteRPC(routedRPCData);
+ }
+ }
+
+ private void RouteRPC(RoutedRPCData rpcData)
+ {
+ ZPackage zPackage = new ZPackage();
+ rpcData.Serialize(zPackage);
+ if (m_server)
+ {
+ if (rpcData.m_targetPeerID != 0L)
+ {
+ ZNetPeer peer = GetPeer(rpcData.m_targetPeerID);
+ if (peer != null && peer.IsReady())
+ {
+ peer.m_rpc.Invoke("RoutedRPC", zPackage);
+ }
+ return;
+ }
+ {
+ foreach (ZNetPeer peer2 in m_peers)
+ {
+ if (rpcData.m_senderPeerID != peer2.m_uid && peer2.IsReady())
+ {
+ peer2.m_rpc.Invoke("RoutedRPC", zPackage);
+ }
+ }
+ return;
+ }
+ }
+ foreach (ZNetPeer peer3 in m_peers)
+ {
+ if (peer3.IsReady())
+ {
+ peer3.m_rpc.Invoke("RoutedRPC", zPackage);
+ }
+ }
+ }
+
+ private void RPC_RoutedRPC(ZRpc rpc, ZPackage pkg)
+ {
+ RoutedRPCData routedRPCData = new RoutedRPCData();
+ routedRPCData.Deserialize(pkg);
+ if (routedRPCData.m_targetPeerID == m_id || routedRPCData.m_targetPeerID == 0L)
+ {
+ HandleRoutedRPC(routedRPCData);
+ }
+ if (m_server && routedRPCData.m_targetPeerID != m_id)
+ {
+ RouteRPC(routedRPCData);
+ }
+ }
+
+ private void HandleRoutedRPC(RoutedRPCData data)
+ {
+ if (data.m_targetZDO.IsNone())
+ {
+ if (m_functions.TryGetValue(data.m_methodHash, out var value))
+ {
+ value.Invoke(data.m_senderPeerID, data.m_parameters);
+ }
+ return;
+ }
+ ZDO zDO = ZDOMan.instance.GetZDO(data.m_targetZDO);
+ if (zDO != null)
+ {
+ ZNetView zNetView = ZNetScene.instance.FindInstance(zDO);
+ if (zNetView != null)
+ {
+ zNetView.HandleRoutedRPC(data);
+ }
+ }
+ }
+
+ public void Register(string name, Action<long> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod(f));
+ }
+
+ public void Register<T>(string name, Action<long, T> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T>(f));
+ }
+
+ public void Register<T, U>(string name, Action<long, T, U> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T, U>(f));
+ }
+
+ public void Register<T, U, V>(string name, Action<long, T, U, V> f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T, U, V>(f));
+ }
+
+ public void Register<T, U, V, B>(string name, RoutedMethod<T, U, V, B>.Method f)
+ {
+ m_functions.Add(name.GetStableHashCode(), new RoutedMethod<T, U, V, B>(f));
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRpc.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRpc.cs
new file mode 100644
index 0000000..319f033
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZRpc.cs
@@ -0,0 +1,405 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+public class ZRpc : IDisposable
+{
+ private interface RpcMethodBase
+ {
+ void Invoke(ZRpc rpc, ZPackage pkg);
+ }
+
+ public class RpcMethod : RpcMethodBase
+ {
+ public delegate void Method(ZRpc RPC);
+
+ private Method m_action;
+
+ public RpcMethod(Method action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(ZRpc rpc, ZPackage pkg)
+ {
+ m_action(rpc);
+ }
+ }
+
+ private class RpcMethod<T> : RpcMethodBase
+ {
+ private Action<ZRpc, T> m_action;
+
+ public RpcMethod(Action<ZRpc, T> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(ZRpc rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+ }
+
+ private class RpcMethod<T, U> : RpcMethodBase
+ {
+ private Action<ZRpc, T, U> m_action;
+
+ public RpcMethod(Action<ZRpc, T, U> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(ZRpc rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+ }
+
+ private class RpcMethod<T, U, V> : RpcMethodBase
+ {
+ private Action<ZRpc, T, U, V> m_action;
+
+ public RpcMethod(Action<ZRpc, T, U, V> action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(ZRpc rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+ }
+
+ public class RpcMethod<T, U, V, B> : RpcMethodBase
+ {
+ public delegate void Method(ZRpc RPC, T p0, U p1, V p2, B p3);
+
+ private Method m_action;
+
+ public RpcMethod(Method action)
+ {
+ m_action = action;
+ }
+
+ public void Invoke(ZRpc rpc, ZPackage pkg)
+ {
+ m_action.DynamicInvoke(Deserialize(rpc, m_action.Method.GetParameters(), pkg));
+ }
+ }
+
+ private ISocket m_socket;
+
+ private ZPackage m_pkg = new ZPackage();
+
+ private Dictionary<int, RpcMethodBase> m_functions = new Dictionary<int, RpcMethodBase>();
+
+ private float m_pingTimer;
+
+ private float m_timeSinceLastData;
+
+ private static float m_pingInterval = 4f;
+
+ private static float m_timeout = 120f;
+
+ private static bool m_DEBUG = false;
+
+ public ZRpc(ISocket socket)
+ {
+ m_socket = socket;
+ }
+
+ public void Dispose()
+ {
+ m_socket.Dispose();
+ }
+
+ public ISocket GetSocket()
+ {
+ return m_socket;
+ }
+
+ public bool Update(float dt)
+ {
+ if (!m_socket.IsConnected())
+ {
+ return false;
+ }
+ for (ZPackage zPackage = m_socket.Recv(); zPackage != null; zPackage = m_socket.Recv())
+ {
+ try
+ {
+ HandlePackage(zPackage);
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Exception in ZRpc::HandlePackage: " + ex);
+ }
+ }
+ UpdatePing(dt);
+ return true;
+ }
+
+ private void UpdatePing(float dt)
+ {
+ m_pingTimer += dt;
+ if (m_pingTimer > m_pingInterval)
+ {
+ m_pingTimer = 0f;
+ if (!m_socket.IsSending())
+ {
+ m_pkg.Clear();
+ m_pkg.Write(0);
+ m_socket.Send(m_pkg);
+ }
+ }
+ if (m_socket.GotNewData())
+ {
+ m_timeSinceLastData = 0f;
+ }
+ m_timeSinceLastData += dt;
+ if (m_timeSinceLastData > m_timeout)
+ {
+ ZLog.LogWarning("ZRpc timeout detected");
+ m_socket.Close();
+ }
+ }
+
+ public float GetTimeSinceLastData()
+ {
+ return m_timeSinceLastData;
+ }
+
+ public bool IsConnected()
+ {
+ return m_socket.IsConnected();
+ }
+
+ private void HandlePackage(ZPackage package)
+ {
+ int num = package.ReadInt();
+ if (num == 0)
+ {
+ return;
+ }
+ RpcMethodBase value2;
+ if (m_DEBUG)
+ {
+ package.ReadString();
+ if (m_functions.TryGetValue(num, out var value))
+ {
+ value.Invoke(this, package);
+ }
+ }
+ else if (m_functions.TryGetValue(num, out value2))
+ {
+ value2.Invoke(this, package);
+ }
+ }
+
+ public void Register(string name, RpcMethod.Method f)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ m_functions.Add(stableHashCode, new RpcMethod(f));
+ }
+
+ public void Register<T>(string name, Action<ZRpc, T> f)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ m_functions.Add(stableHashCode, new RpcMethod<T>(f));
+ }
+
+ public void Register<T, U>(string name, Action<ZRpc, T, U> f)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ m_functions.Add(stableHashCode, new RpcMethod<T, U>(f));
+ }
+
+ public void Register<T, U, V>(string name, Action<ZRpc, T, U, V> f)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ m_functions.Add(stableHashCode, new RpcMethod<T, U, V>(f));
+ }
+
+ public void Register<T, U, V, W>(string name, RpcMethod<T, U, V, W>.Method f)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ m_functions.Add(stableHashCode, new RpcMethod<T, U, V, W>(f));
+ }
+
+ public void Unregister(string name)
+ {
+ int stableHashCode = name.GetStableHashCode();
+ m_functions.Remove(stableHashCode);
+ }
+
+ public void Invoke(string method, params object[] parameters)
+ {
+ if (IsConnected())
+ {
+ m_pingTimer = 0f;
+ m_pkg.Clear();
+ int stableHashCode = method.GetStableHashCode();
+ m_pkg.Write(stableHashCode);
+ if (m_DEBUG)
+ {
+ m_pkg.Write(method);
+ }
+ Serialize(parameters, ref m_pkg);
+ m_socket.Send(m_pkg);
+ }
+ }
+
+ public static void Serialize(object[] parameters, ref ZPackage pkg)
+ {
+ foreach (object obj in parameters)
+ {
+ if (obj is int)
+ {
+ pkg.Write((int)obj);
+ }
+ else if (obj is uint)
+ {
+ pkg.Write((uint)obj);
+ }
+ else if (obj is long)
+ {
+ pkg.Write((long)obj);
+ }
+ else if (obj is float)
+ {
+ pkg.Write((float)obj);
+ }
+ else if (obj is double)
+ {
+ pkg.Write((double)obj);
+ }
+ else if (obj is bool)
+ {
+ pkg.Write((bool)obj);
+ }
+ else if (obj is string)
+ {
+ pkg.Write((string)obj);
+ }
+ else if (obj is ZPackage)
+ {
+ pkg.Write((ZPackage)obj);
+ }
+ else if (obj is List<string>)
+ {
+ List<string> list = obj as List<string>;
+ pkg.Write(list.Count);
+ foreach (string item in list)
+ {
+ pkg.Write(item);
+ }
+ }
+ else if (obj is Vector3)
+ {
+ pkg.Write(((Vector3)obj).x);
+ pkg.Write(((Vector3)obj).y);
+ pkg.Write(((Vector3)obj).z);
+ }
+ else if (obj is Quaternion)
+ {
+ pkg.Write(((Quaternion)obj).x);
+ pkg.Write(((Quaternion)obj).y);
+ pkg.Write(((Quaternion)obj).z);
+ pkg.Write(((Quaternion)obj).w);
+ }
+ else if (obj is ZDOID)
+ {
+ pkg.Write((ZDOID)obj);
+ }
+ else if (obj is HitData)
+ {
+ (obj as HitData).Serialize(ref pkg);
+ }
+ }
+ }
+
+ public static object[] Deserialize(ZRpc rpc, ParameterInfo[] paramInfo, ZPackage pkg)
+ {
+ List<object> parameters = new List<object>();
+ parameters.Add(rpc);
+ Deserialize(paramInfo, pkg, ref parameters);
+ return parameters.ToArray();
+ }
+
+ public static void Deserialize(ParameterInfo[] paramInfo, ZPackage pkg, ref List<object> parameters)
+ {
+ for (int i = 1; i < paramInfo.Length; i++)
+ {
+ ParameterInfo parameterInfo = paramInfo[i];
+ if (parameterInfo.ParameterType == typeof(int))
+ {
+ parameters.Add(pkg.ReadInt());
+ }
+ else if (parameterInfo.ParameterType == typeof(uint))
+ {
+ parameters.Add(pkg.ReadUInt());
+ }
+ else if (parameterInfo.ParameterType == typeof(long))
+ {
+ parameters.Add(pkg.ReadLong());
+ }
+ else if (parameterInfo.ParameterType == typeof(float))
+ {
+ parameters.Add(pkg.ReadSingle());
+ }
+ else if (parameterInfo.ParameterType == typeof(double))
+ {
+ parameters.Add(pkg.ReadDouble());
+ }
+ else if (parameterInfo.ParameterType == typeof(bool))
+ {
+ parameters.Add(pkg.ReadBool());
+ }
+ else if (parameterInfo.ParameterType == typeof(string))
+ {
+ parameters.Add(pkg.ReadString());
+ }
+ else if (parameterInfo.ParameterType == typeof(ZPackage))
+ {
+ parameters.Add(pkg.ReadPackage());
+ }
+ else if (parameterInfo.ParameterType == typeof(List<string>))
+ {
+ int num = pkg.ReadInt();
+ List<string> list = new List<string>(num);
+ for (int j = 0; j < num; j++)
+ {
+ list.Add(pkg.ReadString());
+ }
+ parameters.Add(list);
+ }
+ else if (parameterInfo.ParameterType == typeof(Vector3))
+ {
+ Vector3 vector = new Vector3(pkg.ReadSingle(), pkg.ReadSingle(), pkg.ReadSingle());
+ parameters.Add(vector);
+ }
+ else if (parameterInfo.ParameterType == typeof(Quaternion))
+ {
+ Quaternion quaternion = new Quaternion(pkg.ReadSingle(), pkg.ReadSingle(), pkg.ReadSingle(), pkg.ReadSingle());
+ parameters.Add(quaternion);
+ }
+ else if (parameterInfo.ParameterType == typeof(ZDOID))
+ {
+ parameters.Add(pkg.ReadZDOID());
+ }
+ else if (parameterInfo.ParameterType == typeof(HitData))
+ {
+ HitData hitData = new HitData();
+ hitData.Deserialize(ref pkg);
+ parameters.Add(hitData);
+ }
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSFX.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSFX.cs
new file mode 100644
index 0000000..63294ab
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSFX.cs
@@ -0,0 +1,219 @@
+using UnityEngine;
+
+public class ZSFX : MonoBehaviour
+{
+ public bool m_playOnAwake = true;
+
+ [Header("Clips")]
+ public AudioClip[] m_audioClips = new AudioClip[0];
+
+ [Header("Random")]
+ public float m_maxPitch = 1f;
+
+ public float m_minPitch = 1f;
+
+ public float m_maxVol = 1f;
+
+ public float m_minVol = 1f;
+
+ [Header("Fade")]
+ public float m_fadeInDuration;
+
+ public float m_fadeOutDuration;
+
+ public float m_fadeOutDelay;
+
+ public bool m_fadeOutOnAwake;
+
+ [Header("Pan")]
+ public bool m_randomPan;
+
+ public float m_minPan = -1f;
+
+ public float m_maxPan = 1f;
+
+ [Header("Delay")]
+ public float m_maxDelay;
+
+ public float m_minDelay;
+
+ [Header("Reverb")]
+ public bool m_distanceReverb = true;
+
+ public bool m_useCustomReverbDistance;
+
+ public float m_customReverbDistance = 10f;
+
+ private const float m_globalReverbDistance = 64f;
+
+ private const float m_minReverbSpread = 45f;
+
+ private const float m_maxReverbSpread = 120f;
+
+ private float m_delay;
+
+ private float m_time;
+
+ private float m_fadeOutTimer = -1f;
+
+ private float m_fadeInTimer = -1f;
+
+ private float m_vol = 1f;
+
+ private float m_baseSpread;
+
+ private float m_updateReverbTimer;
+
+ private AudioSource m_audioSource;
+
+ public void Awake()
+ {
+ m_delay = Random.Range(m_minDelay, m_maxDelay);
+ m_audioSource = GetComponent<AudioSource>();
+ m_baseSpread = m_audioSource.spread;
+ }
+
+ private void OnDisable()
+ {
+ if (m_playOnAwake && m_audioSource.loop)
+ {
+ m_time = 0f;
+ m_delay = Random.Range(m_minDelay, m_maxDelay);
+ m_audioSource.Stop();
+ }
+ }
+
+ public void Update()
+ {
+ if (m_audioSource == null)
+ {
+ return;
+ }
+ m_time += Time.deltaTime;
+ if (m_delay >= 0f && m_time >= m_delay)
+ {
+ m_delay = -1f;
+ if (m_playOnAwake)
+ {
+ Play();
+ }
+ }
+ if (!m_audioSource.isPlaying)
+ {
+ return;
+ }
+ if (m_distanceReverb && m_audioSource.loop)
+ {
+ m_updateReverbTimer += Time.deltaTime;
+ if (m_updateReverbTimer > 1f)
+ {
+ m_updateReverbTimer = 0f;
+ UpdateReverb();
+ }
+ }
+ if (m_fadeOutOnAwake && m_time > m_fadeOutDelay)
+ {
+ m_fadeOutOnAwake = false;
+ FadeOut();
+ }
+ if (m_fadeOutTimer >= 0f)
+ {
+ m_fadeOutTimer += Time.deltaTime;
+ if (m_fadeOutTimer >= m_fadeOutDuration)
+ {
+ m_audioSource.volume = 0f;
+ Stop();
+ }
+ else
+ {
+ float num = Mathf.Clamp01(m_fadeOutTimer / m_fadeOutDuration);
+ m_audioSource.volume = (1f - num) * m_vol;
+ }
+ }
+ else if (m_fadeInTimer >= 0f)
+ {
+ m_fadeInTimer += Time.deltaTime;
+ float num2 = Mathf.Clamp01(m_fadeInTimer / m_fadeInDuration);
+ m_audioSource.volume = num2 * m_vol;
+ if (m_fadeInTimer > m_fadeInDuration)
+ {
+ m_fadeInTimer = -1f;
+ }
+ }
+ }
+
+ public void FadeOut()
+ {
+ if (m_fadeOutTimer < 0f)
+ {
+ m_fadeOutTimer = 0f;
+ }
+ }
+
+ public void Stop()
+ {
+ if (m_audioSource != null)
+ {
+ m_audioSource.Stop();
+ }
+ }
+
+ public bool IsPlaying()
+ {
+ if (m_audioSource == null)
+ {
+ return false;
+ }
+ return m_audioSource.isPlaying;
+ }
+
+ private void UpdateReverb()
+ {
+ Camera mainCamera = Utils.GetMainCamera();
+ if (m_distanceReverb && m_audioSource.spatialBlend != 0f && mainCamera != null)
+ {
+ float num = Vector3.Distance(mainCamera.transform.position, base.transform.position);
+ float num2 = (m_useCustomReverbDistance ? m_customReverbDistance : 64f);
+ float a = Mathf.Clamp01(num / num2);
+ float b = Mathf.Clamp01(m_audioSource.maxDistance / num2) * Mathf.Clamp01(num / m_audioSource.maxDistance);
+ float num3 = Mathf.Max(a, b);
+ m_audioSource.bypassReverbZones = false;
+ m_audioSource.reverbZoneMix = num3;
+ if (m_baseSpread < 120f)
+ {
+ float a2 = Mathf.Max(m_baseSpread, 45f);
+ m_audioSource.spread = Mathf.Lerp(a2, 120f, num3);
+ }
+ }
+ else
+ {
+ m_audioSource.bypassReverbZones = true;
+ }
+ }
+
+ public void Play()
+ {
+ if (!(m_audioSource == null) && m_audioClips.Length != 0 && m_audioSource.gameObject.activeInHierarchy)
+ {
+ int num = Random.Range(0, m_audioClips.Length);
+ m_audioSource.clip = m_audioClips[num];
+ m_audioSource.pitch = Random.Range(m_minPitch, m_maxPitch);
+ if (m_randomPan)
+ {
+ m_audioSource.panStereo = Random.Range(m_minPan, m_maxPan);
+ }
+ m_vol = Random.Range(m_minVol, m_maxVol);
+ if (m_fadeInDuration > 0f)
+ {
+ m_audioSource.volume = 0f;
+ m_fadeInTimer = 0f;
+ }
+ else
+ {
+ m_audioSource.volume = m_vol;
+ }
+ UpdateReverb();
+ m_audioSource.Play();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket.cs
new file mode 100644
index 0000000..f2a2f35
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket.cs
@@ -0,0 +1,449 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+public class ZSocket : IDisposable
+{
+ private Socket m_socket;
+
+ private Mutex m_mutex = new Mutex();
+
+ private Mutex m_sendMutex = new Mutex();
+
+ private Queue<Socket> m_newConnections = new Queue<Socket>();
+
+ private static int m_maxRecvBuffer = 10485760;
+
+ private int m_recvOffset;
+
+ private byte[] m_recvBuffer;
+
+ private byte[] m_recvSizeBuffer = new byte[4];
+
+ private Queue<ZPackage> m_pkgQueue = new Queue<ZPackage>();
+
+ private bool m_isSending;
+
+ private Queue<byte[]> m_sendQueue = new Queue<byte[]>();
+
+ private IPEndPoint m_endpoint;
+
+ private string m_originalHostName;
+
+ private int m_listenPort;
+
+ private int m_lastRecvPkgSize;
+
+ private int m_totalSent;
+
+ private int m_totalRecv;
+
+ public ZSocket()
+ {
+ m_socket = CreateSocket();
+ }
+
+ public static Socket CreateSocket()
+ {
+ return new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
+ {
+ NoDelay = true
+ };
+ }
+
+ public ZSocket(Socket socket, string originalHostName = null)
+ {
+ m_socket = socket;
+ m_originalHostName = originalHostName;
+ try
+ {
+ m_endpoint = m_socket.RemoteEndPoint as IPEndPoint;
+ }
+ catch
+ {
+ Close();
+ return;
+ }
+ BeginReceive();
+ }
+
+ public void Dispose()
+ {
+ Close();
+ m_mutex.Close();
+ m_sendMutex.Close();
+ m_recvBuffer = null;
+ }
+
+ public void Close()
+ {
+ if (m_socket != null)
+ {
+ try
+ {
+ if (m_socket.Connected)
+ {
+ m_socket.Shutdown(SocketShutdown.Both);
+ }
+ }
+ catch (Exception)
+ {
+ }
+ m_socket.Close();
+ }
+ m_socket = null;
+ m_endpoint = null;
+ }
+
+ public static IPEndPoint GetEndPoint(string host, int port)
+ {
+ return new IPEndPoint(Dns.GetHostEntry(host).AddressList[0], port);
+ }
+
+ public bool Connect(string host, int port)
+ {
+ ZLog.Log("Connecting to " + host + " : " + port);
+ IPEndPoint endPoint = GetEndPoint(host, port);
+ m_socket.BeginConnect(endPoint, null, null).AsyncWaitHandle.WaitOne(3000, exitContext: true);
+ if (!m_socket.Connected)
+ {
+ return false;
+ }
+ try
+ {
+ m_endpoint = m_socket.RemoteEndPoint as IPEndPoint;
+ }
+ catch
+ {
+ Close();
+ return false;
+ }
+ BeginReceive();
+ ZLog.Log(" connected");
+ return true;
+ }
+
+ public bool StartHost(int port)
+ {
+ if (m_listenPort != 0)
+ {
+ Close();
+ }
+ if (!BindSocket(m_socket, IPAddress.Any, port, port + 10))
+ {
+ ZLog.LogWarning("Failed to bind socket");
+ return false;
+ }
+ m_socket.Listen(100);
+ m_socket.BeginAccept(AcceptCallback, m_socket);
+ return true;
+ }
+
+ private bool BindSocket(Socket socket, IPAddress ipAddress, int startPort, int endPort)
+ {
+ for (int i = startPort; i <= endPort; i++)
+ {
+ try
+ {
+ IPEndPoint localEP = new IPEndPoint(ipAddress, i);
+ m_socket.Bind(localEP);
+ m_listenPort = i;
+ ZLog.Log("Bound socket port " + i);
+ return true;
+ }
+ catch
+ {
+ ZLog.Log("Failed to bind port:" + i);
+ }
+ }
+ return false;
+ }
+
+ private void BeginReceive()
+ {
+ m_socket.BeginReceive(m_recvSizeBuffer, 0, m_recvSizeBuffer.Length, SocketFlags.None, PkgSizeReceived, m_socket);
+ }
+
+ private void PkgSizeReceived(IAsyncResult res)
+ {
+ int num;
+ try
+ {
+ num = m_socket.EndReceive(res);
+ }
+ catch (Exception)
+ {
+ Disconnect();
+ return;
+ }
+ m_totalRecv += num;
+ if (num != 4)
+ {
+ Disconnect();
+ return;
+ }
+ int num2 = BitConverter.ToInt32(m_recvSizeBuffer, 0);
+ if (num2 == 0 || num2 > 10485760)
+ {
+ ZLog.LogError("Invalid pkg size " + num2);
+ return;
+ }
+ m_lastRecvPkgSize = num2;
+ m_recvOffset = 0;
+ m_lastRecvPkgSize = num2;
+ if (m_recvBuffer == null)
+ {
+ m_recvBuffer = new byte[m_maxRecvBuffer];
+ }
+ m_socket.BeginReceive(m_recvBuffer, m_recvOffset, m_lastRecvPkgSize, SocketFlags.None, PkgReceived, m_socket);
+ }
+
+ private void Disconnect()
+ {
+ if (m_socket != null)
+ {
+ try
+ {
+ m_socket.Disconnect(reuseSocket: true);
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ private void PkgReceived(IAsyncResult res)
+ {
+ int num;
+ try
+ {
+ num = m_socket.EndReceive(res);
+ }
+ catch (Exception)
+ {
+ Disconnect();
+ return;
+ }
+ m_totalRecv += num;
+ m_recvOffset += num;
+ if (m_recvOffset < m_lastRecvPkgSize)
+ {
+ int size = m_lastRecvPkgSize - m_recvOffset;
+ if (m_recvBuffer == null)
+ {
+ m_recvBuffer = new byte[m_maxRecvBuffer];
+ }
+ m_socket.BeginReceive(m_recvBuffer, m_recvOffset, size, SocketFlags.None, PkgReceived, m_socket);
+ }
+ else
+ {
+ ZPackage item = new ZPackage(m_recvBuffer, m_lastRecvPkgSize);
+ m_mutex.WaitOne();
+ m_pkgQueue.Enqueue(item);
+ m_mutex.ReleaseMutex();
+ BeginReceive();
+ }
+ }
+
+ private void AcceptCallback(IAsyncResult res)
+ {
+ Socket item;
+ try
+ {
+ item = m_socket.EndAccept(res);
+ }
+ catch
+ {
+ Disconnect();
+ return;
+ }
+ m_mutex.WaitOne();
+ m_newConnections.Enqueue(item);
+ m_mutex.ReleaseMutex();
+ m_socket.BeginAccept(AcceptCallback, m_socket);
+ }
+
+ public ZSocket Accept()
+ {
+ if (m_newConnections.Count == 0)
+ {
+ return null;
+ }
+ Socket socket = null;
+ m_mutex.WaitOne();
+ if (m_newConnections.Count > 0)
+ {
+ socket = m_newConnections.Dequeue();
+ }
+ m_mutex.ReleaseMutex();
+ if (socket != null)
+ {
+ return new ZSocket(socket);
+ }
+ return null;
+ }
+
+ public bool IsConnected()
+ {
+ if (m_socket != null)
+ {
+ return m_socket.Connected;
+ }
+ return false;
+ }
+
+ public void Send(ZPackage pkg)
+ {
+ if (pkg.Size() == 0 || m_socket == null || !m_socket.Connected)
+ {
+ return;
+ }
+ byte[] array = pkg.GetArray();
+ byte[] bytes = BitConverter.GetBytes(array.Length);
+ m_sendMutex.WaitOne();
+ if (!m_isSending)
+ {
+ if (array.Length > 10485760)
+ {
+ ZLog.LogError("Too big data package: " + array.Length);
+ }
+ try
+ {
+ m_totalSent += bytes.Length;
+ m_socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, PkgSent, null);
+ m_isSending = true;
+ m_sendQueue.Enqueue(array);
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Handled exception in ZSocket:Send:" + ex);
+ Disconnect();
+ }
+ }
+ else
+ {
+ m_sendQueue.Enqueue(bytes);
+ m_sendQueue.Enqueue(array);
+ }
+ m_sendMutex.ReleaseMutex();
+ }
+
+ private void PkgSent(IAsyncResult res)
+ {
+ m_sendMutex.WaitOne();
+ if (m_sendQueue.Count > 0 && IsConnected())
+ {
+ byte[] array = m_sendQueue.Dequeue();
+ try
+ {
+ m_totalSent += array.Length;
+ m_socket.BeginSend(array, 0, array.Length, SocketFlags.None, PkgSent, null);
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Handled exception in pkgsent:" + ex);
+ m_isSending = false;
+ Disconnect();
+ }
+ }
+ else
+ {
+ m_isSending = false;
+ }
+ m_sendMutex.ReleaseMutex();
+ }
+
+ public ZPackage Recv()
+ {
+ if (m_socket == null)
+ {
+ return null;
+ }
+ if (m_pkgQueue.Count == 0)
+ {
+ return null;
+ }
+ ZPackage result = null;
+ m_mutex.WaitOne();
+ if (m_pkgQueue.Count > 0)
+ {
+ result = m_pkgQueue.Dequeue();
+ }
+ m_mutex.ReleaseMutex();
+ return result;
+ }
+
+ public string GetEndPointString()
+ {
+ if (m_endpoint != null)
+ {
+ return m_endpoint.ToString();
+ }
+ return "None";
+ }
+
+ public string GetEndPointHost()
+ {
+ if (m_endpoint != null)
+ {
+ return m_endpoint.Address.ToString();
+ }
+ return "None";
+ }
+
+ public IPEndPoint GetEndPoint()
+ {
+ return m_endpoint;
+ }
+
+ public bool IsPeer(string host, int port)
+ {
+ if (!IsConnected())
+ {
+ return false;
+ }
+ if (m_endpoint == null)
+ {
+ return false;
+ }
+ IPEndPoint endpoint = m_endpoint;
+ if (endpoint.Address.ToString() == host && endpoint.Port == port)
+ {
+ return true;
+ }
+ if (m_originalHostName != null && m_originalHostName == host && endpoint.Port == port)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsHost()
+ {
+ return m_listenPort != 0;
+ }
+
+ public int GetHostPort()
+ {
+ return m_listenPort;
+ }
+
+ public bool IsSending()
+ {
+ if (!m_isSending)
+ {
+ return m_sendQueue.Count > 0;
+ }
+ return true;
+ }
+
+ public void GetAndResetStats(out int totalSent, out int totalRecv)
+ {
+ totalSent = m_totalSent;
+ totalRecv = m_totalRecv;
+ m_totalSent = 0;
+ m_totalRecv = 0;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket2.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket2.cs
new file mode 100644
index 0000000..887648d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSocket2.cs
@@ -0,0 +1,440 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+public class ZSocket2 : IDisposable, ISocket
+{
+ private TcpListener m_listner;
+
+ private TcpClient m_socket;
+
+ private Mutex m_mutex = new Mutex();
+
+ private Mutex m_sendMutex = new Mutex();
+
+ private static int m_maxRecvBuffer = 10485760;
+
+ private int m_recvOffset;
+
+ private byte[] m_recvBuffer;
+
+ private int m_recvSizeOffset;
+
+ private byte[] m_recvSizeBuffer = new byte[4];
+
+ private Queue<ZPackage> m_pkgQueue = new Queue<ZPackage>();
+
+ private bool m_isSending;
+
+ private Queue<byte[]> m_sendQueue = new Queue<byte[]>();
+
+ private IPEndPoint m_endpoint;
+
+ private string m_originalHostName;
+
+ private int m_listenPort;
+
+ private int m_lastRecvPkgSize;
+
+ private int m_totalSent;
+
+ private int m_totalRecv;
+
+ private bool m_gotData;
+
+ public ZSocket2()
+ {
+ }
+
+ public static TcpClient CreateSocket()
+ {
+ TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork);
+ ConfigureSocket(tcpClient);
+ return tcpClient;
+ }
+
+ private static void ConfigureSocket(TcpClient socket)
+ {
+ socket.NoDelay = true;
+ socket.SendBufferSize = 2048;
+ }
+
+ public ZSocket2(TcpClient socket, string originalHostName = null)
+ {
+ m_socket = socket;
+ m_originalHostName = originalHostName;
+ try
+ {
+ m_endpoint = m_socket.Client.RemoteEndPoint as IPEndPoint;
+ }
+ catch
+ {
+ Close();
+ return;
+ }
+ BeginReceive();
+ }
+
+ public void Dispose()
+ {
+ Close();
+ m_mutex.Close();
+ m_sendMutex.Close();
+ m_recvBuffer = null;
+ }
+
+ public void Close()
+ {
+ ZLog.Log("Closing socket " + GetEndPointString());
+ if (m_listner != null)
+ {
+ m_listner.Stop();
+ m_listner = null;
+ }
+ if (m_socket != null)
+ {
+ m_socket.Close();
+ m_socket = null;
+ }
+ m_endpoint = null;
+ }
+
+ public static IPEndPoint GetEndPoint(string host, int port)
+ {
+ return new IPEndPoint(Dns.GetHostEntry(host).AddressList[0], port);
+ }
+
+ public bool StartHost(int port)
+ {
+ if (m_listner != null)
+ {
+ m_listner.Stop();
+ m_listner = null;
+ }
+ if (!BindSocket(port, port + 10))
+ {
+ ZLog.LogWarning("Failed to bind socket");
+ return false;
+ }
+ return true;
+ }
+
+ private bool BindSocket(int startPort, int endPort)
+ {
+ for (int i = startPort; i <= endPort; i++)
+ {
+ try
+ {
+ m_listner = new TcpListener(IPAddress.Any, i);
+ m_listner.Start();
+ m_listenPort = i;
+ ZLog.Log("Bound socket port " + i);
+ return true;
+ }
+ catch
+ {
+ ZLog.Log("Failed to bind port:" + i);
+ m_listner = null;
+ }
+ }
+ return false;
+ }
+
+ private void BeginReceive()
+ {
+ m_recvSizeOffset = 0;
+ m_socket.GetStream().BeginRead(m_recvSizeBuffer, 0, m_recvSizeBuffer.Length, PkgSizeReceived, m_socket);
+ }
+
+ private void PkgSizeReceived(IAsyncResult res)
+ {
+ if (m_socket == null || !m_socket.Connected)
+ {
+ ZLog.LogWarning("PkgSizeReceived socket closed");
+ Close();
+ return;
+ }
+ int num;
+ try
+ {
+ num = m_socket.GetStream().EndRead(res);
+ }
+ catch (Exception ex)
+ {
+ ZLog.LogWarning("PkgSizeReceived exception " + ex.ToString());
+ Close();
+ return;
+ }
+ if (num == 0)
+ {
+ ZLog.LogWarning("PkgSizeReceived Got 0 bytes data,closing socket");
+ Close();
+ return;
+ }
+ m_gotData = true;
+ m_recvSizeOffset += num;
+ if (m_recvSizeOffset < m_recvSizeBuffer.Length)
+ {
+ int count = m_recvSizeBuffer.Length - m_recvOffset;
+ m_socket.GetStream().BeginRead(m_recvSizeBuffer, m_recvSizeOffset, count, PkgSizeReceived, m_socket);
+ return;
+ }
+ int num2 = BitConverter.ToInt32(m_recvSizeBuffer, 0);
+ if (num2 == 0 || num2 > 10485760)
+ {
+ ZLog.LogError("PkgSizeReceived Invalid pkg size " + num2);
+ return;
+ }
+ m_lastRecvPkgSize = num2;
+ m_recvOffset = 0;
+ m_lastRecvPkgSize = num2;
+ if (m_recvBuffer == null)
+ {
+ m_recvBuffer = new byte[m_maxRecvBuffer];
+ }
+ m_socket.GetStream().BeginRead(m_recvBuffer, m_recvOffset, m_lastRecvPkgSize, PkgReceived, m_socket);
+ }
+
+ private void PkgReceived(IAsyncResult res)
+ {
+ int num;
+ try
+ {
+ num = m_socket.GetStream().EndRead(res);
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("PkgReceived error " + ex.ToString());
+ Close();
+ return;
+ }
+ if (num == 0)
+ {
+ ZLog.LogWarning("PkgReceived: Got 0 bytes data,closing socket");
+ Close();
+ return;
+ }
+ m_gotData = true;
+ m_totalRecv += num;
+ m_recvOffset += num;
+ if (m_recvOffset < m_lastRecvPkgSize)
+ {
+ int count = m_lastRecvPkgSize - m_recvOffset;
+ if (m_recvBuffer == null)
+ {
+ m_recvBuffer = new byte[m_maxRecvBuffer];
+ }
+ m_socket.GetStream().BeginRead(m_recvBuffer, m_recvOffset, count, PkgReceived, m_socket);
+ }
+ else
+ {
+ ZPackage item = new ZPackage(m_recvBuffer, m_lastRecvPkgSize);
+ m_mutex.WaitOne();
+ m_pkgQueue.Enqueue(item);
+ m_mutex.ReleaseMutex();
+ BeginReceive();
+ }
+ }
+
+ public ISocket Accept()
+ {
+ if (m_listner == null)
+ {
+ return null;
+ }
+ if (!m_listner.Pending())
+ {
+ return null;
+ }
+ TcpClient socket = m_listner.AcceptTcpClient();
+ ConfigureSocket(socket);
+ return new ZSocket2(socket);
+ }
+
+ public bool IsConnected()
+ {
+ if (m_socket != null)
+ {
+ return m_socket.Connected;
+ }
+ return false;
+ }
+
+ public void Send(ZPackage pkg)
+ {
+ if (pkg.Size() == 0 || m_socket == null || !m_socket.Connected)
+ {
+ return;
+ }
+ byte[] array = pkg.GetArray();
+ byte[] bytes = BitConverter.GetBytes(array.Length);
+ byte[] array2 = new byte[array.Length + bytes.Length];
+ bytes.CopyTo(array2, 0);
+ array.CopyTo(array2, 4);
+ m_sendMutex.WaitOne();
+ if (!m_isSending)
+ {
+ if (array2.Length > 10485760)
+ {
+ ZLog.LogError("Too big data package: " + array2.Length);
+ }
+ try
+ {
+ m_totalSent += array2.Length;
+ m_socket.GetStream().BeginWrite(array2, 0, array2.Length, PkgSent, m_socket);
+ m_isSending = true;
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("Handled exception in ZSocket:Send:" + ex);
+ Close();
+ }
+ }
+ else
+ {
+ m_sendQueue.Enqueue(array2);
+ }
+ m_sendMutex.ReleaseMutex();
+ }
+
+ private void PkgSent(IAsyncResult res)
+ {
+ try
+ {
+ m_socket.GetStream().EndWrite(res);
+ }
+ catch (Exception ex)
+ {
+ ZLog.Log("PkgSent error " + ex.ToString());
+ Close();
+ return;
+ }
+ m_sendMutex.WaitOne();
+ if (m_sendQueue.Count > 0 && IsConnected())
+ {
+ byte[] array = m_sendQueue.Dequeue();
+ try
+ {
+ m_totalSent += array.Length;
+ m_socket.GetStream().BeginWrite(array, 0, array.Length, PkgSent, m_socket);
+ }
+ catch (Exception ex2)
+ {
+ ZLog.Log("Handled exception in pkgsent:" + ex2);
+ m_isSending = false;
+ Close();
+ }
+ }
+ else
+ {
+ m_isSending = false;
+ }
+ m_sendMutex.ReleaseMutex();
+ }
+
+ public ZPackage Recv()
+ {
+ if (m_socket == null)
+ {
+ return null;
+ }
+ if (m_pkgQueue.Count == 0)
+ {
+ return null;
+ }
+ ZPackage result = null;
+ m_mutex.WaitOne();
+ if (m_pkgQueue.Count > 0)
+ {
+ result = m_pkgQueue.Dequeue();
+ }
+ m_mutex.ReleaseMutex();
+ return result;
+ }
+
+ public string GetEndPointString()
+ {
+ if (m_endpoint != null)
+ {
+ return m_endpoint.ToString();
+ }
+ return "None";
+ }
+
+ public string GetHostName()
+ {
+ if (m_endpoint != null)
+ {
+ return m_endpoint.Address.ToString();
+ }
+ return "None";
+ }
+
+ public IPEndPoint GetEndPoint()
+ {
+ return m_endpoint;
+ }
+
+ public bool IsPeer(string host, int port)
+ {
+ if (!IsConnected())
+ {
+ return false;
+ }
+ if (m_endpoint == null)
+ {
+ return false;
+ }
+ IPEndPoint endpoint = m_endpoint;
+ if (endpoint.Address.ToString() == host && endpoint.Port == port)
+ {
+ return true;
+ }
+ if (m_originalHostName != null && m_originalHostName == host && endpoint.Port == port)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsHost()
+ {
+ return m_listenPort != 0;
+ }
+
+ public int GetHostPort()
+ {
+ return m_listenPort;
+ }
+
+ public bool IsSending()
+ {
+ if (!m_isSending)
+ {
+ return m_sendQueue.Count > 0;
+ }
+ return true;
+ }
+
+ public void GetAndResetStats(out int totalSent, out int totalRecv)
+ {
+ totalSent = m_totalSent;
+ totalRecv = m_totalRecv;
+ m_totalSent = 0;
+ m_totalRecv = 0;
+ }
+
+ public bool GotNewData()
+ {
+ bool gotData = m_gotData;
+ m_gotData = false;
+ return gotData;
+ }
+
+ public bool Flush()
+ {
+ return true;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs
new file mode 100644
index 0000000..45811a2
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs
@@ -0,0 +1,427 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using Steamworks;
+
+public class ZSteamMatchmaking
+{
+ private static ZSteamMatchmaking m_instance;
+
+ private List<MasterClient.ServerData> m_matchmakingServers = new List<MasterClient.ServerData>();
+
+ private List<MasterClient.ServerData> m_dedicatedServers = new List<MasterClient.ServerData>();
+
+ private List<MasterClient.ServerData> m_dedicatedServersTemp = new List<MasterClient.ServerData>();
+
+ private List<MasterClient.ServerData> m_friendServers = new List<MasterClient.ServerData>();
+
+ private int m_serverListRevision;
+
+ private CallResult<LobbyCreated_t> m_lobbyCreated;
+
+ private CallResult<LobbyMatchList_t> m_lobbyMatchList;
+
+ private CallResult<LobbyEnter_t> m_lobbyEntered;
+
+ private Callback<GameServerChangeRequested_t> m_changeServer;
+
+ private Callback<GameLobbyJoinRequested_t> m_joinRequest;
+
+ private Callback<LobbyDataUpdate_t> m_lobbyDataUpdate;
+
+ private Callback<GetAuthSessionTicketResponse_t> m_authSessionTicketResponse;
+
+ private Callback<SteamServerConnectFailure_t> m_steamServerConnectFailure;
+
+ private Callback<SteamServersConnected_t> m_steamServersConnected;
+
+ private Callback<SteamServersDisconnected_t> m_steamServersDisconnected;
+
+ private CSteamID m_myLobby = CSteamID.Nil;
+
+ private CSteamID m_joinUserID = CSteamID.Nil;
+
+ private CSteamID m_queuedJoinLobby = CSteamID.Nil;
+
+ private List<KeyValuePair<CSteamID, string>> m_requestedFriendGames = new List<KeyValuePair<CSteamID, string>>();
+
+ private ISteamMatchmakingServerListResponse m_steamServerCallbackHandler;
+
+ private ISteamMatchmakingPingResponse m_joinServerCallbackHandler;
+
+ private HServerQuery m_joinQuery;
+
+ private HServerListRequest m_serverListRequest;
+
+ private bool m_haveListRequest;
+
+ private bool m_refreshingList;
+
+ private string m_registerServerName = "";
+
+ private bool m_registerPassword;
+
+ private string m_registerVerson = "";
+
+ private string m_nameFilter = "";
+
+ private bool m_friendsFilter = true;
+
+ private HAuthTicket m_authTicket = HAuthTicket.Invalid;
+
+ public static ZSteamMatchmaking instance => m_instance;
+
+ public static void Initialize()
+ {
+ if (m_instance == null)
+ {
+ m_instance = new ZSteamMatchmaking();
+ }
+ }
+
+ private ZSteamMatchmaking()
+ {
+ m_steamServerCallbackHandler = new ISteamMatchmakingServerListResponse(OnServerResponded, OnServerFailedToRespond, OnRefreshComplete);
+ m_joinServerCallbackHandler = new ISteamMatchmakingPingResponse(OnJoinServerRespond, OnJoinServerFailed);
+ m_lobbyCreated = CallResult<LobbyCreated_t>.Create(OnLobbyCreated);
+ m_lobbyMatchList = CallResult<LobbyMatchList_t>.Create(OnLobbyMatchList);
+ m_changeServer = Callback<GameServerChangeRequested_t>.Create(OnChangeServerRequest);
+ m_joinRequest = Callback<GameLobbyJoinRequested_t>.Create(OnJoinRequest);
+ m_lobbyDataUpdate = Callback<LobbyDataUpdate_t>.Create(OnLobbyDataUpdate);
+ m_authSessionTicketResponse = Callback<GetAuthSessionTicketResponse_t>.Create(OnAuthSessionTicketResponse);
+ }
+
+ public byte[] RequestSessionTicket()
+ {
+ ReleaseSessionTicket();
+ byte[] array = new byte[1024];
+ uint pcbTicket = 0u;
+ m_authTicket = SteamUser.GetAuthSessionTicket(array, 1024, out pcbTicket);
+ if (m_authTicket == HAuthTicket.Invalid)
+ {
+ return null;
+ }
+ byte[] array2 = new byte[pcbTicket];
+ Buffer.BlockCopy(array, 0, array2, 0, (int)pcbTicket);
+ return array2;
+ }
+
+ public void ReleaseSessionTicket()
+ {
+ if (!(m_authTicket == HAuthTicket.Invalid))
+ {
+ SteamUser.CancelAuthTicket(m_authTicket);
+ m_authTicket = HAuthTicket.Invalid;
+ ZLog.Log("Released session ticket");
+ }
+ }
+
+ public bool VerifySessionTicket(byte[] ticket, CSteamID steamID)
+ {
+ return SteamUser.BeginAuthSession(ticket, ticket.Length, steamID) == EBeginAuthSessionResult.k_EBeginAuthSessionResultOK;
+ }
+
+ private void OnAuthSessionTicketResponse(GetAuthSessionTicketResponse_t data)
+ {
+ ZLog.Log("Session auth respons callback");
+ }
+
+ private void OnSteamServersConnected(SteamServersConnected_t data)
+ {
+ ZLog.Log("Game server connected");
+ }
+
+ private void OnSteamServersDisconnected(SteamServersDisconnected_t data)
+ {
+ ZLog.LogWarning("Game server disconnected");
+ }
+
+ private void OnSteamServersConnectFail(SteamServerConnectFailure_t data)
+ {
+ ZLog.LogWarning("Game server connected failed");
+ }
+
+ private void OnChangeServerRequest(GameServerChangeRequested_t data)
+ {
+ ZLog.Log("ZSteamMatchmaking got change server request to:" + data.m_rgchServer);
+ QueueServerJoin(data.m_rgchServer);
+ }
+
+ private void OnJoinRequest(GameLobbyJoinRequested_t data)
+ {
+ ZLog.Log(string.Concat("ZSteamMatchmaking got join request friend:", data.m_steamIDFriend, " lobby:", data.m_steamIDLobby));
+ if (!Game.instance)
+ {
+ QueueLobbyJoin(data.m_steamIDLobby);
+ }
+ }
+
+ public void QueueServerJoin(string addr)
+ {
+ string[] array = addr.Split(':');
+ if (array.Length >= 2 && array[0].Split('.').Length == 4)
+ {
+ int num = BitConverter.ToInt32(IPAddress.Parse(array[0]).GetAddressBytes(), 0);
+ uint num2 = (uint)IPAddress.HostToNetworkOrder(num);
+ int num3 = int.Parse(array[1]) + 1;
+ ZLog.Log("request " + array[0] + " " + array[1] + " ip:" + num + " nboip:" + num2 + " port:" + num3);
+ m_joinQuery = SteamMatchmakingServers.PingServer(num2, (ushort)num3, m_joinServerCallbackHandler);
+ }
+ }
+
+ private void OnJoinServerRespond(gameserveritem_t serverData)
+ {
+ ZLog.Log("Got join server data " + serverData.GetServerName() + " " + serverData.m_steamID);
+ m_joinUserID = serverData.m_steamID;
+ }
+
+ private void OnJoinServerFailed()
+ {
+ ZLog.Log("Failed to get join server data");
+ }
+
+ public void QueueLobbyJoin(CSteamID lobbyID)
+ {
+ if (SteamMatchmaking.GetLobbyGameServer(lobbyID, out var _, out var _, out var psteamIDGameServer))
+ {
+ ZLog.Log(" hostid: " + psteamIDGameServer);
+ m_joinUserID = psteamIDGameServer;
+ m_queuedJoinLobby = CSteamID.Nil;
+ }
+ else
+ {
+ ZLog.Log(string.Concat("Failed to get lobby data for lobby ", lobbyID, ", requesting lobby data"));
+ m_queuedJoinLobby = lobbyID;
+ SteamMatchmaking.RequestLobbyData(lobbyID);
+ }
+ }
+
+ private void OnLobbyDataUpdate(LobbyDataUpdate_t data)
+ {
+ CSteamID cSteamID = new CSteamID(data.m_ulSteamIDLobby);
+ if (cSteamID == m_queuedJoinLobby)
+ {
+ ZLog.Log("Got lobby data, for queued lobby");
+ if (SteamMatchmaking.GetLobbyGameServer(cSteamID, out var _, out var _, out var psteamIDGameServer))
+ {
+ m_joinUserID = psteamIDGameServer;
+ }
+ m_queuedJoinLobby = CSteamID.Nil;
+ return;
+ }
+ ZLog.Log("Got requested lobby data");
+ foreach (KeyValuePair<CSteamID, string> requestedFriendGame in m_requestedFriendGames)
+ {
+ if (requestedFriendGame.Key == cSteamID)
+ {
+ MasterClient.ServerData lobbyServerData = GetLobbyServerData(cSteamID);
+ if (lobbyServerData != null)
+ {
+ lobbyServerData.m_name = requestedFriendGame.Value + " [" + lobbyServerData.m_name + "]";
+ m_friendServers.Add(lobbyServerData);
+ m_serverListRevision++;
+ }
+ }
+ }
+ }
+
+ public void RegisterServer(string name, bool password, string version, bool publicServer, string worldName)
+ {
+ UnregisterServer();
+ SteamAPICall_t hAPICall = SteamMatchmaking.CreateLobby((!publicServer) ? ELobbyType.k_ELobbyTypeFriendsOnly : ELobbyType.k_ELobbyTypePublic, 32);
+ m_lobbyCreated.Set(hAPICall);
+ m_registerServerName = name;
+ m_registerPassword = password;
+ m_registerVerson = version;
+ ZLog.Log("Registering lobby");
+ }
+
+ private void OnLobbyCreated(LobbyCreated_t data, bool ioError)
+ {
+ ZLog.Log(string.Concat("Lobby was created ", data.m_eResult, " ", data.m_ulSteamIDLobby, " error:", ioError.ToString()));
+ if (!ioError)
+ {
+ m_myLobby = new CSteamID(data.m_ulSteamIDLobby);
+ SteamMatchmaking.SetLobbyData(m_myLobby, "name", m_registerServerName);
+ SteamMatchmaking.SetLobbyData(m_myLobby, "password", m_registerPassword ? "1" : "0");
+ SteamMatchmaking.SetLobbyData(m_myLobby, "version", m_registerVerson);
+ SteamMatchmaking.SetLobbyGameServer(m_myLobby, 0u, 0, SteamUser.GetSteamID());
+ }
+ }
+
+ private void OnLobbyEnter(LobbyEnter_t data, bool ioError)
+ {
+ ZLog.LogWarning("Entering lobby " + data.m_ulSteamIDLobby);
+ }
+
+ public void UnregisterServer()
+ {
+ if (m_myLobby != CSteamID.Nil)
+ {
+ SteamMatchmaking.SetLobbyJoinable(m_myLobby, bLobbyJoinable: false);
+ SteamMatchmaking.LeaveLobby(m_myLobby);
+ m_myLobby = CSteamID.Nil;
+ }
+ }
+
+ public void RequestServerlist()
+ {
+ if (m_friendsFilter)
+ {
+ RequestFriendGames();
+ return;
+ }
+ RequestPublicLobbies();
+ RequestDedicatedServers();
+ }
+
+ private void RequestFriendGames()
+ {
+ m_friendServers.Clear();
+ m_requestedFriendGames.Clear();
+ int num = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagImmediate);
+ if (num == -1)
+ {
+ ZLog.Log("GetFriendCount returned -1, the current user is not logged in.");
+ num = 0;
+ }
+ for (int i = 0; i < num; i++)
+ {
+ CSteamID friendByIndex = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagImmediate);
+ string friendPersonaName = SteamFriends.GetFriendPersonaName(friendByIndex);
+ if (SteamFriends.GetFriendGamePlayed(friendByIndex, out var pFriendGameInfo) && pFriendGameInfo.m_gameID == (CGameID)SteamManager.APP_ID && pFriendGameInfo.m_steamIDLobby != CSteamID.Nil)
+ {
+ ZLog.Log("Friend is in our game");
+ m_requestedFriendGames.Add(new KeyValuePair<CSteamID, string>(pFriendGameInfo.m_steamIDLobby, friendPersonaName));
+ SteamMatchmaking.RequestLobbyData(pFriendGameInfo.m_steamIDLobby);
+ }
+ }
+ m_serverListRevision++;
+ }
+
+ private void RequestPublicLobbies()
+ {
+ SteamAPICall_t hAPICall = SteamMatchmaking.RequestLobbyList();
+ m_lobbyMatchList.Set(hAPICall);
+ }
+
+ private void RequestDedicatedServers()
+ {
+ if (!m_refreshingList)
+ {
+ if (m_haveListRequest)
+ {
+ SteamMatchmakingServers.ReleaseRequest(m_serverListRequest);
+ m_haveListRequest = false;
+ }
+ m_dedicatedServersTemp.Clear();
+ m_serverListRequest = SteamMatchmakingServers.RequestInternetServerList(SteamUtils.GetAppID(), new MatchMakingKeyValuePair_t[0], 0u, m_steamServerCallbackHandler);
+ m_refreshingList = true;
+ m_haveListRequest = true;
+ }
+ }
+
+ private void OnLobbyMatchList(LobbyMatchList_t data, bool ioError)
+ {
+ m_matchmakingServers.Clear();
+ for (int i = 0; i < data.m_nLobbiesMatching; i++)
+ {
+ CSteamID lobbyByIndex = SteamMatchmaking.GetLobbyByIndex(i);
+ MasterClient.ServerData lobbyServerData = GetLobbyServerData(lobbyByIndex);
+ if (lobbyServerData != null)
+ {
+ m_matchmakingServers.Add(lobbyServerData);
+ }
+ }
+ m_serverListRevision++;
+ }
+
+ private MasterClient.ServerData GetLobbyServerData(CSteamID lobbyID)
+ {
+ string lobbyData = SteamMatchmaking.GetLobbyData(lobbyID, "name");
+ bool password = SteamMatchmaking.GetLobbyData(lobbyID, "password") == "1";
+ string lobbyData2 = SteamMatchmaking.GetLobbyData(lobbyID, "version");
+ int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(lobbyID);
+ if (m_nameFilter.Length > 0 && !lobbyData.Contains(m_nameFilter))
+ {
+ return null;
+ }
+ if (SteamMatchmaking.GetLobbyGameServer(lobbyID, out var _, out var _, out var psteamIDGameServer))
+ {
+ MasterClient.ServerData serverData = new MasterClient.ServerData();
+ serverData.m_name = lobbyData;
+ serverData.m_password = password;
+ serverData.m_version = lobbyData2;
+ serverData.m_players = numLobbyMembers;
+ serverData.m_steamHostID = (ulong)psteamIDGameServer;
+ ZLog.Log("Got server " + lobbyData + " host:" + serverData.m_steamHostID);
+ return serverData;
+ }
+ ZLog.Log("Failed to get lobby gameserver");
+ return null;
+ }
+
+ public void GetServers(List<MasterClient.ServerData> allServers)
+ {
+ if (m_friendsFilter)
+ {
+ allServers.AddRange(m_friendServers);
+ return;
+ }
+ allServers.AddRange(m_matchmakingServers);
+ allServers.AddRange(m_dedicatedServers);
+ }
+
+ public CSteamID GetJoinUserID()
+ {
+ CSteamID joinUserID = m_joinUserID;
+ m_joinUserID = CSteamID.Nil;
+ return joinUserID;
+ }
+
+ private void OnServerResponded(HServerListRequest request, int iServer)
+ {
+ gameserveritem_t serverDetails = SteamMatchmakingServers.GetServerDetails(request, iServer);
+ string serverName = serverDetails.GetServerName();
+ if (m_nameFilter.Length <= 0 || serverName.Contains(m_nameFilter))
+ {
+ MasterClient.ServerData serverData = new MasterClient.ServerData();
+ serverData.m_name = serverName;
+ serverData.m_steamHostID = (ulong)serverDetails.m_steamID;
+ serverData.m_password = serverDetails.m_bPassword;
+ serverData.m_players = serverDetails.m_nPlayers;
+ serverData.m_version = serverDetails.GetGameTags();
+ m_dedicatedServersTemp.Add(serverData);
+ }
+ }
+
+ private void OnServerFailedToRespond(HServerListRequest request, int iServer)
+ {
+ ZLog.Log("Server failed to respond");
+ }
+
+ private void OnRefreshComplete(HServerListRequest request, EMatchMakingServerResponse response)
+ {
+ ZLog.Log("Refresh complete " + m_dedicatedServersTemp.Count + " " + response);
+ m_dedicatedServers.Clear();
+ m_dedicatedServers.AddRange(m_dedicatedServersTemp);
+ m_dedicatedServersTemp.Clear();
+ m_refreshingList = false;
+ m_serverListRevision++;
+ }
+
+ public void SetNameFilter(string filter)
+ {
+ m_nameFilter = filter;
+ }
+
+ public void SetFriendFilter(bool enabled)
+ {
+ m_friendsFilter = enabled;
+ }
+
+ public int GetServerListRevision()
+ {
+ return m_serverListRevision;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamSocket.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamSocket.cs
new file mode 100644
index 0000000..30a271d
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSteamSocket.cs
@@ -0,0 +1,340 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Steamworks;
+
+public class ZSteamSocket : IDisposable, ISocket
+{
+ private static List<ZSteamSocket> m_sockets = new List<ZSteamSocket>();
+
+ private static Callback<P2PSessionRequest_t> m_SessionRequest;
+
+ private static Callback<P2PSessionConnectFail_t> m_connectionFailed;
+
+ private Queue<ZSteamSocket> m_pendingConnections = new Queue<ZSteamSocket>();
+
+ private CSteamID m_peerID = CSteamID.Nil;
+
+ private bool m_listner;
+
+ private Queue<ZPackage> m_pkgQueue = new Queue<ZPackage>();
+
+ private Queue<byte[]> m_sendQueue = new Queue<byte[]>();
+
+ private int m_totalSent;
+
+ private int m_totalRecv;
+
+ private bool m_gotData;
+
+ public ZSteamSocket()
+ {
+ m_sockets.Add(this);
+ RegisterGlobalCallbacks();
+ }
+
+ public ZSteamSocket(CSteamID peerID)
+ {
+ m_sockets.Add(this);
+ m_peerID = peerID;
+ RegisterGlobalCallbacks();
+ }
+
+ private static void RegisterGlobalCallbacks()
+ {
+ if (m_connectionFailed == null)
+ {
+ ZLog.Log("ZSteamSocket Registering global callbacks");
+ m_connectionFailed = Callback<P2PSessionConnectFail_t>.Create(OnConnectionFailed);
+ }
+ if (m_SessionRequest == null)
+ {
+ m_SessionRequest = Callback<P2PSessionRequest_t>.Create(OnSessionRequest);
+ }
+ }
+
+ private static void UnregisterGlobalCallbacks()
+ {
+ ZLog.Log("ZSteamSocket UnregisterGlobalCallbacks, existing sockets:" + m_sockets.Count);
+ if (m_connectionFailed != null)
+ {
+ m_connectionFailed.Dispose();
+ m_connectionFailed = null;
+ }
+ if (m_SessionRequest != null)
+ {
+ m_SessionRequest.Dispose();
+ m_SessionRequest = null;
+ }
+ }
+
+ private static void OnConnectionFailed(P2PSessionConnectFail_t data)
+ {
+ ZLog.Log("Got connection failed callback: " + data.m_steamIDRemote);
+ foreach (ZSteamSocket socket in m_sockets)
+ {
+ if (socket.IsPeer(data.m_steamIDRemote))
+ {
+ socket.Close();
+ }
+ }
+ }
+
+ private static void OnSessionRequest(P2PSessionRequest_t data)
+ {
+ ZLog.Log("Got session request from " + data.m_steamIDRemote);
+ if (SteamNetworking.AcceptP2PSessionWithUser(data.m_steamIDRemote))
+ {
+ GetListner()?.QueuePendingConnection(data.m_steamIDRemote);
+ }
+ }
+
+ public void Dispose()
+ {
+ ZLog.Log("Disposing socket");
+ Close();
+ m_pkgQueue.Clear();
+ m_sockets.Remove(this);
+ if (m_sockets.Count == 0)
+ {
+ ZLog.Log("Last socket, unregistering callback");
+ UnregisterGlobalCallbacks();
+ }
+ }
+
+ public void Close()
+ {
+ ZLog.Log("Closing socket " + GetEndPointString());
+ if (m_peerID != CSteamID.Nil)
+ {
+ Flush();
+ ZLog.Log(" send queue size:" + m_sendQueue.Count);
+ Thread.Sleep(100);
+ SteamNetworking.GetP2PSessionState(m_peerID, out var pConnectionState);
+ ZLog.Log(" P2P state, bytes in send queue:" + pConnectionState.m_nBytesQueuedForSend);
+ SteamNetworking.CloseP2PSessionWithUser(m_peerID);
+ SteamUser.EndAuthSession(m_peerID);
+ m_peerID = CSteamID.Nil;
+ }
+ m_listner = false;
+ }
+
+ public bool StartHost()
+ {
+ m_listner = true;
+ m_pendingConnections.Clear();
+ return true;
+ }
+
+ private ZSteamSocket QueuePendingConnection(CSteamID id)
+ {
+ foreach (ZSteamSocket pendingConnection in m_pendingConnections)
+ {
+ if (pendingConnection.IsPeer(id))
+ {
+ return pendingConnection;
+ }
+ }
+ ZSteamSocket zSteamSocket = new ZSteamSocket(id);
+ m_pendingConnections.Enqueue(zSteamSocket);
+ return zSteamSocket;
+ }
+
+ public ISocket Accept()
+ {
+ if (!m_listner)
+ {
+ return null;
+ }
+ if (m_pendingConnections.Count > 0)
+ {
+ return m_pendingConnections.Dequeue();
+ }
+ return null;
+ }
+
+ public bool IsConnected()
+ {
+ return m_peerID != CSteamID.Nil;
+ }
+
+ public void Send(ZPackage pkg)
+ {
+ if (pkg.Size() != 0 && IsConnected())
+ {
+ byte[] array = pkg.GetArray();
+ byte[] bytes = BitConverter.GetBytes(array.Length);
+ byte[] array2 = new byte[array.Length + bytes.Length];
+ bytes.CopyTo(array2, 0);
+ array.CopyTo(array2, 4);
+ m_sendQueue.Enqueue(array);
+ SendQueuedPackages();
+ }
+ }
+
+ public bool Flush()
+ {
+ SendQueuedPackages();
+ return m_sendQueue.Count == 0;
+ }
+
+ private void SendQueuedPackages()
+ {
+ if (!IsConnected())
+ {
+ return;
+ }
+ while (m_sendQueue.Count > 0)
+ {
+ byte[] array = m_sendQueue.Peek();
+ if (SteamNetworking.SendP2PPacket(m_peerID, array, (uint)array.Length, EP2PSend.k_EP2PSendReliable))
+ {
+ m_totalSent += array.Length;
+ m_sendQueue.Dequeue();
+ continue;
+ }
+ break;
+ }
+ }
+
+ public static void Update()
+ {
+ foreach (ZSteamSocket socket in m_sockets)
+ {
+ socket.SendQueuedPackages();
+ }
+ ReceivePackages();
+ }
+
+ private static void ReceivePackages()
+ {
+ uint pcubMsgSize;
+ while (SteamNetworking.IsP2PPacketAvailable(out pcubMsgSize))
+ {
+ byte[] array = new byte[pcubMsgSize];
+ if (SteamNetworking.ReadP2PPacket(array, pcubMsgSize, out var _, out var psteamIDRemote))
+ {
+ QueueNewPkg(psteamIDRemote, array);
+ continue;
+ }
+ break;
+ }
+ }
+
+ private static void QueueNewPkg(CSteamID sender, byte[] data)
+ {
+ foreach (ZSteamSocket socket in m_sockets)
+ {
+ if (socket.IsPeer(sender))
+ {
+ socket.QueuePackage(data);
+ return;
+ }
+ }
+ ZSteamSocket listner = GetListner();
+ if (listner != null)
+ {
+ ZLog.Log("Got package from unconnected peer " + sender);
+ listner.QueuePendingConnection(sender).QueuePackage(data);
+ }
+ else
+ {
+ ZLog.Log(string.Concat("Got package from unkown peer ", sender, " but no active listner"));
+ }
+ }
+
+ private static ZSteamSocket GetListner()
+ {
+ foreach (ZSteamSocket socket in m_sockets)
+ {
+ if (socket.IsHost())
+ {
+ return socket;
+ }
+ }
+ return null;
+ }
+
+ private void QueuePackage(byte[] data)
+ {
+ ZPackage item = new ZPackage(data);
+ m_pkgQueue.Enqueue(item);
+ m_gotData = true;
+ m_totalRecv += data.Length;
+ }
+
+ public ZPackage Recv()
+ {
+ if (!IsConnected())
+ {
+ return null;
+ }
+ if (m_pkgQueue.Count > 0)
+ {
+ return m_pkgQueue.Dequeue();
+ }
+ return null;
+ }
+
+ public string GetEndPointString()
+ {
+ return m_peerID.ToString();
+ }
+
+ public string GetHostName()
+ {
+ return m_peerID.ToString();
+ }
+
+ public CSteamID GetPeerID()
+ {
+ return m_peerID;
+ }
+
+ public bool IsPeer(CSteamID peer)
+ {
+ if (!IsConnected())
+ {
+ return false;
+ }
+ return peer == m_peerID;
+ }
+
+ public bool IsHost()
+ {
+ return m_listner;
+ }
+
+ public bool IsSending()
+ {
+ if (!IsConnected())
+ {
+ return false;
+ }
+ return m_sendQueue.Count > 0;
+ }
+
+ public void GetAndResetStats(out int totalSent, out int totalRecv)
+ {
+ totalSent = m_totalSent;
+ totalRecv = m_totalRecv;
+ m_totalSent = 0;
+ m_totalRecv = 0;
+ }
+
+ public bool GotNewData()
+ {
+ bool gotData = m_gotData;
+ m_gotData = false;
+ return gotData;
+ }
+
+ public int GetHostPort()
+ {
+ if (IsHost())
+ {
+ return 1;
+ }
+ return -1;
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncAnimation.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncAnimation.cs
new file mode 100644
index 0000000..eb6d5a1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncAnimation.cs
@@ -0,0 +1,217 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ZSyncAnimation : MonoBehaviour
+{
+ private ZNetView m_nview;
+
+ private Animator m_animator;
+
+ public List<string> m_syncBools = new List<string>();
+
+ public List<string> m_syncFloats = new List<string>();
+
+ public List<string> m_syncInts = new List<string>();
+
+ public bool m_smoothCharacterSpeeds = true;
+
+ private static int m_forwardSpeedID;
+
+ private static int m_sidewaySpeedID;
+
+ private static int m_animSpeedID;
+
+ private int[] m_boolHashes;
+
+ private bool[] m_boolDefaults;
+
+ private int[] m_floatHashes;
+
+ private float[] m_floatDefaults;
+
+ private int[] m_intHashes;
+
+ private int[] m_intDefaults;
+
+ private const int m_zdoSalt = 438569;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_animator = GetComponentInChildren<Animator>();
+ m_animator.logWarnings = false;
+ m_nview.Register<string>("SetTrigger", RPC_SetTrigger);
+ m_boolHashes = new int[m_syncBools.Count];
+ m_boolDefaults = new bool[m_syncBools.Count];
+ for (int i = 0; i < m_syncBools.Count; i++)
+ {
+ m_boolHashes[i] = GetHash(m_syncBools[i]);
+ m_boolDefaults[i] = m_animator.GetBool(m_boolHashes[i]);
+ }
+ m_floatHashes = new int[m_syncFloats.Count];
+ m_floatDefaults = new float[m_syncFloats.Count];
+ for (int j = 0; j < m_syncFloats.Count; j++)
+ {
+ m_floatHashes[j] = GetHash(m_syncFloats[j]);
+ m_floatDefaults[j] = m_animator.GetFloat(m_floatHashes[j]);
+ }
+ m_intHashes = new int[m_syncInts.Count];
+ m_intDefaults = new int[m_syncInts.Count];
+ for (int k = 0; k < m_syncInts.Count; k++)
+ {
+ m_intHashes[k] = GetHash(m_syncInts[k]);
+ m_intDefaults[k] = m_animator.GetInteger(m_intHashes[k]);
+ }
+ if (m_forwardSpeedID == 0)
+ {
+ m_forwardSpeedID = GetHash("forward_speed");
+ m_sidewaySpeedID = GetHash("sideway_speed");
+ m_animSpeedID = GetHash("anim_speed");
+ }
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ }
+ else
+ {
+ SyncParameters();
+ }
+ }
+
+ public static int GetHash(string name)
+ {
+ return Animator.StringToHash(name);
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ SyncParameters();
+ }
+ }
+
+ private void SyncParameters()
+ {
+ ZDO zDO = m_nview.GetZDO();
+ if (!m_nview.IsOwner())
+ {
+ for (int i = 0; i < m_boolHashes.Length; i++)
+ {
+ int num = m_boolHashes[i];
+ bool @bool = zDO.GetBool(438569 + num, m_boolDefaults[i]);
+ m_animator.SetBool(num, @bool);
+ }
+ for (int j = 0; j < m_floatHashes.Length; j++)
+ {
+ int num2 = m_floatHashes[j];
+ float @float = zDO.GetFloat(438569 + num2, m_floatDefaults[j]);
+ if (m_smoothCharacterSpeeds && (num2 == m_forwardSpeedID || num2 == m_sidewaySpeedID))
+ {
+ m_animator.SetFloat(num2, @float, 0.2f, Time.fixedDeltaTime);
+ }
+ else
+ {
+ m_animator.SetFloat(num2, @float);
+ }
+ }
+ for (int k = 0; k < m_intHashes.Length; k++)
+ {
+ int num3 = m_intHashes[k];
+ int @int = zDO.GetInt(438569 + num3, m_intDefaults[k]);
+ m_animator.SetInteger(num3, @int);
+ }
+ float float2 = zDO.GetFloat(m_animSpeedID, 1f);
+ m_animator.speed = float2;
+ }
+ else
+ {
+ zDO.Set(m_animSpeedID, m_animator.speed);
+ }
+ }
+
+ public void SetTrigger(string name)
+ {
+ m_nview.InvokeRPC(ZNetView.Everybody, "SetTrigger", name);
+ }
+
+ public void SetBool(string name, bool value)
+ {
+ int hash = GetHash(name);
+ SetBool(hash, value);
+ }
+
+ public void SetBool(int hash, bool value)
+ {
+ if (m_animator.GetBool(hash) != value)
+ {
+ m_animator.SetBool(hash, value);
+ if (m_nview.GetZDO() != null && m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set(438569 + hash, value);
+ }
+ }
+ }
+
+ public void SetFloat(string name, float value)
+ {
+ int hash = GetHash(name);
+ SetFloat(hash, value);
+ }
+
+ public void SetFloat(int hash, float value)
+ {
+ if (!(Mathf.Abs(m_animator.GetFloat(hash) - value) < 0.01f))
+ {
+ if (m_smoothCharacterSpeeds && (hash == m_forwardSpeedID || hash == m_sidewaySpeedID))
+ {
+ m_animator.SetFloat(hash, value, 0.2f, Time.fixedDeltaTime);
+ }
+ else
+ {
+ m_animator.SetFloat(hash, value);
+ }
+ if (m_nview.GetZDO() != null && m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set(438569 + hash, value);
+ }
+ }
+ }
+
+ public void SetInt(string name, int value)
+ {
+ int hash = GetHash(name);
+ SetInt(hash, value);
+ }
+
+ public void SetInt(int hash, int value)
+ {
+ if (m_animator.GetInteger(hash) != value)
+ {
+ m_animator.SetInteger(hash, value);
+ if (m_nview.GetZDO() != null && m_nview.IsOwner())
+ {
+ m_nview.GetZDO().Set(438569 + hash, value);
+ }
+ }
+ }
+
+ private void RPC_SetTrigger(long sender, string name)
+ {
+ m_animator.SetTrigger(name);
+ }
+
+ public void SetSpeed(float speed)
+ {
+ m_animator.speed = speed;
+ }
+
+ public bool IsOwner()
+ {
+ if (!m_nview.IsValid())
+ {
+ return false;
+ }
+ return m_nview.IsOwner();
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncTransform.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncTransform.cs
new file mode 100644
index 0000000..01431f0
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZSyncTransform.cs
@@ -0,0 +1,327 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ZSyncTransform : MonoBehaviour
+{
+ public bool m_syncPosition = true;
+
+ public bool m_syncRotation = true;
+
+ public bool m_syncScale;
+
+ public bool m_syncBodyVelocity;
+
+ public bool m_characterParentSync;
+
+ private const float m_smoothness = 0.2f;
+
+ private bool m_isKinematicBody;
+
+ private bool m_useGravity = true;
+
+ private Vector3 m_tempRelPos;
+
+ private bool m_haveTempRelPos;
+
+ private float m_targetPosTimer;
+
+ private uint m_posRevision;
+
+ private int m_lastUpdateFrame = -1;
+
+ private static int m_velHash = "vel".GetStableHashCode();
+
+ private static int m_scaleHash = "scale".GetStableHashCode();
+
+ private static int m_bodyVel = "body_vel".GetStableHashCode();
+
+ private static int m_bodyAVel = "body_avel".GetStableHashCode();
+
+ private static int m_relPos = "relPos".GetStableHashCode();
+
+ private static KeyValuePair<int, int> m_parentIDHash = ZDO.GetHashZDOID("parentID");
+
+ private ZNetView m_nview;
+
+ private Rigidbody m_body;
+
+ private Projectile m_projectile;
+
+ private Character m_character;
+
+ private void Awake()
+ {
+ m_nview = GetComponent<ZNetView>();
+ m_body = GetComponent<Rigidbody>();
+ m_projectile = GetComponent<Projectile>();
+ m_character = GetComponent<Character>();
+ if (m_nview.GetZDO() == null)
+ {
+ base.enabled = false;
+ }
+ else if ((bool)m_body)
+ {
+ m_isKinematicBody = m_body.isKinematic;
+ m_useGravity = m_body.useGravity;
+ }
+ }
+
+ private Vector3 GetVelocity()
+ {
+ if (m_body != null)
+ {
+ return m_body.velocity;
+ }
+ if (m_projectile != null)
+ {
+ return m_projectile.GetVelocity();
+ }
+ return Vector3.zero;
+ }
+
+ private Vector3 GetPosition()
+ {
+ if (!m_body)
+ {
+ return base.transform.position;
+ }
+ return m_body.position;
+ }
+
+ private void OwnerSync()
+ {
+ ZDO zDO = m_nview.GetZDO();
+ if (!zDO.IsOwner())
+ {
+ return;
+ }
+ if (base.transform.position.y < -5000f)
+ {
+ if ((bool)m_body)
+ {
+ m_body.velocity = Vector3.zero;
+ }
+ ZLog.Log("Object fell out of world:" + base.gameObject.name);
+ float groundHeight = ZoneSystem.instance.GetGroundHeight(base.transform.position);
+ Vector3 position = base.transform.position;
+ position.y = groundHeight + 1f;
+ base.transform.position = position;
+ return;
+ }
+ if (m_syncPosition)
+ {
+ zDO.SetPosition(GetPosition());
+ zDO.Set(m_velHash, GetVelocity());
+ if (m_characterParentSync)
+ {
+ if (m_character.GetRelativePosition(out var parent, out var relativePos, out var relativeVel))
+ {
+ zDO.Set(m_parentIDHash, parent);
+ zDO.Set(m_relPos, relativePos);
+ zDO.Set(m_velHash, relativeVel);
+ }
+ else
+ {
+ zDO.Set(m_parentIDHash, ZDOID.None);
+ }
+ }
+ }
+ if (m_syncRotation && base.transform.hasChanged)
+ {
+ Quaternion rotation = (m_body ? m_body.rotation : base.transform.rotation);
+ zDO.SetRotation(rotation);
+ }
+ if (m_syncScale && base.transform.hasChanged)
+ {
+ zDO.Set(m_scaleHash, base.transform.localScale);
+ }
+ if ((bool)m_body)
+ {
+ if (m_syncBodyVelocity)
+ {
+ m_nview.GetZDO().Set(m_bodyVel, m_body.velocity);
+ m_nview.GetZDO().Set(m_bodyAVel, m_body.angularVelocity);
+ }
+ m_body.useGravity = m_useGravity;
+ }
+ base.transform.hasChanged = false;
+ }
+
+ private void SyncPosition(ZDO zdo, float dt)
+ {
+ if (m_characterParentSync && zdo.HasOwner())
+ {
+ ZDOID zDOID = zdo.GetZDOID(m_parentIDHash);
+ if (!zDOID.IsNone())
+ {
+ GameObject gameObject = ZNetScene.instance.FindInstance(zDOID);
+ if ((bool)gameObject)
+ {
+ ZSyncTransform component = gameObject.GetComponent<ZSyncTransform>();
+ if ((bool)component)
+ {
+ component.ClientSync(dt);
+ }
+ Vector3 vector = zdo.GetVec3(m_relPos, Vector3.zero);
+ Vector3 vec = zdo.GetVec3(m_velHash, Vector3.zero);
+ if (zdo.m_dataRevision != m_posRevision)
+ {
+ m_posRevision = zdo.m_dataRevision;
+ m_targetPosTimer = 0f;
+ }
+ m_targetPosTimer += dt;
+ m_targetPosTimer = Mathf.Min(m_targetPosTimer, 2f);
+ vector += vec * m_targetPosTimer;
+ if (!m_haveTempRelPos)
+ {
+ m_haveTempRelPos = true;
+ m_tempRelPos = vector;
+ }
+ if (Vector3.Distance(m_tempRelPos, vector) > 0.001f)
+ {
+ m_tempRelPos = Vector3.Lerp(m_tempRelPos, vector, 0.2f);
+ vector = m_tempRelPos;
+ }
+ Vector3 vector2 = gameObject.transform.TransformPoint(vector);
+ if (Vector3.Distance(base.transform.position, vector2) > 0.001f)
+ {
+ base.transform.position = vector2;
+ }
+ return;
+ }
+ }
+ }
+ m_haveTempRelPos = false;
+ Vector3 position = zdo.GetPosition();
+ if (zdo.m_dataRevision != m_posRevision)
+ {
+ m_posRevision = zdo.m_dataRevision;
+ m_targetPosTimer = 0f;
+ }
+ if (zdo.HasOwner())
+ {
+ m_targetPosTimer += dt;
+ m_targetPosTimer = Mathf.Min(m_targetPosTimer, 2f);
+ Vector3 vec2 = zdo.GetVec3(m_velHash, Vector3.zero);
+ position += vec2 * m_targetPosTimer;
+ }
+ if (Vector3.Distance(base.transform.position, position) > 0.001f)
+ {
+ base.transform.position = Vector3.Lerp(base.transform.position, position, 0.2f);
+ }
+ }
+
+ private void ClientSync(float dt)
+ {
+ ZDO zDO = m_nview.GetZDO();
+ if (zDO.IsOwner())
+ {
+ return;
+ }
+ int frameCount = Time.frameCount;
+ if (m_lastUpdateFrame == frameCount)
+ {
+ return;
+ }
+ m_lastUpdateFrame = frameCount;
+ if (m_isKinematicBody)
+ {
+ if (m_syncPosition)
+ {
+ Vector3 vector = zDO.GetPosition();
+ if (Vector3.Distance(m_body.position, vector) > 5f)
+ {
+ m_body.position = vector;
+ }
+ else
+ {
+ if (Vector3.Distance(m_body.position, vector) > 0.01f)
+ {
+ vector = Vector3.Lerp(m_body.position, vector, 0.2f);
+ }
+ m_body.MovePosition(vector);
+ }
+ }
+ if (m_syncRotation)
+ {
+ Quaternion rotation = zDO.GetRotation();
+ if (Quaternion.Angle(m_body.rotation, rotation) > 45f)
+ {
+ m_body.rotation = rotation;
+ }
+ else
+ {
+ m_body.MoveRotation(rotation);
+ }
+ }
+ }
+ else
+ {
+ if (m_syncPosition)
+ {
+ SyncPosition(zDO, dt);
+ }
+ if (m_syncRotation)
+ {
+ Quaternion rotation2 = zDO.GetRotation();
+ if (Quaternion.Angle(base.transform.rotation, rotation2) > 0.001f)
+ {
+ base.transform.rotation = Quaternion.Slerp(base.transform.rotation, rotation2, 0.2f);
+ }
+ }
+ if ((bool)m_body)
+ {
+ m_body.useGravity = false;
+ if (m_syncBodyVelocity && m_nview.HasOwner())
+ {
+ Vector3 vec = zDO.GetVec3(m_bodyVel, Vector3.zero);
+ Vector3 vec2 = zDO.GetVec3(m_bodyAVel, Vector3.zero);
+ if (vec.magnitude > 0.01f || vec2.magnitude > 0.01f)
+ {
+ m_body.velocity = vec;
+ m_body.angularVelocity = vec2;
+ }
+ else
+ {
+ m_body.Sleep();
+ }
+ }
+ else if (!m_body.IsSleeping())
+ {
+ m_body.velocity = Vector3.zero;
+ m_body.angularVelocity = Vector3.zero;
+ m_body.Sleep();
+ }
+ }
+ }
+ if (m_syncScale)
+ {
+ Vector3 vec3 = zDO.GetVec3(m_scaleHash, base.transform.localScale);
+ base.transform.localScale = vec3;
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ ClientSync(Time.fixedDeltaTime);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ if (m_nview.IsValid())
+ {
+ OwnerSync();
+ }
+ }
+
+ public void SyncNow()
+ {
+ if (m_nview.IsValid())
+ {
+ OwnerSync();
+ }
+ }
+}
diff --git a/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZoneSystem.cs b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZoneSystem.cs
new file mode 100644
index 0000000..cc376b1
--- /dev/null
+++ b/Valheim_v0.141.2_r202102/Valheim/assembly_valheim/ZoneSystem.cs
@@ -0,0 +1,1712 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class ZoneSystem : MonoBehaviour
+{
+ private class ZoneData
+ {
+ public GameObject m_root;
+
+ public float m_ttl;
+ }
+
+ private class ClearArea
+ {
+ public Vector3 m_center;
+
+ public float m_radius;
+
+ public ClearArea(Vector3 p, float r)
+ {
+ m_center = p;
+ m_radius = r;
+ }
+ }
+
+ [Serializable]
+ public class ZoneVegetation
+ {
+ public string m_name = "veg";
+
+ public GameObject m_prefab;
+
+ public bool m_enable = true;
+
+ public float m_min;
+
+ public float m_max = 10f;
+
+ public bool m_forcePlacement;
+
+ public float m_scaleMin = 1f;
+
+ public float m_scaleMax = 1f;
+
+ public float m_randTilt;
+
+ public float m_chanceToUseGroundTilt;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ [BitMask(typeof(Heightmap.BiomeArea))]
+ public Heightmap.BiomeArea m_biomeArea = Heightmap.BiomeArea.Everything;
+
+ public bool m_blockCheck = true;
+
+ public float m_minAltitude = -1000f;
+
+ public float m_maxAltitude = 1000f;
+
+ public float m_minOceanDepth;
+
+ public float m_maxOceanDepth;
+
+ public float m_minTilt;
+
+ public float m_maxTilt = 90f;
+
+ public float m_terrainDeltaRadius;
+
+ public float m_maxTerrainDelta = 2f;
+
+ public float m_minTerrainDelta;
+
+ public bool m_snapToWater;
+
+ public float m_groundOffset;
+
+ public int m_groupSizeMin = 1;
+
+ public int m_groupSizeMax = 1;
+
+ public float m_groupRadius;
+
+ [Header("Forest fractal 0-1 inside forest")]
+ public bool m_inForest;
+
+ public float m_forestTresholdMin;
+
+ public float m_forestTresholdMax = 1f;
+
+ [HideInInspector]
+ public bool m_foldout;
+
+ public ZoneVegetation Clone()
+ {
+ return MemberwiseClone() as ZoneVegetation;
+ }
+ }
+
+ [Serializable]
+ public class ZoneLocation
+ {
+ public bool m_enable = true;
+
+ public string m_prefabName;
+
+ [BitMask(typeof(Heightmap.Biome))]
+ public Heightmap.Biome m_biome;
+
+ [BitMask(typeof(Heightmap.BiomeArea))]
+ public Heightmap.BiomeArea m_biomeArea = Heightmap.BiomeArea.Everything;
+
+ public int m_quantity;
+
+ public float m_chanceToSpawn = 10f;
+
+ public bool m_prioritized;
+
+ public bool m_centerFirst;
+
+ public bool m_unique;
+
+ public string m_group = "";
+
+ public float m_minDistanceFromSimilar;
+
+ public bool m_iconAlways;
+
+ public bool m_iconPlaced;
+
+ public bool m_randomRotation = true;
+
+ public bool m_slopeRotation;
+
+ public bool m_snapToWater;
+
+ public float m_maxTerrainDelta = 2f;
+
+ public float m_minTerrainDelta;
+
+ [Header("Forest fractal 0-1 inside forest")]
+ public bool m_inForest;
+
+ public float m_forestTresholdMin;
+
+ public float m_forestTresholdMax = 1f;
+
+ [Space(10f)]
+ public float m_minDistance;
+
+ public float m_maxDistance;
+
+ public float m_minAltitude = -1000f;
+
+ public float m_maxAltitude = 1000f;
+
+ [NonSerialized]
+ public GameObject m_prefab;
+
+ [NonSerialized]
+ public int m_hash;
+
+ [NonSerialized]
+ public Location m_location;
+
+ [NonSerialized]
+ public float m_interiorRadius = 10f;
+
+ [NonSerialized]
+ public float m_exteriorRadius = 10f;
+
+ [NonSerialized]
+ public List<ZNetView> m_netViews = new List<ZNetView>();
+
+ [NonSerialized]
+ public List<RandomSpawn> m_randomSpawns = new List<RandomSpawn>();
+
+ [HideInInspector]
+ public bool m_foldout;
+
+ public ZoneLocation Clone()
+ {
+ return MemberwiseClone() as ZoneLocation;
+ }
+ }
+
+ public struct LocationInstance
+ {
+ public ZoneLocation m_location;
+
+ public Vector3 m_position;
+
+ public bool m_placed;
+ }
+
+ public enum SpawnMode
+ {
+ Full,
+ Client,
+ Ghost
+ }
+
+ private Dictionary<Vector3, string> tempIconList = new Dictionary<Vector3, string>();
+
+ private RaycastHit[] rayHits = new RaycastHit[200];
+
+ private static ZoneSystem m_instance;
+
+ [HideInInspector]
+ public List<Heightmap.Biome> m_biomeFolded = new List<Heightmap.Biome>();
+
+ [HideInInspector]
+ public List<Heightmap.Biome> m_vegetationFolded = new List<Heightmap.Biome>();
+
+ [HideInInspector]
+ public List<Heightmap.Biome> m_locationFolded = new List<Heightmap.Biome>();
+
+ [NonSerialized]
+ public bool m_drawLocations;
+
+ [NonSerialized]
+ public string m_drawLocationsFilter = "";
+
+ [Tooltip("Zones to load around center sector")]
+ public int m_activeArea = 1;
+
+ public int m_activeDistantArea = 1;
+
+ [Tooltip("Zone size, should match netscene sector size")]
+ public float m_zoneSize = 64f;
+
+ [Tooltip("Time before destroying inactive zone")]
+ public float m_zoneTTL = 4f;
+
+ [Tooltip("Time before spawning active zone")]
+ public float m_zoneTTS = 4f;
+
+ public GameObject m_zonePrefab;
+
+ public GameObject m_zoneCtrlPrefab;
+
+ public GameObject m_locationProxyPrefab;
+
+ public float m_waterLevel = 30f;
+
+ [Header("Versions")]
+ public int m_pgwVersion = 53;
+
+ public int m_locationVersion = 1;
+
+ [Header("Generation data")]
+ public List<ZoneVegetation> m_vegetation = new List<ZoneVegetation>();
+
+ public List<ZoneLocation> m_locations = new List<ZoneLocation>();
+
+ private Dictionary<int, ZoneLocation> m_locationsByHash = new Dictionary<int, ZoneLocation>();
+
+ private bool m_error;
+
+ private bool m_didZoneTest;
+
+ private int m_terrainRayMask;
+
+ private int m_blockRayMask;
+
+ private int m_solidRayMask;
+
+ private float m_updateTimer;
+
+ private Dictionary<Vector2i, ZoneData> m_zones = new Dictionary<Vector2i, ZoneData>();
+
+ private HashSet<Vector2i> m_generatedZones = new HashSet<Vector2i>();
+
+ private bool m_locationsGenerated;
+
+ private Dictionary<Vector2i, LocationInstance> m_locationInstances = new Dictionary<Vector2i, LocationInstance>();
+
+ private Dictionary<Vector3, string> m_locationIcons = new Dictionary<Vector3, string>();
+
+ private HashSet<string> m_globalKeys = new HashSet<string>();
+
+ private HashSet<Vector2i> m_tempGeneratedZonesSaveClone;
+
+ private HashSet<string> m_tempGlobalKeysSaveClone;
+
+ private List<LocationInstance> m_tempLocationsSaveClone;
+
+ private bool m_tempLocationsGeneratedSaveClone;
+
+ private List<ClearArea> m_tempClearAreas = new List<ClearArea>();
+
+ private List<GameObject> m_tempSpawnedObjects = new List<GameObject>();
+
+ public static ZoneSystem instance => m_instance;
+
+ private void Awake()
+ {
+ m_instance = this;
+ m_terrainRayMask = LayerMask.GetMask("terrain");
+ m_blockRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece");
+ m_solidRayMask = LayerMask.GetMask("Default", "static_solid", "Default_small", "piece", "terrain");
+ SceneManager.LoadScene("locations", LoadSceneMode.Additive);
+ ZLog.Log("Zonesystem Awake " + Time.frameCount);
+ }
+
+ private void Start()
+ {
+ ZLog.Log("Zonesystem Start " + Time.frameCount);
+ SetupLocations();
+ ValidateVegetation();
+ if (!m_locationsGenerated && ZNet.instance.IsServer())
+ {
+ GenerateLocations();
+ }
+ ZRoutedRpc zRoutedRpc = ZRoutedRpc.instance;
+ zRoutedRpc.m_onNewPeer = (Action<long>)Delegate.Combine(zRoutedRpc.m_onNewPeer, new Action<long>(OnNewPeer));
+ if (ZNet.instance.IsServer())
+ {
+ ZRoutedRpc.instance.Register<string>("SetGlobalKey", RPC_SetGlobalKey);
+ return;
+ }
+ ZRoutedRpc.instance.Register<List<string>>("GlobalKeys", RPC_GlobalKeys);
+ ZRoutedRpc.instance.Register<ZPackage>("LocationIcons", RPC_LocationIcons);
+ }
+
+ private void SendGlobalKeys(long peer)
+ {
+ List<string> list = new List<string>(m_globalKeys);
+ ZRoutedRpc.instance.InvokeRoutedRPC(peer, "GlobalKeys", list);
+ }
+
+ private void RPC_GlobalKeys(long sender, List<string> keys)
+ {
+ ZLog.Log("client got keys " + keys.Count);
+ m_globalKeys.Clear();
+ foreach (string key in keys)
+ {
+ m_globalKeys.Add(key);
+ }
+ }
+
+ private void SendLocationIcons(long peer)
+ {
+ ZPackage zPackage = new ZPackage();
+ tempIconList.Clear();
+ GetLocationIcons(tempIconList);
+ zPackage.Write(tempIconList.Count);
+ foreach (KeyValuePair<Vector3, string> tempIcon in tempIconList)
+ {
+ zPackage.Write(tempIcon.Key);
+ zPackage.Write(tempIcon.Value);
+ }
+ ZRoutedRpc.instance.InvokeRoutedRPC(peer, "LocationIcons", zPackage);
+ }
+
+ private void RPC_LocationIcons(long sender, ZPackage pkg)
+ {
+ ZLog.Log("client got location icons");
+ m_locationIcons.Clear();
+ int num = pkg.ReadInt();
+ for (int i = 0; i < num; i++)
+ {
+ Vector3 key = pkg.ReadVector3();
+ string value = pkg.ReadString();
+ m_locationIcons[key] = value;
+ }
+ ZLog.Log("Icons:" + num);
+ }
+
+ private void OnNewPeer(long peerID)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ ZLog.Log("Server: New peer connected,sending global keys");
+ SendGlobalKeys(peerID);
+ SendLocationIcons(peerID);
+ }
+ }
+
+ private void SetupLocations()
+ {
+ GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
+ GameObject gameObject = null;
+ GameObject[] array2 = array;
+ foreach (GameObject gameObject2 in array2)
+ {
+ if (gameObject2.name == "_Locations")
+ {
+ gameObject = gameObject2;
+ break;
+ }
+ }
+ Location[] componentsInChildren = gameObject.GetComponentsInChildren<Location>(includeInactive: true);
+ Location[] array3 = componentsInChildren;
+ for (int i = 0; i < array3.Length; i++)
+ {
+ if (array3[i].transform.gameObject.activeInHierarchy)
+ {
+ m_error = true;
+ }
+ }
+ foreach (ZoneLocation location3 in m_locations)
+ {
+ Transform transform = null;
+ array3 = componentsInChildren;
+ foreach (Location location in array3)
+ {
+ if (location.gameObject.name == location3.m_prefabName)
+ {
+ transform = location.transform;
+ break;
+ }
+ }
+ if (transform == null && !location3.m_enable)
+ {
+ continue;
+ }
+ location3.m_prefab = transform.gameObject;
+ location3.m_hash = location3.m_prefab.name.GetStableHashCode();
+ Location location2 = (location3.m_location = location3.m_prefab.GetComponentInChildren<Location>());
+ location3.m_interiorRadius = (location2.m_hasInterior ? location2.m_interiorRadius : 0f);
+ location3.m_exteriorRadius = location2.m_exteriorRadius;
+ if (Application.isPlaying)
+ {
+ PrepareNetViews(location3.m_prefab, location3.m_netViews);
+ PrepareRandomSpawns(location3.m_prefab, location3.m_randomSpawns);
+ if (!m_locationsByHash.ContainsKey(location3.m_hash))
+ {
+ m_locationsByHash.Add(location3.m_hash, location3);
+ }
+ }
+ }
+ }
+
+ public static void PrepareNetViews(GameObject root, List<ZNetView> views)
+ {
+ views.Clear();
+ ZNetView[] componentsInChildren = root.GetComponentsInChildren<ZNetView>(includeInactive: true);
+ foreach (ZNetView zNetView in componentsInChildren)
+ {
+ if (Utils.IsEnabledInheirarcy(zNetView.gameObject, root))
+ {
+ views.Add(zNetView);
+ }
+ }
+ }
+
+ public static void PrepareRandomSpawns(GameObject root, List<RandomSpawn> randomSpawns)
+ {
+ randomSpawns.Clear();
+ RandomSpawn[] componentsInChildren = root.GetComponentsInChildren<RandomSpawn>(includeInactive: true);
+ foreach (RandomSpawn randomSpawn in componentsInChildren)
+ {
+ if (Utils.IsEnabledInheirarcy(randomSpawn.gameObject, root))
+ {
+ randomSpawns.Add(randomSpawn);
+ randomSpawn.Prepare();
+ }
+ }
+ }
+
+ private void OnDestroy()
+ {
+ m_instance = null;
+ }
+
+ private void ValidateVegetation()
+ {
+ foreach (ZoneVegetation item in m_vegetation)
+ {
+ if (item.m_enable && (bool)item.m_prefab && item.m_prefab.GetComponent<ZNetView>() == null)
+ {
+ ZLog.LogError("Vegetation " + item.m_prefab.name + " [ " + item.m_name + "] is missing ZNetView");
+ }
+ }
+ }
+
+ public void PrepareSave()
+ {
+ m_tempGeneratedZonesSaveClone = new HashSet<Vector2i>(m_generatedZones);
+ m_tempGlobalKeysSaveClone = new HashSet<string>(m_globalKeys);
+ m_tempLocationsSaveClone = new List<LocationInstance>(m_locationInstances.Values);
+ m_tempLocationsGeneratedSaveClone = m_locationsGenerated;
+ }
+
+ public void SaveASync(BinaryWriter writer)
+ {
+ writer.Write(m_tempGeneratedZonesSaveClone.Count);
+ foreach (Vector2i item in m_tempGeneratedZonesSaveClone)
+ {
+ writer.Write(item.x);
+ writer.Write(item.y);
+ }
+ writer.Write(m_pgwVersion);
+ writer.Write(m_locationVersion);
+ writer.Write(m_tempGlobalKeysSaveClone.Count);
+ foreach (string item2 in m_tempGlobalKeysSaveClone)
+ {
+ writer.Write(item2);
+ }
+ writer.Write(m_tempLocationsGeneratedSaveClone);
+ writer.Write(m_tempLocationsSaveClone.Count);
+ foreach (LocationInstance item3 in m_tempLocationsSaveClone)
+ {
+ writer.Write(item3.m_location.m_prefabName);
+ writer.Write(item3.m_position.x);
+ writer.Write(item3.m_position.y);
+ writer.Write(item3.m_position.z);
+ writer.Write(item3.m_placed);
+ }
+ m_tempGeneratedZonesSaveClone.Clear();
+ m_tempGeneratedZonesSaveClone = null;
+ m_tempGlobalKeysSaveClone.Clear();
+ m_tempGlobalKeysSaveClone = null;
+ m_tempLocationsSaveClone.Clear();
+ m_tempLocationsSaveClone = null;
+ }
+
+ public void Load(BinaryReader reader, int version)
+ {
+ m_generatedZones.Clear();
+ int num = reader.ReadInt32();
+ for (int i = 0; i < num; i++)
+ {
+ Vector2i item = default(Vector2i);
+ item.x = reader.ReadInt32();
+ item.y = reader.ReadInt32();
+ m_generatedZones.Add(item);
+ }
+ if (version < 13)
+ {
+ return;
+ }
+ int num2 = reader.ReadInt32();
+ int num3 = ((version >= 21) ? reader.ReadInt32() : 0);
+ if (num2 != m_pgwVersion)
+ {
+ m_generatedZones.Clear();
+ }
+ if (version >= 14)
+ {
+ m_globalKeys.Clear();
+ int num4 = reader.ReadInt32();
+ for (int j = 0; j < num4; j++)
+ {
+ string item2 = reader.ReadString();
+ m_globalKeys.Add(item2);
+ }
+ }
+ if (version < 18)
+ {
+ return;
+ }
+ if (version >= 20)
+ {
+ m_locationsGenerated = reader.ReadBoolean();
+ }
+ m_locationInstances.Clear();
+ int num5 = reader.ReadInt32();
+ for (int k = 0; k < num5; k++)
+ {
+ string text = reader.ReadString();
+ Vector3 zero = Vector3.zero;
+ zero.x = reader.ReadSingle();
+ zero.y = reader.ReadSingle();
+ zero.z = reader.ReadSingle();
+ bool generated = false;
+ if (version >= 19)
+ {
+ generated = reader.ReadBoolean();
+ }
+ ZoneLocation location = GetLocation(text);
+ if (location != null)
+ {
+ RegisterLocation(location, zero, generated);
+ }
+ else
+ {
+ ZLog.DevLog("Failed to find location " + text);
+ }
+ }
+ ZLog.Log("Loaded " + num5 + " locations");
+ if (num2 != m_pgwVersion)
+ {
+ m_locationInstances.Clear();
+ m_locationsGenerated = false;
+ }
+ if (num3 != m_locationVersion)
+ {
+ m_locationsGenerated = false;
+ }
+ }
+
+ private void Update()
+ {
+ if (ZNet.GetConnectionStatus() != ZNet.ConnectionStatus.Connected)
+ {
+ return;
+ }
+ m_updateTimer += Time.deltaTime;
+ if (!(m_updateTimer > 0.1f))
+ {
+ return;
+ }
+ m_updateTimer = 0f;
+ bool flag = CreateLocalZones(ZNet.instance.GetReferencePosition());
+ UpdateTTL(0.1f);
+ if (!ZNet.instance.IsServer() || flag)
+ {
+ return;
+ }
+ CreateGhostZones(ZNet.instance.GetReferencePosition());
+ foreach (ZNetPeer peer in ZNet.instance.GetPeers())
+ {
+ CreateGhostZones(peer.GetRefPos());
+ }
+ }
+
+ private bool CreateGhostZones(Vector3 refPoint)
+ {
+ Vector2i zone = GetZone(refPoint);
+ if (!IsZoneGenerated(zone) && SpawnZone(zone, SpawnMode.Ghost, out var _))
+ {
+ return true;
+ }
+ int num = m_activeArea + m_activeDistantArea;
+ for (int i = zone.y - num; i <= zone.y + num; i++)
+ {
+ for (int j = zone.x - num; j <= zone.x + num; j++)
+ {
+ Vector2i zoneID = new Vector2i(j, i);
+ if (!IsZoneGenerated(zoneID) && SpawnZone(zoneID, SpawnMode.Ghost, out var _))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool CreateLocalZones(Vector3 refPoint)
+ {
+ Vector2i zone = GetZone(refPoint);
+ if (PokeLocalZone(zone))
+ {
+ return true;
+ }
+ for (int i = zone.y - m_activeArea; i <= zone.y + m_activeArea; i++)
+ {
+ for (int j = zone.x - m_activeArea; j <= zone.x + m_activeArea; j++)
+ {
+ Vector2i vector2i = new Vector2i(j, i);
+ if (!(vector2i == zone) && PokeLocalZone(vector2i))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private bool PokeLocalZone(Vector2i zoneID)
+ {
+ if (m_zones.TryGetValue(zoneID, out var value))
+ {
+ value.m_ttl = 0f;
+ return false;
+ }
+ SpawnMode mode = ((!ZNet.instance.IsServer() || IsZoneGenerated(zoneID)) ? SpawnMode.Client : SpawnMode.Full);
+ if (SpawnZone(zoneID, mode, out var root))
+ {
+ ZoneData zoneData = new ZoneData();
+ zoneData.m_root = root;
+ m_zones.Add(zoneID, zoneData);
+ return true;
+ }
+ return false;
+ }
+
+ public bool IsZoneLoaded(Vector3 point)
+ {
+ Vector2i zone = GetZone(point);
+ return IsZoneLoaded(zone);
+ }
+
+ public bool IsZoneLoaded(Vector2i zoneID)
+ {
+ return m_zones.ContainsKey(zoneID);
+ }
+
+ private bool SpawnZone(Vector2i zoneID, SpawnMode mode, out GameObject root)
+ {
+ Vector3 zonePos = GetZonePos(zoneID);
+ Heightmap componentInChildren = m_zonePrefab.GetComponentInChildren<Heightmap>();
+ if (!HeightmapBuilder.instance.IsTerrainReady(zonePos, componentInChildren.m_width, componentInChildren.m_scale, componentInChildren.m_isDistantLod, WorldGenerator.instance))
+ {
+ root = null;
+ return false;
+ }
+ root = UnityEngine.Object.Instantiate(m_zonePrefab, zonePos, Quaternion.identity);
+ if ((mode == SpawnMode.Ghost || mode == SpawnMode.Full) && !IsZoneGenerated(zoneID))
+ {
+ Heightmap componentInChildren2 = root.GetComponentInChildren<Heightmap>();
+ m_tempClearAreas.Clear();
+ m_tempSpawnedObjects.Clear();
+ PlaceLocations(zoneID, zonePos, root.transform, componentInChildren2, m_tempClearAreas, mode, m_tempSpawnedObjects);
+ PlaceVegetation(zoneID, zonePos, root.transform, componentInChildren2, m_tempClearAreas, mode, m_tempSpawnedObjects);
+ PlaceZoneCtrl(zoneID, zonePos, mode, m_tempSpawnedObjects);
+ if (mode == SpawnMode.Ghost)
+ {
+ foreach (GameObject tempSpawnedObject in m_tempSpawnedObjects)
+ {
+ UnityEngine.Object.Destroy(tempSpawnedObject);
+ }
+ m_tempSpawnedObjects.Clear();
+ UnityEngine.Object.Destroy(root);
+ root = null;
+ }
+ SetZoneGenerated(zoneID);
+ }
+ return true;
+ }
+
+ private void PlaceZoneCtrl(Vector2i zoneID, Vector3 zoneCenterPos, SpawnMode mode, List<GameObject> spawnedObjects)
+ {
+ if (mode == SpawnMode.Full || mode == SpawnMode.Ghost)
+ {
+ if (mode == SpawnMode.Ghost)
+ {
+ ZNetView.StartGhostInit();
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_zoneCtrlPrefab, zoneCenterPos, Quaternion.identity);
+ gameObject.GetComponent<ZNetView>().GetZDO().SetPGWVersion(m_pgwVersion);
+ if (mode == SpawnMode.Ghost)
+ {
+ spawnedObjects.Add(gameObject);
+ ZNetView.FinishGhostInit();
+ }
+ }
+ }
+
+ private Vector3 GetRandomPointInRadius(Vector3 center, float radius)
+ {
+ float f = UnityEngine.Random.value * (float)Math.PI * 2f;
+ float num = UnityEngine.Random.Range(0f, radius);
+ return center + new Vector3(Mathf.Sin(f) * num, 0f, Mathf.Cos(f) * num);
+ }
+
+ private void PlaceVegetation(Vector2i zoneID, Vector3 zoneCenterPos, Transform parent, Heightmap hmap, List<ClearArea> clearAreas, SpawnMode mode, List<GameObject> spawnedObjects)
+ {
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ int seed = WorldGenerator.instance.GetSeed();
+ float num = m_zoneSize / 2f;
+ int num2 = 1;
+ foreach (ZoneVegetation item in m_vegetation)
+ {
+ num2++;
+ if (!item.m_enable || !hmap.HaveBiome(item.m_biome))
+ {
+ continue;
+ }
+ UnityEngine.Random.InitState(seed + zoneID.x * 4271 + zoneID.y * 9187 + item.m_prefab.name.GetStableHashCode());
+ int num3 = 1;
+ if (item.m_max < 1f)
+ {
+ if (UnityEngine.Random.value > item.m_max)
+ {
+ continue;
+ }
+ }
+ else
+ {
+ num3 = UnityEngine.Random.Range((int)item.m_min, (int)item.m_max + 1);
+ }
+ bool flag = item.m_prefab.GetComponent<ZNetView>() != null;
+ float num4 = Mathf.Cos((float)Math.PI / 180f * item.m_maxTilt);
+ float num5 = Mathf.Cos((float)Math.PI / 180f * item.m_minTilt);
+ float num6 = num - item.m_groupRadius;
+ int num7 = (item.m_forcePlacement ? (num3 * 50) : num3);
+ int num8 = 0;
+ for (int i = 0; i < num7; i++)
+ {
+ Vector3 vector = new Vector3(UnityEngine.Random.Range(zoneCenterPos.x - num6, zoneCenterPos.x + num6), 0f, UnityEngine.Random.Range(zoneCenterPos.z - num6, zoneCenterPos.z + num6));
+ int num9 = UnityEngine.Random.Range(item.m_groupSizeMin, item.m_groupSizeMax + 1);
+ bool flag2 = false;
+ for (int j = 0; j < num9; j++)
+ {
+ Vector3 p = ((j == 0) ? vector : GetRandomPointInRadius(vector, item.m_groupRadius));
+ float num10 = UnityEngine.Random.Range(0, 360);
+ float num11 = UnityEngine.Random.Range(item.m_scaleMin, item.m_scaleMax);
+ float x = UnityEngine.Random.Range(0f - item.m_randTilt, item.m_randTilt);
+ float z = UnityEngine.Random.Range(0f - item.m_randTilt, item.m_randTilt);
+ if (item.m_blockCheck && IsBlocked(p))
+ {
+ continue;
+ }
+ GetGroundData(ref p, out var normal, out var biome, out var biomeArea, out var hmap2);
+ if ((item.m_biome & biome) == 0 || (item.m_biomeArea & biomeArea) == 0)
+ {
+ continue;
+ }
+ float num12 = p.y - m_waterLevel;
+ if (num12 < item.m_minAltitude || num12 > item.m_maxAltitude)
+ {
+ continue;
+ }
+ if (item.m_minOceanDepth != item.m_maxOceanDepth)
+ {
+ float oceanDepth = hmap2.GetOceanDepth(p);
+ if (oceanDepth < item.m_minOceanDepth || oceanDepth > item.m_maxOceanDepth)
+ {
+ continue;
+ }
+ }
+ if (normal.y < num4 || normal.y > num5)
+ {
+ continue;
+ }
+ if (item.m_terrainDeltaRadius > 0f)
+ {
+ GetTerrainDelta(p, item.m_terrainDeltaRadius, out var delta, out var _);
+ if (delta > item.m_maxTerrainDelta || delta < item.m_minTerrainDelta)
+ {
+ continue;
+ }
+ }
+ if (item.m_inForest)
+ {
+ float forestFactor = WorldGenerator.GetForestFactor(p);
+ if (forestFactor < item.m_forestTresholdMin || forestFactor > item.m_forestTresholdMax)
+ {
+ continue;
+ }
+ }
+ if (InsideClearArea(clearAreas, p))
+ {
+ continue;
+ }
+ if (item.m_snapToWater)
+ {
+ p.y = m_waterLevel;
+ }
+ p.y += item.m_groundOffset;
+ Quaternion identity = Quaternion.identity;
+ identity = ((!(item.m_chanceToUseGroundTilt > 0f) || !(UnityEngine.Random.value <= item.m_chanceToUseGroundTilt)) ? Quaternion.Euler(x, num10, z) : Quaternion.AngleAxis(num10, normal));
+ if (flag)
+ {
+ if (mode == SpawnMode.Full || mode == SpawnMode.Ghost)
+ {
+ if (mode == SpawnMode.Ghost)
+ {
+ ZNetView.StartGhostInit();
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(item.m_prefab, p, identity);
+ ZNetView component = gameObject.GetComponent<ZNetView>();
+ component.SetLocalScale(new Vector3(num11, num11, num11));
+ component.GetZDO().SetPGWVersion(m_pgwVersion);
+ if (mode == SpawnMode.Ghost)
+ {
+ spawnedObjects.Add(gameObject);
+ ZNetView.FinishGhostInit();
+ }
+ }
+ }
+ else
+ {
+ GameObject obj = UnityEngine.Object.Instantiate(item.m_prefab, p, identity);
+ obj.transform.localScale = new Vector3(num11, num11, num11);
+ obj.transform.SetParent(parent, worldPositionStays: true);
+ }
+ flag2 = true;
+ }
+ if (flag2)
+ {
+ num8++;
+ }
+ if (num8 >= num3)
+ {
+ break;
+ }
+ }
+ }
+ UnityEngine.Random.state = state;
+ }
+
+ private bool InsideClearArea(List<ClearArea> areas, Vector3 point)
+ {
+ foreach (ClearArea area in areas)
+ {
+ if (point.x > area.m_center.x - area.m_radius && point.x < area.m_center.x + area.m_radius && point.z > area.m_center.z - area.m_radius && point.z < area.m_center.z + area.m_radius)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ZoneLocation GetLocation(int hash)
+ {
+ if (m_locationsByHash.TryGetValue(hash, out var value))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ private ZoneLocation GetLocation(string name)
+ {
+ foreach (ZoneLocation location in m_locations)
+ {
+ if (location.m_prefabName == name)
+ {
+ return location;
+ }
+ }
+ return null;
+ }
+
+ private void ClearNonPlacedLocations()
+ {
+ Dictionary<Vector2i, LocationInstance> dictionary = new Dictionary<Vector2i, LocationInstance>();
+ foreach (KeyValuePair<Vector2i, LocationInstance> locationInstance in m_locationInstances)
+ {
+ if (locationInstance.Value.m_placed)
+ {
+ dictionary.Add(locationInstance.Key, locationInstance.Value);
+ }
+ }
+ m_locationInstances = dictionary;
+ }
+
+ private void CheckLocationDuplicates()
+ {
+ ZLog.Log("Checking for location duplicates");
+ for (int i = 0; i < m_locations.Count; i++)
+ {
+ ZoneLocation zoneLocation = m_locations[i];
+ if (!zoneLocation.m_enable)
+ {
+ continue;
+ }
+ for (int j = i + 1; j < m_locations.Count; j++)
+ {
+ ZoneLocation zoneLocation2 = m_locations[j];
+ if (zoneLocation2.m_enable && zoneLocation.m_prefabName == zoneLocation2.m_prefabName)
+ {
+ ZLog.LogWarning("Two locations points to the same location prefab " + zoneLocation.m_prefabName);
+ }
+ }
+ }
+ }
+
+ public void GenerateLocations()
+ {
+ if (!Application.isPlaying)
+ {
+ ZLog.Log("Setting up locations");
+ SetupLocations();
+ }
+ ZLog.Log("Generating locations");
+ DateTime now = DateTime.Now;
+ m_locationsGenerated = true;
+ UnityEngine.Random.State state = UnityEngine.Random.state;
+ CheckLocationDuplicates();
+ ClearNonPlacedLocations();
+ foreach (ZoneLocation item in m_locations.OrderByDescending((ZoneLocation a) => a.m_prioritized))
+ {
+ if (item.m_enable && item.m_quantity != 0)
+ {
+ GenerateLocations(item);
+ }
+ }
+ UnityEngine.Random.state = state;
+ ZLog.Log(" Done generating locations, duration:" + (DateTime.Now - now).TotalMilliseconds + " ms");
+ }
+
+ private int CountNrOfLocation(ZoneLocation location)
+ {
+ int num = 0;
+ foreach (LocationInstance value in m_locationInstances.Values)
+ {
+ if (value.m_location.m_prefabName == location.m_prefabName)
+ {
+ num++;
+ }
+ }
+ if (num > 0)
+ {
+ ZLog.Log("Old location found " + location.m_prefabName + " x " + num);
+ }
+ return num;
+ }
+
+ private void GenerateLocations(ZoneLocation location)
+ {
+ DateTime now = DateTime.Now;
+ UnityEngine.Random.InitState(WorldGenerator.instance.GetSeed() + location.m_prefabName.GetStableHashCode());
+ int num = 0;
+ int num2 = 0;
+ int num3 = 0;
+ int num4 = 0;
+ int num5 = 0;
+ int num6 = 0;
+ int num7 = 0;
+ int num8 = 0;
+ float locationRadius = Mathf.Max(location.m_exteriorRadius, location.m_interiorRadius);
+ int num9 = 0;
+ int num10 = CountNrOfLocation(location);
+ float num11 = 10000f;
+ if (location.m_centerFirst)
+ {
+ num11 = location.m_minDistance;
+ }
+ if (location.m_unique && num10 > 0)
+ {
+ return;
+ }
+ for (int i = 0; i < 100000; i++)
+ {
+ if (num10 >= location.m_quantity)
+ {
+ break;
+ }
+ Vector2i randomZone = GetRandomZone(num11);
+ if (location.m_centerFirst)
+ {
+ num11 += 1f;
+ }
+ if (m_locationInstances.ContainsKey(randomZone))
+ {
+ num++;
+ }
+ else
+ {
+ if (IsZoneGenerated(randomZone))
+ {
+ continue;
+ }
+ Vector3 zonePos = GetZonePos(randomZone);
+ Heightmap.BiomeArea biomeArea = WorldGenerator.instance.GetBiomeArea(zonePos);
+ if ((location.m_biomeArea & biomeArea) == 0)
+ {
+ num4++;
+ continue;
+ }
+ for (int j = 0; j < 20; j++)
+ {
+ num9++;
+ Vector3 randomPointInZone = GetRandomPointInZone(randomZone, locationRadius);
+ float magnitude = randomPointInZone.magnitude;
+ if (location.m_minDistance != 0f && magnitude < location.m_minDistance)
+ {
+ num2++;
+ continue;
+ }
+ if (location.m_maxDistance != 0f && magnitude > location.m_maxDistance)
+ {
+ num2++;
+ continue;
+ }
+ Heightmap.Biome biome = WorldGenerator.instance.GetBiome(randomPointInZone);
+ if ((location.m_biome & biome) == 0)
+ {
+ num3++;
+ continue;
+ }
+ randomPointInZone.y = WorldGenerator.instance.GetHeight(randomPointInZone.x, randomPointInZone.z);
+ float num12 = randomPointInZone.y - m_waterLevel;
+ if (num12 < location.m_minAltitude || num12 > location.m_maxAltitude)
+ {
+ num5++;
+ continue;
+ }
+ if (location.m_inForest)
+ {
+ float forestFactor = WorldGenerator.GetForestFactor(randomPointInZone);
+ if (forestFactor < location.m_forestTresholdMin || forestFactor > location.m_forestTresholdMax)
+ {
+ num6++;
+ continue;
+ }
+ }
+ WorldGenerator.instance.GetTerrainDelta(randomPointInZone, location.m_exteriorRadius, out var delta, out var _);
+ if (delta > location.m_maxTerrainDelta || delta < location.m_minTerrainDelta)
+ {
+ num8++;
+ continue;
+ }
+ if (location.m_minDistanceFromSimilar > 0f && HaveLocationInRange(location.m_prefabName, location.m_group, randomPointInZone, location.m_minDistanceFromSimilar))
+ {
+ num7++;
+ continue;
+ }
+ RegisterLocation(location, randomPointInZone, generated: false);
+ num10++;
+ break;
+ }
+ }
+ }
+ if (num10 < location.m_quantity)
+ {
+ ZLog.LogWarning("Failed to place all " + location.m_prefabName + ", placed " + num10 + " out of " + location.m_quantity);
+ ZLog.DevLog("errorLocationInZone " + num);
+ ZLog.DevLog("errorCenterDistance " + num2);
+ ZLog.DevLog("errorBiome " + num3);
+ ZLog.DevLog("errorBiomeArea " + num4);
+ ZLog.DevLog("errorAlt " + num5);
+ ZLog.DevLog("errorForest " + num6);
+ ZLog.DevLog("errorSimilar " + num7);
+ ZLog.DevLog("errorTerrainDelta " + num8);
+ }
+ _ = DateTime.Now - now;
+ }
+
+ private Vector2i GetRandomZone(float range)
+ {
+ int num = (int)range / (int)m_zoneSize;
+ Vector2i vector2i;
+ do
+ {
+ vector2i = new Vector2i(UnityEngine.Random.Range(-num, num), UnityEngine.Random.Range(-num, num));
+ }
+ while (!(GetZonePos(vector2i).magnitude < 10000f));
+ return vector2i;
+ }
+
+ private Vector3 GetRandomPointInZone(Vector2i zone, float locationRadius)
+ {
+ Vector3 zonePos = GetZonePos(zone);
+ float num = m_zoneSize / 2f;
+ float x = UnityEngine.Random.Range(0f - num + locationRadius, num - locationRadius);
+ float z = UnityEngine.Random.Range(0f - num + locationRadius, num - locationRadius);
+ return zonePos + new Vector3(x, 0f, z);
+ }
+
+ private Vector3 GetRandomPointInZone(float locationRadius)
+ {
+ Vector3 point = new Vector3(UnityEngine.Random.Range(-10000f, 10000f), 0f, UnityEngine.Random.Range(-10000f, 10000f));
+ Vector2i zone = GetZone(point);
+ Vector3 zonePos = GetZonePos(zone);
+ float num = m_zoneSize / 2f;
+ return new Vector3(UnityEngine.Random.Range(zonePos.x - num + locationRadius, zonePos.x + num - locationRadius), 0f, UnityEngine.Random.Range(zonePos.z - num + locationRadius, zonePos.z + num - locationRadius));
+ }
+
+ private void PlaceLocations(Vector2i zoneID, Vector3 zoneCenterPos, Transform parent, Heightmap hmap, List<ClearArea> clearAreas, SpawnMode mode, List<GameObject> spawnedObjects)
+ {
+ if (!m_locationsGenerated)
+ {
+ GenerateLocations();
+ }
+ DateTime now = DateTime.Now;
+ if (m_locationInstances.TryGetValue(zoneID, out var value) && !value.m_placed)
+ {
+ Vector3 p = value.m_position;
+ GetGroundData(ref p, out var _, out var _, out var _, out var _);
+ if (value.m_location.m_snapToWater)
+ {
+ p.y = m_waterLevel;
+ }
+ if (value.m_location.m_location.m_clearArea)
+ {
+ ClearArea item = new ClearArea(p, value.m_location.m_exteriorRadius);
+ clearAreas.Add(item);
+ }
+ Quaternion rot = Quaternion.identity;
+ if (value.m_location.m_slopeRotation)
+ {
+ GetTerrainDelta(p, value.m_location.m_exteriorRadius, out var _, out var slopeDirection);
+ Vector3 forward = new Vector3(slopeDirection.x, 0f, slopeDirection.z);
+ forward.Normalize();
+ rot = Quaternion.LookRotation(forward);
+ Vector3 eulerAngles = rot.eulerAngles;
+ eulerAngles.y = Mathf.Round(eulerAngles.y / 22.5f) * 22.5f;
+ rot.eulerAngles = eulerAngles;
+ }
+ else if (value.m_location.m_randomRotation)
+ {
+ rot = Quaternion.Euler(0f, (float)UnityEngine.Random.Range(0, 16) * 22.5f, 0f);
+ }
+ int seed = WorldGenerator.instance.GetSeed() + zoneID.x * 4271 + zoneID.y * 9187;
+ SpawnLocation(value.m_location, seed, p, rot, mode, spawnedObjects);
+ value.m_placed = true;
+ m_locationInstances[zoneID] = value;
+ TimeSpan timeSpan = DateTime.Now - now;
+ ZLog.Log(string.Concat("Placed locations in zone ", zoneID, " duration ", timeSpan.TotalMilliseconds, " ms"));
+ if (value.m_location.m_unique)
+ {
+ RemoveUnplacedLocations(value.m_location);
+ }
+ if (value.m_location.m_iconPlaced)
+ {
+ SendLocationIcons(ZRoutedRpc.Everybody);
+ }
+ }
+ }
+
+ private void RemoveUnplacedLocations(ZoneLocation location)
+ {
+ List<Vector2i> list = new List<Vector2i>();
+ foreach (KeyValuePair<Vector2i, LocationInstance> locationInstance in m_locationInstances)
+ {
+ if (locationInstance.Value.m_location == location && !locationInstance.Value.m_placed)
+ {
+ list.Add(locationInstance.Key);
+ }
+ }
+ foreach (Vector2i item in list)
+ {
+ m_locationInstances.Remove(item);
+ }
+ ZLog.DevLog("Removed " + list.Count + " unplaced locations of type " + location.m_prefabName);
+ }
+
+ public bool TestSpawnLocation(string name, Vector3 pos)
+ {
+ if (!ZNet.instance.IsServer())
+ {
+ return false;
+ }
+ ZoneLocation location = GetLocation(name);
+ if (location == null)
+ {
+ ZLog.Log("Missing location:" + name);
+ Console.instance.Print("Missing location:" + name);
+ return false;
+ }
+ if (location.m_prefab == null)
+ {
+ ZLog.Log("Missing prefab in location:" + name);
+ Console.instance.Print("Missing location:" + name);
+ return false;
+ }
+ float num = Mathf.Max(location.m_exteriorRadius, location.m_interiorRadius);
+ Vector2i zone = GetZone(pos);
+ Vector3 zonePos = GetZonePos(zone);
+ pos.x = Mathf.Clamp(pos.x, zonePos.x - m_zoneSize / 2f + num, zonePos.x + m_zoneSize / 2f - num);
+ pos.z = Mathf.Clamp(pos.z, zonePos.z - m_zoneSize / 2f + num, zonePos.z + m_zoneSize / 2f - num);
+ ZLog.Log(string.Concat("radius ", num, " ", zonePos, " ", pos));
+ MessageHud.instance.ShowMessage(MessageHud.MessageType.Center, "Location spawned, world saving DISABLED until restart");
+ m_didZoneTest = true;
+ float y = (float)UnityEngine.Random.Range(0, 16) * 22.5f;
+ List<GameObject> spawnedGhostObjects = new List<GameObject>();
+ SpawnLocation(location, UnityEngine.Random.Range(0, 99999), pos, Quaternion.Euler(0f, y, 0f), SpawnMode.Full, spawnedGhostObjects);
+ return true;
+ }
+
+ public GameObject SpawnProxyLocation(int hash, int seed, Vector3 pos, Quaternion rot)
+ {
+ ZoneLocation location = GetLocation(hash);
+ if (location == null)
+ {
+ ZLog.LogWarning("Missing location:" + hash);
+ return null;
+ }
+ List<GameObject> spawnedGhostObjects = new List<GameObject>();
+ return SpawnLocation(location, seed, pos, rot, SpawnMode.Client, spawnedGhostObjects);
+ }
+
+ private GameObject SpawnLocation(ZoneLocation location, int seed, Vector3 pos, Quaternion rot, SpawnMode mode, List<GameObject> spawnedGhostObjects)
+ {
+ Vector3 position = location.m_prefab.transform.position;
+ Quaternion quaternion = Quaternion.Inverse(location.m_prefab.transform.rotation);
+ UnityEngine.Random.InitState(seed);
+ if (mode == SpawnMode.Full || mode == SpawnMode.Ghost)
+ {
+ foreach (ZNetView netView in location.m_netViews)
+ {
+ netView.gameObject.SetActive(value: true);
+ }
+ foreach (RandomSpawn randomSpawn in location.m_randomSpawns)
+ {
+ randomSpawn.Randomize();
+ }
+ WearNTear.m_randomInitialDamage = location.m_location.m_applyRandomDamage;
+ foreach (ZNetView netView2 in location.m_netViews)
+ {
+ if (netView2.gameObject.activeSelf)
+ {
+ Vector3 vector = netView2.gameObject.transform.position - position;
+ Vector3 position2 = pos + rot * vector;
+ Quaternion quaternion2 = quaternion * netView2.gameObject.transform.rotation;
+ Quaternion rotation = rot * quaternion2;
+ if (mode == SpawnMode.Ghost)
+ {
+ ZNetView.StartGhostInit();
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(netView2.gameObject, position2, rotation);
+ gameObject.GetComponent<ZNetView>().GetZDO().SetPGWVersion(m_pgwVersion);
+ DungeonGenerator component = gameObject.GetComponent<DungeonGenerator>();
+ if ((bool)component)
+ {
+ component.Generate(mode);
+ }
+ if (mode == SpawnMode.Ghost)
+ {
+ spawnedGhostObjects.Add(gameObject);
+ ZNetView.FinishGhostInit();
+ }
+ }
+ }
+ WearNTear.m_randomInitialDamage = false;
+ CreateLocationProxy(location, seed, pos, rot, mode, spawnedGhostObjects);
+ SnapToGround.SnappAll();
+ return null;
+ }
+ foreach (RandomSpawn randomSpawn2 in location.m_randomSpawns)
+ {
+ randomSpawn2.Randomize();
+ }
+ foreach (ZNetView netView3 in location.m_netViews)
+ {
+ netView3.gameObject.SetActive(value: false);
+ }
+ GameObject obj = UnityEngine.Object.Instantiate(location.m_prefab, pos, rot);
+ obj.SetActive(value: true);
+ SnapToGround.SnappAll();
+ return obj;
+ }
+
+ private void CreateLocationProxy(ZoneLocation location, int seed, Vector3 pos, Quaternion rotation, SpawnMode mode, List<GameObject> spawnedGhostObjects)
+ {
+ if (mode == SpawnMode.Ghost)
+ {
+ ZNetView.StartGhostInit();
+ }
+ GameObject gameObject = UnityEngine.Object.Instantiate(m_locationProxyPrefab, pos, rotation);
+ LocationProxy component = gameObject.GetComponent<LocationProxy>();
+ bool spawnNow = mode == SpawnMode.Full;
+ component.SetLocation(location.m_prefab.name, seed, spawnNow, m_pgwVersion);
+ if (mode == SpawnMode.Ghost)
+ {
+ spawnedGhostObjects.Add(gameObject);
+ ZNetView.FinishGhostInit();
+ }
+ }
+
+ private void RegisterLocation(ZoneLocation location, Vector3 pos, bool generated)
+ {
+ LocationInstance value = default(LocationInstance);
+ value.m_location = location;
+ value.m_position = pos;
+ value.m_placed = generated;
+ Vector2i zone = GetZone(pos);
+ if (m_locationInstances.ContainsKey(zone))
+ {
+ ZLog.LogWarning("Location already exist in zone " + zone);
+ }
+ else
+ {
+ m_locationInstances.Add(zone, value);
+ }
+ }
+
+ private bool HaveLocationInRange(string prefabName, string group, Vector3 p, float radius)
+ {
+ foreach (LocationInstance value in m_locationInstances.Values)
+ {
+ if ((value.m_location.m_prefabName == prefabName || (group.Length > 0 && group == value.m_location.m_group)) && Vector3.Distance(value.m_position, p) < radius)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool GetLocationIcon(string name, out Vector3 pos)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ foreach (KeyValuePair<Vector2i, LocationInstance> locationInstance in m_locationInstances)
+ {
+ if ((locationInstance.Value.m_location.m_iconAlways || (locationInstance.Value.m_location.m_iconPlaced && locationInstance.Value.m_placed)) && locationInstance.Value.m_location.m_prefabName == name)
+ {
+ pos = locationInstance.Value.m_position;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ foreach (KeyValuePair<Vector3, string> locationIcon in m_locationIcons)
+ {
+ if (locationIcon.Value == name)
+ {
+ pos = locationIcon.Key;
+ return true;
+ }
+ }
+ }
+ pos = Vector3.zero;
+ return false;
+ }
+
+ public void GetLocationIcons(Dictionary<Vector3, string> icons)
+ {
+ if (ZNet.instance.IsServer())
+ {
+ foreach (LocationInstance value in m_locationInstances.Values)
+ {
+ if (value.m_location.m_iconAlways || (value.m_location.m_iconPlaced && value.m_placed))
+ {
+ icons[value.m_position] = value.m_location.m_prefabName;
+ }
+ }
+ return;
+ }
+ foreach (KeyValuePair<Vector3, string> locationIcon in m_locationIcons)
+ {
+ icons.Add(locationIcon.Key, locationIcon.Value);
+ }
+ }
+
+ private void GetTerrainDelta(Vector3 center, float radius, out float delta, out Vector3 slopeDirection)
+ {
+ int num = 10;
+ float num2 = -999999f;
+ float num3 = 999999f;
+ Vector3 vector = center;
+ Vector3 vector2 = center;
+ for (int i = 0; i < num; i++)
+ {
+ Vector2 vector3 = UnityEngine.Random.insideUnitCircle * radius;
+ Vector3 vector4 = center + new Vector3(vector3.x, 0f, vector3.y);
+ float groundHeight = GetGroundHeight(vector4);
+ if (groundHeight < num3)
+ {
+ num3 = groundHeight;
+ vector2 = vector4;
+ }
+ if (groundHeight > num2)
+ {
+ num2 = groundHeight;
+ vector = vector4;
+ }
+ }
+ delta = num2 - num3;
+ slopeDirection = Vector3.Normalize(vector2 - vector);
+ }
+
+ public bool IsBlocked(Vector3 p)
+ {
+ p.y += 2000f;
+ if (Physics.Raycast(p, Vector3.down, 10000f, m_blockRayMask))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public float GetAverageGroundHeight(Vector3 p, float radius)
+ {
+ Vector3 origin = p;
+ origin.y = 6000f;
+ if (Physics.Raycast(origin, Vector3.down, out var hitInfo, 10000f, m_terrainRayMask))
+ {
+ return hitInfo.point.y;
+ }
+ return p.y;
+ }
+
+ public float GetGroundHeight(Vector3 p)
+ {
+ Vector3 origin = p;
+ origin.y = 6000f;
+ if (Physics.Raycast(origin, Vector3.down, out var hitInfo, 10000f, m_terrainRayMask))
+ {
+ return hitInfo.point.y;
+ }
+ return p.y;
+ }
+
+ public bool GetGroundHeight(Vector3 p, out float height)
+ {
+ p.y = 6000f;
+ if (Physics.Raycast(p, Vector3.down, out var hitInfo, 10000f, m_terrainRayMask))
+ {
+ height = hitInfo.point.y;
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ public float GetSolidHeight(Vector3 p)
+ {
+ Vector3 origin = p;
+ origin.y += 1000f;
+ if (Physics.Raycast(origin, Vector3.down, out var hitInfo, 2000f, m_solidRayMask))
+ {
+ return hitInfo.point.y;
+ }
+ return p.y;
+ }
+
+ public bool GetSolidHeight(Vector3 p, out float height)
+ {
+ p.y += 1000f;
+ if (Physics.Raycast(p, Vector3.down, out var hitInfo, 2000f, m_solidRayMask) && !hitInfo.collider.attachedRigidbody)
+ {
+ height = hitInfo.point.y;
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ public bool GetSolidHeight(Vector3 p, float radius, out float height, Transform ignore)
+ {
+ height = p.y - 1000f;
+ p.y += 1000f;
+ int num = ((!(radius <= 0f)) ? Physics.SphereCastNonAlloc(p, radius, Vector3.down, rayHits, 2000f, m_solidRayMask) : Physics.RaycastNonAlloc(p, Vector3.down, rayHits, 2000f, m_solidRayMask));
+ bool result = false;
+ for (int i = 0; i < num; i++)
+ {
+ RaycastHit raycastHit = rayHits[i];
+ Collider collider = raycastHit.collider;
+ if (!(collider.attachedRigidbody != null) && (!(ignore != null) || !Utils.IsParent(collider.transform, ignore)))
+ {
+ if (raycastHit.point.y > height)
+ {
+ height = raycastHit.point.y;
+ }
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public bool GetSolidHeight(Vector3 p, out float height, out Vector3 normal)
+ {
+ GameObject go;
+ return GetSolidHeight(p, out height, out normal, out go);
+ }
+
+ public bool GetSolidHeight(Vector3 p, out float height, out Vector3 normal, out GameObject go)
+ {
+ p.y += 1000f;
+ if (Physics.Raycast(p, Vector3.down, out var hitInfo, 2000f, m_solidRayMask) && !hitInfo.collider.attachedRigidbody)
+ {
+ height = hitInfo.point.y;
+ normal = hitInfo.normal;
+ go = hitInfo.collider.gameObject;
+ return true;
+ }
+ height = 0f;
+ normal = Vector3.zero;
+ go = null;
+ return false;
+ }
+
+ public bool FindFloor(Vector3 p, out float height)
+ {
+ if (Physics.Raycast(p + Vector3.up * 1f, Vector3.down, out var hitInfo, 1000f, m_solidRayMask))
+ {
+ height = hitInfo.point.y;
+ return true;
+ }
+ height = 0f;
+ return false;
+ }
+
+ public void GetGroundData(ref Vector3 p, out Vector3 normal, out Heightmap.Biome biome, out Heightmap.BiomeArea biomeArea, out Heightmap hmap)
+ {
+ biome = Heightmap.Biome.None;
+ biomeArea = Heightmap.BiomeArea.Everything;
+ hmap = null;
+ if (Physics.Raycast(p + Vector3.up * 5000f, Vector3.down, out var hitInfo, 10000f, m_terrainRayMask))
+ {
+ p.y = hitInfo.point.y;
+ normal = hitInfo.normal;
+ Heightmap component = hitInfo.collider.GetComponent<Heightmap>();
+ if ((bool)component)
+ {
+ biome = component.GetBiome(hitInfo.point);
+ biomeArea = component.GetBiomeArea();
+ hmap = component;
+ }
+ }
+ else
+ {
+ normal = Vector3.up;
+ }
+ }
+
+ private void UpdateTTL(float dt)
+ {
+ foreach (KeyValuePair<Vector2i, ZoneData> zone in m_zones)
+ {
+ zone.Value.m_ttl += dt;
+ }
+ foreach (KeyValuePair<Vector2i, ZoneData> zone2 in m_zones)
+ {
+ if (zone2.Value.m_ttl > m_zoneTTL && !ZNetScene.instance.HaveInstanceInSector(zone2.Key))
+ {
+ UnityEngine.Object.Destroy(zone2.Value.m_root);
+ m_zones.Remove(zone2.Key);
+ break;
+ }
+ }
+ }
+
+ public void GetVegetation(Heightmap.Biome biome, List<ZoneVegetation> vegetation)
+ {
+ foreach (ZoneVegetation item in m_vegetation)
+ {
+ if ((item.m_biome & biome) != 0 || item.m_biome == biome)
+ {
+ vegetation.Add(item);
+ }
+ }
+ }
+
+ public void GetLocations(Heightmap.Biome biome, List<ZoneLocation> locations, bool skipDisabled)
+ {
+ foreach (ZoneLocation location in m_locations)
+ {
+ if (((location.m_biome & biome) != 0 || location.m_biome == biome) && (!skipDisabled || location.m_enable))
+ {
+ locations.Add(location);
+ }
+ }
+ }
+
+ public bool FindClosestLocation(string name, Vector3 point, out LocationInstance closest)
+ {
+ float num = 999999f;
+ closest = default(LocationInstance);
+ bool result = false;
+ foreach (LocationInstance value in m_locationInstances.Values)
+ {
+ float num2 = Vector3.Distance(value.m_position, point);
+ if (value.m_location.m_prefabName == name && num2 < num)
+ {
+ num = num2;
+ closest = value;
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public Vector2i GetZone(Vector3 point)
+ {
+ int x = Mathf.FloorToInt((point.x + m_zoneSize / 2f) / m_zoneSize);
+ int y = Mathf.FloorToInt((point.z + m_zoneSize / 2f) / m_zoneSize);
+ return new Vector2i(x, y);
+ }
+
+ public Vector3 GetZonePos(Vector2i id)
+ {
+ return new Vector3((float)id.x * m_zoneSize, 0f, (float)id.y * m_zoneSize);
+ }
+
+ private void SetZoneGenerated(Vector2i zoneID)
+ {
+ m_generatedZones.Add(zoneID);
+ }
+
+ private bool IsZoneGenerated(Vector2i zoneID)
+ {
+ return m_generatedZones.Contains(zoneID);
+ }
+
+ public bool SkipSaving()
+ {
+ if (!m_error)
+ {
+ return m_didZoneTest;
+ }
+ return true;
+ }
+
+ public void ResetGlobalKeys()
+ {
+ m_globalKeys.Clear();
+ SendGlobalKeys(ZRoutedRpc.Everybody);
+ }
+
+ public void SetGlobalKey(string name)
+ {
+ ZRoutedRpc.instance.InvokeRoutedRPC("SetGlobalKey", name);
+ }
+
+ public bool GetGlobalKey(string name)
+ {
+ return m_globalKeys.Contains(name);
+ }
+
+ private void RPC_SetGlobalKey(long sender, string name)
+ {
+ if (!m_globalKeys.Contains(name))
+ {
+ m_globalKeys.Add(name);
+ SendGlobalKeys(ZRoutedRpc.Everybody);
+ }
+ }
+
+ public List<string> GetGlobalKeys()
+ {
+ return new List<string>(m_globalKeys);
+ }
+
+ public Dictionary<Vector2i, LocationInstance>.ValueCollection GetLocationList()
+ {
+ return m_locationInstances.Values;
+ }
+}