Skip to content
Permalink
Browse files

fix #6096 #6093

call AllowWeaponTarget when auto-generating CAI attack commands
when targetID=-1 and weaponNum=-1 targetPriority determines the
target search radius; targetPriority=nil accompanies any actual
target being considered
  • Loading branch information...
rt
rt committed Dec 9, 2018
1 parent d24a712 commit 198e315d4d7c736794223d3c8aece278909ac967
Showing with 139 additions and 115 deletions.
  1. +26 −15 rts/Lua/LuaHandleSynced.cpp
  2. +67 −69 rts/Sim/Units/CommandAI/AirCAI.cpp
  3. +46 −31 rts/Sim/Units/CommandAI/MobileCAI.cpp
@@ -1235,6 +1235,7 @@ int CSyncedLuaHandle::AllowWeaponTargetCheck(unsigned int attackerID, unsigned i
return ret;

ret = lua_toint(L, -1);

lua_pop(L, 1);
return ret;
}
@@ -1245,10 +1246,8 @@ bool CSyncedLuaHandle::AllowWeaponTarget(
unsigned int targetID,
unsigned int attackerWeaponNum,
unsigned int attackerWeaponDefID,
float* targetPriority)
{
assert(targetPriority != nullptr);

float* targetPriority
) {
bool ret = true;

if (!watchWeaponDefs[attackerWeaponDefID])
@@ -1266,18 +1265,24 @@ bool CSyncedLuaHandle::AllowWeaponTarget(
lua_pushnumber(L, targetID);
lua_pushnumber(L, attackerWeaponNum + LUA_WEAPON_BASE_INDEX);
lua_pushnumber(L, attackerWeaponDefID);
lua_pushnumber(L, *targetPriority);

if (targetPriority != nullptr) {
// Weapon::AutoTarget
lua_pushnumber(L, *targetPriority);
} else {
// {Air,Mobile}CAI::AutoGenerateTarget
lua_pushnil(L);
}

if (!RunCallInTraceback(L, cmdStr, 5, 2, traceBack.GetErrFuncIdx(), false))
return ret;

ret = luaL_optboolean(L, -2, false);
if (targetPriority != nullptr)
*targetPriority = luaL_optnumber(L, -1, *targetPriority);

if (lua_isnumber(L, -1))
*targetPriority = lua_tonumber(L, -1);
ret = luaL_optboolean(L, -2, false);

lua_pop(L, 2);

return ret;
}

@@ -1308,6 +1313,7 @@ bool CSyncedLuaHandle::AllowWeaponInterceptTarget(
return ret;

ret = luaL_optboolean(L, -1, false);

lua_pop(L, 1);
return ret;
}
@@ -1319,6 +1325,11 @@ bool CSyncedLuaHandle::AllowWeaponInterceptTarget(

int CSyncedLuaHandle::SyncedRandom(lua_State* L)
{
#if 0
spring_lua_synced_rand(L);
return 1;
#endif

switch (lua_gettop(L)) {
case 0: {
lua_pushnumber(L, gsRNG.NextFloat());
@@ -1327,12 +1338,13 @@ int CSyncedLuaHandle::SyncedRandom(lua_State* L)

case 1: {
if (lua_isnumber(L, 1)) {
const int maxn = lua_toint(L, 1);
const int l = 1;
const int u = lua_toint(L, 1);

if (maxn < 1)
luaL_error(L, "error: too small upper limit (%d) given to math.random(), should be >= 1 {synced}", maxn);
if (u < 1)
luaL_error(L, "error: too small upper limit (%d) given to math.random(), should be >= 1 {synced}", u);

lua_pushnumber(L, 1 + gsRNG.NextInt(maxn));
lua_pushnumber(L, 1 + gsRNG.NextInt(u));
return 1;
}
} break;
@@ -1347,9 +1359,8 @@ int CSyncedLuaHandle::SyncedRandom(lua_State* L)

const float diff = (upper - lower);
const float r = gsRNG.NextFloat(); // [0,1], not [0,1) ?
const int value = lower + (int)(r * (diff + 1));

lua_pushnumber(L, Clamp(value, lower, upper));
lua_pushnumber(L, Clamp(lower + int(r * (diff + 1)), lower, upper));
return 1;
}
} break;
@@ -15,6 +15,7 @@
#include "Sim/Units/UnitHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "System/EventHandler.h"
#include "System/myMath.h"
#include "System/Log/ILog.h"
#include "System/StringUtil.h"
@@ -176,77 +177,76 @@ void CAirCAI::SlowUpdate()

#if (AUTO_GENERATE_ATTACK_ORDERS == 1)
if (commandQue.empty()) {
if (!AirAutoGenerateTarget(GetStrafeAirMoveType(owner))) {
// if no target found, queue is still empty so bail now
// queue remains empty if no target, can bail early
if (!AirAutoGenerateTarget(GetStrafeAirMoveType(owner)))
return;
}
}
#endif

// FIXME: check owner->UsingScriptMoveType() and skip rest if true?
AAirMoveType* myPlane = GetStrafeAirMoveType(owner);
Command& c = commandQue.front();

if (c.GetID() == CMD_WAIT) {
if ((myPlane->aircraftState == AAirMoveType::AIRCRAFT_FLYING)
&& !owner->unitDef->DontLand() && myPlane->autoLand)
{
StopMove();
}
return;
}

switch (c.GetID()) {
case CMD_WAIT: {
if ((myPlane->aircraftState == AAirMoveType::AIRCRAFT_FLYING) && myPlane->autoLand && !owner->unitDef->DontLand())
StopMove();

return;
} break;
case CMD_AREA_ATTACK: {
ExecuteAreaAttack(c);
return;
}
} break;
default: {
CMobileCAI::Execute();
return;
}
} break;
}
}

bool CAirCAI::AirAutoGenerateTarget(AAirMoveType* myPlane) {
assert(commandQue.empty());
assert(myPlane->owner == owner);

if (owner->weapons.empty())
return false;

const UnitDef* ownerDef = owner->unitDef;

const bool autoLand = !ownerDef->DontLand() && myPlane->autoLand;
const bool autoAttack = ((owner->fireState >= FIRESTATE_FIREATWILL) && (owner->moveState != MOVESTATE_HOLDPOS));
const bool isFlying = (myPlane->aircraftState == AAirMoveType::AIRCRAFT_FLYING);

if (myPlane->aircraftState == AAirMoveType::AIRCRAFT_FLYING && autoLand) {
StopMove();
}
// float searchRadius = 500.0f * owner->moveState;
float searchRadius = 1000.0f * owner->moveState;

if (ownerDef->canAttack && autoAttack && owner->maxRange > 0) {
if (ownerDef->IsFighterAirUnit()) {
const float3 P = owner->pos + (owner->speed * 10.0);
const float R = 1000.0f * owner->moveState;
const CUnit* enemy = CGameHelper::GetClosestEnemyAircraft(NULL, P, R, owner->allyteam);
if (!ownerDef->canAttack || !autoAttack || owner->maxRange <= 0.0f)
return false;

if (IsValidTarget(enemy)) {
Command nc(CMD_ATTACK, INTERNAL_ORDER, enemy->id);
commandQue.push_front(nc);
inCommand = false;
return true;
}
} else {
const float3 P = owner->pos + (owner->speed * 20.0f);
const float R = 500.0f * owner->moveState;
const CUnit* enemy = CGameHelper::GetClosestValidTarget(P, R, owner->allyteam, this);
// pass bogus target-id and weapon-number s.t. script knows context and can set radius
if (!eventHandler.AllowWeaponTarget(owner->id, -1, -1, 0, &searchRadius))
return false;

if (enemy != NULL) {
Command nc(CMD_ATTACK, INTERNAL_ORDER, enemy->id);
commandQue.push_front(nc);
inCommand = false;
return true;
}
}
if (isFlying && autoLand)
StopMove();

const CUnit* tgt = nullptr;
const CWeapon* wpn = owner->weapons[0];

if (ownerDef->IsFighterAirUnit()) {
tgt = CGameHelper::GetClosestEnemyAircraft(nullptr, owner->pos + owner->speed * 10.0f, searchRadius, owner->allyteam);
} else {
tgt = CGameHelper::GetClosestValidTarget(owner->pos + owner->speed * 20.0f, searchRadius, owner->allyteam, this);
}

return false;
if (!IsValidTarget(tgt))
return false;
if (!eventHandler.AllowWeaponTarget(owner->id, tgt->id, wpn->weaponNum, wpn->weaponDef->id, nullptr))
return false;

Command nc(CMD_ATTACK, INTERNAL_ORDER, tgt->id);
commandQue.push_front(nc);
inCommand = false;
return true;
}


@@ -257,21 +257,22 @@ void CAirCAI::ExecuteMove(Command& c)
AAirMoveType* myPlane = GetStrafeAirMoveType(owner);
SetGoal(cmdPos, owner->pos);

const CStrafeAirMoveType* airMT = (!owner->UsingScriptMoveType())? static_cast<const CStrafeAirMoveType*>(myPlane): NULL;
const float radius = (airMT != NULL)? std::max(airMT->turnRadius + 2 * SQUARE_SIZE, 128.f) : 127.f;
const CStrafeAirMoveType* airMT = (!owner->UsingScriptMoveType())? static_cast<const CStrafeAirMoveType*>(myPlane): nullptr;

const float mtRadius = (airMT != nullptr)? std::max(airMT->turnRadius + 2 * SQUARE_SIZE, 128.0f) : 127.0f;
const float sqRadius = Square(mtRadius);

// we're either circling or will get to the target in 8 frames
if ((owner->pos - cmdPos).SqLength2D() < (radius * radius)
|| (owner->pos + owner->speed*8 - cmdPos).SqLength2D() < 127*127)
{
if ((owner->pos - cmdPos).SqLength2D() < sqRadius || (owner->pos + owner->speed * 8.0f - cmdPos).SqLength2D() < Square(127.0f))
StopMoveAndFinishCommand();
}
}


