summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Valheim_v202102/.gitignore6
-rw-r--r--Valheim_v202102/Doc/作弊.txt10
-rw-r--r--Valheim_v202102/Doc/分析.xlsxbin0 -> 1697725 bytes
-rw-r--r--Valheim_v202102/Doc/分析/地形生成.xlsxbin0 -> 18088 bytes
-rw-r--r--Valheim_v202102/Doc/反编译和mod.txt9
-rw-r--r--Valheim_v202102/Doc/说明.txt1
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/.gitignore399
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/AnimalAI.cs80
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/AnimationEffect.cs102
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Aoe.cs331
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Attack.cs988
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/AudioMan.cs496
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/AutoJumpLedge.cs19
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/BaseAI.cs1459
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Beacon.cs46
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Bed.cs201
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Beehive.cs186
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Billboard.cs37
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/BiomeEnvSetup.cs23
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/BossStone.cs111
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CamShaker.cs65
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CameraEffects.cs127
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Chair.cs73
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ChangeLog.cs15
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Character.cs2567
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CharacterAnimEvent.cs525
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CharacterDrop.cs118
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs48
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Chat.cs568
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CircleProjector.cs63
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ClutterSystem.cs472
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ConnectPanel.cs215
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Console.cs654
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Container.cs417
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CookingStation.cs363
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Corpse.cs67
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CraftingStation.cs317
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/CreatureSpawner.cs160
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DLCMan.cs98
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DamageText.cs181
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DepthCamera.cs39
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Destructible.cs213
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DestructibleType.cs7
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DistantFogEmitter.cs114
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Door.cs166
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DreamTexts.cs61
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DropOnDestroyed.cs46
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DropTable.cs152
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DungeonDB.cs105
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/DungeonGenerator.cs787
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EffectArea.cs108
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EffectFade.cs66
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EffectList.cs88
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EmitterRotation.cs37
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EnemyHud.cs216
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EnvEntry.cs12
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EnvMan.cs987
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EnvSetup.cs108
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EnvZone.cs49
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/EventZone.cs38
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Feedback.cs91
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/FejdStartup.cs1393
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Fermenter.cs342
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Fireplace.cs307
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Fish.cs373
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/FishingFloat.cs313
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Floating.cs174
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/FollowPlayer.cs37
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/FootStep.cs401
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Game.cs575
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/GameCamera.cs663
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Gibber.cs114
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/GlobalWind.cs98
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Growup.cs34
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/GuidePoint.cs28
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Heightmap.cs1111
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/HeightmapBuilder.cs273
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/HitArea.cs25
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/HitData.cs625
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/HotkeyBar.cs156
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/HoverText.cs16
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Hoverable.cs6
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Hud.cs1171
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Humanoid.cs1550
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/IDestructible.cs6
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/IEquipmentVisual.cs4
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/IProjectile.cs8
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ISocket.cs30
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/IWaterInteractable.cs10
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ImpactEffect.cs159
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/InputFieldSubmit.cs24
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/InstanceRenderer.cs176
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/InstantiatePrefab.cs22
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Interactable.cs6
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Interpolate.cs456
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Inventory.cs755
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/InventoryGrid.cs378
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/InventoryGui.cs1535
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ItemDrop.cs970
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ItemStand.cs392
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ItemStyle.cs9
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/KeyHints.cs95
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Ladder.cs50
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Ledge.cs40
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LevelEffects.cs99
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Leviathan.cs91
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LightFlicker.cs71
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LightLod.cs106
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LineAttach.cs27
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LineConnect.cs141
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Location.cs118
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LocationProxy.cs43
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LodFadeInOut.cs30
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/LootSpawner.cs89
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MasterClient.cs291
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs344
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Menu.cs131
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MenuScene.cs41
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MenuShipMovement.cs23
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MessageHud.cs305
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MineRock.cs233
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MineRock5.cs472
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Minimap.cs1463
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MistEmitter.cs91
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MonsterAI.cs744
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MovementTest.cs30
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/MusicMan.cs473
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/NavmeshTest.cs62
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ObjectDB.cs104
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Odin.cs55
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/OfferingBowl.cs213
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ParticleDecal.cs42
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs754
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Pickable.cs146
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PickableItem.cs194
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Piece.cs332
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PieceTable.cs224
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Plant.cs243
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Player.cs4732
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PlayerController.cs173
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PlayerCustomizaton.cs176
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PlayerProfile.cs444
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PointGenerator.cs70
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/PrivateArea.cs546
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Procreation.cs144
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Projectile.cs375
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs5
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Ragdoll.cs193
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandEventSystem.cs504
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomAnimation.cs101
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomEvent.cs119
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomFlyingBird.cs273
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomIdle.cs48
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomMovement.cs22
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomSpawn.cs59
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RandomSpeak.cs45
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Raven.cs563
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Recipe.cs37
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ReflectionUpdate.cs84
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Room.cs119
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RoomConnection.cs35
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RopeAttachment.cs66
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RoutedMethod.cs74
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RoutedMethodBase.cs4
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/RuneStone.cs83
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SEMan.cs321
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Burning.cs54
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Cozy.cs34
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Finder.cs71
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Frost.cs36
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Harpooned.cs128
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs36
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Poison.cs50
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Rested.cs98
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Shield.cs36
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Smoke.cs34
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Spawn.cs32
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Stats.cs322
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SE_Wet.cs41
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SceneLoader.cs23
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs93
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ServerCtrl.cs53
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Settings.cs582
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Ship.cs746
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ShipConstructor.cs58
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ShipControlls.cs175
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ShipEffects.cs150
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ShuffleClass.cs20
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Sign.cs82
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Skills.cs333
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SkillsDialog.cs56
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SleepText.cs43
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SlowUpdate.cs34
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SlowUpdater.cs41
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Smelter.cs519
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Smoke.cs128
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SmokeLod.cs5
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SmokeRenderer.cs26
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SmokeSpawner.cs73
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SnapToGround.cs63
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SpawnAbility.cs164
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SpawnArea.cs198
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SpawnOnDamaged.cs29
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SpawnSystem.cs510
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StateController.cs53
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StaticPhysics.cs122
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StaticTarget.cs80
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StationExtension.cs158
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StatusEffect.cs268
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StealthSystem.cs83
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/SteamManager.cs166
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/StoreGui.cs354
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Switch.cs56
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Tail.cs116
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Talker.cs60
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Tameable.cs239
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Teleport.cs64
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TeleportHome.cs13
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TeleportWorld.cs159
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs21
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TerrainLod.cs37
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TerrainModifier.cs246
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TestCollision.cs19
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TestSceneCharacter.cs82
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TestSceneSetup.cs13
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TextInput.cs93
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TextReceiver.cs6
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TextViewer.cs155
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TextsDialog.cs196
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ThorFly.cs24
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Thunder.cs133
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TimedDestruction.cs51
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ToggleImage.cs30
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ToggleSwitch.cs53
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TombStone.cs217
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Tracker.cs34
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Trader.cs168
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TreeBase.cs183
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/TreeLog.cs139
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Tutorial.cs64
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Vagon.cs333
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Valheim.csproj273
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Valheim.sln25
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Valkyrie.cs192
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/VariantDialog.cs58
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Vegvisir.cs38
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Version.cs101
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/VisEquipment.cs1022
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WaterMark.cs12
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WaterTrigger.cs24
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WaterVolume.cs237
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WayStone.cs71
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WearNTear.cs792
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WearNTearUpdater.cs41
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/Windmill.cs91
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/World.cs236
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/WorldGenerator.cs1069
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZBroastcast.cs174
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZConnector.cs150
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZConnector2.cs131
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZDO.cs1076
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZDOComparer.cs14
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZDOID.cs105
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZDOMan.cs1207
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZDOPool.cs69
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNat.cs32
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNet.cs1488
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNetPeer.cs44
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNetScene.cs423
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNetView.cs226
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZNtp.cs137
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZPackage.cs293
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZRoutedRpc.cs234
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZRpc.cs405
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSFX.cs219
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSocket.cs449
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSocket2.cs440
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs427
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSteamSocket.cs340
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSyncAnimation.cs217
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZSyncTransform.cs327
-rw-r--r--Valheim_v202102/Valheim/assembly_valheim/ZoneSystem.cs1712
282 files changed, 71342 insertions, 0 deletions
diff --git a/Valheim_v202102/.gitignore b/Valheim_v202102/.gitignore
new file mode 100644
index 0000000..223208c
--- /dev/null
+++ b/Valheim_v202102/.gitignore
@@ -0,0 +1,6 @@
+~*.*
+*.log
+Dump
+Valheim/MelonLoader/
+Valheim/Mods/
+Game/ \ No newline at end of file
diff --git a/Valheim_v202102/Doc/作弊.txt b/Valheim_v202102/Doc/作弊.txt
new file mode 100644
index 0000000..3daed88
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Doc/分析.xlsx b/Valheim_v202102/Doc/分析.xlsx
new file mode 100644
index 0000000..d5e5b83
--- /dev/null
+++ b/Valheim_v202102/Doc/分析.xlsx
Binary files differ
diff --git a/Valheim_v202102/Doc/分析/地形生成.xlsx b/Valheim_v202102/Doc/分析/地形生成.xlsx
new file mode 100644
index 0000000..10237e2
--- /dev/null
+++ b/Valheim_v202102/Doc/分析/地形生成.xlsx
Binary files differ
diff --git a/Valheim_v202102/Doc/反编译和mod.txt b/Valheim_v202102/Doc/反编译和mod.txt
new file mode 100644
index 0000000..229f382
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Doc/说明.txt b/Valheim_v202102/Doc/说明.txt
new file mode 100644
index 0000000..dda2762
--- /dev/null
+++ b/Valheim_v202102/Doc/说明.txt
@@ -0,0 +1 @@
+knowhow \ No newline at end of file
diff --git a/Valheim_v202102/Valheim/assembly_valheim/.gitignore b/Valheim_v202102/Valheim/assembly_valheim/.gitignore
new file mode 100644
index 0000000..a4da27a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/AnimalAI.cs b/Valheim_v202102/Valheim/assembly_valheim/AnimalAI.cs
new file mode 100644
index 0000000..8f747b4
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/AnimationEffect.cs b/Valheim_v202102/Valheim/assembly_valheim/AnimationEffect.cs
new file mode 100644
index 0000000..f77f3b2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Aoe.cs b/Valheim_v202102/Valheim/assembly_valheim/Aoe.cs
new file mode 100644
index 0000000..4f657e9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Attack.cs b/Valheim_v202102/Valheim/assembly_valheim/Attack.cs
new file mode 100644
index 0000000..fe7c100
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/AudioMan.cs b/Valheim_v202102/Valheim/assembly_valheim/AudioMan.cs
new file mode 100644
index 0000000..3c4d300
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/AutoJumpLedge.cs b/Valheim_v202102/Valheim/assembly_valheim/AutoJumpLedge.cs
new file mode 100644
index 0000000..d39ae81
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/BaseAI.cs b/Valheim_v202102/Valheim/assembly_valheim/BaseAI.cs
new file mode 100644
index 0000000..ea33b4d
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/BaseAI.cs
@@ -0,0 +1,1459 @@
+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);
+ }
+
+ 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;
+ }
+
+ 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_v202102/Valheim/assembly_valheim/Beacon.cs b/Valheim_v202102/Valheim/assembly_valheim/Beacon.cs
new file mode 100644
index 0000000..8dd7cba
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Bed.cs b/Valheim_v202102/Valheim/assembly_valheim/Bed.cs
new file mode 100644
index 0000000..2af71df
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Beehive.cs b/Valheim_v202102/Valheim/assembly_valheim/Beehive.cs
new file mode 100644
index 0000000..0e92ae1
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Billboard.cs b/Valheim_v202102/Valheim/assembly_valheim/Billboard.cs
new file mode 100644
index 0000000..108afa6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/BiomeEnvSetup.cs b/Valheim_v202102/Valheim/assembly_valheim/BiomeEnvSetup.cs
new file mode 100644
index 0000000..4ff8e60
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/BossStone.cs b/Valheim_v202102/Valheim/assembly_valheim/BossStone.cs
new file mode 100644
index 0000000..67aa52f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CamShaker.cs b/Valheim_v202102/Valheim/assembly_valheim/CamShaker.cs
new file mode 100644
index 0000000..4d661c5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CameraEffects.cs b/Valheim_v202102/Valheim/assembly_valheim/CameraEffects.cs
new file mode 100644
index 0000000..7aa1f95
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Chair.cs b/Valheim_v202102/Valheim/assembly_valheim/Chair.cs
new file mode 100644
index 0000000..09c5277
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ChangeLog.cs b/Valheim_v202102/Valheim/assembly_valheim/ChangeLog.cs
new file mode 100644
index 0000000..ff4874f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Character.cs b/Valheim_v202102/Valheim/assembly_valheim/Character.cs
new file mode 100644
index 0000000..7807218
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CharacterAnimEvent.cs b/Valheim_v202102/Valheim/assembly_valheim/CharacterAnimEvent.cs
new file mode 100644
index 0000000..8f0db87
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CharacterDrop.cs b/Valheim_v202102/Valheim/assembly_valheim/CharacterDrop.cs
new file mode 100644
index 0000000..89dfc87
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs b/Valheim_v202102/Valheim/assembly_valheim/CharacterTimedDestruction.cs
new file mode 100644
index 0000000..f4382e2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Chat.cs b/Valheim_v202102/Valheim/assembly_valheim/Chat.cs
new file mode 100644
index 0000000..4646819
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CircleProjector.cs b/Valheim_v202102/Valheim/assembly_valheim/CircleProjector.cs
new file mode 100644
index 0000000..a60fab6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ClutterSystem.cs b/Valheim_v202102/Valheim/assembly_valheim/ClutterSystem.cs
new file mode 100644
index 0000000..b08e638
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ConnectPanel.cs b/Valheim_v202102/Valheim/assembly_valheim/ConnectPanel.cs
new file mode 100644
index 0000000..cd973c6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Console.cs b/Valheim_v202102/Valheim/assembly_valheim/Console.cs
new file mode 100644
index 0000000..f2310db
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Container.cs b/Valheim_v202102/Valheim/assembly_valheim/Container.cs
new file mode 100644
index 0000000..54b8214
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CookingStation.cs b/Valheim_v202102/Valheim/assembly_valheim/CookingStation.cs
new file mode 100644
index 0000000..24fa4b0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Corpse.cs b/Valheim_v202102/Valheim/assembly_valheim/Corpse.cs
new file mode 100644
index 0000000..995e11a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CraftingStation.cs b/Valheim_v202102/Valheim/assembly_valheim/CraftingStation.cs
new file mode 100644
index 0000000..aef3ad6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/CreatureSpawner.cs b/Valheim_v202102/Valheim/assembly_valheim/CreatureSpawner.cs
new file mode 100644
index 0000000..5cc99f5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DLCMan.cs b/Valheim_v202102/Valheim/assembly_valheim/DLCMan.cs
new file mode 100644
index 0000000..b4375ec
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DamageText.cs b/Valheim_v202102/Valheim/assembly_valheim/DamageText.cs
new file mode 100644
index 0000000..bdca3fb
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DepthCamera.cs b/Valheim_v202102/Valheim/assembly_valheim/DepthCamera.cs
new file mode 100644
index 0000000..9790a6c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Destructible.cs b/Valheim_v202102/Valheim/assembly_valheim/Destructible.cs
new file mode 100644
index 0000000..e6b56a9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DestructibleType.cs b/Valheim_v202102/Valheim/assembly_valheim/DestructibleType.cs
new file mode 100644
index 0000000..8060cd9
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/DestructibleType.cs
@@ -0,0 +1,7 @@
+public enum DestructibleType
+{
+ None = 0,
+ Default = 1,
+ Tree = 2,
+ Character = 4
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/DistantFogEmitter.cs b/Valheim_v202102/Valheim/assembly_valheim/DistantFogEmitter.cs
new file mode 100644
index 0000000..fb42650
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Door.cs b/Valheim_v202102/Valheim/assembly_valheim/Door.cs
new file mode 100644
index 0000000..e9ac2b9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DreamTexts.cs b/Valheim_v202102/Valheim/assembly_valheim/DreamTexts.cs
new file mode 100644
index 0000000..4c2b44d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DropOnDestroyed.cs b/Valheim_v202102/Valheim/assembly_valheim/DropOnDestroyed.cs
new file mode 100644
index 0000000..99df9bd
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DropTable.cs b/Valheim_v202102/Valheim/assembly_valheim/DropTable.cs
new file mode 100644
index 0000000..b50151a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DungeonDB.cs b/Valheim_v202102/Valheim/assembly_valheim/DungeonDB.cs
new file mode 100644
index 0000000..d6a7d35
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/DungeonGenerator.cs b/Valheim_v202102/Valheim/assembly_valheim/DungeonGenerator.cs
new file mode 100644
index 0000000..f7a73aa
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EffectArea.cs b/Valheim_v202102/Valheim/assembly_valheim/EffectArea.cs
new file mode 100644
index 0000000..0fbedb1
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EffectFade.cs b/Valheim_v202102/Valheim/assembly_valheim/EffectFade.cs
new file mode 100644
index 0000000..cefd3a0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EffectList.cs b/Valheim_v202102/Valheim/assembly_valheim/EffectList.cs
new file mode 100644
index 0000000..61350b6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EmitterRotation.cs b/Valheim_v202102/Valheim/assembly_valheim/EmitterRotation.cs
new file mode 100644
index 0000000..41fe5e5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EnemyHud.cs b/Valheim_v202102/Valheim/assembly_valheim/EnemyHud.cs
new file mode 100644
index 0000000..3c4802a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EnvEntry.cs b/Valheim_v202102/Valheim/assembly_valheim/EnvEntry.cs
new file mode 100644
index 0000000..e21e0fe
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EnvMan.cs b/Valheim_v202102/Valheim/assembly_valheim/EnvMan.cs
new file mode 100644
index 0000000..7119264
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EnvSetup.cs b/Valheim_v202102/Valheim/assembly_valheim/EnvSetup.cs
new file mode 100644
index 0000000..deb01ad
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EnvZone.cs b/Valheim_v202102/Valheim/assembly_valheim/EnvZone.cs
new file mode 100644
index 0000000..210d6e5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/EventZone.cs b/Valheim_v202102/Valheim/assembly_valheim/EventZone.cs
new file mode 100644
index 0000000..3601944
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Feedback.cs b/Valheim_v202102/Valheim/assembly_valheim/Feedback.cs
new file mode 100644
index 0000000..05a7db3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/FejdStartup.cs b/Valheim_v202102/Valheim/assembly_valheim/FejdStartup.cs
new file mode 100644
index 0000000..3de4355
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Fermenter.cs b/Valheim_v202102/Valheim/assembly_valheim/Fermenter.cs
new file mode 100644
index 0000000..d4a1dde
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Fireplace.cs b/Valheim_v202102/Valheim/assembly_valheim/Fireplace.cs
new file mode 100644
index 0000000..6cc6478
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Fish.cs b/Valheim_v202102/Valheim/assembly_valheim/Fish.cs
new file mode 100644
index 0000000..8c88937
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/FishingFloat.cs b/Valheim_v202102/Valheim/assembly_valheim/FishingFloat.cs
new file mode 100644
index 0000000..735f68b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Floating.cs b/Valheim_v202102/Valheim/assembly_valheim/Floating.cs
new file mode 100644
index 0000000..de3b5ff
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/FollowPlayer.cs b/Valheim_v202102/Valheim/assembly_valheim/FollowPlayer.cs
new file mode 100644
index 0000000..d5c2992
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/FootStep.cs b/Valheim_v202102/Valheim/assembly_valheim/FootStep.cs
new file mode 100644
index 0000000..711bd91
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Game.cs b/Valheim_v202102/Valheim/assembly_valheim/Game.cs
new file mode 100644
index 0000000..ce6806a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/GameCamera.cs b/Valheim_v202102/Valheim/assembly_valheim/GameCamera.cs
new file mode 100644
index 0000000..82f2d5e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Gibber.cs b/Valheim_v202102/Valheim/assembly_valheim/Gibber.cs
new file mode 100644
index 0000000..1f1c196
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/GlobalWind.cs b/Valheim_v202102/Valheim/assembly_valheim/GlobalWind.cs
new file mode 100644
index 0000000..c0d50a6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Growup.cs b/Valheim_v202102/Valheim/assembly_valheim/Growup.cs
new file mode 100644
index 0000000..b04c2bf
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/GuidePoint.cs b/Valheim_v202102/Valheim/assembly_valheim/GuidePoint.cs
new file mode 100644
index 0000000..23ec869
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Heightmap.cs b/Valheim_v202102/Valheim/assembly_valheim/Heightmap.cs
new file mode 100644
index 0000000..b498b19
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/HeightmapBuilder.cs b/Valheim_v202102/Valheim/assembly_valheim/HeightmapBuilder.cs
new file mode 100644
index 0000000..6fab0cc
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/HitArea.cs b/Valheim_v202102/Valheim/assembly_valheim/HitArea.cs
new file mode 100644
index 0000000..3e89592
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/HitData.cs b/Valheim_v202102/Valheim/assembly_valheim/HitData.cs
new file mode 100644
index 0000000..fc6a332
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/HotkeyBar.cs b/Valheim_v202102/Valheim/assembly_valheim/HotkeyBar.cs
new file mode 100644
index 0000000..c884d08
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/HoverText.cs b/Valheim_v202102/Valheim/assembly_valheim/HoverText.cs
new file mode 100644
index 0000000..5cf4f59
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Hoverable.cs b/Valheim_v202102/Valheim/assembly_valheim/Hoverable.cs
new file mode 100644
index 0000000..a340096
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/Hoverable.cs
@@ -0,0 +1,6 @@
+public interface Hoverable
+{
+ string GetHoverText();
+
+ string GetHoverName();
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/Hud.cs b/Valheim_v202102/Valheim/assembly_valheim/Hud.cs
new file mode 100644
index 0000000..facecda
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Humanoid.cs b/Valheim_v202102/Valheim/assembly_valheim/Humanoid.cs
new file mode 100644
index 0000000..501fe2b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/IDestructible.cs b/Valheim_v202102/Valheim/assembly_valheim/IDestructible.cs
new file mode 100644
index 0000000..6d82fb1
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/IDestructible.cs
@@ -0,0 +1,6 @@
+public interface IDestructible
+{
+ void Damage(HitData hit);
+
+ DestructibleType GetDestructibleType();
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/IEquipmentVisual.cs b/Valheim_v202102/Valheim/assembly_valheim/IEquipmentVisual.cs
new file mode 100644
index 0000000..7d4b4c2
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/IEquipmentVisual.cs
@@ -0,0 +1,4 @@
+internal interface IEquipmentVisual
+{
+ void Setup(int style);
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/IProjectile.cs b/Valheim_v202102/Valheim/assembly_valheim/IProjectile.cs
new file mode 100644
index 0000000..81f27cf
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ISocket.cs b/Valheim_v202102/Valheim/assembly_valheim/ISocket.cs
new file mode 100644
index 0000000..f6ca9b7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/IWaterInteractable.cs b/Valheim_v202102/Valheim/assembly_valheim/IWaterInteractable.cs
new file mode 100644
index 0000000..02008ce
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ImpactEffect.cs b/Valheim_v202102/Valheim/assembly_valheim/ImpactEffect.cs
new file mode 100644
index 0000000..4beca90
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/InputFieldSubmit.cs b/Valheim_v202102/Valheim/assembly_valheim/InputFieldSubmit.cs
new file mode 100644
index 0000000..1a8ac47
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/InstanceRenderer.cs b/Valheim_v202102/Valheim/assembly_valheim/InstanceRenderer.cs
new file mode 100644
index 0000000..3ced0a9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/InstantiatePrefab.cs b/Valheim_v202102/Valheim/assembly_valheim/InstantiatePrefab.cs
new file mode 100644
index 0000000..eb2c331
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Interactable.cs b/Valheim_v202102/Valheim/assembly_valheim/Interactable.cs
new file mode 100644
index 0000000..6d603a0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Interpolate.cs b/Valheim_v202102/Valheim/assembly_valheim/Interpolate.cs
new file mode 100644
index 0000000..d393f29
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Inventory.cs b/Valheim_v202102/Valheim/assembly_valheim/Inventory.cs
new file mode 100644
index 0000000..f31d5d5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/InventoryGrid.cs b/Valheim_v202102/Valheim/assembly_valheim/InventoryGrid.cs
new file mode 100644
index 0000000..1cec964
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/InventoryGui.cs b/Valheim_v202102/Valheim/assembly_valheim/InventoryGui.cs
new file mode 100644
index 0000000..c9e63e3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ItemDrop.cs b/Valheim_v202102/Valheim/assembly_valheim/ItemDrop.cs
new file mode 100644
index 0000000..55e21cb
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ItemStand.cs b/Valheim_v202102/Valheim/assembly_valheim/ItemStand.cs
new file mode 100644
index 0000000..f068855
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ItemStyle.cs b/Valheim_v202102/Valheim/assembly_valheim/ItemStyle.cs
new file mode 100644
index 0000000..eefa038
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/KeyHints.cs b/Valheim_v202102/Valheim/assembly_valheim/KeyHints.cs
new file mode 100644
index 0000000..176f9fc
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Ladder.cs b/Valheim_v202102/Valheim/assembly_valheim/Ladder.cs
new file mode 100644
index 0000000..e139dde
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Ledge.cs b/Valheim_v202102/Valheim/assembly_valheim/Ledge.cs
new file mode 100644
index 0000000..dd78829
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LevelEffects.cs b/Valheim_v202102/Valheim/assembly_valheim/LevelEffects.cs
new file mode 100644
index 0000000..9cb9333
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Leviathan.cs b/Valheim_v202102/Valheim/assembly_valheim/Leviathan.cs
new file mode 100644
index 0000000..1a7a21c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LightFlicker.cs b/Valheim_v202102/Valheim/assembly_valheim/LightFlicker.cs
new file mode 100644
index 0000000..c2b944c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LightLod.cs b/Valheim_v202102/Valheim/assembly_valheim/LightLod.cs
new file mode 100644
index 0000000..9f8ab8f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LineAttach.cs b/Valheim_v202102/Valheim/assembly_valheim/LineAttach.cs
new file mode 100644
index 0000000..3fcbc50
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LineConnect.cs b/Valheim_v202102/Valheim/assembly_valheim/LineConnect.cs
new file mode 100644
index 0000000..e2f9298
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Location.cs b/Valheim_v202102/Valheim/assembly_valheim/Location.cs
new file mode 100644
index 0000000..1cb1b0c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LocationProxy.cs b/Valheim_v202102/Valheim/assembly_valheim/LocationProxy.cs
new file mode 100644
index 0000000..2ff2833
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LodFadeInOut.cs b/Valheim_v202102/Valheim/assembly_valheim/LodFadeInOut.cs
new file mode 100644
index 0000000..ae4d2dd
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/LootSpawner.cs b/Valheim_v202102/Valheim/assembly_valheim/LootSpawner.cs
new file mode 100644
index 0000000..5488631
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MasterClient.cs b/Valheim_v202102/Valheim/assembly_valheim/MasterClient.cs
new file mode 100644
index 0000000..ce770bd
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs b/Valheim_v202102/Valheim/assembly_valheim/MeleeWeaponTrail.cs
new file mode 100644
index 0000000..1b0f539
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Menu.cs b/Valheim_v202102/Valheim/assembly_valheim/Menu.cs
new file mode 100644
index 0000000..0ab76a7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MenuScene.cs b/Valheim_v202102/Valheim/assembly_valheim/MenuScene.cs
new file mode 100644
index 0000000..6a14e0e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MenuShipMovement.cs b/Valheim_v202102/Valheim/assembly_valheim/MenuShipMovement.cs
new file mode 100644
index 0000000..22ebd04
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MessageHud.cs b/Valheim_v202102/Valheim/assembly_valheim/MessageHud.cs
new file mode 100644
index 0000000..26ed8af
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MineRock.cs b/Valheim_v202102/Valheim/assembly_valheim/MineRock.cs
new file mode 100644
index 0000000..e177734
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MineRock5.cs b/Valheim_v202102/Valheim/assembly_valheim/MineRock5.cs
new file mode 100644
index 0000000..c250c15
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Minimap.cs b/Valheim_v202102/Valheim/assembly_valheim/Minimap.cs
new file mode 100644
index 0000000..3b7cefe
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MistEmitter.cs b/Valheim_v202102/Valheim/assembly_valheim/MistEmitter.cs
new file mode 100644
index 0000000..ba59986
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MonsterAI.cs b/Valheim_v202102/Valheim/assembly_valheim/MonsterAI.cs
new file mode 100644
index 0000000..1c72d80
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MovementTest.cs b/Valheim_v202102/Valheim/assembly_valheim/MovementTest.cs
new file mode 100644
index 0000000..4ac6ec2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/MusicMan.cs b/Valheim_v202102/Valheim/assembly_valheim/MusicMan.cs
new file mode 100644
index 0000000..e5735f4
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/NavmeshTest.cs b/Valheim_v202102/Valheim/assembly_valheim/NavmeshTest.cs
new file mode 100644
index 0000000..c0b4a0c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ObjectDB.cs b/Valheim_v202102/Valheim/assembly_valheim/ObjectDB.cs
new file mode 100644
index 0000000..46c0f5c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Odin.cs b/Valheim_v202102/Valheim/assembly_valheim/Odin.cs
new file mode 100644
index 0000000..7a82e11
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/OfferingBowl.cs b/Valheim_v202102/Valheim/assembly_valheim/OfferingBowl.cs
new file mode 100644
index 0000000..8f361b3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ParticleDecal.cs b/Valheim_v202102/Valheim/assembly_valheim/ParticleDecal.cs
new file mode 100644
index 0000000..f9bf10e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Pathfinding.cs b/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs
new file mode 100644
index 0000000..8db3b1b
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/Pathfinding.cs
@@ -0,0 +1,754 @@
+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_v202102/Valheim/assembly_valheim/Pickable.cs b/Valheim_v202102/Valheim/assembly_valheim/Pickable.cs
new file mode 100644
index 0000000..23d83db
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PickableItem.cs b/Valheim_v202102/Valheim/assembly_valheim/PickableItem.cs
new file mode 100644
index 0000000..10d4fdd
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Piece.cs b/Valheim_v202102/Valheim/assembly_valheim/Piece.cs
new file mode 100644
index 0000000..1ba0993
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PieceTable.cs b/Valheim_v202102/Valheim/assembly_valheim/PieceTable.cs
new file mode 100644
index 0000000..17944e2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Plant.cs b/Valheim_v202102/Valheim/assembly_valheim/Plant.cs
new file mode 100644
index 0000000..bc11954
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Player.cs b/Valheim_v202102/Valheim/assembly_valheim/Player.cs
new file mode 100644
index 0000000..da847cc
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PlayerController.cs b/Valheim_v202102/Valheim/assembly_valheim/PlayerController.cs
new file mode 100644
index 0000000..d589690
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PlayerCustomizaton.cs b/Valheim_v202102/Valheim/assembly_valheim/PlayerCustomizaton.cs
new file mode 100644
index 0000000..6113453
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PlayerProfile.cs b/Valheim_v202102/Valheim/assembly_valheim/PlayerProfile.cs
new file mode 100644
index 0000000..8ab7849
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PointGenerator.cs b/Valheim_v202102/Valheim/assembly_valheim/PointGenerator.cs
new file mode 100644
index 0000000..ef338e7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/PrivateArea.cs b/Valheim_v202102/Valheim/assembly_valheim/PrivateArea.cs
new file mode 100644
index 0000000..448f69c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Procreation.cs b/Valheim_v202102/Valheim/assembly_valheim/Procreation.cs
new file mode 100644
index 0000000..1ec5aa3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Projectile.cs b/Valheim_v202102/Valheim/assembly_valheim/Projectile.cs
new file mode 100644
index 0000000..e2f8eac
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs b/Valheim_v202102/Valheim/assembly_valheim/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbd7eef
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Ragdoll.cs b/Valheim_v202102/Valheim/assembly_valheim/Ragdoll.cs
new file mode 100644
index 0000000..fd7b3a1
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandEventSystem.cs b/Valheim_v202102/Valheim/assembly_valheim/RandEventSystem.cs
new file mode 100644
index 0000000..e048ba7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomAnimation.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomAnimation.cs
new file mode 100644
index 0000000..4ed5f23
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomEvent.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomEvent.cs
new file mode 100644
index 0000000..8e6df2d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomFlyingBird.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomFlyingBird.cs
new file mode 100644
index 0000000..a47db33
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomIdle.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomIdle.cs
new file mode 100644
index 0000000..ca1f094
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomMovement.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomMovement.cs
new file mode 100644
index 0000000..6f273d2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomSpawn.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomSpawn.cs
new file mode 100644
index 0000000..9038073
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RandomSpeak.cs b/Valheim_v202102/Valheim/assembly_valheim/RandomSpeak.cs
new file mode 100644
index 0000000..b879931
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Raven.cs b/Valheim_v202102/Valheim/assembly_valheim/Raven.cs
new file mode 100644
index 0000000..69335b7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Recipe.cs b/Valheim_v202102/Valheim/assembly_valheim/Recipe.cs
new file mode 100644
index 0000000..c3d2bc0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ReflectionUpdate.cs b/Valheim_v202102/Valheim/assembly_valheim/ReflectionUpdate.cs
new file mode 100644
index 0000000..d88d045
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Room.cs b/Valheim_v202102/Valheim/assembly_valheim/Room.cs
new file mode 100644
index 0000000..31dc7e6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RoomConnection.cs b/Valheim_v202102/Valheim/assembly_valheim/RoomConnection.cs
new file mode 100644
index 0000000..36d0285
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RopeAttachment.cs b/Valheim_v202102/Valheim/assembly_valheim/RopeAttachment.cs
new file mode 100644
index 0000000..893038a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RoutedMethod.cs b/Valheim_v202102/Valheim/assembly_valheim/RoutedMethod.cs
new file mode 100644
index 0000000..1db0574
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/RoutedMethodBase.cs b/Valheim_v202102/Valheim/assembly_valheim/RoutedMethodBase.cs
new file mode 100644
index 0000000..1039b5d
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/RoutedMethodBase.cs
@@ -0,0 +1,4 @@
+internal interface RoutedMethodBase
+{
+ void Invoke(long rpc, ZPackage pkg);
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/RuneStone.cs b/Valheim_v202102/Valheim/assembly_valheim/RuneStone.cs
new file mode 100644
index 0000000..c245a30
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SEMan.cs b/Valheim_v202102/Valheim/assembly_valheim/SEMan.cs
new file mode 100644
index 0000000..6788e8b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Burning.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Burning.cs
new file mode 100644
index 0000000..c49db65
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Cozy.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Cozy.cs
new file mode 100644
index 0000000..20ecf8c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Finder.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Finder.cs
new file mode 100644
index 0000000..d38cb25
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Frost.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Frost.cs
new file mode 100644
index 0000000..e988a7d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Harpooned.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Harpooned.cs
new file mode 100644
index 0000000..b145556
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_HealthUpgrade.cs
new file mode 100644
index 0000000..a733ac9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Poison.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Poison.cs
new file mode 100644
index 0000000..7da4506
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Rested.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Rested.cs
new file mode 100644
index 0000000..8af611f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Shield.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Shield.cs
new file mode 100644
index 0000000..0fd1124
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Smoke.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Smoke.cs
new file mode 100644
index 0000000..bc47a88
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Spawn.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Spawn.cs
new file mode 100644
index 0000000..0a8ec6c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Stats.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Stats.cs
new file mode 100644
index 0000000..91aab87
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SE_Wet.cs b/Valheim_v202102/Valheim/assembly_valheim/SE_Wet.cs
new file mode 100644
index 0000000..a501d1b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SceneLoader.cs b/Valheim_v202102/Valheim/assembly_valheim/SceneLoader.cs
new file mode 100644
index 0000000..c5f0faf
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs b/Valheim_v202102/Valheim/assembly_valheim/ScrollRectEnsureVisible.cs
new file mode 100644
index 0000000..b0c807d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ServerCtrl.cs b/Valheim_v202102/Valheim/assembly_valheim/ServerCtrl.cs
new file mode 100644
index 0000000..7ce8e7c
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Settings.cs b/Valheim_v202102/Valheim/assembly_valheim/Settings.cs
new file mode 100644
index 0000000..066f8f6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Ship.cs b/Valheim_v202102/Valheim/assembly_valheim/Ship.cs
new file mode 100644
index 0000000..7ad6482
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ShipConstructor.cs b/Valheim_v202102/Valheim/assembly_valheim/ShipConstructor.cs
new file mode 100644
index 0000000..b754868
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ShipControlls.cs b/Valheim_v202102/Valheim/assembly_valheim/ShipControlls.cs
new file mode 100644
index 0000000..c8911ed
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ShipEffects.cs b/Valheim_v202102/Valheim/assembly_valheim/ShipEffects.cs
new file mode 100644
index 0000000..d7bf567
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ShuffleClass.cs b/Valheim_v202102/Valheim/assembly_valheim/ShuffleClass.cs
new file mode 100644
index 0000000..5787a18
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Sign.cs b/Valheim_v202102/Valheim/assembly_valheim/Sign.cs
new file mode 100644
index 0000000..04e91d9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Skills.cs b/Valheim_v202102/Valheim/assembly_valheim/Skills.cs
new file mode 100644
index 0000000..642f867
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SkillsDialog.cs b/Valheim_v202102/Valheim/assembly_valheim/SkillsDialog.cs
new file mode 100644
index 0000000..01f8e66
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SleepText.cs b/Valheim_v202102/Valheim/assembly_valheim/SleepText.cs
new file mode 100644
index 0000000..1566d30
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SlowUpdate.cs b/Valheim_v202102/Valheim/assembly_valheim/SlowUpdate.cs
new file mode 100644
index 0000000..2871f3d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SlowUpdater.cs b/Valheim_v202102/Valheim/assembly_valheim/SlowUpdater.cs
new file mode 100644
index 0000000..b97b1ee
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Smelter.cs b/Valheim_v202102/Valheim/assembly_valheim/Smelter.cs
new file mode 100644
index 0000000..c35b772
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Smoke.cs b/Valheim_v202102/Valheim/assembly_valheim/Smoke.cs
new file mode 100644
index 0000000..01dfa2e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SmokeLod.cs b/Valheim_v202102/Valheim/assembly_valheim/SmokeLod.cs
new file mode 100644
index 0000000..2ae82c0
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/SmokeLod.cs
@@ -0,0 +1,5 @@
+using UnityEngine;
+
+public class SmokeLod : MonoBehaviour
+{
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/SmokeRenderer.cs b/Valheim_v202102/Valheim/assembly_valheim/SmokeRenderer.cs
new file mode 100644
index 0000000..474f921
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SmokeSpawner.cs b/Valheim_v202102/Valheim/assembly_valheim/SmokeSpawner.cs
new file mode 100644
index 0000000..8787c56
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SnapToGround.cs b/Valheim_v202102/Valheim/assembly_valheim/SnapToGround.cs
new file mode 100644
index 0000000..2aa1ad8
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SpawnAbility.cs b/Valheim_v202102/Valheim/assembly_valheim/SpawnAbility.cs
new file mode 100644
index 0000000..f71dfcf
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SpawnArea.cs b/Valheim_v202102/Valheim/assembly_valheim/SpawnArea.cs
new file mode 100644
index 0000000..1a052fa
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SpawnOnDamaged.cs b/Valheim_v202102/Valheim/assembly_valheim/SpawnOnDamaged.cs
new file mode 100644
index 0000000..a334005
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SpawnSystem.cs b/Valheim_v202102/Valheim/assembly_valheim/SpawnSystem.cs
new file mode 100644
index 0000000..8b5fa4a
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StateController.cs b/Valheim_v202102/Valheim/assembly_valheim/StateController.cs
new file mode 100644
index 0000000..1e97056
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StaticPhysics.cs b/Valheim_v202102/Valheim/assembly_valheim/StaticPhysics.cs
new file mode 100644
index 0000000..47a4685
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StaticTarget.cs b/Valheim_v202102/Valheim/assembly_valheim/StaticTarget.cs
new file mode 100644
index 0000000..a538dc5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StationExtension.cs b/Valheim_v202102/Valheim/assembly_valheim/StationExtension.cs
new file mode 100644
index 0000000..321c548
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StatusEffect.cs b/Valheim_v202102/Valheim/assembly_valheim/StatusEffect.cs
new file mode 100644
index 0000000..40ba74b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StealthSystem.cs b/Valheim_v202102/Valheim/assembly_valheim/StealthSystem.cs
new file mode 100644
index 0000000..774ca07
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/SteamManager.cs b/Valheim_v202102/Valheim/assembly_valheim/SteamManager.cs
new file mode 100644
index 0000000..7866906
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/StoreGui.cs b/Valheim_v202102/Valheim/assembly_valheim/StoreGui.cs
new file mode 100644
index 0000000..8ea6962
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Switch.cs b/Valheim_v202102/Valheim/assembly_valheim/Switch.cs
new file mode 100644
index 0000000..9b18b0d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Tail.cs b/Valheim_v202102/Valheim/assembly_valheim/Tail.cs
new file mode 100644
index 0000000..ab17b28
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Talker.cs b/Valheim_v202102/Valheim/assembly_valheim/Talker.cs
new file mode 100644
index 0000000..7d1c361
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Tameable.cs b/Valheim_v202102/Valheim/assembly_valheim/Tameable.cs
new file mode 100644
index 0000000..3f418c0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Teleport.cs b/Valheim_v202102/Valheim/assembly_valheim/Teleport.cs
new file mode 100644
index 0000000..a395fb7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TeleportHome.cs b/Valheim_v202102/Valheim/assembly_valheim/TeleportHome.cs
new file mode 100644
index 0000000..fc411a3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TeleportWorld.cs b/Valheim_v202102/Valheim/assembly_valheim/TeleportWorld.cs
new file mode 100644
index 0000000..e5be540
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs b/Valheim_v202102/Valheim/assembly_valheim/TeleportWorldTrigger.cs
new file mode 100644
index 0000000..97f28a7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TerrainLod.cs b/Valheim_v202102/Valheim/assembly_valheim/TerrainLod.cs
new file mode 100644
index 0000000..99402d7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TerrainModifier.cs b/Valheim_v202102/Valheim/assembly_valheim/TerrainModifier.cs
new file mode 100644
index 0000000..9804830
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TestCollision.cs b/Valheim_v202102/Valheim/assembly_valheim/TestCollision.cs
new file mode 100644
index 0000000..29ca07f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TestSceneCharacter.cs b/Valheim_v202102/Valheim/assembly_valheim/TestSceneCharacter.cs
new file mode 100644
index 0000000..95f1742
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TestSceneSetup.cs b/Valheim_v202102/Valheim/assembly_valheim/TestSceneSetup.cs
new file mode 100644
index 0000000..e8cc282
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TextInput.cs b/Valheim_v202102/Valheim/assembly_valheim/TextInput.cs
new file mode 100644
index 0000000..419d21f
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TextReceiver.cs b/Valheim_v202102/Valheim/assembly_valheim/TextReceiver.cs
new file mode 100644
index 0000000..33507c5
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/TextReceiver.cs
@@ -0,0 +1,6 @@
+public interface TextReceiver
+{
+ string GetText();
+
+ void SetText(string text);
+}
diff --git a/Valheim_v202102/Valheim/assembly_valheim/TextViewer.cs b/Valheim_v202102/Valheim/assembly_valheim/TextViewer.cs
new file mode 100644
index 0000000..9e41172
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TextsDialog.cs b/Valheim_v202102/Valheim/assembly_valheim/TextsDialog.cs
new file mode 100644
index 0000000..da3a792
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ThorFly.cs b/Valheim_v202102/Valheim/assembly_valheim/ThorFly.cs
new file mode 100644
index 0000000..a24de60
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Thunder.cs b/Valheim_v202102/Valheim/assembly_valheim/Thunder.cs
new file mode 100644
index 0000000..6b7198e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TimedDestruction.cs b/Valheim_v202102/Valheim/assembly_valheim/TimedDestruction.cs
new file mode 100644
index 0000000..55f4e73
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ToggleImage.cs b/Valheim_v202102/Valheim/assembly_valheim/ToggleImage.cs
new file mode 100644
index 0000000..6c0f5c6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ToggleSwitch.cs b/Valheim_v202102/Valheim/assembly_valheim/ToggleSwitch.cs
new file mode 100644
index 0000000..bc0f4aa
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TombStone.cs b/Valheim_v202102/Valheim/assembly_valheim/TombStone.cs
new file mode 100644
index 0000000..dd74763
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Tracker.cs b/Valheim_v202102/Valheim/assembly_valheim/Tracker.cs
new file mode 100644
index 0000000..f9aaed8
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Trader.cs b/Valheim_v202102/Valheim/assembly_valheim/Trader.cs
new file mode 100644
index 0000000..cb5289e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TreeBase.cs b/Valheim_v202102/Valheim/assembly_valheim/TreeBase.cs
new file mode 100644
index 0000000..4126c97
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/TreeLog.cs b/Valheim_v202102/Valheim/assembly_valheim/TreeLog.cs
new file mode 100644
index 0000000..a2ec07b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Tutorial.cs b/Valheim_v202102/Valheim/assembly_valheim/Tutorial.cs
new file mode 100644
index 0000000..564d399
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Vagon.cs b/Valheim_v202102/Valheim/assembly_valheim/Vagon.cs
new file mode 100644
index 0000000..8539bf3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Valheim.csproj b/Valheim_v202102/Valheim/assembly_valheim/Valheim.csproj
new file mode 100644
index 0000000..f3dd810
--- /dev/null
+++ b/Valheim_v202102/Valheim/assembly_valheim/Valheim.csproj
@@ -0,0 +1,273 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>assembly_valheim</AssemblyName>
+ <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
+ <TargetFramework>net40</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <LangVersion>11.0</LangVersion>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup />
+ <ItemGroup>
+ <Reference Include="assembly_googleanalytics">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_googleanalytics.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_guiutils">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_guiutils.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_lux">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_lux.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_postprocessing">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_postprocessing.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_simplemeshcombine">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_simplemeshcombine.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_steamworks">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_steamworks.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_sunshafts">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_sunshafts.dll</HintPath>
+ </Reference>
+ <Reference Include="assembly_utils">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\assembly_utils.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Security">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\Mono.Security.dll</HintPath>
+ </Reference>
+ <Reference Include="mscorlib">
+ <HintPath>..\Valheim\valheim_Data\Managed\mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="netstandard">
+ <HintPath>..\..\Valheim\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>..\..\Valheim\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>..\..\Valheim\valheim_Data\Managed\System.Globalization.Extensions.dll</HintPath>
+ </Reference>
+ <Reference Include="System.IO.Compression">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\System.IO.Compression.dll</HintPath>
+ </Reference>
+ <Reference Include="System.IO.Compression.FileSystem">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\System.IO.Compression.FileSystem.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\System.Net.Http.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Runtime.Serialization.Xml">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\System.Runtime.Serialization.Xml.dll</HintPath>
+ </Reference>
+ <Reference Include="System.ServiceModel.Internals">
+ <HintPath>..\..\Valheim\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>..\..\Valheim\valheim_Data\Managed\System.Xml.XPath.XDocument.dll</HintPath>
+ </Reference>
+ <Reference Include="Unity.TextMeshPro">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\Unity.TextMeshPro.dll</HintPath>
+ </Reference>
+ <Reference Include="Unity.Timeline">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\Unity.Timeline.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AccessibilityModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AIModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AndroidJNIModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AndroidJNIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AnimationModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ARModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ARModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AssetBundleModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AudioModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClothModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ClothModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClusterInputModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ClusterInputModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ClusterRendererModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ClusterRendererModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.CrashReportingModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.CrashReportingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.DirectorModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.DirectorModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.DSPGraphModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.DSPGraphModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.GameCenterModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.GameCenterModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.GridModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.GridModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.HotReloadModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.HotReloadModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ImageConversionModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.IMGUIModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputLegacyModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.InputModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.InputModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.JSONSerializeModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.JSONSerializeModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.LocalizationModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.LocalizationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ParticleSystemModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PerformanceReportingModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.PerformanceReportingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.Physics2DModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.PhysicsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ProfilerModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ProfilerModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ScreenCaptureModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SharedInternalsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.SharedInternalsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SpriteMaskModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SpriteShapeModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.SpriteShapeModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.StreamingModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.StreamingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SubstanceModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.SubstanceModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SubsystemsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.SubsystemsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TerrainModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TerrainModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TerrainPhysicsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TerrainPhysicsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TextCoreModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TextRenderingModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TilemapModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TilemapModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.TLSModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UI">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UI.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UIElementsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UIModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UIModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UmbraModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UmbraModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UNETModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityAnalyticsModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityConnectModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityConnectModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityTestProtocolModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityTestProtocolModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestAssetBundleModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestAudioModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestTextureModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityWebRequestWWWModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VehiclesModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.VehiclesModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VFXModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.VFXModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VideoModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.VRModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.VRModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.WindModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.WindModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.XRModule">
+ <HintPath>..\..\Valheim\valheim_Data\Managed\UnityEngine.XRModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Valheim_v202102/Valheim/assembly_valheim/Valheim.sln b/Valheim_v202102/Valheim/assembly_valheim/Valheim.sln
new file mode 100644
index 0000000..f4adca7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Valkyrie.cs b/Valheim_v202102/Valheim/assembly_valheim/Valkyrie.cs
new file mode 100644
index 0000000..ee2aa56
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/VariantDialog.cs b/Valheim_v202102/Valheim/assembly_valheim/VariantDialog.cs
new file mode 100644
index 0000000..30f3ea6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Vegvisir.cs b/Valheim_v202102/Valheim/assembly_valheim/Vegvisir.cs
new file mode 100644
index 0000000..7e8ccb3
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Version.cs b/Valheim_v202102/Valheim/assembly_valheim/Version.cs
new file mode 100644
index 0000000..9c05fc7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/VisEquipment.cs b/Valheim_v202102/Valheim/assembly_valheim/VisEquipment.cs
new file mode 100644
index 0000000..7eba531
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WaterMark.cs b/Valheim_v202102/Valheim/assembly_valheim/WaterMark.cs
new file mode 100644
index 0000000..92bf3f9
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WaterTrigger.cs b/Valheim_v202102/Valheim/assembly_valheim/WaterTrigger.cs
new file mode 100644
index 0000000..4d100a6
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WaterVolume.cs b/Valheim_v202102/Valheim/assembly_valheim/WaterVolume.cs
new file mode 100644
index 0000000..40187f2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WayStone.cs b/Valheim_v202102/Valheim/assembly_valheim/WayStone.cs
new file mode 100644
index 0000000..21f0be7
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WearNTear.cs b/Valheim_v202102/Valheim/assembly_valheim/WearNTear.cs
new file mode 100644
index 0000000..118ba82
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WearNTearUpdater.cs b/Valheim_v202102/Valheim/assembly_valheim/WearNTearUpdater.cs
new file mode 100644
index 0000000..8225e2e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/Windmill.cs b/Valheim_v202102/Valheim/assembly_valheim/Windmill.cs
new file mode 100644
index 0000000..1420e82
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/World.cs b/Valheim_v202102/Valheim/assembly_valheim/World.cs
new file mode 100644
index 0000000..6fb1408
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/WorldGenerator.cs b/Valheim_v202102/Valheim/assembly_valheim/WorldGenerator.cs
new file mode 100644
index 0000000..7d96344
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZBroastcast.cs b/Valheim_v202102/Valheim/assembly_valheim/ZBroastcast.cs
new file mode 100644
index 0000000..a33eb77
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZConnector.cs b/Valheim_v202102/Valheim/assembly_valheim/ZConnector.cs
new file mode 100644
index 0000000..9c23678
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZConnector2.cs b/Valheim_v202102/Valheim/assembly_valheim/ZConnector2.cs
new file mode 100644
index 0000000..0643547
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZDO.cs b/Valheim_v202102/Valheim/assembly_valheim/ZDO.cs
new file mode 100644
index 0000000..d592aab
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZDOComparer.cs b/Valheim_v202102/Valheim/assembly_valheim/ZDOComparer.cs
new file mode 100644
index 0000000..68aad96
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZDOID.cs b/Valheim_v202102/Valheim/assembly_valheim/ZDOID.cs
new file mode 100644
index 0000000..6814e25
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZDOMan.cs b/Valheim_v202102/Valheim/assembly_valheim/ZDOMan.cs
new file mode 100644
index 0000000..7544039
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZDOPool.cs b/Valheim_v202102/Valheim/assembly_valheim/ZDOPool.cs
new file mode 100644
index 0000000..57c477e
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNat.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNat.cs
new file mode 100644
index 0000000..058cb86
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNet.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNet.cs
new file mode 100644
index 0000000..9306206
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNetPeer.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNetPeer.cs
new file mode 100644
index 0000000..a2c2482
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNetScene.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNetScene.cs
new file mode 100644
index 0000000..ae853c5
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNetView.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNetView.cs
new file mode 100644
index 0000000..c5879ae
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZNtp.cs b/Valheim_v202102/Valheim/assembly_valheim/ZNtp.cs
new file mode 100644
index 0000000..f04cb95
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZPackage.cs b/Valheim_v202102/Valheim/assembly_valheim/ZPackage.cs
new file mode 100644
index 0000000..2151732
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZRoutedRpc.cs b/Valheim_v202102/Valheim/assembly_valheim/ZRoutedRpc.cs
new file mode 100644
index 0000000..8a9536b
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZRpc.cs b/Valheim_v202102/Valheim/assembly_valheim/ZRpc.cs
new file mode 100644
index 0000000..319f033
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSFX.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSFX.cs
new file mode 100644
index 0000000..63294ab
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSocket.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSocket.cs
new file mode 100644
index 0000000..f2a2f35
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSocket2.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSocket2.cs
new file mode 100644
index 0000000..887648d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSteamMatchmaking.cs
new file mode 100644
index 0000000..45811a2
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSteamSocket.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSteamSocket.cs
new file mode 100644
index 0000000..30a271d
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSyncAnimation.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSyncAnimation.cs
new file mode 100644
index 0000000..eb6d5a1
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZSyncTransform.cs b/Valheim_v202102/Valheim/assembly_valheim/ZSyncTransform.cs
new file mode 100644
index 0000000..01431f0
--- /dev/null
+++ b/Valheim_v202102/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_v202102/Valheim/assembly_valheim/ZoneSystem.cs b/Valheim_v202102/Valheim/assembly_valheim/ZoneSystem.cs
new file mode 100644
index 0000000..cc376b1
--- /dev/null
+++ b/Valheim_v202102/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;
+ }
+}