[*] Improved AI collision detection
[-] Correcting transporting
This commit is contained in:
parent
f80feaecf7
commit
4dafa76a97
6 changed files with 100 additions and 31 deletions
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "action/action_resource.h"
|
||||
|
||||
#include "ai.h"
|
||||
#include "animation.h"
|
||||
#include "interface.h"
|
||||
#include "iolib.h"
|
||||
|
@ -384,6 +385,14 @@ int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
|
|||
return -1;
|
||||
case PF_REACHED:
|
||||
return 1;
|
||||
case PF_WAIT:
|
||||
if (unit.Player->AiEnabled) {
|
||||
this->Range++;
|
||||
if (this->Range >= 5) {
|
||||
this->Range = 0;
|
||||
AiCanNotMove(unit);
|
||||
}
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -404,6 +413,14 @@ int COrder_Resource::MoveToResource_Unit(CUnit &unit)
|
|||
return -1;
|
||||
case PF_REACHED:
|
||||
break;
|
||||
case PF_WAIT:
|
||||
if (unit.Player->AiEnabled) {
|
||||
this->Range++;
|
||||
if (this->Range >= 5) {
|
||||
this->Range = 0;
|
||||
AiCanNotMove(unit);
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Goal gone or something.
|
||||
if (unit.Anim.Unbreakable || goal->IsVisibleAsGoal(*unit.Player)) {
|
||||
|
@ -899,6 +916,14 @@ int COrder_Resource::MoveToDepot(CUnit &unit)
|
|||
return -1;
|
||||
case PF_REACHED:
|
||||
break;
|
||||
case PF_WAIT:
|
||||
if (unit.Player->AiEnabled) {
|
||||
this->Range++;
|
||||
if (this->Range >= 5) {
|
||||
this->Range = 0;
|
||||
AiCanNotMove(unit);
|
||||
}
|
||||
}
|
||||
default:
|
||||
if (unit.Anim.Unbreakable || goal.IsVisibleAsGoal(player)) {
|
||||
return 0;
|
||||
|
@ -1136,6 +1161,7 @@ bool COrder_Resource::ActionResourceInit(CUnit &unit)
|
|||
{
|
||||
Assert(this->State == SUB_START_RESOURCE);
|
||||
|
||||
this->Range = 0;
|
||||
CUnit *const goal = this->GetGoal();
|
||||
CUnit *mine = this->Resource.Mine;
|
||||
|
||||
|
|
|
@ -833,8 +833,8 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
|
||||
AiPlayer = unit.Player->Ai;
|
||||
|
||||
// No more than 1 move per 3 cycle ( avoid stressing the pathfinder )
|
||||
if (GameCycle <= AiPlayer->LastCanNotMoveGameCycle + 3) {
|
||||
// No more than 1 move per 10 cycle ( avoid stressing the pathfinder )
|
||||
if (GameCycle <= AiPlayer->LastCanNotMoveGameCycle + 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -851,7 +851,7 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
if (blocker.IsUnusable()) {
|
||||
continue;
|
||||
}
|
||||
if (!blocker.IsIdle()) {
|
||||
if (!blocker.CanMove() || blocker.Moving) {
|
||||
continue;
|
||||
}
|
||||
if (blocker.Player != unit.Player && blocker.Player->IsAllied(*unit.Player) == false) {
|
||||
|
@ -862,9 +862,6 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
if (blockertype.UnitType != unittype.UnitType) {
|
||||
continue;
|
||||
}
|
||||
if (!blocker.CanMove()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vec2i b0 = blocker.tilePos;
|
||||
const Vec2i b1(b0.x + blockertype.TileWidth - 1, b0.y + blockertype.TileHeight - 1);
|
||||
|
@ -884,7 +881,7 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
r = (r + 1) & 7;
|
||||
--trycount;
|
||||
|
||||
const Vec2i pos = blocker.tilePos + dirs[r];
|
||||
const Vec2i pos = blocker.tilePos + blocker.Type->TileWidth * dirs[r];
|
||||
|
||||
// Out of the map => no !
|
||||
if (!Map.Info.IsPointOnMap(pos)) {
|
||||
|
@ -894,6 +891,9 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
if (pos == u0) {
|
||||
continue;
|
||||
}
|
||||
if (Map.Field(pos)->UnitCache.size() > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
movableunits[movablenb] = &blocker;
|
||||
movablepos[movablenb] = pos;
|
||||
|
@ -909,8 +909,16 @@ static void AiMoveUnitInTheWay(CUnit &unit)
|
|||
// Don't move more than 1 unit.
|
||||
if (movablenb) {
|
||||
const int index = SyncRand() % movablenb;
|
||||
|
||||
COrder *savedOrder = NULL;
|
||||
if (movableunits[index]->IsIdle() == false) {
|
||||
if (unit.CanStoreOrder(unit.CurrentOrder())) {
|
||||
savedOrder = unit.CurrentOrder()->Clone();
|
||||
}
|
||||
}
|
||||
CommandMove(*movableunits[index], movablepos[index], FlushCommands);
|
||||
if (savedOrder != NULL) {
|
||||
unit.SavedOrder = savedOrder;
|
||||
}
|
||||
AiPlayer->LastCanNotMoveGameCycle = GameCycle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -378,10 +378,22 @@ void AiForce::Attack(const Vec2i &pos)
|
|||
}
|
||||
Vec2i goalPos(pos);
|
||||
|
||||
bool isNaval = false;
|
||||
for (size_t i = 0; i != this->Units.size(); ++i) {
|
||||
CUnit *const unit = this->Units[i];
|
||||
if (unit->Type->UnitType == UnitTypeNaval && unit->Type->CanAttack) {
|
||||
isNaval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Map.Info.IsPointOnMap(goalPos) == false) {
|
||||
/* Search in entire map */
|
||||
const CUnit *enemy = NULL;
|
||||
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy);
|
||||
if (isNaval) {
|
||||
AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &enemy);
|
||||
} else {
|
||||
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy);
|
||||
}
|
||||
if (enemy) {
|
||||
goalPos = enemy->tilePos;
|
||||
}
|
||||
|
@ -571,9 +583,15 @@ void AiForceManager::CheckUnits(int *counter)
|
|||
}
|
||||
for (unsigned int j = 0; j < force.UnitTypes.size(); ++j) {
|
||||
const AiUnitType &aiut = force.UnitTypes[j];
|
||||
const int t = aiut.Type->Slot;
|
||||
const unsigned int t = aiut.Type->Slot;
|
||||
const int wantedCount = aiut.Want;
|
||||
const int requested = wantedCount - (unit_types_count[t] + counter[t] - attacking[t]);
|
||||
int e = unit_types_count[t];
|
||||
if (t < AiHelpers.Equiv.size()) {
|
||||
for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) {
|
||||
e += unit_types_count[AiHelpers.Equiv[t][j]->Slot];
|
||||
}
|
||||
}
|
||||
const int requested = wantedCount - (e + counter[t] - attacking[t]);
|
||||
|
||||
if (requested > 0) { // Request it.
|
||||
AiAddUnitTypeRequest(*aiut.Type, requested);
|
||||
|
@ -778,27 +796,28 @@ static void AiGroupAttackerForTransport(AiForce &aiForce)
|
|||
CUnit &unit = *aiForce.Units[i];
|
||||
CUnit &transporter = *aiForce.Units[transporterIndex];
|
||||
|
||||
if (transporter.IsIdle()
|
||||
&& unit.CurrentAction() == UnitActionBoard
|
||||
if (unit.CurrentAction() == UnitActionBoard
|
||||
&& static_cast<COrder_Board *>(unit.CurrentOrder())->GetGoal() == &transporter) {
|
||||
CommandFollow(transporter, unit, 0);
|
||||
}
|
||||
if (CanTransport(transporter, unit) && unit.IsIdle() && unit.Container == NULL) {
|
||||
CommandBoard(unit, transporter, FlushCommands);
|
||||
CommandFollow(transporter, unit, 0);
|
||||
if (--nbToTransport == 0) { // full : next transporter.
|
||||
for (++transporterIndex; transporterIndex < aiForce.Size(); ++transporterIndex) {
|
||||
const CUnit &nextTransporter = *aiForce.Units[transporterIndex];
|
||||
if (CanTransport(transporter, unit) && (unit.IsIdle()
|
||||
|| (unit.CurrentAction() == UnitActionBoard && !unit.Moving
|
||||
&& static_cast<COrder_Board *>(unit.CurrentOrder())->GetGoal() != &transporter)) && unit.Container == NULL) {
|
||||
CommandBoard(unit, transporter, FlushCommands);
|
||||
CommandFollow(transporter, unit, 0);
|
||||
if (--nbToTransport == 0) { // full : next transporter.
|
||||
for (++transporterIndex; transporterIndex < aiForce.Size(); ++transporterIndex) {
|
||||
const CUnit &nextTransporter = *aiForce.Units[transporterIndex];
|
||||
|
||||
if (nextTransporter.Type->CanTransport()) {
|
||||
nbToTransport = nextTransporter.Type->MaxOnBoard - nextTransporter.BoardCount;
|
||||
if (nextTransporter.Type->CanTransport()) {
|
||||
nbToTransport = nextTransporter.Type->MaxOnBoard - nextTransporter.BoardCount;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (transporterIndex == aiForce.Size()) { // No more transporter.
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (transporterIndex == aiForce.Size()) { // No more transporter.
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -964,7 +983,19 @@ void AiForce::Update()
|
|||
if (State == AiForceAttackingState_Attacking && idleUnits.size() == this->Size()) {
|
||||
const CUnit *unit = NULL;
|
||||
|
||||
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &unit);
|
||||
bool isNaval = false;
|
||||
for (size_t i = 0; i != this->Units.size(); ++i) {
|
||||
CUnit *const unit = this->Units[i];
|
||||
if (unit->Type->UnitType == UnitTypeNaval && unit->Type->CanAttack) {
|
||||
isNaval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNaval) {
|
||||
AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &unit);
|
||||
} else {
|
||||
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &unit);
|
||||
}
|
||||
if (!unit) {
|
||||
// No enemy found, give up
|
||||
// FIXME: should the force go home or keep trying to attack?
|
||||
|
|
|
@ -42,7 +42,7 @@ class COrder_Resource : public COrder
|
|||
|
||||
public:
|
||||
COrder_Resource(CUnit &harvester) : COrder(UnitActionResource), worker(&harvester),
|
||||
CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false)
|
||||
CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false), Range(0)
|
||||
{
|
||||
Resource.Pos.x = Resource.Pos.y = -1;
|
||||
goalPos.x = goalPos.y = -1;
|
||||
|
@ -94,6 +94,7 @@ private:
|
|||
int State;
|
||||
int TimeToHarvest; /// how much time until we harvest some more.
|
||||
bool DoneHarvesting; /// Harvesting done, wait for action to break.
|
||||
int Range;
|
||||
#if 1
|
||||
// duplicate of Resource.Pos ?
|
||||
Vec2i goalPos;
|
||||
|
|
|
@ -527,7 +527,7 @@ static int CostMoveToCallBack_Default(unsigned int index, const CUnit &unit)
|
|||
do {
|
||||
const int flag = mf->Flags & mask;
|
||||
if (flag && (AStarKnowUnseenTerrain || mf->playerInfo.IsExplored(*unit.Player))) {
|
||||
if ((unit.Player->AiEnabled == false) && (flag & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit))) {
|
||||
if (flag & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit)) {
|
||||
// we can't cross fixed units and other unpassable things
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -216,10 +216,13 @@ class BestDepotFinder
|
|||
return;
|
||||
}
|
||||
|
||||
// calck real travel distance
|
||||
if (!worker->Container) {
|
||||
d = UnitReachable(*worker, *dest, 1);
|
||||
if (best_dist == INT_MAX) {
|
||||
best_depot = dest;
|
||||
}
|
||||
|
||||
// calck real travel distance
|
||||
|
||||
d = UnitReachable(worker->Container ? *worker->Container : *worker, *dest, 1);
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue