feat(version): support 4.6.51
This commit is contained in:
1 parent
530def48df
commit
dfe7292a14
182 files changed
+811980
-87492
No files matched your search
+23
-2
@@ -783,8 +783,8 @@ void runFlowTests() {
|
||||
check(client.await(cmd::GetChallengePeakDataScRsp, packet), "arbitration data answered");
|
||||
proto::GetChallengePeakDataScRsp peakData;
|
||||
check(parseBody(packet, peakData), "arbitration data parses");
|
||||
check(peakData.challenge_peak_groups.size() >= 10, "with every season in it");
|
||||
check(peakData.current_peak_group_id == 10, "and the newest on show");
|
||||
check(peakData.challenge_peak_groups.size() >= 11, "with every season in it");
|
||||
check(peakData.current_peak_group_id == 11, "and the newest on show");
|
||||
|
||||
proto::SetChallengePeakMobLineupAvatarCsReq teams;
|
||||
teams.peak_group_id = 9;
|
||||
@@ -1277,6 +1277,27 @@ void runFlowTests() {
|
||||
check(nowhere.size() == 1 && nowhere[0].find("no command") != std::string::npos,
|
||||
"and an unknown command says so instead of going quiet");
|
||||
|
||||
// The chat box is hidden with everything else, so the UI has to come back by itself.
|
||||
// Watermark pushes share the notify and are skipped.
|
||||
auto awaitLua = [&](const std::string& marker, int timeoutMs) {
|
||||
uint64_t deadline = util::nowMs() + static_cast<uint64_t>(timeoutMs);
|
||||
net::Packet pushedPacket;
|
||||
while (util::nowMs() < deadline) {
|
||||
proto::ClientDownloadDataScNotify pushed;
|
||||
if (!client.await(cmd::ClientDownloadDataScNotify, pushedPacket, timeoutMs)) return false;
|
||||
if (parseBody(pushedPacket, pushed) && pushed.download_data &&
|
||||
pushed.download_data->data.find(marker) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
std::vector<std::string> hidden = typed("/hideui 1");
|
||||
check(hidden.size() == 1 && hidden[0].find("hidden for 1s") != std::string::npos,
|
||||
"/hideui says for how long");
|
||||
check(awaitLua("canvas.enabled = false", 2000), "the hide goes out at once");
|
||||
check(awaitLua("canvas.enabled = true", 3000), "and the UI comes back after the delay");
|
||||
|
||||
std::vector<std::string> chatter = typed("hello");
|
||||
check(chatter.size() == 1 && chatter[0].find("/help") != std::string::npos,
|
||||
"plain chat is nudged towards /help");
|
||||
|
||||
+47
-6
@@ -713,7 +713,7 @@ void testChallengeHistory() {
|
||||
|
||||
// Anomaly Arbitration. Production rows have no arena, so the beta dump fills it in,
|
||||
// and places season ten, which production does not have at all.
|
||||
check(tables.peakGroups().size() >= 10, "every arbitration season loaded");
|
||||
check(tables.peakGroups().size() >= 11, "every arbitration season loaded");
|
||||
const data::PeakInfo* knight = tables.peak(101);
|
||||
check(knight != nullptr && knight->mapEntranceId == 3013501 && knight->eventId == 30501011,
|
||||
"a production knight gets its arena from the beta dump");
|
||||
@@ -778,8 +778,9 @@ void testRosterProtos() {
|
||||
|
||||
const std::vector<uint32_t>& ids = game::Roster::baseAvatarIds();
|
||||
check(!ids.empty(), "the roster has base ids");
|
||||
// Derived from AvatarConfig; the 4.5 + 4.6-beta merge comes to exactly 88 base ids.
|
||||
check(ids.size() == 88, "the derived roster has all 88 base ids");
|
||||
// Derived from AvatarConfig; 4.5 + 4.6-beta + the 4.6.51 overlay come to 89 base ids.
|
||||
check(ids.size() == 89, "the derived roster has all 89 base ids");
|
||||
check(std::find(ids.begin(), ids.end(), 1511u) != ids.end(), "Aha from the 4.6.51 overlay");
|
||||
check(std::find(ids.begin(), ids.end(), 6022u) == ids.end(), "story-only units are excluded");
|
||||
check(std::find(ids.begin(), ids.end(), 1503u) != ids.end(), "beta-only avatars are included");
|
||||
check(ids.size() >= 2 && ids[0] == 8001 && ids[1] == 1001, "Trailblazer and March lead");
|
||||
@@ -802,9 +803,15 @@ void testRosterProtos() {
|
||||
check(battle.hp == 10000, "hp is a percentage in hundredths");
|
||||
check(battle.sp_bar && battle.sp_bar->max_sp >= 10000, "sp is scaled to hundredths");
|
||||
check(!battle.skilltree_list.empty(), "traces are filled in");
|
||||
check(!buffs.empty(), "a technique buff was produced");
|
||||
check(buffs[0].wave_flag == 0xFFFFFFFFu, "technique buffs apply to every wave");
|
||||
check(buffs[0].owner_index == 0, "owned by the avatar that brought it");
|
||||
// A build may switch every technique off; then there is nothing to check.
|
||||
auto build = game::SrTools::instance().data();
|
||||
auto it = build->avatars.find(8008);
|
||||
bool techniquesOff = it != build->avatars.end() && it->second.techniques.empty();
|
||||
check(techniquesOff || !buffs.empty(), "a technique buff was produced");
|
||||
if (!buffs.empty()) {
|
||||
check(buffs[0].wave_flag == 0xFFFFFFFFu, "technique buffs apply to every wave");
|
||||
check(buffs[0].owner_index == 0, "owned by the avatar that brought it");
|
||||
}
|
||||
}
|
||||
|
||||
void testSceneBuild() {
|
||||
@@ -993,6 +1000,39 @@ void testEveryScenePacketFits() {
|
||||
"the bag fits in one kcp message");
|
||||
}
|
||||
|
||||
// 4.6.51 seasons come from the beta dump alone: floors with no group rows, all three
|
||||
// modes in one table, Pure Fiction floors with no extras.
|
||||
void testNewSeasons() {
|
||||
const data::Tables& tables = data::Tables::get();
|
||||
if (!tables.loaded()) return;
|
||||
const data::ChallengeInfo* story = tables.challenge(20281);
|
||||
const data::ChallengeInfo* boss = tables.challenge(30231);
|
||||
const data::ChallengeInfo* memory = tables.challenge(5601);
|
||||
check(story && story->kind == data::ChallengeKind::Story, "a 2xxx season is Pure Fiction");
|
||||
check(boss && boss->kind == data::ChallengeKind::Boss, "a 3xxx season is Apocalyptic Shadow");
|
||||
check(memory && memory->kind == data::ChallengeKind::Memory, "a 1xxx season is Memory");
|
||||
const data::ChallengeGroupInfo* season = tables.challengeGroup(2028);
|
||||
const data::ChallengeGroupInfo* previous = tables.challengeGroup(2026);
|
||||
check(season && season->kind == data::ChallengeKind::Story, "the new season is listed");
|
||||
check(season && previous && season->rewardLineGroupId == previous->rewardLineGroupId,
|
||||
"with its mode's reward line");
|
||||
check(tables.challengeGroup(1037) && tables.challengeGroup(3023), "and the other two modes'");
|
||||
check(story && story->roundLimit == 5 && story->battleTargetIds == std::vector<uint32_t>{2001, 2002},
|
||||
"Pure Fiction extras come from the same floor of an earlier season");
|
||||
|
||||
check(tables.stageInvasion(30127112) == 2, "a stage's invasion is loaded");
|
||||
check(tables.stageInvasion(1) == 0, "and most stages have none");
|
||||
game::Player player = makeTestPlayer();
|
||||
game::BattleRequest request;
|
||||
request.stageIds = {30127112};
|
||||
proto::SceneBattleInfo info = game::battle::create(player, request);
|
||||
int invasion = 0;
|
||||
for (const proto::BattleBuff& buff : info.buff_list) {
|
||||
if (buff.id == 3034002 || buff.id == 3034012) ++invasion;
|
||||
}
|
||||
check(invasion == 2, "the fight carries the invasion's attack and support buffs");
|
||||
}
|
||||
|
||||
void testBattleBuild() {
|
||||
if (!data::SceneRes::get().loaded() || !data::Tables::get().loaded()) return;
|
||||
|
||||
@@ -1324,6 +1364,7 @@ void runGameTests() {
|
||||
testChallengeRun();
|
||||
testTierceRun();
|
||||
testEveryScenePacketFits();
|
||||
testNewSeasons();
|
||||
testBattleBuild();
|
||||
testBattleSourceSplit();
|
||||
testPropInteraction();
|
||||
|
||||
+8
-9
@@ -167,17 +167,16 @@ void testCmdIds() {
|
||||
}
|
||||
|
||||
void testLineupCmdIds() {
|
||||
// 716 is JoinLineupScRsp and 719 ReplaceLineupScRsp; the dump's own table had them
|
||||
// mislabelled. Answering a join on 719 leaves the party UI waiting forever, so the
|
||||
// names are corrected in proto/cmdids.txt.
|
||||
check(cmd::JoinLineupScRsp == 716, "JoinLineupScRsp is 716");
|
||||
check(cmd::ReplaceLineupScRsp == 719, "ReplaceLineupScRsp is 719");
|
||||
check(cmd::name(716) == "JoinLineupScRsp", "716 names itself");
|
||||
check(cmd::name(719) == "ReplaceLineupScRsp", "719 names itself");
|
||||
// The two replies are easy to swap: answering a join on the replace id leaves the
|
||||
// party UI waiting forever. 4.6.51 has them at 771 and 715.
|
||||
check(cmd::JoinLineupScRsp == 771, "JoinLineupScRsp is 771");
|
||||
check(cmd::ReplaceLineupScRsp == 715, "ReplaceLineupScRsp is 715");
|
||||
check(cmd::name(771) == "JoinLineupScRsp", "771 names itself");
|
||||
check(cmd::name(715) == "ReplaceLineupScRsp", "715 names itself");
|
||||
// The generic fallback derives the response name from the request name, so
|
||||
// ReplaceLineupCsReq now resolves even without a handler.
|
||||
check(cmd::id("ReplaceLineupScRsp") == 719, "the reverse lookup agrees");
|
||||
check(cmd::id("JoinLineupScRsp") == 716, "and for the join");
|
||||
check(cmd::id("ReplaceLineupScRsp") == 715, "the reverse lookup agrees");
|
||||
check(cmd::id("JoinLineupScRsp") == 771, "and for the join");
|
||||
}
|
||||
|
||||
void testIdleTimeout() {
|
||||
|
||||
Reference in new issue
Block a user