mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[0023] Use DBC data to set the correct amount of hp and mana based on player level and class. Patch by Subv
Signed-off-by: Salja <salja2012@hotmail.de>
This commit is contained in:
parent
6092ba754f
commit
0d7006dd23
12 changed files with 48 additions and 142 deletions
|
|
@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
|
|||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`cache_id` int(10) default '0',
|
||||
`required_0001_xxxxx_01_mangos` bit(1) default NULL
|
||||
`required_0023_xxxxx_01_mangos_player_classlevelstats` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_0001_xxxxx_01_mangos required_0023_xxxxx_01_mangos_player_classlevelstats bit;
|
||||
|
||||
DROP TABLE IF EXISTS `player_classlevelstats`;
|
||||
|
|
@ -106,6 +106,8 @@ DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStor
|
|||
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
|
||||
//DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
|
||||
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
|
||||
DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore(GtOCTBaseHPByClassfmt);
|
||||
DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore(GtOCTBaseMPByClassfmt);
|
||||
|
||||
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
|
||||
|
||||
|
|
@ -480,6 +482,8 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
|
||||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTBaseHPByClassStore, dbcPath,"gtOCTBaseHPByClass.dbc"); // 15595
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTBaseMPByClassStore, dbcPath,"gtOCTBaseMPByClass.dbc"); // 15595
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemBagFamilyStore, dbcPath,"ItemBagFamily.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemClassStore, dbcPath,"ItemClass.dbc");
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingSca
|
|||
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
|
||||
//extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
|
||||
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
|
||||
extern DBCStorage <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore;
|
||||
extern DBCStorage <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore;
|
||||
extern DBCStorage <HolidaysEntry> sHolidaysStore;
|
||||
extern DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore;
|
||||
extern DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore;
|
||||
|
|
|
|||
|
|
@ -1058,6 +1058,16 @@ struct GtRegenMPPerSptEntry
|
|||
float ratio;
|
||||
};
|
||||
|
||||
struct GtOCTBaseHPByClassEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct GtOCTBaseMPByClassEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
/*struct HolidayDescriptionsEntry
|
||||
{
|
||||
uint32 ID; // 0, m_ID this is NOT holiday id
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ const char GtOCTRegenHPfmt[]="xf";
|
|||
//const char GtOCTRegenMPfmt[]="f";
|
||||
const char GtRegenHPPerSptfmt[]="xf";
|
||||
const char GtRegenMPPerSptfmt[]="xf";
|
||||
const char GtOCTBaseHPByClassfmt[]="df";
|
||||
const char GtOCTBaseMPByClassfmt[]="df";
|
||||
const char Holidaysfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char ItemClassfmt[]="nixxxs";
|
||||
const char ItemArmorQualityfmt[]="nfffffffi";
|
||||
|
|
|
|||
|
|
@ -165,10 +165,6 @@ ObjectMgr::~ObjectMgr()
|
|||
for (PetLevelInfoMap::iterator i = petInfo.begin(); i != petInfo.end(); ++i)
|
||||
delete[] i->second;
|
||||
|
||||
// free only if loaded
|
||||
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
|
||||
delete[] playerClassInfo[class_].levelInfo;
|
||||
|
||||
for (int race = 0; race < MAX_RACES; ++race)
|
||||
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
|
||||
delete[] playerInfo[race][class_].levelInfo;
|
||||
|
|
@ -3003,104 +2999,6 @@ void ObjectMgr::LoadPlayerInfo()
|
|||
}
|
||||
}
|
||||
|
||||
// Loading levels data (class only dependent)
|
||||
{
|
||||
// 0 1 2 3
|
||||
QueryResult* result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats");
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
BarGoLink bar(1);
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u level health/mana definitions", count);
|
||||
sLog.outErrorDb("Error loading `player_classlevelstats` table or empty table.");
|
||||
Log::WaitBeforeContinueIfNeed();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
BarGoLink bar(result->GetRowCount());
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 current_class = fields[0].GetUInt32();
|
||||
if (current_class >= MAX_CLASSES)
|
||||
{
|
||||
sLog.outErrorDb("Wrong class %u in `player_classlevelstats` table, ignoring.", current_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 current_level = fields[1].GetUInt32();
|
||||
if (current_level == 0)
|
||||
{
|
||||
sLog.outErrorDb("Wrong level %u in `player_classlevelstats` table, ignoring.", current_level);
|
||||
continue;
|
||||
}
|
||||
else if (current_level > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.", STRONG_MAX_LEVEL, current_level);
|
||||
else
|
||||
{
|
||||
DETAIL_LOG("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.", current_level);
|
||||
++count; // make result loading percent "expected" correct in case disabled detail mode for example.
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerClassInfo* pClassInfo = &playerClassInfo[current_class];
|
||||
|
||||
if (!pClassInfo->levelInfo)
|
||||
pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)];
|
||||
|
||||
PlayerClassLevelInfo* pClassLevelInfo = &pClassInfo->levelInfo[current_level - 1];
|
||||
|
||||
pClassLevelInfo->basehealth = fields[2].GetUInt16();
|
||||
pClassLevelInfo->basemana = fields[3].GetUInt16();
|
||||
|
||||
bar.step();
|
||||
++count;
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u level health/mana definitions", count);
|
||||
}
|
||||
|
||||
// Fill gaps and check integrity
|
||||
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
|
||||
{
|
||||
// skip nonexistent classes
|
||||
if (!sChrClassesStore.LookupEntry(class_))
|
||||
continue;
|
||||
|
||||
PlayerClassInfo* pClassInfo = &playerClassInfo[class_];
|
||||
|
||||
// fatal error if no level 1 data
|
||||
if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0)
|
||||
{
|
||||
sLog.outErrorDb("Class %i Level 1 does not have health/mana data!", class_);
|
||||
Log::WaitBeforeContinueIfNeed();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// fill level gaps
|
||||
for (uint32 level = 1; level < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL); ++level)
|
||||
{
|
||||
if (pClassInfo->levelInfo[level].basehealth == 0)
|
||||
{
|
||||
sLog.outErrorDb("Class %i Level %i does not have health/mana data. Using stats data of level %i.", class_, level + 1, level);
|
||||
pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loading levels data (class/race dependent)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
|
|
@ -3289,17 +3187,25 @@ void ObjectMgr::LoadPlayerInfo()
|
|||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const
|
||||
void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, uint32& baseHP, uint32& baseMana) const
|
||||
{
|
||||
if (level < 1 || class_ >= MAX_CLASSES)
|
||||
return;
|
||||
|
||||
PlayerClassInfo const* pInfo = &playerClassInfo[class_];
|
||||
|
||||
if (level > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
||||
level = sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL);
|
||||
|
||||
*info = pInfo->levelInfo[level - 1];
|
||||
GtOCTBaseHPByClassEntry const* hp = sGtOCTBaseHPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
|
||||
GtOCTBaseMPByClassEntry const* mp = sGtOCTBaseMPByClassStore.LookupEntry((class_-1) * GT_MAX_LEVEL + level-1);
|
||||
|
||||
if (!hp || !mp)
|
||||
{
|
||||
sLog.outError("Tried to get non-existant Class-Level combination data for base hp/mp. Class %u Level %u", class_, level);
|
||||
return;
|
||||
}
|
||||
|
||||
baseHP = uint32(hp->ratio);
|
||||
baseMana = uint32(mp->ratio);
|
||||
}
|
||||
|
||||
void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint32 level, PlayerLevelInfo* info) const
|
||||
|
|
|
|||
|
|
@ -509,12 +509,7 @@ class ObjectMgr
|
|||
|
||||
PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint32 level) const;
|
||||
|
||||
PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const
|
||||
{
|
||||
if (class_ >= MAX_CLASSES) return NULL;
|
||||
return &playerClassInfo[class_];
|
||||
}
|
||||
void GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const;
|
||||
void GetPlayerClassLevelInfo(uint32 class_, uint32 level, uint32& baseHP, uint32& baseMana) const;
|
||||
|
||||
PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const
|
||||
{
|
||||
|
|
@ -1174,8 +1169,6 @@ class ObjectMgr
|
|||
// PetLevelInfoMap[creature_id][level]
|
||||
PetLevelInfoMap petInfo; // [creature_id][level]
|
||||
|
||||
PlayerClassInfo playerClassInfo[MAX_CLASSES];
|
||||
|
||||
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
|
||||
PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES];
|
||||
|
||||
|
|
|
|||
|
|
@ -2530,15 +2530,15 @@ void Player::GiveLevel(uint32 level)
|
|||
PlayerLevelInfo info;
|
||||
sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), level, &info);
|
||||
|
||||
PlayerClassLevelInfo classInfo;
|
||||
sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, &classInfo);
|
||||
uint32 basehp = 0, basemana = 0;
|
||||
sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, basehp, basemana);
|
||||
|
||||
// send levelup info to client
|
||||
WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_POWERS * 4 + MAX_STATS * 4));
|
||||
data << uint32(level);
|
||||
data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth()));
|
||||
data << uint32(int32(basehp) - int32(GetCreateHealth()));
|
||||
// for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-4)
|
||||
data << uint32(int32(classInfo.basemana) - int32(GetCreateMana()));
|
||||
data << uint32(int32(basemana) - int32(GetCreateMana()));
|
||||
data << uint32(0);
|
||||
data << uint32(0);
|
||||
data << uint32(0);
|
||||
|
|
@ -2564,8 +2564,8 @@ void Player::GiveLevel(uint32 level)
|
|||
for (int i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
SetCreateStat(Stats(i), info.stats[i]);
|
||||
|
||||
SetCreateHealth(classInfo.basehealth);
|
||||
SetCreateMana(classInfo.basemana);
|
||||
SetCreateHealth(basehp);
|
||||
SetCreateMana(basemana);
|
||||
|
||||
InitTalentForLevel();
|
||||
InitTaxiNodesForLevel();
|
||||
|
|
@ -2639,8 +2639,8 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||
if (reapplyMods) // reapply stats values only on .reset stats (level) command
|
||||
_RemoveAllStatBonuses();
|
||||
|
||||
PlayerClassLevelInfo classInfo;
|
||||
sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo);
|
||||
uint32 basehp = 0, basemana = 0;
|
||||
sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana);
|
||||
|
||||
PlayerLevelInfo info;
|
||||
sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info);
|
||||
|
|
@ -2663,10 +2663,10 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||
for (int i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
SetStat(Stats(i), info.stats[i]);
|
||||
|
||||
SetCreateHealth(classInfo.basehealth);
|
||||
SetCreateHealth(basehp);
|
||||
|
||||
// set create powers
|
||||
SetCreateMana(classInfo.basemana);
|
||||
SetCreateMana(basemana);
|
||||
|
||||
SetArmor(int32(m_createStats[STAT_AGILITY] * 2));
|
||||
|
||||
|
|
@ -2750,7 +2750,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||
for (int i = POWER_MANA; i < MAX_POWERS; ++i)
|
||||
SetMaxPower(Powers(i), GetCreatePowers(Powers(i)));
|
||||
|
||||
SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later
|
||||
SetMaxHealth(basehp); // stamina bonus will applied later
|
||||
|
||||
// cleanup mounted state (it will set correctly at aura loading if player saved at mount.
|
||||
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
|
||||
|
|
|
|||
|
|
@ -265,20 +265,6 @@ struct PlayerCreateInfoItem
|
|||
|
||||
typedef std::list<PlayerCreateInfoItem> PlayerCreateInfoItems;
|
||||
|
||||
struct PlayerClassLevelInfo
|
||||
{
|
||||
PlayerClassLevelInfo() : basehealth(0), basemana(0) {}
|
||||
uint16 basehealth;
|
||||
uint16 basemana;
|
||||
};
|
||||
|
||||
struct PlayerClassInfo
|
||||
{
|
||||
PlayerClassInfo() : levelInfo(NULL) { }
|
||||
|
||||
PlayerClassLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
|
||||
};
|
||||
|
||||
struct PlayerLevelInfo
|
||||
{
|
||||
PlayerLevelInfo() { for (int i = 0; i < MAX_STATS; ++i) stats[i] = 0; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "0022"
|
||||
#define REVISION_NR "0023"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __REVISION_SQL_H__
|
||||
#define __REVISION_SQL_H__
|
||||
#define REVISION_DB_CHARACTERS "required_0001_xxxxx_01_characters"
|
||||
#define REVISION_DB_MANGOS "required_0001_xxxxx_01_mangos"
|
||||
#define REVISION_DB_MANGOS "required_0023_xxxxx_01_mangos_player_classlevelstats"
|
||||
#define REVISION_DB_REALMD "required_0014_xxxxx_01_realmd_account_access"
|
||||
#endif // __REVISION_SQL_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue