Fix ActionRessource and DeassignWorkerFromMine
This commit is contained in:
parent
04c20eb84d
commit
09f642805e
8 changed files with 318 additions and 225 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -566,7 +566,7 @@ public:
|
|||
|
||||
union {
|
||||
Vec2i Patrol; /// position for patroling.
|
||||
union {
|
||||
struct {
|
||||
Vec2i Pos; /// position for terrain resource.
|
||||
CUnit *Mine;
|
||||
} Resource;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue