diff options
author | chai <215380520@qq.com> | 2024-05-20 20:28:49 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-05-20 20:28:49 +0800 |
commit | db64ca2ebcfc2239702ba53e3497b44cd14d8c27 (patch) | |
tree | be17abde084302284e5acc69bed0c2dfd83f9cf7 |
+init
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 Binary files differnew file mode 100644 index 0000000..d5e5b83 --- /dev/null +++ b/Valheim_v202102/Doc/分析.xlsx diff --git a/Valheim_v202102/Doc/分析/地形生成.xlsx b/Valheim_v202102/Doc/分析/地形生成.xlsx Binary files differnew file mode 100644 index 0000000..10237e2 --- /dev/null +++ b/Valheim_v202102/Doc/分析/地形生成.xlsx 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; + } +} |