aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql5
-rw-r--r--sql/updates/characters/master/2021_10_02_00_characters.sql12
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp13
-rw-r--r--src/server/game/Entities/Player/Player.h8
5 files changed, 39 insertions, 5 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index e1ea55f1a03..637cfc8c1b0 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1806,6 +1806,8 @@ CREATE TABLE `characters` (
`orientation` float NOT NULL DEFAULT '0',
`taximask` text NOT NULL,
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `createTime` bigint(20) NOT NULL DEFAULT '0',
+ `createMode` tinyint(4) NOT NULL DEFAULT '0',
`cinematic` tinyint(3) unsigned NOT NULL DEFAULT '0',
`totaltime` int(10) unsigned NOT NULL DEFAULT '0',
`leveltime` int(10) unsigned NOT NULL DEFAULT '0',
@@ -3718,7 +3720,8 @@ INSERT INTO `updates` VALUES
('2021_05_11_00_characters.sql','C3F0337CE8363F970AB4FDB9D23BBB7C650A0B0E','ARCHIVED','2021-05-11 15:39:26',0),
('2021_07_04_00_characters.sql','E0E7AD664DDB553E96B457DD9ED8976665E94007','ARCHIVED','2021-07-04 22:23:24',0),
('2021_08_11_00_characters.sql','2137A52A45B045104B97D39626CE3C0214625B17','ARCHIVED','2021-08-11 21:48:57',0),
-('2021_08_18_00_characters.sql','5BA1326EE8EC907CDE82E6E8BCB38EA2E661F10A','ARCHIVED','2021-08-18 15:14:17',0);
+('2021_08_18_00_characters.sql','5BA1326EE8EC907CDE82E6E8BCB38EA2E661F10A','ARCHIVED','2021-08-18 15:14:17',0),
+('2021_10_02_00_characters.sql','C6831D3ED03F6BD390A5E5E403FA402D6DC0E95D','RELEASED','2021-10-02 21:21:37',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/master/2021_10_02_00_characters.sql b/sql/updates/characters/master/2021_10_02_00_characters.sql
new file mode 100644
index 00000000000..e6e6285b72f
--- /dev/null
+++ b/sql/updates/characters/master/2021_10_02_00_characters.sql
@@ -0,0 +1,12 @@
+ALTER TABLE `characters`
+ ADD `createTime` bigint(20) NOT NULL DEFAULT '0' AFTER `online`,
+ ADD `createMode` tinyint(4) NOT NULL DEFAULT '0' AFTER `createTime`;
+
+ -- AT_LOGIN_FIRST: Characters that have never logged in have accurate creation timestamp in `logout_time`
+UPDATE `characters` SET `createTime`=`logout_time` WHERE (`at_login` & 0x20) != 0;
+ -- attempt to find lowest criteria timestamp for characters that have logged in already
+UPDATE `characters` SET `createTime`=(SELECT COALESCE(MIN(candidates.`date`), UNIX_TIMESTAMP()) FROM (
+SELECT MIN(cap.`date`) `date` FROM `character_achievement_progress` cap WHERE cap.`guid`=`characters`.`guid`
+UNION
+SELECT MIN(ca.`date`) `date` FROM `character_achievement` ca WHERE ca.`guid`=`characters`.`guid`
+) candidates) WHERE (`at_login` & 0x20) = 0;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index c30f02c1918..fec2dbf81bb 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -83,7 +83,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, "
- "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
+ "position_x, position_y, position_z, map, orientation, taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
"resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
"health, power1, power2, power3, power4, power5, power6, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, raidDifficulty, legacyRaidDifficulty, fishingSteps, "
@@ -476,13 +476,13 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// Player saving
PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, "
"map, instance_id, dungeonDifficulty, raidDifficulty, legacyRaidDifficulty, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, "
- "taximask, cinematic, "
+ "taximask, createTime, createMode, cinematic, "
"totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, primarySpecialization, "
"extra_flags, stable_slots, at_login, zone, "
"death_expire_time, taxi_path, totalKills, "
"todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
"power4, power5, power6, latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild) VALUES "
- "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,inventorySlots=?,bankSlots=?,restState=?,playerFlags=?,playerFlagsEx=?,"
"map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,numRespecs=?,primarySpecialization=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b2a8dd0a632..9185f23ec27 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -202,6 +202,8 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
m_trade = nullptr;
+ m_createTime = 0;
+ m_createMode = PlayerCreateMode::Normal;
m_cinematic = 0;
m_movie = 0;
@@ -450,6 +452,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac
}
SetMap(sMapMgr->CreateMap(info->mapId, this));
+ m_createTime = GameTime::GetGameTime();
UpdatePositionData();
uint8 powertype = cEntry->DisplayPower;
@@ -17725,7 +17728,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder)
struct PlayerLoadData
{
// "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, "
- // "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
+ // "position_x, position_y, position_z, map, orientation, taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
// "resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
// "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
// "health, power1, power2, power3, power4, power5, power6, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, raidDifficulty, legacyRaidDifficulty, fishingSteps, "
@@ -17752,6 +17755,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder)
uint16 map;
float orientation;
std::string taximask;
+ time_t createTime;
+ PlayerCreateMode createMode;
uint8 cinematic;
uint32 totaltime;
uint32 leveltime;
@@ -17820,6 +17825,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder)
map = fields[i++].GetUInt16();
orientation = fields[i++].GetFloat();
taximask = fields[i++].GetString();
+ createTime = fields[i++].GetInt64();
+ createMode = PlayerCreateMode(fields[i++].GetInt8());
cinematic = fields[i++].GetUInt8();
totaltime = fields[i++].GetUInt32();
leveltime = fields[i++].GetUInt32();
@@ -18302,6 +18309,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder)
SetDrunkValue(newDrunkValue);
+ m_createTime = fields.createTime;
+ m_createMode = fields.createMode;
m_cinematic = fields.cinematic;
m_Played_time[PLAYED_TIME_TOTAL] = fields.totaltime;
m_Played_time[PLAYED_TIME_LEVEL] = fields.leveltime;
@@ -20371,6 +20380,8 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
std::ostringstream ss;
ss << m_taxi;
stmt->setString(index++, ss.str());
+ stmt->setInt64(index++, m_createTime);
+ stmt->setInt8(index++, AsUnderlyingType(m_createMode));
stmt->setUInt8(index++, m_cinematic);
stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_TOTAL]);
stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_LEVEL]);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 02aba42b5d5..17818b4c33c 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -114,6 +114,12 @@ namespace WorldPackets
TC_GAME_API uint32 GetBagSize(Bag const* bag);
TC_GAME_API Item* GetItemInBag(Bag const* bag, uint8 slot);
+enum class PlayerCreateMode : int8
+{
+ Normal = 0,
+ NPE = 1
+};
+
typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 256
@@ -2900,6 +2906,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
JoinedChannelsList m_channels;
+ time_t m_createTime;
+ PlayerCreateMode m_createMode;
uint8 m_cinematic;
uint32 m_movie;