Files
CypherCore/Source/Game/Miscellaneous/Formulas.cs
T

247 lines
8.5 KiB
C#

// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Constants;
using Game.DataStorage;
using Game.Entities;
using System;
namespace Game
{
public class Formulas
{
public static float HKHonorAtLevelF(uint level, float multiplier = 1.0f)
{
float honor = multiplier * level * 1.55f;
Global.ScriptMgr.OnHonorCalculation(honor, level, multiplier);
return honor;
}
public static uint HKHonorAtLevel(uint level, float multiplier = 1.0f)
{
return (uint)Math.Ceiling(HKHonorAtLevelF(level, multiplier));
}
public static uint GetGrayLevel(uint pl_level)
{
uint level;
if (pl_level < 7)
level = 0;
else if (pl_level < 35)
{
byte count = 0;
for (int i = 15; i <= pl_level; ++i)
if (i % 5 == 0) ++count;
level = (uint)((pl_level - 7) - (count - 1));
}
else
level = pl_level - 10;
Global.ScriptMgr.OnGrayLevelCalculation(level, pl_level);
return level;
}
public static XPColorChar GetColorCode(uint pl_level, uint mob_level)
{
XPColorChar color;
if (mob_level >= pl_level + 5)
color = XPColorChar.Red;
else if (mob_level >= pl_level + 3)
color = XPColorChar.Orange;
else if (mob_level >= pl_level - 2)
color = XPColorChar.Yellow;
else if (mob_level > GetGrayLevel(pl_level))
color = XPColorChar.Green;
else
color = XPColorChar.Gray;
Global.ScriptMgr.OnColorCodeCalculation(color, pl_level, mob_level);
return color;
}
public static uint GetZeroDifference(uint pl_level)
{
uint diff;
if (pl_level < 4)
diff = 5;
else if (pl_level < 10)
diff = 6;
else if (pl_level < 12)
diff = 7;
else if (pl_level < 16)
diff = 8;
else if (pl_level < 20)
diff = 9;
else if (pl_level < 30)
diff = 11;
else if (pl_level < 40)
diff = 12;
else if (pl_level < 45)
diff = 13;
else if (pl_level < 50)
diff = 14;
else if (pl_level < 55)
diff = 15;
else if (pl_level < 60)
diff = 16;
else
diff = 17;
Global.ScriptMgr.OnZeroDifferenceCalculation(diff, pl_level);
return diff;
}
public static uint BaseGain(uint pl_level, uint mob_level)
{
uint baseGain;
GtXpRecord xpPlayer = CliDB.XpGameTable.GetRow(pl_level);
GtXpRecord xpMob = CliDB.XpGameTable.GetRow(mob_level);
if (mob_level >= pl_level)
{
uint nLevelDiff = mob_level - pl_level;
if (nLevelDiff > 4)
nLevelDiff = 4;
baseGain = (uint)Math.Round(xpPlayer.PerKill * (1 + 0.05f * nLevelDiff));
}
else
{
uint gray_level = GetGrayLevel(pl_level);
if (mob_level > gray_level)
{
uint ZD = GetZeroDifference(pl_level);
baseGain = (uint)Math.Round(xpMob.PerKill * ((1 - ((pl_level - mob_level) / ZD)) * (xpMob.Divisor / xpPlayer.Divisor)));
}
else
baseGain = 0;
}
if (WorldConfig.GetIntValue(WorldCfg.MinCreatureScaledXpRatio) != 0 && pl_level != mob_level)
{
// Use mob level instead of player level to avoid overscaling on gain in a min is enforced
uint baseGainMin = BaseGain(pl_level, pl_level) * WorldConfig.GetUIntValue(WorldCfg.MinCreatureScaledXpRatio) / 100;
baseGain = Math.Max(baseGainMin, baseGain);
}
Global.ScriptMgr.OnBaseGainCalculation(baseGain, pl_level, mob_level);
return baseGain;
}
public static uint XPGain(Player player, Unit u, bool isBattleGround = false)
{
Creature creature = u.ToCreature();
uint gain = 0;
if (creature == null || creature.CanGiveExperience())
{
float xpMod = 1.0f;
gain = BaseGain(player.GetLevel(), u.GetLevelForTarget(player));
if (gain != 0 && creature != null)
{
// Players get only 10% xp for killing creatures of lower expansion levels than himself
if ((creature.GetCreatureDifficulty().GetHealthScalingExpansion() < (int)GetExpansionForLevel(player.GetLevel())))
gain = (uint)Math.Round(gain / 10.0f);
if (creature.IsElite())
{
// Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus.
if (u.GetMap().IsDungeon())
xpMod *= 2.75f;
else
xpMod *= 2.0f;
}
xpMod *= creature.GetCreatureTemplate().ModExperience;
}
xpMod *= isBattleGround ? WorldConfig.GetFloatValue(WorldCfg.RateXpBgKill) : WorldConfig.GetFloatValue(WorldCfg.RateXpKill);
if (creature != null && creature.m_PlayerDamageReq != 0) // if players dealt less than 50% of the damage and were credited anyway (due to CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ), scale XP gained appropriately (linear scaling)
xpMod *= 1.0f - 2.0f * creature.m_PlayerDamageReq / creature.GetMaxHealth();
gain = (uint)(gain * xpMod);
}
Global.ScriptMgr.OnGainCalculation(gain, player, u);
return gain;
}
public static float XPInGroupRate(uint count, bool isRaid)
{
float rate;
if (isRaid)
{
// FIXME: Must apply decrease modifiers depending on raid size.
// set to < 1 to, so client will display raid related strings
rate = 0.99f;
}
else
{
switch (count)
{
case 0:
case 1:
case 2:
rate = 1.0f;
break;
case 3:
rate = 1.166f;
break;
case 4:
rate = 1.3f;
break;
case 5:
default:
rate = 1.4f;
break;
}
}
Global.ScriptMgr.OnGroupRateCalculation(rate, count, isRaid);
return rate;
}
static Expansion GetExpansionForLevel(uint level)
{
if (level < 60)
return Expansion.Classic;
else if (level < 70)
return Expansion.BurningCrusade;
else if (level < 80)
return Expansion.WrathOfTheLichKing;
else if (level < 85)
return Expansion.Cataclysm;
else if (level < 90)
return Expansion.MistsOfPandaria;
else if (level < 100)
return Expansion.WarlordsOfDraenor;
else
return Expansion.Legion;
}
public static uint ConquestRatingCalculator(uint rate)
{
if (rate <= 1500)
return 1350; // Default conquest points
else if (rate > 3000)
rate = 3000;
// http://www.arenajunkies.com/topic/179536-conquest-point-cap-vs-personal-rating-chart/page__st__60#entry3085246
return (uint)(1.4326 * ((1511.26 / (1 + 1639.28 / Math.Exp(0.00412 * rate))) + 850.15));
}
public static uint BgConquestRatingCalculator(uint rate)
{
// WowWiki: Battlegroundratings receive a bonus of 22.2% to the cap they generate
return (uint)((ConquestRatingCalculator(rate) * 1.222f) + 0.5f);
}
}
}