Some more COrder_ (Die, Patrol, StandGroung, Still)

This commit is contained in:
joris 2012-02-22 08:45:58 +01:00
parent 58f777c425
commit c3dea78611
13 changed files with 492 additions and 527 deletions

View file

@ -350,10 +350,6 @@ void HandleActionBuild(COrder& /*order*/, CUnit &unit)
// Action_built
//////////////////////////
/* virtual */ COrder_Built *COrder_Built::Clone() const
{
return new COrder_Built(*this);
}
/* virtual */ void COrder_Built::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-built\", ");

View file

@ -39,15 +39,81 @@
#include "stratagus.h"
#include "unittype.h"
#include "animation.h"
#include "player.h"
#include "unit.h"
#include "actions.h"
#include "map.h"
#include "iolib.h"
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
/* virtual */ void COrder_Die::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-die\"}");
}
/* virtual */ bool COrder_Die::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
return false;
}
static bool AnimateActionDie(CUnit &unit)
{
const CAnimations *animations = unit.Type->Animations;
if (animations == NULL) {
return false;
}
if (animations->Death[unit.DamagedType]) {
UnitShowAnimation(unit, animations->Death[unit.DamagedType]);
return true;
} else if (animations->Death[ANIMATIONS_DEATHTYPES]) {
UnitShowAnimation(unit, animations->Death[ANIMATIONS_DEATHTYPES]);
return true;
}
return false;
}
/* virtual */ bool COrder_Die::Execute(CUnit &unit)
{
// Show death animation
if (AnimateActionDie(unit) == false) {
// some units has no death animation
unit.Anim.Unbreakable = 0;
}
if (unit.Anim.Unbreakable) {
return false;
}
CUnitType &type = *unit.Type;
// Die sequence terminated, generate corpse.
if (type.CorpseType == NULL) {
unit.Remove(NULL);
unit.Release();
return false;
}
CUnitType &corpseType = *type.CorpseType;
Assert(type.TileWidth >= corpseType.TileWidth && type.TileHeight >= corpseType.TileHeight);
// Update sight for new corpse
// We have to unmark BEFORE changing the type.
// Always do that, since types can have different vision properties.
unit.Remove(NULL);
unit.Type = &corpseType;
unit.Stats = &type.Stats[unit.Player->Index];
unit.Place(unit.tilePos);
unit.SubAction = 0;
unit.Frame = 0;
UnitUpdateHeading(unit);
AnimateActionDie(unit); // with new corpse.
return false;
}
/**
** Unit dies!
**
@ -57,48 +123,8 @@ void HandleActionDie(COrder& order, CUnit &unit)
{
Assert(order.Action == UnitActionDie);
// Show death animation
if (unit.Type->Animations && unit.Type->Animations->Death[unit.DamagedType]) {
UnitShowAnimation(unit, unit.Type->Animations->Death[unit.DamagedType]);
}
else if (unit.Type->Animations && unit.Type->Animations->Death[ANIMATIONS_DEATHTYPES]) {
UnitShowAnimation(unit, unit.Type->Animations->Death[ANIMATIONS_DEATHTYPES]);
} else {
// some units has no death animation
unit.Anim.Unbreakable = 0;
}
if (unit.Anim.Unbreakable) {
return;
}
// Die sequence terminated, generate corpse.
if (!unit.Type->CorpseType) {
// We may be in the cache if we just finished out death animation
// even though there is no corpse.
// (unit.Type->Animations && unit.Type->Animations->Death)
// Remove us from the map to be safe
unit.Remove(NULL);
unit.Release();
return;
}
Assert(unit.Type->TileWidth >= unit.Type->CorpseType->TileWidth &&
unit.Type->TileHeight >= unit.Type->CorpseType->TileHeight);
// Update sight for new corpse
// We have to unmark BEFORE changing the type.
// Always do that, since types can have different vision properties.
unit.Remove(NULL);
unit.Type = unit.Type->CorpseType;
unit.Stats = &unit.Type->Stats[unit.Player->Index];
unit.Place(unit.tilePos);
unit.SubAction = 0;
unit.Frame = 0;
UnitUpdateHeading(unit);
if (unit.Type->Animations && unit.Type->Animations->Death[ANIMATIONS_DEATHTYPES]) {
UnitShowAnimation(unit, unit.Type->Animations->Death[ANIMATIONS_DEATHTYPES]);
if (order.Execute(unit)) {
unit.ClearAction();
}
}

View file

@ -42,26 +42,97 @@
#include "actions.h"
#include "pathfinder.h"
#include "map.h"
#include "iolib.h"
#include "script.h"
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
extern bool AutoRepair(CUnit &unit);
extern bool AutoCast(CUnit &unit);
/**
** Swap the patrol points.
*/
static void SwapPatrolPoints(CUnit &unit)
/* virtual */ void COrder_Patrol::Save(CFile &file, const CUnit &unit) const
{
COrderPtr order = unit.CurrentOrder();
file.printf("{\"action-patrol\",");
std::swap(order->Arg1.Patrol.x, order->goalPos.x);
std::swap(order->Arg1.Patrol.y, order->goalPos.y);
file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
file.printf(" \"range\", %d,", this->Range);
unit.CurrentOrder()->Data.Move.Cycles = 0; //moving counter
unit.CurrentOrder()->NewResetPath();
file.printf(" \"patrol\", {%d, %d},\n ", this->WayPoint.x, this->WayPoint.y);
SaveDataMove(file);
file.printf("}");
}
/* virtual */ bool COrder_Patrol::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
if (ParseMoveData(l, j, value)) {
return true;
} else if (!strcmp(value, "patrol")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclGetPos(l, &this->WayPoint.x , &this->WayPoint.y);
lua_pop(l, 1);
} else {
return false;
}
return true;
}
/* virtual */ bool COrder_Patrol::Execute(CUnit &unit)
{
if (unit.Wait) {
unit.Wait--;
return false;
}
if (!unit.SubAction) { // first entry.
this->Data.Move.Cycles = 0; //moving counter
this->NewResetPath();
unit.SubAction = 1;
}
switch (DoActionMove(unit)) {
case PF_FAILED:
unit.SubAction = 1;
break;
case PF_UNREACHABLE:
// Increase range and try again
unit.SubAction = 1;
if (this->CheckRange()) {
this->Range++;
break;
}
// FALL THROUGH
case PF_REACHED:
unit.SubAction = 1;
this->Range = 0;
std::swap(this->WayPoint, this->goalPos);
this->Data.Move.Cycles = 0; //moving counter
this->NewResetPath();
break;
case PF_WAIT:
// Wait for a while then give up
unit.SubAction++;
if (unit.SubAction == 5) {
unit.SubAction = 1;
this->Range = 0;
std::swap(this->WayPoint, this->goalPos);
this->Data.Move.Cycles = 0; //moving counter
this->NewResetPath();
}
break;
default: // moving
unit.SubAction = 1;
break;
}
if (!unit.Anim.Unbreakable) {
if (AutoAttack(unit, false) || AutoRepair(unit) || AutoCast(unit)) {
return true;
}
}
return false;
}
/**
@ -77,76 +148,10 @@ static void SwapPatrolPoints(CUnit &unit)
*/
void HandleActionPatrol(COrder& order, CUnit &unit)
{
if (unit.Wait) {
unit.Wait--;
return;
}
Assert(order.Action == UnitActionPatrol);
if (!unit.SubAction) { // first entry.
order.Data.Move.Cycles = 0; //moving counter
order.NewResetPath();
unit.SubAction = 1;
}
switch (DoActionMove(unit)) {
case PF_FAILED:
unit.SubAction = 1;
break;
case PF_UNREACHABLE:
// Increase range and try again
unit.SubAction = 1;
if (order.CheckRange()) {
order.Range++;
break;
}
// FALL THROUGH
case PF_REACHED:
unit.SubAction = 1;
order.Range = 0;
SwapPatrolPoints(unit);
break;
case PF_WAIT:
// Wait for a while then give up
unit.SubAction++;
if (unit.SubAction == 5) {
unit.SubAction = 1;
order.Range = 0;
SwapPatrolPoints(unit);
}
break;
default: // moving
unit.SubAction = 1;
break;
}
if (!unit.Anim.Unbreakable) {
//
// Attack any enemy in reaction range.
// If don't set the goal, the unit can then choose a
// better goal if moving nearer to enemy.
//
if (unit.Type->CanAttack) {
const CUnit *goal = AttackUnitsInReactRange(unit);
if (goal) {
// Save current command to come back.
COrder *savedOrder = order.Clone();
DebugPrint("Patrol attack %d\n" _C_ UnitNumber(*goal));
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
savedOrder = NULL;
}
unit.ClearAction();
return;
}
}
// Look for something to auto repair or auto cast
if (AutoRepair(unit) || AutoCast(unit)) {
return;
}
if (order.Execute(unit)) {
unit.ClearAction();
}
}

View file

@ -54,11 +54,6 @@
-- Functions
----------------------------------------------------------------------------*/
/* virtual */ COrder_Research *COrder_Research::Clone() const
{
return new COrder_Research(*this);
}
/* virtual */ void COrder_Research::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-research\"");

View file

@ -62,11 +62,6 @@
-- Functions
----------------------------------------------------------------------------*/
/* virtual */ COrder_SpellCast *COrder_SpellCast::Clone() const
{
return new COrder_SpellCast(*this);
}
/* virtual */ void COrder_SpellCast::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-spell-cast\",");
@ -94,7 +89,9 @@
/* virtual */ bool COrder_SpellCast::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
if (!strcmp(value, "spell")) {
if (ParseMoveData(l, j, value)) {
return true;
} else if (!strcmp(value, "spell")) {
++j;
lua_rawgeti(l, -1, j + 1);
this->Spell = SpellTypeByIdent(LuaToString(l, -1));

View file

@ -38,19 +38,53 @@
#include "stratagus.h"
#include "unit.h"
#include "actions.h"
#include "iolib.h"
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
/* virtual */ void COrder_StandGround::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-stand-ground\"");
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("}");
}
/* virtual */ bool COrder_StandGround::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
return false;
}
/* virtual */ bool COrder_StandGround::Execute(CUnit &unit)
{
ActionStillGeneric(unit, true);
return false;
}
/**
** Unit stands ground!
**
** @param unit Action handled for this unit pointer.
*/
void HandleActionStandGround(COrder& /*order*/, CUnit &unit)
void HandleActionStandGround(COrder& order, CUnit &unit)
{
ActionStillGeneric(unit, true);
Assert(order.Action == UnitActionStandGround);
if (order.Execute(unit)) {
unit.ClearAction();
}
}
//@}

