[-] Transporters don't attack inagressive air units
This commit is contained in:
parent
7c28912489
commit
7cb2a8f9a4
8 changed files with 92 additions and 46 deletions
|
@ -55,6 +55,7 @@
|
|||
#define AIATTACK_RANGE 0
|
||||
#define AIATTACK_ALLMAP 1
|
||||
#define AIATTACK_BUILDING 2
|
||||
#define AIATTACK_AGRESSIVE 3
|
||||
|
||||
template <const int FIND_TYPE>
|
||||
class AiForceEnemyFinder
|
||||
|
@ -86,11 +87,17 @@ public:
|
|||
} else if (FIND_TYPE == AIATTACK_ALLMAP) {
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
|
||||
} else if (FIND_TYPE == AIATTACK_BUILDING) {
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth, true);
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsBuildingType());
|
||||
Assert(!*enemy || (*enemy)->Type->Building);
|
||||
if (*enemy == NULL) {
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
|
||||
}
|
||||
} else if (FIND_TYPE == AIATTACK_AGRESSIVE) {
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth, IsAggresiveUnit());
|
||||
Assert(!*enemy || (*enemy)->IsAgressive());
|
||||
if (*enemy == NULL) {
|
||||
*enemy = AttackUnitsInDistance(*unit, MaxMapWidth);
|
||||
}
|
||||
}
|
||||
return *enemy == NULL;
|
||||
}
|
||||
|
@ -386,10 +393,20 @@ void AiForce::Attack(const Vec2i &pos)
|
|||
break;
|
||||
}
|
||||
}
|
||||
bool isTransporter = false;
|
||||
for (size_t i = 0; i != this->Units.size(); ++i) {
|
||||
CUnit *const unit = this->Units[i];
|
||||
if (unit->Type->CanTransport() && unit->IsAgressive() == false) {
|
||||
isTransporter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Map.Info.IsPointOnMap(goalPos) == false) {
|
||||
/* Search in entire map */
|
||||
const CUnit *enemy = NULL;
|
||||
if (isNaval) {
|
||||
if (isTransporter) {
|
||||
AiForceEnemyFinder<AIATTACK_AGRESSIVE>(*this, &enemy);
|
||||
} else if (isNaval) {
|
||||
AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &enemy);
|
||||
} else {
|
||||
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy);
|
||||
|
@ -400,7 +417,7 @@ void AiForce::Attack(const Vec2i &pos)
|
|||
} else {
|
||||
isDefenceForce = true;
|
||||
}
|
||||
if (Map.Info.IsPointOnMap(goalPos) == false) {
|
||||
if (Map.Info.IsPointOnMap(goalPos) == false || isTransporter) {
|
||||
DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index);
|
||||
if (State == AiForceAttackingState_Waiting && !PlanAttack()) {
|
||||
DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index);
|
||||
|
|
|
@ -75,6 +75,9 @@ public:
|
|||
|| unit->CurrentAction() == UnitActionDie) {
|
||||
return;
|
||||
}
|
||||
if (unit->Type->UnitType == UnitTypeFly && unit->IsAgressive() == false) {
|
||||
return;
|
||||
}
|
||||
if (pos.x < unit->tilePos.x || pos.x >= unit->tilePos.x + type.TileWidth
|
||||
|| pos.y < unit->tilePos.y || pos.y >= unit->tilePos.y + type.TileHeight) {
|
||||
return;
|
||||
|
|
|
@ -442,7 +442,7 @@ public:
|
|||
bool GrayscaleIcons; /// Use grayscaled icons for unavailable units, upgrades, etc
|
||||
bool IconsShift; /// Shift icons slightly when you press on them
|
||||
bool StereoSound; /// Enables/diables stereo sound effects
|
||||
bool MineNotifications; /// Show mine is running low/depleted messages (as in Warcraft 3)
|
||||
bool MineNotifications; /// Show mine is running low/depleted messages
|
||||
|
||||
int ShowOrders; /// How many second show orders of unit on map.
|
||||
int ShowNameDelay; /// How many cycles need to wait until unit's name popup will appear.
|
||||
|
|
|
@ -45,7 +45,19 @@
|
|||
// Some predicates
|
||||
//
|
||||
|
||||
class HasSameTypeAs
|
||||
class CUnitFilter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CUnit *unit) const { return true; };
|
||||
};
|
||||
|
||||
class NoFilter : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CUnit *) const { return true; }
|
||||
};
|
||||
|
||||
class HasSameTypeAs : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit HasSameTypeAs(const CUnitType &_type) : type(&_type) {}
|
||||
|
@ -54,7 +66,7 @@ private:
|
|||
const CUnitType *type;
|
||||
};
|
||||
|
||||
class HasSamePlayerAs
|
||||
class HasSamePlayerAs : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit HasSamePlayerAs(const CPlayer &_player) : player(&_player) {}
|
||||
|
@ -63,7 +75,7 @@ private:
|
|||
const CPlayer *player;
|
||||
};
|
||||
|
||||
class HasNotSamePlayerAs
|
||||
class HasNotSamePlayerAs : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit HasNotSamePlayerAs(const CPlayer &_player) : player(&_player) {}
|
||||
|
@ -72,7 +84,7 @@ private:
|
|||
const CPlayer *player;
|
||||
};
|
||||
|
||||
class IsAlliedWith
|
||||
class IsAlliedWith : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit IsAlliedWith(const CPlayer &_player) : player(&_player) {}
|
||||
|
@ -81,7 +93,7 @@ private:
|
|||
const CPlayer *player;
|
||||
};
|
||||
|
||||
class IsEnemyWith
|
||||
class IsEnemyWith : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit IsEnemyWith(const CPlayer &_player) : player(&_player) {}
|
||||
|
@ -90,7 +102,7 @@ private:
|
|||
const CPlayer *player;
|
||||
};
|
||||
|
||||
class HasSamePlayerAndTypeAs
|
||||
class HasSamePlayerAndTypeAs : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit HasSamePlayerAndTypeAs(const CUnit &unit) :
|
||||
|
@ -110,7 +122,7 @@ private:
|
|||
const CUnitType *type;
|
||||
};
|
||||
|
||||
class IsNotTheSameUnitAs
|
||||
class IsNotTheSameUnitAs : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit IsNotTheSameUnitAs(const CUnit &unit) : forbidden(&unit) {}
|
||||
|
@ -119,13 +131,19 @@ private:
|
|||
const CUnit *forbidden;
|
||||
};
|
||||
|
||||
class IsBuildingType
|
||||
class IsBuildingType : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CUnit *unit) const { return unit->Type->Building; }
|
||||
};
|
||||
|
||||
class OutOfMinRange
|
||||
class IsAggresiveUnit : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CUnit *unit) const { return unit->IsAgressive(); }
|
||||
};
|
||||
|
||||
class OutOfMinRange : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit OutOfMinRange(const int range, const Vec2i pos) : range(range), pos(pos) {}
|
||||
|
@ -137,7 +155,7 @@ private:
|
|||
|
||||
|
||||
template <typename Pred>
|
||||
class NotPredicate
|
||||
class NotPredicate : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
explicit NotPredicate(Pred _pred) : pred(_pred) {}
|
||||
|
@ -150,7 +168,7 @@ template <typename Pred>
|
|||
NotPredicate<Pred> MakeNotPredicate(Pred pred) { return NotPredicate<Pred>(pred); }
|
||||
|
||||
template <typename Pred1, typename Pred2>
|
||||
class AndPredicate
|
||||
class AndPredicate : public CUnitFilter
|
||||
{
|
||||
public:
|
||||
AndPredicate(Pred1 _pred1, Pred2 _pred2) : pred1(_pred1), pred2(_pred2) {}
|
||||
|
@ -310,12 +328,17 @@ extern CUnit *ResourceDepositOnMap(const Vec2i &pos, int resource);
|
|||
/// Check map for obstacles in a line between 2 tiles
|
||||
extern bool CheckObstaclesBetweenTiles(const Vec2i &unitPos, const Vec2i &goalPos, unsigned short flags, int *distance = NULL);
|
||||
/// Find best enemy in numeric range to attack
|
||||
extern CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings = false);
|
||||
extern CUnit *AttackUnitsInDistance(const CUnit &unit, int range, CUnitFilter pred);
|
||||
extern CUnit *AttackUnitsInDistance(const CUnit &unit, int range);
|
||||
/// Find best enemy in attack range to attack
|
||||
extern CUnit *AttackUnitsInRange(const CUnit &unit, CUnitFilter pred);
|
||||
extern CUnit *AttackUnitsInRange(const CUnit &unit);
|
||||
/// Find best enemy in reaction range to attack
|
||||
extern CUnit *AttackUnitsInReactRange(const CUnit &unit, CUnitFilter pred);
|
||||
extern CUnit *AttackUnitsInReactRange(const CUnit &unit);
|
||||
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
#endif // !__UNIT_FIND_H__
|
||||
|
|
|
@ -543,9 +543,9 @@ static int CostMoveToCallBack_Default(unsigned int index, const CUnit &unit)
|
|||
} else {
|
||||
// for non moving unit Always Fail unless goal is unit, or unit can attack the target
|
||||
if (&unit != goal) {
|
||||
if (goal->Player->IsEnemy(unit) && unit.IsAgressive() && CanTarget(*unit.Type, *goal->Type)
|
||||
&& goal->Variable[UNHOLYARMOR_INDEX].Value == 0 && goal->IsVisibleAsGoal(*unit.Player)) {
|
||||
cost += 2 * AStarMovingUnitCrossingCost;
|
||||
if (goal->Player->IsEnemy(unit) && unit.IsAgressive() && CanTarget(*unit.Type, *goal->Type)
|
||||
&& goal->Variable[UNHOLYARMOR_INDEX].Value == 0 && goal->IsVisibleAsGoal(*unit.Player)) {
|
||||
cost += 2 * AStarMovingUnitCrossingCost;
|
||||
} else {
|
||||
// FIXME: Need support for moving a fixed unit to add cost
|
||||
return -1;
|
||||
|
|
|
@ -210,7 +210,7 @@ extern void beos_init(int argc, char **argv);
|
|||
|
||||
#ifdef USE_STACKTRACE
|
||||
#include <stdexcept>
|
||||
#include <stacktrace/call_stack.hpp>
|
||||
#include <stacktrace/call_stack.hpp>
|
||||
#include <stacktrace/stack_exception.hpp>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
#ifdef USE_STACKTRACE
|
||||
#include <stdexcept>
|
||||
#include <stacktrace/call_stack.hpp>
|
||||
#include <stacktrace/call_stack.hpp>
|
||||
#include <stacktrace/stack_exception.hpp>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -54,12 +54,6 @@
|
|||
-- Finding units
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class NoFilter
|
||||
{
|
||||
public:
|
||||
bool operator()(const CUnit *) const { return true; }
|
||||
};
|
||||
|
||||
void Select(const Vec2i <Pos, const Vec2i &rbPos, std::vector<CUnit *> &units)
|
||||
{
|
||||
Select(ltPos, rbPos, units, NoFilter());
|
||||
|
@ -740,6 +734,10 @@ private:
|
|||
return INT_MAX;
|
||||
}
|
||||
|
||||
if (dtype.UnitType == UnitTypeFly && dest->IsAgressive() == false) {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
// Calculate the costs to attack the unit.
|
||||
// Unit with the smallest attack costs will be taken.
|
||||
int cost = 0;
|
||||
|
@ -1123,7 +1121,7 @@ bool CheckObstaclesBetweenTiles(const Vec2i &unitPos, const Vec2i &goalPos, unsi
|
|||
**
|
||||
** @return Unit to be attacked.
|
||||
*/
|
||||
CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings)
|
||||
CUnit *AttackUnitsInDistance(const CUnit &unit, int range, CUnitFilter pred)
|
||||
{
|
||||
// if necessary, take possible damage on allied units into account...
|
||||
if (unit.Type->Missile.Missile->Range > 1
|
||||
|
@ -1138,13 +1136,8 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings)
|
|||
// If unit is removed, use containers x and y
|
||||
const CUnit *firstContainer = unit.Container ? unit.Container : &unit;
|
||||
std::vector<CUnit *> table;
|
||||
if (onlyBuildings) {
|
||||
SelectAroundUnit(*firstContainer, missile_range, table,
|
||||
MakeAndPredicate(HasNotSamePlayerAs(Players[PlayerNumNeutral]), IsBuildingType()));
|
||||
} else {
|
||||
SelectAroundUnit(*firstContainer, missile_range, table,
|
||||
MakeNotPredicate(HasSamePlayerAs(Players[PlayerNumNeutral])));
|
||||
}
|
||||
SelectAroundUnit(*firstContainer, missile_range, table,
|
||||
MakeAndPredicate(HasNotSamePlayerAs(Players[PlayerNumNeutral]), pred));
|
||||
|
||||
if (table.empty() == false) {
|
||||
return BestRangeTargetFinder(unit, range).Find(table);
|
||||
|
@ -1155,13 +1148,8 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings)
|
|||
const CUnit *firstContainer = unit.Container ? unit.Container : &unit;
|
||||
std::vector<CUnit *> table;
|
||||
|
||||
if (onlyBuildings) {
|
||||
SelectAroundUnit(*firstContainer, range, table,
|
||||
MakeAndPredicate(HasNotSamePlayerAs(Players[PlayerNumNeutral]), IsBuildingType()));
|
||||
} else {
|
||||
SelectAroundUnit(*firstContainer, range, table,
|
||||
MakeNotPredicate(HasSamePlayerAs(Players[PlayerNumNeutral])));
|
||||
}
|
||||
SelectAroundUnit(*firstContainer, range, table,
|
||||
MakeAndPredicate(HasNotSamePlayerAs(Players[PlayerNumNeutral]), pred));
|
||||
|
||||
const int n = static_cast<int>(table.size());
|
||||
if (range > 25 && table.size() > 9) {
|
||||
|
@ -1173,6 +1161,11 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings)
|
|||
}
|
||||
}
|
||||
|
||||
CUnit *AttackUnitsInDistance(const CUnit &unit, int range)
|
||||
{
|
||||
return AttackUnitsInDistance(unit, range, NoFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
** Attack units in attack range.
|
||||
**
|
||||
|
@ -1180,10 +1173,15 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings)
|
|||
**
|
||||
** @return Pointer to unit which should be attacked.
|
||||
*/
|
||||
CUnit *AttackUnitsInRange(const CUnit &unit)
|
||||
CUnit *AttackUnitsInRange(const CUnit &unit, CUnitFilter pred)
|
||||
{
|
||||
Assert(unit.Type->CanAttack);
|
||||
return AttackUnitsInDistance(unit, unit.Stats->Variables[ATTACKRANGE_INDEX].Max);
|
||||
return AttackUnitsInDistance(unit, unit.Stats->Variables[ATTACKRANGE_INDEX].Max, pred);
|
||||
}
|
||||
|
||||
CUnit *AttackUnitsInRange(const CUnit &unit)
|
||||
{
|
||||
return AttackUnitsInRange(unit, NoFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1193,11 +1191,16 @@ CUnit *AttackUnitsInRange(const CUnit &unit)
|
|||
**
|
||||
** @return Pointer to unit which should be attacked.
|
||||
*/
|
||||
CUnit *AttackUnitsInReactRange(const CUnit &unit)
|
||||
CUnit *AttackUnitsInReactRange(const CUnit &unit, CUnitFilter pred)
|
||||
{
|
||||
Assert(unit.Type->CanAttack);
|
||||
const int range = unit.Player->Type == PlayerPerson ? unit.Type->ReactRangePerson : unit.Type->ReactRangeComputer;
|
||||
return AttackUnitsInDistance(unit, range);
|
||||
return AttackUnitsInDistance(unit, range, pred);
|
||||
}
|
||||
|
||||
CUnit *AttackUnitsInReactRange(const CUnit &unit)
|
||||
{
|
||||
return AttackUnitsInReactRange(unit, NoFilter());
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
Loading…
Reference in a new issue