diff --git a/sql/characters.sql b/sql/characters.sql index 683c03d59..31627b178 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_9661_01_characters_character_talent` bit(1) default NULL + `required_9680_01_characters_character_stats` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -830,6 +830,55 @@ LOCK TABLES `character_spell_cooldown` WRITE; /*!40000 ALTER TABLE `character_spell_cooldown` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_stats` +-- + +DROP TABLE IF EXISTS `character_stats`; +CREATE TABLE `character_stats` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `maxhealth` int(10) UNSIGNED NOT NULL default '0', + `maxpower1` int(10) UNSIGNED NOT NULL default '0', + `maxpower2` int(10) UNSIGNED NOT NULL default '0', + `maxpower3` int(10) UNSIGNED NOT NULL default '0', + `maxpower4` int(10) UNSIGNED NOT NULL default '0', + `maxpower5` int(10) UNSIGNED NOT NULL default '0', + `maxpower6` int(10) UNSIGNED NOT NULL default '0', + `maxpower7` int(10) UNSIGNED NOT NULL default '0', + `strength` int(10) UNSIGNED NOT NULL default '0', + `agility` int(10) UNSIGNED NOT NULL default '0', + `stamina` int(10) UNSIGNED NOT NULL default '0', + `intellect` int(10) UNSIGNED NOT NULL default '0', + `spirit` int(10) UNSIGNED NOT NULL default '0', + `armor` int(10) UNSIGNED NOT NULL default '0', + `resHoly` int(10) UNSIGNED NOT NULL default '0', + `resFire` int(10) UNSIGNED NOT NULL default '0', + `resNature` int(10) UNSIGNED NOT NULL default '0', + `resFrost` int(10) UNSIGNED NOT NULL default '0', + `resShadow` int(10) UNSIGNED NOT NULL default '0', + `resArcane` int(10) UNSIGNED NOT NULL default '0', + `blockPct` float UNSIGNED NOT NULL default '0', + `dodgePct` float UNSIGNED NOT NULL default '0', + `parryPct` float UNSIGNED NOT NULL default '0', + `critPct` float UNSIGNED NOT NULL default '0', + `rangedCritPct` float UNSIGNED NOT NULL default '0', + `spellCritPct` float UNSIGNED NOT NULL default '0', + `attackPower` int(10) UNSIGNED NOT NULL default '0', + `rangedAttackPower` int(10) UNSIGNED NOT NULL default '0', + `spellPower` int(10) UNSIGNED NOT NULL default '0', + + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_stats` +-- + +LOCK TABLES `character_stats` WRITE; +/*!40000 ALTER TABLE `character_stats` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_stats` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_talent` -- diff --git a/sql/updates/9680_01_characters_character_stats.sql b/sql/updates/9680_01_characters_character_stats.sql new file mode 100644 index 000000000..ee937cbac --- /dev/null +++ b/sql/updates/9680_01_characters_character_stats.sql @@ -0,0 +1,37 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_9661_01_characters_character_talent required_9680_01_characters_character_stats bit; + +DROP TABLE IF EXISTS `character_stats`; +CREATE TABLE `character_stats` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier, Low part', + `maxhealth` int(10) UNSIGNED NOT NULL default '0', + `maxpower1` int(10) UNSIGNED NOT NULL default '0', + `maxpower2` int(10) UNSIGNED NOT NULL default '0', + `maxpower3` int(10) UNSIGNED NOT NULL default '0', + `maxpower4` int(10) UNSIGNED NOT NULL default '0', + `maxpower5` int(10) UNSIGNED NOT NULL default '0', + `maxpower6` int(10) UNSIGNED NOT NULL default '0', + `maxpower7` int(10) UNSIGNED NOT NULL default '0', + `strength` int(10) UNSIGNED NOT NULL default '0', + `agility` int(10) UNSIGNED NOT NULL default '0', + `stamina` int(10) UNSIGNED NOT NULL default '0', + `intellect` int(10) UNSIGNED NOT NULL default '0', + `spirit` int(10) UNSIGNED NOT NULL default '0', + `armor` int(10) UNSIGNED NOT NULL default '0', + `resHoly` int(10) UNSIGNED NOT NULL default '0', + `resFire` int(10) UNSIGNED NOT NULL default '0', + `resNature` int(10) UNSIGNED NOT NULL default '0', + `resFrost` int(10) UNSIGNED NOT NULL default '0', + `resShadow` int(10) UNSIGNED NOT NULL default '0', + `resArcane` int(10) UNSIGNED NOT NULL default '0', + `blockPct` float UNSIGNED NOT NULL default '0', + `dodgePct` float UNSIGNED NOT NULL default '0', + `parryPct` float UNSIGNED NOT NULL default '0', + `critPct` float UNSIGNED NOT NULL default '0', + `rangedCritPct` float UNSIGNED NOT NULL default '0', + `spellCritPct` float UNSIGNED NOT NULL default '0', + `attackPower` int(10) UNSIGNED NOT NULL default '0', + `rangedAttackPower` int(10) UNSIGNED NOT NULL default '0', + `spellPower` int(10) UNSIGNED NOT NULL default '0', + + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index aa0add420..137b42cb7 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -102,6 +102,7 @@ pkgdata_DATA = \ 9656_02_mangos_mangos_string.sql \ 9661_01_characters_character_talent.sql \ 9663_01_mangos_mangos_string.sql \ + 9680_01_characters_character_stats.sql \ README ## Additional files to include when running 'make dist' @@ -184,4 +185,5 @@ EXTRA_DIST = \ 9656_02_mangos_mangos_string.sql \ 9661_01_characters_character_talent.sql \ 9663_01_mangos_mangos_string.sql \ + 9680_01_characters_character_stats.sql \ README diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 931ddb743..250acb593 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16511,6 +16511,8 @@ void Player::SaveToDB() GetSession()->SaveTutorialsData(); // changed only while character in game _SaveGlyphs(); _SaveTalents(); + if(m_session->isLogingOut()) // only save stats on logout + _SaveStats(); CharacterDatabase.CommitTransaction(); @@ -16904,6 +16906,40 @@ void Player::_SaveTalents() } } +// save player stats -- only for external usage +// real stats will be recalculated on player login +void Player::_SaveStats() +{ + // check if stat saving is enabled and if char level is high enough + if(!sWorld.getConfig(CONFIG_UINT32_MIN_LEVEL_STAT_SAVE) || getLevel() < sWorld.getConfig(CONFIG_UINT32_MIN_LEVEL_STAT_SAVE)) + return; + + CharacterDatabase.PExecute("DELETE FROM character_stats WHERE guid = '%u'", GetGUIDLow()); + std::ostringstream ss; + ss << "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, " + "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " + "blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, spellPower) VALUES (" + << GetGUIDLow() << ", " + << GetMaxHealth() << ", "; + for(int i = 0; i < MAX_POWERS; ++i) + ss << GetMaxPower(Powers(i)) << ", "; + for(int i = 0; i < MAX_STATS; ++i) + ss << GetStat(Stats(i)) << ", "; + // armor + school resistances + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + ss << GetResistance(SpellSchools(i)) << ","; + ss << GetFloatValue(PLAYER_BLOCK_PERCENTAGE) << ", " + << GetFloatValue(PLAYER_DODGE_PERCENTAGE) << ", " + << GetFloatValue(PLAYER_PARRY_PERCENTAGE) << ", " + << GetFloatValue(PLAYER_CRIT_PERCENTAGE) << ", " + << GetFloatValue(PLAYER_RANGED_CRIT_PERCENTAGE) << ", " + << GetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1) << ", " + << GetUInt32Value(UNIT_FIELD_ATTACK_POWER) << ", " + << GetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) << ", " + << GetBaseSpellPowerBonus() << ")"; + CharacterDatabase.Execute( ss.str().c_str() ); +} + void Player::outDebugValues() const { if(!sLog.IsOutDebug()) // optimize disabled debug output diff --git a/src/game/Player.h b/src/game/Player.h index 2f637fc42..fd30a45e9 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2358,6 +2358,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _SaveBGData(); void _SaveGlyphs(); void _SaveTalents(); + void _SaveStats(); void _SetCreateBits(UpdateMask *updateMask, Player *target) const; void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; diff --git a/src/game/World.cpp b/src/game/World.cpp index 5924b0f0c..e89de4def 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -516,7 +516,8 @@ void World::LoadConfigSettings(bool reload) setConfigMinMax(CONFIG_UINT32_COMPRESSION, "Compression", 1, 1, 9); setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true); setConfig(CONFIG_BOOL_GRID_UNLOAD, "GridUnload", true); - setConfigPos(CONFIG_UINT32_INTERVAL_SAVE, "PlayerSaveInterval", 15 * MINUTE * IN_MILLISECONDS); + setConfigPos(CONFIG_UINT32_INTERVAL_SAVE, "PlayerSave.Interval", 15 * MINUTE * IN_MILLISECONDS); + setConfigMinMax(CONFIG_UINT32_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, 0, MAX_LEVEL); setConfigMin(CONFIG_UINT32_INTERVAL_GRIDCLEAN, "GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS, MIN_GRID_DELAY); if (reload) diff --git a/src/game/World.h b/src/game/World.h index 557e7a232..7c72395e8 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -173,6 +173,7 @@ enum eConfigUInt32Values CONFIG_UINT32_TIMERBAR_BREATH_MAX, CONFIG_UINT32_TIMERBAR_FIRE_GMLEVEL, CONFIG_UINT32_TIMERBAR_FIRE_MAX, + CONFIG_UINT32_MIN_LEVEL_STAT_SAVE, CONFIG_UINT32_VALUE_COUNT }; diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 296ae772f..131132d9f 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -1,7 +1,7 @@ ##################################### # MaNGOS Configuration file # ##################################### -ConfVersion=2010030401 +ConfVersion=2010040601 ################################################################################################################### # CONNECTIONS AND DIRECTORIES @@ -112,10 +112,15 @@ BindIP = "0.0.0.0" # Weather update interval (in milliseconds) # Default: 600000 (10 min) # -# PlayerSaveInterval +# PlayerSave.Interval # Player save interval (in milliseconds) # Default: 900000 (15 min) # +# PlayerSave.Stats.MinLevel +# Minimum level for saving character stats for external usage in database +# Default: 0 (do not save character stats) +# 1+ (save stats for characters with level 1+) +# # vmap.enableLOS # vmap.enableHeight # Enable/Disable VMmap support for line of sight and height calculation @@ -159,6 +164,7 @@ BindIP = "0.0.0.0" # Default: 1 (permit addon channel) # 0 (do not permit addon channel) # +# ################################################################################################################### UseProcessors = 0 @@ -172,7 +178,8 @@ SocketSelectTime = 10000 GridCleanUpDelay = 300000 MapUpdateInterval = 100 ChangeWeatherInterval = 600000 -PlayerSaveInterval = 900000 +PlayerSave.Interval = 900000 +PlayerSave.Stats.MinLevel = 0 vmap.enableLOS = 0 vmap.enableHeight = 0 vmap.ignoreMapIds = "369" diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 06b18f4ce..e4efc3cdd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9679" + #define REVISION_NR "9680" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index d715a463b..7caace28a 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ - #define REVISION_DB_CHARACTERS "required_9661_01_characters_character_talent" + #define REVISION_DB_CHARACTERS "required_9680_01_characters_character_stats" #define REVISION_DB_MANGOS "required_9663_01_mangos_mangos_string" #define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #endif // __REVISION_SQL_H__