Fix ActionRessource and DeassignWorkerFromMine

This commit is contained in:
joris 2012-01-23 11:59:13 +01:00
parent 04c20eb84d
commit 09f642805e
8 changed files with 318 additions and 225 deletions

View file

@ -66,67 +66,87 @@
-- Functions
----------------------------------------------------------------------------*/
/**
** Move unit to terrain.
**
** @return 1 if reached, -1 if unreacheable, 0 if on the way.
*/
static int MoveToResource_Terrain(CUnit &unit)
{
Vec2i pos = unit.CurrentOrder()->goalPos;
// Wood gone, look somewhere else.
if ((!Map.ForestOnMap(pos)) && (!unit.IX) && (!unit.IY)) {
if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 16,
unit.Player, unit.CurrentOrder()->goalPos, &pos)) {
// no wood in range
return -1;
} else {
unit.CurrentOrder()->goalPos = pos;
NewResetPath(unit);
}
}
switch (DoActionMove(unit)) {
case PF_UNREACHABLE:
unit.Wait = 10;
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 9999,
unit.Player, unit.tilePos, &pos)) {
unit.CurrentOrder()->goalPos = pos;
NewResetPath(unit);
DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y);
// FIXME: can't this overflow? It really shouldn't, since
// x and y are really supossed to be reachable, checked thorugh a flood fill.
// I don't know, sometimes stuff happens.
return 0;
}
return -1;
case PF_REACHED:
return 1;
default:
return 0;
}
}
/**
** Move unit to unit resource.
**
** @return 1 if reached, -1 if unreacheable, 0 if on the way.
*/
static int MoveToResource_Unit(CUnit &unit)
{
const CUnit *goal = unit.CurrentOrder()->GetGoal();
Assert(goal);
switch (DoActionMove(unit)) { // reached end-point?
case PF_UNREACHABLE:
return -1;
case PF_REACHED:
break;
default:
// Goal gone or something.
if (unit.Anim.Unbreakable || goal->IsVisibleAsGoal(*unit.Player)) {
return 0;
}
break;
}
return 1;
}
/**
** Move unit to resource.
**
** @param unit Pointer to unit.
**
** @return TRUE if reached, otherwise FALSE.
** @return 1 if reached, -1 if unreacheable, 0 if on the way.
*/
static int MoveToResource(CUnit &unit)
{
const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
if (resinfo.TerrainHarvester) {
Vec2i pos = unit.CurrentOrder()->goalPos;
// Wood gone, look somewhere else.
if ((!Map.ForestOnMap(pos)) && (!unit.IX) && (!unit.IY)) {
if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 16,
unit.Player, unit.CurrentOrder()->goalPos, &pos)) {
// no wood in range
return -1;
} else {
unit.CurrentOrder()->goalPos = pos;
NewResetPath(unit);
}
}
switch (DoActionMove(unit)) {
case PF_UNREACHABLE:
unit.Wait = 10;
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 9999,
unit.Player, unit.tilePos, &pos)) {
unit.CurrentOrder()->goalPos = pos;
NewResetPath(unit);
DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y);
// FIXME: can't this overflow? It really shouldn't, since
// x and y are really supossed to be reachable, checked thorugh a flood fill.
// I don't know, sometimes stuff happens.
return 0;
}
return -1;
case PF_REACHED:
return 1;
default:
return 0;
}
return MoveToResource_Terrain(unit);
} else {
CUnit *goal = unit.CurrentOrder()->GetGoal();
Assert(goal);
switch (DoActionMove(unit)) { // reached end-point?
case PF_UNREACHABLE:
return -1;
case PF_REACHED:
break;
default:
// Goal gone or something.
if (unit.Anim.Unbreakable ||
goal->IsVisibleAsGoal(*unit.Player)) {
return 0;
}
break;
}
return 1;
return MoveToResource_Unit(unit);
}
}
@ -324,6 +344,8 @@ static void LoseResource(CUnit &unit, const CUnit &source)
}
}
/**
** Gather the resource
**
@ -441,7 +463,6 @@ static int GatherResource(CUnit &unit)
LoseResource(*uins, *source);
}
}
if (source->Data.Resource.Workers) {
CUnit *next, *worker = source->Data.Resource.Workers;
for (; NULL != worker; worker = next)
@ -462,7 +483,6 @@ static int GatherResource(CUnit &unit)
//Assert(source->Data.Resource.Assigned == 0);
source->Data.Resource.Workers = NULL;
}
// Don't destroy the resource twice.
// This only happens when it's empty.
if (!dead) {
@ -517,7 +537,6 @@ int GetNumWaitingWorkers(const CUnit &mine)
*/
static int StopGathering(CUnit &unit)
{
CUnit *depot;
CUnit *source = 0;
const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
@ -531,12 +550,15 @@ static int StopGathering(CUnit &unit)
source->Data.Resource.Active--;
Assert(source->Data.Resource.Active >= 0);
if (!resinfo.HarvestFromOutside && source->Data.Resource.Active == 0)
if (!resinfo.HarvestFromOutside && source->Data.Resource.Active == 0) {
source->SubAction = 1;
}
//Store resource position.
//source->RefsIncrease();
//unit.Orders[0]->Arg1.Resource.Mine = source;
if (unit.Orders[0]->Arg1.Resource.Mine) {
unit.Orders[0]->Arg1.Resource.Mine->RefsDecrease();
}
source->RefsIncrease();
unit.Orders[0]->Arg1.Resource.Mine = source;
if (source->Type->MaxOnBoard) {
int count = 0;
@ -544,8 +566,7 @@ static int StopGathering(CUnit &unit)
CUnit *next = NULL;
for(; NULL != worker; worker = worker->NextWorker)
{
if (worker != &unit &&
worker->SubAction == SUB_START_GATHERING && worker->Wait) {
if (worker != &unit && worker->SubAction == SUB_START_GATHERING && worker->Wait) {
count++;
if (next) {
if (next->Wait > worker->Wait)
@ -572,6 +593,7 @@ static int StopGathering(CUnit &unit)
} else {
// Store resource position.
unit.CurrentOrder()->Arg1.Resource.Pos = unit.tilePos;
Assert(unit.CurrentOrder()->Arg1.Resource.Mine == NULL);
}
#ifdef DEBUG
@ -581,17 +603,24 @@ static int StopGathering(CUnit &unit)
#endif
// Find and send to resource deposit.
if (!(depot = FindDeposit(unit, 1000, unit.CurrentResource))
|| !unit.ResourcesHeld) {
CUnit *depot = FindDeposit(unit, 1000, unit.CurrentResource);
if (!depot || !unit.ResourcesHeld) {
if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) {
Assert(unit.Container);
DropOutOnSide(unit, LookingW, source);
}
CUnit *mine = unit.Orders[0]->Arg1.Resource.Mine;
if (mine) {
unit.DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
unit.Orders[0]->Arg1.Resource.Mine = NULL;
}
DebugPrint("%d: Worker %d report: Can't find a resource [%d] deposit.\n"
_C_ unit.Player->Index _C_ unit.Slot _C_ unit.CurrentResource);
unit.CurrentOrder()->ClearGoal();
unit.ClearAction();
// should return 0, done below!
return 0;
} else {
if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) {
@ -638,8 +667,7 @@ static int MoveToDepot(CUnit &unit)
// Target is dead, stop getting resources.
//
if (!goal->IsVisibleAsGoal(*unit.Player)) {
DebugPrint("%d: Worker %d report: Destroyed depot\n"
_C_ unit.Player->Index _C_ unit.Slot);
DebugPrint("%d: Worker %d report: Destroyed depot\n" _C_ unit.Player->Index _C_ unit.Slot);
unit.CurrentOrder()->ClearGoal();
@ -647,8 +675,7 @@ static int MoveToDepot(CUnit &unit)
if (depot) {
UnitGotoGoal(unit, depot, SUB_MOVE_TO_DEPOT);
DebugPrint("%d: Worker %d report: Going to new deposit.\n"
_C_ unit.Player->Index _C_ unit.Slot);
DebugPrint("%d: Worker %d report: Going to new deposit.\n" _C_ unit.Player->Index _C_ unit.Slot);
} else {
DebugPrint("%d: Worker %d report: Can't find a new resource deposit.\n"
_C_ unit.Player->Index _C_ unit.Slot);
@ -666,7 +693,6 @@ static int MoveToDepot(CUnit &unit)
}
// If resource depot is still under construction, wait!
//
if (goal->CurrentOrder()->Action == UnitActionBuilt) {
unit.Wait = 10;
return 0;
@ -675,17 +701,13 @@ static int MoveToDepot(CUnit &unit)
unit.CurrentOrder()->ClearGoal();
unit.Wait = resinfo.WaitAtDepot;
//
// Place unit inside the depot
//
if (unit.Wait) {
unit.Remove(goal);
unit.Anim.CurrAnim = NULL;
}
//
// Update resource.
//
unit.Player->Resources[resinfo.FinalResource] += (unit.ResourcesHeld * unit.Player->Incomes[resinfo.FinalResource]) / 100;
unit.Player->TotalResources[resinfo.FinalResource] += (unit.ResourcesHeld * unit.Player->Incomes[resinfo.FinalResource]) / 100;
unit.ResourcesHeld = 0;
@ -708,7 +730,6 @@ static int MoveToDepot(CUnit &unit)
*/
static int WaitInDepot(CUnit &unit)
{
Vec2i pos;
const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
const CUnit *depot = ResourceDepositOnMap(unit.tilePos, resinfo.ResourceId);
@ -716,7 +737,7 @@ static int WaitInDepot(CUnit &unit)
// Range hardcoded. don't stray too far though
if (resinfo.TerrainHarvester) {
pos = unit.CurrentOrder()->Arg1.Resource.Pos;
Vec2i pos = unit.CurrentOrder()->Arg1.Resource.Pos;
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 10, unit.Player, pos, &pos)) {
if (depot) {
@ -730,12 +751,11 @@ static int WaitInDepot(CUnit &unit)
unit.ClearAction();
}
} else {
CUnit *goal;
CUnit *mine = unit.CurrentOrder()->Arg1.Resource.Mine;
const int range = (mine ? 15 : 1000);
pos = mine ? mine->tilePos : unit.tilePos;
const Vec2i pos = mine ? mine->tilePos : unit.tilePos;
CUnit *goal = UnitFindResource(unit, pos, range, unit.CurrentResource, unit.Player->AiEnabled, depot);
goal = UnitFindResource(unit, pos, range, unit.CurrentResource, unit.Player->AiEnabled, depot);
if (goal) {
if (depot) {
DropOutNearest(unit, goal->tilePos + goal->Type->GetHalfTileSize(), depot);
@ -750,7 +770,6 @@ static int WaitInDepot(CUnit &unit)
goal->RefsIncrease();
unit.CurrentOrder()->Arg1.Resource.Mine = goal;
}
unit.CurrentOrder()->SetGoal(goal);
unit.CurrentOrder()->Range = 1;
unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1;
@ -812,6 +831,53 @@ void ResourceGiveUp(CUnit &unit)
unit.ClearAction();
}
/**
** Initialize
**
** return false if action is canceled, true otherwise.
*/
static bool ActionResourceInit(CUnit &unit)
{
Assert(unit.SubAction == SUB_START_RESOURCE);
CUnit *const goal = unit.CurrentOrder()->GetGoal();
int newres;
if (goal) {
newres = goal->Type->GivesResource;
} else {
//FIXME: hardcoded wood
newres = WoodCost;
}
if (newres != unit.CurrentResource) {
DropResource(unit);
}
unit.CurrentResource = newres;
if (newres == 0) {
unit.ResourcesHeld = 0;
ResourceGiveUp(unit);
return false;
}
COrderPtr order = unit.CurrentOrder();
order->CurrentResource = newres;
if (goal && order->Arg1.Resource.Mine != goal) {
CUnit *mine = order->Arg1.Resource.Mine;
if (mine) {
unit.DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
order->Arg1.Resource.Mine = NULL;
}
if (goal->CurrentAction() != UnitActionBuilt) {
unit.AssignWorkerToMine(*goal);
goal->RefsIncrease();
order->Arg1.Resource.Mine = goal;
}
}
UnitGotoGoal(unit, goal, SUB_MOVE_TO_RESOURCE);
return true;
}
/**
** Control the unit action: getting a resource.
**
@ -821,9 +887,6 @@ void ResourceGiveUp(CUnit &unit)
*/
void HandleActionResource(CUnit &unit)
{
int ret;
int newres;
if (unit.Wait) {
// FIXME: show idle animation while we wait?
unit.Wait--;
@ -832,61 +895,35 @@ void HandleActionResource(CUnit &unit)
// Let's start mining.
if (unit.SubAction == SUB_START_RESOURCE) {
CUnit *const goal = unit.CurrentOrder()->GetGoal();
if (goal) {
newres = goal->Type->GivesResource;
} else {
//FIXME: hardcoded wood
newres = WoodCost;
}
if (newres != unit.CurrentResource) {
DropResource(unit);
}
if ((unit.CurrentResource = newres))
{
COrderPtr order = unit.CurrentOrder();
order->CurrentResource = newres;
if (goal && order->Arg1.Resource.Mine != goal) {
CUnit *mine = order->Arg1.Resource.Mine;
if (mine) {
unit.DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
order->Arg1.Resource.Mine = NULL;
}
if (goal->CurrentAction() != UnitActionBuilt) {
unit.AssignWorkerToMine(*goal);
goal->RefsIncrease();
order->Arg1.Resource.Mine = goal;
}
}
UnitGotoGoal(unit, goal, SUB_MOVE_TO_RESOURCE);
//NewResetPath(unit);
//unit.SubAction = SUB_MOVE_TO_RESOURCE;
//unit.Data.Move.Cycles = 0;
} else {
unit.ResourcesHeld = 0;
ResourceGiveUp(unit);
if (ActionResourceInit(unit) == false) {
return;
}
}
// Move to the resource location.
if (unit.SubAction >= SUB_MOVE_TO_RESOURCE
&& unit.SubAction < SUB_UNREACHABLE_RESOURCE) {
// -1 failure, 0 not yet reached, 1 reached
if ((ret = MoveToResource(unit))) {
if (ret == -1) {
// Can't Reach
if (SUB_MOVE_TO_RESOURCE <= unit.SubAction && unit.SubAction < SUB_UNREACHABLE_RESOURCE) {
const int ret = MoveToResource(unit);
switch (ret)
{
case -1: // Can't Reach
{
unit.SubAction++;
unit.Wait = 5;
return;
} else {
// Reached
unit.SubAction = SUB_START_GATHERING;
}
} else {
// Move along.
return;
case 1: // Reached
{
unit.SubAction = SUB_START_GATHERING;
break;
}
case 0: // Move along.
return;
default:
{
Assert(0);
break;
}
}
}
@ -924,19 +961,30 @@ void HandleActionResource(CUnit &unit)
}
// Move back home.
if (unit.SubAction >= SUB_MOVE_TO_DEPOT
&& unit.SubAction < SUB_UNREACHABLE_DEPOT) {
// -1 failure, 0 not yet reached, 1 reached
if ((ret = MoveToDepot(unit))) {
if (ret == -1) {
// Can't Reach
if (SUB_MOVE_TO_DEPOT <= unit.SubAction && unit.SubAction < SUB_UNREACHABLE_DEPOT) {
const int ret = MoveToDepot(unit);
switch (ret)
{
case -1: // Can't Reach
{
unit.SubAction++;
unit.Wait = 5;
} else {
return;
}
case 1: // Reached
{
unit.SubAction = SUB_RETURN_RESOURCE;
return;
}
case 0: // Move along.
return;
default:
{
Assert(0);
return;
}
}
return;
}
// Depot seems to be unreachable

View file

@ -88,7 +88,7 @@ void HandleActionReturnGoods(CUnit &unit)
//unit.CurrentOrder()->Arg1.ResourcePos = -1;
NewResetPath(unit);
unit.SubAction = 70; // FIXME : Define value.
unit.SubAction = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value.
}
//@}

View file

@ -503,12 +503,21 @@ static void HandleUnitAction(CUnit &unit)
//
// Release pending references.
//
if (order->Action == UnitActionResource) {
CUnit *mine = order->Arg1.Resource.Mine;
if (mine) {
unit.DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
order->Arg1.Resource.Mine = NULL;
}
}
if (order->HasGoal()) {
CUnit *goal = order->GetGoal();
// If mining decrease the active count on the resource.
if (order->Action == UnitActionResource) {
if(unit.SubAction == 60) {
// FIXME: SUB_GATHER_RESOURCE ?
if (unit.SubAction == 60 /* SUB_GATHER_RESOURCE */ ) {
goal->Data.Resource.Active--;
Assert(goal->Data.Resource.Active >= 0);
}

View file

@ -844,6 +844,75 @@ static void AiCheckingWork()
-- WORKERS/RESOURCES
----------------------------------------------------------------------------*/
/**
** Assign worker to gather a certain resource from terrain.
**
** @param unit pointer to the unit.
** @param resource resource identification.
**
** @return 1 if the worker was assigned, 0 otherwise.
*/
static int AiAssignHarvesterFromTerrain(CUnit &unit, int resource)
{
// TODO : hardcoded forest
Vec2i forestPos;
// Code for terrain harvesters. Search for piece of terrain to mine.
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 1000, unit.Player, unit.tilePos, &forestPos)) {
CommandResourceLoc(unit, forestPos, FlushCommands);
return 1;
}
// Ask the AI to explore...
AiExplore(unit.tilePos, MapFieldLandUnit);
// Failed.
return 0;
}
/**
** Assign worker to gather a certain resource from Unit.
**
** @param unit pointer to the unit.
** @param resource resource identification.
**
** @return 1 if the worker was assigned, 0 otherwise.
*/
static int AiAssignHarvesterFromUnit(CUnit &unit, int resource)
{
// Find a resource to harvest from.
CUnit *mine = UnitFindResource(unit, unit.tilePos, 1000, resource, true);
if (mine) {
CommandResource(unit, *mine, FlushCommands);
return 1;
}
int exploremask = 0;
for (size_t i = 0; i != UnitTypes.size(); ++i) {
const CUnitType* type = UnitTypes[i];
if (type && type->GivesResource == resource) {
switch (type->UnitType) {
case UnitTypeLand:
exploremask |= MapFieldLandUnit;
break;
case UnitTypeFly:
exploremask |= MapFieldAirUnit;
break;
case UnitTypeNaval:
exploremask |= MapFieldSeaUnit;
break;
default:
Assert(0);
}
}
}
// Ask the AI to explore
AiExplore(unit.tilePos, exploremask);
// Failed.
return 0;
}
/**
** Assign worker to gather a certain resource.
**
@ -854,68 +923,19 @@ static void AiCheckingWork()
*/
static int AiAssignHarvester(CUnit &unit, int resource)
{
ResourceInfo *resinfo;
// It can't.
if (unit.Removed) {
return 0;
}
resinfo = unit.Type->ResInfo[resource];
Assert(resinfo);
if (resinfo->TerrainHarvester) {
Vec2i forestPos;
const ResourceInfo &resinfo = *unit.Type->ResInfo[resource];
Assert(&resinfo);
//
// Code for terrain harvesters. Search for piece of terrain to mine.
//
if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 1000,
unit.Player, unit.tilePos, &forestPos)) {
CommandResourceLoc(unit, forestPos, FlushCommands);
return 1;
}
// Ask the AI to explore...
AiExplore(unit.tilePos, MapFieldLandUnit);
if (resinfo.TerrainHarvester) {
return AiAssignHarvesterFromTerrain(unit, resource);
} else {
int exploremask = 0;
//
// Find a resource to harvest from.
//
CUnit *dest = UnitFindResource(unit, unit.tilePos, 1000, resource, true);
if (dest) {
//FIXME: rb - when workers can speedup building then such assign may be ok.
//if(dest->CurrentAction() == UnitActionBuilt)
//CommandBuildBuilding(unit, dest->tilePos, dest->Type, FlushCommands);
//else
CommandResource(unit, *dest, FlushCommands);
return 1;
}
for (std::vector<CUnitType *>::iterator i = UnitTypes.begin();
i != UnitTypes.end(); i++) {
if (*i && (*i)->GivesResource == resource) {
switch ((*i)->UnitType) {
case UnitTypeLand:
exploremask |= MapFieldLandUnit;
break;
case UnitTypeFly:
exploremask |= MapFieldAirUnit;
break;
case UnitTypeNaval:
exploremask |= MapFieldSeaUnit;
break;
default:
Assert(0);
}
}
}
// Ask the AI to explore
AiExplore(unit.tilePos, exploremask);
return AiAssignHarvesterFromUnit(unit, resource);
}
// Failed.
return 0;
}
static int CmpWorkers(const void *w0,const void *w1) {

View file

@ -566,7 +566,7 @@ public:
union {
Vec2i Patrol; /// position for patroling.
union {
struct {
Vec2i Pos; /// position for terrain resource.
CUnit *Mine;
} Resource;

View file

@ -276,19 +276,19 @@ void CclParseOrder(lua_State *l, COrderPtr order)
} else if (!strcmp(value, "resource-pos")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclGetPos(l, &order->Arg1.Resource.Pos.x ,
&order->Arg1.Resource.Pos.y);
order->Arg1.Resource.Mine = NULL;
CclGetPos(l, &order->Arg1.Resource.Pos.x , &order->Arg1.Resource.Pos.y);
lua_pop(l, 1);
//FIXME: hardcoded wood
Assert(order->CurrentResource && order->CurrentResource == WoodCost);
Assert(order->CurrentResource);
} else if (!strcmp(value, "resource-mine")) {
++j;
lua_rawgeti(l, -1, j + 1);
Vec2i invalidPos = {-1, -1};
order->Arg1.Resource.Pos = invalidPos;
order->Arg1.Resource.Mine = CclGetUnitFromRef(l);
lua_pop(l, 1);
} else if (!strcmp(value, "mine")) {
/* old save format */
} else if (!strcmp(value, "mine")) { /* old save format */
int pos;
++j;
lua_rawgeti(l, -1, j + 1);
@ -303,11 +303,15 @@ void CclParseOrder(lua_State *l, COrderPtr order)
mine = ResourceOnMap(mpos, pos, true);
} while (!mine && pos < MaxCosts);
if (mine) {
Vec2i invalidPos = {-1, -1};
order->Arg1.Resource.Pos = invalidPos;
mine->RefsIncrease();
order->Arg1.Resource.Mine = mine;
order->CurrentResource = pos;
} else {
order->CurrentResource = WoodCost;
order->Arg1.Resource.Mine = NULL;
order->Arg1.Resource.Pos = mpos;
}
} else {

View file

@ -126,9 +126,7 @@ void CUnit::COrder::Release() {
Goal->RefsDecrease();
Goal = NoUnitP;
}
//FIXME: Hardcoded wood
if (Action == UnitActionResource && CurrentResource != WoodCost &&
Arg1.Resource.Mine ) {
if (Action == UnitActionResource && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsDecrease();
Arg1.Resource.Mine = NoUnitP;
}
@ -145,22 +143,13 @@ CUnit::COrder::COrder(const CUnit::COrder &ths): Goal(ths.Goal), Range(ths.Range
memcpy(&Arg1, &ths.Arg1, sizeof(Arg1));
//FIXME: Hardcoded wood
if (Action == UnitActionResource &&
CurrentResource != WoodCost && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsIncrease();
if (Action == UnitActionResource && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsIncrease();
}
}
CUnit::COrder& CUnit::COrder::operator=(const CUnit::COrder &rhs) {
if (this != &rhs) {
//FIXME: Hardcoded wood
if (Action == UnitActionResource &&
CurrentResource != WoodCost && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsDecrease();
}
Action = rhs.Action;
Range = rhs.Range;
MinRange = rhs.MinRange;
@ -172,8 +161,7 @@ CUnit::COrder& CUnit::COrder::operator=(const CUnit::COrder &rhs) {
memcpy(&Arg1, &rhs.Arg1, sizeof(Arg1));
//FIXME: Hardcoded wood
if (Action == UnitActionResource &&
CurrentResource != WoodCost && Arg1.Resource.Mine) {
if (Action == UnitActionResource && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsIncrease();
}
}
@ -1555,8 +1543,26 @@ void CUnit::ChangeOwner(CPlayer &newplayer)
UpdateForNewUnit(*this, 1);
}
#ifdef DEBUG
static bool IsMineAssignedBy(const CUnit &mine, const CUnit &worker)
{
for (CUnit* it = mine.Data.Resource.Workers; it; it = it->NextWorker) {
if (it == &worker) {
return true;
}
}
return false;
}
#endif
void CUnit::AssignWorkerToMine(CUnit &mine)
{
Assert(this->NextWorker == NULL);
Assert(IsMineAssignedBy(mine, *this) == false);
CUnit *head = mine.Data.Resource.Workers;
/*
DebugPrint("%d: Worker [%d] is adding into %s [%d] on %d pos\n"
@ -1573,6 +1579,7 @@ void CUnit::AssignWorkerToMine(CUnit &mine)
void CUnit::DeAssignWorkerFromMine(CUnit &mine)
{
Assert(IsMineAssignedBy(mine, *this) == true);
CUnit *prev = NULL, *worker = mine.Data.Resource.Workers;
/*
DebugPrint("%d: Worker [%d] is removing from %s [%d] left %d units assigned\n"
@ -1581,10 +1588,11 @@ void CUnit::DeAssignWorkerFromMine(CUnit &mine)
_C_ mine.Slot
_C_ mine.Data.Resource.Assigned);
*/
for(int i = 0; NULL != worker; worker = worker->NextWorker,++i)
for (int i = 0; NULL != worker; worker = worker->NextWorker, ++i)
{
if (worker == this) {
CUnit *next = worker->NextWorker;
worker->NextWorker = NULL;
if (prev) {
prev->NextWorker = next;
}
@ -3357,9 +3365,12 @@ void CleanUnits()
int count = NumUnits;
do {
CUnit *unit = Units[count - 1];
if (unit == NULL) {
continue;
}
if (!unit->Destroyed) {
if (//unit->Type->Harvester &&
unit->CurrentAction() == UnitActionResource) {
if (unit->CurrentAction() == UnitActionResource) {
ResourceInfo *resinfo = unit->Type->ResInfo[unit->CurrentResource];
if (resinfo && !resinfo->TerrainHarvester) {
CUnit *mine = unit->CurrentOrder()->Arg1.Resource.Mine;
@ -3371,7 +3382,7 @@ void CleanUnits()
}
}
unit->CurrentOrder()->ClearGoal();
if(!unit->Removed) {
if (!unit->Removed) {
unit->Remove(NULL);
}
UnitClearOrders(*unit);

View file

@ -183,19 +183,20 @@ void SaveOrder(const COrderPtr order, CFile *file)
case UnitActionResource :
case UnitActionReturnGoods :
if (order->CurrentResource) {
file->printf(", \"current-resource\", \"%s\",",
DefaultResourceNames[order->CurrentResource].c_str());
if(order->CurrentResource == WoodCost) {
file->printf(" \"resource-pos\", {%d, %d}",
order->Arg1.Resource.Pos.x, order->Arg1.Resource.Pos.y);
file->printf(", \"current-resource\", \"%s\",", DefaultResourceNames[order->CurrentResource].c_str());
const CUnit *mine = order->Arg1.Resource.Mine;
if (mine == NULL) {
const Vec2i &pos = order->Arg1.Resource.Pos;
file->printf(" \"resource-pos\", {%d, %d}", pos.x, pos.y);
} else {
if (order->Arg1.Resource.Mine->Destroyed) {
if (mine->Destroyed) {
/* this unit is destroyed so it's not in the global unit
* array - this means it won't be saved!!! */
printf ("FIXME: storing destroyed Mine - loading will fail.\n");
}
file->printf(" \"resource-mine\", \"%s\"",
UnitReference(*order->Arg1.Resource.Mine).c_str());
file->printf(" \"resource-mine\", \"%s\"", UnitReference(*mine).c_str());
}
}
break;