Пример #1
0
 private void Start()
 {
     instance       = this;
     MoveSpeed      = 1f;
     MutationPoints = 1;
     ExpGoal        = GetGoalExp();
     if (!GameSetup.IsNewGame)
     {
         Serializer.Load();
     }
 }
Пример #2
0
 private void Start()
 {
     instance       = this;
     MoveSpeed      = 1f;
     MutationPoints = 1;
     ExpGoal        = GetGoalExp();
     if (!GameSetup.IsNewGame)
     {
         Serializer.Load();
     }
     InitializeHandHeld();
     Invoke("SendJoinMessage", 10);
 }
        public static void PopulateStats()
        {
            var scAdd  = new ItemStat.StatCompare(x => { return(x.Sum()); });
            var scMult = new ItemStat.StatCompare(x =>
            {
                float f = 1;
                for (int j = 0; j < x.Count; j++)
                {
                    f *= x[j];
                }
                return(f - 1);
            });
            var scMultPlusOne = new ItemStat.StatCompare(x =>
            {
                float f = 1;
                for (int j = 0; j < x.Count; j++)
                {
                    f *= 1 + x[j];
                }
                return(f);
            });
            var scOneMinusMult = new ItemStat.StatCompare(x =>
            {
                float f = 1;
                for (int k = 0; k < x.Count; k++)
                {
                    f *= 1 - x[k];
                }
                return(1 - f);
            });

            int i = 1;

            new ItemStat(i, 1.5f, 2.5f, 0.83f, "Strength", scAdd, 4,
                         () => ModdedPlayer.Stats.strength.GetFormattedAmount(), StatActions.AddStrength, StatActions.RemoveStrength, StatActions.AddStrength);
            i++;
            new ItemStat(i, 1.5f, 2.5f, 0.83f, "Agility", scAdd, 4, () => ModdedPlayer.Stats.agility.GetFormattedAmount(), StatActions.AddAgility, StatActions.RemoveAgility, StatActions.AddAgility);
            i++;
            new ItemStat(i, 1.5f, 2.5f, 0.83f, "Vitality", scAdd, 4, () => ModdedPlayer.Stats.vitality.GetFormattedAmount(), StatActions.AddVitality, StatActions.RemoveVitality, StatActions.AddVitality);
            i++;
            new ItemStat(i, 1.5f, 2.5f, 0.83f, "Intelligence", scAdd, 4, () => ModdedPlayer.Stats.intelligence.GetFormattedAmount(), StatActions.AddIntelligence, StatActions.RemoveIntelligence, StatActions.AddIntelligence);
            i++;
            new ItemStat(i, 2.8f, 4.5f, 1.2f, "Maximum Life", scAdd, 3, () => ModdedPlayer.Stats.maxHealth.GetFormattedAmount(), StatActions.AddHealth, StatActions.RemoveHealth, StatActions.AddHealth);
            i++;
            new ItemStat(i, 1f, 1.25f, 1.2f, "Maximum Energy", scAdd, 3, () => ModdedPlayer.Stats.maxEnergy.GetFormattedAmount(), StatActions.AddEnergy, StatActions.RemoveEnergy, StatActions.AddEnergy);
            i++;
            new ItemStat(i, 0.015f, 0.0275f, 1.2f, "Life Per Second", scAdd, 3, () => ModdedPlayer.Stats.healthRecoveryPerSecond.GetFormattedAmount(), StatActions.AddHPRegen, StatActions.RemoveHPRegen, StatActions.AddHPRegen)
            {
                DisplayAsPercent = false, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.02f, 0.031f, 1.2f, "Stamina Per Second", scAdd, 2, () => ModdedPlayer.Stats.staminaRecoveryperSecond.GetFormattedAmount(), StatActions.AddStaminaRegen, StatActions.RemoveStaminaRegen, StatActions.AddStaminaRegen)
            {
                DisplayAsPercent = false, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.019f, 0.025f, 0.5f, "Stamina Regeneration", scAdd, 5, () => ModdedPlayer.Stats.staminaPerSecRate.GetFormattedAmount(), StatActions.AddStaminaRegenPercent, StatActions.RemoveStaminaRegenPercent, StatActions.AddStaminaRegenPercent)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 1.5f
            };
            i++;
            new ItemStat(i, 0.019f, 0.025f, 0.5f, "Life Regeneration", scAdd, 5, () => ModdedPlayer.Stats.healthPerSecRate.GetFormattedAmount(), StatActions.AddHealthRegenPercent, StatActions.RemoveHealthRegenPercent, StatActions.AddHealthRegenPercent)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 1.5f
            };
            i++;
            new ItemStat(i, 0.003f, 0.007f, 0.5f, "Damage Reduction", scOneMinusMult, 4, () => (1 - ModdedPlayer.Stats.allDamageTaken).ToString("P"), StatActions.AddDamageReduction, StatActions.RemoveDamageReduction, StatActions.AddDamageReduction)
            {
                ValueCap = 0.3f, DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.008f, 0.013f, 0.25f, "Critical Hit Chance", scAdd, 6, () => ModdedPlayer.Stats.critChance.GetFormattedAmount(), StatActions.AddCritChance, StatActions.RemoveCritChance, StatActions.AddCritChance)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 0.2f
            };
            i++;
            new ItemStat(i, 0.0016f, 0.00215f, 1.25f, "Critical Hit Damage", scAdd, 6, () => ModdedPlayer.Stats.critDamage.GetFormattedAmount(), StatActions.AddCritDamage, StatActions.RemoveCritDamage, StatActions.AddCritDamage)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 3f
            };
            i++;
            new ItemStat(i, 0.07f, 0.14f, 1f, "Life on hit", scAdd, 4, () => ModdedPlayer.Stats.healthOnHit.GetFormattedAmount(), StatActions.AddLifeOnHit, StatActions.RemoveLifeOnHit, StatActions.AddLifeOnHit);
            i++;
            new ItemStat(i, 0.003f, 0.004f, 0.5f, "Dodge chance", scOneMinusMult, 4, () => (1 - ModdedPlayer.Stats.getHitChance).ToString("P"), StatActions.AddDodgeChance, StatActions.RemoveDodgeChance, StatActions.AddDodgeChance)
            {
                ValueCap = 0.35f, DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 4f, 6f, 1.12f, "Armor", scAdd, 3, () => ModdedPlayer.Stats.armor.GetFormattedAmount(), StatActions.AddArmor, StatActions.RemoveArmor, StatActions.AddArmor);
            i++;
            new ItemStat(i, 0.004f, 0.006f, 0.5f, "Resistance to magic", scOneMinusMult, 5, () => (1 - ModdedPlayer.Stats.magicDamageTaken).ToString("P"), StatActions.AddMagicResistance, StatActions.RemoveMagicResistance, StatActions.AddMagicResistance)
            {
                ValueCap = 0.35f, DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.006f, 0.009f, 0.4f, "Attack speed", scAdd, 6, () => ModdedPlayer.Stats.attackSpeed.GetFormattedAmount(), StatActions.AddAttackSpeed, StatActions.RemoveAttackSpeed, StatActions.AddAttackSpeed)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.005f, 0.02f, 0.25f, "Experience gain", scMult, 7, () => ModdedPlayer.Stats.expGain.GetFormattedAmount(), StatActions.AddExpFactor, StatActions.RemoveExpFactor, StatActions.AddExpFactor)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 1f
            };
            i++;
            new ItemStat(i, 1.5f, 1.8f, 0f, "Massacre Duration", scAdd, 7, () => ModdedPlayer.Stats.maxMassacreTime.GetFormattedAmount(), StatActions.AddMaxMassacreTime, StatActions.RemoveMaxMassacreTime, StatActions.AddMaxMassacreTime)
            {
                RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.014f, 0.017f, 0.45f, "Spell Damage Increase", scAdd, 5, () => ModdedPlayer.Stats.spellIncreasedDmg.GetFormattedAmount(), StatActions.AddSpellDamageAmplifier, StatActions.RemoveSpellDamageAmplifier, StatActions.AddSpellDamageAmplifier)
            {
                DisplayAsPercent = true,
                RoundingCount    = 1,
                ValueCap         = 1f
            };
            i++;
            new ItemStat(i, 0.014f, 0.017f, 0.45f, "Melee Damage Increase", scAdd, 5, () => ModdedPlayer.Stats.meleeIncreasedDmg.GetFormattedAmount(), StatActions.AddMeleeDamageAmplifier, StatActions.RemoveMeleeDamageAmplifier, StatActions.AddMeleeDamageAmplifier)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 1f
            };
            i++;
            new ItemStat(i, 0.014f, 0.017f, 0.45f, "Ranged Damage Increase", scAdd, 5, () => ModdedPlayer.Stats.rangedIncreasedDmg.GetFormattedAmount(), StatActions.AddRangedDamageAmplifier, StatActions.RemoveRangedDamageAmplifier, StatActions.AddRangedDamageAmplifier)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 1f
            };
            i++;
            new ItemStat(i, 0.9f, 1.2f, 1.2f, "Base Spell Damage", scAdd, 4, () => ModdedPlayer.Stats.spellFlatDmg.GetFormattedAmount(), StatActions.AddspellFlatDmg, StatActions.RemovespellFlatDmg, StatActions.AddspellFlatDmg);
            i++;
            new ItemStat(i, 0.8f, 1f, 1.2f, "Base Melee Damage", scAdd, 4, () => ModdedPlayer.Stats.meleeFlatDmg.GetFormattedAmount(), StatActions.AddMeleeDamageBonus, StatActions.RemoveMeleeDamageBonus, StatActions.AddMeleeDamageBonus);
            i++;
            new ItemStat(i, 0.8f, 1f, 1.2f, "Base Ranged Damage", scAdd, 4, () => ModdedPlayer.Stats.rangedFlatDmg.GetFormattedAmount(), StatActions.AddRangedDamageBonus, StatActions.RemoveRangedDamageBonus, StatActions.AddRangedDamageBonus);
            i++;
            new ItemStat(i, 0.011f, 0.015f, 0f, "Energy Per Agility", scAdd, 7, () => ModdedPlayer.Stats.maxEnergyFromAgi.GetFormattedAmount(), StatActions.AddmaxEnergyFromAgi, StatActions.RemovemaxEnergyFromAgi, StatActions.AddmaxEnergyFromAgi)
            {
                DisplayAsPercent = false, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.07f, 0.1f, 0f, "Health Per Vitality", scAdd, 7, () => ModdedPlayer.Stats.maxHealthFromVit.GetFormattedAmount(), StatActions.AddmaxHealthFromVit, StatActions.RemovemaxHealthFromVit, StatActions.AddmaxHealthFromVit)
            {
                DisplayAsPercent = false, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.0013f, 0.0023f, 0f, "Spell Damage Per Int", scAdd, 7, () => ModdedPlayer.Stats.spellDmgFromInt.GetFormattedAmount(), StatActions.AddspellDmgFromInt, StatActions.RemovespellDmgFromInt, StatActions.AddspellDmgFromInt)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.0013f, 0.0023f, 0f, "Melee Damage Per Strength", scAdd, 7, () => ModdedPlayer.Stats.meleeDmgFromStr.GetFormattedAmount(), StatActions.AddmeleeDmgFromStr, StatActions.RemovemeleeDmgFromStr, StatActions.AddmeleeDmgFromStr)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.0015f, 0.003f, 0.6f, "All Recovery", scMultPlusOne, 6, () => ModdedPlayer.Stats.allRecoveryMult.GetFormattedAmount(), StatActions.AddHealingMultipier, StatActions.RemoveHealingMultipier, StatActions.AddHealingMultipier)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 1f / 4f, 1f / 4f, 0f, "PERMANENT PERK POINTS", scAdd, 6, () => ModdedPlayer.instance.MutationPoints.ToString(), null, null, StatActions.PERMANENT_perkPointIncrease);
            i++;
            new ItemStat(i, 100f, 100f, 3.5f, "EXPERIENCE", scAdd, 5, () => ModdedPlayer.instance.ExpCurrent.ToString("N") + " / " + ModdedPlayer.instance.ExpGoal.ToString("N"), null, null, StatActions.PERMANENT_expIncrease);
            i++;
            new ItemStat(i, 0.01f, 0.02f, 0.4f, "Movement Speed", scAdd, 6, () => ModdedPlayer.Stats.movementSpeed.GetFormattedAmount(), StatActions.AddMoveSpeed, StatActions.RemoveMoveSpeed, StatActions.AddMoveSpeed)
            {
                DisplayAsPercent = true, RoundingCount = 2, ValueCap = 0.3f
            };
            i++;
            new ItemStat(i, 0.008f, 0.01f, 0.5f, "Weapon Size", scMultPlusOne, 4, () => ModdedPlayer.Stats.weaponRange.GetFormattedAmount(), f => ModdedPlayer.Stats.weaponRange.Multiply(1 + f), f => ModdedPlayer.Stats.weaponRange.Divide(1 + f), null)
            {
                DisplayAsPercent = true, RoundingCount = 2, ValueCap = 0.4f
            };
            i++;
            new ItemStat(i, 0.01f, 0.015f, 0.4f, "Attack Cost Reduction", scOneMinusMult, 3, () => (ModdedPlayer.Stats.attackStaminaCost - 1).ToString("P"), f => ModdedPlayer.Stats.attackStaminaCost.Multiply(1 - f), f => ModdedPlayer.Stats.attackStaminaCost.Divide(1 - f))
            {
                DisplayAsPercent = true, RoundingCount = 2, ValueCap = 0.6f
            };
            i++;
            new ItemStat(i, 0.004f, 0.006f, 0.4f, "Spell Cost Reduction", scOneMinusMult, 6, () => (1 - ModdedPlayer.Stats.spellCost).ToString("P"), f => ModdedPlayer.Stats.spellCost.valueMultiplicative *= 1 - f, f => ModdedPlayer.Stats.spellCost.valueMultiplicative /= 1 - f, f => ModdedPlayer.Stats.spellCost.valueMultiplicative *= 1 - f)
            {
                DisplayAsPercent = true, RoundingCount = 2, ValueCap = 0.4f
            };
            i++;
            new ItemStat(i, 0.0075f, 0.01f, 0.4f, "Spell Cost to Stamina", scOneMinusMult, 5, () => (ModdedPlayer.Stats.SpellCostToStamina).ToString("P"), f => ModdedPlayer.Stats.spellCostEnergyCost.Multiply(1 - f), f => ModdedPlayer.Stats.spellCostEnergyCost.Divide(1 - f))
            {
                ValueCap = 0.55f, DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.6f, 0.8f, 0.85f, "Strength", scAdd, 2, () => ModdedPlayer.Stats.strength.GetFormattedAmount(), StatActions.AddStrength, StatActions.RemoveStrength, StatActions.AddStrength);
            i++;
            new ItemStat(i, 0.6f, 0.8f, 0.85f, "Agility", scAdd, 2, () => ModdedPlayer.Stats.agility.GetFormattedAmount(), StatActions.AddAgility, StatActions.RemoveAgility, StatActions.AddAgility);
            i++;
            new ItemStat(i, 0.6f, 0.8f, 0.85f, "Vitality", scAdd, 2, () => ModdedPlayer.Stats.vitality.GetFormattedAmount(), StatActions.AddVitality, StatActions.RemoveVitality, StatActions.AddVitality);
            i++;
            new ItemStat(i, 0.6f, 0.8f, 0.85f, "Intelligence", scAdd, 2, () => ModdedPlayer.Stats.intelligence.GetFormattedAmount(), StatActions.AddIntelligence, StatActions.RemoveIntelligence, StatActions.AddIntelligence);
            i++;
            new ItemStat(i, 1f, 1.1f, 1.12f, "Armor", scAdd, 2, () => ModdedPlayer.Stats.armor.GetFormattedAmount(), StatActions.AddArmor, StatActions.RemoveArmor, StatActions.AddArmor);
            i++;
            new ItemStat(i, 0.003f, 0.005f, 0.8f, "Energy Per Second", scAdd, 5, () => ModdedPlayer.Stats.energyRecoveryperSecond.GetFormattedAmount(), StatActions.AddEnergyRegen, StatActions.RemoveEnergyRegen, StatActions.AddEnergyRegen)
            {
                RoundingCount = 3
            };
            i++;
            new ItemStat(i, 0.004f, 0.0065f, 0.5f, "Maximum Life", scAdd, 6, () => ModdedPlayer.Stats.maxHealthMult.GetFormattedAmount(), f => ModdedPlayer.Stats.maxHealthMult.valueAdditive += f, f => ModdedPlayer.Stats.maxHealthMult.valueAdditive -= f)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.004f, 0.0065f, 0.5f, "Maximum Energy", scAdd, 6, () => ModdedPlayer.Stats.maxEnergyMult.GetFormattedAmount(), f => ModdedPlayer.Stats.maxEnergyMult.valueAdditive += f, f => ModdedPlayer.Stats.maxEnergyMult.valueAdditive -= f, f => ModdedPlayer.Stats.maxEnergyMult.valueAdditive += f)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.004f, 0.005f, 0.5f, "Cooldown Reduction", scOneMinusMult, 6, () => (1 - ModdedPlayer.Stats.cooldown).ToString("P"), f => ModdedPlayer.Stats.cooldown.valueMultiplicative *= (1 - f), f => ModdedPlayer.Stats.cooldown.valueMultiplicative /= (1 - f), f => ModdedPlayer.Stats.cooldown.valueMultiplicative *= (1 - f))
            {
                DisplayAsPercent = true, RoundingCount = 2, ValueCap = 0.5f
            };
            i++;
            new ItemStat(i, 0.0015f, 0.0023f, 0f, "Ranged Damage Per Agi", scAdd, 7, () => ModdedPlayer.Stats.rangedDmgFromAgi.GetFormattedAmount(), f => ModdedPlayer.Stats.rangedDmgFromAgi.valueAdditive += f, f => ModdedPlayer.Stats.rangedDmgFromAgi.valueAdditive += -f, f => ModdedPlayer.Stats.rangedDmgFromAgi.valueAdditive += f)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.02f, 0.03f, 0.7f, "Energy on hit", scAdd, 4, () => ModdedPlayer.Stats.energyOnHit.GetFormattedAmount(), f => ModdedPlayer.Stats.energyOnHit.valueAdditive += f, f => ModdedPlayer.Stats.energyOnHit.valueAdditive += -f, f => ModdedPlayer.Stats.energyOnHit.valueAdditive += f)
            {
                RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.0175f, 0.02f, 0.5f, "Block", scAdd, 1, () => ModdedPlayer.Stats.block.GetFormattedAmount(), f => ModdedPlayer.Stats.block.valueAdditive += f, f => ModdedPlayer.Stats.block.valueAdditive += -f, f => ModdedPlayer.Stats.block.valueAdditive += f)
            {
                ValueCap = 0.5f, DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.03f, 0.04f, 0.5f, "Projectile speed", scAdd, 4, () => ModdedPlayer.Stats.projectileSpeed.GetFormattedAmount(), f => ModdedPlayer.Stats.projectileSpeed.valueAdditive += f, f => ModdedPlayer.Stats.projectileSpeed.valueAdditive += -f, f => ModdedPlayer.Stats.projectileSpeed.valueAdditive += f)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.02f, 0.025f, 0.4f, "Projectile size", scAdd, 4, () => ModdedPlayer.Stats.projectileSize.GetFormattedAmount(), f => ModdedPlayer.Stats.projectileSize.valueAdditive += f, f => ModdedPlayer.Stats.projectileSize.valueAdditive += -f, f => ModdedPlayer.Stats.projectileSize.valueAdditive += f)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 1f, 1.25f, 1.21f, "Melee armor piercing", scAdd, 5, () => ModdedPlayer.Stats.TotalMeleeArmorPiercing.ToString(), f => ModdedPlayer.Stats.meleeArmorPiercing.valueAdditive += Mathf.RoundToInt(f), f => ModdedPlayer.Stats.meleeArmorPiercing.valueAdditive += -Mathf.RoundToInt(f), f => ModdedPlayer.Stats.meleeArmorPiercing.valueAdditive += Mathf.RoundToInt(f));
            i++;
            new ItemStat(i, 0.65f, 0.9f, 1.2f, "Ranged armor piercing", scAdd, 5, () => ModdedPlayer.Stats.TotalRangedArmorPiercing.ToString(), f => ModdedPlayer.Stats.rangedArmorPiercing.valueAdditive += Mathf.RoundToInt(f), f => ModdedPlayer.Stats.rangedArmorPiercing.valueAdditive += -Mathf.RoundToInt(f), f => ModdedPlayer.Stats.rangedArmorPiercing.valueAdditive += Mathf.RoundToInt(f));
            i++;
            new ItemStat(i, 0.65f, 0.88f, 1.2f, "Armor piercing", scAdd, 5, () => $"M{ModdedPlayer.Stats.TotalMeleeArmorPiercing} R{ModdedPlayer.Stats.TotalRangedArmorPiercing}", f => ModdedPlayer.Stats.allArmorPiercing.valueAdditive += Mathf.RoundToInt(f), f => ModdedPlayer.Stats.allArmorPiercing.valueAdditive += -Mathf.RoundToInt(f), f => ModdedPlayer.Stats.allArmorPiercing.valueAdditive += Mathf.RoundToInt(f));
            i++;
            new ItemStat(i, 0.01f, 0.0145f, 0.4f, "Magic Find", scMultPlusOne, 7, () => ModdedPlayer.Stats.magicFind.Value.ToString("P"), StatActions.AddMagicFind, StatActions.RemoveMagicFind, StatActions.AddMagicFind)
            {
                DisplayAsPercent = true, RoundingCount = 1, ValueCap = 0.25f
            };
            i++;
            new ItemStat(i, 0.5f, 0.78f, 0.8f, "All attributes", scAdd, 4, () => $"S{ModdedPlayer.Stats.strength} A{ModdedPlayer.Stats.agility} I{ModdedPlayer.Stats.intelligence} V{ModdedPlayer.Stats.vitality}", StatActions.AddAllStats, StatActions.RemoveAllStats, StatActions.AddAllStats);
            i++;
            new ItemStat(i, 0, 0, 0, "Refund points", scAdd, 7, () => "", f => ModdedPlayer.Respec(), f => ModdedPlayer.Respec(), f => ModdedPlayer.Respec());
            i++;
            new ItemStat(i, 0.008f, 0.01f, 0.4f, "Jump Power", scAdd, 4, () => ModdedPlayer.Stats.jumpPower.GetFormattedAmount(), StatActions.AddJump, StatActions.RemoveJump, StatActions.AddJump)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.052f, 0.068f, 0.45f, "Headshot Damage", scMultPlusOne, 4, () => ModdedPlayer.Stats.headShotDamage.GetFormattedAmount(), f => ModdedPlayer.Stats.headShotDamage.valueMultiplicative *= 1 + f, f => ModdedPlayer.Stats.headShotDamage.valueMultiplicative /= 1 + f, null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.011f, 0.016f, 0.4f, "Fire Damage", scAdd, 4, () => ModdedPlayer.Stats.fireDamage.GetFormattedAmount(), f => ModdedPlayer.Stats.fireDamage.valueAdditive += f, f => ModdedPlayer.Stats.fireDamage.valueAdditive -= f, null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.008f, 0.01f, 0.5f, "Chance on hit to slow", scAdd, 3, () => ModdedPlayer.Stats.chanceToSlow.GetFormattedAmount(), f => ModdedPlayer.Stats.chanceToSlow.valueAdditive += f, f => ModdedPlayer.Stats.chanceToSlow.valueAdditive -= f, null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.007f, 0.01f, 0.5f, "Chance on hit to bleed", scAdd, 3, () => ModdedPlayer.Stats.chanceToBleed.GetFormattedAmount(), f => ModdedPlayer.Stats.chanceToBleed.valueAdditive += f, f => ModdedPlayer.Stats.chanceToBleed.valueAdditive -= f, null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 0.008f, 0.01f, 0.5f, "Chance on hit to weaken", scAdd, 3, () => ModdedPlayer.Stats.chanceToWeaken.GetFormattedAmount(), f => ModdedPlayer.Stats.chanceToWeaken.valueAdditive += f, f => ModdedPlayer.Stats.chanceToWeaken.valueAdditive -= f, null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            new ItemStat(i, 1.1f, 1.3f, 1.23f, "Thorns", scAdd, 4, () => ModdedPlayer.Stats.thorns.GetFormattedAmount(), f => ModdedPlayer.Stats.thorns.valueAdditive += f, f => ModdedPlayer.Stats.thorns.valueAdditive -= f, f => ModdedPlayer.Stats.thorns.valueAdditive += f);
            ;
            i++;
            new ItemStat(i, 0.065f, 0.08f, 0.5f, "Projectile pierce chance", scAdd, 6, () => ModdedPlayer.Stats.projectilePierceChance.GetFormattedAmount(), f => ModdedPlayer.Stats.projectilePierceChance.valueAdditive += f, f => ModdedPlayer.Stats.projectilePierceChance.valueAdditive += -f, f => ModdedPlayer.Stats.projectilePierceChance.valueAdditive += f)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.06f, 0.08f, 1f, "Explosive damage", scAdd, 6, () => ModdedPlayer.Stats.explosionDamage.GetFormattedAmount(), f => ModdedPlayer.Stats.explosionDamage.Add(f), f => ModdedPlayer.Stats.projectilePierceChance.Substract(f))
            {
                RoundingCount = 1
            };
            i++;

            //Extra carry items
            i = 1000;
            new ItemStat(i, 9f, 15f, 0f, "Extra Carried Sticks", scAdd, 4, () => LocalPlayer.Inventory.GetMaxAmountOf(57).ToString(), f => ModdedPlayer.instance.AddExtraItemCapacity(57, Mathf.RoundToInt(f)), f => ModdedPlayer.instance.AddExtraItemCapacity(57, -Mathf.RoundToInt(f)), null);
            i++;
            new ItemStat(i, 7f, 10f, 0f, "Extra Carried Rocks", scAdd, 4, () => LocalPlayer.Inventory.GetMaxAmountOf(53).ToString(), f => ModdedPlayer.instance.AddExtraItemCapacity(53, Mathf.RoundToInt(f)), f => ModdedPlayer.instance.AddExtraItemCapacity(53, -Mathf.RoundToInt(f)), null);
            i++;
            new ItemStat(i, 6f, 8f, 0f, "Extra Carried Ropes", scAdd, 4, () => LocalPlayer.Inventory.GetMaxAmountOf(43).ToString(), f => ModdedPlayer.instance.AddExtraItemCapacity(54, Mathf.RoundToInt(f)), f => ModdedPlayer.instance.AddExtraItemCapacity(43, -Mathf.RoundToInt(f)), null);
            i++;
            new ItemStat(i, 9f, 15f, 0f, "Extra Carried Drinks", scAdd, 4, () => "Booze: " + LocalPlayer.Inventory.GetMaxAmountOf((int)MoreCraftingReceipes.VanillaItemIDs.BOOZE).ToString() + " Soda: " + LocalPlayer.Inventory.GetMaxAmountOf((int)MoreCraftingReceipes.VanillaItemIDs.SODA), f =>
            {
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BOOZE, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.SODA, Mathf.RoundToInt(f));
            },
                         f =>
            {
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BOOZE, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.SODA, -Mathf.RoundToInt(f));
            },
                         null);
            i++;
            new ItemStat(i, 7f, 10f, 0f, "Extra Carried Food", scAdd, 4, () => "...", f =>
            {
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.GENERICMEAT, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.SMALLGENERICMEAT, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BLACKBERRY, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BLUEBERRY, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.CHOCOLATEBAR, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.LIZARD, Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.RABBITDEAD, Mathf.RoundToInt(f));
            },
                         f =>
            {
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.GENERICMEAT, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.SMALLGENERICMEAT, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BLACKBERRY, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.BLUEBERRY, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.CHOCOLATEBAR, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.LIZARD, -Mathf.RoundToInt(f));
                ModdedPlayer.instance.AddExtraItemCapacity((int)MoreCraftingReceipes.VanillaItemIDs.RABBITDEAD, -Mathf.RoundToInt(f));
            },
                         null);
            i++;


            i = 2000;
            new ItemStat(i, 16f, 20f, 0f, "Black Hole Size", scAdd, 6, () => ModdedPlayer.Stats.spell_blackhole_radius.GetFormattedAmount(), f => ModdedPlayer.Stats.spell_blackhole_radius.valueAdditive += f, f => ModdedPlayer.Stats.spell_blackhole_radius.valueAdditive += -f, f => ModdedPlayer.Stats.spell_blackhole_radius.valueAdditive += f)
            {
                RoundingCount = 1
            };
            i++;
            new ItemStat(i, 3f, 4.5f, 0f, "Black Hole Lifetime", scAdd, 6, () => ModdedPlayer.Stats.spell_blackhole_duration.GetFormattedAmount(), f => ModdedPlayer.Stats.spell_blackhole_duration.valueAdditive += f, f => ModdedPlayer.Stats.spell_blackhole_duration.valueAdditive += -f, f => ModdedPlayer.Stats.spell_blackhole_duration.valueAdditive += f)
            {
                RoundingCount = 1
            };
            i++;
            new ItemStat(i, 6f, 9f, 0f, "Black Hole Gravitational Force", scAdd, 6, () => ModdedPlayer.Stats.spell_blackhole_pullforce.GetFormattedAmount(), f => ModdedPlayer.Stats.spell_blackhole_pullforce.valueAdditive += f, f => ModdedPlayer.Stats.spell_blackhole_pullforce.valueAdditive += -f, f => ModdedPlayer.Stats.spell_blackhole_pullforce.valueAdditive += f)
            {
                RoundingCount = 1
            };
            i++;
            new ItemStat(i, 0.4f, 0.465f, 1f, "Black Hole damage", scAdd, 6, () => ModdedPlayer.Stats.spell_blackhole_damage.GetFormattedAmount(), f => ModdedPlayer.Stats.spell_blackhole_damage.valueAdditive += f, f => ModdedPlayer.Stats.spell_blackhole_damage.valueAdditive += -f, f => ModdedPlayer.Stats.spell_blackhole_damage.valueAdditive += f)
            {
                RoundingCount = 1
            };
            i++;
            new ItemStat(i, 1, 1, 0, "Stun on hit", scAdd, 1, () => "", f => ModdedPlayer.Stats.i_HammerStun.value = true, f => ModdedPlayer.Stats.i_HammerStun.value = false, null);
            i++;
            new ItemStat(i, 3, 3.5f, 0, "Snap Freeze Duration", scAdd, 3, () => ModdedPlayer.Stats.spell_snapFreezeDuration.GetFormattedAmount(), f => ModdedPlayer.Stats.spell_snapFreezeDuration.valueAdditive += f, f => ModdedPlayer.Stats.spell_snapFreezeDuration.valueAdditive -= f, null);
            i++;
            new ItemStat(i, 1f, 1.25f, 0, "Raft Speed", scAdd, 4, () => ModdedPlayer.Stats.perk_RaftSpeedMultipier.GetFormattedAmount(), f => ModdedPlayer.Stats.perk_RaftSpeedMultipier.Add(f), f => ModdedPlayer.Stats.perk_RaftSpeedMultipier.Substract(f), null)
            {
                DisplayAsPercent = true, RoundingCount = 2
            };
            i++;
            i = 3000;
            new ItemStat(i++, 1, 3.5f, 0, "Empty Socket", scAdd, 0, null, null, null)
            {
                Multipier = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Crit Chance", scAdd, 0, null, StatActions.AddCritChance, StatActions.RemoveCritChance, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Agility", scAdd, 0, null, StatActions.AddAgility, StatActions.RemoveAgility, null)
            {
                RoundingCount = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Movement Speed", scAdd, 0, null, StatActions.AddMoveSpeed, StatActions.RemoveMoveSpeed, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Ranged Damage", scAdd, 0, null, StatActions.AddRangedDamageAmplifier, StatActions.RemoveRangedDamageAmplifier, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Ranged Armor Piercing", scAdd, 0, null, f => ModdedPlayer.Stats.rangedArmorPiercing.valueAdditive += Mathf.RoundToInt(f), f => ModdedPlayer.Stats.rangedArmorPiercing.valueAdditive += -Mathf.RoundToInt(f), null)
            {
                RoundingCount = 0
            };

            //3006
            new ItemStat(i++, 0, 0, 1, "Socketed Shark Tooth: Attack Speed", scAdd, 0, null, StatActions.AddAttackSpeed, StatActions.RemoveAttackSpeed, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socketed Shark Tooth: Strength", scAdd, 0, null, StatActions.AddStrength, StatActions.RemoveStrength, null)
            {
                RoundingCount = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socketed Shark Tooth: Damage Reduction", scOneMinusMult, 0, null, StatActions.AddDamageReduction, StatActions.RemoveDamageReduction, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socketed Shark Tooth: Melee Damage", scAdd, 0, null, StatActions.AddMeleeDamageAmplifier, StatActions.RemoveMeleeDamageAmplifier, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socketed Shark Tooth: Melee Armor Piercing", scAdd, 0, null, f => ModdedPlayer.Stats.meleeArmorPiercing.valueAdditive += Mathf.RoundToInt(f), f => ModdedPlayer.Stats.meleeArmorPiercing.valueAdditive += -Mathf.RoundToInt(f), null)
            {
                RoundingCount = 0
            };

            //30011
            new ItemStat(i++, 0, 0, 1, "Socket: Cooldown Reduction", scOneMinusMult, 0, null, f => ModdedPlayer.Stats.cooldown.valueMultiplicative *= (1 - f), f => ModdedPlayer.Stats.cooldown.valueMultiplicative /= (1 - f), null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Intelligence", scAdd, 0, null, StatActions.AddIntelligence, StatActions.RemoveIntelligence, null)
            {
                RoundingCount = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Spell Cost Reduction", scOneMinusMult, 0, null, f => ModdedPlayer.Stats.spellCost.valueMultiplicative *= 1 - f, f => ModdedPlayer.Stats.spellCost.valueMultiplicative /= 1 - f, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Spell Damage", scAdd, 0, null, StatActions.AddSpellDamageAmplifier, StatActions.RemoveSpellDamageAmplifier, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Energy On Hit", scAdd, 0, null, f => ModdedPlayer.Stats.energyOnHit.valueAdditive += f, f => ModdedPlayer.Stats.energyOnHit.valueAdditive += -f, null)
            {
                RoundingCount = 2, Multipier = 0.02f
            };

            //3016
            new ItemStat(i++, 0, 0, 1, "Socket: Experience Gain", scMultPlusOne, 0, null, StatActions.AddExpFactor, StatActions.RemoveExpFactor, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Vitality ", scAdd, 0, null, StatActions.AddVitality, StatActions.RemoveVitality, null)
            {
                RoundingCount = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Magic Find", scAdd, 0, null, f => StatActions.AddMagicFind(f), f => StatActions.AddMagicFind(-f), null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: All Healing", scMultPlusOne, 0, null, StatActions.AddHealingMultipier, StatActions.RemoveHealingMultipier, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Life Per Second", scAdd, 0, null, StatActions.AddHPRegen, StatActions.RemoveHPRegen, null)
            {
                RoundingCount = 1, Multipier = 0.04f
            };

            //3021
            new ItemStat(i++, 0, 0, 1, "Socket: Maximum Health ", scMultPlusOne, 0, null, f => ModdedPlayer.Stats.maxHealthMult.valueMultiplicative *= 1 + f, f => ModdedPlayer.Stats.maxHealthMult.valueMultiplicative /= 1 + f, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Armor ", scAdd, 0, null, StatActions.AddArmor, StatActions.RemoveArmor, null)
            {
                RoundingCount = 0
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Resistance To Magic", scOneMinusMult, 0, null, StatActions.AddMagicResistance, StatActions.RemoveMagicResistance, null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Weapon Range", scMultPlusOne, 0, null, f => ModdedPlayer.Stats.weaponRange.Multiply(1 + f), f => ModdedPlayer.Stats.weaponRange.Divide(1 + f), null)
            {
                DisplayAsPercent = true, RoundingCount = 1
            };
            new ItemStat(i++, 0, 0, 1, "Socket: Thorns", scAdd, 0, null, f => ModdedPlayer.Stats.thorns.valueAdditive += f, f => ModdedPlayer.Stats.thorns.valueAdditive -= f, null)
            {
                RoundingCount = 0, Multipier = 3f
            };
        }
Пример #4
0
        private void DoLoad(string path, out float HealthPercentage, out Dictionary <int, int> ExtraCarriedItems)
        {
            ExtraCarriedItems = new Dictionary <int, int>();
            HealthPercentage  = 1;
            try
            {
                byte[]       bytes = File.ReadAllBytes(path);
                BinaryReader buf   = new BinaryReader(new MemoryStream(bytes));

                //reading in the same order to saving
                string version = buf.ReadString();
                if (ModSettings.RequiresNewSave)
                {
                    var ver = Res.ResourceLoader.CompareVersion(version, ModSettings.RequiresNewSaveVersion);
                    if (ver == Res.ResourceLoader.Status.Newer)
                    {
                        CotfUtils.Log("last time cotf was played on this save was on version: " + version + "  \ndue to issues with this and following updates, new save will be used. Sorry for inconvenience");
                        return;
                    }
                }
                ModdedPlayer.instance.ExpCurrent = buf.ReadInt64();                           //buf.Write(ModdedPlayer.instance.ExpCurrent);
                HealthPercentage = buf.ReadSingle();                                          //buf.Write(LocalPlayer.Stats.Health / ModdedPlayer.Stats.TotalMaxHealth);
                ModdedPlayer.instance.MutationPoints = buf.ReadInt32();                       //buf.Write(ModdedPlayer.instance.MutationPoints);
                ModdedPlayer.instance.level          = buf.ReadInt32();                       //buf.Write(ModdedPlayer.instance.Level);
                ModdedPlayer.instance.AssignLevelAttributes();
                ModdedPlayer.instance.PermanentBonusPerkPoints = buf.ReadInt32();             //buf.Write(ModdedPlayer.instance.PermanentBonusPerkPoints);
                ModdedPlayer.instance.LastDayOfGeneration      = buf.ReadInt32();             //buf.Write(ModdedPlayer.instance.LastDayOfGeneration);
                ModdedPlayer.instance.ExpGoal = ModdedPlayer.instance.GetGoalExp();
                //extra carried item amounts
                //key - ID of an item
                //value - amount at the moment of saving
                int ExtraItemCount = buf.ReadInt32();                                               //buf.Write(ModdedPlayer.instance.ExtraCarryingCapactity.Count);
                for (int i = 0; i < ExtraItemCount; i++)
                {
                    int ID     = buf.ReadInt32();
                    int AMOUNT = buf.ReadInt32();
                    ExtraCarriedItems.Add(ID, AMOUNT);
                }
                //loading inventory
                int ItemSlotCount = buf.ReadInt32();
                for (int i = 0; i < ItemSlotCount; i++)
                {
                    int Slot = buf.ReadInt32();
                    int ID   = buf.ReadInt32();

                    if (ID != -1)
                    {
                        int LVL       = buf.ReadInt32();
                        int AMO       = buf.ReadInt32();
                        int StatCount = buf.ReadInt32();

                        Item LoadedItem = new Item(ItemDataBase.ItemBases[ID], AMO, 0, false)
                        {
                            level = LVL
                        };

                        for (int a = 0; a < StatCount; a++)
                        {
                            int   statID      = buf.ReadInt32();
                            int   statgroupID = buf.ReadInt32();
                            float statAMO     = buf.ReadSingle();

                            ItemStat stat = new ItemStat(ItemDataBase.Stats[statID], 1, statgroupID)
                            {
                                Amount = statAMO
                            };

                            LoadedItem.Stats.Add(stat);
                            LoadedItem.SortStats();
                        }
                        Inventory.Instance.ItemSlots[Slot] = LoadedItem;
                    }
                    else
                    {
                        Inventory.Instance.ItemSlots[Slot] = null;
                    }
                }

                //loading perks
                int perkCount = buf.ReadInt32();
                for (int i = 0; i < perkCount; i++)
                {
                    int  id         = buf.ReadInt32();
                    bool isBought   = buf.ReadBoolean();
                    int  applyCount = buf.ReadInt32();
                    PerkDatabase.perks[id].isBought = isBought;
                    try
                    {
                        if (isBought)
                        {
                            PerkDatabase.perks[id].boughtTimes = applyCount;
                            if (applyCount == 0)
                            {
                                PerkDatabase.perks[id].isApplied = true;
                                PerkDatabase.perks[id].apply();
                            }
                            else
                            {
                                for (int a = 0; a < applyCount; a++)
                                {
                                    PerkDatabase.perks[id].apply();
                                }
                                PerkDatabase.perks[id].isApplied = true;
                            }
                            PerkDatabase.perks[id].OnBuy();
                        }
                    }
                    catch (System.Exception ex)
                    {
                        ModAPI.Log.Write($"Loading perks exception: id = {id}, isBought = {isBought}, applycount ={applyCount}\n" + ex);
                    }
                }

                //loading bought spells
                int spellCount = buf.ReadInt32();
                for (int i = 0; i < spellCount; i++)
                {
                    int  ID       = buf.ReadInt32();
                    bool isBought = buf.ReadBoolean();
                    SpellDataBase.spellDictionary[ID].Bought = isBought;
                }

                //loading spell loadout
                int spellLoadoutCount = buf.ReadInt32();
                for (int i = 0; i < spellLoadoutCount; i++)
                {
                    int ID = buf.ReadInt32();
                    if (ID == -1)
                    {
                        SpellCaster.instance.infos[i].spell = null;
                    }
                    else
                    {
                        SpellCaster.instance.infos[i].spell = SpellDataBase.spellDictionary[ID];
                        SpellCaster.instance.infos[i].spell.EquippedSlot = i;
                    }
                }

                ModdedPlayer.ReapplyAllSpell();
            }
            catch (System.Exception ex)
            {
                ModAPI.Log.Write(ex.ToString());
            }
        }
Пример #5
0
        private IEnumerator DoLoadCoroutine()
        {
            while (LocalPlayer.Stats == null || LocalPlayer.Inventory == null)
            {
                yield return(null);
            }

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            //waits some frames

            string path = Path();

            if (path == string.Empty)
            {
                yield break;
            }
            //checking and cancelling loading routine if there is no directory of the save
            if (!Directory.Exists(path))
            {
                yield break;
            }

            path += "/COTF.save";
            if (!File.Exists(path))
            {
                yield break;
            }

            yield return(new WaitForSeconds(1f));

            DoLoad(path, out float HealthPercentage, out Dictionary <int, int> ExtraCarriedItems);

            //waiting for buffs and perks to apply
            yield return(new WaitForSeconds(5f));

            ModdedPlayer.ResetAllStats();
            //bringing health back to correct amount
            yield return(null);

            LocalPlayer.Stats.Health = ModdedPlayer.Stats.TotalMaxHealth * HealthPercentage;
            //waiting for buffs and perks to apply
            yield return(new WaitForSeconds(6f));

            //fixing missing items
            foreach (KeyValuePair <int, int> item in ExtraCarriedItems)
            {
                int amount = LocalPlayer.Inventory.AmountOf(item.Key);
                if (amount < item.Value)
                {
                    int toAdd = item.Value - amount;
                    LocalPlayer.Inventory.AddItem(item.Key, toAdd);
                }
            }
        }
Пример #6
0
        private void DrawGuide()
        {
            GUI.Label(new Rect(0, 0, 300, 100), "Page: " + guidePage);
            int a = 0;

            Bookmarks.Clear();

            BookPositionY = BookScrollAmount;
            SetGuiStylesForGuide();

            if (GUI.Button(new Rect(5f * screenScale, 5f * screenScale, 100 * screenScale, 50 * screenScale), "<", headerstyle))
            {
                ChangePage(guidePage - 1);
            }
            if (GUI.Button(new Rect(Screen.width - 105f * screenScale, 5f * screenScale, 100 * screenScale, 50 * screenScale), ">", headerstyle))
            {
                ChangePage(guidePage + 1);
            }



            if (guidePage == a++)
            {
                Header("Basic Information");
                MarkBookmark("Home");
                Label("\tExperience");
                Stat("Current level", ModdedPlayer.instance.level.ToString());
                Stat("Current experience", ModdedPlayer.instance.ExpCurrent.ToString());
                Stat("Experience goal", ModdedPlayer.instance.ExpGoal.ToString(), "Next level: " + (ModdedPlayer.instance.level + 1) + " you will need to get this amount of experience:\t " + ModdedPlayer.instance.GetGoalExp(ModdedPlayer.instance.level + 1));
                Stat("Progress amount: ", (((float)ModdedPlayer.instance.ExpCurrent / ModdedPlayer.instance.ExpGoal).ToString("P")));
                Label("\tLevel is the estimation of my power. I must become stronger to survive." +
                      "\nHigher level allow me to equip better equipement. " +
                      "\nLeveling up gives me the ability to develop usefull abilities. (Currently you have " + ModdedPlayer.instance.MutationPoints + " mutation points), which you can spend on unlocking spells or perks. ");
                Space(50);
                Label("\nSources of experience" +
                      "\n-Mutants - Enemies give the most experience, it's possible to chain kills to get more exp, and the reward is exp reward is based on bounty." +
                      "\n-Animals - Experience gained does not increase with difficulty. Good way of gaining experience. Rarer animals like crocodiles and racoons give more experience compared to common like rabbits and lizards" +
                      "\n-Tall bushes - Give minium amount of experience." +
                      "\n-Trees - A bit more than bushes." +
                      "\n-Effigies - It's possible to gain experience and low rarity items by breaking effigies scattered across the map." +
                      "\n-Rare consumable - Gives a large amount of experience, it's rarity is orange\n");

                Space(100);

                Header("Information - Items");
                Label($"\tEquipement can be obtained by killing enemies and breaking effigies. Normal enemies can drop a few items on death, if the odds are in your favor. The chance to get any items from a normal enemy is {0.1f* ModdedPlayer.Stats.magicFind.Value* ModSettings.DropChanceMultiplier:P}. The amount of items obtained from normal enemies increases with more players in a lobby.\n" +
                      "Elite enemies always drop items in large amounts.\n" +
                      "\tItems can be equipped by dragging and dropping them onto a right equipement slot or shift+left click. The item will grant it's stats only if you meets item's level requirement. The best tier of items is only obtainable on high difficulties.");
                Label("By unlocking a perk in the survival category, it's possible to change the stats on your existing items, and reforge unused items into something useful. Reforged item will have the same level as item put into the main crafting slot.");
                Label("In the inventory, you can compare an item with your equipped item by holding down left shift.");
                Label("By holding down left shift and clicking on an item, it will be equipped. This server the same purpose as dragging and dropping an item.");
                Label("By holding down left control and clicking on an item, be used as an ingredient for crafting.");
                Label("By pressing left alt you toggle a window to show total amount of a stat when you hover over it.");

                Space(100);
                Header("Information - Statistics");
                Label("\tAttributes");
                Label("Strength - This stat increases melee damage and thorns. It multiplies with melee damage increase.");
                Label("Agility - This stat increases ranged damage and maximum energy.");
                Label("Intelligence - This stat increases magic damage and energy regeneration rate.");
                Label("Vitality - This stat increases maximum health");

                Space(100);

                Header("Information - Mutations and Abilities");
                Label("\tUpon leveling up, the player will recieve a upgrade point. Then it's up to the player to use it to unlock a mutation, that will serve as a permanent perk, or to spend two upgrade points to unlock a ability.\n" +
                      "Abilities are in majority of the cases more powerful than perks, as they cost more and the number of active abilities is limitied to 6.\n" +
                      "Some perks can be bought multiple times for increased effects.\n" +
                      "\n" +
                      "Refunding - it is possible to refund all points, to do so, heart of purity needs to be consumed. This item is of yellow rarity, and thus unobtainable on easy and veteran difficulties. Heart of purity will be granted to a player upon reaching level 15, 30 and 40" +
                      "More points - to gain a point without leveling, a rare item of green rarity needs to be consumed. It permamently adds a upgrade point, and it persists even after refunding. Items to grant additional upgrade points are granted to player to upon reaching level 50, 65 and 75. To obtain them in different means, you need to play on challenge difficulties or higher");
                Space(100);

                Header("Information - Enemies");
                Label("\tEnemies in the forest have adapted to your skill. As they level with you, they become faster and stronger. But speed and strength alone shouldn't be your main concern. There are a lot more dangerous beings out there." +
                      "\n\n" +
                      "Common enemies changed slightly. Their health increases with level.\n" +
                      "A new statistic to enemies is 'Armor'. This property reduces damage taken by the enemies from physical attacks, and partly reduces damage from magical attacks. Armor can be reduced in a number of ways.\n" +
                      "The easiest way to reduce armor is to use fire. Fire works as a way to crowd control enemies, it renders a few enemies unable to run and attack as they shake off the flames.\n" +
                      "Other way to reduce armor is to equip items, which reduce armor on hit.\n" +
                      "If you dont have any way to reduce enemy's armor, damaging them with spells would decrease the reduction from armor by 2/3, allowing you to deal some damage.");
                Space(30);
                Label("Elite enemies\n" +
                      "An elite is a uncommon type of a mutant with increased stats and access to special abilities, that make encounters with them challenging." +
                      "\nEnemy abilities:");
                Label("- Steadfast - This defensive ability causes enemy to reduce all damage exceeding a percent of their maximum health. To deal with this kind of ability, damage over time and fast attacks are recommended. This ability counters nuke instances of damage.");
                Label("- Blizzard - A temporary aura around an enemy, that slows anyone in it's area of effect. Affects movement speed and attack speed. Best way to deal with this is to avoid getting within it's range. Crowd controll from ranged attacks and running seems like the best option.");
                Label("- Radiance - A permanent aura around an enemy. It deals damage anyone around. The only way of dealing with this is to never get close to the enemy.");
                Label("- Chains - Roots anyone in a big radius around the elite. The duration this root increases with difficulty. Several abilities that provide resistance to crowd controll clear the effects of this ability.");
                Label("- Black hole - A very strong ability. The spell has a fixed cooldown, and the enemy will attempt to cast it as soon as a player gets within his range effective.");
                Label("- Trap sphere - Long lasting sphere that forces you to stay inside it untill it's effects wears off");
                Label("- Juggernaut - The enemy is completely immune to crowd controll and bleeding.\n");
                Label("- Gargantuan - Describes an enemy that is bigger, faster, stronger and has more health.");
                Label("- Tiny - An enemy has decreased size. It's harder to hit it with ranged attacks and most of the melee weapons can only attack the enemy with slow smashes.");
                Label("- Extra tough - enemy has a lot more healt");
                Label("- Extra deadly - enemy has a lot more damage");
                Label("- Basher - the enemy stuns on hit. Best way to fight it is to not get hit or parry it's attacks.");
                Label("- Warping - An ability allowing to teleport. Strong against glass cannon builds, running away and ranged attacks. Weak agnist melee strikes and a lot of durability.");
                Label("- Rain Empowerment - If it rains, the enemy gains in strenght, speed, armor and size.");
                Label("- Meteors - Periodically spawns a rain of powerful meteors. They are rather easy to spot and they move at a slow medium speed.");
                Label("- Flare - Slows and damages me if you stand inside. Heals and makes enemies faster.");
                Label("- Undead - An enemy upon dieing restores portion of it's health, gets stronger and bigger.");
                Label("- Plasma cannon - Creates a turret that fires a laser beam that damages players and buildings.");
                Label("- Poisonous - Enemies gain a attack modifier, that applies a stacking debuff, which deals damage over time. Once hit, it is adviced to retreat and wait for the poison stop damaging you.");
                Label("- Cataclysm - Enemy uses the cataclysm spell to slow you down and damage you.");

                Header("Changes");
                Label("Champions of The Forest provides variety of changes to in-game mechanics." +
                      "\nArmor no longer absorbs all damage. Instead it reduces the damage by 70%." +
                      "\nPlayer is slowed down if out of stamina (the inner blue bar)" +
                      "\nTraps no longer instantly kill cannibals. Instead they deal damage." +
                      "\nDynamite no longer instantly kills enemies. Instead it deals up to 700 damage" +
                      "\nEnemies have armor and increased health." +
                      "\nPlayers now take increased damage from fire, frost, drowning, falling, food poisoning and polluted water based on their maximum health" +
                      "\nPlayers take increased damage from explosives. This affects how much damage the worm does" +
                      "\nPlayer deal increased damage to other players if friendly fire is enabled.");
            }
            else if (guidePage == a++)
            {
                Header("Statistics");
                Stat("Strength", ModdedPlayer.Stats.strength.GetFormattedAmount() + " str", "Increases melee damage by " + ModdedPlayer.Stats.meleeDmgFromStr.GetFormattedAmount() + " for every 1 point of strength. Current bonus melee damage from strength [" + ModdedPlayer.Stats.strength.GetAmount() * ModdedPlayer.Stats.meleeDmgFromStr.GetAmount() * 100 + "%]");
                Stat("Agility", ModdedPlayer.Stats.agility.GetFormattedAmount() + " agi", "Increases ranged damage by " + ModdedPlayer.Stats.rangedDmgFromAgi.GetFormattedAmount() + " for every 1 point of agility. Current bonus ranged damage from agility [" + ModdedPlayer.Stats.agility.GetAmount() * ModdedPlayer.Stats.rangedDmgFromAgi.GetAmount() * 100 + "%]\n" +
                     "Increases maximum energy by " + ModdedPlayer.Stats.maxEnergyFromAgi.GetFormattedAmount() + " for every 1 point of agility. Current bonus ranged damage from agility [" + ModdedPlayer.Stats.agility.GetAmount() * ModdedPlayer.Stats.maxEnergyFromAgi.GetAmount() * 100 + "%]");
                Stat("Vitality", ModdedPlayer.Stats.vitality.GetFormattedAmount() + " vit", "Increases health by " + ModdedPlayer.Stats.maxHealthFromVit.GetFormattedAmount() + " for every 1 point of vitality. Current bonus health from vitality [" + ModdedPlayer.Stats.vitality.GetAmount() * ModdedPlayer.Stats.maxHealthFromVit.GetAmount() + "]");
                Stat("Intelligence", ModdedPlayer.Stats.intelligence.GetFormattedAmount() + " int", "Increases spell damage by " + ModdedPlayer.Stats.spellDmgFromInt.GetFormattedAmount() + " for every 1 point of intelligence. Current bonus spell damage from intelligence [" + ModdedPlayer.Stats.intelligence.GetAmount() * ModdedPlayer.Stats.spellDmgFromInt.GetAmount() + "]\n" +
                     "Increases stamina regen by " + ModdedPlayer.Stats.energyRecoveryFromInt.GetFormattedAmount() + " for every 1 point of intelligence. Current bonus stamina regen from intelligence [" + ModdedPlayer.Stats.intelligence.GetAmount() * ModdedPlayer.Stats.energyRecoveryFromInt.GetAmount() * 100 + "%]");


                Space(60);
                Image(99, 70);
                Header("Defense");
                Space(10);
                Stat("Max health", ModdedPlayer.Stats.TotalMaxHealth.ToString(), "Total health pool.\n" +
                     "Base health: " + ModdedPlayer.ModdedPlayerStats.baseHealth +
                     "\nBonus health: " + ModdedPlayer.Stats.maxHealth.GetFormattedAmount() +
                     "\nHealth from vitality: " + ModdedPlayer.Stats.maxHealthFromVit.GetAmount() * ModdedPlayer.Stats.vitality.GetAmount() +
                     "\nHealth multipier: " + ModdedPlayer.Stats.maxHealthMult.GetFormattedAmount());
                Stat("Max energy", ModdedPlayer.Stats.TotalMaxEnergy.ToString(), "Total energy pool.\n" +
                     "Base energy: " + ModdedPlayer.ModdedPlayerStats.baseEnergy +
                     "\nBonus energy: " + ModdedPlayer.Stats.maxEnergy.GetFormattedAmount() +
                     "\nEnergy from agility: " + ModdedPlayer.Stats.maxEnergyFromAgi.GetAmount() * ModdedPlayer.Stats.agility.GetAmount() +
                     "\nEnergy multipier: " + ModdedPlayer.Stats.maxEnergyMult.GetFormattedAmount());
                Stat("Armor", ModdedPlayer.Stats.armor.GetFormattedAmount(), $"Armor provides physical damage reduction.\nPhysical damage reduction from {ModdedPlayer.Stats.armor.GetFormattedAmount()} armor is equal to {1-ModReferences.DamageReduction(ModdedPlayer.Stats.armor.Value):P}");
                Stat("Magic resistance", (1 - ModdedPlayer.Stats.magicDamageTaken.GetAmount()).ToString("P"), "Magic damage reduction. Decreases damage from enemy abilities.");
                Stat("Dodge Chance", (1 - ModdedPlayer.Stats.getHitChance.GetAmount()).ToString("P"), "A chance to avoid entire instance of damage. Works only for physical damage sources. This means dodge is ineffective against fire, poison, cold, various spells. Meteor rain ability deals physical damage and can be dodged");
                Stat("Damage taken reduction", (1f - ModdedPlayer.Stats.allDamageTaken.GetAmount()).ToString("P"));
                Stat("Block", ModdedPlayer.Stats.block.GetFormattedAmount());
                Stat("Temporary health", ModdedPlayer.instance.DamageAbsorbAmount.ToString(), "One way to obtain temporary health is to use sustain shield ability");
                Stat("Fire resistance", (1 - ModdedPlayer.Stats.fireDamageTaken.GetAmount()).ToString("P"));
                Stat("Thorns", ModdedPlayer.Stats.TotalThornsDamage.ToString(), $"Thorns inflict damage to attacking enemies. Thorns from gear and mutations {ModdedPlayer.Stats.thorns.GetFormattedAmount()}. Thorns from attributes {(ModdedPlayer.Stats.thornsPerStrenght.GetAmount() * ModdedPlayer.Stats.strength.GetAmount() + ModdedPlayer.Stats.vitality.GetAmount() * ModdedPlayer.Stats.thornsPerVit.GetAmount())}.\nThorns damage is applied to attackers even when you are blocking");

                Space(60);
                Header("Recovery");
                Space(10);


                Stat("Total Stamina recovery per second", ModdedPlayer.Stats.TotalStaminaRecoveryAmount.ToString() + "", "Stamina regen is temporairly paused after sprinting");
                Stat("Stamina per second", ModdedPlayer.Stats.staminaRecoveryperSecond.GetAmount() * ModdedPlayer.Stats.staminaPerSecRate.GetAmount() + "", "Stamina per second: " + ModdedPlayer.Stats.staminaRecoveryperSecond.GetAmount() + "\nStamina regen bonus: " + ModdedPlayer.Stats.staminaPerSecRate.GetFormattedAmount());

                Stat("Energy per second", ModdedPlayer.Stats.energyRecoveryperSecond.GetAmount() * ModdedPlayer.Stats.TotalStaminaRecoveryMultiplier + "", "Energy per second: " + ModdedPlayer.Stats.energyRecoveryperSecond.GetAmount() + "\nStamina and energy regen multipier: " + ModdedPlayer.Stats.TotalStaminaRecoveryMultiplier);
                Stat("Energy on hit", ModdedPlayer.Stats.energyOnHit.GetAmount() * ModdedPlayer.Stats.TotalStaminaRecoveryMultiplier + "", "Energy on hit from items and perks: " + ModdedPlayer.Stats.energyOnHit.GetAmount());
                Stat("Health per second", ModdedPlayer.Stats.healthRecoveryPerSecond.GetAmount() * (ModdedPlayer.Stats.healthPerSecRate.GetAmount()) * ModdedPlayer.Stats.allRecoveryMult.GetAmount() + "", "Health per second: " + ModdedPlayer.Stats.healthRecoveryPerSecond.GetAmount() + "\nStamina regen bonus: " + ModdedPlayer.Stats.healthPerSecRate.GetFormattedAmount() + "\nAll Recovery Amplification: " + (ModdedPlayer.Stats.allRecoveryMult.GetAmount() - 1));
                Stat("Health on hit", ModdedPlayer.Stats.healthOnHit.GetAmount() * ModdedPlayer.Stats.allRecoveryMult.GetAmount() + "", "Health on hit: " + ModdedPlayer.Stats.healthOnHit.GetAmount() + "\nHealth regen bonus: " + ModdedPlayer.Stats.allRecoveryMult.GetFormattedAmount() + "\nAll Healing Amplification: " + (ModdedPlayer.Stats.allRecoveryMult.GetAmount() - 1));

                Space(60);
                Header("Attack");
                Space(10);
                Stat("All damage", ModdedPlayer.Stats.allDamage.GetFormattedAmount());
                Stat("Critical hit damage", ModdedPlayer.Stats.critDamage.GetFormattedAmount());
                Stat("Critical hit chance", ModdedPlayer.Stats.critChance.GetFormattedAmount());
                Stat("Attack speed", ModdedPlayer.Stats.attackSpeed.GetFormattedAmount(), "Increases the speed of player actions - weapon swinging, reloading guns and drawing bows");
                Stat("Fire damage", ModdedPlayer.Stats.fireDamage.GetFormattedAmount(), "Increases fire damage");
                Stat("Bleed chance", ModdedPlayer.Stats.chanceToBleed.GetFormattedAmount(), "Bleeding enemies take 5% of damage dealt per second for 10 seconds");
                Stat("Weaken chance", ModdedPlayer.Stats.chanceToWeaken.GetFormattedAmount(), "Weakened enemies take 20% increased damage from all players.");
                Stat("Slow chance", ModdedPlayer.Stats.chanceToSlow.GetFormattedAmount(), "Slowed enemies move and attack 50% slower");

                Space(20);
                Image(89, 70);
                Header("Melee");
                Space(10);

                Stat("Melee damage", ModdedPlayer.Stats.MeleeDamageMult.ToString("P"), "Melee damage multipier can be increased by perks, inventory items, spells, passive abilities, and attributes.\n" +
                     "Bonus from strength: " + ModdedPlayer.Stats.strength.GetAmount() * ModdedPlayer.Stats.meleeDmgFromStr.GetAmount() * 100 + "%\n" +
                     "Increase to melee damage: " + (ModdedPlayer.Stats.meleeIncreasedDmg - 1).ToString("P") + "\n" +
                     "Increase to all damage: " + (ModdedPlayer.Stats.allDamage - 1).ToString("P"));
                Stat("Additional melee weapon damage", ModdedPlayer.Stats.meleeFlatDmg.GetFormattedAmount(), "Melee damage bonus can be increased by perks and inventory items (mainly this stat occurs on weapons). This is added to weapon damage and multiplied by the stat above");
                Stat("Melee range", ModdedPlayer.Stats.weaponRange.GetFormattedAmount());
                Stat("Heavy attack damage", ModdedPlayer.Stats.heavyAttackDmg.GetFormattedAmount());

                Space(20);
                Image(98, 70);
                Header("Ranged");
                Space(10);

                Stat("Ranged damage", ModdedPlayer.Stats.RangedDamageMult.ToString("P"), "Ranged damage multipier can be increased by perks, inventory items, spells, passive abilities, and attributes.\n" +
                     "Bonus from agility: " + (ModdedPlayer.Stats.agility.GetAmount() * ModdedPlayer.Stats.rangedDmgFromAgi.GetAmount()).ToString("P") + "\n" +
                     "Increase to ranged damage: " + (ModdedPlayer.Stats.rangedIncreasedDmg.GetAmount() - 1).ToString("P") + "\n" +
                     "From size matters perk: " + (ModdedPlayer.Stats.perk_projectileDamageIncreasedBySize.GetAmount() ? (ModdedPlayer.Stats.projectileSize.GetAmount() - 1) * 2 : 0f).ToString("P") +
                     "\nIncrease to all damage: " + (ModdedPlayer.Stats.allDamage - 1).ToString("P"));
                Stat("Additional ranged weapon damage", ModdedPlayer.Stats.rangedFlatDmg.GetFormattedAmount(), "Ranged damage bonus can be increased by perks and inventory items (mainly this stat occurs on weapons). This is added to projectile damage and multiplied by the stat above");
                Stat("Projectile speed", ModdedPlayer.Stats.projectileSpeed.GetFormattedAmount(), "Faster projectiles fly further and fall slower");
                Stat("Projectile size", ModdedPlayer.Stats.projectileSize.GetFormattedAmount(), "Bigger projectiles allow to land headshots easier. Most projectiles still can hit only 1 target.");
                Stat("Headshot damage", ModdedPlayer.Stats.headShotDamage.GetFormattedAmount(), "Damage multipier on headshot");
                Stat("Projectile pierce chance", ModdedPlayer.Stats.projectilePierceChance.GetFormattedAmount(), "Chance for a projectile to pierce a bone of an enemy and fly right through to hit objects behind the enemy. Increasing this value beyond 100% will make your projectiles always pierce on first enemy contact, and any further hits will also have a chance to pierce.");
                Stat("No consume chance", ModdedPlayer.Stats.perk_projectileNoConsumeChance.GetFormattedAmount());
                Stat("Spear headshot chance", ModdedPlayer.Stats.perk_thrownSpearCritChance.GetFormattedAmount());
                if (ModdedPlayer.Stats.perk_thrownSpearhellChance.GetAmount() > 0)
                {
                    Stat("Double spear chance", ModdedPlayer.Stats.perk_thrownSpearhellChance.GetFormattedAmount());
                }
                if (ModdedPlayer.Stats.perk_thrownSpearDamageMult.GetAmount() != 1)
                {
                    Stat("Spear damage", ModdedPlayer.Stats.perk_thrownSpearDamageMult.GetFormattedAmount());
                }
                Stat("Bullet headshot chance", ModdedPlayer.Stats.perk_bulletCritChance.GetFormattedAmount());
                if (ModdedPlayer.Stats.perk_bulletDamageMult.GetAmount() != 1)
                {
                    Stat("Bullet damage", ModdedPlayer.Stats.perk_bulletDamageMult.GetFormattedAmount());
                }
                if (ModdedPlayer.Stats.perk_crossbowDamageMult.GetAmount() != 1)
                {
                    Stat("Crossbow damage", ModdedPlayer.Stats.perk_crossbowDamageMult.GetFormattedAmount());
                }
                if (ModdedPlayer.Stats.perk_bowDamageMult.GetAmount() != 1)
                {
                    Stat("Bow damage", ModdedPlayer.Stats.perk_bowDamageMult.GetFormattedAmount());
                }
                if (ModdedPlayer.Stats.i_CrossfireQuiver.GetAmount())
                {
                    Stat("Shooting an enemy creates magic arrows", "");
                }

                Stat("Multishot Projectiles", (ModdedPlayer.Stats.i_SoraBracers.GetAmount() ? (4 + ModdedPlayer.Stats.perk_multishotProjectileCount.GetAmount()) : ModdedPlayer.Stats.perk_multishotProjectileCount.GetAmount()).ToString("N"));
                Stat("Multishot Cost", (ModdedPlayer.Stats.i_SoraBracers.GetAmount() ? 1f * Mathf.Pow(ModdedPlayer.Stats.perk_multishotProjectileCount.GetAmount(), 1.75f) : 10 * Mathf.Pow(ModdedPlayer.Stats.perk_multishotProjectileCount.GetAmount(), 1.75f)).ToString(), "Formula for multishot cost in energy is (Multishot Projectiles ^ 1.75) * 10");;

                Space(20);
                Image(110, 70);
                Header("Magic");
                Space(10);

                Stat("Spell damage", ModdedPlayer.Stats.TotalMagicDamageMultiplier.ToString("P"), "Spell damage multipier can be increased by perks, inventory items, spells, passive abilities, and attributes.\n" +
                     "Bonus from intelligence: " + (ModdedPlayer.Stats.intelligence.GetAmount() * ModdedPlayer.Stats.spellDmgFromInt.GetAmount()).ToString("P") + "\n" +
                     "Increase to spell damage: " + (ModdedPlayer.Stats.spellIncreasedDmg - 1).ToString("P") + "\n" +
                     "Increase to all damage: " + (ModdedPlayer.Stats.allDamage - 1).ToString("P"));
                Stat("Additional spell damage", ModdedPlayer.Stats.spellFlatDmg.GetFormattedAmount(), "Spell damage bonus can be increased by perks and inventory items. This is added to spell damage and multiplied by the stat above. Often spells take a fraction of this stat and add it to spell's damage.");
                Stat("Spell cost reduction", (1 - ModdedPlayer.Stats.spellCost.GetAmount()).ToString("P"));
                Stat("Spell cost redirected to stamina", ModdedPlayer.Stats.SpellCostToStamina.ToString("P"));
                Stat("Cooldown reduction", (1 - ModdedPlayer.Stats.cooldown.GetAmount()).ToString("P"));

                Space(20);
                GUI.color = Color.red;
                Image(96, 70);
                GUI.color = Color.white;
                Header("Armor reduction");
                Space(10);
                Stat("Melee", ModdedPlayer.Stats.meleeArmorPiercing.GetAmount() + "", "Total melee armor reduction: " + ModdedPlayer.Stats.TotalMeleeArmorPiercing.ToString());
                Stat("Ranged", ModdedPlayer.Stats.rangedArmorPiercing.GetAmount() + "", "Total ranged armor reduction: " + ModdedPlayer.Stats.TotalRangedArmorPiercing.ToString());
                //Stat("Thorns", ModdedPlayer.Stats.thornsArmorPiercing.GetAmount() + "", "Total thorns armor reduction: " + ModdedPlayer.Stats.TotalThornsArmorPiercing.ToString());
                Stat("Any source", ModdedPlayer.Stats.allArmorPiercing.GetAmount() + "", "Decreases armor of enemies hit by either of the sources");
            }
            else if (guidePage == a++)
            {
                Header("Survivor stats");
                Space(10);

                Stat("Movement speed", ModdedPlayer.Stats.movementSpeed.GetAmount().ToString(), "Multipier of base movement speed. Base walking speed is equal to " + FPCharacterMod.basewalkSpeed + " feet per second, with bonuses it's " + FPCharacterMod.basewalkSpeed * ModdedPlayer.Stats.movementSpeed.GetAmount() + " feet/second");
                Stat("Jump power", ModdedPlayer.Stats.jumpPower.GetAmount().ToString(), "Multipier of base jump power. Increases height of your jumps");
                Stat("Hunger rate", (1 / ModdedPlayer.Stats.perk_hungerRate).ToString("P"), "How much slower is the rate of consuming food compared to normal.");
                Stat("Thirst rate", (1 / ModdedPlayer.Stats.perk_thirstRate).ToString("P"), "How much slower is the rate of consuming water compared to normal.");
                Stat("Experience gain", ModdedPlayer.Stats.expGain.GetFormattedAmount(), "Multipier of any experience gained");
                Stat("Massacre duration", ModdedPlayer.Stats.maxMassacreTime.GetAmount() + " s", "How long massacres can last");
                Stat("Time on kill", ModdedPlayer.Stats.timeBonusPerKill.GetAmount() + " s", "Amount of time that is added to massacre for every kill");
                if (ModdedPlayer.Stats.perk_turboRaftOwners.GetAmount() > 0)
                {
                    Stat("Turbo raft speed", ModdedPlayer.Stats.perk_RaftSpeedMultipier.GetFormattedAmount(), "Speed multiplier of rafts. Other player's items and perks also affect this value");
                }
                Stat("Magic find", ModdedPlayer.Stats.magicFind.Value.ToString("P"), "Affects rarity of items looted from monsters, as well as the chance to get items from non-elite enemies. Increases globally, and this value is affected by every player. ");
                foreach (var mfStat in ModdedPlayer.Stats.magicFind.OtherPlayerValues)
                {
                    Stat(mfStat.Key + "'s Magic Find", mfStat.Value.ToString("P"), "Magic find from other players");
                }

                Space(40);
                Image(90, 70);
                Header("Inventory Stats");
                Space(10);
                foreach (KeyValuePair <int, ModdedPlayer.ExtraItemCapacity> pair in ModdedPlayer.instance.ExtraCarryingCapactity)
                {
                    string item_name = TheForest.Utils.Scene.HudGui.GetItemName(pair.Value.ID, (pair.Value.Amount > 1), false);
                    Stat(item_name, "+" + pair.Value.Amount, "How many extra '" + item_name + "' you can carry. Item ID is " + pair.Value.ID);
                }
                Space(10);
                if (ModdedPlayer.instance.GeneratedResources.Count > 0)
                {
                    Header("Generated resources");
                }
                foreach (var pair in ModdedPlayer.instance.GeneratedResources)
                {
                    string item_name = TheForest.Utils.Scene.HudGui.GetItemName(pair.Key, (pair.Value > 1), false);
                    Stat(item_name, pair.ToString(), "How many '" + item_name + "' you generate daily. Item ID is " + pair.Key);
                }
            }
            else if (guidePage == a++)
            {
                if (BookPositionY < Screen.height && BookPositionY > -140 * screenScale)
                {
                    Rect labelRect = new Rect(GuideWidthDecrease * screenScale + GuideMargin * screenScale, BookPositionY, Screen.width - 2 * screenScale * (GuideMargin + GuideWidthDecrease), 85 * screenScale);
                    if (GUI.Button(labelRect, "Bugged stats? Click to reset", new GUIStyle(GUI.skin.button)
                    {
                        font = mainFont,
                        fontSize = Mathf.RoundToInt(70 * screenScale),
                        alignment = TextAnchor.UpperCenter,
                        richText = true,
                    }))
                    {
                        ModdedPlayer.ResetAllStats();
                    }
                    BookPositionY += 85 * screenScale;
                    Rect imageRect = new Rect(400 * screenScale, BookPositionY, Screen.width - 800 * screenScale, 60 * screenScale);
                    GUI.DrawTexture(imageRect, ResourceLoader.GetTexture(30));
                    BookPositionY += 70 * screenScale;
                }
                else
                {
                    BookPositionY += 155 * screenScale;
                }
            }
        }