void CAirCAI::ExecuteFight(Command& c)
{
assert((c.GetOpts() & INTERNAL_ORDER) || owner->unitDef->canFight);
const UnitDef* ownerDef = owner->unitDef;

assert((c.GetOpts() & INTERNAL_ORDER) || ownerDef->canFight);

// FIXME: check owner->UsingScriptMoveType() and skip rest if true?
AAirMoveType* myPlane = GetStrafeAirMoveType(owner);
@@ -289,9 +290,8 @@ void CAirCAI::ExecuteFight(Command& c)
}

if (c.GetNumParams() >= 6) {
if (!inCommand) {
if (!inCommand)
commandPos1 = c.GetPos(3);
}
} else {
// HACK to make sure the line (commandPos1,commandPos2) is NOT
// rotated (only shortened) if we reach this because the previous return
@@ -300,9 +300,8 @@ void CAirCAI::ExecuteFight(Command& c)
// outside the area close to the line (for a new command).
commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);

if ((owner->pos - commandPos1).SqLength2D() > (150 * 150)) {
if ((owner->pos - commandPos1).SqLength2D() > Square(150.0f))
commandPos1 = owner->pos;
}
}

float3 goalPos = c.GetPos(0);
@@ -311,21 +310,19 @@ void CAirCAI::ExecuteFight(Command& c)
inCommand = true;
commandPos2 = goalPos;
}
if (c.GetNumParams() >= 6) {
if (c.GetNumParams() >= 6)
goalPos = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
}

// CMD_FIGHT is pretty useless if !canAttack, but we try to honour the modders wishes anyway...
if (owner->unitDef->canAttack && (owner->fireState >= FIRESTATE_FIREATWILL)
&& (owner->moveState != MOVESTATE_HOLDPOS) && (owner->maxRange > 0))
if ((owner->fireState >= FIRESTATE_FIREATWILL) && (owner->moveState != MOVESTATE_HOLDPOS) && (owner->maxRange > 0.0f) && ownerDef->canAttack)
{
CUnit* enemy = NULL;
CUnit* enemy = nullptr;

if (owner->unitDef->IsFighterAirUnit()) {
const float3 P = ClosestPointOnLine(commandPos1, commandPos2, owner->pos + owner->speed*10);
const float R = 1000.0f * owner->moveState;
if (ownerDef->IsFighterAirUnit()) {
const float3 ofs = owner->speed * 10.0f;
const float3 pos = ClosestPointOnLine(commandPos1, commandPos2, owner->pos + ofs);

enemy = CGameHelper::GetClosestEnemyAircraft(NULL, P, R, owner->allyteam);
enemy = CGameHelper::GetClosestEnemyAircraft(nullptr, pos, 1000.0f * owner->moveState, owner->allyteam);
}
if (IsValidTarget(enemy) && (owner->moveState != MOVESTATE_MANEUVER
|| LinePointDist(commandPos1, commandPos2, enemy->pos) < 1000))
@@ -348,12 +345,13 @@ void CAirCAI::ExecuteFight(Command& c)
lastPC1 = gs->frameNum;
SlowUpdate();
}

return;
} else {
const float3 P = ClosestPointOnLine(commandPos1, commandPos2, owner->pos + owner->speed * 20);
const float R = 500.0f * owner->moveState;
const float3 ofs = owner->speed * 20.0f;
const float3 pos = ClosestPointOnLine(commandPos1, commandPos2, owner->pos + ofs);

enemy = CGameHelper::GetClosestValidTarget(P, R, owner->allyteam, this);
enemy = CGameHelper::GetClosestValidTarget(pos, 500.0f * owner->moveState, owner->allyteam, this);

if (enemy != nullptr) {
PushOrUpdateReturnFight();
@@ -522,15 +520,15 @@ int CAirCAI::GetDefaultCmd(const CUnit* pointed, const CFeature* feature)
{
if (pointed) {
if (!teamHandler.Ally(gu->myAllyTeam, pointed->allyteam)) {
if (owner->unitDef->canAttack) {
if (owner->unitDef->canAttack)
return CMD_ATTACK;
}

} else {
if (owner->unitDef->canGuard) {
if (owner->unitDef->canGuard)
return CMD_GUARD;
}
}
}

return CMD_MOVE;
}

0 comments on commit 198e315

Please sign in to comment.
You can’t perform that action at this time.