COrder_Resource (include returnGoods)

Fix COrder_Still::Save
This commit is contained in:
joris 2012-02-25 08:51:34 +01:00
parent d8f56f96c7
commit c648cb13e9
12 changed files with 400 additions and 477 deletions

File diff suppressed because it is too large Load diff

View file

@ -47,7 +47,7 @@
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
#if 0
/**
** Return goods to gold/wood deposit.
**
@ -90,5 +90,5 @@ void HandleActionReturnGoods(COrder& order, CUnit &unit)
order.NewResetPath();
order.SubAction.Res = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value.
}
#endif
//@}

View file

@ -59,7 +59,7 @@ enum {
/* virtual */ void COrder_Still::Save(CFile &file, const CUnit &unit) const
{
if (this->Action == UnitActionStill) {
file.printf("{\"action-still\"");
file.printf("{\"action-still\",");
} else {
file.printf("{\"action-stand-ground\",");
}
@ -76,7 +76,7 @@ enum {
file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
}
file.printf(", \"state\", %d", this->State);
file.printf("\"state\", %d", this->State);
file.printf("}");
}

View file

@ -269,7 +269,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures
/* static */ COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos)
{
COrder *order = new COrder(UnitActionResource);
COrder_Resource *order = new COrder_Resource(harvester);
Vec2i ressourceLoc;
// Find the closest piece of wood next to a tile where the unit can move
@ -286,16 +286,21 @@ unsigned SyncHash; /// Hash calculated to find sync failures
ressourceLoc = pos;
}
order->goalPos = ressourceLoc;
order->CurrentResource = WoodCost; // Hard-coded resource.
order->Range = 1;
return order;
}
/* static */ COrder* COrder::NewActionResource(CUnit &mine)
/* static */ COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine)
{
COrder *order = new COrder(UnitActionResource);
COrder_Resource *order = new COrder_Resource(harvester);
order->SetGoal(&mine);
order->Resource.Mine = &mine;
harvester.AssignWorkerToMine(mine);
order->Resource.Pos = mine.tilePos + mine.Type->GetHalfTileSize();
order->CurrentResource = mine.Type->GivesResource;
order->Range = 1;
return order;
@ -303,16 +308,25 @@ unsigned SyncHash; /// Hash calculated to find sync failures
/* static */ COrder* COrder::NewActionReturnGoods(CUnit *depot)
/* static */ COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot)
{
COrder *order = new COrder(UnitActionReturnGoods);
COrder_Resource *order = new COrder_Resource(harvester);
// Destination could be killed. NETWORK!
if (depot && !depot->Destroyed) {
order->SetGoal(depot);
if (depot && depot->Destroyed) {
depot = NULL;
}
order->Range = 1;
order->CurrentResource = harvester.CurrentResource;
order->DoneHarvesting = true;
if (depot == NULL) {
depot = FindDeposit(harvester, 1000, harvester.CurrentResource);
}
order->Depot = depot;
if (depot) {
order->UnitGotoGoal(harvester, depot, 70); //SUB_MOVE_TO_DEPOT);
}
return order;
}
@ -403,15 +417,9 @@ COrder* COrder::Clone() const
clone->MinRange = this->MinRange;
clone->Width = this->Width;
clone->Height = this->Height;
clone->CurrentResource = this->CurrentResource;
clone->SetGoal(this->Goal);
clone->goalPos = this->goalPos;
memcpy(&clone->Arg1, &this->Arg1, sizeof (clone->Arg1));
memcpy(&clone->Data, &this->Data, sizeof (clone->Data));
//FIXME: Hardcoded wood
if (clone->Action == UnitActionResource && clone->Arg1.Resource.Mine) {
clone->Arg1.Resource.Mine->RefsIncrease();
}
return clone;
}
@ -421,47 +429,6 @@ COrder::~COrder()
Goal->RefsDecrease();
Goal = NoUnitP;
}
if (Action == UnitActionResource && Arg1.Resource.Mine) {
Arg1.Resource.Mine->RefsDecrease();
Arg1.Resource.Mine = NoUnitP;
}
}
void COrder::ReleaseRefs(CUnit &unit)
{
// Release pending references.
if (this->Action == UnitActionResource) {
CUnit *mine = this->Arg1.Resource.Mine;
if (mine) {
unit.DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
this->Arg1.Resource.Mine = NULL;
}
}
if (this->HasGoal()) {
// If mining decrease the active count on the resource.
if (this->Action == UnitActionResource) {
if (this->SubAction.Res == 60 /* SUB_GATHER_RESOURCE */ ) {
CUnit *goal = this->GetGoal();
goal->Resource.Active--;
Assert(goal->Resource.Active >= 0);
}
}
// Still shouldn't have a reference unless attacking
Assert(this->Action != UnitActionStill);
this->ClearGoal();
}
#ifdef DEBUG
else {
if (unit.CurrentResource &&
!unit.Type->ResInfo[unit.CurrentResource]->TerrainHarvester) {
Assert(this->Action != UnitActionResource);
}
}
#endif
}
void COrder::SetGoal(CUnit *const new_goal)
@ -511,21 +478,6 @@ bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/)
case UnitActionTransformInto:
case UnitActionBoard:
case UnitActionUnload:
case UnitActionReturnGoods:
// Unit is working ?
// Maybe AI should cancel action and save resources ???
return true;
case UnitActionResource:
if (SubAction.Res >= 65) {
//Normal return to depot
return true;
}
if (SubAction.Res > 55 &&
unit.ResourcesHeld > 0) {
//escape to Depot with this what you have;
Data.ResWorker.DoneHarvesting = 1;
return true;
}
break;
case UnitActionAttack:
{
@ -1350,8 +1302,8 @@ static void (*HandleActionTable[256])(COrder&, CUnit &) = {
HandleActionNone, // HandleActionPatrol,
HandleActionNone, // HandleActionBuild,
HandleActionNone, // HandleActionRepair,
HandleActionResource,
HandleActionReturnGoods,
HandleActionNone, // HandleActionResource,
HandleActionNone, // HandleActionReturnGoods,
HandleActionNone, // HandleActionTransformInto,
HandleActionNotWritten,

View file

@ -536,7 +536,7 @@ void CommandResource(CUnit &unit, CUnit &dest, int flush)
return;
}
}
*order = COrder::NewActionResource(dest);
*order = COrder::NewActionResource(unit, dest);
ClearSavedAction(unit);
}
@ -568,7 +568,7 @@ void CommandReturnGoods(CUnit &unit, CUnit *goal, int flush)
return;
}
}
*order = COrder::NewActionReturnGoods(goal);
*order = COrder::NewActionReturnGoods(unit, goal);
ClearSavedAction(unit);
}

View file

@ -237,14 +237,13 @@ static int AiBuildBuilding(const CUnitType &type, CUnitType &building, int near_
for (j = 0; j < unit.Orders.size(); ++j) {
int action = unit.Orders[j]->Action;
if (action == UnitActionBuild ||
action == UnitActionRepair ||
action == UnitActionReturnGoods) {
action == UnitActionRepair) {
break;
}
if (action == UnitActionResource) {
const COrder &order = *unit.Orders[j];
const COrder_Resource &order = *static_cast<const COrder_Resource*>(unit.Orders[j]);
if (order.SubAction.Res > 55 /* SUB_START_GATHERING */) {
if (order.IsGatheringStarted()) {
break;
}
}
@ -330,18 +329,10 @@ void AiNewDepotRequest(CUnit &worker) {
_C_ worker->Data.Move.Cycles
);
*/
Assert(worker.CurrentAction() == UnitActionResource);
COrder_Resource &order = *static_cast<COrder_Resource*>(worker.CurrentOrder());
Vec2i pos = {-1, -1};
ResourceInfo *resinfo = worker.Type->ResInfo[worker.CurrentResource];
if (resinfo->TerrainHarvester) {
pos = worker.CurrentOrder()->Arg1.Resource.Pos;
} else {
CUnit *mine = worker.CurrentOrder()->Arg1.Resource.Mine;
if (mine) {
pos = mine->tilePos;
}
}
const Vec2i pos = order.GetHarvestLocation();
if (pos.x != -1 && NULL != FindDepositNearLoc(*worker.Player, pos, 10, worker.CurrentResource)) {
/*
@ -1098,9 +1089,10 @@ static void AiCollectResources()
for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
unit = units_assigned[src_c][k];
COrder &order = *unit->CurrentOrder();
Assert(unit->CurrentAction() == UnitActionResource);
COrder_Resource &order = *static_cast<COrder_Resource*>(unit->CurrentOrder());
if (order.SubAction.Res >= 65 /* SUB_STOP_GATHERING */ ) {
if (order.IsGatheringFinished()) {
//worker returning with resource
continue;
}
@ -1173,9 +1165,9 @@ static int AiRepairBuilding(const CUnitType &type, CUnit &building)
if (unit.CurrentAction() == UnitActionStill) {
table[num++] = &unit;
} else if (unit.CurrentAction() == UnitActionResource) {
COrder &order = *unit.CurrentOrder();
COrder_Resource &order = *static_cast<COrder_Resource*>(unit.CurrentOrder());
if (order.SubAction.Res <= 55 /* SUB_START_GATHERING */) {
if (order.IsGatheringStarted() == false) {
table[num++] = &unit;
}
}

View file

@ -83,7 +83,7 @@ enum UnitAction {
UnitActionRepair, /// unit repairing
UnitActionResource, /// unit harvesting resources
UnitActionReturnGoods, /// unit returning any resource
UnitActionDummy, // UnitActionReturnGoods, /// unit returning any resource
UnitActionTransformInto /// unit transform into type.
};
@ -104,11 +104,10 @@ class COrder
public:
COrder(int action) : Goal(NULL), Range(0), MinRange(0), Width(0),
Height(0), Action(action), Finished(false), CurrentResource(0)
Height(0), Action(action), Finished(false)
{
goalPos.x = -1;
goalPos.y = -1;
memset(&Arg1, 0, sizeof (Arg1));
memset(&SubAction, 0, sizeof (SubAction));
memset(&Data, 0, sizeof (Data));
}
@ -127,7 +126,7 @@ public:
virtual void FillSeenValues(CUnit &unit) const;
virtual void AiUnitKilled(CUnit &unit);
void ReleaseRefs(CUnit &owner);
void ReleaseRefs(CUnit &owner) {}
bool CheckRange() const;
bool HasGoal() const { return Goal != NULL; }
@ -159,8 +158,8 @@ public:
static COrder* NewActionRepair(const Vec2i &pos);
static COrder* NewActionResearch(CUnit &unit, CUpgrade &upgrade);
static COrder* NewActionResource(CUnit &harvester, const Vec2i &pos);
static COrder* NewActionResource(CUnit &mine);
static COrder* NewActionReturnGoods(CUnit *depot);
static COrder* NewActionResource(CUnit &harvester, CUnit &mine);
static COrder* NewActionReturnGoods(CUnit &harvester, CUnit *depot);
static COrder* NewActionSpellCast(SpellType &spell, const Vec2i &pos, CUnit *target);
static COrder* NewActionStandGround();
static COrder* NewActionStill();
@ -172,8 +171,6 @@ public:
#if 1 // currently needed for parsing
static COrder* NewActionAttack() { return new COrder(UnitActionAttack); }
static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); }
static COrder* NewActionResource() { return new COrder(UnitActionResource); }
static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); }
#endif
private:
@ -184,22 +181,13 @@ public:
unsigned int MinRange; /// How far away minimum
unsigned char Width; /// Goal Width (used when Goal is not)
unsigned char Height; /// Goal Height (used when Goal is not)
unsigned char Action; /// global action
const unsigned char Action; /// global action
bool Finished; /// true when order is finish
unsigned char CurrentResource; ///used in UnitActionResource and UnitActionReturnGoods
Vec2i goalPos; /// or tile coordinate of destination
union {
struct {
Vec2i Pos; /// position for terrain resource.
CUnit *Mine;
} Resource;
} Arg1; /// Extra command argument.
union {
int Attack;
int Res;
} SubAction;
@ -211,13 +199,10 @@ public:
#define MAX_PATH_LENGTH 28 /// max length of precalculated path
char Path[MAX_PATH_LENGTH]; /// directions of stored path
} Move; /// ActionMove,...
struct _order_resource_worker_ {
int TimeToHarvest; /// how much time until we harvest some more.
unsigned DoneHarvesting:1; /// Harvesting done, wait for action to break.
} ResWorker; /// Worker harvesting
} Data; /// Storage room for different commands
};
class COrder_Board : public COrder
{
friend COrder* COrder::NewActionBoard(CUnit &unit);
@ -409,6 +394,63 @@ private:
CUpgrade *Upgrade;
};
class COrder_Resource : public COrder
{
friend COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos);
friend COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine);
friend COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot);
public:
COrder_Resource(CUnit &harvester) : COrder(UnitActionResource), worker(&harvester),
CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false)
{
Resource.Pos.x = Resource.Pos.y = -1;
}
~COrder_Resource();
virtual COrder_Resource *Clone() const { return new COrder_Resource(*this); }
virtual void Save(CFile &file, const CUnit &unit) const;
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
virtual void Execute(CUnit &unit);
bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/);
virtual void ReleaseRefs(CUnit &unit);
Vec2i GetHarvestLocation() const; // { return Pos || Mine->tilePos;}
bool IsGatheringStarted() const;
bool IsGatheringFinished() const;
bool IsGatheringWaiting() const;
private:
int MoveToResource_Terrain(CUnit &unit);
int MoveToResource_Unit(CUnit &unit);
int MoveToResource(CUnit &unit);
void UnitGotoGoal(CUnit &unit, CUnit *const goal, int state);
int StartGathering(CUnit &unit);
void LoseResource(CUnit &unit, const CUnit &source);
int GatherResource(CUnit &unit);
int StopGathering(CUnit &unit);
int MoveToDepot(CUnit &unit);
bool WaitInDepot(CUnit &unit);
void DropResource(CUnit &unit);
void ResourceGiveUp(CUnit &unit);
bool ActionResourceInit(CUnit &unit);
private:
CUnitPtr worker; /// unit that own this order.
unsigned char CurrentResource;
struct {
Vec2i Pos; /// position for terrain resource.
CUnitPtr Mine;
} Resource;
CUnitPtr Depot;
int State;
int TimeToHarvest; /// how much time until we harvest some more.
bool DoneHarvesting; /// Harvesting done, wait for action to break.
};
class COrder_SpellCast : public COrder
{
public:
@ -614,8 +656,6 @@ extern void CommandSharedVision(int player, bool state, int opponent);
-- Actions: in action_<name>.c
----------------------------------------------------------------------------*/
extern void DropResource(CUnit &unit);
extern void ResourceGiveUp(CUnit &unit);
extern int GetNumWaitingWorkers(const CUnit &mine);
extern bool AutoAttack(CUnit &unit);
extern bool AutoRepair(CUnit &unit);
@ -632,10 +672,6 @@ typedef void HandleActionFunc(COrder& order, CUnit &unit);
/// Handle command attack
extern HandleActionFunc HandleActionAttack;
/// Handle command resource
extern HandleActionFunc HandleActionResource;
/// Handle command return
extern HandleActionFunc HandleActionReturnGoods;
/*----------------------------------------------------------------------------
-- Actions: actions.c

View file

@ -1246,7 +1246,7 @@ extern void SelectionCclRegister();
// in ccl_unit.c
/// Parse order
extern void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr order);
extern void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr order);
/// register CCL units features
extern void UnitCclRegister();

View file

@ -132,39 +132,6 @@ CUnit *CclGetUnitFromRef(lua_State *l)
return UnitSlots[slot];
}
/**
** Parse res worker data
**
** @param l Lua state.
** @param unit Unit pointer which should be filled with the data.
*/
static void CclParseResWorker(lua_State *l, COrderPtr order)
{
const char *value;
int args;
int j;
if (!lua_istable(l, -1)) {
LuaError(l, "incorrect argument");
}
args = lua_objlen(l, -1);
for (j = 0; j < args; ++j) {
lua_rawgeti(l, -1, j + 1);
value = LuaToString(l, -1);
lua_pop(l, 1);
++j;
if (!strcmp(value, "time-to-harvest")) {
lua_rawgeti(l, -1, j + 1);
order->Data.ResWorker.TimeToHarvest = LuaToNumber(l, -1);
lua_pop(l, 1);
} else if (!strcmp(value, "done-harvesting")) {
order->Data.ResWorker.DoneHarvesting = 1;
--j;
} else {
LuaError(l, "ParseResWorker: Unsupported tag: %s" _C_ value);
}
}
}
bool COrder::ParseGenericData(lua_State *l, int &j, const char *value)
{
@ -261,59 +228,8 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
} else if (!strcmp(value, "subaction")) {
++j;
lua_rawgeti(l, -1, j + 1);
this->SubAction.Attack = this->SubAction.Res = LuaToNumber(l, -1);
this->SubAction.Attack = LuaToNumber(l, -1);
lua_pop(l, 1);
} else if (!strcmp(value, "current-resource")) {
++j;
lua_rawgeti(l, -1, j + 1);
this->CurrentResource = CclGetResourceByName(l);
lua_pop(l, 1);
} else if (!strcmp(value, "resource-pos")) {
++j;
lua_rawgeti(l, -1, j + 1);
this->Arg1.Resource.Mine = NULL;
CclGetPos(l, &this->Arg1.Resource.Pos.x , &this->Arg1.Resource.Pos.y);
lua_pop(l, 1);
Assert(this->CurrentResource);
} else if (!strcmp(value, "resource-mine")) {
++j;
lua_rawgeti(l, -1, j + 1);
Vec2i invalidPos = {-1, -1};
this->Arg1.Resource.Pos = invalidPos;
this->Arg1.Resource.Mine = CclGetUnitFromRef(l);
lua_pop(l, 1);
} else if (!strcmp(value, "data-res-worker")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclParseResWorker(l, this);
lua_pop(l, 1);
} else if (!strcmp(value, "mine")) { /* old save format */
int pos;
++j;
lua_rawgeti(l, -1, j + 1);
pos = LuaToNumber(l, -1);
lua_pop(l, 1);
const Vec2i mpos = {pos >> 16, pos & 0xFFFF};
CUnit *mine = NULL;
pos = 0;
do {
pos++;
mine = ResourceOnMap(mpos, pos, true);
} while (!mine && pos < MaxCosts);
if (mine) {
Vec2i invalidPos = {-1, -1};
this->Arg1.Resource.Pos = invalidPos;
mine->RefsIncrease();
this->Arg1.Resource.Mine = mine;
this->CurrentResource = pos;
} else {
this->CurrentResource = WoodCost;
this->Arg1.Resource.Mine = NULL;
this->Arg1.Resource.Pos = mpos;
}
} else {
return false;
}
@ -326,7 +242,7 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
** @param l Lua state.
** @param order OUT: resulting order.
*/
void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr *orderPtr)
{
const int args = lua_objlen(l, -1);
@ -369,9 +285,7 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
} else if (!strcmp(actiontype, "action-repair")) {
*orderPtr = new COrder_Repair;
} else if (!strcmp(actiontype, "action-resource")) {
*orderPtr = COrder::NewActionResource();
} else if (!strcmp(actiontype, "action-return-goods")) {
*orderPtr = COrder::NewActionReturnGoods();
*orderPtr = new COrder_Resource(unit);
} else if (!strcmp(actiontype, "action-transform-into")) {
*orderPtr = new COrder_TransformInto;
} else {

View file

@ -376,7 +376,6 @@ bool CUnit::RestoreOrder()
//copy
this->Orders.insert(this->Orders.begin() + 1, this->SavedOrder);
this->CurrentResource = this->SavedOrder->CurrentResource;
this->SavedOrder = NULL;
return true;
@ -3410,18 +3409,6 @@ void CleanUnits()
continue;
}
if (!unit->Destroyed) {
if (unit->CurrentAction() == UnitActionResource) {
ResourceInfo *resinfo = unit->Type->ResInfo[unit->CurrentResource];
if (resinfo && !resinfo->TerrainHarvester) {
CUnit *mine = unit->CurrentOrder()->Arg1.Resource.Mine;
if (mine && !mine->Destroyed) {
unit->DeAssignWorkerFromMine(*mine);
mine->RefsDecrease();
unit->CurrentOrder()->Arg1.Resource.Mine = NULL;
}
}
}
unit->CurrentOrder()->ClearGoal();
if (!unit->Removed) {
unit->Remove(NULL);
}

View file

@ -819,11 +819,6 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder
dest = true;
break;
case UnitActionReturnGoods:
e_color = color = ColorYellow;
dest = true;
break;
default:
e_color = color = ColorGray;
DebugPrint("Unknown action %d\n" _C_ order.Action);

View file

@ -102,12 +102,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionAttackGround:
file.printf("\"action-attack-ground\",");
break;
case UnitActionResource:
file.printf("\"action-resource\",");
break;
case UnitActionReturnGoods:
file.printf("\"action-return-goods\",");
break;
default:
DebugPrint("Unknown action in order\n");
}
@ -137,52 +131,16 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionAttackGround:
file.printf(", \"subaction\", %d", order.SubAction.Attack);
break;
case UnitActionResource:
case UnitActionReturnGoods:
file.printf(", \"subaction\", %d", order.SubAction.Res);
break;
}
// Extra arg.
switch (order.Action) {
case UnitActionResource :
case UnitActionReturnGoods :
if (order.CurrentResource) {
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 (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(*mine).c_str());
}
}
break;
default:
break;
}
//
// Order data part
//
switch (order.Action) {
case UnitActionStill:
// FIXME: support other resource types
break;
case UnitActionResource:
file.printf(", \"data-res-worker\", {\"time-to-harvest\", %d", order.Data.ResWorker.TimeToHarvest);
if (order.Data.ResWorker.DoneHarvesting) {
file.printf(", \"done-harvesting\"");
}
file.printf("}");
break;
case UnitActionBuilt:
case UnitActionResearch:
case UnitActionUpgradeTo: