fix(game): delete beaten monsters so ambushes start fights
This commit is contained in:
1 parent
38880e4976
commit
201f1bb07f
3 files changed
+38
-2
No files matched your search
@@ -184,6 +184,22 @@ void onSceneCastSkillCostMp(net::Session& session, const proto::SceneCastSkillCo
|
|||||||
|
|
||||||
int64_t now() { return static_cast<int64_t>(util::nowSec()); }
|
int64_t now() { return static_cast<int64_t>(util::nowSec()); }
|
||||||
|
|
||||||
|
// The monsters a won fight removes. A Stagnant Shadow stays, to be farmed again.
|
||||||
|
std::vector<uint32_t> defeated(const Player& player, const std::vector<uint32_t>& entityIds) {
|
||||||
|
const data::Tables& tables = data::Tables::get();
|
||||||
|
std::vector<uint32_t> out;
|
||||||
|
for (uint32_t entityId : entityIds) {
|
||||||
|
const SceneEntity* entity = player.sceneState().find(entityId);
|
||||||
|
if (entity == nullptr || entity->kind != EntityKind::Monster) continue;
|
||||||
|
uint32_t stage = entity->stageId != 0
|
||||||
|
? entity->stageId
|
||||||
|
: tables.stageForEvent(entity->eventId, player.worldLevel());
|
||||||
|
if (stage != 0 && tables.farmElement(stage) != nullptr) continue;
|
||||||
|
out.push_back(entityId);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// Calyx: the one fight a srtools build is allowed to take over, monsters, blessings and
|
// Calyx: the one fight a srtools build is allowed to take over, monsters, blessings and
|
||||||
// all. `wave` is how many runs were bought, one stage each.
|
// all. `wave` is how many runs were bought, one stage each.
|
||||||
BattleRequest cocoonRequest(uint32_t cocoonId, uint32_t wave, uint32_t worldLevel) {
|
BattleRequest cocoonRequest(uint32_t cocoonId, uint32_t wave, uint32_t worldLevel) {
|
||||||
@@ -453,7 +469,7 @@ void onPveBattleResult(net::Session& session, const proto::PVEBattleResultCsReq&
|
|||||||
BattleContext& context = player->battle();
|
BattleContext& context = player->battle();
|
||||||
bool won = req.end_status == proto::BattleEndStatus::BATTLE_END_WIN && context.active &&
|
bool won = req.end_status == proto::BattleEndStatus::BATTLE_END_WIN && context.active &&
|
||||||
context.battleId == req.battle_id;
|
context.battleId == req.battle_id;
|
||||||
if (won) notify::monstersRemoved(session, *player, context.monsterEntityIds);
|
if (won) notify::monstersRemoved(session, *player, defeated(*player, context.monsterEntityIds));
|
||||||
// A farming run costs and pays only when it is won; losing or fleeing is free.
|
// A farming run costs and pays only when it is won; losing or fleeing is free.
|
||||||
std::vector<data::ItemStack> drops;
|
std::vector<data::ItemStack> drops;
|
||||||
if (won && (context.staminaCost != 0 || context.mappingInfoId != 0)) {
|
if (won && (context.staminaCost != 0 || context.mappingInfoId != 0)) {
|
||||||
|
|||||||
+3
-1
@@ -85,7 +85,9 @@ void monstersRemoved(net::Session& session, Player& player,
|
|||||||
for (uint32_t groupId : groups) {
|
for (uint32_t groupId : groups) {
|
||||||
auto& group = refresh.group_refresh_list.emplace_back();
|
auto& group = refresh.group_refresh_list.emplace_back();
|
||||||
group.group_id = groupId;
|
group.group_id = groupId;
|
||||||
group.refresh_type = proto::SceneGroupRefreshType::SCENE_GROUP_REFRESH_TYPE_LOADED;
|
// Deletes go out as type 3. LOADED sends the client down a legacy path that
|
||||||
|
// throws, leaving the monster alive on its side but gone from ours.
|
||||||
|
group.refresh_type = proto::SceneGroupRefreshType::SCENE_GROUP_REFRESH_TYPE_AFIBFMAFNCC;
|
||||||
for (uint32_t entityId : entityIds) {
|
for (uint32_t entityId : entityIds) {
|
||||||
const SceneEntity* entity = player.sceneState().find(entityId);
|
const SceneEntity* entity = player.sceneState().find(entityId);
|
||||||
if (entity == nullptr || entity->groupId != groupId) continue;
|
if (entity == nullptr || entity->groupId != groupId) continue;
|
||||||
|
|||||||
@@ -402,6 +402,24 @@ void runFlowTests() {
|
|||||||
check(resultRsp.battle_id == result.battle_id, "battle id echoed");
|
check(resultRsp.battle_id == result.battle_id, "battle id echoed");
|
||||||
check(resultRsp.end_status == proto::BattleEndStatus::BATTLE_END_WIN,
|
check(resultRsp.end_status == proto::BattleEndStatus::BATTLE_END_WIN,
|
||||||
"end status echoed");
|
"end status echoed");
|
||||||
|
|
||||||
|
// LOADED here throws in the client and leaves the monster standing.
|
||||||
|
// Earlier refreshes (the lineup edit's) are still queued, so skip to
|
||||||
|
// the one that deletes.
|
||||||
|
bool deleted = false;
|
||||||
|
net::Packet refreshPacket;
|
||||||
|
while (!deleted && client.await(cmd::SceneGroupRefreshScNotify, refreshPacket, 500)) {
|
||||||
|
proto::SceneGroupRefreshScNotify refresh;
|
||||||
|
if (!parseBody(refreshPacket, refresh)) break;
|
||||||
|
for (const proto::GroupRefreshInfo& group : refresh.group_refresh_list) {
|
||||||
|
for (const proto::SceneEntityRefreshInfo& change : group.refresh_entity) {
|
||||||
|
if (change.delete_entity != monsters[0]) continue;
|
||||||
|
deleted = group.refresh_type ==
|
||||||
|
proto::SceneGroupRefreshType::SCENE_GROUP_REFRESH_TYPE_AFIBFMAFNCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(deleted, "the beaten monster is deleted the way the client accepts");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user