aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKinzcool <kinzzcool@hotmail.com>2015-01-16 21:46:00 -0500
committerKinzcool <kinzzcool@hotmail.com>2015-01-16 21:46:00 -0500
commitb21c346658d6165251363f7a86cfa8c7f5925ba9 (patch)
treec78b86690514becbae81be9420bbd795a8fe4fdd
parente9187b5c552707c6a89790c5363ead071af140ec (diff)
Core/Misc: Implemented leveling/killing experience loading from gtOCTLevelExperience.dbc
* Updated the xp formula to Warlords of Draenor
-rw-r--r--sql/updates/world/2015_01_16_00_world.sql5
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/DataStores/DBCStores.cpp40
-rw-r--r--src/server/game/DataStores/DBCStores.h2
-rw-r--r--src/server/game/DataStores/DBCStructure.h5
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp12
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp59
-rw-r--r--src/server/game/Miscellaneous/Formulas.h57
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp4
-rw-r--r--src/server/game/Scripting/ScriptMgr.h4
11 files changed, 94 insertions, 97 deletions
diff --git a/sql/updates/world/2015_01_16_00_world.sql b/sql/updates/world/2015_01_16_00_world.sql
new file mode 100644
index 00000000000..d4ed9192b46
--- /dev/null
+++ b/sql/updates/world/2015_01_16_00_world.sql
@@ -0,0 +1,5 @@
+TRUNCATE `player_xp_for_level`;
+
+ALTER TABLE `player_xp_for_level`
+ CHANGE `lvl` `Level` TINYINT(3) UNSIGNED NOT NULL,
+ CHANGE `xp_for_next_level` `Experience` FLOAT UNSIGNED NOT NULL;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index cf8701dc0d7..8c82a3c051e 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -37,7 +37,7 @@ enum LevelLimit
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
// use as default max player level, must be fit max level for used client
// also see MAX_LEVEL and STRONG_MAX_LEVEL define
- DEFAULT_MAX_LEVEL = 85,
+ DEFAULT_MAX_LEVEL = 100,
// client supported max level for player/pets/etc. Avoid overflow or client stability affected.
// also see GT_MAX_LEVEL define
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 20788fde81d..d0d5fbeb9b8 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -124,6 +124,7 @@ GameTable <GtNpcTotalHpExp3Entry> sGtNpcTotalHpExp3Store(GtNpcTotalHpExp3
GameTable <GtNpcTotalHpExp4Entry> sGtNpcTotalHpExp4Store(GtNpcTotalHpExp4fmt);
GameTable <GtNpcTotalHpExp5Entry> sGtNpcTotalHpExp5Store(GtNpcTotalHpExp5fmt);
GameTable <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore(GtOCTClassCombatRatingScalarfmt);
+GameTable <GtOCTLevelExperienceEntry> sGtOCTLevelExperienceStore(GtOCTLevelExperiencefmt);
GameTable <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
GameTable <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore(GtOCTHpPerStaminafmt);
GameTable <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
@@ -746,6 +747,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadGameTable(bad_dbc_files, "NpcTotalHpExp5", sGtNpcTotalHpExp5Store, dbcPath, "gtNpcTotalHpExp5.dbc"); // 19445
LoadGameTable(bad_dbc_files, "OCTClassCombatRatingScalar", sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc");//19342
LoadGameTable(bad_dbc_files, "OCTHPPerStamina", sGtOCTHpPerStaminaStore, dbcPath, "gtOCTHpPerStamina.dbc");//19342
+ LoadGameTable(bad_dbc_files, "OCTLevelExperience", sGtOCTLevelExperienceStore, dbcPath, "gtOCTLevelExperience.dbc"); // 19342
LoadGameTable(bad_dbc_files, "RegenMPPerSpt", sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");//19342
LoadGameTable(bad_dbc_files, "SpellScaling", sGtSpellScalingStore, dbcPath, "gtSpellScaling.dbc");//19342
LoadGameTable(bad_dbc_files, "OCTBaseHPByClass", sGtOCTBaseHPByClassStore, dbcPath, "gtOCTBaseHPByClass.dbc");//19342
@@ -897,32 +899,20 @@ uint32 GetMaxLevelForExpansion(uint32 expansion)
return 0;
}
-/*
-Used only for calculate xp gain by content lvl.
-Calculation on Gilneas and group maps of LostIslands calculated as CONTENT_1_60.
-*/
-ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
+uint32 GetExpansionForLevel(uint32 level)
{
- mapid = GetVirtualMapForMapAndZone(mapid, zoneId);
- if (mapid < 2)
- return CONTENT_1_60;
-
- MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
- if (!mapEntry)
- return CONTENT_1_60;
-
- // no need enum all maps from phasing
- if (mapEntry->ParentMapID >= 0)
- mapid = mapEntry->ParentMapID;
-
- switch (mapid)
- {
- case 648: //LostIslands
- case 654: //Gilneas
- return CONTENT_1_60;
- default:
- return ContentLevels(mapEntry->Expansion());
- }
+ if (level < 60)
+ return EXPANSION_CLASSIC;
+ else if (level < 70)
+ return EXPANSION_THE_BURNING_CRUSADE;
+ else if (level < 80)
+ return EXPANSION_WRATH_OF_THE_LICH_KING;
+ else if (level < 85)
+ return EXPANSION_CATACLYSM;
+ else if (level < 90)
+ return EXPANSION_MISTS_OF_PANDARIA;
+ else if (level < 100)
+ return EXPANSION_WARLORDS_OF_DRAENOR;
}
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 7c20baf5e55..8f21d07eb1a 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -59,6 +59,7 @@ enum ContentLevels
};
uint32 GetMaxLevelForExpansion(uint32 expansion);
+uint32 GetExpansionForLevel(uint32 level);
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
@@ -187,6 +188,7 @@ extern GameTable <GtNpcTotalHpExp3Entry> sGtNpcTotalHpExp3Store;
extern GameTable <GtNpcTotalHpExp4Entry> sGtNpcTotalHpExp4Store;
extern GameTable <GtNpcTotalHpExp5Entry> sGtNpcTotalHpExp5Store;
extern GameTable <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore;
+extern GameTable <GtOCTLevelExperienceEntry> sGtOCTLevelExperienceStore;
extern GameTable <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore;
extern GameTable <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
extern GameTable <GtSpellScalingEntry> sGtSpellScalingStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 8451c955fc2..15a2f537547 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -890,6 +890,11 @@ struct GtOCTClassCombatRatingScalarEntry
float ratio;
};
+struct GtOCTLevelExperienceEntry
+{
+ float Data;
+};
+
struct GtOCTRegenHPEntry
{
float ratio;
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 3999ec61675..ef707738fd9 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -68,6 +68,7 @@ char const GlyphSlotfmt[] = "nix";
char const GtBarberShopCostBasefmt[] = "xf";
char const GtCombatRatingsfmt[] = "xf";
char const GtOCTHpPerStaminafmt[] = "df";
+char const GtOCTLevelExperiencefmt[] = "xf";
char const GtChanceToMeleeCritBasefmt[] = "xf";
char const GtChanceToMeleeCritfmt[] = "xf";
char const GtChanceToSpellCritBasefmt[] = "xf";
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 5f1042bb93a..2ec00d8f818 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -512,14 +512,10 @@ inline void KillRewarder::_RewardXP(Player* player, float rate)
for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
AddPct(xp, (*i)->GetAmount());
- // 4.2.3. Calculate expansion penalty
- if (_victim->GetTypeId() == TYPEID_UNIT && player->getLevel() >= GetMaxLevelForExpansion(_victim->ToCreature()->GetCreatureTemplate()->expansion))
- xp = CalculatePct(xp, 10); // Players get only 10% xp for killing creatures of lower expansion levels than himself
-
- // 4.2.4. Give XP to player.
+ // 4.2.3. Give XP to player.
player->GiveXP(xp, _victim, _groupRate);
if (Pet* pet = player->GetPet())
- // 4.2.5. If player has pet, reward pet with XP (100% for single player, 50% for group case).
+ // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case).
pet->GivePetXP(_group ? xp / 2 : xp);
}
}
@@ -6630,7 +6626,7 @@ int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr
break;
}
- if (rate != 1.0f && creatureOrQuestLevel <= Trinity::XP::GetGrayLevel(getLevel()))
+ if (rate != 1.0f && creatureOrQuestLevel < Trinity::XP::GetGrayLevel(getLevel()))
percent *= rate;
if (percent <= 0.0f)
@@ -24032,7 +24028,7 @@ bool Player::isHonorOrXPTarget(Unit const* victim) const
uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel());
// Victim level less gray level
- if (v_level <= k_grey)
+ if (v_level < k_grey)
return false;
if (Creature const* const creature = victim->ToCreature())
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e44d1eeb016..b8352794c06 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3293,52 +3293,57 @@ void ObjectMgr::LoadPlayerInfo()
for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
_playerXPperLevel[level] = 0;
- // 0 1
- QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level");
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT Level, Experience FROM player_xp_for_level");
- if (!result)
+ // load the DBC's levels at first...
+ GtOCTLevelExperienceEntry const* exp;
+ for (int level = 0; level < MAX_LEVEL; ++level)
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 xp for level definitions. DB table `player_xp_for_level` is empty.");
- exit(1);
+ exp = sGtOCTLevelExperienceStore.EvaluateTable(level, 0);
+ _playerXPperLevel[level + 1] = exp->Data;
}
uint32 count = 0;
- do
+ // ...overwrite if needed (custom values)
+ if (result)
{
- Field* fields = result->Fetch();
+ do
+ {
+ Field* fields = result->Fetch();
- uint32 current_level = fields[0].GetUInt8();
- uint32 current_xp = fields[1].GetUInt32();
+ uint32 current_level = fields[0].GetUInt16();
+ uint32 current_xp = uint32(fields[1].GetFloat());
- if (current_level >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
- {
- if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
- TC_LOG_ERROR("sql.sql", "Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL, current_level);
- else
+ if (current_level >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
- TC_LOG_INFO("misc", "Unused (> MaxPlayerLevel in worldserver.conf) level %u in `player_xp_for_levels` table, ignoring.", current_level);
- ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
+ TC_LOG_ERROR("sql.sql", "Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL, current_level);
+ else
+ {
+ TC_LOG_INFO("misc", "Unused (> MaxPlayerLevel in worldserver.conf) level %u in `player_xp_for_level` table, ignoring.", current_level);
+ ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ }
+ continue;
}
- continue;
- }
- //PlayerXPperLevel
- _playerXPperLevel[current_level] = current_xp;
- ++count;
+ //PlayerXPperLevel
+ _playerXPperLevel[current_level] = current_xp;
+ ++count;
+ } while (result->NextRow());
}
- while (result->NextRow());
- // fill level gaps
+ // fill level gaps - only accounting levels > MAX_LEVEL
for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
{
if (_playerXPperLevel[level] == 0)
{
- TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 100.", level + 1, level);
- _playerXPperLevel[level] = _playerXPperLevel[level - 1] + 100;
+ TC_LOG_ERROR("sql.sql", "Level %i does not have XP for level data. Using data of level [%i] + 12000.", level + 1, level);
+ _playerXPperLevel[level] = _playerXPperLevel[level - 1] + 12000;
}
}
- TC_LOG_INFO("server.loading", ">> Loaded %u xp for level definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u xp for level definition(s) from database in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
@@ -8368,7 +8373,7 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit
void ObjectMgr::LoadCreatureClassLevelStats()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 16
+ // 0 1 2 3 4 5 6 7 8 9 10 11
QueryResult result = WorldDatabase.Query("SELECT level, class, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2, damage_exp3, damage_exp4, damage_exp5 FROM creature_classlevelstats");
if (!result)
diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h
index bdc78479494..7e26f2336e2 100644
--- a/src/server/game/Miscellaneous/Formulas.h
+++ b/src/server/game/Miscellaneous/Formulas.h
@@ -47,14 +47,18 @@ namespace Trinity
{
uint8 level;
- if (pl_level <= 5)
+ if (pl_level < 7)
level = 0;
- else if (pl_level <= 39)
- level = pl_level - 5 - pl_level / 10;
- else if (pl_level <= 59)
- level = pl_level - 1 - pl_level / 5;
+ else if (pl_level < 35)
+ {
+ uint8 count = 0;
+ for (int i = 15; i <= pl_level; ++i)
+ if (i % 5 == 0) ++count;
+
+ level = (pl_level - 7) - (count - 1);
+ }
else
- level = pl_level - 9;
+ level = pl_level - 10;
sScriptMgr->OnGrayLevelCalculation(level, pl_level);
return level;
@@ -83,7 +87,7 @@ namespace Trinity
{
uint8 diff;
- if (pl_level < 8)
+ if (pl_level < 4)
diff = 5;
else if (pl_level < 10)
diff = 6;
@@ -112,30 +116,15 @@ namespace Trinity
return diff;
}
- inline uint32 BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content)
+ inline uint32 BaseGain(uint8 pl_level, uint8 mob_level)
{
uint32 baseGain;
- uint32 nBaseExp;
- switch (content)
- {
- case CONTENT_1_60:
- nBaseExp = 45;
- break;
- case CONTENT_61_70:
- nBaseExp = 235;
- break;
- case CONTENT_71_80:
- nBaseExp = 580;
- break;
- case CONTENT_81_85:
- nBaseExp = 1878;
- break;
- default:
- TC_LOG_ERROR("misc", "BaseGain: Unsupported content level %u", content);
- nBaseExp = 45;
- break;
- }
+ GtOCTLevelExperienceEntry const* BaseExpPlayer = sGtOCTLevelExperienceStore.EvaluateTable(pl_level - 1, 1);
+ GtOCTLevelExperienceEntry const* BaseExpMob = sGtOCTLevelExperienceStore.EvaluateTable(mob_level - 1, 1);
+
+ GtOCTLevelExperienceEntry const* CoefPlayer = sGtOCTLevelExperienceStore.EvaluateTable(pl_level - 1, 4);
+ GtOCTLevelExperienceEntry const* CoefMob = sGtOCTLevelExperienceStore.EvaluateTable(mob_level - 1, 4);
if (mob_level >= pl_level)
{
@@ -143,7 +132,7 @@ namespace Trinity
if (nLevelDiff > 4)
nLevelDiff = 4;
- baseGain = ((pl_level * 5 + nBaseExp) * (20 + nLevelDiff) / 10 + 1) / 2;
+ baseGain = BaseExpPlayer->Data * (1 + 0.05 * nLevelDiff);
}
else
{
@@ -151,13 +140,13 @@ namespace Trinity
if (mob_level > gray_level)
{
uint8 ZD = GetZeroDifference(pl_level);
- baseGain = (pl_level * 5 + nBaseExp) * (ZD + mob_level - pl_level) / ZD;
+ baseGain = round(BaseExpMob->Data * ((1 - ((pl_level - mob_level) / float(ZD))) * (CoefMob->Data / CoefPlayer->Data)));
}
else
baseGain = 0;
}
- sScriptMgr->OnBaseGainCalculation(baseGain, pl_level, mob_level, content);
+ sScriptMgr->OnBaseGainCalculation(baseGain, pl_level, mob_level);
return baseGain;
}
@@ -171,10 +160,14 @@ namespace Trinity
{
float xpMod = 1.0f;
- gain = BaseGain(player->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(u->GetMapId(), u->GetZoneId()));
+ gain = BaseGain(player->getLevel(), u->getLevel());
if (gain && creature)
{
+ // Players get only 10% xp for killing creatures of lower expansion levels than himself
+ if ((creature->GetCreatureTemplate()->expansion < GetExpansionForLevel(player->getLevel())))
+ gain = uint32(round(gain / 10.0f));
+
if (creature->isElite())
{
// Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus.
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 9c49958f10a..735328a0f1f 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -519,9 +519,9 @@ void ScriptMgr::OnZeroDifferenceCalculation(uint8& diff, uint8 playerLevel)
FOREACH_SCRIPT(FormulaScript)->OnZeroDifferenceCalculation(diff, playerLevel);
}
-void ScriptMgr::OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content)
+void ScriptMgr::OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel)
{
- FOREACH_SCRIPT(FormulaScript)->OnBaseGainCalculation(gain, playerLevel, mobLevel, content);
+ FOREACH_SCRIPT(FormulaScript)->OnBaseGainCalculation(gain, playerLevel, mobLevel);
}
void ScriptMgr::OnGainCalculation(uint32& gain, Player* player, Unit* unit)
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 0e9cdd9808f..b3e4a2314db 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -294,7 +294,7 @@ class FormulaScript : public ScriptObject
virtual void OnZeroDifferenceCalculation(uint8& /*diff*/, uint8 /*playerLevel*/) { }
// Called after calculating base experience gain.
- virtual void OnBaseGainCalculation(uint32& /*gain*/, uint8 /*playerLevel*/, uint8 /*mobLevel*/, ContentLevels /*content*/) { }
+ virtual void OnBaseGainCalculation(uint32& /*gain*/, uint8 /*playerLevel*/, uint8 /*mobLevel*/) { }
// Called after calculating experience gain.
virtual void OnGainCalculation(uint32& /*gain*/, Player* /*player*/, Unit* /*unit*/) { }
@@ -944,7 +944,7 @@ class ScriptMgr
void OnGrayLevelCalculation(uint8& grayLevel, uint8 playerLevel);
void OnColorCodeCalculation(XPColorChar& color, uint8 playerLevel, uint8 mobLevel);
void OnZeroDifferenceCalculation(uint8& diff, uint8 playerLevel);
- void OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel, ContentLevels content);
+ void OnBaseGainCalculation(uint32& gain, uint8 playerLevel, uint8 mobLevel);
void OnGainCalculation(uint32& gain, Player* player, Unit* unit);
void OnGroupRateCalculation(float& rate, uint32 count, bool isRaid);