Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZoneArtifacts v0.1.2
ZoneArtifacts.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using On.RoR2; using R2API; using RoR2; using RoR2.Orbs; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ZoneArtifacts")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("ZoneArtifacts")] [assembly: AssemblyTitle("ZoneArtifacts")] [assembly: AssemblyVersion("0.1.2.0")] namespace ZoneArtifacts; internal static class Hooks { internal static void Install() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(OnStats); HealthComponent.TakeDamage += new hook_TakeDamage(OnTakeDamage); HealthComponent.Heal += new hook_Heal(OnHeal); GlobalEventManager.onServerDamageDealt += OnDamageDealt; GlobalEventManager.onCharacterDeathGlobal += OnDeath; CharacterBody.onBodyInventoryChangedGlobal += OnInventoryChanged; } private static void OnStats(CharacterBody body, StatHookEventArgs a) { if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory)) { return; } EnsureController(body); float num = 1f + 0.2f * Mathf.Max(0f, body.level - 1f); float num2 = 0f; int num3; if ((num3 = Z.N(body, ZId.Battery)) > 0) { a.moveSpeedMultAdd += 0.08f * (float)num3; } if ((num3 = Z.N(body, ZId.Crystal)) > 0) { a.armorAdd += 6f * (float)num3; } if ((num3 = Z.N(body, ZId.Cavity)) > 0) { a.healthMultAdd += 0.08f * (float)num3; a.baseRegenAdd += 0.5f * (float)num3 * num; } if ((num3 = Z.N(body, ZId.Frost)) > 0) { a.armorAdd += 5f * (float)num3; } if ((num3 = Z.N(body, ZId.Static)) > 0) { a.armorAdd += 10f * (float)num3; } if ((num3 = Z.N(body, ZId.Heart)) > 0) { a.baseRegenAdd += 0.8f * (float)num3 * num; } if ((num3 = Z.N(body, ZId.Sun)) > 0) { a.healthMultAdd += 0.1f * (float)num3; a.baseRegenAdd += 1f * (float)num3 * num; ZoneController component = ((Component)body).GetComponent<ZoneController>(); if (Object.op_Implicit((Object)(object)component) && component.IsCalm) { a.baseRegenAdd += 2f * (float)num3 * num; } } if ((num3 = Z.N(body, ZId.Thunderberry)) > 0) { a.moveSpeedMultAdd += 0.25f * (float)num3; } if ((num3 = Z.N(body, ZId.Compass)) > 0) { a.armorAdd += 30f * (float)num3; } if ((num3 = Z.N(body, ZId.Hypercube)) > 0) { a.healthMultAdd += 0.15f * (float)num3; } if ((num3 = Z.N(body, ZId.Bubblegum)) > 0) { a.armorAdd += 45f * (float)num3; a.moveSpeedReductionMultAdd += 0.12f * (float)num3; } if ((num3 = Z.N(body, ZId.Firebird)) > 0) { a.baseRegenAdd += 1.4f * (float)num3 * num; } if ((num3 = Z.N(body, ZId.BlackHole)) > 0) { a.armorAdd += 25f * (float)num3; a.attackSpeedMultAdd += 0.1f * (float)num3; } if ((num3 = Z.N(body, ZId.WeirdWater)) > 0) { a.healthMultAdd += 0.15f * (float)num3; a.attackSpeedReductionMultAdd += 0.12f * (float)num3; } if ((num3 = Z.N(body, ZId.WeirdNut)) > 0) { a.armorAdd += 12f * (float)num3; } if ((num3 = Z.N(body, ZId.EyeOfStorm)) > 0) { a.moveSpeedMultAdd += 0.2f * (float)num3; a.jumpPowerMultAdd += 0.1f * (float)num3; num2 += Z.Red(num3, 0.15f); } if (ZoneArtifactsPlugin.RadiationEnabled == null || ZoneArtifactsPlugin.RadiationEnabled.Value) { int surplus; int num4 = Z.NetRadiation(body, out surplus); if (num4 > 0) { a.regenMultAdd -= Mathf.Min(0.8f, 0.05f * (float)num4); num2 += Mathf.Min(0.3f, 0.01f * (float)num4); } if (surplus > 0 && Z.N(body, ZId.LiquidRock) > 0) { a.baseRegenAdd += 0.4f * Mathf.Min((float)surplus, 6f) * num; } if (Z.N(body, ZId.HeartOfChornobyl) > 0 && num4 > 0) { a.damageMultAdd += Mathf.Min(1.5f, 0.03f * (float)num4); } } if (num2 > 0f) { a.healthMultAdd -= Mathf.Min(num2, 0.9f); } } private static void OnTakeDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo di) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = (Object.op_Implicit((Object)(object)self) ? self.body : null); if (!Object.op_Implicit((Object)(object)val) || di == null || di.rejected || !Object.op_Implicit((Object)(object)val.inventory)) { orig.Invoke(self, di); return; } float num = 1f; if ((int)di.dotIndex != -1) { switch (Z.Classify(di.dotIndex)) { case DotKind.Burn: num = ((Z.N(val, ZId.Hypercube) <= 0 && Z.N(val, ZId.EyeOfStorm) <= 0) ? (num * (1f - Z.Red(Z.N(val, ZId.Crystal), 0.25f))) : 0f); break; case DotKind.Bleed: if (Z.N(val, ZId.Hypercube) > 0 || Z.N(val, ZId.WeirdNut) > 0) { num = 0f; break; } num *= 1f - Z.Red(Z.N(val, ZId.Cavity), 0.3f); num *= 1f - Z.Red(Z.N(val, ZId.Bubblegum), 0.45f); break; case DotKind.Chem: if (Z.N(val, ZId.LiquidRock) > 0 || Z.N(val, ZId.EyeOfStorm) > 0) { num = 0f; } break; } } else if (!Object.op_Implicit((Object)(object)di.attacker)) { num *= 1f - Z.Red(Z.N(val, ZId.WeirdBolt), 0.7f); } if (num > 0f) { int num2 = Z.N(val, ZId.Compass); if (num2 > 0 && di.damage >= self.fullHealth * 0.2f) { num *= 1f - Z.Red(num2, 0.4f); } } if (num <= 0f) { di.rejected = true; orig.Invoke(self, di); return; } if (num < 1f) { di.damage *= num; } orig.Invoke(self, di); AfterDamage(self, val, di); } private static void AfterDamage(HealthComponent self, CharacterBody body, DamageInfo di) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (di.rejected || di.damage <= 0f) { return; } ZoneController component = ((Component)body).GetComponent<ZoneController>(); if (Object.op_Implicit((Object)(object)component)) { component.MarkHit(); } if (!Object.op_Implicit((Object)(object)di.attacker)) { return; } CharacterBody component2 = di.attacker.GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component2) && !((Object)(object)component2 == (Object)(object)body) && (!Object.op_Implicit((Object)(object)component2.teamComponent) || !Object.op_Implicit((Object)(object)body.teamComponent) || component2.teamComponent.teamIndex != body.teamComponent.teamIndex)) { if (Z.N(body, ZId.Bubblegum) > 0) { component2.AddTimedBuff(Buffs.Slow60, 2f); } int num = Z.N(body, ZId.Static); if (num > 0 && Object.op_Implicit((Object)(object)component) && component.StaticReady && self.alive && Z.Roll(0.25f * (float)num, body)) { component.StaticUsed(); Z.Zap(body, component2, 1.5f, 3, 20f); } } } private static float OnHeal(orig_Heal orig, HealthComponent self, float amount, ProcChainMask procChainMask, bool nonRegen) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = (Object.op_Implicit((Object)(object)self) ? self.body : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.inventory)) { float num = 1f; if (!Z.SkipHealBonus) { num += 0.12f * (float)Z.N(val, ZId.Frost) + 0.12f * (float)Z.N(val, ZId.Heart) + 0.25f * (float)Z.N(val, ZId.Firebird); } num *= 1f - Z.Red(Z.N(val, ZId.WeirdNut), 0.35f); amount *= num; } return orig.Invoke(self, amount, procChainMask, nonRegen); } private static void OnDamageDealt(DamageReport report) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (report == null) { return; } DamageInfo damageInfo = report.damageInfo; CharacterBody attackerBody = report.attackerBody; CharacterBody victimBody = report.victimBody; if (damageInfo != null && Object.op_Implicit((Object)(object)attackerBody) && Object.op_Implicit((Object)(object)victimBody) && !((Object)(object)attackerBody == (Object)(object)victimBody) && Object.op_Implicit((Object)(object)attackerBody.inventory) && !(damageInfo.procCoefficient <= 0f) && (int)damageInfo.dotIndex == -1 && (!Object.op_Implicit((Object)(object)attackerBody.teamComponent) || !Object.op_Implicit((Object)(object)victimBody.teamComponent) || attackerBody.teamComponent.teamIndex != victimBody.teamComponent.teamIndex)) { float procCoefficient = damageInfo.procCoefficient; int num; if ((num = Z.N(attackerBody, ZId.Battery)) > 0 && Z.Roll(0.07f * (float)num * procCoefficient, attackerBody)) { Z.Zap(attackerBody, victimBody, 0.6f, 2, 18f); } if ((num = Z.N(attackerBody, ZId.Frost)) > 0 && Z.Roll(0.15f * (float)num * procCoefficient, attackerBody)) { victimBody.AddTimedBuff(Buffs.Slow60, 3f); } if ((num = Z.N(attackerBody, ZId.Firebird)) > 0 && Z.Roll(0.15f * (float)num * procCoefficient, attackerBody)) { Z.Ignite(attackerBody, victimBody, 4f); } } } private static void OnDeath(DamageReport report) { if (report == null || !NetworkServer.active) { return; } CharacterBody attackerBody = report.attackerBody; CharacterBody victimBody = report.victimBody; if (!Object.op_Implicit((Object)(object)attackerBody) || (Object)(object)attackerBody == (Object)(object)victimBody || !Object.op_Implicit((Object)(object)attackerBody.inventory)) { return; } HealthComponent healthComponent = attackerBody.healthComponent; if (!Object.op_Implicit((Object)(object)healthComponent) || !healthComponent.alive) { return; } int num = Z.N(attackerBody, ZId.WeirdPot); if (num > 0) { Z.SelfHeal(healthComponent, healthComponent.fullHealth * 0.015f * (float)num); if (Z.Roll(0.08f, attackerBody)) { attackerBody.AddTimedBuff(Buffs.Slow60, 2f); } } if (Z.N(attackerBody, ZId.Firebird) > 0 && Object.op_Implicit((Object)(object)victimBody) && victimBody.HasBuff(Buffs.OnFire)) { Z.SelfHeal(healthComponent, healthComponent.fullHealth * 0.04f); } } private static void OnInventoryChanged(CharacterBody body) { EnsureController(body); } private static void EnsureController(CharacterBody body) { if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || Object.op_Implicit((Object)(object)((Component)body).GetComponent<ZoneController>())) { return; } for (int i = 0; i < Z.Defs.Length; i++) { ItemDef val = Z.Defs[i]; if (Object.op_Implicit((Object)(object)val) && body.inventory.GetItemCount(val) > 0) { ((Component)body).gameObject.AddComponent<ZoneController>(); break; } } } } internal enum ZId { Battery, Crystal, Cavity, Bubble, Frost, Static, Heart, Sun, WeirdFlower, WeirdPot, WeirdBolt, Thunderberry, Compass, Hypercube, LiquidRock, Bubblegum, Firebird, BlackHole, WeirdWater, WeirdNut, EyeOfStorm, HeartOfChornobyl } internal sealed class ItemSpec { public ZId Id; public string Key; public string IconFile; public string ModelFile; public ItemTier Tier; public int Rad; public string ColorHex; public string[] Tags; public string NameEn; public string PickupEn; public string DescEn; public string LoreEn; public string NameRu; public string PickupRu; public string DescRu; public string LoreRu; } internal static class Cfg { public const float RadRegen = 0.05f; public const float RadHp = 0.01f; public const float RadRegenCap = 0.8f; public const float RadHpCap = 0.3f; public const float battery_move = 0.08f; public const float battery_chance = 0.07f; public const float battery_dmg = 0.6f; public const float battery_bounces = 2f; public const float battery_range = 18f; public const float crystal_armor = 6f; public const float crystal_burn_res = 0.25f; public const float cavity_hp = 0.08f; public const float cavity_regen = 0.5f; public const float cavity_bleed_res = 0.3f; public const float bubble_barrier = 0.12f; public const float bubble_thresh = 0.5f; public const float bubble_cd = 15f; public const float frost_heal = 0.12f; public const float frost_armor = 5f; public const float frost_chance = 0.15f; public const float frost_slow = 3f; public const float static_armor = 10f; public const float static_chance = 0.25f; public const float static_dmg = 1.5f; public const float static_bounces = 3f; public const float static_range = 20f; public const float static_cd = 1.5f; public const float heart_regen = 0.8f; public const float heart_heal = 0.12f; public const float heart_pulse = 0.025f; public const float heart_interval = 6f; public const float sun_hp = 0.1f; public const float sun_regen = 1f; public const float sun_bonus_regen = 2f; public const float sun_calm = 5f; public const float weird_flower_cloak = 8f; public const float weird_flower_cloak_stack = 3f; public const float weird_pot_kill_heal = 0.015f; public const float weird_pot_side_chance = 0.08f; public const float weird_pot_side_slow = 2f; public const float weird_bolt_env_res = 0.7f; public const float weird_bolt_barrier = 0.2f; public const float thunderberry_move = 0.25f; public const float thunderberry_interval = 2f; public const float thunderberry_dmg = 2.5f; public const float thunderberry_bounces = 3f; public const float thunderberry_range = 28f; public const float compass_armor = 30f; public const float compass_big_hit = 0.2f; public const float compass_big_res = 0.4f; public const float hypercube_hp = 0.15f; public const float liquid_rock_surplus_regen = 0.4f; public const float liquid_rock_surplus_cap = 6f; public const float bubblegum_armor = 45f; public const float bubblegum_move_pen = 0.12f; public const float bubblegum_bleed_res = 0.45f; public const float bubblegum_slow = 2f; public const float firebird_heal = 0.25f; public const float firebird_regen = 1.4f; public const float firebird_ignite = 0.15f; public const float firebird_burn_dur = 4f; public const float firebird_burn_heal = 0.04f; public const float black_hole_armor = 25f; public const float black_hole_atk = 0.1f; public const float black_hole_interval = 10f; public const float black_hole_interval_stack = 1f; public const float black_hole_interval_min = 4f; public const float black_hole_radius = 22f; public const float black_hole_pull = 14f; public const float black_hole_slow = 1.5f; public const float weird_water_hp = 0.15f; public const float weird_water_atk_pen = 0.12f; public const float weird_water_stumble_interval = 30f; public const float weird_water_stumble_slow = 2f; public const float weird_nut_armor = 12f; public const float weird_nut_heal_pen = 0.35f; public const float eye_of_storm_move = 0.2f; public const float eye_of_storm_jump = 0.1f; public const float eye_of_storm_hp_pen = 0.15f; public const float heart_of_chornobyl_dmg_per_rad = 0.03f; public const float heart_of_chornobyl_dmg_cap = 1.5f; } internal static class Specs { public static readonly ItemSpec[] All = new ItemSpec[22] { new ItemSpec { Id = ZId.Battery, Key = "BATTERY", IconFile = "battery.png", ModelFile = "battery.zam", Tier = (ItemTier)0, Rad = 1, ColorHex = "#e8c33a", Tags = new string[2] { "Utility", "Damage" }, NameEn = "Battery", PickupEn = "Move faster. Sometimes discharge chain lightning.", DescEn = "Increase <style=cIsUtility>movement speed</style> by <style=cIsUtility>8%</style> <style=cStack>(+8% per stack)</style>. <style=cIsDamage>7%</style> <style=cStack>(+7% per stack)</style> chance on hit to discharge <style=cIsDamage>chain lightning</style> for <style=cIsDamage>60% damage</style>.\n\n<style=cDeath>Radiation +1</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "It hums in your pocket like a trapped insect. The charge never runs out, and no instrument can say why.", NameRu = "Батарейка", PickupRu = "Бег быстрее. Иногда бьёт цепной молнией.", DescRu = "Увеличивает <style=cIsUtility>скорость передвижения</style> на <style=cIsUtility>8%</style> <style=cStack>(+8% за каждый)</style>. Шанс <style=cIsDamage>7%</style> <style=cStack>(+7% за каждый)</style> при попадании выпустить <style=cIsDamage>цепную молнию</style> на <style=cIsDamage>60% урона</style>.\n\n<style=cDeath>Радиация +1</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Она гудит в кармане, как пойманное насекомое. Заряд не кончается, и ни один прибор не может объяснить почему." }, new ItemSpec { Id = ZId.Crystal, Key = "CRYSTAL", IconFile = "crystal.png", ModelFile = "crystal.zam", Tier = (ItemTier)0, Rad = 1, ColorHex = "#ff7a3d", Tags = new string[1] { "Utility" }, NameEn = "Crystal", PickupEn = "Gain armor and resist burning.", DescEn = "Gain <style=cIsHealing>6 armor</style> <style=cStack>(+6 per stack)</style>. Take <style=cIsHealing>25%</style> less <style=cIsDamage>burn damage</style> <style=cStack>(increases hyperbolically)</style>.\n\n<style=cDeath>Radiation +1</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "Warm to the touch even in January. Stalkers keep it close when the Zone starts to smoulder.", NameRu = "Кристалл", PickupRu = "Больше брони и стойкость к огню.", DescRu = "Даёт <style=cIsHealing>6 брони</style> <style=cStack>(+6 за каждый)</style>. Вы получаете на <style=cIsHealing>25%</style> меньше <style=cIsDamage>урона от горения</style> <style=cStack>(растёт гиперболически)</style>.\n\n<style=cDeath>Радиация +1</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Тёплый на ощупь даже в январе. Сталкеры держат его при себе, когда Зона начинает тлеть." }, new ItemSpec { Id = ZId.Cavity, Key = "CAVITY", IconFile = "cavity.png", ModelFile = "cavity.zam", Tier = (ItemTier)0, Rad = 1, ColorHex = "#c9573a", Tags = new string[1] { "Healing" }, NameEn = "Cavity", PickupEn = "More health and resist bleeding.", DescEn = "Increase <style=cIsHealing>maximum health</style> by <style=cIsHealing>8%</style> <style=cStack>(+8% per stack)</style>. Gain <style=cIsHealing>+0.5 base health regeneration</style> <style=cStack>(+0.5 per stack)</style>. Take <style=cIsHealing>30%</style> less <style=cIsDamage>bleed damage</style> <style=cStack>(increases hyperbolically)</style>.\n\n<style=cDeath>Radiation +1</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "A hollow where something used to be. Wounds close faster around it, as if it were hungry for them.", NameRu = "Полость", PickupRu = "Больше здоровья и стойкость к кровотечению.", DescRu = "Увеличивает <style=cIsHealing>максимальное здоровье</style> на <style=cIsHealing>8%</style> <style=cStack>(+8% за каждый)</style>. Даёт <style=cIsHealing>+0.5 к базовой регенерации</style> <style=cStack>(+0.5 за каждый)</style>. Вы получаете на <style=cIsHealing>30%</style> меньше <style=cIsDamage>урона от кровотечения</style> <style=cStack>(растёт гиперболически)</style>.\n\n<style=cDeath>Радиация +1</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Пустота там, где раньше что-то было. Раны затягиваются вокруг неё быстрее, словно она их жаждет." }, new ItemSpec { Id = ZId.Bubble, Key = "BUBBLE", IconFile = "bubble.png", ModelFile = "bubble.zam", Tier = (ItemTier)1, Rad = -2, ColorHex = "#4fd1a5", Tags = new string[2] { "Healing", "Utility" }, NameEn = "Bubble", PickupEn = "Resist radiation. Gain a barrier when badly hurt.", DescEn = "Falling below <style=cIsHealth>50% health</style> grants a <style=cIsHealing>temporary barrier</style> for <style=cIsHealing>12%</style> of maximum health <style=cStack>(+12% per stack)</style>. Recharges after 15 seconds.\n\n<style=cIsHealing>Radiation resistance 2</style> <style=cStack>(cancels radiation from other artifacts)</style>", LoreEn = "A film as thin as soap, and as stubborn as a pressure vessel. When it bursts, the stalker is usually already somewhere else.", NameRu = "Пузырь", PickupRu = "Защита от радиации. Барьер при тяжёлых ранах.", DescRu = "При падении ниже <style=cIsHealth>50% здоровья</style> даёт <style=cIsHealing>временный барьер</style> на <style=cIsHealing>12%</style> максимального здоровья <style=cStack>(+12% за каждый)</style>. Перезарядка 15 с.\n\n<style=cIsHealing>Сопротивление радиации 2</style> <style=cStack>(гасит радиацию других артефактов)</style>", LoreRu = "Плёнка тонкая, как мыльная, и упрямая, как сосуд под давлением. Когда она лопается, сталкер обычно уже в другом месте." }, new ItemSpec { Id = ZId.Frost, Key = "FROST", IconFile = "frost.png", ModelFile = "frost.zam", Tier = (ItemTier)1, Rad = 0, ColorHex = "#7fd4ff", Tags = new string[2] { "Healing", "Utility" }, NameEn = "Frost", PickupEn = "Heal better. Chill enemies you hit.", DescEn = "Receive <style=cIsHealing>12%</style> more <style=cIsHealing>healing</style> <style=cStack>(+12% per stack)</style>. Gain <style=cIsHealing>5 armor</style> <style=cStack>(+5 per stack)</style>. <style=cIsDamage>15%</style> <style=cStack>(+15% per stack)</style> chance on hit to <style=cIsUtility>chill</style> the enemy, slowing it for 3 seconds.", LoreEn = "Crystals grow on its icy crust while you watch. Hold it long enough and your own pulse starts to feel slow.", NameRu = "Мороз", PickupRu = "Лучшее лечение. Охлаждает врагов при ударе.", DescRu = "Вы получаете на <style=cIsHealing>12%</style> больше <style=cIsHealing>лечения</style> <style=cStack>(+12% за каждый)</style>. Даёт <style=cIsHealing>5 брони</style> <style=cStack>(+5 за каждый)</style>. Шанс <style=cIsDamage>15%</style> <style=cStack>(+15% за каждый)</style> при попадании <style=cIsUtility>охладить</style> врага, замедлив его на 3 с.", LoreRu = "Кристаллы растут на ледяной корке прямо на глазах. Подержи его подольше, и собственный пульс покажется медленным." }, new ItemSpec { Id = ZId.Static, Key = "STATIC", IconFile = "static.png", ModelFile = "static.zam", Tier = (ItemTier)1, Rad = 2, ColorHex = "#b48cff", Tags = new string[2] { "Damage", "Utility" }, NameEn = "Static", PickupEn = "Gain armor. Strike back with lightning when hit.", DescEn = "Gain <style=cIsHealing>10 armor</style> <style=cStack>(+10 per stack)</style>. When struck by an enemy, <style=cIsDamage>25%</style> <style=cStack>(+25% per stack)</style> chance to discharge <style=cIsDamage>lightning</style> back at the attacker for <style=cIsDamage>150% damage</style>. Cooldown 1.5 seconds.\n\n<style=cDeath>Radiation +2</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "Every hair on your arm leans toward it. When something hostile comes close, the air tastes of metal.", NameRu = "Статик", PickupRu = "Больше брони. Бьёт молнией в ответ на удар.", DescRu = "Даёт <style=cIsHealing>10 брони</style> <style=cStack>(+10 за каждый)</style>. Когда враг попадает по вам, шанс <style=cIsDamage>25%</style> <style=cStack>(+25% за каждый)</style> ответить <style=cIsDamage>молнией</style> на <style=cIsDamage>150% урона</style>. Перезарядка 1.5 с.\n\n<style=cDeath>Радиация +2</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Каждый волосок на руке тянется к нему. Когда рядом появляется враг, воздух отдаёт металлом." }, new ItemSpec { Id = ZId.Heart, Key = "HEART", IconFile = "heart.png", ModelFile = "heart.zam", Tier = (ItemTier)1, Rad = 1, ColorHex = "#ff4d6a", Tags = new string[1] { "Healing" }, NameEn = "Heart", PickupEn = "Regenerate faster and pulse with healing.", DescEn = "Gain <style=cIsHealing>+0.8 base health regeneration</style> <style=cStack>(+0.8 per stack)</style>. Receive <style=cIsHealing>12%</style> more <style=cIsHealing>healing</style> <style=cStack>(+12% per stack)</style>. Every 6 seconds <style=cIsHealing>heal for 2.5%</style> of maximum health <style=cStack>(+2.5% per stack)</style>.\n\n<style=cDeath>Radiation +1</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "It beats out of time with yours, then slowly falls into step.", NameRu = "Сердце", PickupRu = "Быстрее регенерация и пульсирующее лечение.", DescRu = "Даёт <style=cIsHealing>+0.8 к базовой регенерации</style> <style=cStack>(+0.8 за каждый)</style>. Вы получаете на <style=cIsHealing>12%</style> больше <style=cIsHealing>лечения</style> <style=cStack>(+12% за каждый)</style>. Каждые 6 с <style=cIsHealing>лечит на 2.5%</style> максимального здоровья <style=cStack>(+2.5% за каждый)</style>.\n\n<style=cDeath>Радиация +1</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Оно бьётся невпопад с вашим, а потом постепенно подстраивается." }, new ItemSpec { Id = ZId.Sun, Key = "SUN", IconFile = "sun.png", ModelFile = "sun.zam", Tier = (ItemTier)1, Rad = 0, ColorHex = "#ffb627", Tags = new string[1] { "Healing" }, NameEn = "Sun", PickupEn = "More health. Recover quickly when out of combat.", DescEn = "Increase <style=cIsHealing>maximum health</style> by <style=cIsHealing>10%</style> <style=cStack>(+10% per stack)</style>. Gain <style=cIsHealing>+1 base health regeneration</style> <style=cStack>(+1 per stack)</style>, increased by <style=cIsHealing>+2</style> <style=cStack>(+2 per stack)</style> while you have taken no damage for 5 seconds.", LoreEn = "A small, patient dawn. It does not care about the Emission, only that you are still alive.", NameRu = "Солнце", PickupRu = "Больше здоровья. Быстро восстанавливает вне боя.", DescRu = "Увеличивает <style=cIsHealing>максимальное здоровье</style> на <style=cIsHealing>10%</style> <style=cStack>(+10% за каждый)</style>. Даёт <style=cIsHealing>+1 к базовой регенерации</style> <style=cStack>(+1 за каждый)</style>, а если 5 с вы не получали урон, ещё <style=cIsHealing>+2</style> <style=cStack>(+2 за каждый)</style>.", LoreRu = "Маленький терпеливый рассвет. Ему нет дела до Выброса, лишь бы вы остались живы." }, new ItemSpec { Id = ZId.WeirdFlower, Key = "WEIRD_FLOWER", IconFile = "weird_flower.png", ModelFile = "weird_flower.zam", Tier = (ItemTier)1, Rad = 0, ColorHex = "#e86fd0", Tags = new string[1] { "Utility" }, NameEn = "Weird Flower", PickupEn = "Vanish for a while at the start of each stage.", DescEn = "At the start of each stage (or when picked up), become <style=cIsUtility>cloaked</style> and <style=cIsUtility>faster</style> for <style=cIsUtility>8 seconds</style> <style=cStack>(+3 seconds per stack)</style>.", LoreEn = "After a night beside it, beasts walk past you as if you were a stone.", NameRu = "Странный цветок", PickupRu = "В начале каждого этапа вы ненадолго исчезаете.", DescRu = "В начале каждого этапа (или при подборе) вы становитесь <style=cIsUtility>невидимым</style> и <style=cIsUtility>быстрее</style> на <style=cIsUtility>8 с</style> <style=cStack>(+3 с за каждый)</style>.", LoreRu = "После ночи рядом с ним твари проходят мимо, будто вы камень." }, new ItemSpec { Id = ZId.WeirdPot, Key = "WEIRD_POT", IconFile = "weird_pot.png", ModelFile = "weird_pot.zam", Tier = (ItemTier)1, Rad = 0, ColorHex = "#a8795a", Tags = new string[1] { "Healing" }, NameEn = "Weird Pot", PickupEn = "Heal on kill. Occasionally upsets your stomach.", DescEn = "Killing an enemy <style=cIsHealing>heals</style> you for <style=cIsHealing>1.5%</style> of maximum health <style=cStack>(+1.5% per stack)</style>. <style=cDeath>8%</style> chance on kill of an unpleasant side effect: you are <style=cIsUtility>slowed</style> for 2 seconds.", LoreEn = "You are never hungry. You are also never quite sure what you just ate.", NameRu = "Странный горшок", PickupRu = "Лечит за убийства. Иногда скручивает живот.", DescRu = "Убийство врага <style=cIsHealing>лечит</style> вас на <style=cIsHealing>1.5%</style> максимального здоровья <style=cStack>(+1.5% за каждый)</style>. Шанс <style=cDeath>8%</style> при убийстве получить неприятный побочный эффект: вы <style=cIsUtility>замедляетесь</style> на 2 с.", LoreRu = "Вы больше не чувствуете голода. И не уверены, что именно только что съели." }, new ItemSpec { Id = ZId.WeirdBolt, Key = "WEIRD_BOLT", IconFile = "weird_bolt.png", ModelFile = "weird_bolt.zam", Tier = (ItemTier)1, Rad = 0, ColorHex = "#5ec8ff", Tags = new string[2] { "Utility", "Healing" }, NameEn = "Weird Bolt", PickupEn = "Resist environmental damage. Recharges each stage.", DescEn = "Take <style=cIsHealing>70%</style> less damage from <style=cIsDamage>environmental and anomaly sources</style> (falls, hazards, anything with no attacker) <style=cStack>(increases hyperbolically)</style>. At the start of each stage gain a <style=cIsHealing>barrier</style> for 20% of maximum health <style=cStack>(+20% per stack)</style>.", LoreEn = "It drinks the storm before the storm arrives.", NameRu = "Странный болт", PickupRu = "Защита от среды. Перезаряжается каждый этап.", DescRu = "Вы получаете на <style=cIsHealing>70%</style> меньше урона от <style=cIsDamage>среды и аномалий</style> (падение, ловушки, всё без источника) <style=cStack>(растёт гиперболически)</style>. В начале каждого этапа даёт <style=cIsHealing>барьер</style> на 20% максимального здоровья <style=cStack>(+20% за каждый)</style>.", LoreRu = "Он выпивает бурю раньше, чем она придёт." }, new ItemSpec { Id = ZId.Thunderberry, Key = "THUNDERBERRY", IconFile = "thunderberry.png", ModelFile = "thunderberry.zam", Tier = (ItemTier)2, Rad = 4, ColorHex = "#6f7bff", Tags = new string[2] { "Utility", "Damage" }, NameEn = "Thunderberry", PickupEn = "Move much faster. Sprinting calls down lightning.", DescEn = "Increase <style=cIsUtility>movement speed</style> by <style=cIsUtility>25%</style> <style=cStack>(+25% per stack)</style>. While <style=cIsUtility>sprinting</style>, every 2 seconds a <style=cIsDamage>lightning bolt</style> strikes the nearest enemy within 28m for <style=cIsDamage>250% damage</style>, chaining 3 times.\n\n<style=cDeath>Radiation +4</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "The strongest wind in the Zone lives inside this berry. Run, and it runs with you.", NameRu = "Громоягода", PickupRu = "Намного быстрее. Бег вызывает молнии.", DescRu = "Увеличивает <style=cIsUtility>скорость передвижения</style> на <style=cIsUtility>25%</style> <style=cStack>(+25% за каждый)</style>. Во время <style=cIsUtility>бега</style> каждые 2 с <style=cIsDamage>молния</style> бьёт ближайшего врага в радиусе 28 м на <style=cIsDamage>250% урона</style> и перескакивает ещё 3 раза.\n\n<style=cDeath>Радиация +4</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "В этой ягоде живёт самый сильный ветер Зоны. Бежишь ты, бежит и он." }, new ItemSpec { Id = ZId.Compass, Key = "COMPASS", IconFile = "compass.png", ModelFile = "compass.zam", Tier = (ItemTier)2, Rad = 4, ColorHex = "#d9d9d9", Tags = new string[1] { "Utility" }, NameEn = "Compass", PickupEn = "Gain armor. Big hits are blunted.", DescEn = "Gain <style=cIsHealing>30 armor</style> <style=cStack>(+30 per stack)</style>. Hits that deal more than <style=cIsHealth>20%</style> of your maximum health are reduced by <style=cIsHealing>40%</style> <style=cStack>(increases hyperbolically)</style>.\n\n<style=cDeath>Radiation +4</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "The needle never points north. It points at whatever is about to hit you hardest, and then bends it away.", NameRu = "Компас", PickupRu = "Больше брони. Сильные удары смягчаются.", DescRu = "Даёт <style=cIsHealing>30 брони</style> <style=cStack>(+30 за каждый)</style>. Удары, отнимающие больше <style=cIsHealth>20%</style> максимального здоровья, ослабляются на <style=cIsHealing>40%</style> <style=cStack>(растёт гиперболически)</style>.\n\n<style=cDeath>Радиация +4</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Стрелка никогда не указывает на север. Она указывает на то, что вот-вот ударит сильнее всего, и отводит удар." }, new ItemSpec { Id = ZId.Hypercube, Key = "HYPERCUBE", IconFile = "hypercube.png", ModelFile = "hypercube.zam", Tier = (ItemTier)2, Rad = 4, ColorHex = "#ff5a36", Tags = new string[2] { "Healing", "Utility" }, NameEn = "Hypercube", PickupEn = "Immune to burning and bleeding.", DescEn = "Increase <style=cIsHealing>maximum health</style> by <style=cIsHealing>15%</style> <style=cStack>(+15% per stack)</style>. <style=cIsHealing>Immune</style> to <style=cIsDamage>burn</style> and <style=cIsDamage>bleed</style> damage.\n\n<style=cDeath>Radiation +4</style> <style=cStack>(each point of net radiation: -5% regeneration, -1% maximum health)</style>", LoreEn = "Count its corners twice and you will get different numbers. Fire and blood find nothing to hold on to.", NameRu = "Гиперкуб", PickupRu = "Иммунитет к горению и кровотечению.", DescRu = "Увеличивает <style=cIsHealing>максимальное здоровье</style> на <style=cIsHealing>15%</style> <style=cStack>(+15% за каждый)</style>. <style=cIsHealing>Иммунитет</style> к урону от <style=cIsDamage>горения</style> и <style=cIsDamage>кровотечения</style>.\n\n<style=cDeath>Радиация +4</style> <style=cStack>(каждое очко итоговой радиации: -5% регенерации, -1% максимального здоровья)</style>", LoreRu = "Сосчитай его углы дважды, и числа не совпадут. Огню и крови не за что зацепиться." }, new ItemSpec { Id = ZId.LiquidRock, Key = "LIQUID_ROCK", IconFile = "liquid_rock.png", ModelFile = "liquid_rock.zam", Tier = (ItemTier)2, Rad = -4, ColorHex = "#3dffb0", Tags = new string[2] { "Healing", "Utility" }, NameEn = "Liquid Rock", PickupEn = "Cleanse radiation. Immune to poison.", DescEn = "<style=cIsHealing>Immune</style> to <style=cIsDamage>poison</style> and <style=cIsDamage>blight</style> damage. Resistance exceeding your total radiation is converted into <style=cIsHealing>+0.4 base health regeneration</style> per point (max 6 points).\n\n<style=cIsHealing>Radiation resistance 4</style> <style=cStack>(cancels radiation from other artifacts)</style>", LoreEn = "Stone that forgot to be solid. Everything harmful slides off it, including, at times, you.", NameRu = "Жидкий камень", PickupRu = "Очищает от радиации. Иммунитет к яду.", DescRu = "<style=cIsHealing>Иммунитет</style> к урону от <style=cIsDamage>яда</style> и <style=cIsDamage>порчи</style>. Сопротивление сверх вашей общей радиации превращается в <style=cIsHealing>+0.4 к базовой регенерации</style> за каждое очко (максимум 6 очков).\n\n<style=cIsHealing>Сопротивление радиации 4</style> <style=cStack>(гасит радиацию других артефактов)</style>", LoreRu = "Камень, забывший быть твёрдым. Всё вредное скользит по нему, иногда и вы." }, new ItemSpec { Id = ZId.Bubblegum, Key = "BUBBLEGUM", IconFile = "bubblegum.png", ModelFile = "bubblegum.zam", Tier = (ItemTier)2, Rad = 0, ColorHex = "#ff8fc7", Tags = new string[1] { "Utility" }, NameEn = "Bubblegum", PickupEn = "Huge armor, but slower. Enemies that hit you get stuck.", DescEn = "Gain <style=cIsHealing>45 armor</style> <style=cStack>(+45 per stack)</style>. Take <style=cIsHealing>45%</style> less <style=cIsDamage>bleed damage</style> <style=cStack>(increases hyperbolically)</style>. Reduce <style=cIsUtility>movement speed</style> by <style=cDeath>12%</style> <style=cStack>(+12% per stack)</style>. Enemies that hit you are <style=cIsUtility>stuck and slowed</style> for 2 seconds.", LoreEn = "Chewed by something far larger than you. It remembers, and it wants everyone else to remember too.", NameRu = "Жвачка", PickupRu = "Огромная броня, но медленнее. Враги прилипают.", DescRu = "Даёт <style=cIsHealing>45 брони</style> <style=cStack>(+45 за каждый)</style>. Вы получаете на <style=cIsHealing>45%</style> меньше <style=cIsDamage>урона от кровотечения</style> <style=cStack>(растёт гиперболически)</style>. Снижает <style=cIsUtility>скорость передвижения</style> на <style=cDeath>12%</style> <style=cStack>(+12% за каждый)</style>. Враги, ударившие вас, <style=cIsUtility>прилипают и замедляются</style> на 2 с.", LoreRu = "Её жевало существо куда больше вас. Оно помнит и хочет, чтобы помнили и остальные." }, new ItemSpec { Id = ZId.Firebird, Key = "FIREBIRD", IconFile = "firebird.png", ModelFile = "firebird.zam", Tier = (ItemTier)2, Rad = 0, ColorHex = "#ff6a1a", Tags = new string[2] { "Healing", "Damage" }, NameEn = "Firebird", PickupEn = "Heal better. Ignite enemies and feed on the flames.", DescEn = "Receive <style=cIsHealing>25%</style> more <style=cIsHealing>healing</style> <style=cStack>(+25% per stack)</style>. Gain <style=cIsHealing>+1.4 base health regeneration</style> <style=cStack>(+1.4 per stack)</style>. <style=cIsDamage>15%</style> <style=cStack>(+15% per stack)</style> chance on hit to <style=cIsDamage>ignite</style> for 4 seconds. Killing a burning enemy <style=cIsHealing>heals</style> you for <style=cIsHealing>4%</style> of maximum health.", LoreEn = "Its feathers are not on fire. Fire is simply the shape this bird takes when it is happy.", NameRu = "Жар-птица", PickupRu = "Лучшее лечение. Поджигает врагов и питается пламенем.", DescRu = "Вы получаете на <style=cIsHealing>25%</style> больше <style=cIsHealing>лечения</style> <style=cStack>(+25% за каждый)</style>. Даёт <style=cIsHealing>+1.4 к базовой регенерации</style> <style=cStack>(+1.4 за каждый)</style>. Шанс <style=cIsDamage>15%</style> <style=cStack>(+15% за каждый)</style> при попадании <style=cIsDamage>поджечь</style> цель на 4 с. Убийство горящего врага <style=cIsHealing>лечит</style> вас на <style=cIsHealing>4%</style> максимального здоровья.", LoreRu = "Перья не горят. Огонь для неё просто форма, которую она принимает от радости." }, new ItemSpec { Id = ZId.BlackHole, Key = "BLACK_HOLE", IconFile = "black_hole.png", ModelFile = "black_hole.zam", Tier = (ItemTier)2, Rad = 0, ColorHex = "#8a4dff", Tags = new string[1] { "Utility" }, NameEn = "Black Hole", PickupEn = "Gain armor and attack speed. Periodically drag enemies in.", DescEn = "Gain <style=cIsHealing>25 armor</style> <style=cStack>(+25 per stack)</style> and <style=cIsDamage>10% attack speed</style> <style=cStack>(+10% per stack)</style>. Every 10 seconds <style=cStack>(-1 second per stack, minimum 4)</style> a <style=cIsUtility>gravity pulse</style> drags enemies within 22m toward you and slows them for 1.5 seconds.", LoreEn = "Small enough to hold in one hand. Heavy enough that the ground leans toward it.", NameRu = "Чёрная дыра", PickupRu = "Больше брони и скорости атаки. Периодически стягивает врагов.", DescRu = "Даёт <style=cIsHealing>25 брони</style> <style=cStack>(+25 за каждый)</style> и <style=cIsDamage>10% скорости атаки</style> <style=cStack>(+10% за каждый)</style>. Каждые 10 с <style=cStack>(-1 с за каждый, минимум 4)</style> <style=cIsUtility>гравитационный импульс</style> стягивает врагов в радиусе 22 м к вам и замедляет их на 1.5 с.", LoreRu = "Помещается в ладони. Тяжёлая настолько, что земля клонится к ней." }, new ItemSpec { Id = ZId.WeirdWater, Key = "WEIRD_WATER", IconFile = "weird_water.png", ModelFile = "weird_water.zam", Tier = (ItemTier)3, Rad = -3, ColorHex = "#3aa7ff", Tags = new string[1] { "Healing" }, NameEn = "Weird Water", PickupEn = "Tougher and resistant to radiation, but permanently tipsy.", DescEn = "Increase <style=cIsHealing>maximum health</style> by <style=cIsHealing>15%</style> <style=cStack>(+15% per stack)</style>. <style=cDeath>You are always drunk</style>: reduce <style=cIsDamage>attack speed</style> by <style=cDeath>12%</style> <style=cStack>(+12% per stack)</style> and stumble (slowed for 2 seconds) every 30 seconds.\n\n<style=cIsHealing>Radiation resistance 3</style> <style=cStack>(cancels radiation from other artifacts)</style>", LoreEn = "You cannot drink it. It simply decides, once in a while, that you have had enough.", NameRu = "Странная вода", PickupRu = "Крепче и устойчивее к радиации, но вечно навеселе.", DescRu = "Увеличивает <style=cIsHealing>максимальное здоровье</style> на <style=cIsHealing>15%</style> <style=cStack>(+15% за каждый)</style>. <style=cDeath>Вы всегда пьяны</style>: снижает <style=cIsDamage>скорость атаки</style> на <style=cDeath>12%</style> <style=cStack>(+12% за каждый)</style>, а каждые 30 с вы спотыкаетесь (замедление на 2 с).\n\n<style=cIsHealing>Сопротивление радиации 3</style> <style=cStack>(гасит радиацию других артефактов)</style>", LoreRu = "Её нельзя выпить. Она просто время от времени решает, что с вас хватит." }, new ItemSpec { Id = ZId.WeirdNut, Key = "WEIRD_NUT", IconFile = "weird_nut.png", ModelFile = "weird_nut.zam", Tier = (ItemTier)3, Rad = 0, ColorHex = "#b0b86a", Tags = new string[1] { "Utility" }, NameEn = "Weird Nut", PickupEn = "Immune to bleeding and armored, but healing is weaker.", DescEn = "<style=cIsHealing>Immune</style> to <style=cIsDamage>bleed</style> damage. Gain <style=cIsHealing>12 armor</style> <style=cStack>(+12 per stack)</style>. <style=cDeath>Reduce all healing received by 35%</style> <style=cStack>(increases hyperbolically)</style>.", LoreEn = "It seals every wound shut. The trouble is that it seals shut the medicine too.", NameRu = "Странная гайка", PickupRu = "Иммунитет к кровотечению и броня, но лечение слабее.", DescRu = "<style=cIsHealing>Иммунитет</style> к урону от <style=cIsDamage>кровотечения</style>. Даёт <style=cIsHealing>12 брони</style> <style=cStack>(+12 за каждый)</style>. <style=cDeath>Всё получаемое лечение снижено на 35%</style> <style=cStack>(растёт гиперболически)</style>.", LoreRu = "Она запечатывает любую рану. Беда в том, что заодно запечатывает и лекарство." }, new ItemSpec { Id = ZId.EyeOfStorm, Key = "EYE_OF_STORM", IconFile = "eye_of_storm.png", ModelFile = "eye_of_storm.zam", Tier = (ItemTier)3, Rad = 0, ColorHex = "#9be7ff", Tags = new string[1] { "Utility" }, NameEn = "Eye of the Storm", PickupEn = "Fast and immune to burning and poison, but fragile.", DescEn = "Increase <style=cIsUtility>movement speed</style> by <style=cIsUtility>20%</style> <style=cStack>(+20% per stack)</style> and <style=cIsUtility>jump height</style> by <style=cIsUtility>10%</style> <style=cStack>(+10% per stack)</style>. <style=cIsHealing>Immune</style> to <style=cIsDamage>burn</style>, <style=cIsDamage>poison</style> and <style=cIsDamage>blight</style> damage. <style=cDeath>Reduce maximum health by 15%</style> <style=cStack>(increases hyperbolically)</style>.", LoreEn = "Everything around it howls. Inside, it is perfectly still, and so thin that you can see through yourself.", NameRu = "Глаз бури", PickupRu = "Быстрый и неуязвим для огня и яда, но хрупкий.", DescRu = "Увеличивает <style=cIsUtility>скорость передвижения</style> на <style=cIsUtility>20%</style> <style=cStack>(+20% за каждый)</style> и <style=cIsUtility>высоту прыжка</style> на <style=cIsUtility>10%</style> <style=cStack>(+10% за каждый)</style>. <style=cIsHealing>Иммунитет</style> к урону от <style=cIsDamage>горения</style>, <style=cIsDamage>яда</style> и <style=cIsDamage>порчи</style>. <style=cDeath>Снижает максимальное здоровье на 15%</style> <style=cStack>(растёт гиперболически)</style>.", LoreRu = "Вокруг всё воет. Внутри абсолютная тишина, и ты так тонок, что видишь сквозь себя." }, new ItemSpec { Id = ZId.HeartOfChornobyl, Key = "HEART_OF_CHORNOBYL", IconFile = "heart_of_chornobyl.png", ModelFile = "heart_of_chornobyl.zam", Tier = (ItemTier)3, Rad = 0, ColorHex = "#8cff3a", Tags = new string[1] { "Damage" }, NameEn = "Heart of Chornobyl", PickupEn = "Radiation is amplified, and so is your damage.", DescEn = "<style=cDeath>Amplifies your radiation</style>: net radiation is multiplied by <style=cDeath>2</style> <style=cStack>(+1 per stack)</style>. Gain <style=cIsDamage>3% damage</style> per point of net radiation (max 150%).", LoreEn = "It does not give power. It simply stops hiding what the Zone has already done to you.", NameRu = "Сердце Чернобыля", PickupRu = "Радиация усиливается, и ваш урон тоже.", DescRu = "<style=cDeath>Усиливает вашу радиацию</style>: итоговая радиация умножается на <style=cDeath>2</style> <style=cStack>(+1 за каждый)</style>. Даёт <style=cIsDamage>3% урона</style> за каждое очко итоговой радиации (максимум 150%).", LoreRu = "Оно не даёт силу. Оно лишь перестаёт скрывать то, что Зона уже с вами сделала." } }; } internal static class ItemFactory { private sealed class ModelData { public Mesh Mesh; public Texture2D Albedo; public Texture2D Emission; } private static GameObject _holder; private static readonly List<string> TierMembers = new List<string>(); private static bool _dumpedItemDef; private static int _iconsFromDisk; private static int _iconsEmbedded; private static int _iconsFallback; private static int _modelsBuiltIn; private static int _modelsFallback; private static bool _loggedShader; private static Material _baseMaterial; private static bool _baseMaterialTried; internal static void RegisterAll(string pluginDir) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown _holder = new GameObject("ZoneArtifacts_PickupPrefabs"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); string iconDir = Path.Combine(pluginDir, "icons"); int num = 0; ItemSpec[] all = Specs.All; foreach (ItemSpec itemSpec in all) { try { if (Register(itemSpec, iconDir)) { num++; } } catch (Exception arg) { ZoneArtifactsPlugin.Log.LogError((object)$"Failed to register item {itemSpec.Key}: {arg}"); } } ZoneArtifactsPlugin.Log.LogInfo((object)$"Registered {num}/{Specs.All.Length} items."); ZoneArtifactsPlugin.Log.LogInfo((object)$"Icons: {_iconsEmbedded} built-in, {_iconsFromDisk} from the icons folder, {_iconsFallback} flat-colour fallbacks."); ZoneArtifactsPlugin.Log.LogInfo((object)$"Pickup models: {_modelsBuiltIn} 3D models, {_modelsFallback} sphere fallbacks."); ZoneArtifactsPlugin.Log.LogInfo((object)((TierMembers.Count > 0) ? ("Item tier was written to ItemDef member(s): " + string.Join(", ", TierMembers.ToArray())) : "WARNING: no tier member was found on ItemDef; items will not drop (see the ItemDef member dump above).")); } private static string Token(ItemSpec s, string part) { return "ZA_ITEM_" + s.Key + "_" + part; } private static bool Register(ItemSpec s, string iconDir) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown ItemDef val = ScriptableObject.CreateInstance<ItemDef>(); ((Object)val).name = "ZA_" + s.Key; val.nameToken = Token(s, "NAME"); val.pickupToken = Token(s, "PICKUP"); val.descriptionToken = Token(s, "DESC"); val.loreToken = Token(s, "LORE"); val.canRemove = true; val.hidden = false; val.tags = BuildTags(s); val.pickupIconSprite = LoadSprite(Path.Combine(iconDir, s.IconFile), s.IconFile, s.ColorHex); val.pickupModelPrefab = MakeModel(s); AssignTier(val, s.Tier, s.Key); LanguageAPI.Add(Token(s, "NAME"), s.NameEn); LanguageAPI.Add(Token(s, "PICKUP"), s.PickupEn); LanguageAPI.Add(Token(s, "DESC"), s.DescEn); LanguageAPI.Add(Token(s, "LORE"), s.LoreEn); LanguageAPI.Add(Token(s, "NAME"), s.NameRu, "ru"); LanguageAPI.Add(Token(s, "PICKUP"), s.PickupRu, "ru"); LanguageAPI.Add(Token(s, "DESC"), s.DescRu, "ru"); LanguageAPI.Add(Token(s, "LORE"), s.LoreRu, "ru"); bool num = ItemAPI.Add(new CustomItem(val, (ItemDisplayRule[])(object)new ItemDisplayRule[0])); if (num) { Z.Defs[(int)s.Id] = val; return num; } ZoneArtifactsPlugin.Log.LogWarning((object)("ItemAPI.Add refused " + s.Key + ".")); return num; } private static ItemTag[] BuildTags(ItemSpec s) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) List<ItemTag> list = new List<ItemTag> { (ItemTag)4 }; string[] tags = s.Tags; foreach (string text in tags) { try { list.Add((ItemTag)Enum.Parse(typeof(ItemTag), text)); } catch (ArgumentException) { ZoneArtifactsPlugin.Log.LogWarning((object)("Unknown ItemTag '" + text + "' on " + s.Key + ", skipped.")); } } return list.ToArray(); } private static void AssignTier(ItemDef def, ItemTier tier, string key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) ItemTierDef val = LoadTierDef(tier); bool flag = false; FieldInfo[] fields = typeof(ItemDef).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(ItemTier)) { fieldInfo.SetValue(def, tier); Remember("field " + fieldInfo.Name); flag = true; } else if (Object.op_Implicit((Object)(object)val) && fieldInfo.FieldType == typeof(ItemTierDef)) { fieldInfo.SetValue(def, val); Remember("field " + fieldInfo.Name); flag = true; } } PropertyInfo[] properties = typeof(ItemDef).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanWrite && propertyInfo.GetIndexParameters().Length == 0) { if (propertyInfo.PropertyType == typeof(ItemTier)) { propertyInfo.SetValue(def, tier, null); Remember("property " + propertyInfo.Name); flag = true; } else if (Object.op_Implicit((Object)(object)val) && propertyInfo.PropertyType == typeof(ItemTierDef)) { propertyInfo.SetValue(def, val, null); Remember("property " + propertyInfo.Name); flag = true; } } } if (!flag) { ZoneArtifactsPlugin.Log.LogWarning((object)("No ItemTier/ItemTierDef member found on ItemDef for " + key + ".")); DumpItemDefMembers(); } } private static void Remember(string member) { if (!TierMembers.Contains(member)) { TierMembers.Add(member); } } private static ItemTierDef LoadTierDef(ItemTier tier) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected I4, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) string text; switch ((int)tier) { case 0: text = "RoR2/Base/Common/Tier1Def.asset"; break; case 1: text = "RoR2/Base/Common/Tier2Def.asset"; break; case 2: text = "RoR2/Base/Common/Tier3Def.asset"; break; case 3: text = "RoR2/Base/Common/LunarTierDef.asset"; break; default: return null; } try { return Addressables.LoadAssetAsync<ItemTierDef>((object)text).WaitForCompletion(); } catch (Exception ex) { ZoneArtifactsPlugin.Log.LogWarning((object)("Could not load tier def '" + text + "' (" + ex.GetType().Name + "); only ItemTier members will be set.")); return null; } } private static void DumpItemDefMembers() { if (!_dumpedItemDef) { _dumpedItemDef = true; StringBuilder stringBuilder = new StringBuilder("ItemDef members in this game version: "); FieldInfo[] fields = typeof(ItemDef).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { stringBuilder.Append(fieldInfo.FieldType.Name).Append(' ').Append(fieldInfo.Name) .Append("; "); } PropertyInfo[] properties = typeof(ItemDef).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { stringBuilder.Append("[prop] ").Append(propertyInfo.PropertyType.Name).Append(' ') .Append(propertyInfo.Name) .Append("; "); } ZoneArtifactsPlugin.Log.LogWarning((object)stringBuilder.ToString()); } } private static Sprite LoadSprite(string diskPath, string fileName, string colorHex) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) Sprite val = null; try { if (File.Exists(diskPath)) { val = SpriteFromBytes(File.ReadAllBytes(diskPath)); if ((Object)(object)val != (Object)null) { _iconsFromDisk++; } else { ZoneArtifactsPlugin.Log.LogWarning((object)("Icon file could not be decoded: " + diskPath)); } } } catch (Exception ex) { ZoneArtifactsPlugin.Log.LogWarning((object)("Icon load failed for " + diskPath + ": " + ex.Message)); } if ((Object)(object)val == (Object)null) { try { val = SpriteFromBytes(ReadEmbedded(fileName)); if ((Object)(object)val != (Object)null) { _iconsEmbedded++; } } catch (Exception ex2) { ZoneArtifactsPlugin.Log.LogWarning((object)("Embedded icon failed for " + fileName + ": " + ex2.Message)); } } if ((Object)(object)val != (Object)null) { return val; } _iconsFallback++; ZoneArtifactsPlugin.Log.LogWarning((object)("No usable icon for " + fileName + "; using a flat colour square. Embedded resources: " + string.Join(", ", typeof(ItemFactory).Assembly.GetManifestResourceNames()))); Color magenta = default(Color); if (!ColorUtility.TryParseHtmlString(colorHex, ref magenta)) { magenta = Color.magenta; } Texture2D val2 = new Texture2D(16, 16, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[256]; for (int i = 0; i < array.Length; i++) { array[i] = magenta; } val2.SetPixels(array); val2.Apply(); return Sprite.Create(val2, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f)); } private static Sprite SpriteFromBytes(byte[] bytes) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (bytes == null || bytes.Length == 0) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, bytes)) { return null; } ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } private static byte[] ReadEmbedded(string fileName) { return ReadResource("ZoneArtifacts.icons." + fileName); } private static byte[] ReadResource(string resourceName) { using Stream stream = typeof(ItemFactory).Assembly.GetManifestResourceStream(resourceName); if (stream == null) { return null; } MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static ModelData LoadModel(string fileName, string meshName) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown byte[] array = ReadResource("ZoneArtifacts.models." + fileName); if (array == null) { return null; } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(array)); if (binaryReader.ReadInt32() != 827146586) { return null; } int num = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); if (num <= 0 || num2 <= 0 || num > 64 || num2 > 64) { return null; } ModelData modelData = new ModelData(); modelData.Albedo = ReadPalette(binaryReader, num, num2, meshName + "_albedo"); modelData.Emission = ReadPalette(binaryReader, num, num2, meshName + "_emission"); int num3 = binaryReader.ReadInt32(); if (num3 <= 0 || num3 > 200000) { return null; } Vector3[] array2 = (Vector3[])(object)new Vector3[num3]; Vector3[] array3 = (Vector3[])(object)new Vector3[num3]; Vector2[] array4 = (Vector2[])(object)new Vector2[num3]; Vector4[] array5 = (Vector4[])(object)new Vector4[num3]; for (int i = 0; i < num3; i++) { array2[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array3[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array4[i] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); Vector3 val = Vector3.Cross(array3[i], Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 1E-06f) { val = Vector3.right; } ((Vector3)(ref val)).Normalize(); array5[i] = new Vector4(val.x, val.y, val.z, 1f); } int num4 = binaryReader.ReadInt32(); if (num4 <= 0 || num4 % 3 != 0 || num4 > 1000000) { return null; } int[] array6 = new int[num4]; for (int j = 0; j < num4; j++) { array6[j] = binaryReader.ReadInt32(); } Mesh val2 = new Mesh(); ((Object)val2).name = meshName; if (num3 > 65000) { val2.indexFormat = (IndexFormat)1; } val2.vertices = array2; val2.normals = array3; val2.uv = array4; val2.tangents = array5; val2.triangles = array6; val2.RecalculateBounds(); ((Object)val2).hideFlags = (HideFlags)32; modelData.Mesh = val2; return modelData; } private static Texture2D ReadPalette(BinaryReader br, int w, int h, string name) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown Color32[] array = (Color32[])(object)new Color32[w * h]; for (int i = 0; i < array.Length; i++) { byte b = br.ReadByte(); byte b2 = br.ReadByte(); byte b3 = br.ReadByte(); byte b4 = br.ReadByte(); array[i] = new Color32(b, b2, b3, b4); } Texture2D val = new Texture2D(w, h, (TextureFormat)4, false) { name = name, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; val.SetPixels32(array); val.Apply(false, false); ((Object)val).hideFlags = (HideFlags)32; return val; } private static void ApplyModelMaterial(Material mat, ModelData data) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) LogShaderOnce(mat); if (mat.HasProperty("_MainTex")) { mat.SetTexture("_MainTex", (Texture)(object)data.Albedo); mat.SetTextureScale("_MainTex", Vector2.one); mat.SetTextureOffset("_MainTex", Vector2.zero); } if (mat.HasProperty("_Color")) { mat.SetColor("_Color", Color.white); } if (mat.HasProperty("_NormalTex")) { mat.SetTexture("_NormalTex", (Texture)null); } if (mat.HasProperty("_NormalStrength")) { mat.SetFloat("_NormalStrength", 0f); } if (mat.HasProperty("_EmTex")) { mat.SetTexture("_EmTex", (Texture)(object)data.Emission); } if (mat.HasProperty("_EmColor")) { mat.SetColor("_EmColor", Color.white); } if (mat.HasProperty("_EmPower")) { mat.SetFloat("_EmPower", 1.6f); } } private static void LogShaderOnce(Material mat) { if (_loggedShader) { return; } _loggedShader = true; try { Shader shader = mat.shader; StringBuilder stringBuilder = new StringBuilder(); int propertyCount = shader.GetPropertyCount(); for (int i = 0; i < propertyCount; i++) { stringBuilder.Append(shader.GetPropertyName(i)).Append(' '); } ZoneArtifactsPlugin.Log.LogInfo((object)$"Pickup material uses shader '{((Object)shader).name}'. Properties: {stringBuilder}"); } catch (Exception ex) { ZoneArtifactsPlugin.Log.LogInfo((object)("Could not list the pickup shader properties: " + ex.Message)); } } private static GameObject MakeModel(ItemSpec s) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) try { ModelData modelData = null; try { modelData = LoadModel(s.ModelFile, "ZA_" + s.Key); } catch (Exception ex) { ZoneArtifactsPlugin.Log.LogWarning((object)("3D model for " + s.Key + " could not be read (" + ex.Message + "); using a sphere.")); } GameObject val; Renderer val2; if (modelData != null) { val = new GameObject("ZA_Pickup_" + s.Key); val.AddComponent<MeshFilter>().sharedMesh = modelData.Mesh; val2 = (Renderer)(object)val.AddComponent<MeshRenderer>(); val.transform.SetParent(_holder.transform, false); _modelsBuiltIn++; } else { val = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val).name = "ZA_Pickup_" + s.Key; Collider component = val.GetComponent<Collider>(); if (Object.op_Implicit((Object)(object)component)) { Object.DestroyImmediate((Object)(object)component); } val.transform.SetParent(_holder.transform, false); val.transform.localScale = Vector3.one * 0.55f; val2 = val.GetComponent<Renderer>(); _modelsFallback++; } Color white = default(Color); if (!ColorUtility.TryParseHtmlString(s.ColorHex, ref white)) { white = Color.white; } Material val3 = null; Material baseMaterial = GetBaseMaterial(); if (Object.op_Implicit((Object)(object)baseMaterial)) { val3 = new Material(baseMaterial); if (val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", (Texture)null); } } else { Shader val4 = Shader.Find("Hopoo Games/Deferred/Standard"); if (!Object.op_Implicit((Object)(object)val4)) { val4 = Shader.Find("Standard"); } if (Object.op_Implicit((Object)(object)val4)) { val3 = new Material(val4); } } if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val3)) { if (modelData != null) { ApplyModelMaterial(val3, modelData); } else { if (val3.HasProperty("_Color")) { val3.SetColor("_Color", white); } if (val3.HasProperty("_EmColor")) { val3.SetColor("_EmColor", white * 0.6f); } } val2.sharedMaterial = val3; } GameObject val5 = new GameObject("FocusPoint"); val5.transform.SetParent(val.transform, false); GameObject val6 = new GameObject("CameraPosition"); val6.transform.SetParent(val.transform, false); val6.transform.localPosition = new Vector3(0f, 0f, -5f); ModelPanelParameters obj = val.AddComponent<ModelPanelParameters>(); obj.focusPointTransform = val5.transform; obj.cameraPositionTransform = val6.transform; obj.minDistance = 1.5f; obj.maxDistance = 4f; return val; } catch (Exception ex2) { ZoneArtifactsPlugin.Log.LogWarning((object)("Custom pickup model failed for " + s.Key + " (" + ex2.Message + "); using the mystery model.")); return LegacyResourcesAPI.Load<GameObject>("Prefabs/PickupModels/PickupMystery"); } } private static Material GetBaseMaterial() { if (_baseMaterialTried) { return _baseMaterial; } _baseMaterialTried = true; try { GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/PickupModels/PickupMystery"); if (Object.op_Implicit((Object)(object)val)) { Renderer componentInChildren = val.GetComponentInChildren<Renderer>(true); if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.sharedMaterial)) { _baseMaterial = componentInChildren.sharedMaterial; } } } catch (Exception ex) { ZoneArtifactsPlugin.Log.LogWarning((object)("Could not load the vanilla pickup material (" + ex.Message + "); falling back to Shader.Find.")); } return _baseMaterial; } } internal enum DotKind { None, Burn, Bleed, Chem, Other } internal static class Z { internal static readonly ItemDef[] Defs = (ItemDef[])(object)new ItemDef[Specs.All.Length]; internal static bool SkipHealBonus; private static readonly TeamIndex[] AllTeams; private static readonly Dictionary<int, DotKind> DotCache; internal static void SelfHeal(HealthComponent hc, float amount) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)hc) || amount <= 0f) { return; } SkipHealBonus = true; try { hc.Heal(amount, default(ProcChainMask), true); } finally { SkipHealBonus = false; } } internal static int N(CharacterBody body, ZId id) { if (!Object.op_Implicit((Object)(object)body)) { return 0; } Inventory inventory = body.inventory; if (!Object.op_Implicit((Object)(object)inventory)) { return 0; } ItemDef val = Defs[(int)id]; if (!Object.op_Implicit((Object)(object)val)) { return 0; } return inventory.GetItemCount(val); } internal static float Red(int n, float p) { if (n <= 0 || p <= 0f) { return 0f; } if (p >= 1f) { return 1f; } float num = p / (1f - p) * (float)n; return num / (1f + num); } internal static bool Roll(float chance, CharacterBody body) { if (chance <= 0f) { return false; } CharacterMaster val = (Object.op_Implicit((Object)(object)body) ? body.master : null); return Util.CheckRoll(Mathf.Clamp01(chance) * 100f, val); } internal static void Radiation(CharacterBody body, out int positive, out int resist) { positive = 0; resist = 0; ItemSpec[] all = Specs.All; for (int i = 0; i < all.Length; i++) { int rad = all[i].Rad; if (rad == 0) { continue; } int num = N(body, all[i].Id); if (num > 0) { if (rad > 0) { positive += rad * num; } else { resist += -rad * num; } } } } internal static int NetRadiation(CharacterBody body, out int surplus) { Radiation(body, out var positive, out var resist); surplus = Mathf.Max(0, resist - positive); int num = Mathf.Max(0, positive - resist); int num2 = N(body, ZId.HeartOfChornobyl); if (num2 > 0) { num *= 1 + num2; } return num; } internal unsafe static DotKind Classify(DotIndex index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown int key = (int)index; if (DotCache.TryGetValue(key, out var value)) { return value; } string text = ((object)(*(DotIndex*)(&index))/*cast due to .constrained prefix*/).ToString(); value = ((text.IndexOf("Burn", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Helfire", StringComparison.OrdinalIgnoreCase) >= 0) ? DotKind.Burn : ((text.IndexOf("Bleed", StringComparison.OrdinalIgnoreCase) >= 0) ? DotKind.Bleed : ((text.IndexOf("Poison", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Blight", StringComparison.OrdinalIgnoreCase) < 0) ? DotKind.Other : DotKind.Chem))); DotCache[key] = value; return value; } internal static List<CharacterBody> Enemies(CharacterBody me) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between I4 and Unknown List<CharacterBody> list = new List<CharacterBody>(); TeamIndex val = (TeamIndex)((!Object.op_Implicit((Object)(object)me.teamComponent)) ? (-1) : ((int)me.teamComponent.teamIndex)); for (int i = 0; i < AllTeams.Length; i++) { if ((int)AllTeams[i] == (int)val) { continue; } foreach (TeamComponent teamMember in TeamComponent.GetTeamMembers(AllTeams[i])) { if (Object.op_Implicit((Object)(object)teamMember)) { CharacterBody body = teamMember.body; if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && body.healthComponent.alive) { list.Add(body); } } } } return list; } internal static CharacterBody Nearest(CharacterBody me, float range) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) CharacterBody result = null; float num = range * range; Vector3 corePosition = me.corePosition; foreach (CharacterBody item in Enemies(me)) { Vector3 val = item.corePosition - corePosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num && Object.op_Implicit((Object)(object)item.mainHurtBox)) { num = sqrMagnitude; result = item; } } return result; } internal static void Zap(CharacterBody attacker, CharacterBody target, float damageMult, int bounces, float range) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)attacker) && Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)target.mainHurtBox) && Object.op_Implicit((Object)(object)attacker.teamComponent) && !((Object)(object)OrbManager.instance == (Object)null)) { LightningOrb val = new LightningOrb { origin = attacker.corePosition, damageValue = attacker.damage * damageMult, isCrit = false, bouncesRemaining = Mathf.Max(0, bounces), teamIndex = attacker.teamComponent.teamIndex, attacker = ((Component)attacker).gameObject, procCoefficient = 0f, bouncedObjects = new List<HealthComponent>(), lightningType = (LightningType)0, damageColorIndex = (DamageColorIndex)3, range = range, target = target.mainHurtBox }; OrbManager.instance.AddOrb((Orb)(object)val); } } internal static void Ignite(CharacterBody attacker, CharacterBody victim, float seconds) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)attacker) && Object.op_Implicit((Object)(object)victim)) { InflictDotInfo val = new InflictDotInfo { victimObject = ((Component)victim).gameObject, attackerObject = ((Component)attacker).gameObject, dotIndex = (DotIndex)1, duration = seconds, damageMultiplier = 1f }; DotController.InflictDot(ref val); } } internal static void Pull(CharacterBody target, Vector3 dir, float speed) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) CharacterMotor characterMotor = target.characterMotor; if (Object.op_Implicit((Object)(object)characterMotor)) { characterMotor.ApplyForce(dir * speed * characterMotor.mass, true, false); return; } Rigidbody component = ((Component)target).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component)) { component.AddForce(dir * speed * component.mass, (ForceMode)1); } } static Z() { TeamIndex[] array = new TeamIndex[4]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); AllTeams = (TeamIndex[])(object)array; DotCache = new Dictionary<int, DotKind>(); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.zoneartifacts.ZoneArtifacts", "ZoneArtifacts", "0.1.2")] public class ZoneArtifactsPlugin : BaseUnityPlugin { public const string PluginGuid = "com.zoneartifacts.ZoneArtifacts"; public const string PluginName = "ZoneArtifacts"; public const string PluginVersion = "0.1.2"; internal static ManualLogSource Log; internal static ConfigEntry<bool> RadiationEnabled; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; RadiationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "RadiationEnabled", true, "Enable the shared radiation mechanic. Every point of net radiation lowers health regeneration and maximum health. Artifacts with radiation resistance cancel it. If false, radiation penalties (and the Heart of Chornobyl damage bonus) are disabled."); ItemFactory.RegisterAll(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)); Hooks.Install(); Log.LogInfo((object)string.Format("{0} {1} loaded, {2} items defined.", "ZoneArtifacts", "0.1.2", Specs.All.Length)); } } public class ZoneController : MonoBehaviour { private CharacterBody _body; private bool _started; private bool _wasCalm = true; private float _lastHitTime = -999f; private float _tThunder; private float _tHeart; private float _tBlack; private float _tStumble; private float _bubbleCd; private float _staticCd; public bool IsCalm => Time.time - _lastHitTime >= 5f; public bool StaticReady => _staticCd <= 0f; public void StaticUsed() { _staticCd = 1.5f; } public void MarkHit() { _lastHitTime = Time.time; if (_wasCalm) { _wasCalm = false; if (Object.op_Implicit((Object)(object)_body)) { _body.MarkAllStatsDirty(); } } } private void Awake() { _body = ((Component)this).GetComponent<CharacterBody>(); } private void FixedUpdate() { if (!Object.op_Implicit((Object)(object)_body) || !Object.op_Implicit((Object)(object)_body.inventory)) { return; } bool isCalm = IsCalm; if (isCalm != _wasCalm) { _wasCalm = isCalm; if (Z.N(_body, ZId.Sun) > 0) { _body.MarkAllStatsDirty(); } } if (!NetworkServer.active) { return; } HealthComponent healthComponent = _body.healthComponent; if (Object.op_Implicit((Object)(object)healthComponent) && healthComponent.alive) { float fixedDeltaTime = Time.fixedDeltaTime; if (!_started) { _started = true; OnFirstTick(healthComponent); } if (_staticCd > 0f) { _staticCd -= fixedDeltaTime; } if (_bubbleCd > 0f) { _bubbleCd -= fixedDeltaTime; } TickThunderberry(fixedDeltaTime); TickBubble(healthComponent); TickHeart(healthComponent, fixedDeltaTime); TickBlackHole(fixedDeltaTime); TickWeirdWater(fixedDeltaTime); } } private void OnFirstTick(HealthComponent hc) { int num = Z.N(_body, ZId.WeirdFlower); if (num > 0) { float num2 = 8f + 3f * (float)(num - 1); _body.AddTimedBuff(Buffs.Cloak, num2); _body.AddTimedBuff(Buffs.CloakSpeed, num2); } int num3 = Z.N(_body, ZId.WeirdBolt); if (num3 > 0) { hc.AddBarrier(hc.fullCombinedHealth * 0.2f * (float)num3); } } private void TickThunderberry(float dt) { if (Z.N(_body, ZId.Thunderberry) <= 0) { return; } if (!_body.isSprinting) { _tThunder = Mathf.Min(_tThunder, 1f); return; } _tThunder += dt; if (!(_tThunder < 2f)) { CharacterBody val = Z.Nearest(_body, 28f); if (Object.op_Implicit((Object)(object)val)) { _tThunder = 0f; Z.Zap(_body, val, 2.5f, 3, 20f); } } } private void TickBubble(HealthComponent hc) { int num = Z.N(_body, ZId.Bubble); if (num > 0 && !(_bubbleCd > 0f) && !(hc.combinedHealthFraction > 0.5f)) { hc.AddBarrier(hc.fullCombinedHealth * 0.12f * (float)num); _bubbleCd = 15f; } } private void TickHeart(HealthComponent hc, float dt) { int num = Z.N(_body, ZId.Heart); if (num > 0) { _tHeart += dt; if (!(_tHeart < 6f)) { _tHeart = 0f; Z.SelfHeal(hc, hc.fullHealth * 0.025f * (float)num); } } } private void TickBlackHole(float dt) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) int num = Z.N(_body, ZId.BlackHole); if (num <= 0) { return; } float num2 = Mathf.Max(4f, 10f - 1f * (float)(num - 1)); _tBlack += dt; if (_tBlack < num2) { return; } _tBlack = 0f; Vector3 corePosition = _body.corePosition; foreach (CharacterBody item in Z.Enemies(_body)) { Vector3 val = corePosition - item.corePosition; float magnitude = ((Vector3)(ref val)).magnitude; if (!(magnitude > 22f) && !(magnitude < 1.5f)) { Z.Pull(item, val / magnitude, 14f); item.AddTimedBuff(Buffs.Slow60, 1.5f); } } } private void TickWeirdWater(float dt) { if (Z.N(_body, ZId.WeirdWater) > 0) { _tStumble += dt; if (!(_tStumble < 30f)) { _tStumble = 0f; _body.AddTimedBuff(Buffs.Slow60, 2f); } } } }