fix(login): select the last played character in a stable list

The character list selected index 0 and was ordered by last login, so
the characters swapped places on the selection screen after each
session. Live kept them in the order they were made and selected the
one with the latest last login (a new character counts as logged in
when it is made): 2014 captures show e.g. a new fourth character
appended and selected (index 3), and after the next login the list in
the same order with index 0 for the character played last.

Characters are now sorted by ID (creation order) and the one with the
latest last login is selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 08:42:01 -05:00
parent d43cdef104
commit 4399daad4c
2 changed files with 10 additions and 2 deletions

View File

@@ -248,8 +248,16 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
chars.push_back(character); chars.push_back(character);
} }
// Live kept the characters in the order they were made and selected the one with the latest last login (a new
// character counts as logged in when it is made), as 2014 captures of the character list show. Character IDs
// only grow, so sorting by ID gives the order they were made in.
std::ranges::sort(chars, {}, &Character::GetID);
ClientPackets::CharacterListResponse response; ClientPackets::CharacterListResponse response;
response.selectedCharacterIndex = 0; //TODO: Pick the most recent played index. character index in front, just picking 0 response.selectedCharacterIndex = 0;
for (size_t i = 1; i < chars.size(); i++) {
if (chars[i]->GetLastLogin() > chars[response.selectedCharacterIndex]->GetLastLogin()) response.selectedCharacterIndex = static_cast<uint8_t>(i);
}
for (const auto* const character : u->GetCharacters()) { for (const auto* const character : u->GetCharacters()) {
auto& entry = response.characters.emplace_back(); auto& entry = response.characters.emplace_back();

View File

@@ -113,7 +113,7 @@ namespace ClientPackets {
}; };
// Written as a u8 count first // Written as a u8 count first
uint8_t selectedCharacterIndex{}; // TODO: Pick the most recent played index. DLU always sends 0 uint8_t selectedCharacterIndex{}; // The character with the latest last login
std::vector<Character> characters{}; std::vector<Character> characters{};
CharacterListResponse() : LUBitStream(ServiceType::CLIENT, MessageType::Client::CHARACTER_LIST_RESPONSE) {} CharacterListResponse() : LUBitStream(ServiceType::CLIENT, MessageType::Client::CHARACTER_LIST_RESPONSE) {}