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()); }
|
||||
|
||||
// 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
|
||||
// all. `wave` is how many runs were bought, one stage each.
|
||||
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();
|
||||
bool won = req.end_status == proto::BattleEndStatus::BATTLE_END_WIN && context.active &&
|
||||
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.
|
||||
std::vector<data::ItemStack> drops;
|
||||
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) {
|
||||
auto& group = refresh.group_refresh_list.emplace_back();
|
||||
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) {
|
||||
const SceneEntity* entity = player.sceneState().find(entityId);
|
||||
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.end_status == proto::BattleEndStatus::BATTLE_END_WIN,
|
||||
"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