Move some functions from unit.cpp to unit_find.cpp
Add unit_find.h
This commit is contained in:
parent
77ad8b6eb5
commit
55d9c4b267
21 changed files with 565 additions and 496 deletions
|
@ -490,6 +490,7 @@ set(stratagus_generic_HDRS
|
|||
src/include/ui.h
|
||||
src/include/unit.h
|
||||
src/include/unit_cache.h
|
||||
src/include/unit_find.h
|
||||
src/include/unit_manager.h
|
||||
src/include/unitptr.h
|
||||
src/include/unitsound.h
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "spells.h"
|
||||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "script.h"
|
||||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
enum {
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "sound.h"
|
||||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "spells.h"
|
||||
#include "tileset.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
enum {
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "player.h"
|
||||
#include "script.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "pathfinder.h"
|
||||
#include "player.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
#include "depend.h"
|
||||
#include "map.h"
|
||||
#include "pathfinder.h"
|
||||
#include "unittype.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Types
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "missile.h"
|
||||
#include "pathfinder.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "pathfinder.h"
|
||||
#include "player.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
#include "upgrade.h"
|
||||
|
||||
|
|
|
@ -36,29 +36,31 @@
|
|||
#include <deque>
|
||||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "editor.h"
|
||||
|
||||
#include "commands.h"
|
||||
#include "font.h"
|
||||
#include "guichan.h"
|
||||
#include "interface.h"
|
||||
#include "iocompat.h"
|
||||
#include "iolib.h"
|
||||
#include "map.h"
|
||||
#include "menus.h"
|
||||
#include "minimap.h"
|
||||
#include "network.h"
|
||||
#include "replay.h"
|
||||
#include "script.h"
|
||||
#include "settings.h"
|
||||
#include "sound.h"
|
||||
#include "sound_server.h"
|
||||
#include "tileset.h"
|
||||
#include "ui.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
#include "video.h"
|
||||
#include "map.h"
|
||||
#include "tileset.h"
|
||||
#include "minimap.h"
|
||||
#include "settings.h"
|
||||
#include "network.h"
|
||||
#include "sound_server.h"
|
||||
#include "ui.h"
|
||||
#include "interface.h"
|
||||
#include "font.h"
|
||||
#include "widgets.h"
|
||||
#include "editor.h"
|
||||
#include "results.h"
|
||||
#include "menus.h"
|
||||
#include "sound.h"
|
||||
#include "iolib.h"
|
||||
#include "iocompat.h"
|
||||
#include "commands.h"
|
||||
#include "guichan.h"
|
||||
#include "replay.h"
|
||||
|
||||
#include "script.h"
|
||||
|
||||
extern void DoScrollArea(int state, bool fast);
|
||||
extern void DrawGuichanWidgets();
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "results.h"
|
||||
#include "script.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -466,37 +466,6 @@ public:
|
|||
PixelPos GetMapPixelPosCenter() const;
|
||||
};
|
||||
|
||||
//unit_find
|
||||
struct CUnitTypeFinder {
|
||||
const UnitTypeType type;
|
||||
CUnitTypeFinder(const UnitTypeType t) : type(t) {}
|
||||
bool operator()(const CUnit *const unit) const {
|
||||
const CUnitType *const t = unit->Type;
|
||||
if (t->Vanishes || (type != static_cast<UnitTypeType>(-1) && t->UnitType != type)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CUnit *Find(const CUnitCache &cache) const { return cache.find(*this); }
|
||||
CUnit *Find(const CMapField *const mf) const { return mf->UnitCache.find(*this); }
|
||||
};
|
||||
|
||||
struct CResourceFinder {
|
||||
const int resource;
|
||||
const int mine_on_top;
|
||||
CResourceFinder(const int r, int on_top) : resource(r), mine_on_top(on_top) {}
|
||||
inline bool operator()(const CUnit *const unit) const {
|
||||
const CUnitType *const type = unit->Type;
|
||||
return (type->GivesResource == resource
|
||||
&& unit->ResourcesHeld != 0
|
||||
&& (mine_on_top ? type->CanHarvest : !type->CanHarvest)
|
||||
&& !unit->IsUnusable(true) //allow mines under construction
|
||||
);
|
||||
}
|
||||
CUnit *Find(const CMapField *const mf) const { return mf->UnitCache.find(*this); }
|
||||
};
|
||||
|
||||
#define NoUnitP (CUnit *)0 /// return value: for no unit found
|
||||
|
||||
#define MAX_UNIT_SLOTS 65535 /// Maximal number of used slots
|
||||
|
@ -633,19 +602,6 @@ extern CUnit *CanBuildUnitType(const CUnit *unit, const CUnitType &type, const V
|
|||
/// Get the suitable animation frame depends of unit's damaged type.
|
||||
extern int ExtraDeathIndex(const char *death);
|
||||
|
||||
/// Find resource
|
||||
extern CUnit *UnitFindResource(const CUnit &unit, const CUnit &startUnit, int range,
|
||||
int resource, bool check_usage = false, const CUnit *deposit = NULL);
|
||||
|
||||
/// Find nearest deposit
|
||||
extern CUnit *FindDeposit(const CUnit &unit, int range, int resource);
|
||||
/// Find the next idle worker
|
||||
extern CUnit *FindIdleWorker(const CPlayer &player, const CUnit *last);
|
||||
|
||||
/// Find the neareast piece of terrain with specific flags.
|
||||
extern bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *pos);
|
||||
|
||||
/// @todo more docu
|
||||
extern CUnit *UnitOnScreen(CUnit *unit, int x, int y);
|
||||
|
||||
|
@ -713,29 +669,6 @@ extern int FindAndSortUnits(const CViewport *vp, std::vector<CUnit *> &table);
|
|||
/// Show a unit's orders.
|
||||
extern void ShowOrder(const CUnit &unit);
|
||||
|
||||
// in unit_find.cpp
|
||||
|
||||
extern void FindUnitsByType(const CUnitType &type, std::vector<CUnit *> &units);
|
||||
|
||||
/// Find all units of this type of the player
|
||||
extern void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &units);
|
||||
/// Return any unit on that map tile
|
||||
extern CUnit *UnitOnMapTile(const Vec2i &pos, unsigned int type);// = -1);
|
||||
/// Return possible attack target on that map area
|
||||
extern CUnit *TargetOnMap(const CUnit &unit, const Vec2i &pos1, const Vec2i &pos2);
|
||||
|
||||
/// Return resource, if on map tile
|
||||
extern CUnit *ResourceOnMap(const Vec2i &pos, int resource, bool mine_on_top = true);
|
||||
/// Return resource deposit, if on map tile
|
||||
extern CUnit *ResourceDepositOnMap(const Vec2i &pos, int resource);
|
||||
|
||||
/// Find best enemy in numeric range to attack
|
||||
extern CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings = false);
|
||||
/// Find best enemy in attack range to attack
|
||||
extern CUnit *AttackUnitsInRange(const CUnit &unit);
|
||||
/// Find best enemy in reaction range to attack
|
||||
extern CUnit *AttackUnitsInReactRange(const CUnit &unit);
|
||||
|
||||
// in groups.c
|
||||
|
||||
/// Initialize data structures for groups
|
||||
|
|
115
src/include/unit_find.h
Normal file
115
src/include/unit_find.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name unit.h - The unit headerfile. */
|
||||
//
|
||||
// (c) Copyright 1998-2012 by Lutz Sammer, Jimmy Salmon and Joris Dauphin
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; only version 2 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
|
||||
#ifndef __UNIT_FIND_H__
|
||||
#define __UNIT_FIND_H__
|
||||
|
||||
//@{
|
||||
|
||||
#include "unit.h"
|
||||
#include "unittype.h"
|
||||
|
||||
class CUnitCache;
|
||||
class CMapField;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
//unit_find
|
||||
struct CUnitTypeFinder {
|
||||
const UnitTypeType type;
|
||||
CUnitTypeFinder(const UnitTypeType t) : type(t) {}
|
||||
bool operator()(const CUnit *const unit) const {
|
||||
const CUnitType *const t = unit->Type;
|
||||
if (t->Vanishes || (type != static_cast<UnitTypeType>(-1) && t->UnitType != type)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CUnit *Find(const CUnitCache &cache) const { return cache.find(*this); }
|
||||
CUnit *Find(const CMapField *const mf) const { return mf->UnitCache.find(*this); }
|
||||
};
|
||||
|
||||
struct CResourceFinder {
|
||||
const int resource;
|
||||
const int mine_on_top;
|
||||
CResourceFinder(const int r, int on_top) : resource(r), mine_on_top(on_top) {}
|
||||
inline bool operator()(const CUnit *const unit) const {
|
||||
const CUnitType *const type = unit->Type;
|
||||
return (type->GivesResource == resource
|
||||
&& unit->ResourcesHeld != 0
|
||||
&& (mine_on_top ? type->CanHarvest : !type->CanHarvest)
|
||||
&& !unit->IsUnusable(true) //allow mines under construction
|
||||
);
|
||||
}
|
||||
CUnit *Find(const CMapField *const mf) const { return mf->UnitCache.find(*this); }
|
||||
};
|
||||
|
||||
/// Find resource
|
||||
extern CUnit *UnitFindResource(const CUnit &unit, const CUnit &startUnit, int range,
|
||||
int resource, bool check_usage = false, const CUnit *deposit = NULL);
|
||||
|
||||
/// Find nearest deposit
|
||||
extern CUnit *FindDeposit(const CUnit &unit, int range, int resource);
|
||||
/// Find the next idle worker
|
||||
extern CUnit *FindIdleWorker(const CPlayer &player, const CUnit *last);
|
||||
|
||||
/// Find the neareast piece of terrain with specific flags.
|
||||
extern bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *pos);
|
||||
|
||||
|
||||
// in unit_find.cpp
|
||||
|
||||
extern void FindUnitsByType(const CUnitType &type, std::vector<CUnit *> &units);
|
||||
|
||||
/// Find all units of this type of the player
|
||||
extern void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &units);
|
||||
/// Return any unit on that map tile
|
||||
extern CUnit *UnitOnMapTile(const Vec2i &pos, unsigned int type);// = -1);
|
||||
/// Return possible attack target on that map area
|
||||
extern CUnit *TargetOnMap(const CUnit &unit, const Vec2i &pos1, const Vec2i &pos2);
|
||||
|
||||
/// Return resource, if on map tile
|
||||
extern CUnit *ResourceOnMap(const Vec2i &pos, int resource, bool mine_on_top = true);
|
||||
/// Return resource deposit, if on map tile
|
||||
extern CUnit *ResourceDepositOnMap(const Vec2i &pos, int resource);
|
||||
|
||||
/// Find best enemy in numeric range to attack
|
||||
extern CUnit *AttackUnitsInDistance(const CUnit &unit, int range, bool onlyBuildings = false);
|
||||
/// Find best enemy in attack range to attack
|
||||
extern CUnit *AttackUnitsInRange(const CUnit &unit);
|
||||
/// Find best enemy in reaction range to attack
|
||||
extern CUnit *AttackUnitsInReactRange(const CUnit &unit);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // !__UNIT_FIND_H__
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "map.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
|
||||
#include "pathfinder.h"
|
||||
|
||||
|
|
|
@ -48,9 +48,10 @@
|
|||
#include "sound.h"
|
||||
#include "sound_server.h"
|
||||
#include "tileset.h"
|
||||
#include "unittype.h"
|
||||
#include "unit.h"
|
||||
#include "ui.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
#include "video.h"
|
||||
#include "widgets.h"
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "spells.h"
|
||||
#include "tileset.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unitsound.h"
|
||||
#include "unittype.h"
|
||||
#include "video.h"
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "script.h"
|
||||
#include "spells.h"
|
||||
#include "trigger.h"
|
||||
#include "unit_find.h"
|
||||
#include "unit_manager.h"
|
||||
#include "unittype.h"
|
||||
#include "upgrade.h"
|
||||
|
|
|
@ -41,30 +41,32 @@
|
|||
#include "stratagus.h"
|
||||
|
||||
#include "unit.h"
|
||||
|
||||
#include "actions.h"
|
||||
#include "ai.h"
|
||||
#include "animation.h"
|
||||
#include "commands.h"
|
||||
#include "construct.h"
|
||||
#include "editor.h"
|
||||
#include "interface.h"
|
||||
#include "iolib.h"
|
||||
#include "luacallback.h"
|
||||
#include "map.h"
|
||||
#include "missile.h"
|
||||
#include "network.h"
|
||||
#include "pathfinder.h"
|
||||
#include "player.h"
|
||||
#include "script.h"
|
||||
#include "sound.h"
|
||||
#include "sound_server.h"
|
||||
#include "spells.h"
|
||||
#include "tileset.h"
|
||||
#include "ui.h"
|
||||
#include "unit_find.h"
|
||||
#include "unit_manager.h"
|
||||
#include "video.h"
|
||||
#include "unitsound.h"
|
||||
#include "unittype.h"
|
||||
#include "animation.h"
|
||||
#include "player.h"
|
||||
#include "tileset.h"
|
||||
#include "map.h"
|
||||
#include "actions.h"
|
||||
#include "sound_server.h"
|
||||
#include "missile.h"
|
||||
#include "interface.h"
|
||||
#include "sound.h"
|
||||
#include "ai.h"
|
||||
#include "pathfinder.h"
|
||||
#include "network.h"
|
||||
#include "ui.h"
|
||||
#include "script.h"
|
||||
#include "editor.h"
|
||||
#include "spells.h"
|
||||
#include "luacallback.h"
|
||||
#include "construct.h"
|
||||
#include "iolib.h"
|
||||
#include "video.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Documentation
|
||||
|
@ -2277,392 +2279,6 @@ void DropOutAll(const CUnit &source)
|
|||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Finding units
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class TerrainFinder
|
||||
{
|
||||
public:
|
||||
TerrainFinder(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i *resPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos) {}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
const CPlayer &player;
|
||||
int maxDist;
|
||||
int movemask;
|
||||
int resmask;
|
||||
Vec2i *resPos;
|
||||
};
|
||||
|
||||
VisitResult TerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!player.AiEnabled && !Map.IsFieldExplored(player, pos)) {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
// Look if found what was required.
|
||||
if (Map.CheckMask(pos, resmask)) {
|
||||
if (resPos) {
|
||||
*resPos = pos;
|
||||
}
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
if (CanMoveToMask(pos, movemask)) { // reachable
|
||||
if (terrainTraversal.Get(pos) <= maxDist) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Find the closest piece of terrain with the given flags.
|
||||
**
|
||||
** @param movemask The movement mask to reach that location.
|
||||
** @param resmask Result tile mask.
|
||||
** @param range Maximum distance for the search.
|
||||
** @param player Only search fields explored by player
|
||||
** @param startPos Map start position for the search.
|
||||
**
|
||||
** @param terrainPos OUT: Map position of tile.
|
||||
**
|
||||
** @note Movement mask can be 0xFFFFFFFF to have no effect
|
||||
** Range is not circular, but square.
|
||||
** Player is ignored if nil(search the entire map)
|
||||
**
|
||||
** @return True if wood was found.
|
||||
*/
|
||||
bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos)
|
||||
{
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
||||
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
|
||||
terrainTraversal.Init();
|
||||
|
||||
terrainTraversal.PushPos(startPos);
|
||||
|
||||
TerrainFinder terrainFinder(player, range, movemask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit), resmask, terrainPos);
|
||||
|
||||
return terrainTraversal.Run(terrainFinder);
|
||||
}
|
||||
|
||||
|
||||
template <const bool NEARLOCATION>
|
||||
class BestDepotFinder
|
||||
{
|
||||
inline void operator()(CUnit *const dest) {
|
||||
/* Only resource depots */
|
||||
if (dest->Type->CanStore[resource]
|
||||
&& dest->IsAliveOnMap()
|
||||
&& dest->CurrentAction() != UnitActionBuilt) {
|
||||
// Unit in range?
|
||||
|
||||
if (NEARLOCATION) {
|
||||
int d = dest->MapDistanceTo(u_near.loc);
|
||||
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
if (d <= range && d < best_dist) {
|
||||
best_depot = dest;
|
||||
best_dist = d;
|
||||
}
|
||||
} else {
|
||||
int d;
|
||||
const CUnit *worker = u_near.worker;
|
||||
if (!worker->Container) {
|
||||
d = worker->MapDistanceTo(*dest);
|
||||
} else {
|
||||
d = worker->Container->MapDistanceTo(*dest);
|
||||
}
|
||||
|
||||
// Use Circle, not square :)
|
||||
if (d > range) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calck real travel distance
|
||||
if (!worker->Container) {
|
||||
d = UnitReachable(*worker, *dest, 1);
|
||||
}
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
if (d && d < best_dist) {
|
||||
best_depot = dest;
|
||||
best_dist = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
BestDepotFinder(const CUnit &w, int res, int ran) :
|
||||
resource(res), range(ran),
|
||||
best_dist(INT_MAX), best_depot(0) {
|
||||
u_near.worker = &w;
|
||||
}
|
||||
|
||||
BestDepotFinder(const Vec2i &pos, int res, int ran) :
|
||||
resource(res), range(ran),
|
||||
best_dist(INT_MAX), best_depot(0) {
|
||||
u_near.loc = pos;
|
||||
}
|
||||
|
||||
template <typename ITERATOR>
|
||||
CUnit *Find(ITERATOR begin, ITERATOR end) {
|
||||
for (ITERATOR it = begin; it != end; ++it) {
|
||||
this->operator()(*it);
|
||||
}
|
||||
return best_depot;
|
||||
}
|
||||
|
||||
CUnit *Find(CUnitCache &cache) {
|
||||
cache.for_each(*this);
|
||||
return best_depot;
|
||||
}
|
||||
private:
|
||||
struct {
|
||||
const CUnit *worker;
|
||||
Vec2i loc;
|
||||
} u_near;
|
||||
const int resource;
|
||||
const int range;
|
||||
int best_dist;
|
||||
public:
|
||||
CUnit *best_depot;
|
||||
};
|
||||
|
||||
CUnit *FindDepositNearLoc(CPlayer &p, const Vec2i &pos, int range, int resource)
|
||||
{
|
||||
BestDepotFinder<true> finder(pos, resource, range);
|
||||
CUnit *depot = finder.Find(p.UnitBegin(), p.UnitEnd());
|
||||
|
||||
if (!depot) {
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
if (i != p.Index &&
|
||||
Players[i].IsAllied(p) &&
|
||||
p.IsAllied(Players[i])) {
|
||||
finder.Find(Players[i].UnitBegin(), Players[i].UnitEnd());
|
||||
}
|
||||
}
|
||||
depot = finder.best_depot;
|
||||
}
|
||||
return depot;
|
||||
}
|
||||
|
||||
class ResourceUnitFinder
|
||||
{
|
||||
public:
|
||||
ResourceUnitFinder(const CUnit &worker, const CUnit *deposit, int resource, int maxRange, bool check_usage, CUnit **resultMine) :
|
||||
worker(worker),
|
||||
resinfo(*worker.Type->ResInfo[resource]),
|
||||
deposit(deposit),
|
||||
movemask(worker.Type->MovementMask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit)),
|
||||
resource(resource),
|
||||
maxRange(maxRange),
|
||||
check_usage(check_usage),
|
||||
res_finder(resource, 1),
|
||||
resultMine(resultMine) {
|
||||
bestCost.SetToMax();
|
||||
*resultMine = NULL;
|
||||
}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
bool MineIsUsable(const CUnit &mine) const;
|
||||
|
||||
struct ResourceUnitFinder_Cost {
|
||||
public:
|
||||
void SetFrom(const CUnit &mine, const CUnit *deposit, bool check_usage);
|
||||
bool operator < (const ResourceUnitFinder_Cost &rhs) const {
|
||||
if (assigned != rhs.assigned) {
|
||||
return assigned < rhs.assigned;
|
||||
} else if (waiting != rhs.waiting) {
|
||||
return waiting < rhs.waiting;
|
||||
} else {
|
||||
return distance < rhs.distance;
|
||||
}
|
||||
}
|
||||
void SetToMax() { assigned = waiting = distance = UINT_MAX; }
|
||||
bool IsMin() const { return assigned == 0 && waiting == 0 && distance == 0; }
|
||||
|
||||
public:
|
||||
unsigned int assigned;
|
||||
unsigned int waiting;
|
||||
unsigned int distance;
|
||||
};
|
||||
|
||||
private:
|
||||
const CUnit &worker;
|
||||
const ResourceInfo &resinfo;
|
||||
const CUnit *deposit;
|
||||
unsigned int movemask;
|
||||
int resource;
|
||||
int maxRange;
|
||||
bool check_usage;
|
||||
CResourceFinder res_finder;
|
||||
ResourceUnitFinder_Cost bestCost;
|
||||
CUnit **resultMine;
|
||||
};
|
||||
|
||||
bool ResourceUnitFinder::MineIsUsable(const CUnit &mine) const
|
||||
{
|
||||
return mine.Type->CanHarvest && mine.ResourcesHeld
|
||||
&& (resinfo.HarvestFromOutside
|
||||
|| mine.Player->Index == PlayerMax - 1
|
||||
|| mine.Player == worker.Player
|
||||
|| (worker.IsAllied(mine) && mine.IsAllied(worker)));
|
||||
}
|
||||
|
||||
void ResourceUnitFinder::ResourceUnitFinder_Cost::SetFrom(const CUnit &mine, const CUnit *deposit, bool check_usage)
|
||||
{
|
||||
distance = deposit ? mine.MapDistanceTo(*deposit) : 0;
|
||||
if (check_usage) {
|
||||
assigned = mine.Resource.Assigned - mine.Type->MaxOnBoard;
|
||||
waiting = GetNumWaitingWorkers(mine);
|
||||
} else {
|
||||
assigned = 0;
|
||||
waiting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VisitResult ResourceUnitFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!worker.Player->AiEnabled && !Map.IsFieldExplored(*worker.Player, pos)) {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
|
||||
CUnit *mine = res_finder.Find(Map.Field(pos));
|
||||
|
||||
if (mine && mine != *resultMine && MineIsUsable(*mine)) {
|
||||
ResourceUnitFinder::ResourceUnitFinder_Cost cost;
|
||||
|
||||
cost.SetFrom(*mine, deposit, check_usage);
|
||||
if (cost < bestCost) {
|
||||
*resultMine = mine;
|
||||
|
||||
if (cost.IsMin()) {
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
bestCost = cost;
|
||||
}
|
||||
}
|
||||
if (CanMoveToMask(pos, movemask)) { // reachable
|
||||
if (terrainTraversal.Get(pos) < maxRange) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Find Resource.
|
||||
**
|
||||
** @param unit The unit that wants to find a resource.
|
||||
** @param startUnit Find closest unit from this location
|
||||
** @param range Maximum distance to the resource.
|
||||
** @param resource The resource id.
|
||||
**
|
||||
** @note This will return an usable resource building that doesn't
|
||||
** belong to the player or one of his allies.
|
||||
**
|
||||
** @return NoUnitP or resource unit
|
||||
*/
|
||||
CUnit *UnitFindResource(const CUnit &unit, const CUnit &startUnit, int range, int resource,
|
||||
bool check_usage, const CUnit *deposit)
|
||||
{
|
||||
if (!deposit) { // Find the nearest depot
|
||||
deposit = FindDepositNearLoc(*unit.Player, startUnit.tilePos, range, resource);
|
||||
}
|
||||
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
||||
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
|
||||
terrainTraversal.Init();
|
||||
|
||||
terrainTraversal.PushUnitPosAndNeighboor(startUnit);
|
||||
|
||||
CUnit *resultMine = NULL;
|
||||
|
||||
ResourceUnitFinder resourceUnitFinder(unit, deposit, resource, range, check_usage, &resultMine);
|
||||
|
||||
terrainTraversal.Run(resourceUnitFinder);
|
||||
return resultMine;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find deposit. This will find a deposit for a resource
|
||||
**
|
||||
** @param unit The unit that wants to find a resource.
|
||||
** @param x Closest to x
|
||||
** @param y Closest to y
|
||||
** @param range Maximum distance to the deposit.
|
||||
** @param resource Resource to find deposit from.
|
||||
**
|
||||
** @note This will return a reachable allied depot.
|
||||
**
|
||||
** @return NoUnitP or deposit unit
|
||||
*/
|
||||
CUnit *FindDeposit(const CUnit &unit, int range, int resource)
|
||||
{
|
||||
BestDepotFinder<false> finder(unit, resource, range);
|
||||
CUnit *depot = finder.Find(unit.Player->UnitBegin(), unit.Player->UnitEnd());
|
||||
if (!depot) {
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
if (i != unit.Player->Index &&
|
||||
Players[i].IsAllied(*unit.Player) &&
|
||||
unit.Player->IsAllied(Players[i])) {
|
||||
finder.Find(Players[i].UnitBegin(), Players[i].UnitEnd());
|
||||
}
|
||||
}
|
||||
depot = finder.best_depot;
|
||||
}
|
||||
return depot;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find the next idle worker
|
||||
**
|
||||
** @param player Player's units to search through
|
||||
** @param last Previous idle worker selected
|
||||
**
|
||||
** @return NoUnitP or next idle worker
|
||||
*/
|
||||
CUnit *FindIdleWorker(const CPlayer &player, const CUnit *last)
|
||||
{
|
||||
CUnit *FirstUnitFound = NoUnitP;
|
||||
int SelectNextUnit = (last == NoUnitP) ? 1 : 0;
|
||||
const int nunits = player.GetUnitCount();
|
||||
|
||||
for (int i = 0; i < nunits; ++i) {
|
||||
CUnit &unit = player.GetUnit(i);
|
||||
if (unit.Type->Harvester && unit.Type->ResInfo && !unit.Removed) {
|
||||
if (unit.CurrentAction() == UnitActionStill) {
|
||||
if (SelectNextUnit && !IsOnlySelected(unit)) {
|
||||
return &unit;
|
||||
}
|
||||
if (FirstUnitFound == NULL) {
|
||||
FirstUnitFound = &unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (&unit == last) {
|
||||
SelectNextUnit = 1;
|
||||
}
|
||||
}
|
||||
if (FirstUnitFound != NoUnitP && !IsOnlySelected(*FirstUnitFound)) {
|
||||
return FirstUnitFound;
|
||||
}
|
||||
return NoUnitP;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Select units
|
||||
----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "stratagus.h"
|
||||
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
|
||||
#include "actions.h"
|
||||
#include "map.h"
|
||||
|
@ -45,8 +45,395 @@
|
|||
#include "pathfinder.h"
|
||||
#include "player.h"
|
||||
#include "spells.h"
|
||||
#include "unit.h"
|
||||
#include "unittype.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Finding units
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
class TerrainFinder
|
||||
{
|
||||
public:
|
||||
TerrainFinder(const CPlayer &player, int maxDist, int movemask, int resmask, Vec2i *resPos) :
|
||||
player(player), maxDist(maxDist), movemask(movemask), resmask(resmask), resPos(resPos) {}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
const CPlayer &player;
|
||||
int maxDist;
|
||||
int movemask;
|
||||
int resmask;
|
||||
Vec2i *resPos;
|
||||
};
|
||||
|
||||
VisitResult TerrainFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!player.AiEnabled && !Map.IsFieldExplored(player, pos)) {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
// Look if found what was required.
|
||||
if (Map.CheckMask(pos, resmask)) {
|
||||
if (resPos) {
|
||||
*resPos = pos;
|
||||
}
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
if (CanMoveToMask(pos, movemask)) { // reachable
|
||||
if (terrainTraversal.Get(pos) <= maxDist) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Find the closest piece of terrain with the given flags.
|
||||
**
|
||||
** @param movemask The movement mask to reach that location.
|
||||
** @param resmask Result tile mask.
|
||||
** @param range Maximum distance for the search.
|
||||
** @param player Only search fields explored by player
|
||||
** @param startPos Map start position for the search.
|
||||
**
|
||||
** @param terrainPos OUT: Map position of tile.
|
||||
**
|
||||
** @note Movement mask can be 0xFFFFFFFF to have no effect
|
||||
** Range is not circular, but square.
|
||||
** Player is ignored if nil(search the entire map)
|
||||
**
|
||||
** @return True if wood was found.
|
||||
*/
|
||||
bool FindTerrainType(int movemask, int resmask, int range,
|
||||
const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos)
|
||||
{
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
||||
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
|
||||
terrainTraversal.Init();
|
||||
|
||||
terrainTraversal.PushPos(startPos);
|
||||
|
||||
TerrainFinder terrainFinder(player, range, movemask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit), resmask, terrainPos);
|
||||
|
||||
return terrainTraversal.Run(terrainFinder);
|
||||
}
|
||||
|
||||
|
||||
template <const bool NEARLOCATION>
|
||||
class BestDepotFinder
|
||||
{
|
||||
inline void operator()(CUnit *const dest) {
|
||||
/* Only resource depots */
|
||||
if (dest->Type->CanStore[resource]
|
||||
&& dest->IsAliveOnMap()
|
||||
&& dest->CurrentAction() != UnitActionBuilt) {
|
||||
// Unit in range?
|
||||
|
||||
if (NEARLOCATION) {
|
||||
int d = dest->MapDistanceTo(u_near.loc);
|
||||
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
if (d <= range && d < best_dist) {
|
||||
best_depot = dest;
|
||||
best_dist = d;
|
||||
}
|
||||
} else {
|
||||
int d;
|
||||
const CUnit *worker = u_near.worker;
|
||||
if (!worker->Container) {
|
||||
d = worker->MapDistanceTo(*dest);
|
||||
} else {
|
||||
d = worker->Container->MapDistanceTo(*dest);
|
||||
}
|
||||
|
||||
// Use Circle, not square :)
|
||||
if (d > range) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calck real travel distance
|
||||
if (!worker->Container) {
|
||||
d = UnitReachable(*worker, *dest, 1);
|
||||
}
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
if (d && d < best_dist) {
|
||||
best_depot = dest;
|
||||
best_dist = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
BestDepotFinder(const CUnit &w, int res, int ran) :
|
||||
resource(res), range(ran),
|
||||
best_dist(INT_MAX), best_depot(0) {
|
||||
u_near.worker = &w;
|
||||
}
|
||||
|
||||
BestDepotFinder(const Vec2i &pos, int res, int ran) :
|
||||
resource(res), range(ran),
|
||||
best_dist(INT_MAX), best_depot(0) {
|
||||
u_near.loc = pos;
|
||||
}
|
||||
|
||||
template <typename ITERATOR>
|
||||
CUnit *Find(ITERATOR begin, ITERATOR end) {
|
||||
for (ITERATOR it = begin; it != end; ++it) {
|
||||
this->operator()(*it);
|
||||
}
|
||||
return best_depot;
|
||||
}
|
||||
|
||||
CUnit *Find(CUnitCache &cache) {
|
||||
cache.for_each(*this);
|
||||
return best_depot;
|
||||
}
|
||||
private:
|
||||
struct {
|
||||
const CUnit *worker;
|
||||
Vec2i loc;
|
||||
} u_near;
|
||||
const int resource;
|
||||
const int range;
|
||||
int best_dist;
|
||||
public:
|
||||
CUnit *best_depot;
|
||||
};
|
||||
|
||||
CUnit *FindDepositNearLoc(CPlayer &p, const Vec2i &pos, int range, int resource)
|
||||
{
|
||||
BestDepotFinder<true> finder(pos, resource, range);
|
||||
CUnit *depot = finder.Find(p.UnitBegin(), p.UnitEnd());
|
||||
|
||||
if (!depot) {
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
if (i != p.Index &&
|
||||
Players[i].IsAllied(p) &&
|
||||
p.IsAllied(Players[i])) {
|
||||
finder.Find(Players[i].UnitBegin(), Players[i].UnitEnd());
|
||||
}
|
||||
}
|
||||
depot = finder.best_depot;
|
||||
}
|
||||
return depot;
|
||||
}
|
||||
|
||||
class ResourceUnitFinder
|
||||
{
|
||||
public:
|
||||
ResourceUnitFinder(const CUnit &worker, const CUnit *deposit, int resource, int maxRange, bool check_usage, CUnit **resultMine) :
|
||||
worker(worker),
|
||||
resinfo(*worker.Type->ResInfo[resource]),
|
||||
deposit(deposit),
|
||||
movemask(worker.Type->MovementMask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit)),
|
||||
resource(resource),
|
||||
maxRange(maxRange),
|
||||
check_usage(check_usage),
|
||||
res_finder(resource, 1),
|
||||
resultMine(resultMine) {
|
||||
bestCost.SetToMax();
|
||||
*resultMine = NULL;
|
||||
}
|
||||
VisitResult Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from);
|
||||
private:
|
||||
bool MineIsUsable(const CUnit &mine) const;
|
||||
|
||||
struct ResourceUnitFinder_Cost {
|
||||
public:
|
||||
void SetFrom(const CUnit &mine, const CUnit *deposit, bool check_usage);
|
||||
bool operator < (const ResourceUnitFinder_Cost &rhs) const {
|
||||
if (assigned != rhs.assigned) {
|
||||
return assigned < rhs.assigned;
|
||||
} else if (waiting != rhs.waiting) {
|
||||
return waiting < rhs.waiting;
|
||||
} else {
|
||||
return distance < rhs.distance;
|
||||
}
|
||||
}
|
||||
void SetToMax() { assigned = waiting = distance = UINT_MAX; }
|
||||
bool IsMin() const { return assigned == 0 && waiting == 0 && distance == 0; }
|
||||
|
||||
public:
|
||||
unsigned int assigned;
|
||||
unsigned int waiting;
|
||||
unsigned int distance;
|
||||
};
|
||||
|
||||
private:
|
||||
const CUnit &worker;
|
||||
const ResourceInfo &resinfo;
|
||||
const CUnit *deposit;
|
||||
unsigned int movemask;
|
||||
int resource;
|
||||
int maxRange;
|
||||
bool check_usage;
|
||||
CResourceFinder res_finder;
|
||||
ResourceUnitFinder_Cost bestCost;
|
||||
CUnit **resultMine;
|
||||
};
|
||||
|
||||
bool ResourceUnitFinder::MineIsUsable(const CUnit &mine) const
|
||||
{
|
||||
return mine.Type->CanHarvest && mine.ResourcesHeld
|
||||
&& (resinfo.HarvestFromOutside
|
||||
|| mine.Player->Index == PlayerMax - 1
|
||||
|| mine.Player == worker.Player
|
||||
|| (worker.IsAllied(mine) && mine.IsAllied(worker)));
|
||||
}
|
||||
|
||||
void ResourceUnitFinder::ResourceUnitFinder_Cost::SetFrom(const CUnit &mine, const CUnit *deposit, bool check_usage)
|
||||
{
|
||||
distance = deposit ? mine.MapDistanceTo(*deposit) : 0;
|
||||
if (check_usage) {
|
||||
assigned = mine.Resource.Assigned - mine.Type->MaxOnBoard;
|
||||
waiting = GetNumWaitingWorkers(mine);
|
||||
} else {
|
||||
assigned = 0;
|
||||
waiting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VisitResult ResourceUnitFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
|
||||
{
|
||||
if (!worker.Player->AiEnabled && !Map.IsFieldExplored(*worker.Player, pos)) {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
|
||||
CUnit *mine = res_finder.Find(Map.Field(pos));
|
||||
|
||||
if (mine && mine != *resultMine && MineIsUsable(*mine)) {
|
||||
ResourceUnitFinder::ResourceUnitFinder_Cost cost;
|
||||
|
||||
cost.SetFrom(*mine, deposit, check_usage);
|
||||
if (cost < bestCost) {
|
||||
*resultMine = mine;
|
||||
|
||||
if (cost.IsMin()) {
|
||||
return VisitResult_Finished;
|
||||
}
|
||||
bestCost = cost;
|
||||
}
|
||||
}
|
||||
if (CanMoveToMask(pos, movemask)) { // reachable
|
||||
if (terrainTraversal.Get(pos) < maxRange) {
|
||||
return VisitResult_Ok;
|
||||
} else {
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
} else { // unreachable
|
||||
return VisitResult_DeadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Find Resource.
|
||||
**
|
||||
** @param unit The unit that wants to find a resource.
|
||||
** @param startUnit Find closest unit from this location
|
||||
** @param range Maximum distance to the resource.
|
||||
** @param resource The resource id.
|
||||
**
|
||||
** @note This will return an usable resource building that doesn't
|
||||
** belong to the player or one of his allies.
|
||||
**
|
||||
** @return NoUnitP or resource unit
|
||||
*/
|
||||
CUnit *UnitFindResource(const CUnit &unit, const CUnit &startUnit, int range, int resource,
|
||||
bool check_usage, const CUnit *deposit)
|
||||
{
|
||||
if (!deposit) { // Find the nearest depot
|
||||
deposit = FindDepositNearLoc(*unit.Player, startUnit.tilePos, range, resource);
|
||||
}
|
||||
|
||||
TerrainTraversal terrainTraversal;
|
||||
|
||||
terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight);
|
||||
terrainTraversal.Init();
|
||||
|
||||
terrainTraversal.PushUnitPosAndNeighboor(startUnit);
|
||||
|
||||
CUnit *resultMine = NULL;
|
||||
|
||||
ResourceUnitFinder resourceUnitFinder(unit, deposit, resource, range, check_usage, &resultMine);
|
||||
|
||||
terrainTraversal.Run(resourceUnitFinder);
|
||||
return resultMine;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find deposit. This will find a deposit for a resource
|
||||
**
|
||||
** @param unit The unit that wants to find a resource.
|
||||
** @param x Closest to x
|
||||
** @param y Closest to y
|
||||
** @param range Maximum distance to the deposit.
|
||||
** @param resource Resource to find deposit from.
|
||||
**
|
||||
** @note This will return a reachable allied depot.
|
||||
**
|
||||
** @return NoUnitP or deposit unit
|
||||
*/
|
||||
CUnit *FindDeposit(const CUnit &unit, int range, int resource)
|
||||
{
|
||||
BestDepotFinder<false> finder(unit, resource, range);
|
||||
CUnit *depot = finder.Find(unit.Player->UnitBegin(), unit.Player->UnitEnd());
|
||||
if (!depot) {
|
||||
for (int i = 0; i < PlayerMax; ++i) {
|
||||
if (i != unit.Player->Index &&
|
||||
Players[i].IsAllied(*unit.Player) &&
|
||||
unit.Player->IsAllied(Players[i])) {
|
||||
finder.Find(Players[i].UnitBegin(), Players[i].UnitEnd());
|
||||
}
|
||||
}
|
||||
depot = finder.best_depot;
|
||||
}
|
||||
return depot;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find the next idle worker
|
||||
**
|
||||
** @param player Player's units to search through
|
||||
** @param last Previous idle worker selected
|
||||
**
|
||||
** @return NoUnitP or next idle worker
|
||||
*/
|
||||
CUnit *FindIdleWorker(const CPlayer &player, const CUnit *last)
|
||||
{
|
||||
CUnit *FirstUnitFound = NoUnitP;
|
||||
int SelectNextUnit = (last == NoUnitP) ? 1 : 0;
|
||||
const int nunits = player.GetUnitCount();
|
||||
|
||||
for (int i = 0; i < nunits; ++i) {
|
||||
CUnit &unit = player.GetUnit(i);
|
||||
if (unit.Type->Harvester && unit.Type->ResInfo && !unit.Removed) {
|
||||
if (unit.CurrentAction() == UnitActionStill) {
|
||||
if (SelectNextUnit && !IsOnlySelected(unit)) {
|
||||
return &unit;
|
||||
}
|
||||
if (FirstUnitFound == NULL) {
|
||||
FirstUnitFound = &unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (&unit == last) {
|
||||
SelectNextUnit = 1;
|
||||
}
|
||||
}
|
||||
if (FirstUnitFound != NoUnitP && !IsOnlySelected(*FirstUnitFound)) {
|
||||
return FirstUnitFound;
|
||||
}
|
||||
return NoUnitP;
|
||||
}
|
||||
|
||||
/**
|
||||
** Find all units of type.
|
||||
**
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "player.h"
|
||||
#include "script.h"
|
||||
#include "unit.h"
|
||||
#include "unit_find.h"
|
||||
#include "unittype.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue