Removed MAX_ORDERS, units can have as many orders as they require.
Added Memory management for Orders, so they are reused, less mallocs. Remove MustRedraw and EnableRedraw, they are not used, everything is redrawn each frame. Remove TrainingQueue LIMIT, you can train as many units as you like if the training queue is enable. This needs further configuration work. But operates correctly.
This commit is contained in:
parent
0408df5c3a
commit
087c4c85e9
25 changed files with 211 additions and 219 deletions
src
action
ai
editor
include
map
pathfinder
stratagus
ui
unit
|
@ -125,8 +125,6 @@ static int ActionMoveGeneric(Unit* unit, const Animation* anim)
|
|||
y = unit->Y + yd;
|
||||
MoveUnitToXY(unit, x, y);
|
||||
|
||||
MustRedraw |= RedrawMinimap;
|
||||
|
||||
// Remove unit from the current selection
|
||||
if (unit->Selected && !IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
if (NumSelected == 1) { // Remove building cursor
|
||||
|
|
|
@ -102,20 +102,18 @@ void HandleActionTrain(Unit* unit)
|
|||
//
|
||||
if (!unit->SubAction) {
|
||||
unit->Data.Train.Ticks = 0;
|
||||
unit->Data.Train.What[0] = unit->Orders[0].Type;
|
||||
unit->Data.Train.Count = 1;
|
||||
unit->SubAction = 1;
|
||||
}
|
||||
unit->Data.Train.Ticks += SpeedTrain;
|
||||
// FIXME: Should count down
|
||||
if (unit->Data.Train.Ticks >=
|
||||
unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost]) {
|
||||
unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost]) {
|
||||
//
|
||||
// Check if there are still unit slots.
|
||||
//
|
||||
if (NumUnits >= UnitMax) {
|
||||
unit->Data.Train.Ticks =
|
||||
unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost];
|
||||
unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost];
|
||||
unit->Reset = 1;
|
||||
unit->Wait = CYCLES_PER_SECOND / 6;
|
||||
return;
|
||||
|
@ -124,20 +122,20 @@ void HandleActionTrain(Unit* unit)
|
|||
//
|
||||
// Check if enough supply available.
|
||||
//
|
||||
food = PlayerCheckLimits(player, unit->Data.Train.What[0]);
|
||||
food = PlayerCheckLimits(player, unit->Orders[0].Type);
|
||||
if (food < 0) {
|
||||
if (food == -3 && unit->Player->AiEnabled) {
|
||||
AiNeedMoreSupply(unit, unit->Orders[0].Type);
|
||||
}
|
||||
|
||||
unit->Data.Train.Ticks =
|
||||
unit->Data.Train.What[0]->Stats[player->Player].Costs[TimeCost];
|
||||
unit->Orders[0].Type->Stats[player->Player].Costs[TimeCost];
|
||||
unit->Reset = 1;
|
||||
unit->Wait = CYCLES_PER_SECOND / 6;
|
||||
return;
|
||||
}
|
||||
|
||||
nunit = MakeUnit(unit->Data.Train.What[0], player);
|
||||
nunit = MakeUnit(unit->Orders[0].Type, player);
|
||||
nunit->X = unit->X;
|
||||
nunit->Y = unit->Y;
|
||||
type = unit->Type;
|
||||
|
@ -166,16 +164,8 @@ void HandleActionTrain(Unit* unit)
|
|||
|
||||
unit->Reset = unit->Wait = 1;
|
||||
|
||||
if (--unit->Data.Train.Count) {
|
||||
int z;
|
||||
for (z = 0; z < unit->Data.Train.Count; ++z) {
|
||||
unit->Data.Train.What[z] = unit->Data.Train.What[z + 1];
|
||||
}
|
||||
unit->Data.Train.Ticks = 0;
|
||||
} else {
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->SubAction = 0;
|
||||
}
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->SubAction = 0;
|
||||
|
||||
if (!CanHandleOrder(nunit, &unit->NewOrder)) {
|
||||
DebugPrint("Wrong order for unit\n");
|
||||
|
|
|
@ -555,7 +555,7 @@ void UnitActions(void)
|
|||
fprintf(logf, "%d %s S%d/%d-%d P%d Refs %d: %X %d,%d %d,%d\n",
|
||||
UnitNumber(unit), unit->Type ? unit->Type->Ident : "unit-killed",
|
||||
unit->State, unit->SubAction,
|
||||
unit->Orders[0].Action,
|
||||
unit->Orders ? unit->Orders[0].Action : -1,
|
||||
unit->Player ? unit->Player->Player : -1, unit->Refs,SyncRandSeed,
|
||||
unit->X, unit->Y, unit->IX, unit->IY);
|
||||
|
||||
|
@ -569,7 +569,7 @@ void UnitActions(void)
|
|||
// Calculate some hash.
|
||||
//
|
||||
SyncHash = (SyncHash << 5) | (SyncHash >> 27);
|
||||
SyncHash ^= unit->Orders[0].Action << 18;
|
||||
SyncHash ^= unit->Orders ? unit->Orders[0].Action << 18 : 0;
|
||||
SyncHash ^= unit->State << 12;
|
||||
SyncHash ^= unit->SubAction << 6;
|
||||
SyncHash ^= unit->Refs << 3;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "unittype.h"
|
||||
|
@ -96,21 +97,57 @@ static void ReleaseOrders(Unit* unit)
|
|||
*/
|
||||
static Order* GetNextOrder(Unit* unit, int flush)
|
||||
{
|
||||
Order *OldOrders;
|
||||
if (flush) {
|
||||
// empty command queue
|
||||
ReleaseOrders(unit);
|
||||
} else if (unit->OrderCount == MAX_ORDERS) {
|
||||
// FIXME: johns: wrong place for an error message.
|
||||
// FIXME: johns: should be checked by AI or the user interface
|
||||
// NOTE: But must still be checked here.
|
||||
NotifyPlayer(unit->Player, NotifyYellow, unit->X, unit->Y,
|
||||
"Unit order list is full");
|
||||
return NULL;
|
||||
} else if (unit->OrderCount == unit->TotalOrders) {
|
||||
// Expand Order Queue if filled
|
||||
OldOrders = unit->Orders;
|
||||
unit->Orders = realloc(unit->Orders, sizeof(Order) * unit->TotalOrders * 2);
|
||||
// Realloc failed, fail gracefully
|
||||
if (!unit->Orders) {
|
||||
unit->Orders = OldOrders;
|
||||
NotifyPlayer(unit->Player, NotifyYellow, unit->X, unit->Y,
|
||||
"Unable to add order to list");
|
||||
return NULL;
|
||||
}
|
||||
memset(&unit->Orders[unit->TotalOrders], 0, sizeof(Order) * unit->TotalOrders);
|
||||
unit->TotalOrders *= 2;
|
||||
}
|
||||
|
||||
return &unit->Orders[(int)unit->OrderCount++];
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove an order from the list of orders pending
|
||||
**
|
||||
** @param unit pointer to unit
|
||||
** @param order number of the order to remove
|
||||
*/
|
||||
static void RemoveOrder(Unit* unit, int order)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = order;
|
||||
while(i < unit->OrderCount - 1) {
|
||||
unit->Orders[i] = unit->Orders[i + 1];
|
||||
++i;
|
||||
}
|
||||
|
||||
if (unit->OrderCount > 1) {
|
||||
--unit->OrderCount;
|
||||
} else {
|
||||
unit->Orders[i].Action = UnitActionStill;
|
||||
unit->Orders[i].X = unit->Orders[i].Y = -1;
|
||||
unit->SubAction = 0;
|
||||
unit->Orders[i].Type = NULL;
|
||||
unit->Orders[i].Arg1 = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
** Clear the saved action.
|
||||
**
|
||||
|
@ -839,6 +876,8 @@ void CommandReturnGoods(Unit* unit, Unit* goal, int flush)
|
|||
void CommandTrainUnit(Unit* unit, UnitType* type,
|
||||
int flush __attribute__((unused)))
|
||||
{
|
||||
Order* order;
|
||||
|
||||
//
|
||||
// Check if unit is still valid? (NETWORK!)
|
||||
//
|
||||
|
@ -855,32 +894,19 @@ void CommandTrainUnit(Unit* unit, UnitType* type,
|
|||
//
|
||||
// Not already training?
|
||||
//
|
||||
if (unit->Orders[0].Action != UnitActionTrain) {
|
||||
if (unit->OrderCount == 2 && unit->Orders[1].Action == UnitActionTrain) {
|
||||
DebugPrint("FIXME: not supported. Unit queue full!\n");
|
||||
return;
|
||||
} else {
|
||||
ReleaseOrders(unit);
|
||||
unit->Orders[1].Action = UnitActionTrain;
|
||||
}
|
||||
Assert(unit->OrderCount == 1 && unit->OrderFlush == 1);
|
||||
|
||||
unit->OrderCount = 2;
|
||||
unit->Orders[1].Type = type;
|
||||
unit->Orders[1].X = unit->Orders[1].Y = -1;
|
||||
unit->Orders[1].Goal = NoUnitP;
|
||||
unit->Orders[1].Arg1 = NULL;
|
||||
} else {
|
||||
//
|
||||
// Training slots are all already full. (NETWORK!)
|
||||
//
|
||||
if (!EnableTrainingQueue || unit->Data.Train.Count >= MAX_UNIT_TRAIN) {
|
||||
DebugPrint("Unit queue full!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unit->Data.Train.What[unit->Data.Train.Count++] = type;
|
||||
if (!EnableTrainingQueue && unit->Orders[0].Action == UnitActionTrain) {
|
||||
DebugPrint("Unit queue full!\n");
|
||||
return;
|
||||
}
|
||||
if (!(order = GetNextOrder(unit, 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
order->Action = UnitActionTrain;
|
||||
order->Type = type;
|
||||
order->X = order->Y = -1;
|
||||
order->Goal = NoUnitP;
|
||||
order->Arg1 = NULL;
|
||||
// FIXME: if you give quick an other order, the resources are lost!
|
||||
PlayerSubUnitType(unit->Player, type);
|
||||
}
|
||||
|
@ -896,8 +922,6 @@ void CommandTrainUnit(Unit* unit, UnitType* type,
|
|||
*/
|
||||
void CommandCancelTraining(Unit* unit, int slot, const UnitType* type)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
|
||||
DebugPrint("Cancel %d type: %s\n" _C_ slot _C_
|
||||
type ? type->Ident : "-any-");
|
||||
|
@ -907,42 +931,45 @@ void CommandCancelTraining(Unit* unit, int slot, const UnitType* type)
|
|||
//
|
||||
// Check if unit is still training 'slot'? (NETWORK!)
|
||||
//
|
||||
if (unit->Orders[0].Action == UnitActionTrain) {
|
||||
n = unit->Data.Train.Count;
|
||||
Assert(n >= 1);
|
||||
if (slot == -1) { // default last slot!
|
||||
slot += n;
|
||||
|
||||
if (slot == -1) {
|
||||
// Cancel All training
|
||||
while(unit->Orders[0].Action == UnitActionTrain) {
|
||||
PlayerAddCostsFactor(unit->Player,
|
||||
unit->Orders[0].Type->Stats[unit->Player->Player].Costs,
|
||||
CancelTrainingCostsFactor);
|
||||
RemoveOrder(unit, 0);
|
||||
}
|
||||
unit->Data.Train.Ticks = 0;
|
||||
unit->Wait = unit->Reset = 1; // immediately start next training
|
||||
if (unit->Player == ThisPlayer && unit->Selected) {
|
||||
SelectedUnitChanged();
|
||||
}
|
||||
//
|
||||
// Check if slot and unit-type is still trained? (NETWORK!)
|
||||
//
|
||||
if (slot >= n || (type && unit->Data.Train.What[slot] != type)) {
|
||||
// FIXME: we can look if this is now in an earlier slot.
|
||||
} else if (unit->OrderCount < slot) {
|
||||
// Order has moved
|
||||
return;
|
||||
} else if (unit->Orders[slot].Action != UnitActionTrain) {
|
||||
// Order has moved, we are not training
|
||||
return;
|
||||
} else if (unit->Orders[slot].Action == UnitActionTrain) {
|
||||
// Still training this order, same unit?
|
||||
if (type && unit->Orders[slot].Type != type) {
|
||||
// Different unit being trained
|
||||
return;
|
||||
}
|
||||
|
||||
DebugPrint("Cancel training\n");
|
||||
|
||||
PlayerAddCostsFactor(unit->Player,
|
||||
unit->Data.Train.What[slot]->Stats[unit->Player->Player].Costs,
|
||||
unit->Orders[slot].Type->Stats[unit->Player->Player].Costs,
|
||||
CancelTrainingCostsFactor);
|
||||
|
||||
if (--n) {
|
||||
// Copy the other slots down
|
||||
for (i = slot; i < n; ++i) {
|
||||
unit->Data.Train.What[i] = unit->Data.Train.What[i + 1];
|
||||
}
|
||||
if (!slot) { // Canceled in work slot
|
||||
unit->Data.Train.Ticks = 0;
|
||||
unit->Wait = unit->Reset = 1; // immediately start next training
|
||||
}
|
||||
unit->Data.Train.Count = n;
|
||||
} else {
|
||||
DebugPrint("Last slot\n");
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->SubAction = 0;
|
||||
unit->Wait = unit->Reset = 1;
|
||||
|
||||
if (!slot) { // Canceled in work slot
|
||||
unit->Data.Train.Ticks = 0;
|
||||
unit->Wait = unit->Reset = 1; // immediately start next training
|
||||
}
|
||||
RemoveOrder(unit, slot);
|
||||
|
||||
//
|
||||
// Update interface.
|
||||
|
|
|
@ -1513,7 +1513,6 @@ static int FindTransporterOnZone(int waterzone, ZoneSet* destzones,
|
|||
// If transporter is moving, check if it is moving on our coast
|
||||
if (!unitok &&
|
||||
unit->OrderCount + (unit->OrderFlush ? 1 : 0) >= 2 &&
|
||||
unit->OrderCount < MAX_ORDERS - 1 &&
|
||||
unit->Orders[unit->OrderFlush ? 1 : 0].Action == UnitActionFollow &&
|
||||
unit->Orders[unit->OrderCount - 1].Action == UnitActionUnload &&
|
||||
unit->BoardCount + unit->OrderCount - (unit->OrderFlush ? 1 : 0) <= unit->Type->MaxOnBoard) {
|
||||
|
|
|
@ -77,10 +77,10 @@ static int IconWidth; /// Icon width in panels
|
|||
static int IconHeight; /// Icon height in panels
|
||||
|
||||
|
||||
char EditorRunning; /// True editor is running
|
||||
char EditorMapLoaded; /// Map loaded in editor
|
||||
|
||||
EditorStateType EditorState; /// Current editor state.
|
||||
EditorStateType EditorState; /// Current editor state.
|
||||
EditorRunningType EditorRunning; /// Running State of editor.
|
||||
|
||||
static char TileToolRandom; /// Tile tool draws random
|
||||
static char TileToolDecoration; /// Tile tool draws with decorations
|
||||
|
@ -201,7 +201,6 @@ void EditTile(int x, int y, int tile)
|
|||
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
UpdateMinimapXY(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
|
||||
EditorTileChanged(x, y);
|
||||
}
|
||||
|
@ -1168,7 +1167,6 @@ static void EditorCallbackButtonDown(unsigned button __attribute__ ((unused)))
|
|||
if (TheMap.Info->PlayerType[CursorPlayer] != PlayerNobody) {
|
||||
SelectedPlayer = CursorPlayer;
|
||||
ThisPlayer = Players + SelectedPlayer;
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2025,7 +2023,7 @@ void EditorMainLoop(void)
|
|||
|
||||
while (1) {
|
||||
EditorMapLoaded = 0;
|
||||
EditorRunning = 1;
|
||||
EditorRunning = EditorEditing;
|
||||
|
||||
CreateEditor();
|
||||
|
||||
|
|
|
@ -38,7 +38,15 @@
|
|||
----------------------------------------------------------------------------*/
|
||||
|
||||
/// Editor is running
|
||||
extern char EditorRunning;
|
||||
typedef enum _editor_running_state_ {
|
||||
EditorNotRunning = 0, ///< Not Running
|
||||
EditorStarted = 1, ///< Editor Enabled at all
|
||||
EditorCommandLine = 2, ///< Called from Command Line
|
||||
EditorEditing = 4 ///< Editor is fully running
|
||||
} EditorRunningType;
|
||||
|
||||
extern EditorRunningType EditorRunning;
|
||||
|
||||
/// Map loaded in editor
|
||||
extern char EditorMapLoaded;
|
||||
/// Current editor state type.
|
||||
|
|
|
@ -248,6 +248,7 @@ extern char NameLine[];
|
|||
/// Game cycles per second to simulate (original 30-40)
|
||||
#define CYCLES_PER_SECOND 30 // 1/30s 0.33ms
|
||||
|
||||
#define DEFAULT_START_ORDERS 4 // The number of Orders allocated on unit creation
|
||||
/// Must redraw flags
|
||||
enum _must_redraw_flags_ {
|
||||
RedrawNothing = 1 << 0, ///< Nothing to do
|
||||
|
@ -275,21 +276,6 @@ enum _must_redraw_flags_ {
|
|||
RedrawEverything = -1, ///< Must redraw everything
|
||||
};
|
||||
|
||||
/// Must redraw all maps
|
||||
#define RedrawMaps (RedrawMinimap | RedrawMap)
|
||||
/// Must redraw all cursors
|
||||
#define RedrawCursors (RedrawMinimapCursor | RedrawCursor)
|
||||
/// Must redraw all panels
|
||||
#define RedrawPanels (RedrawInfoPanel | RedrawButtonPanel)
|
||||
/// Must redraw after color cycle
|
||||
#define RedrawColorCycle (RedrawMap | RedrawInfoPanel | RedrawButtonPanel | RedrawResources)
|
||||
|
||||
/// Invalidated redraw flags
|
||||
extern int MustRedraw;
|
||||
|
||||
/// Enable redraw flags
|
||||
extern int EnableRedraw;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- clone.c
|
||||
----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -331,18 +331,23 @@
|
|||
** Unit::OrderCount
|
||||
**
|
||||
** The number of the orders unit to process. An unit has atleast
|
||||
** one order. Unit::OrderCount should be a number between 1 and
|
||||
** ::MAX_ORDERS. The orders are in Unit::Orders[].
|
||||
** one order. Unit::OrderCount should be a number at least 1.
|
||||
** The orders are in Unit::Orders[].
|
||||
**
|
||||
** Unit::OrderFlush
|
||||
**
|
||||
** A flag, which tells the unit to stop with the current order
|
||||
** and immediately start with the next order.
|
||||
**
|
||||
** Unit::TotalOrders
|
||||
**
|
||||
** The number of Orders allocated for this unit to use.
|
||||
** Default is 4, but is dynamically updated if more orders are
|
||||
** given.
|
||||
**
|
||||
** Unit::Orders
|
||||
**
|
||||
** Contains all orders of the unit. Slot 0 is always used.
|
||||
** Up to ::MAX_ORDERS can be stored.
|
||||
**
|
||||
** Unit::SavedOrder
|
||||
**
|
||||
|
@ -596,10 +601,10 @@ struct _unit_ {
|
|||
unsigned Rs : 8;
|
||||
unsigned char CurrentResource;
|
||||
|
||||
#define MAX_ORDERS 16 ///< How many outstanding orders?
|
||||
char OrderCount; ///< how many orders in queue
|
||||
char OrderFlush; ///< cancel current order, take next
|
||||
Order Orders[MAX_ORDERS]; ///< orders to process
|
||||
int TotalOrders; ///< Total Number of orders available
|
||||
Order* Orders; ///< orders to process
|
||||
Order SavedOrder; ///< order to continue after current
|
||||
Order NewOrder; ///< order for new trained units
|
||||
char* AutoCastSpell; ///< spells to auto cast
|
||||
|
@ -632,10 +637,6 @@ struct _unit_ {
|
|||
} UpgradeTo; ///< Upgrade to action
|
||||
struct _order_train_ {
|
||||
int Ticks; ///< Ticks to complete
|
||||
int Count; ///< Units in training queue
|
||||
// TODO: vladi: later we should train more units or automatic
|
||||
#define MAX_UNIT_TRAIN 6 ///< max number of units in queue
|
||||
UnitType* What[MAX_UNIT_TRAIN]; ///< Unit trained
|
||||
} Train; ///< Train units action
|
||||
} Data; ///< Storage room for different commands
|
||||
|
||||
|
@ -729,6 +730,9 @@ extern int NumTeamSelected[PlayerMax]; ///< Number of Units a team member ha
|
|||
extern Unit* ReleasedHead; ///< Head of the released unit list.
|
||||
extern Unit* ReleasedTail; ///< Tail of the released unit list.
|
||||
|
||||
extern Order* ReleasedOrderHead; ///< Head of the released orders list.
|
||||
extern Order* ReleasedOrderTail; ///< Tail of the released unit list.
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -207,8 +207,6 @@ void ViewportSetViewpoint(Viewport* vp, int x, int y, int offsetx, int offsety)
|
|||
vp->OffsetY = y % TileSizeY;
|
||||
vp->MapWidth = ((vp->EndX - vp->X) + vp->OffsetX - 1) / TileSizeX + 1;
|
||||
vp->MapHeight = ((vp->EndY - vp->Y) + vp->OffsetY - 1) / TileSizeY + 1;
|
||||
|
||||
MustRedraw |= RedrawMinimap | RedrawMinimapCursor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -178,7 +178,6 @@ void MapFixSeenRockTile(int x, int y)
|
|||
// FIXME: can this only happen if seen?
|
||||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +316,6 @@ void MapFixRockTile(int x, int y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +342,6 @@ void MapRemoveRock(unsigned x, unsigned y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
#ifdef MAP_REGIONS
|
||||
MapSplitterTilesCleared(x, y, x, y);
|
||||
|
|
|
@ -165,7 +165,6 @@ void MapFixSeenWallTile(int x, int y)
|
|||
// FIXME: can this only happen if seen?
|
||||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +264,6 @@ void MapFixWallTile(int x, int y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +303,6 @@ void MapRemoveWall(unsigned x, unsigned y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
#ifdef MAP_REGIONS
|
||||
MapSplitterTilesCleared(x, y, x, y);
|
||||
|
@ -347,7 +344,6 @@ void MapSetWall(unsigned x, unsigned y, int humanwall)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
#ifdef MAP_REGIONS
|
||||
MapSplitterTilesOccuped(x, y, x, y);
|
||||
|
|
|
@ -176,7 +176,6 @@ void MapFixSeenWoodTile(int x, int y)
|
|||
// FIXME: can this only happen if seen?
|
||||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +312,6 @@ void MapFixWoodTile(int x, int y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +339,6 @@ void MapRemoveWood(unsigned x, unsigned y)
|
|||
if (IsMapFieldVisible(ThisPlayer, x, y)) {
|
||||
UpdateMinimapSeenXY(x, y);
|
||||
MapMarkSeenTile(x, y);
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
#ifdef MAP_REGIONS
|
||||
MapSplitterTilesCleared(x, y, x, y);
|
||||
|
|
|
@ -729,6 +729,10 @@ int AStarFindPath(Unit* unit, int gx, int gy, int gw, int gh, int minrange, int
|
|||
|
||||
// let's clean up the matrix now
|
||||
AStarCleanUp(num_in_close);
|
||||
if ((TheMap.Width*TheMap.Height) - counter > 500) {
|
||||
DebugPrint("%s:%d Visited %d tiles\n" _C_ unit->Type->Name _C_ UnitNumber(unit)
|
||||
_C_ (TheMap.Width*TheMap.Height) - counter);
|
||||
}
|
||||
return path_length;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "commands.h"
|
||||
#include "cdaudio.h"
|
||||
#include "pathfinder.h"
|
||||
#include "editor.h"
|
||||
|
||||
#ifdef USE_SDLCD
|
||||
#include "SDL.h"
|
||||
|
@ -336,7 +337,7 @@ void DrawMapArea(void)
|
|||
*/
|
||||
void UpdateDisplay(void)
|
||||
{
|
||||
if (EnableRedraw != RedrawMenu) {
|
||||
if (GameRunning || EditorRunning == EditorEditing) {
|
||||
int i;
|
||||
|
||||
DrawMapArea();
|
||||
|
|
|
@ -257,10 +257,6 @@ int SpeedResearch = 1; ///< speed factor for researching
|
|||
== DISPLAY
|
||||
============================================================================*/
|
||||
|
||||
// FIXME: not the correct place
|
||||
int MustRedraw = RedrawEverything; ///< Redraw flags
|
||||
int EnableRedraw = RedrawEverything; ///< Enable flags
|
||||
|
||||
unsigned long GameCycle; ///< Game simulation cycle counter
|
||||
unsigned long FastForwardCycle; ///< Cycle to fastforward to in a replay
|
||||
|
||||
|
@ -664,8 +660,6 @@ void MenuLoop(char* filename, WorldMap* map)
|
|||
PlayMusic(MenuMusic);
|
||||
}
|
||||
|
||||
EnableRedraw = RedrawMenu;
|
||||
|
||||
GuiGameStarted = 0;
|
||||
while (GuiGameStarted == 0) {
|
||||
int old_video_sync;
|
||||
|
@ -673,7 +667,7 @@ void MenuLoop(char* filename, WorldMap* map)
|
|||
old_video_sync = VideoSyncSpeed;
|
||||
VideoSyncSpeed = 100;
|
||||
SetVideoSync();
|
||||
if (EditorRunning == 2) {
|
||||
if (EditorRunning == EditorCommandLine) {
|
||||
SetupEditor();
|
||||
}
|
||||
if (EditorRunning) {
|
||||
|
@ -685,7 +679,6 @@ void MenuLoop(char* filename, WorldMap* map)
|
|||
SetVideoSync();
|
||||
}
|
||||
|
||||
EnableRedraw = RedrawEverything;
|
||||
DebugPrint("Menu start: NetPlayers %d\n" _C_ NetPlayers);
|
||||
filename = CurrentMapPath;
|
||||
} else {
|
||||
|
@ -983,7 +976,7 @@ int main(int argc, char** argv)
|
|||
}
|
||||
continue;
|
||||
case 'e':
|
||||
EditorRunning = 2;
|
||||
EditorRunning = EditorCommandLine;
|
||||
continue;
|
||||
case 'E':
|
||||
EditorStartFile = optarg;
|
||||
|
|
|
@ -811,8 +811,7 @@ void DoButtonButtonClicked(int button)
|
|||
break;
|
||||
|
||||
case ButtonCancelTrain:
|
||||
Assert(Selected[0]->Orders[0].Action == UnitActionTrain &&
|
||||
Selected[0]->Data.Train.Count);
|
||||
Assert(Selected[0]->Orders[0].Action == UnitActionTrain);
|
||||
SendCommandCancelTraining(Selected[0], -1, NULL);
|
||||
ClearStatusLine();
|
||||
ClearCosts();
|
||||
|
@ -848,8 +847,7 @@ void DoButtonButtonClicked(int button)
|
|||
// FIXME: training queue full check is not correct for network.
|
||||
// FIXME: this can be correct written, with a little more code.
|
||||
if (Selected[0]->Orders[0].Action == UnitActionTrain &&
|
||||
(Selected[0]->Data.Train.Count == MAX_UNIT_TRAIN ||
|
||||
!EnableTrainingQueue)) {
|
||||
!EnableTrainingQueue) {
|
||||
NotifyPlayer(Selected[0]->Player, NotifyYellow, Selected[0]->X,
|
||||
Selected[0]->Y, "Unit training queue is full");
|
||||
} else if (PlayerCheckLimits(Selected[0]->Player, type) >= 0 &&
|
||||
|
|
|
@ -461,8 +461,6 @@ static void UiToggleBigMap(void)
|
|||
|
||||
SetViewportMode(TheUI.ViewportMode);
|
||||
|
||||
EnableRedraw = RedrawMap | RedrawCursor | RedrawMessage | RedrawMenu |
|
||||
RedrawTimer | RedrawAll;
|
||||
SetStatusLine("Big map enabled");
|
||||
} else {
|
||||
TheUI.MapArea.X = mapx;
|
||||
|
@ -472,7 +470,6 @@ static void UiToggleBigMap(void)
|
|||
|
||||
SetViewportMode(TheUI.ViewportMode);
|
||||
|
||||
EnableRedraw = RedrawEverything;
|
||||
SetStatusLine("Returning to old map");
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +556,6 @@ static void UiToggleTerrain(void)
|
|||
} else {
|
||||
SetStatusLine("Terrain hidden.");
|
||||
}
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -375,20 +375,20 @@ static void DrawUnitInfo(const Unit* unit)
|
|||
// Building training units.
|
||||
//
|
||||
if (unit->Orders[0].Action == UnitActionTrain) {
|
||||
if (unit->Data.Train.Count == 1) {
|
||||
if (unit->Orders[1].Action != UnitActionTrain) {
|
||||
if (TheUI.SingleTrainingText) {
|
||||
VideoDrawText(TheUI.SingleTrainingTextX, TheUI.SingleTrainingTextY,
|
||||
TheUI.SingleTrainingFont, TheUI.SingleTrainingText);
|
||||
}
|
||||
if (TheUI.SingleTrainingButton) {
|
||||
DrawUnitIcon(unit->Player, unit->Data.Train.What[0]->Icon.Icon,
|
||||
DrawUnitIcon(unit->Player, unit->Orders[0].Type->Icon.Icon,
|
||||
(ButtonAreaUnderCursor == ButtonAreaTraining &&
|
||||
ButtonUnderCursor == 0) ?
|
||||
(IconActive | (MouseButtons & LeftButton)) : 0,
|
||||
TheUI.SingleTrainingButton->X, TheUI.SingleTrainingButton->Y);
|
||||
}
|
||||
|
||||
UiDrawCompletedBar(unit->Data.Train.What[0]->Stats[
|
||||
UiDrawCompletedBar(unit->Orders[0].Type->Stats[
|
||||
unit->Player->Player].Costs[TimeCost],
|
||||
unit->Data.Train.Ticks);
|
||||
} else {
|
||||
|
@ -397,17 +397,19 @@ static void DrawUnitInfo(const Unit* unit)
|
|||
TheUI.TrainingFont, TheUI.TrainingText);
|
||||
}
|
||||
if (TheUI.TrainingButtons) {
|
||||
for (i = 0; i < unit->Data.Train.Count &&
|
||||
for (i = 0; i < unit->OrderCount &&
|
||||
i < TheUI.NumTrainingButtons; ++i) {
|
||||
DrawUnitIcon(unit->Player, unit->Data.Train.What[i]->Icon.Icon,
|
||||
(ButtonAreaUnderCursor == ButtonAreaTraining &&
|
||||
ButtonUnderCursor == i) ?
|
||||
(IconActive | (MouseButtons & LeftButton)) : 0,
|
||||
TheUI.TrainingButtons[i].X, TheUI.TrainingButtons[i].Y);
|
||||
if (unit->Orders[i].Action == UnitActionTrain) {
|
||||
DrawUnitIcon(unit->Player, unit->Orders[i].Type->Icon.Icon,
|
||||
(ButtonAreaUnderCursor == ButtonAreaTraining &&
|
||||
ButtonUnderCursor == i) ?
|
||||
(IconActive | (MouseButtons & LeftButton)) : 0,
|
||||
TheUI.TrainingButtons[i].X, TheUI.TrainingButtons[i].Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UiDrawCompletedBar(unit->Data.Train.What[0]->Stats[
|
||||
UiDrawCompletedBar(unit->Orders[0].Type->Stats[
|
||||
unit->Player->Player].Costs[TimeCost],
|
||||
unit->Data.Train.Ticks);
|
||||
}
|
||||
|
|
|
@ -1837,7 +1837,6 @@ static void SetFogOfWar(Menuitem *mi __attribute__((unused)))
|
|||
UpdateFogOfWarChange();
|
||||
CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, "fow on", -1);
|
||||
}
|
||||
MustRedraw &= ~RedrawMinimap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4718,7 +4717,7 @@ static void StartEditor(void)
|
|||
{
|
||||
SetupEditor();
|
||||
|
||||
EditorRunning = 1;
|
||||
EditorRunning = EditorStarted;
|
||||
EndMenu();
|
||||
}
|
||||
|
||||
|
@ -4763,7 +4762,7 @@ void SetupEditor(void)
|
|||
static void EditorSelectCancel(void)
|
||||
{
|
||||
QuitToMenu = 1;
|
||||
EditorRunning = 0;
|
||||
EditorRunning = EditorNotRunning;
|
||||
EndMenu();
|
||||
}
|
||||
|
||||
|
@ -5349,7 +5348,7 @@ void EditorLoadMenu(void)
|
|||
}
|
||||
|
||||
EditorMapLoaded = 1;
|
||||
EditorRunning = 0;
|
||||
EditorRunning = EditorNotRunning;
|
||||
EndMenu();
|
||||
}
|
||||
|
||||
|
@ -6193,7 +6192,7 @@ static void EditorSaveConfirmCancel(void)
|
|||
static void EditorQuitToMenu(void)
|
||||
{
|
||||
QuitToMenu = 1;
|
||||
EditorRunning = 0;
|
||||
EditorRunning = EditorNotRunning;
|
||||
EndMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -445,7 +445,7 @@ static void HandleMouseOn(int x, int y)
|
|||
}
|
||||
if (NumSelected == 1 && Selected[0]->Type->Building && !BigMapMode) {
|
||||
if (Selected[0]->Orders[0].Action == UnitActionTrain) {
|
||||
if (Selected[0]->Data.Train.Count == 1) {
|
||||
if (Selected[0]->OrderCount == 1) {
|
||||
if (TheUI.SingleTrainingButton &&
|
||||
x >= TheUI.SingleTrainingButton->X &&
|
||||
x < TheUI.SingleTrainingButton->X + TheUI.SingleTrainingButton->Width + 7 &&
|
||||
|
@ -457,10 +457,10 @@ static void HandleMouseOn(int x, int y)
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
i = (TheUI.NumTrainingButtons < Selected[0]->Data.Train.Count) ?
|
||||
TheUI.NumTrainingButtons : Selected[0]->Data.Train.Count;
|
||||
for (--i; i >= 0; --i) {
|
||||
if (x >= TheUI.TrainingButtons[i].X &&
|
||||
for (i = 0; i < Selected[0]->OrderCount &&
|
||||
i < TheUI.NumTrainingButtons; ++i) {
|
||||
if (Selected[0]->Orders[i].Action == UnitActionTrain &&
|
||||
x >= TheUI.TrainingButtons[i].X &&
|
||||
x < TheUI.TrainingButtons[i].X + TheUI.TrainingButtons[i].Width + 7 &&
|
||||
y >= TheUI.TrainingButtons[i].Y &&
|
||||
y < TheUI.TrainingButtons[i].Y + TheUI.TrainingButtons[i].Height + 7) {
|
||||
|
@ -1482,7 +1482,6 @@ void UIHandleButtonDown(unsigned button)
|
|||
if (NumSelected && Selected[0]->Player == ThisPlayer &&
|
||||
CursorState == CursorStatePoint) {
|
||||
CursorState = CursorStatePieMenu;
|
||||
MustRedraw |= RedrawCursor;
|
||||
}
|
||||
} else if (MouseButtons & LeftButton) { // enter select mode
|
||||
CursorStartX = CursorX;
|
||||
|
@ -1587,13 +1586,14 @@ void UIHandleButtonDown(unsigned button)
|
|||
} else if (ButtonAreaUnderCursor == ButtonAreaTraining) {
|
||||
if (!GameObserve && !GamePaused &&
|
||||
PlayersTeamed(ThisPlayer->Player, Selected[0]->Player->Player)) {
|
||||
if (ButtonUnderCursor < Selected[0]->Data.Train.Count) {
|
||||
if (ButtonUnderCursor < Selected[0]->OrderCount &&
|
||||
Selected[0]->Orders[ButtonUnderCursor].Action == UnitActionTrain) {
|
||||
DebugPrint("Cancel slot %d %s\n" _C_
|
||||
ButtonUnderCursor _C_
|
||||
Selected[0]->Data.Train.What[ButtonUnderCursor]->Ident);
|
||||
Selected[0]->Orders[ButtonUnderCursor].Type->Ident);
|
||||
SendCommandCancelTraining(Selected[0],
|
||||
ButtonUnderCursor,
|
||||
Selected[0]->Data.Train.What[ButtonUnderCursor]);
|
||||
Selected[0]->Orders[ButtonUnderCursor].Type);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
|
|
@ -348,12 +348,9 @@ void CclParseOrder(lua_State* l, Order* order)
|
|||
*/
|
||||
static void CclParseOrders(lua_State* l, Unit* unit)
|
||||
{
|
||||
int args;
|
||||
int j;
|
||||
|
||||
args = luaL_getn(l, -1);
|
||||
Assert(args == MAX_ORDERS);
|
||||
for (j = 0; j < args; ++j) {
|
||||
for (j = 0; j < unit->TotalOrders; ++j) {
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
CclParseOrder(l, &unit->Orders[j]);
|
||||
lua_pop(l, 1);
|
||||
|
@ -514,7 +511,6 @@ static void CclParseUpgradeTo(lua_State* l, Unit* unit)
|
|||
static void CclParseTrain(lua_State* l, Unit* unit)
|
||||
{
|
||||
const char* value;
|
||||
int i;
|
||||
int args;
|
||||
int j;
|
||||
|
||||
|
@ -531,30 +527,6 @@ static void CclParseTrain(lua_State* l, Unit* unit)
|
|||
lua_rawgeti(l, -1, j + 1);
|
||||
unit->Data.Train.Ticks = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "count")) {
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
unit->Data.Train.Count = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "queue")) {
|
||||
int subargs;
|
||||
int k;
|
||||
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
if (!lua_istable(l, -1)) {
|
||||
LuaError(l, "incorrect argument");
|
||||
}
|
||||
subargs = luaL_getn(l, -1);
|
||||
for (i = 0, k = 0; i < MAX_UNIT_TRAIN && k < subargs; ++i, ++k) {
|
||||
lua_rawgeti(l, -1, k + 1);
|
||||
value = LuaToString(l, -1);
|
||||
lua_pop(l, 1);
|
||||
if (!strcmp(value, "unit-none")) {
|
||||
unit->Data.Train.What[i] = NULL;
|
||||
} else {
|
||||
unit->Data.Train.What[i] = UnitTypeByIdent(value);
|
||||
}
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -859,6 +831,11 @@ static int CclUnit(lua_State* l)
|
|||
unit->OrderCount = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "order-flush")) {
|
||||
unit->OrderFlush = LuaToNumber(l, j + 1);
|
||||
} else if (!strcmp(value, "order-total")) {
|
||||
unit->TotalOrders = LuaToNumber(l, j + 1);
|
||||
free(unit->Orders);
|
||||
// Allocate the space for orders
|
||||
unit->Orders = calloc(unit->TotalOrders, sizeof(Order));
|
||||
} else if (!strcmp(value, "orders")) {
|
||||
int hp;
|
||||
|
||||
|
|
|
@ -74,6 +74,9 @@ Unit** UnitSlotFree; ///< First free unit slot
|
|||
Unit* ReleasedHead; ///< List of released units.
|
||||
Unit* ReleasedTail; ///< List tail of released units.
|
||||
|
||||
Order* ReleasedOrderHead; ///< List of released Orders.
|
||||
Order* ReleasedOrderTail; ///< List tail of released orders.
|
||||
|
||||
Unit* Units[MAX_UNIT_SLOTS]; ///< Array of used slots
|
||||
int NumUnits; ///< Number of slots used
|
||||
|
||||
|
@ -225,6 +228,18 @@ void ReleaseUnit(Unit* unit)
|
|||
unit->Refs = GameCycle + (NetworkMaxLag << 1); // could be reuse after this time
|
||||
unit->Type = 0; // for debugging.
|
||||
free(unit->CacheLinks);
|
||||
|
||||
if (ReleasedOrderHead) {
|
||||
ReleasedOrderTail->Arg1 = unit->Orders;
|
||||
ReleasedOrderTail = unit->Orders;
|
||||
unit->Orders->Arg1 = NULL;
|
||||
} else {
|
||||
ReleasedOrderHead = ReleasedOrderTail = unit->Orders;
|
||||
unit->Orders->Arg1 = NULL;
|
||||
}
|
||||
unit->Orders->X = GameCycle + (NetworkMaxLag << 1); // could be reuse after this time
|
||||
unit->Orders->Y = unit->TotalOrders; // store order count for when reused
|
||||
unit->Orders = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,6 +354,18 @@ void InitUnit(Unit* unit, UnitType* type)
|
|||
|
||||
unit->Rs = MyRand() % 100; // used for fancy buildings and others
|
||||
|
||||
// Init Orders and Default to Still/None
|
||||
if (ReleasedOrderHead && (unsigned)ReleasedOrderHead->X < GameCycle) {
|
||||
unit->Orders = ReleasedOrderHead;
|
||||
unit->TotalOrders = ReleasedOrderHead->Y;
|
||||
ReleasedOrderHead = (Order*)ReleasedOrderHead->Arg1;
|
||||
} else {
|
||||
// No Available Orders in Memory, create new ones
|
||||
unit->TotalOrders = DEFAULT_START_ORDERS;
|
||||
unit->Orders = calloc(unit->TotalOrders, sizeof(Order));
|
||||
}
|
||||
|
||||
|
||||
unit->OrderCount = 1; // No orders
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->Orders[0].X = unit->Orders[0].Y = -1;
|
||||
|
@ -596,7 +623,6 @@ static void MarkUnitFieldFlags(const Unit* unit)
|
|||
MapSplitterTilesOccuped(x, y, x + type->TileWidth - 1, y + type->TileHeight - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -761,7 +787,6 @@ void PlaceUnit(Unit* unit, int x, int y)
|
|||
// Vision
|
||||
MapMarkUnitSight(unit);
|
||||
|
||||
MustRedraw |= RedrawMinimap;
|
||||
UnitCountSeen(unit);
|
||||
}
|
||||
|
||||
|
@ -832,7 +857,6 @@ void RemoveUnit(Unit* unit, Unit* host)
|
|||
if (unit == UnitUnderCursor) {
|
||||
UnitUnderCursor = NULL;
|
||||
}
|
||||
MustRedraw |= RedrawMinimap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3576,8 +3600,9 @@ void SaveUnit(const Unit* unit, CLFile* file)
|
|||
}
|
||||
CLprintf(file, "\"order-count\", %d,\n ", unit->OrderCount);
|
||||
CLprintf(file, "\"order-flush\", %d,\n ", unit->OrderFlush);
|
||||
CLprintf(file, "\"order-total\", %d,\n ", unit->TotalOrders);
|
||||
CLprintf(file, "\"orders\", {");
|
||||
for (i = 0; i < MAX_ORDERS; ++i) {
|
||||
for (i = 0; i < unit->TotalOrders; ++i) {
|
||||
CLprintf(file, "\n ");
|
||||
SaveOrder(&unit->Orders[i], file);
|
||||
CLprintf(file, ",");
|
||||
|
@ -3643,17 +3668,7 @@ void SaveUnit(const Unit* unit, CLFile* file)
|
|||
case UnitActionTrain:
|
||||
CLprintf(file, ",\n \"data-train\", {");
|
||||
CLprintf(file, "\"ticks\", %d, ", unit->Data.Train.Ticks);
|
||||
CLprintf(file, "\"count\", %d, ", unit->Data.Train.Count);
|
||||
CLprintf(file, "\"queue\", {");
|
||||
for (i = 0; i < MAX_UNIT_TRAIN; ++i) {
|
||||
if (i < unit->Data.Train.Count) {
|
||||
CLprintf(file, "\"%s\", ", unit->Data.Train.What[i]->Ident);
|
||||
} else {
|
||||
/* this slot is currently unused */
|
||||
CLprintf(file, "\"unit-none\", ");
|
||||
}
|
||||
}
|
||||
CLprintf(file, "}}");
|
||||
CLprintf(file, "}");
|
||||
break;
|
||||
default:
|
||||
CLprintf(file, ",\n \"data-move\", {");
|
||||
|
@ -3791,6 +3806,7 @@ void CleanUnits(void)
|
|||
{
|
||||
Unit** table;
|
||||
Unit* unit;
|
||||
Order* order;
|
||||
|
||||
//
|
||||
// Free memory for all units in unit table.
|
||||
|
@ -3809,6 +3825,14 @@ void CleanUnits(void)
|
|||
ReleasedHead = unit->Next;
|
||||
free(unit);
|
||||
}
|
||||
|
||||
//
|
||||
// Release memory of Orders in the release queue.
|
||||
while ((order = ReleasedOrderHead)) {
|
||||
ReleasedOrderHead = order->Arg1;
|
||||
free(order);
|
||||
}
|
||||
|
||||
InitUnitsMemory();
|
||||
|
||||
XpDamage = 0;
|
||||
|
|
|
@ -1083,7 +1083,7 @@ static void DrawDecoration(const Unit* unit, const UnitType* type, int x, int y)
|
|||
if (unit->Orders[0].Action == UnitActionTrain) {
|
||||
unit->Variable[TRAINING_INDEX].Value = unit->Data.Train.Ticks;
|
||||
unit->Variable[TRAINING_INDEX].Max =
|
||||
unit->Data.Train.What[0]->Stats[unit->Player->Player].Costs[TimeCost];
|
||||
unit->Orders[0].Type->Stats[unit->Player->Player].Costs[TimeCost];
|
||||
}
|
||||
|
||||
// UpgradeTo
|
||||
|
|
|
@ -1165,16 +1165,16 @@ static void ConvertUnitTypeTo(Player* player, const UnitType* src, UnitType* dst
|
|||
// FIXME: what about buildings?
|
||||
//
|
||||
} else {
|
||||
if (unit->Orders[0].Action == UnitActionTrain) {
|
||||
for (j = 0; j < unit->Data.Train.Count; ++j) {
|
||||
if (unit->Data.Train.What[j] == src) {
|
||||
unit->Data.Train.What[j] = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 1; j < unit->OrderCount; ++j) {
|
||||
for (j = 0; j < unit->OrderCount; ++j) {
|
||||
if (unit->Orders[j].Action == UnitActionTrain &&
|
||||
unit->Orders[j].Type == src) {
|
||||
if (j == 0) {
|
||||
// Must Adjust Ticks to the fraction that was trained
|
||||
unit->Data.Train.Ticks =
|
||||
unit->Data.Train.Ticks *
|
||||
dst->Stats[player->Player].Costs[TimeCost] /
|
||||
src->Stats[player->Player].Costs[TimeCost];
|
||||
}
|
||||
unit->Orders[j].Type = dst;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue