Create specific "construtor" for each order.

This commit is contained in:
joris 2012-02-17 09:05:42 +01:00
parent 0e54eae28e
commit 5d4ddd2508
11 changed files with 681 additions and 649 deletions

View file

@ -147,13 +147,7 @@ static int CheckForTargetInRange(CUnit &unit)
CUnit *goal = AttackUnitsInReactRange(unit);
if (goal) {
COrder *savedOrder = new COrder();
savedOrder->Action = order->Action;
savedOrder->MinRange = 0;//order->MinRange;
savedOrder->Range = 0;//order->Range;
savedOrder->goalPos = order->goalPos;
COrder *savedOrder = COrder::NewActionAttack(unit, order->goalPos);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;

View file

@ -131,15 +131,14 @@ void HandleActionPatrol(COrder& order, CUnit &unit)
// Save current command to come back.
COrder *savedOrder = new COrder(order);
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();
unit.CurrentOrder()->ClearGoal();
DebugPrint("Patrol attack %d\n" _C_ UnitNumber(*goal));
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
return;
}
}

View file

@ -272,11 +272,7 @@ static bool AutoAttack(CUnit &unit, bool stand_ground)
if ((goal = AttackUnitsInReactRange(unit))) {
// Weak goal, can choose other unit, come back after attack
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
COrder *savedOrder = new COrder;
savedOrder->Action = UnitActionAttack;
savedOrder->Range = 0;
savedOrder->goalPos = unit.tilePos;
COrder *savedOrder = COrder::NewActionAttack(unit, unit.tilePos);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;
@ -316,11 +312,7 @@ void AutoAttack(CUnit &unit, CUnitCache &targets, bool stand_ground)
if (goal) {
// Weak goal, can choose other unit, come back after attack
CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
COrder *savedOrder = new COrder;
savedOrder->Action = UnitActionAttack;
savedOrder->Range = 0;
savedOrder->goalPos = unit.tilePos;
COrder *savedOrder = COrder::NewActionAttack(unit, unit.tilePos);
if (unit.StoreOrder(savedOrder) == false) {
delete savedOrder;

View file

@ -82,6 +82,345 @@ COrder::COrder(const COrder &rhs): Goal(rhs.Goal), Range(rhs.Range),
}
}
/* static */ COrder* COrder::NewActionAttack(const CUnit &attacker, CUnit &target)
{
COrder *order = new COrder;
order->Action = UnitActionAttack;
if (target.Destroyed) {
order->goalPos = target.tilePos + target.Type->GetHalfTileSize();
} else {
// Removed, Dying handled by action routine.
order->SetGoal(&target);
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
}
return order;
}
/* static */ COrder* COrder::NewActionAttack(const CUnit &attacker, const Vec2i &dest)
{
Assert(Map.Info.IsPointOnMap(dest));
COrder *order = new COrder;
order->Action = UnitActionAttack;
if (Map.WallOnMap(dest) && Map.IsFieldExplored(*attacker.Player, dest)) {
// FIXME: look into action_attack.cpp about this ugly problem
order->goalPos = dest;
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
} else {
order->goalPos = dest;
}
return order;
}
/* static */ COrder* COrder::NewActionAttackGround(const CUnit &attacker, const Vec2i &dest)
{
COrder *order = new COrder;
order->Action = UnitActionAttackGround;
order->goalPos = dest;
order->Range = attacker.Stats->Variables[ATTACKRANGE_INDEX].Max;
order->MinRange = attacker.Type->MinAttackRange;
return order;
}
/* static */ COrder* COrder::NewActionBoard(CUnit &unit)
{
COrder *order = new COrder;
order->Action = UnitActionBoard;
order->SetGoal(&unit);
order->Range = 1;
return order;
}
/* static */ COrder* COrder::NewActionBuild(const CUnit &builder, const Vec2i &pos, CUnitType &building)
{
COrder *order = new COrder;
order->Action = UnitActionBuild;
order->goalPos = pos;
order->Width = building.TileWidth;
order->Height = building.TileHeight;
if (building.BuilderOutside) {
order->Range = builder.Type->RepairRange;
} else {
// If building inside, but be next to stop
if (building.ShoreBuilding && builder.Type->UnitType == UnitTypeLand) {
// Peon won't dive :-)
order->Range = 1;
}
}
order->Arg1.Type = &building;
if (building.BuilderOutside) {
order->MinRange = 1;
}
return order;
}
/* static */ COrder* COrder::NewActionBuilt()
{
COrder *order = new COrder;
order->Action = UnitActionBuilt;
return order;
}
/* static */ COrder* COrder::NewActionDie()
{
COrder *order = new COrder;
order->Action = UnitActionDie;
return order;
}
/* static */ COrder* COrder::NewActionFollow(CUnit &dest)
{
COrder *order = new COrder;
order->Action = UnitActionFollow;
// Destination could be killed.
// Should be handled in action, but is not possible!
// Unit::Refs is used as timeout counter.
if (dest.Destroyed) {
order->goalPos = dest.tilePos + dest.Type->GetHalfTileSize();
} else {
order->SetGoal(&dest);
order->Range = 1;
}
return order;
}
/* static */ COrder* COrder::NewActionMove(const Vec2i &pos)
{
COrder *order = new COrder;
order->Action = UnitActionMove;
order->goalPos = pos;
return order;
}
/* static */ COrder* COrder::NewActionPatrol(const Vec2i &currentPos, const Vec2i &dest)
{
Assert(Map.Info.IsPointOnMap(currentPos));
Assert(Map.Info.IsPointOnMap(dest));
COrder *order = new COrder;
order->Action = UnitActionPatrol;
order->goalPos = dest;
order->Arg1.Patrol = currentPos;
return order;
}
/* static */ COrder* COrder::NewActionRepair(CUnit &unit, CUnit &target)
{
COrder *order = new COrder;
order->Action = UnitActionRepair;
if (target.Destroyed) {
order->goalPos = target.tilePos + target.Type->GetHalfTileSize();
} else {
order->SetGoal(&target);
order->Range = unit.Type->RepairRange;
}
return order;
}
/* static */ COrder* COrder::NewActionRepair(const Vec2i &pos)
{
Assert(Map.Info.IsPointOnMap(pos));
COrder *order = new COrder;
order->Action = UnitActionRepair;
order->goalPos = pos;
return order;
}
/* static */ COrder* COrder::NewActionResearch(CUnit &unit, CUpgrade &upgrade)
{
COrder *order = new COrder;
order->Action = UnitActionResearch;
// FIXME: if you give quick an other order, the resources are lost!
unit.Player->SubCosts(upgrade.Costs);
order->Arg1.Upgrade = &upgrade;
return order;
}
/* static */ COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos)
{
COrder *order = new COrder;
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");
}
// Max Value > 1
if ((MyAbs(ressourceLoc.x - pos.x) | MyAbs(ressourceLoc.y - pos.y)) > 1) {
if (!FindTerrainType(0, MapFieldForest, 0, 20, harvester.Player, ressourceLoc, &ressourceLoc)) {
DebugPrint("FIXME: Give up???\n");
}
} else {
// The destination is next to a reachable tile.
ressourceLoc = pos;
}
order->goalPos = ressourceLoc;
order->Range = 1;
return order;
}
/* static */ COrder* COrder::NewActionResource(CUnit &mine)
{
COrder *order = new COrder;
order->Action = UnitActionResource;
order->SetGoal(&mine);
order->Range = 1;
return order;
}
/* static */ COrder* COrder::NewActionReturnGoods(CUnit *depot)
{
COrder *order = new COrder;
order->Action = UnitActionReturnGoods;
// Destination could be killed. NETWORK!
if (depot && !depot->Destroyed) {
order->SetGoal(depot);
}
order->Range = 1;
return order;
}
/* static */ COrder* COrder::NewActionSpellCast(SpellType &spell, const Vec2i &pos, CUnit *target)
{
COrder *order = new COrder;
order->Action = UnitActionSpellCast;
order->Range = spell.Range;
if (target) {
// Destination could be killed.
// Should be handled in action, but is not possible!
// Unit::Refs is used as timeout counter.
if (target->Destroyed) {
// FIXME: where check if spell needs a unit as destination?
// FIXME: target->Type is now set to 0. maybe we shouldn't bother.
const Vec2i diag = {order->Range, order->Range};
order->goalPos = target->tilePos /* + target->Type->GetHalfTileSize() */ - diag;
order->Range <<= 1;
} else {
order->SetGoal(target);
}
} else {
order->goalPos = pos;
}
order->Arg1.Spell = &spell;
return order;
}
/* static */ COrder* COrder::NewActionStandGround()
{
COrder *order = new COrder;
order->Action = UnitActionStandGround;
return order;
}
/* static */ COrder* COrder::NewActionStill()
{
COrder *order = new COrder;
order->Action = UnitActionStill;
return order;
}
/* static */ COrder* COrder::NewActionTrain(CUnit &trainer, CUnitType &type)
{
COrder *order = new COrder;
order->Action = UnitActionTrain;
order->Arg1.Type = &type;
// FIXME: if you give quick an other order, the resources are lost!
trainer.Player->SubUnitType(type);
return order;
}
/* static */ COrder* COrder::NewActionTransformInto(CUnitType &type)
{
COrder *order = new COrder;
order->Action = UnitActionTransformInto;
order->Arg1.Type = &type;
return order;
}
/* static */ COrder* COrder::NewActionUnload(const Vec2i &pos, CUnit *what)
{
COrder *order = new COrder;
order->Action = UnitActionUnload;
order->goalPos = pos;
if (what && !what->Destroyed) {
order->SetGoal(what);
}
return order;
}
/* static */ COrder* COrder::NewActionUpgradeTo(CUnit &unit, CUnitType &type)
{
COrder *order = new COrder;
order->Action = UnitActionUpgradeTo;
// FIXME: if you give quick an other order, the resources are lost!
unit.Player->SubUnitType(type);
order->Arg1.Type = &type;
return order;
}
COrder& COrder::operator=(const COrder &rhs) {
if (this != &rhs) {
Action = rhs.Action;

File diff suppressed because it is too large Load diff

View file

@ -714,11 +714,7 @@ void AiHelpMe(const CUnit *attacker, CUnit &defender)
&& CanTarget(aiunit.Type, attacker->Type)) {
CommandAttack(aiunit, attacker->tilePos, const_cast<CUnit*>(attacker), FlushCommands);
if (aiunit.SavedOrder == NULL) {
COrder *savedOrder = new COrder;
savedOrder->Action = UnitActionAttack;
savedOrder->Range = 0;
savedOrder->goalPos = aiunit.tilePos;
COrder *savedOrder = COrder::NewActionAttack(aiunit, aiunit.tilePos);
if (aiunit.StoreOrder(savedOrder) == false) {
delete savedOrder;

View file

@ -10,7 +10,7 @@
//
/**@name actions.h - The actions headerfile. */
//
// (c) Copyright 1998-2006 by Lutz Sammer and Jimmy Salmon
// (c) Copyright 1998-2012 by Lutz Sammer and Jimmy Salmon
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -150,6 +150,31 @@ public:
void AiUnitKilled(CUnit &unit);
void OnAnimationAttack(CUnit &unit);
static COrder* NewActionAttack(const CUnit &attacker, CUnit &target);
static COrder* NewActionAttack(const CUnit &attacker, const Vec2i &dest);
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* NewActionDie();
static COrder* NewActionFollow(CUnit &dest);
static COrder* NewActionMove(const Vec2i &pos);
static COrder* NewActionPatrol(const Vec2i &currentPos, const Vec2i &dest);
static COrder* NewActionRepair(CUnit &unit, CUnit &target);
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* NewActionSpellCast(SpellType &spell, const Vec2i &pos, CUnit *target);
static COrder* NewActionStandGround();
static COrder* NewActionStill();
static COrder* NewActionTrain(CUnit &trainer, CUnitType &type);
static COrder* NewActionTransformInto(CUnitType &type);
static COrder* NewActionUnload(const Vec2i &pos, CUnit *what);
static COrder* NewActionUpgradeTo(CUnit &unit, CUnitType &type);
private:
friend void CclParseOrder(lua_State *l, const CUnit &unit, COrder* order);
@ -160,8 +185,7 @@ public:
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
unsigned char CurrentResource; //used in UnitActionResource and
//UnitActionReturnGoods
unsigned char CurrentResource; ///used in UnitActionResource and UnitActionReturnGoods
Vec2i goalPos; /// or tile coordinate of destination
@ -292,10 +316,6 @@ extern void CommandDiplomacy(int player, int state, int opponent);
extern void CommandSetResource(int player, int resource, int value);
/// Prepare shared vision command
extern void CommandSharedVision(int player, bool state, int opponent);
/// Send any command
//extern void CommandAnyOrder(CUnit &unit, COrder *order, int flush);
/// Move an order in command queue
extern void CommandMoveOrder(CUnit &unit, int src, int dst);
/*----------------------------------------------------------------------------
-- Actions: in action_<name>.c
@ -328,7 +348,7 @@ extern HandleActionFunc HandleActionPatrol;
/// Show attack animation
extern void AnimateActionAttack(CUnit &unit);
/// Handle command attack
extern HandleActionFunc HandleActionAttack;
extern HandleActionFunc HandleActionAttack;
/// Handle command board
extern HandleActionFunc HandleActionBoard;
/// Handle command unload

View file

@ -597,8 +597,6 @@ public:
CUnit *Goal; /// Generic/Teleporter goal pointer
COrder *CreateOrder();
COrder *CurrentOrder() const { return Orders[0]; }
unsigned int CurrentAction() const;

View file

@ -307,13 +307,11 @@ void GroupHelpMe(CUnit *attacker, CUnit &defender)
&& CanTarget(gunit.Type, attacker->Type)) {
CommandAttack(gunit, attacker->tilePos, attacker, FlushCommands);
if (gunit.SavedOrder == NULL) {
COrder *savedOrder = new COrder;
savedOrder->Action = UnitActionAttack;
savedOrder->goalPos = gunit.tilePos;
COrder *savedOrder = COrder::NewActionAttack(gunit, gunit.tilePos);
if (gunit.StoreOrder(savedOrder) == false) {
delete savedOrder;
savedOrder = NULL;
}
}
}

View file

@ -589,9 +589,12 @@ static void CclParseOrders(lua_State *l, CUnit &unit)
unit.OrderCount = 0;
for (int j = 0; j < n; ++j) {
lua_rawgeti(l, -1, j + 1);
COrderPtr order = unit.CreateOrder();
Assert(order == unit.Orders[j]);
CclParseOrder(l, unit, order);
unit.Orders.push_back(new COrder);
COrderPtr* order = &unit.Orders[(int)unit.OrderCount++];
Assert(order == &unit.Orders[j]);
CclParseOrder(l, unit, *order);
lua_pop(l, 1);
}
}

View file

@ -260,13 +260,6 @@ void CUnit::Release(bool final)
UnitManager.ReleaseUnit(this);
}
COrder *CUnit::CreateOrder()
{
Orders.push_back(new COrder);
return Orders[(int)OrderCount++];
}
unsigned int CUnit::CurrentAction() const
{
return (CurrentOrder()->Action);
@ -1059,8 +1052,8 @@ void UnitClearOrders(CUnit &unit)
delete unit.Orders[i];
}
unit.Orders.clear();
unit.OrderCount = 0;
CommandStopUnit(unit);
unit.OrderCount = 1;
unit.Orders.push_back(COrder::NewActionStill());
unit.SubAction = unit.State = 0;
}
@ -2720,14 +2713,15 @@ void LetUnitDie(CUnit &unit)
UnitLost(unit);
UnitClearOrders(unit);
//
// Unit has death animation.
//
// Not good: UnitUpdateHeading(unit);
unit.SubAction = 0;
unit.State = 0;
unit.CurrentOrder()->Action = UnitActionDie;
delete unit.Orders[0];
unit.Orders[0] = COrder::NewActionDie();
if (type->CorpseType) {
#ifdef DYNAMIC_LOAD
if (!type->Sprite) {
@ -2977,19 +2971,13 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
}
}
if (goal) {
if (target.SavedOrder == NULL) {
COrder* savedOrder = new COrder;
COrder *savedOrder = new COrder(*target.CurrentOrder());
savedOrder->Action = UnitActionAttack;
savedOrder->goalPos = target.tilePos;
savedOrder->Range = target.Stats->Variables[ATTACKRANGE_INDEX].Max;
savedOrder->MinRange = target.Type->MinAttackRange;
if (target.StoreOrder(savedOrder) == false) {
delete savedOrder;
}
}
CommandAttack(target, goal->tilePos, NoUnitP, FlushCommands);
if (target.StoreOrder(savedOrder) == false) {
delete savedOrder;
savedOrder = NULL;
}
return;
}
}