View file

@ -47,11 +47,35 @@
#include "pathfinder.h"
#include "spells.h"
#include "player.h"
#include "iolib.h"
#define SUB_STILL_INIT 0
#define SUB_STILL_STANDBY 1
#define SUB_STILL_ATTACK 2
/* virtual */ void COrder_Still::Save(CFile &file, const CUnit &unit) const
{
file.printf("{\"action-still\"");
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("}");
}
/* virtual */ bool COrder_Still::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
return false;
}
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
@ -239,66 +263,81 @@ bool AutoRepair(CUnit &unit)
{
const int repairRange = unit.Type->Variable[AUTOREPAIRRANGE_INDEX].Value;
if (unit.AutoRepair && repairRange) {
CUnit *repairedUnit = UnitToRepairInRange(unit, repairRange);
if (repairedUnit != NoUnitP) {
const Vec2i invalidPos = {-1, -1};
COrder *savedOrder = unit.CurrentOrder()->Clone();
//Command* will clear unit.SavedOrder
CommandRepair(unit, invalidPos, repairedUnit, FlushCommands);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
savedOrder = NULL;
}
return true;
}
if (unit.AutoRepair == false || repairRange == 0) {
return false;
}
return false;
CUnit *repairedUnit = UnitToRepairInRange(unit, repairRange);
if (repairedUnit == NoUnitP) {
return false;
}
const Vec2i invalidPos = {-1, -1};
COrder *savedOrder = unit.CurrentOrder()->Clone();
//Command* will clear unit.SavedOrder
CommandRepair(unit, invalidPos, repairedUnit, FlushCommands);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
savedOrder = NULL;
}
return true;
}
/**
** Auto attack nearby units if possible
*/
static bool AutoAttack(CUnit &unit, bool stand_ground)
bool AutoAttack(CUnit &unit, bool stand_ground)
{
CUnit *goal;
// Cowards and invisible units don't attack unless ordered.
if (unit.IsAgressive()) {
// Normal units react in reaction range.
if (!stand_ground && !unit.Removed && unit.CanMove()) {
if ((goal = AttackUnitsInReactRange(unit))) {
// Weak goal, can choose other unit, come back after attack
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
COrder *savedOrder = COrder::NewActionAttack(unit, unit.tilePos);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
}
return true;
}
// Removed units can only attack in AttackRange, from bunker
} else {
if ((goal = AttackUnitsInRange(unit))) {
CUnit *temp = unit.CurrentOrder()->GetGoal();
if (temp && temp->CurrentAction() == UnitActionDie) {
unit.CurrentOrder()->ClearGoal();
temp = NoUnitP;
}
if (unit.SubAction < SUB_STILL_ATTACK || temp != goal) {
// New target.
unit.CurrentOrder()->SetGoal(goal);
unit.State = 0;
unit.SubAction = SUB_STILL_ATTACK; // Mark attacking.
UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
}
return true;
}
}
if (unit.Type->CanAttack == false) {
return false;
}
return false;
if (stand_ground || unit.Removed || unit.CanMove() == false) {
// Removed units can only attack in AttackRange, from bunker
CUnit *goal = AttackUnitsInRange(unit);
if (goal == NULL) {
return false;
}
CUnit *temp = unit.CurrentOrder()->GetGoal();
if (temp && temp->CurrentAction() == UnitActionDie) {
unit.CurrentOrder()->ClearGoal();
temp = NoUnitP;
}
if (unit.SubAction < SUB_STILL_ATTACK || temp != goal) {
// New target.
unit.CurrentOrder()->SetGoal(goal);
unit.State = 0;
unit.SubAction = SUB_STILL_ATTACK; // Mark attacking.
UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
}
return true;
}
// Normal units react in reaction range.
CUnit *goal = AttackUnitsInReactRange(unit);
if (goal == NULL) {
return false;
}
COrder *savedOrder;
if (unit.SavedOrder != NULL) {
savedOrder = unit.SavedOrder->Clone();
} else if (unit.CurrentAction() == UnitActionStill) {
savedOrder = COrder::NewActionAttack(unit, unit.tilePos);
} else {
savedOrder = unit.CurrentOrder()->Clone();
}
// Weak goal, can choose other unit, come back after attack
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
}
return true;
}
void AutoAttack(CUnit &unit, CUnitCache &targets, bool stand_ground)
@ -360,8 +399,7 @@ void ActionStillGeneric(CUnit &unit, bool stand_ground)
return;
}
switch (unit.SubAction)
{
switch (unit.SubAction) {
case SUB_STILL_INIT: //first entry
MapMarkUnitGuard(unit);
unit.SubAction = SUB_STILL_STANDBY;
@ -378,7 +416,7 @@ void ActionStillGeneric(CUnit &unit, bool stand_ground)
return;
}
if (AutoAttack(unit, stand_ground)
if ((unit.IsAgressive() && AutoAttack(unit, stand_ground))
|| AutoCast(unit)
|| AutoRepair(unit)
|| MoveRandomly(unit)) {
@ -391,9 +429,18 @@ void ActionStillGeneric(CUnit &unit, bool stand_ground)
**
** @param unit Unit pointer for still action.
*/
void HandleActionStill(COrder& /*order*/, CUnit &unit)
void HandleActionStill(COrder& order, CUnit &unit)
{
ActionStillGeneric(unit, false);
Assert(order.Action == UnitActionStill);
order.Execute(unit);
}
/* virtual */ bool COrder_Still::Execute(CUnit &unit)
{
ActionStillGeneric(unit, false);
return false;
}
//@}

View file

@ -92,9 +92,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionAttack(const CUnit &attacker, CUnit &target)
{
COrder *order = new COrder;
order->Action = UnitActionAttack;
COrder *order = new COrder(UnitActionAttack);
if (target.Destroyed) {
order->goalPos = target.tilePos + target.Type->GetHalfTileSize();
@ -111,9 +109,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
{
Assert(Map.Info.IsPointOnMap(dest));
COrder *order = new COrder;
order->Action = UnitActionAttack;
COrder *order = new COrder(UnitActionAttack);
if (Map.WallOnMap(dest) && Map.IsFieldExplored(*attacker.Player, dest)) {
// FIXME: look into action_attack.cpp about this ugly problem
@ -128,9 +124,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionAttackGround(const CUnit &attacker, const Vec2i &dest)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionAttackGround);
order->Action = UnitActionAttackGround;
order->goalPos = dest;
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
@ -141,9 +136,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionBoard(CUnit &unit)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionBoard);
order->Action = UnitActionBoard;
order->SetGoal(&unit);
order->Range = 1;
@ -153,9 +147,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionBuild(const CUnit &builder, const Vec2i &pos, CUnitType &building)
{
COrder *order = new COrder;
order->Action = UnitActionBuild;
COrder *order = new COrder(UnitActionBuild);
order->goalPos = pos;
order->Width = building.TileWidth;
@ -200,17 +192,13 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionDie()
{
COrder *order = new COrder;
order->Action = UnitActionDie;
return order;
return new COrder_Die;
}
/* static */ COrder* COrder::NewActionFollow(CUnit &dest)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionFollow);
order->Action = UnitActionFollow;
// Destination could be killed.
// Should be handled in action, but is not possible!
// Unit::Refs is used as timeout counter.
@ -227,9 +215,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionMove(const Vec2i &pos)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionMove);
order->Action = UnitActionMove;
order->goalPos = pos;
return order;
@ -241,20 +228,18 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
Assert(Map.Info.IsPointOnMap(currentPos));
Assert(Map.Info.IsPointOnMap(dest));
COrder *order = new COrder;
COrder_Patrol *order = new COrder_Patrol();
order->Action = UnitActionPatrol;
order->goalPos = dest;
order->Arg1.Patrol = currentPos;
order->WayPoint = currentPos;
return order;
}
/* static */ COrder* COrder::NewActionRepair(CUnit &unit, CUnit &target)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionRepair);
order->Action = UnitActionRepair;
if (target.Destroyed) {
order->goalPos = target.tilePos + target.Type->GetHalfTileSize();
} else {
@ -268,9 +253,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
{
Assert(Map.Info.IsPointOnMap(pos));
COrder *order = new COrder;
COrder *order = new COrder(UnitActionRepair);
order->Action = UnitActionRepair;
order->goalPos = pos;
return order;
}
@ -293,11 +277,9 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionResource);
Vec2i ressourceLoc;
order->Action = UnitActionResource;
// Find the closest piece of wood next to a tile where the unit can move
if (!FindTerrainType(0, (harvester.Type->MovementMask), 1, 20, harvester.Player, pos, &ressourceLoc)) {
DebugPrint("FIXME: Give up???\n");
@ -319,9 +301,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionResource(CUnit &mine)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionResource);
order->Action = UnitActionResource;
order->SetGoal(&mine);
order->Range = 1;
@ -332,9 +313,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionReturnGoods(CUnit *depot)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionReturnGoods);
order->Action = UnitActionReturnGoods;
// Destination could be killed. NETWORK!
if (depot && !depot->Destroyed) {
order->SetGoal(depot);
@ -374,19 +354,12 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionStandGround()
{
COrder *order = new COrder;
order->Action = UnitActionStandGround;
return order;
return new COrder_StandGround;
}
/* static */ COrder* COrder::NewActionStill()
{
COrder *order = new COrder;
order->Action = UnitActionStill;
return order;
return new COrder_Still;
}
@ -394,9 +367,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionTrain(CUnit &trainer, CUnitType &type)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionTrain);
order->Action = UnitActionTrain;
order->Arg1.Type = &type;
// FIXME: if you give quick an other order, the resources are lost!
trainer.Player->SubUnitType(type);
@ -406,9 +378,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionTransformInto(CUnitType &type)
{
COrder *order = new COrder;
order->Action = UnitActionTransformInto;
COrder *order = new COrder(UnitActionTransformInto);
order->Arg1.Type = &type;
@ -417,9 +387,8 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionUnload(const Vec2i &pos, CUnit *what)
{
COrder *order = new COrder;
COrder *order = new COrder(UnitActionUnload);
order->Action = UnitActionUnload;
order->goalPos = pos;
if (what && !what->Destroyed) {
order->SetGoal(what);
@ -430,9 +399,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
/* static */ COrder* COrder::NewActionUpgradeTo(CUnit &unit, CUnitType &type)
{
COrder *order = new COrder;
order->Action = UnitActionUpgradeTo;
COrder *order = new COrder(UnitActionUpgradeTo);
// FIXME: if you give quick an other order, the resources are lost!
unit.Player->SubUnitType(type);
@ -441,152 +408,10 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
return order;
}
#if 1 // currently needed for parsing
/* static */ COrder* COrder::NewActionAttack()
{
COrder *order = new COrder;
order->Action = UnitActionAttack;
return order;
}
/* static */ COrder* COrder::NewActionAttackGround()
{
COrder *order = new COrder;
order->Action = UnitActionAttackGround;
return order;
}
/* static */ COrder* COrder::NewActionBoard()
{
COrder *order = new COrder;
order->Action = UnitActionBoard;
return order;
}
/* static */ COrder* COrder::NewActionBuild()
{
COrder *order = new COrder;
order->Action = UnitActionBuild;
return order;
}
/* static */ COrder* COrder::NewActionBuilt()
{
COrder *order = new COrder_Built;
order->Action = UnitActionBuilt;
return order;
}
/* static */ COrder* COrder::NewActionFollow()
{
COrder *order = new COrder;
order->Action = UnitActionFollow;
return order;
}
/* static */ COrder* COrder::NewActionMove()
{
COrder *order = new COrder;
order->Action = UnitActionMove;
return order;
}
/* static */ COrder* COrder::NewActionPatrol()
{
COrder *order = new COrder;
order->Action = UnitActionPatrol;
return order;
}
/* static */ COrder* COrder::NewActionRepair()
{
COrder *order = new COrder;
order->Action = UnitActionRepair;
return order;
}
/* static */ COrder* COrder::NewActionResearch()
{
COrder_Research *order = new COrder_Research;
order->Action = UnitActionResearch;
return order;
}
/* static */ COrder* COrder::NewActionResource()
{
COrder *order = new COrder;
order->Action = UnitActionResource;
return order;
}
/* static */ COrder* COrder::NewActionReturnGoods()
{
COrder *order = new COrder;
order->Action = UnitActionReturnGoods;
return order;
}
/* static */ COrder* COrder::NewActionSpellCast()
{
COrder *order = new COrder_SpellCast;
order->Action = UnitActionSpellCast;
return order;
}
/* static */ COrder* COrder::NewActionTrain()
{
COrder *order = new COrder;
order->Action = UnitActionTrain;
return order;
}
/* static */ COrder* COrder::NewActionTransformInto()
{
COrder *order = new COrder;
order->Action = UnitActionTransformInto;
return order;
}
/* static */ COrder* COrder::NewActionUnload()
{
COrder *order = new COrder;
order->Action = UnitActionUnload;
return order;
}
/* static */ COrder* COrder::NewActionUpgradeTo()
{
COrder *order = new COrder;
order->Action = UnitActionUpgradeTo;
return order;
}
#endif
COrder* COrder::Clone() const
{
COrder *clone = new COrder();
COrder *clone = new COrder(this->Action);
clone->Action = this->Action;
clone->Range = this->Range;
clone->MinRange = this->MinRange;
clone->Width = this->Width;

View file

@ -102,8 +102,8 @@ struct lua_State;
class COrder
{
public:
COrder() : Goal(NULL), Range(0), MinRange(0), Width(0),
Height(0), Action(UnitActionNone), CurrentResource(0)
COrder(int action) : Goal(NULL), Range(0), MinRange(0), Width(0),
Height(0), Action(action), CurrentResource(0)
{
goalPos.x = -1;
goalPos.y = -1;
@ -154,7 +154,7 @@ public:
*/
void NewResetPath() { Data.Move.Fast = 1; Data.Move.Length = 0; }
void SaveDataMove(CFile &file) const;
bool ParseMoveData(lua_State *l, int &j, const char *value);
bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/);
void AiUnitKilled(CUnit &unit);
@ -165,7 +165,6 @@ public:
static COrder* NewActionAttackGround(const CUnit &attacker, const Vec2i &dest);
static COrder* NewActionBoard(CUnit &unit);
static COrder* NewActionBuild(const CUnit &builder, const Vec2i &pos, CUnitType &building);
static COrder* NewActionBuilt();
static COrder* NewActionBuilt(CUnit &builder, CUnit &unit);
static COrder* NewActionDie();
static COrder* NewActionFollow(CUnit &dest);
@ -186,22 +185,19 @@ public:
static COrder* NewActionUpgradeTo(CUnit &unit, CUnitType &type);
#if 1 // currently needed for parsing
static COrder* NewActionAttack();
static COrder* NewActionAttackGround();
static COrder* NewActionBoard();
static COrder* NewActionBuild();
static COrder* NewActionFollow();
static COrder* NewActionMove();
static COrder* NewActionPatrol();
static COrder* NewActionRepair();
static COrder* NewActionResearch();
static COrder* NewActionResource();
static COrder* NewActionReturnGoods();
static COrder* NewActionSpellCast();
static COrder* NewActionTrain();
static COrder* NewActionTransformInto();
static COrder* NewActionUnload();
static COrder* NewActionUpgradeTo();
static COrder* NewActionAttack() { return new COrder(UnitActionAttack); }
static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); }
static COrder* NewActionBoard() { return new COrder(UnitActionBoard); }
static COrder* NewActionBuild() { return new COrder(UnitActionBuild); }
static COrder* NewActionFollow() { return new COrder(UnitActionFollow); }
static COrder* NewActionMove() { return new COrder(UnitActionMove); }
static COrder* NewActionRepair() { return new COrder(UnitActionRepair); }
static COrder* NewActionResource() { return new COrder(UnitActionResource); }
static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); }
static COrder* NewActionTrain() { return new COrder(UnitActionTrain); }
static COrder* NewActionTransformInto() { return new COrder(UnitActionTransformInto); }
static COrder* NewActionUnload() { return new COrder(UnitActionUnload); }
static COrder* NewActionUpgradeTo() { return new COrder(UnitActionUpgradeTo); }
#endif
private:
@ -218,7 +214,6 @@ public:
Vec2i goalPos; /// or tile coordinate of destination
union {
Vec2i Patrol; /// position for patroling.
struct {
Vec2i Pos; /// position for terrain resource.
CUnit *Mine;
@ -257,7 +252,9 @@ class COrder_Built : public COrder
{
friend COrder* COrder::NewActionBuilt(CUnit &builder, CUnit &unit);
public:
virtual COrder_Built *Clone() const;
COrder_Built() : COrder(UnitActionBuilt) {}
virtual COrder_Built *Clone() const { return new COrder_Built(*this); }
virtual void Save(CFile &file, const CUnit &unit) const;
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
@ -289,11 +286,45 @@ private:
};
class COrder_Die : public COrder
{
public:
COrder_Die() : COrder(UnitActionDie) {}
virtual COrder_Die *Clone() const { return new COrder_Die(*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
{
friend COrder* COrder::NewActionPatrol(const Vec2i &currentPos, const Vec2i &dest);
public:
COrder_Patrol() : COrder(UnitActionPatrol) {}
virtual COrder_Patrol *Clone() const { return new COrder_Patrol(*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);
const Vec2i& GetWayPoint() const { return WayPoint; }
private:
Vec2i WayPoint; /// position for patroling.
};
class COrder_Research : public COrder
{
public:
virtual COrder_Research *Clone() const;
COrder_Research() : COrder(UnitActionResearch), Upgrade(NULL) {}
virtual COrder_Research *Clone() const { return new COrder_Research(*this); }
virtual void Save(CFile &file, const CUnit &unit) const;
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
@ -309,10 +340,12 @@ private:
CUpgrade *Upgrade;
};
class COrder_SpellCast: public COrder
class COrder_SpellCast : public COrder
{
public:
virtual COrder_SpellCast *Clone() const;
COrder_SpellCast() : COrder(UnitActionSpellCast), Spell(NULL) {}
virtual COrder_SpellCast *Clone() const { return new COrder_SpellCast(*this); }
virtual void Save(CFile &file, const CUnit &unit) const;
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
@ -329,6 +362,36 @@ private:
class COrder_StandGround : public COrder
{
public:
COrder_StandGround() : COrder(UnitActionStandGround) {}
virtual COrder_StandGround *Clone() const { return new COrder_StandGround(*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_Still : public COrder
{
public:
COrder_Still() : COrder(UnitActionStill) {}
virtual COrder_Still *Clone() const { return new COrder_Still(*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);
};
/*----------------------------------------------------------------------------
-- Variables
----------------------------------------------------------------------------*/
@ -413,6 +476,10 @@ extern void DropResource(CUnit &unit);
extern void ResourceGiveUp(CUnit &unit);
extern int GetNumWaitingWorkers(const CUnit &mine);
extern void AutoAttack(CUnit &unit, CUnitCache &targets, bool stand_ground);
extern bool AutoAttack(CUnit &unit, bool stand_ground);
extern bool AutoRepair(CUnit &unit);
extern bool AutoCast(CUnit &unit);
extern void UnHideUnit(CUnit &unit);
typedef void HandleActionFunc(COrder& order, CUnit &unit);

View file

@ -287,7 +287,28 @@ extern int CclCommand(const std::string &command, bool exitOnError = true);
CUnit *CclGetUnitFromRef(lua_State *l);
/**
** Get a position from lua state
**
** @param l Lua state.
** param x pointer to output x position.
** @param y pointer to output y position.
**
** @return The unit pointer
*/
template <typename T>
static void CclGetPos(lua_State *l, T *x , T *y, const int offset = -1)
{
if (!lua_istable(l, offset) || lua_objlen(l, offset) != 2) {
LuaError(l, "incorrect argument");
}
lua_rawgeti(l, offset, 1);
*x = LuaToNumber(l, -1);
lua_pop(l, 1);
lua_rawgeti(l, offset, 2);
*y = LuaToNumber(l, -1);
lua_pop(l, 1);
}
extern NumberDesc *Damage; /// Damage calculation for missile.

View file

@ -132,29 +132,6 @@ CUnit *CclGetUnitFromRef(lua_State *l)
return UnitSlots[slot];
}
/**
** Get a position from lua state
**
** @param l Lua state.
** @param x pointer to output x position.
** @param y pointer to output y position.
**
** @return The unit pointer
*/
template <typename T>
static void CclGetPos(lua_State *l, T *x , T *y, const int offset = -1)
{
if (!lua_istable(l, offset) || lua_objlen(l, offset) != 2) {
LuaError(l, "incorrect argument");
}
lua_rawgeti(l, offset, 1);
*x = LuaToNumber(l, -1);
lua_pop(l, 1);
lua_rawgeti(l, offset, 2);
*y = LuaToNumber(l, -1);
lua_pop(l, 1);
}
/**
** Parse res worker data
**
@ -251,55 +228,6 @@ static void CclParseTrain(lua_State *l, COrderPtr order)
}
}
/**
** Parse stored data for move order
**
** @param l Lua state.
** @param unit Unit pointer which should be filled with the data.
*/
static void CclParseMove(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, "cycles")) {
lua_rawgeti(l, -1, j + 1);
order->Data.Move.Cycles = LuaToNumber(l, -1);
lua_pop(l, 1);
} else if (!strcmp(value, "fast")) {
order->Data.Move.Fast = 1;
--j;
} else if (!strcmp(value, "path")) {
int subargs;
int k;
lua_rawgeti(l, -1, j + 1);
if (!lua_istable(l, -1)) {
LuaError(l, "incorrect argument");
}
subargs = lua_objlen(l, -1);
for (k = 0; k < subargs; ++k) {
lua_rawgeti(l, -1, k + 1);
order->Data.Move.Path[k] = LuaToNumber(l, -1);
lua_pop(l, 1);
}
order->Data.Move.Length = subargs;
lua_pop(l, 1);
} else {
LuaError(l, "ParseMove: Unsupported tag: %s" _C_ value);
}
}
}
bool COrder::ParseGenericData(lua_State *l, int &j, const char *value)
{
@ -339,6 +267,52 @@ bool COrder::ParseGenericData(lua_State *l, int &j, const char *value)
return true;
}
bool COrder::ParseMoveData(lua_State *l, int &j, const char *value)
{
if (strcmp(value, "data-move") != 0) {
return false;
}
++j;
lua_rawgeti(l, -1, j + 1);
if (!lua_istable(l, -1)) {
LuaError(l, "incorrect argument");
}
const int args = 1 + lua_objlen(l, -1);
for (int i = 1; i < args; ++i) {
lua_rawgeti(l, -1, i);
const char *tag = LuaToString(l, -1);
lua_pop(l, 1);
++i;
if (!strcmp(tag, "cycles")) {
lua_rawgeti(l, -1, i);
this->Data.Move.Cycles = LuaToNumber(l, -1);
lua_pop(l, 1);
} else if (!strcmp(tag, "fast")) {
this->Data.Move.Fast = 1;
--i;
} else if (!strcmp(tag, "path")) {
lua_rawgeti(l, -1, i);
if (!lua_istable(l, -1)) {
LuaError(l, "incorrect argument _");
}
const int subargs = lua_objlen(l, -1);
for (int k = 0; k < subargs; ++k) {
lua_rawgeti(l, -1, k + 1);
this->Data.Move.Path[k] = LuaToNumber(l, -1);
lua_pop(l, 1);
}
this->Data.Move.Length = subargs;
lua_pop(l, 1);
} else {
LuaError(l, "ParseMove: Unsupported tag: %s" _C_ tag);
}
}
lua_pop(l, 1);
return true;
}
bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
{
if (!strcmp(value, "type")) {
@ -347,11 +321,6 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
this->Arg1.Type = UnitTypeByIdent(LuaToString(l, -1));
lua_pop(l, 1);
} else if (!strcmp(value, "patrol")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclGetPos(l, &this->Arg1.Patrol.x , &this->Arg1.Patrol.y);
lua_pop(l, 1);
} else if (!strcmp(value, "current-resource")) {
++j;
lua_rawgeti(l, -1, j + 1);
@ -387,11 +356,6 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
lua_rawgeti(l, -1, j + 1);
CclParseTrain(l, this);
lua_pop(l, 1);
} else if (!strcmp(value, "data-move")) {
++j;
lua_rawgeti(l, -1, j + 1);
CclParseMove(l, this);
lua_pop(l, 1);
} else if (!strcmp(value, "mine")) { /* old save format */
int pos;
++j;
@ -439,9 +403,9 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
lua_pop(l, 1);
if (!strcmp(actiontype, "action-still")) {
*orderPtr = COrder::NewActionStill();
*orderPtr = new COrder_Still;
} else if (!strcmp(actiontype, "action-stand-ground")) {
*orderPtr = COrder::NewActionStandGround();
*orderPtr = new COrder_StandGround;
} else if (!strcmp(actiontype, "action-follow")) {
*orderPtr = COrder::NewActionFollow();
} else if (!strcmp(actiontype, "action-move")) {
@ -451,23 +415,23 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
} else if (!strcmp(actiontype, "action-attack-ground")) {
*orderPtr = COrder::NewActionAttackGround();
} else if (!strcmp(actiontype, "action-die")) {
*orderPtr = COrder::NewActionDie();
*orderPtr = new COrder_Die;
} else if (!strcmp(actiontype, "action-spell-cast")) {
*orderPtr = COrder::NewActionSpellCast();
*orderPtr = new COrder_SpellCast;
} else if (!strcmp(actiontype, "action-train")) {
*orderPtr = COrder::NewActionTrain();
} else if (!strcmp(actiontype, "action-upgrade-to")) {
*orderPtr = COrder::NewActionUpgradeTo();
} else if (!strcmp(actiontype, "action-research")) {
*orderPtr = COrder::NewActionResearch();
*orderPtr = new COrder_Research;
} else if (!strcmp(actiontype, "action-built")) {
*orderPtr = COrder::NewActionBuilt();
*orderPtr = new COrder_Built;
} else if (!strcmp(actiontype, "action-board")) {
*orderPtr = COrder::NewActionBoard();
} else if (!strcmp(actiontype, "action-unload")) {
*orderPtr = COrder::NewActionUnload();
} else if (!strcmp(actiontype, "action-patrol")) {
*orderPtr = COrder::NewActionPatrol();
*orderPtr = new COrder_Patrol;
} else if (!strcmp(actiontype, "action-build")) {
*orderPtr = COrder::NewActionBuild();
} else if (!strcmp(actiontype, "action-repair")) {

View file

@ -737,12 +737,15 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder
break;
case UnitActionPatrol:
{
Video.DrawLineClip(ColorGreen, pos1.x, pos1.y, pos2.x, pos2.y);
e_color = color = ColorBlue;
pos1 = CurrentViewport->TilePosToScreen_Center(order.Arg1.Patrol);
const COrder_Patrol &orderPatrol = static_cast<const COrder_Patrol&>(order);
pos1 = CurrentViewport->TilePosToScreen_Center(orderPatrol.GetWayPoint());
dest = true;
break;
}
case UnitActionRepair:
e_color = color = ColorGreen;
dest = true;

View file

@ -96,12 +96,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionNone:
file.printf("\"action-none\",");
break;
case UnitActionStill:
file.printf("\"action-still\",");
break;
case UnitActionStandGround:
file.printf("\"action-stand-ground\",");
break;
case UnitActionFollow:
file.printf("\"action-follow\",");
break;
@ -114,9 +108,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionAttackGround:
file.printf("\"action-attack-ground\",");
break;
case UnitActionDie:
file.printf("\"action-die\",");
break;
case UnitActionTrain:
file.printf("\"action-train\",");
break;
@ -129,9 +120,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionUnload:
file.printf("\"action-unload\",");
break;
case UnitActionPatrol:
file.printf("\"action-patrol\",");
break;
case UnitActionBuild:
file.printf("\"action-build\",");
break;
@ -174,9 +162,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
case UnitActionTransformInto:
file.printf(", \"type\", \"%s\"", order.Arg1.Type->Ident.c_str());
break;
case UnitActionPatrol:
file.printf(", \"patrol\", {%d, %d}", order.Arg1.Patrol.x, order.Arg1.Patrol.y);
break;
case UnitActionResource :
case UnitActionReturnGoods :
if (order.CurrentResource) {