From 77334d35331ce8c577f31fe8a9a00b00a7a3a40d Mon Sep 17 00:00:00 2001 From: joris <joris.dauphin@gmail.com> Date: Thu, 23 Feb 2012 16:12:12 +0100 Subject: [PATCH] COrder_{Move, Follow} Fix typo with Unload. --- src/action/action_follow.cpp | 161 ++++++++++++++++++++--------------- src/action/action_move.cpp | 105 +++++++++++------------ src/action/action_unload.cpp | 2 +- src/action/actions.cpp | 6 +- src/include/actions.h | 33 ++++++- src/unit/script_unit.cpp | 8 +- src/unit/unit_save.cpp | 9 -- 7 files changed, 182 insertions(+), 142 deletions(-) diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp index 21408a57c..629499b9a 100644 --- a/src/action/action_follow.cpp +++ b/src/action/action_follow.cpp @@ -41,46 +41,72 @@ #include "unit.h" #include "unittype.h" #include "pathfinder.h" -#include "map.h" #include "actions.h" +#include "iolib.h" +#include "script.h" /*---------------------------------------------------------------------------- --- Variables +-- Functions ----------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------- --- Function -----------------------------------------------------------------------------*/ -/** -** Unit follow action: -** -** @param unit Pointer to unit. -*/ -void HandleActionFollow(COrder& order, CUnit &unit) +/* virtual */ void COrder_Follow::Save(CFile &file, const CUnit &unit) const +{ + file.printf("{\"action-follow\","); + + file.printf(" \"range\", %d,", this->Range); + if (this->HasGoal()) { + CUnit &goal = *this->GetGoal(); + if (goal.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 Goal - loading will fail.\n"); + } + file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str()); + } + file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); + + file.printf(" \"state\", %d,", this->State); + SaveDataMove(file); + + file.printf("}"); +} + +/* virtual */ bool COrder_Follow::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) +{ + if (ParseMoveData(l, j, value)) { + return true; + } else if (!strcmp(value, "state")) { + ++j; + lua_rawgeti(l, -1, j + 1); + this->State = LuaToNumber(l, -1); + lua_pop(l, 1); + } else { + return false; + } + return true; +} + +/* virtual */ bool COrder_Follow::Execute(CUnit &unit) { if (unit.Wait) { unit.Wait--; - return; + return false; } - CUnit *goal = order.GetGoal(); + CUnit *goal = this->GetGoal(); // Reached target - if (order.SubAction.Follow == 128) { + if (this->State == 128) { if (!goal || !goal->IsVisibleAsGoal(*unit.Player)) { DebugPrint("Goal gone\n"); - order.ClearGoal(); - unit.ClearAction(); - return; + return true; } - if (goal->tilePos == order.goalPos) { + if (goal->tilePos == this->goalPos) { // Move to the next order if (unit.Orders.size() > 1) { - order.ClearGoal(); - unit.ClearAction(); - return; + return true; } // Reset frame to still frame while we wait @@ -88,32 +114,30 @@ void HandleActionFollow(COrder& order, CUnit &unit) unit.Frame = unit.Type->StillFrame; UnitUpdateHeading(unit); unit.Wait = 10; - if (order.Range > 1) { - order.Range = 1; - order.SubAction.Follow = 0; + if (this->Range > 1) { + this->Range = 1; + this->State = 0; } - return; + return false; } - order.SubAction.Follow = 0; + this->State = 0; } - if (!order.SubAction.Follow) { // first entry - order.SubAction .Follow= 1; - order.NewResetPath(); - Assert(unit.State == 0); + if (!this->State) { // first entry + this->State = 1; + this->NewResetPath(); } switch (DoActionMove(unit)) { // reached end-point? case PF_UNREACHABLE: // Some tries to reach the goal - if (order.CheckRange()) { - order.Range++; + if (this->CheckRange()) { + this->Range++; break; } // FALL THROUGH case PF_REACHED: { if (!goal) { // goal has died - unit.ClearAction(); - return; + return true; } // Handle Teleporter Units // FIXME: BAD HACK @@ -132,8 +156,6 @@ void HandleActionFollow(COrder& order, CUnit &unit) unit.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2, unit.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2); #endif - unit.ClearAction(); - // FIXME: we must check if the units supports the new order. CUnit &dest = *goal->Goal; @@ -141,26 +163,24 @@ void HandleActionFollow(COrder& order, CUnit &unit) || (dest.NewOrder->Action == UnitActionResource && !unit.Type->Harvester) || (dest.NewOrder->Action == UnitActionAttack && !unit.Type->CanAttack) || (dest.NewOrder->Action == UnitActionBoard && unit.Type->UnitType != UnitTypeLand)) { - unit.ClearAction(); - unit.CurrentOrder()->ClearGoal(); + return true; } else { if (dest.NewOrder->HasGoal()) { if (dest.NewOrder->GetGoal()->Destroyed) { - // FIXME: perhaps we should use another dest? - DebugPrint("Destroyed unit in teleport unit\n"); - dest.NewOrder->ClearGoal(); - dest.NewOrder->Action = UnitActionStill; + delete dest.NewOrder; + dest.NewOrder = NULL; + return true; } } delete unit.CurrentOrder(); unit.Orders[0] = dest.NewOrder->Clone(); unit.CurrentResource = dest.CurrentResource; + return false; } - return; } - order.goalPos = goal->tilePos; - order.SubAction.Follow = 128; + this->goalPos = goal->tilePos; + this->State = 128; } // FALL THROUGH default: @@ -170,36 +190,43 @@ void HandleActionFollow(COrder& order, CUnit &unit) // Target destroyed? if (goal && !goal->IsVisibleAsGoal(*unit.Player)) { DebugPrint("Goal gone\n"); - order.goalPos = goal->tilePos + goal->Type->GetHalfTileSize(); - order.ClearGoal(); + this->goalPos = goal->tilePos + goal->Type->GetHalfTileSize(); + this->ClearGoal(); goal = NoUnitP; - order.NewResetPath(); + this->NewResetPath(); } - if (!unit.Anim.Unbreakable) { - // If our leader is dead or stops or attacks: - // Attack any enemy in reaction range. - // If don't set the goal, the unit can than choose a - // better goal if moving nearer to enemy. - if (unit.Type->CanAttack - && (!goal || goal->CurrentAction() == UnitActionAttack || goal->CurrentAction() == UnitActionStill)) { - goal = AttackUnitsInReactRange(unit); - if (goal) { - // Save current command to come back. - COrder *savedOrder = order.Clone(); + if (unit.Anim.Unbreakable) { + return false; + } + // If our leader is dead or stops or attacks: + // Attack any enemy in reaction range. + // If don't set the goal, the unit can than choose a + // better goal if moving nearer to enemy. + if (unit.Type->CanAttack + && (!goal || goal->CurrentAction() == UnitActionAttack || goal->CurrentAction() == UnitActionStill)) { + CUnit *target = AttackUnitsInReactRange(unit); + if (target) { + // Save current command to come back. + COrder *savedOrder = this->Clone(); - CommandAttack(unit, goal->tilePos, NULL, FlushCommands); + CommandAttack(unit, target->tilePos, NULL, FlushCommands); - if (unit.StoreOrder(savedOrder) == false) { - delete savedOrder; - savedOrder = NULL; - } - // This stops the follow command and the attack is executed - unit.CurrentOrder()->ClearGoal(); - unit.ClearAction(); + if (unit.StoreOrder(savedOrder) == false) { + delete savedOrder; + savedOrder = NULL; } + return true; } } + return false; +} + +void HandleActionFollow(COrder& order, CUnit &unit) +{ + if (order.Execute(unit)) { + unit.ClearAction(); + } } //@} diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp index 864fd5901..9c78f2f1e 100644 --- a/src/action/action_move.cpp +++ b/src/action/action_move.cpp @@ -37,27 +37,43 @@ #include <stdlib.h> #include "stratagus.h" -#include "video.h" + +#include "actions.h" #include "unittype.h" #include "animation.h" -#include "player.h" #include "unit.h" -#include "tileset.h" -#include "map.h" -#include "actions.h" #include "pathfinder.h" #include "sound.h" #include "interface.h" #include "map.h" #include "ai.h" +#include "iolib.h" +#include "script.h" /*---------------------------------------------------------------------------- --- Variables +-- Functions ----------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------- --- Function -----------------------------------------------------------------------------*/ + +/* virtual */ void COrder_Move::Save(CFile &file, const CUnit &unit) const +{ + file.printf("{\"action-move\","); + + file.printf(" \"range\", %d,", this->Range); + file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y); + + SaveDataMove(file); + file.printf("}"); +} + +/* virtual */ bool COrder_Move::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit) +{ + if (ParseMoveData(l, j, value)) { + return true; + } else { + return false; + } +} /** ** Unit moves! Generic function called from other actions. @@ -72,16 +88,17 @@ int DoActionMove(CUnit &unit) Vec2i posd; // movement in tile. int d; Vec2i pos; - int move; - int off; Assert(unit.CanMove()); - if (!unit.Moving && - (unit.Type->Animations->Move != unit.Anim.CurrAnim || !unit.Anim.Wait)) { + + COrder& order = *unit.CurrentOrder(); + + if (!unit.Moving && (unit.Type->Animations->Move != unit.Anim.CurrAnim || !unit.Anim.Wait)) { Assert(!unit.Anim.Unbreakable); // FIXME: So units flying up and down are not affected. - unit.IX = unit.IY = 0; + unit.IX = 0; + unit.IY = 0; UnmarkUnitFieldFlags(unit); d = NextPathElement(unit, &posd.x, &posd.y); @@ -110,14 +127,14 @@ int DoActionMove(CUnit &unit) break; } pos = unit.tilePos; - off = unit.Offset; + int off = unit.Offset; // // Transporter (un)docking? // // FIXME: This is an ugly hack - if (unit.Type->CanTransport() && - ((Map.WaterOnMap(off) && Map.CoastOnMap(pos + posd)) || - (Map.CoastOnMap(off) && Map.WaterOnMap(pos + posd)))) { + if (unit.Type->CanTransport() + && ((Map.WaterOnMap(off) && Map.CoastOnMap(pos + posd)) + || (Map.CoastOnMap(off) && Map.WaterOnMap(pos + posd)))) { PlayUnitSound(unit, VoiceDocking); } @@ -142,12 +159,11 @@ int DoActionMove(CUnit &unit) } else { posd.x = Heading2X[unit.Direction / NextDirection]; posd.y = Heading2Y[unit.Direction / NextDirection]; - d = unit.CurrentOrder()->Data.Move.Length + 1; + d = order.Data.Move.Length + 1; } - unit.CurrentOrder()->Data.Move.Cycles++;//reset have to be manualy controled by caller. - move = UnitShowAnimationScaled(unit, unit.Type->Animations->Move, - Map.Field(unit.Offset)->Cost); + order.Data.Move.Cycles++;//reset have to be manualy controled by caller. + int move = UnitShowAnimationScaled(unit, unit.Type->Animations->Move, Map.Field(unit.Offset)->Cost); unit.IX += posd.x * move; unit.IY += posd.y * move; @@ -161,58 +177,37 @@ int DoActionMove(CUnit &unit) return d; } -/** -** Unit move action: -** -** Move to a place or to a unit (can move). -** Tries 10x to reach the target, note this are the complete tries. -** If the target entered another unit, move to it's position. -** If the target unit is destroyed, continue to move to it's last position. -** -** @param unit Pointer to unit. -*/ -void HandleActionMove(COrder& order, CUnit &unit) -{ - CUnit *goal; +/* virtual */ bool COrder_Move::Execute(CUnit &unit) +{ Assert(unit.CanMove()); if (unit.Wait) { unit.Wait--; - return; + return false; } - // FIXME: (mr-russ) Make a reachable goal here with GoalReachable ... switch (DoActionMove(unit)) { // reached end-point? case PF_UNREACHABLE: - // // Some tries to reach the goal - // - if (order.CheckRange()) { - order.Range++; + if (this->CheckRange()) { + this->Range++; break; } // FALL THROUGH case PF_REACHED: - // Release target, if any. - order.ClearGoal(); - unit.ClearAction(); - return; - + return true; default: break; } + return false; +} - // - // Target destroyed? - // - goal = order.GetGoal(); - if (goal && goal->Destroyed) { - DebugPrint("Goal dead\n"); - order.goalPos = goal->tilePos + goal->Type->GetHalfTileSize(); - order.ClearGoal(); - order.NewResetPath(); +void HandleActionMove(COrder& order, CUnit &unit) +{ + if (order.Execute(unit)) { + unit.ClearAction(); } } diff --git a/src/action/action_unload.cpp b/src/action/action_unload.cpp index cd52b1f84..611181ea1 100644 --- a/src/action/action_unload.cpp +++ b/src/action/action_unload.cpp @@ -63,7 +63,7 @@ file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str()); } file.printf(" \"tile\", {%d, %d}, ", this->goalPos.x, this->goalPos.y); - file.printf("\"state\", %d,\n "); + file.printf("\"state\", %d,\n ", this->State); SaveDataMove(file); file.printf("}"); } diff --git a/src/action/actions.cpp b/src/action/actions.cpp index 15159991a..a66f221a4 100644 --- a/src/action/actions.cpp +++ b/src/action/actions.cpp @@ -192,7 +192,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures /* static */ COrder* COrder::NewActionFollow(CUnit &dest) { - COrder *order = new COrder(UnitActionFollow); + COrder_Follow *order = new COrder_Follow; // Destination could be killed. // Should be handled in action, but is not possible! @@ -210,7 +210,9 @@ unsigned SyncHash; /// Hash calculated to find sync failures /* static */ COrder* COrder::NewActionMove(const Vec2i &pos) { - COrder *order = new COrder(UnitActionMove); + Assert(Map.Info.IsPointOnMap(pos)); + + COrder_Move *order = new COrder_Move; order->goalPos = pos; diff --git a/src/include/actions.h b/src/include/actions.h index f6abac63f..3c793a224 100644 --- a/src/include/actions.h +++ b/src/include/actions.h @@ -171,11 +171,8 @@ public: #if 1 // currently needed for parsing static COrder* NewActionAttack() { return new COrder(UnitActionAttack); } static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); } - static COrder* NewActionFollow() { return new COrder(UnitActionFollow); } - static COrder* NewActionMove() { return new COrder(UnitActionMove); } static COrder* NewActionResource() { return new COrder(UnitActionResource); } static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); } - static COrder* NewActionUnload() { return new COrder(UnitActionUnload); } #endif private: @@ -200,7 +197,6 @@ public: union { int Attack; - int Follow; int Res; } SubAction; @@ -319,6 +315,35 @@ public: virtual bool Execute(CUnit &unit); }; +class COrder_Follow : public COrder +{ +public: + COrder_Follow() : COrder(UnitActionFollow), State(0) {} + + virtual COrder_Follow *Clone() const { return new COrder_Follow(*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 bool Execute(CUnit &unit); +private: + unsigned int State; +}; + +class COrder_Move : public COrder +{ +public: + COrder_Move() : COrder(UnitActionMove) {} + + virtual COrder_Move *Clone() const { return new COrder_Move(*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 bool Execute(CUnit &unit); +}; + + class COrder_Patrol : public COrder { diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp index fea37faaf..c5202b91a 100644 --- a/src/unit/script_unit.cpp +++ b/src/unit/script_unit.cpp @@ -257,7 +257,7 @@ 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.Follow = this->SubAction.Res = LuaToNumber(l, -1); + this->SubAction.Attack = this->SubAction.Res = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "current-resource")) { ++j; @@ -335,9 +335,9 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr) } else if (!strcmp(actiontype, "action-stand-ground")) { *orderPtr = new COrder_Still(true); } else if (!strcmp(actiontype, "action-follow")) { - *orderPtr = COrder::NewActionFollow(); + *orderPtr = new COrder_Follow; } else if (!strcmp(actiontype, "action-move")) { - *orderPtr = COrder::NewActionMove(); + *orderPtr = new COrder_Move; } else if (!strcmp(actiontype, "action-attack")) { *orderPtr = COrder::NewActionAttack(); } else if (!strcmp(actiontype, "action-attack-ground")) { @@ -357,7 +357,7 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr) } else if (!strcmp(actiontype, "action-board")) { *orderPtr = new COrder_Board; } else if (!strcmp(actiontype, "action-unload")) { - *orderPtr = COrder::NewActionUnload(); + *orderPtr = new COrder_Unload; } else if (!strcmp(actiontype, "action-patrol")) { *orderPtr = new COrder_Patrol; } else if (!strcmp(actiontype, "action-build")) { diff --git a/src/unit/unit_save.cpp b/src/unit/unit_save.cpp index 15eb222aa..5dee3daa6 100644 --- a/src/unit/unit_save.cpp +++ b/src/unit/unit_save.cpp @@ -96,12 +96,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file) case UnitActionNone: file.printf("\"action-none\","); break; - case UnitActionFollow: - file.printf("\"action-follow\","); - break; - case UnitActionMove: - file.printf("\"action-move\","); - break; case UnitActionAttack: file.printf("\"action-attack\","); break; @@ -138,9 +132,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file) case UnitActionAttackGround: file.printf(", \"subaction\", %d", order.SubAction.Attack); break; - case UnitActionFollow: - file.printf(", \"subaction\", %d", order.SubAction.Follow); - break; case UnitActionResource: case UnitActionReturnGoods: file.printf(", \"subaction\", %d", order.SubAction.Res);