diff --git a/common/database.cpp b/common/database.cpp index cea5ddf2b..74596df23 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1095,13 +1095,13 @@ void Database::SetLFP(uint32 character_id, bool is_lfp) CharacterDataRepository::UpdateOne(*this, e); } -void Database::SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon) +void Database::SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 ingame) { auto e = CharacterDataRepository::FindOne(*this, character_id); - e.firstlogon = first_logon; - e.lfg = is_lfg ? 1 : 0; - e.lfp = is_lfp ? 1 : 0; + e.ingame = ingame; + e.lfg = is_lfg ? 1 : 0; + e.lfp = is_lfp ? 1 : 0; CharacterDataRepository::UpdateOne(*this, e); } @@ -1115,11 +1115,11 @@ void Database::SetLFG(uint32 character_id, bool is_lfg) CharacterDataRepository::UpdateOne(*this, e); } -void Database::SetFirstLogon(uint32 character_id, uint8 first_logon) +void Database::SetIngame(uint32 character_id, uint8 ingame) { auto e = CharacterDataRepository::FindOne(*this, character_id); - e.firstlogon = first_logon; + e.ingame = ingame; CharacterDataRepository::UpdateOne(*this, e); } diff --git a/common/database.h b/common/database.h index fe08e83fb..9b81f66a0 100644 --- a/common/database.h +++ b/common/database.h @@ -263,7 +263,7 @@ public: bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year); void ClearMerchantTemp(); void ClearPTimers(uint32 character_id); - void SetFirstLogon(uint32 character_id, uint8 first_logon); + void SetIngame(uint32 character_id, uint8 ingame); void SetLFG(uint32 character_id, bool is_lfg); void SetLFP(uint32 character_id, bool is_lfp); void SetLoginFlags(uint32 character_id, bool is_lfp, bool is_lfg, uint8 first_logon); diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 29aad812f..006bc6997 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7098,7 +7098,19 @@ ALTER TABLE `npc_types` ADD COLUMN `npc_tint_id` SMALLINT UNSIGNED NULL DEFAULT '0' AFTER `multiquest_enabled`; )", .content_schema_update = true - } + }, + ManifestEntry{ + .description = "2025_04_16_character_data_first_login.sql", + .check = "SHOW COLUMNS FROM `character_data` LIKE 'first_login'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `character_data` +CHANGE COLUMN `firstlogon` `ingame` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `xtargets`, +ADD COLUMN `first_login` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `xtargets`; +)", + .content_schema_update = false + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/repositories/base/base_character_data_repository.h b/common/repositories/base/base_character_data_repository.h index 05d8daa7e..3356d13c2 100644 --- a/common/repositories/base/base_character_data_repository.h +++ b/common/repositories/base/base_character_data_repository.h @@ -115,12 +115,14 @@ public: uint8_t lfg; std::string mailkey; uint8_t xtargets; - int8_t firstlogon; + uint8_t ingame; + uint32_t first_login; uint32_t e_aa_effects; uint32_t e_percent_to_aa; uint32_t e_expended_aa_spent; uint32_t aa_points_spent_old; uint32_t aa_points_old; + int32_t expansions; uint32_t e_last_invsnapshot; time_t deleted_at; uint8_t illusion_block; @@ -230,12 +232,14 @@ public: "lfg", "mailkey", "xtargets", - "firstlogon", + "ingame", + "first_login", "e_aa_effects", "e_percent_to_aa", "e_expended_aa_spent", "aa_points_spent_old", "aa_points_old", + "expansions", "e_last_invsnapshot", "deleted_at", "illusion_block", @@ -341,12 +345,14 @@ public: "lfg", "mailkey", "xtargets", - "firstlogon", + "ingame", + "first_login", "e_aa_effects", "e_percent_to_aa", "e_expended_aa_spent", "aa_points_spent_old", "aa_points_old", + "expansions", "e_last_invsnapshot", "UNIX_TIMESTAMP(deleted_at)", "illusion_block", @@ -486,12 +492,14 @@ public: e.lfg = 0; e.mailkey = ""; e.xtargets = 5; - e.firstlogon = 0; + e.ingame = 0; + e.first_login = 0; e.e_aa_effects = 0; e.e_percent_to_aa = 0; e.e_expended_aa_spent = 0; e.aa_points_spent_old = 0; e.aa_points_old = 0; + e.expansions = -1; e.e_last_invsnapshot = 0; e.deleted_at = 0; e.illusion_block = 0; @@ -627,15 +635,17 @@ public: e.lfg = row[93] ? static_cast(strtoul(row[93], nullptr, 10)) : 0; e.mailkey = row[94] ? row[94] : ""; e.xtargets = row[95] ? static_cast(strtoul(row[95], nullptr, 10)) : 5; - e.firstlogon = row[96] ? static_cast(atoi(row[96])) : 0; - e.e_aa_effects = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; - e.e_percent_to_aa = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; - e.e_expended_aa_spent = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; - e.aa_points_spent_old = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; - e.aa_points_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; - e.e_last_invsnapshot = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; - e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); - e.illusion_block = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.ingame = row[96] ? static_cast(strtoul(row[96], nullptr, 10)) : 0; + e.first_login = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; + e.e_aa_effects = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; + e.e_percent_to_aa = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; + e.e_expended_aa_spent = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; + e.aa_points_spent_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; + e.aa_points_old = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; + e.expansions = row[103] ? static_cast(atoi(row[103])) : -1; + e.e_last_invsnapshot = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.deleted_at = strtoll(row[105] ? row[105] : "-1", nullptr, 10); + e.illusion_block = row[106] ? static_cast(strtoul(row[106], nullptr, 10)) : 0; return e; } @@ -764,15 +774,17 @@ public: v.push_back(columns[93] + " = " + std::to_string(e.lfg)); v.push_back(columns[94] + " = '" + Strings::Escape(e.mailkey) + "'"); v.push_back(columns[95] + " = " + std::to_string(e.xtargets)); - v.push_back(columns[96] + " = " + std::to_string(e.firstlogon)); - v.push_back(columns[97] + " = " + std::to_string(e.e_aa_effects)); - v.push_back(columns[98] + " = " + std::to_string(e.e_percent_to_aa)); - v.push_back(columns[99] + " = " + std::to_string(e.e_expended_aa_spent)); - v.push_back(columns[100] + " = " + std::to_string(e.aa_points_spent_old)); - v.push_back(columns[101] + " = " + std::to_string(e.aa_points_old)); - v.push_back(columns[102] + " = " + std::to_string(e.e_last_invsnapshot)); - v.push_back(columns[103] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); - v.push_back(columns[104] + " = " + std::to_string(e.illusion_block)); + v.push_back(columns[96] + " = " + std::to_string(e.ingame)); + v.push_back(columns[97] + " = " + std::to_string(e.first_login)); + v.push_back(columns[98] + " = " + std::to_string(e.e_aa_effects)); + v.push_back(columns[99] + " = " + std::to_string(e.e_percent_to_aa)); + v.push_back(columns[100] + " = " + std::to_string(e.e_expended_aa_spent)); + v.push_back(columns[101] + " = " + std::to_string(e.aa_points_spent_old)); + v.push_back(columns[102] + " = " + std::to_string(e.aa_points_old)); + v.push_back(columns[103] + " = " + std::to_string(e.expansions)); + v.push_back(columns[104] + " = " + std::to_string(e.e_last_invsnapshot)); + v.push_back(columns[105] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); + v.push_back(columns[106] + " = " + std::to_string(e.illusion_block)); auto results = db.QueryDatabase( fmt::format( @@ -890,12 +902,14 @@ public: v.push_back(std::to_string(e.lfg)); v.push_back("'" + Strings::Escape(e.mailkey) + "'"); v.push_back(std::to_string(e.xtargets)); - v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.ingame)); + v.push_back(std::to_string(e.first_login)); v.push_back(std::to_string(e.e_aa_effects)); v.push_back(std::to_string(e.e_percent_to_aa)); v.push_back(std::to_string(e.e_expended_aa_spent)); v.push_back(std::to_string(e.aa_points_spent_old)); v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.expansions)); v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back(std::to_string(e.illusion_block)); @@ -1024,12 +1038,14 @@ public: v.push_back(std::to_string(e.lfg)); v.push_back("'" + Strings::Escape(e.mailkey) + "'"); v.push_back(std::to_string(e.xtargets)); - v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.ingame)); + v.push_back(std::to_string(e.first_login)); v.push_back(std::to_string(e.e_aa_effects)); v.push_back(std::to_string(e.e_percent_to_aa)); v.push_back(std::to_string(e.e_expended_aa_spent)); v.push_back(std::to_string(e.aa_points_spent_old)); v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.expansions)); v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back(std::to_string(e.illusion_block)); @@ -1162,15 +1178,17 @@ public: e.lfg = row[93] ? static_cast(strtoul(row[93], nullptr, 10)) : 0; e.mailkey = row[94] ? row[94] : ""; e.xtargets = row[95] ? static_cast(strtoul(row[95], nullptr, 10)) : 5; - e.firstlogon = row[96] ? static_cast(atoi(row[96])) : 0; - e.e_aa_effects = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; - e.e_percent_to_aa = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; - e.e_expended_aa_spent = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; - e.aa_points_spent_old = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; - e.aa_points_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; - e.e_last_invsnapshot = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; - e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); - e.illusion_block = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.ingame = row[96] ? static_cast(strtoul(row[96], nullptr, 10)) : 0; + e.first_login = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; + e.e_aa_effects = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; + e.e_percent_to_aa = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; + e.e_expended_aa_spent = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; + e.aa_points_spent_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; + e.aa_points_old = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; + e.expansions = row[103] ? static_cast(atoi(row[103])) : -1; + e.e_last_invsnapshot = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.deleted_at = strtoll(row[105] ? row[105] : "-1", nullptr, 10); + e.illusion_block = row[106] ? static_cast(strtoul(row[106], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -1291,15 +1309,17 @@ public: e.lfg = row[93] ? static_cast(strtoul(row[93], nullptr, 10)) : 0; e.mailkey = row[94] ? row[94] : ""; e.xtargets = row[95] ? static_cast(strtoul(row[95], nullptr, 10)) : 5; - e.firstlogon = row[96] ? static_cast(atoi(row[96])) : 0; - e.e_aa_effects = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; - e.e_percent_to_aa = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; - e.e_expended_aa_spent = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; - e.aa_points_spent_old = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; - e.aa_points_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; - e.e_last_invsnapshot = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; - e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); - e.illusion_block = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.ingame = row[96] ? static_cast(strtoul(row[96], nullptr, 10)) : 0; + e.first_login = row[97] ? static_cast(strtoul(row[97], nullptr, 10)) : 0; + e.e_aa_effects = row[98] ? static_cast(strtoul(row[98], nullptr, 10)) : 0; + e.e_percent_to_aa = row[99] ? static_cast(strtoul(row[99], nullptr, 10)) : 0; + e.e_expended_aa_spent = row[100] ? static_cast(strtoul(row[100], nullptr, 10)) : 0; + e.aa_points_spent_old = row[101] ? static_cast(strtoul(row[101], nullptr, 10)) : 0; + e.aa_points_old = row[102] ? static_cast(strtoul(row[102], nullptr, 10)) : 0; + e.expansions = row[103] ? static_cast(atoi(row[103])) : -1; + e.e_last_invsnapshot = row[104] ? static_cast(strtoul(row[104], nullptr, 10)) : 0; + e.deleted_at = strtoll(row[105] ? row[105] : "-1", nullptr, 10); + e.illusion_block = row[106] ? static_cast(strtoul(row[106], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -1470,12 +1490,14 @@ public: v.push_back(std::to_string(e.lfg)); v.push_back("'" + Strings::Escape(e.mailkey) + "'"); v.push_back(std::to_string(e.xtargets)); - v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.ingame)); + v.push_back(std::to_string(e.first_login)); v.push_back(std::to_string(e.e_aa_effects)); v.push_back(std::to_string(e.e_percent_to_aa)); v.push_back(std::to_string(e.e_expended_aa_spent)); v.push_back(std::to_string(e.aa_points_spent_old)); v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.expansions)); v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back(std::to_string(e.illusion_block)); @@ -1597,12 +1619,14 @@ public: v.push_back(std::to_string(e.lfg)); v.push_back("'" + Strings::Escape(e.mailkey) + "'"); v.push_back(std::to_string(e.xtargets)); - v.push_back(std::to_string(e.firstlogon)); + v.push_back(std::to_string(e.ingame)); + v.push_back(std::to_string(e.first_login)); v.push_back(std::to_string(e.e_aa_effects)); v.push_back(std::to_string(e.e_percent_to_aa)); v.push_back(std::to_string(e.e_expended_aa_spent)); v.push_back(std::to_string(e.aa_points_spent_old)); v.push_back(std::to_string(e.aa_points_old)); + v.push_back(std::to_string(e.expansions)); v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back(std::to_string(e.illusion_block)); diff --git a/zone/client.h b/zone/client.h index c56815d90..9ac7f997c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -2080,7 +2080,8 @@ private: uint16 trader_id; uint16 customer_id; uint32 account_creation; - uint8 firstlogon; + bool first_login; + bool ingame; uint32 mercid; // current merc uint8 mercSlot; // selected merc slot time_t m_trader_transaction_date; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7eff0210b..cd28da8d3 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -807,29 +807,41 @@ void Client::CompleteConnect() m_last_position_before_bulk_update = GetPosition(); /* This sub event is for if a player logs in for the first time since entering world. */ - if (firstlogon == 1) { - TraderRepository::DeleteWhere(database, fmt::format("`char_id` = '{}'", CharacterID())); - BuyerRepository::DeleteBuyer(database, CharacterID()); - LogTradingDetail( - "Removed trader abd buyer entries for Character ID {} on first logon to ensure table consistency.", + if (ingame) { + auto e = CharacterDataRepository::FindOne( + database, CharacterID() ); + bool is_first_login = e.first_login == 0; + RecordPlayerEventLog(PlayerEvent::WENT_ONLINE, PlayerEvent::EmptyEvent{}); if (parse->PlayerHasQuestSub(EVENT_CONNECT)) { - parse->EventPlayer(EVENT_CONNECT, this, "", 0); + const std::string& export_string = fmt::format( + "{} {}", + GetPP().lastlogin, + is_first_login ? 1 : 0 + ); + parse->EventPlayer(EVENT_CONNECT, this, export_string, 0); } - /** - * Update last login since this doesn't get updated until a late save later so we can update online status - */ - database.QueryDatabase( - StringFormat( - "UPDATE `character_data` SET `last_login` = UNIX_TIMESTAMP() WHERE id = %u", + if (is_first_login) { + e.first_login = time(nullptr); + TraderRepository::DeleteWhere(database, fmt::format("`char_id` = '{}'", CharacterID())); + BuyerRepository::DeleteBuyer(database, CharacterID()); + LogTradingDetail( + "Removed trader abd buyer entries for Character ID {} on first logon to ensure table consistency.", CharacterID() - ) - ); + ); + } + + e.last_login = time(nullptr); + + const int updated = CharacterDataRepository::UpdateOne(database, e); + if (!updated) { + LogError("Failed to update login time for character_id [{}]", CharacterID()); + } if (IsPetNameChangeAllowed() && !RuleB(Pets, AlwaysAllowPetRename)) { InvokeChangePetName(false); @@ -878,7 +890,7 @@ void Client::CompleteConnect() entity_list.SendFindableNPCList(this); if (IsInAGuild()) { - if (firstlogon == 1) { + if (ingame) { guild_mgr.UpdateDbMemberOnline(CharacterID(), true); SendGuildMembersList(); } @@ -1314,14 +1326,14 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Load Character Data */ query = fmt::format( - "SELECT `lfp`, `lfg`, `xtargets`, `firstlogon`, `guild_id`, `rank`, `exp_enabled`, `tribute_enable`, `extra_haste`, `illusion_block` FROM `character_data` LEFT JOIN `guild_members` ON `id` = `char_id` WHERE `id` = {}", + "SELECT `lfp`, `lfg`, `xtargets`, `first_login`, `guild_id`, `rank`, `exp_enabled`, `tribute_enable`, `extra_haste`, `illusion_block`, `ingame` FROM `character_data` LEFT JOIN `guild_members` ON `id` = `char_id` WHERE `id` = {}", cid ); auto results = database.QueryDatabase(query); for (auto row : results) { if (row[4] && Strings::ToInt(row[4]) > 0) { - guild_id = Strings::ToInt(row[4]); - guildrank = row[5] ? Strings::ToInt(row[5]) : GUILD_RANK_NONE; + guild_id = Strings::ToInt(row[4]); + guildrank = row[5] ? Strings::ToInt(row[5]) : GUILD_RANK_NONE; guild_tribute_opt_in = row[7] ? Strings::ToBool(row[7]) : 0; } @@ -1329,10 +1341,21 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) SetExtraHaste(Strings::ToInt(row[8]), false); SetIllusionBlock(Strings::ToBool(row[9])); - if (LFP) { LFP = Strings::ToInt(row[0]); } - if (LFG) { LFG = Strings::ToInt(row[1]); } - if (row[3]) - firstlogon = Strings::ToInt(row[3]); + if (LFP) { + LFP = Strings::ToInt(row[0]); + } + + if (LFG) { + LFG = Strings::ToInt(row[1]); + } + + if (row[3]) { + first_login = Strings::ToUnsignedInt(row[3]); + } + + if (row[10]) { + ingame = Strings::ToBool(row[10]); + } } if (RuleB(Character, SharedBankPlat)) @@ -1720,7 +1743,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) // Taunt persists when zoning on newer clients, overwrite default. if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { - if (!firstlogon) { + if (!ingame) { pet->SetTaunting(m_petinfo.taunting); } } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index c9de4c160..ec63581d6 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -727,7 +727,7 @@ void Client::OnDisconnect(bool hard_disconnect) { o->trade->Reset(); } - database.SetFirstLogon(CharacterID(), 0); //We change firstlogon status regardless of if a player logs out to zone or not, because we only want to trigger it on their first login from world. + database.SetIngame(CharacterID(), 0); //We change ingame status regardless of if a player logs out to zone or not, because we only want to trigger it on their first login from world. /* Remove from all proximities */ ClearAllProximities(); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index e42022146..9d3e2f156 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -2543,6 +2543,13 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_CONNECT: { + Seperator sep(data); + ExportVar(package_name.c_str(), "last_login", sep.arg[0]); + ExportVar(package_name.c_str(), "is_first_login", sep.arg[1]); + break; + } + default: { break; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 050657bbc..fa684a490 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -353,6 +353,7 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_AA_LOSS] = handle_player_aa_loss; PlayerArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_player_spell_blocked; PlayerArgumentDispatch[EVENT_READ_ITEM] = handle_player_read_item; + PlayerArgumentDispatch[EVENT_CONNECT] = handle_player_connect; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index d6419189a..7cdd8cbe3 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -1809,6 +1809,23 @@ void handle_player_read_item( } } +void handle_player_connect( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) +{ + Seperator sep(data.c_str()); + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0])); + lua_setfield(L, -2, "last_login"); + + lua_pushboolean(L, Strings::ToBool(sep.arg[1])); + lua_setfield(L, -2, "is_first_login"); +} + // Item void handle_item_click( QuestInterface *parse, diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 4a9a1bbb9..3cb428c58 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -865,6 +865,15 @@ void handle_player_read_item( std::vector *extra_pointers ); +void handle_player_connect( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + // Item void handle_item_click( QuestInterface *parse,