--- 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, 31 /* restore | shields | cloak | resurrection | native work effects */); }); + MAIN_THREAD_EM_ASM({ if (Module['webbarProtocol']) Module['webbarProtocol'](8, 63 /* restore | shields | cloak | resurrection | native work effects | area resurrection */); }); MAIN_THREAD_EM_ASM({ if (Module['webbarIdentity']) Module['webbarIdentity']($0, $1, $2, $3); }, gu->myPlayerNum, gu->myTeam, gu->myAllyTeam, int(gu->spectating)); @@ -274,9 +274,14 @@ command.PushPos(float3(order.x, CGround::GetHeightReal(order.x, order.z), order.z)); command.PushParam(order.radius); } - } else if (order.kind == 1006 || order.kind == 1007) { - const int kind = order.kind == 1006 ? CMD_REPAIR : CMD_RECLAIM; + } else if (order.kind == 1006 || order.kind == 1007 || order.kind == 1008) { + const int kind = order.kind == 1006 ? CMD_REPAIR : order.kind == 1007 ? CMD_RECLAIM : CMD_RESURRECT; requireCapability(kind); + // Native area resurrection chooses eligible LOS-visible wrecks itself. + if (kind == CMD_RESURRECT) { + std::erase_if(ids, [&](int id) { const auto* def = unitHandler.GetUnit(id)->unitDef; return !def->IsBuilderUnit() || !def->canResurrect; }); + if (ids.empty()) status = 8; + } if (!validPosition() || !std::isfinite(order.radius) || order.radius <= 0.0f || order.radius > 2000.0f) status = 3; else { command = Command(kind, uint8_t(order.options & SHIFT_KEY)); --- a/rts/Game/WebbarWorld.h +++ b/rts/Game/WebbarWorld.h @@ -51,9 +51,16 @@ uint32_t index = 0; for (const Command& command: unit->commandAI->commandQue) { if (index >= 24 || queues.size() >= 1024) break; + const bool internal = command.IsInternalOrder(); + // Native area work prepends a target to its temporary child command. + // That target ID is not an X coordinate; preserve the parent area instead. + const bool areaChild = internal && command.GetNumParams() == 5 && (command.GetID() == CMD_RESURRECT || command.GetID() == CMD_REPAIR); const bool position = command.GetNumParams() >= 3; - queues.push_back({uint32_t(unit->id), command.GetTag(), command.GetID(), command.GetNumParams() == 1 ? uint32_t(command.GetParam(0)) : 0xffffffff, - position ? command.GetParam(0) : 0.0f, position ? command.GetParam(1) : 0.0f, position ? command.GetParam(2) : 0.0f, index++}); + const unsigned int offset = areaChild ? 1 : 0; + const bool areaResurrect = command.GetID() == CMD_RESURRECT && command.GetNumParams() == 4; + const uint32_t flags = (internal ? 0x80000000u : 0u) | (areaResurrect ? 0x40000000u : 0u); + queues.push_back({uint32_t(unit->id), command.GetTag(), command.GetID(), (command.GetNumParams() == 1 || areaChild) ? uint32_t(command.GetParam(0)) : 0xffffffff, + position ? command.GetParam(offset) : 0.0f, position ? command.GetParam(offset + 1) : 0.0f, position ? command.GetParam(offset + 2) : 0.0f, (index++) | flags}); } if (unit->unitDef->IsFactoryUnit()) { const auto& rally = static_cast(unit->commandAI)->newUnitCommands;