--- a/rts/Game/WebbarBrowser.h +++ b/rts/Game/WebbarBrowser.h @@ -81,7 +81,7 @@ if (!catalogSent) { catalogSent = true; if (std::getenv("WEBBAR_NETWORK") != nullptr) { static WebbarNetworkResult result; } - MAIN_THREAD_EM_ASM({ if (Module['webbarProtocol']) Module['webbarProtocol'](8, 127 /* restore | shields | cloak | resurrection | native work effects | area resurrection | manual launch */); }); + MAIN_THREAD_EM_ASM({ if (Module['webbarProtocol']) Module['webbarProtocol'](8, 255 /* restore | shields | cloak | resurrection | native work effects | area resurrection | manual launch | capture */); }); MAIN_THREAD_EM_ASM({ if (Module['webbarIdentity']) Module['webbarIdentity']($0, $1, $2, $3); }, gu->myPlayerNum, gu->myTeam, gu->myAllyTeam, int(gu->spectating)); @@ -314,6 +314,17 @@ if (ids.empty()) status = 8; else if (target == nullptr || target->team != gu->myTeam || target->isDead) status = 4; else command.PushParam(float(order.target)); + } else if (order.kind == CMD_CAPTURE) { + requireCapability(CMD_CAPTURE); + std::erase_if(ids, [&](int id) { const auto* def = unitHandler.GetUnit(id)->unitDef; return !def->IsBuilderUnit() || !def->canCapture; }); + const CUnit* target = unitHandler.GetUnit(order.target); + if (ids.empty()) status = 8; + else if (target == nullptr || target->isDead || target->team == gu->myTeam || !WebbarVisible(target)) status = 4; + else { + // Native BuilderCAI owns capturability, range, resource spending, + // progress and target loss, including changes before queued execution. + command.PushParam(float(order.target)); + } } else if (order.kind == CMD_RESURRECT) { requireCapability(CMD_RESURRECT); std::erase_if(ids, [&](int id) { const auto* def = unitHandler.GetUnit(id)->unitDef; return !def->IsBuilderUnit() || !def->canResurrect; }); --- a/rts/Game/WebbarCloak.h +++ b/rts/Game/WebbarCloak.h @@ -17,7 +17,7 @@ for (const CUnit* unit: unitHandler.GetActiveUnits()) { if (unit->isDead || unit->team != gu->myTeam) continue; const auto* def = unit->unitDef; - if (!def->canCloak && !unit->isCloaked && !unit->stealth && !unit->sonarStealth && !def->canResurrect) continue; + if (!def->canCloak && !unit->isCloaked && !unit->stealth && !unit->sonarStealth && !def->canResurrect && unit->stockpileWeapon == nullptr) continue; if (records.size() >= 4096) { ++dropped; continue; } const auto rule = [&](const char* name) { const auto it = unit->modParams.find(name);