OpenXcom Forum

Modding => Released Mods => Brutal AI => Topic started by: Xilmi on November 11, 2022, 12:43:45 am

Title: Target-Voxel for Throwing-simulation in AI off by 1 voxel
Post by: Xilmi on November 11, 2022, 12:43:45 am
In AI-code both scoreFiringMode and grenadeAction do a simulation for the trajectory of throwing a grenade. For that they set the targetPostion to:

targetPosition = target->getPosition().toVoxel() + Position (8,8, (2 + -target->getTile()->getTerrainLevel()));

However, in the actual calculateThrow-function in Projectile.cpp the

targetVoxel = _action.target.toVoxel() + Position(8,8, (1 + -targetTile->getTerrainLevel()));

is different by 1 in the Z-value.

Doesn't look like much but I have a save-game where it made all the difference between works and doesn't work.

Here it tried to throw to the selected tile. According to old AI-code it thought it could throw there. But actually couldn't. With adjusted code it realizes that it can't throw there and isntead picks a position nearby, where it works.
Title: Re: Target-Voxel for Throwing-simulation in AI off by 1 voxel
Post by: Xilmi on November 18, 2022, 11:43:40 pm
Tested with Celatids for the first time and in some occassions got my infinite loop due to giving invalid commands-issue back.

The validity-check for weapons with arcing-shot is apparently way more complicated than for throwing since...

Code: [Select]
if (_action.type == BA_THROW)
{
targets.push_back(targetVoxel);
}
else
{
BattleUnit *tu = targetTile->getOverlappingUnit(_save);
if (Options::forceFire && _save->isCtrlPressed(true) && _save->getSide() == FACTION_PLAYER)
{
targets.push_back(_action.target.toVoxel() + Position(0, 0, 12));
forced = true;
}
else if (tu && ((_action.actor->getFaction() != FACTION_PLAYER) ||
tu->getVisible()))
{ //unit
targetVoxel.z += tu->getFloatHeight(); //ground level is the base
targets.push_back(targetVoxel + Position(0, 0, tu->getHeight()/2 + 1));
targets.push_back(targetVoxel + Position(0, 0, 2));
targets.push_back(targetVoxel + Position(0, 0, tu->getHeight() - 1));
}
else if (targetTile->getMapData(O_OBJECT) != 0)
{
targetVoxel = _action.target.toVoxel() + Position(8,8,0);
targets.push_back(targetVoxel + Position(0, 0, 13));
targets.push_back(targetVoxel + Position(0, 0, 8));
targets.push_back(targetVoxel + Position(0, 0, 23));
targets.push_back(targetVoxel + Position(0, 0, 2));
}
else if (targetTile->getMapData(O_NORTHWALL) != 0)
{
targetVoxel = _action.target.toVoxel() + Position(8,0,0);
targets.push_back(targetVoxel + Position(0, 0, 13));
targets.push_back(targetVoxel + Position(0, 0, 8));
targets.push_back(targetVoxel + Position(0, 0, 20));
targets.push_back(targetVoxel + Position(0, 0, 3));
}
else if (targetTile->getMapData(O_WESTWALL) != 0)
  {
targetVoxel = _action.target.toVoxel() + Position(0,8,0);
targets.push_back(targetVoxel + Position(0, 0, 13));
targets.push_back(targetVoxel + Position(0, 0, 8));
targets.push_back(targetVoxel + Position(0, 0, 20));
targets.push_back(targetVoxel + Position(0, 0, 2));
}
else if (targetTile->getMapData(O_FLOOR) != 0)
{
targets.push_back(targetVoxel);
}
}

So instead of checking one target-voxel a whole bunch is beeing checked. But they are all different from the one being checked for an actual throw. So the same code cannot be used for throwing and arcing-shots.