Add COrder_Built
This commit is contained in:
parent
0ad3061456
commit
58f777c425
22 changed files with 482 additions and 455 deletions
src
action
include
map
pathfinder
stratagus
ui
unit
|
@ -49,42 +49,13 @@
|
|||
#include "interface.h"
|
||||
#include "pathfinder.h"
|
||||
#include "construct.h"
|
||||
#include "iolib.h"
|
||||
#include "script.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
** Update construction frame
|
||||
**
|
||||
** @param unit The building under construction.
|
||||
*/
|
||||
static void UpdateConstructionFrame(CUnit &unit)
|
||||
{
|
||||
CConstructionFrame *cframe;
|
||||
CConstructionFrame *tmp;
|
||||
int percent;
|
||||
|
||||
percent = unit.CurrentOrder()->Data.Built.Progress /
|
||||
(unit.Type->Stats[unit.Player->Index].Costs[TimeCost] * 6);
|
||||
cframe = tmp = unit.Type->Construction->Frames;
|
||||
while (tmp) {
|
||||
if (percent < tmp->Percent) {
|
||||
break;
|
||||
}
|
||||
cframe = tmp;
|
||||
tmp = tmp->Next;
|
||||
}
|
||||
if (cframe != unit.CurrentOrder()->Data.Built.Frame) {
|
||||
unit.CurrentOrder()->Data.Built.Frame = cframe;
|
||||
if (unit.Frame < 0) {
|
||||
unit.Frame = -cframe->Frame - 1;
|
||||
} else {
|
||||
unit.Frame = cframe->Frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Move to build location
|
||||
**
|
||||
|
@ -287,7 +258,8 @@ static void StartBuilding(CUnit &unit, CUnit &ontop)
|
|||
}
|
||||
|
||||
// Must set action before placing, otherwise it will incorrectly mark radar
|
||||
build->CurrentOrder()->Action = UnitActionBuilt;
|
||||
delete build->CurrentOrder();
|
||||
build->Orders[0] = COrder::NewActionBuilt(unit, *build);
|
||||
|
||||
// Must place after previous for map flags
|
||||
build->Place(pos);
|
||||
|
@ -298,18 +270,10 @@ static void StartBuilding(CUnit &unit, CUnit &ontop)
|
|||
// HACK: the building is not ready yet
|
||||
build->Player->UnitTypesCount[type.Slot]--;
|
||||
|
||||
// Make sure the bulding doesn't cancel itself out right away.
|
||||
build->CurrentOrder()->Data.Built.Progress = 0;//FIXME ? 100 : 0
|
||||
build->Variable[HP_INDEX].Value = 1;
|
||||
if (build->Variable[SHIELD_INDEX].Max)
|
||||
build->Variable[SHIELD_INDEX].Value = 1;
|
||||
UpdateConstructionFrame(*build);
|
||||
|
||||
// We need somebody to work on it.
|
||||
if (!type.BuilderOutside) {
|
||||
//FIXME: cancel buld gen crash
|
||||
// Place the builder inside the building
|
||||
build->CurrentOrder()->Data.Built.Worker = &unit;
|
||||
// HACK: allows the unit to be removed
|
||||
build->CurrentSightRange = 1;
|
||||
//HACK: reset anim
|
||||
|
@ -337,7 +301,6 @@ static void StartBuilding(CUnit &unit, CUnit &ontop)
|
|||
// Mark the new building seen.
|
||||
MapMarkUnitSight(*build);
|
||||
}
|
||||
UpdateConstructionFrame(*build);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,48 +322,6 @@ static void BuildBuilding(CUnit &unit)
|
|||
//
|
||||
//int animlength = unit.Data.Build.Cycles;
|
||||
unit.CurrentOrder()->Data.Build.Cycles = 0;
|
||||
#if 0
|
||||
CUnit *goal;
|
||||
int hp;
|
||||
|
||||
//goal hp are mod by HandleActionBuilt
|
||||
//and outsid builder use repair now.
|
||||
goal = unit.CurrentOrder()->GetGoal();
|
||||
//Assert(goal);
|
||||
if(!goal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (goal->CurrentAction() == UnitActionDie) {
|
||||
unit.CurrentOrder()->ClearGoal();
|
||||
unit.State = 0;
|
||||
unit.ClearAction();
|
||||
return;
|
||||
}
|
||||
|
||||
// hp is the current damage taken by the unit.
|
||||
hp = (goal->CurrentOrder()->Data.Built.Progress * goal->Variable[HP_INDEX].Max) /
|
||||
(goal->Stats->Costs[TimeCost] * 600) - goal->Variable[HP_INDEX].Value;
|
||||
|
||||
// FIXME: implement this below:
|
||||
// unit.CurrentOrder()->Data.Built.Worker->Type->BuilderSpeedFactor;
|
||||
goal->CurrentOrder()->Data.Built.Progress += 100 * animlength * SpeedBuild;
|
||||
// Keep the same level of damage while increasing HP.
|
||||
goal->Variable[HP_INDEX].Value = (goal->Data.Built.Progress * goal->Variable[HP_INDEX].Max) /
|
||||
(goal->Stats->Costs[TimeCost] * 600) - hp;
|
||||
if (goal->Variable[HP_INDEX].Value > goal->Variable[HP_INDEX].Max) {
|
||||
goal->Variable[HP_INDEX].Value = goal->Variable[HP_INDEX].Max;
|
||||
}
|
||||
|
||||
//
|
||||
// Building is gone or finished
|
||||
//
|
||||
if (goal->Variable[HP_INDEX].Value == goal->Variable[HP_INDEX].Max) {
|
||||
unit.CurrentOrder()->ClearGoal();
|
||||
unit.State = 0;
|
||||
unit.ClearAction();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,6 +346,317 @@ 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\", ");
|
||||
|
||||
CConstructionFrame *cframe = unit.Type->Construction->Frames;
|
||||
int frame = 0;
|
||||
while (cframe != this->Data.Frame) {
|
||||
cframe = cframe->Next;
|
||||
++frame;
|
||||
}
|
||||
if (this->Data.Worker == NULL) {
|
||||
file.printf("\"worker\", \"%s\", ", UnitReference(this->Data.Worker).c_str());
|
||||
}
|
||||
file.printf("\"progress\", %d, \"frame\", %d", this->Data.Progress, frame);
|
||||
if (this->Data.Cancel) {
|
||||
file.printf(", \"cancel\"");
|
||||
}
|
||||
file.printf("}");
|
||||
}
|
||||
|
||||
/* virtual */ bool COrder_Built::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
|
||||
{
|
||||
if (!strcmp(value, "worker")) {
|
||||
++j;
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
this->Data.Worker = CclGetUnitFromRef(l);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "progress")) {
|
||||
++j;
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
this->Data.Progress = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "cancel")) {
|
||||
this->Data.Cancel = 1;
|
||||
} else if (!strcmp(value, "frame")) {
|
||||
++j;
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
int frame = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
CConstructionFrame *cframe = unit.Type->Construction->Frames;
|
||||
while (frame--) {
|
||||
cframe = cframe->Next;
|
||||
}
|
||||
this->Data.Frame = cframe;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void CancelBuilt(COrder_Built &order, CUnit &unit)
|
||||
{
|
||||
Assert(unit.CurrentOrder() == &order);
|
||||
CUnit *worker = order.GetWorkerPtr();
|
||||
|
||||
// Drop out unit
|
||||
if (worker != NULL) {
|
||||
|
||||
|
||||
|
||||
worker->ClearAction();
|
||||
|
||||
// HACK: make sure the sight is updated correctly
|
||||
// unit.CurrentSightRange = 1;
|
||||
DropOutOnSide(*worker, LookingW, &unit);
|
||||
// unit.CurrentSightRange = 0;
|
||||
}
|
||||
|
||||
// Player gets back 75% of the original cost for a building.
|
||||
unit.Player->AddCostsFactor(unit.Stats->Costs, CancelBuildingCostsFactor);
|
||||
// Cancel building
|
||||
LetUnitDie(unit);
|
||||
}
|
||||
|
||||
static bool Finish(COrder_Built &order, CUnit& unit)
|
||||
{
|
||||
const CUnitType &type = *unit.Type;
|
||||
CPlayer &player = *unit.Player;
|
||||
|
||||
DebugPrint("%d: Building %s(%s) ready.\n" _C_ player.Index _C_ type.Ident.c_str() _C_ type.Name.c_str() );
|
||||
|
||||
// HACK: the building is ready now
|
||||
player.UnitTypesCount[type.Slot]++;
|
||||
unit.Constructed = 0;
|
||||
if (unit.Frame < 0) {
|
||||
unit.Frame = -1;
|
||||
} else {
|
||||
unit.Frame = 0;
|
||||
}
|
||||
CUnit *worker = order.GetWorkerPtr();
|
||||
|
||||
if (worker != NULL) {
|
||||
if (type.BuilderLost) {
|
||||
// Bye bye worker.
|
||||
LetUnitDie(*worker);
|
||||
worker = NULL;
|
||||
} else { // Drop out the worker.
|
||||
worker->ClearAction();
|
||||
#if 0
|
||||
// HACK: make sure the sight is updated correctly
|
||||
// unit.CurrentSightRange = 1;
|
||||
#endif
|
||||
DropOutOnSide(*worker, LookingW, &unit);
|
||||
|
||||
// If we can harvest from the new building, do it.
|
||||
if (worker->Type->ResInfo[type.GivesResource]) {
|
||||
CommandResource(*worker, unit, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type.GivesResource && type.StartingResources != 0) {
|
||||
// Has StartingResources, Use those
|
||||
unit.ResourcesHeld = type.StartingResources;
|
||||
}
|
||||
|
||||
player.Notify(NotifyGreen, unit.tilePos.x, unit.tilePos.y, _("New %s done"), type.Name.c_str());
|
||||
if (&player == ThisPlayer) {
|
||||
if (type.Sound.Ready.Sound) {
|
||||
PlayUnitSound(unit, VoiceReady);
|
||||
} else if (worker) {
|
||||
PlayUnitSound(*worker, VoiceWorkCompleted);
|
||||
} else {
|
||||
PlayUnitSound(unit, VoiceBuilding);
|
||||
}
|
||||
}
|
||||
|
||||
if (player.AiEnabled) {
|
||||
/* Worker can be NULL */
|
||||
AiWorkComplete(worker, unit);
|
||||
}
|
||||
|
||||
// FIXME: Vladi: this is just a hack to test wall fixing,
|
||||
// FIXME: also not sure if the right place...
|
||||
// FIXME: Johns: hardcoded unit-type wall / more races!
|
||||
if (&type == UnitTypeOrcWall || &type == UnitTypeHumanWall) {
|
||||
Map.SetWall(unit.tilePos, &type == UnitTypeHumanWall);
|
||||
unit.Remove(NULL);
|
||||
UnitLost(unit);
|
||||
UnitClearOrders(unit);
|
||||
unit.Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateForNewUnit(unit, 0);
|
||||
|
||||
// Set the direction of the building if it supports them
|
||||
if (type.NumDirections > 1) {
|
||||
if (type.Wall) { // Special logic for walls
|
||||
CorrectWallDirections(unit);
|
||||
CorrectWallNeighBours(unit);
|
||||
} else {
|
||||
unit.Direction = (MyRand() >> 8) & 0xFF; // random heading
|
||||
}
|
||||
UnitUpdateHeading(unit);
|
||||
}
|
||||
|
||||
if (IsOnlySelected(unit) || &player == ThisPlayer) {
|
||||
SelectedUnitChanged();
|
||||
}
|
||||
MapUnmarkUnitSight(unit);
|
||||
unit.CurrentSightRange = unit.Stats->Variables[SIGHTRANGE_INDEX].Max;
|
||||
MapMarkUnitSight(unit);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* virtual */ bool COrder_Built::Execute(CUnit &unit)
|
||||
{
|
||||
const CUnitType &type = *unit.Type;
|
||||
|
||||
int amount;
|
||||
if (type.BuilderOutside) {
|
||||
amount = type.AutoBuildRate;
|
||||
} else {
|
||||
// FIXME: implement this below:
|
||||
// this->Data.Worker->Type->BuilderSpeedFactor;
|
||||
amount = 100;
|
||||
}
|
||||
this->Progress(unit, amount);
|
||||
|
||||
// Check if construction should be canceled...
|
||||
if (this->Data.Cancel || this->Data.Progress < 0) {
|
||||
DebugPrint("%d: %s canceled.\n" _C_ unit.Player->Index _C_ unit.Type->Name.c_str());
|
||||
|
||||
CancelBuilt(*this, unit);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int maxProgress = type.Stats[unit.Player->Index].Costs[TimeCost] * 600;
|
||||
|
||||
// Check if building ready. Note we can both build and repair.
|
||||
if (!unit.Anim.Unbreakable && this->Data.Progress >= maxProgress) {
|
||||
return Finish(*this, unit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */ void COrder_Built::Cancel(CUnit &unit)
|
||||
{
|
||||
this->Data.Cancel = 1;
|
||||
}
|
||||
|
||||
/* virtual */ void COrder_Built::UpdateUnitVariables(CUnit &unit) const
|
||||
{
|
||||
Assert(unit.CurrentOrder() == this);
|
||||
|
||||
unit.Variable[BUILD_INDEX].Value = this->Data.Progress;
|
||||
unit.Variable[BUILD_INDEX].Max = unit.Type->Stats[unit.Player->Index].Costs[TimeCost] * 600;
|
||||
|
||||
// This should happen when building unit with several peons
|
||||
// Maybe also with only one.
|
||||
// FIXME : Should be better to fix it in action_{build,repair}.c ?
|
||||
if (unit.Variable[BUILD_INDEX].Value > unit.Variable[BUILD_INDEX].Max) {
|
||||
// assume value is wrong.
|
||||
unit.Variable[BUILD_INDEX].Value = unit.Variable[BUILD_INDEX].Max;
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ void COrder_Built::FillSeenValues(CUnit &unit) const
|
||||
{
|
||||
unit.Seen.State = 1;
|
||||
unit.Seen.CFrame = this->Data.Frame;
|
||||
}
|
||||
|
||||
|
||||
static const CConstructionFrame *FindCFramePercent(const CConstructionFrame &cframe, int percent)
|
||||
{
|
||||
const CConstructionFrame *prev = &cframe;
|
||||
|
||||
for (const CConstructionFrame *it = cframe.Next; it; it = it->Next) {
|
||||
if (percent < it->Percent) {
|
||||
return prev;
|
||||
}
|
||||
prev = it;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
** Update construction frame
|
||||
**
|
||||
** @param unit The building under construction.
|
||||
*/
|
||||
void COrder_Built::UpdateConstructionFrame(CUnit &unit)
|
||||
{
|
||||
const CUnitType &type = *unit.Type;
|
||||
const int percent = this->Data.Progress / (type.Stats[unit.Player->Index].Costs[TimeCost] * 6);
|
||||
const CConstructionFrame *cframe = FindCFramePercent(*type.Construction->Frames, percent);
|
||||
|
||||
Assert(cframe != NULL);
|
||||
|
||||
if (cframe != this->Data.Frame) {
|
||||
this->Data.Frame = cframe;
|
||||
if (unit.Frame < 0) {
|
||||
unit.Frame = -cframe->Frame - 1;
|
||||
} else {
|
||||
unit.Frame = cframe->Frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COrder_Built::Progress(CUnit &unit, int amount)
|
||||
{
|
||||
Boost(unit, amount, HP_INDEX);
|
||||
Boost(unit, amount, SHIELD_INDEX);
|
||||
|
||||
this->Data.Progress += amount * SpeedBuild;
|
||||
UpdateConstructionFrame(unit);
|
||||
}
|
||||
|
||||
void COrder_Built::ProgressHp(CUnit &unit, int amount)
|
||||
{
|
||||
Boost(unit, amount, HP_INDEX);
|
||||
|
||||
this->Data.Progress += amount * SpeedBuild;
|
||||
UpdateConstructionFrame(unit);
|
||||
}
|
||||
|
||||
|
||||
void COrder_Built::Boost(CUnit &building, int amount, int varIndex) const
|
||||
{
|
||||
Assert(building.CurrentOrder() == this);
|
||||
|
||||
const int costs = building.Stats->Costs[TimeCost] * 600;
|
||||
const int progress = this->Data.Progress;
|
||||
const int newProgress = progress + amount * SpeedBuild;
|
||||
const int maxValue = building.Variable[varIndex].Max;
|
||||
|
||||
int ¤tValue = building.Variable[varIndex].Value;
|
||||
|
||||
// damageValue is the current damage taken by the unit.
|
||||
const int damageValue = (progress * maxValue) / costs - currentValue;
|
||||
|
||||
// Keep the same level of damage while increasing Value.
|
||||
currentValue = (newProgress * maxValue) / costs - damageValue;
|
||||
currentValue = std::min(currentValue, maxValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** Unit under Construction
|
||||
**
|
||||
|
@ -432,183 +664,12 @@ void HandleActionBuild(COrder& /*order*/, CUnit &unit)
|
|||
*/
|
||||
void HandleActionBuilt(COrder& order, CUnit &unit)
|
||||
{
|
||||
CUnit *worker;
|
||||
CUnitType *type;
|
||||
int n, mod;
|
||||
int progress, oldprogress;
|
||||
//For shields
|
||||
int sn, smod;
|
||||
Assert(order.Action == UnitActionBuilt);
|
||||
|
||||
type = unit.Type;
|
||||
|
||||
// mod is use for round to upper
|
||||
mod = (unit.Stats->Costs[TimeCost] * 600) - unit.Variable[HP_INDEX].Value;
|
||||
smod = (unit.Stats->Costs[TimeCost] * 600) - unit.Variable[SHIELD_INDEX].Value;
|
||||
|
||||
// n is the current damage taken by the unit.
|
||||
n = (order.Data.Built.Progress * unit.Variable[HP_INDEX].Max + (mod - 1)) / mod;
|
||||
sn = (order.Data.Built.Progress * unit.Variable[SHIELD_INDEX].Max + (smod - 1)) / smod;
|
||||
|
||||
// This below is most often 0
|
||||
if (type->BuilderOutside) {
|
||||
progress = unit.Type->AutoBuildRate;
|
||||
} else {
|
||||
progress = 100;
|
||||
// FIXME: implement this below:
|
||||
// unit.Data.Built.Worker->Type->BuilderSpeedFactor;
|
||||
}
|
||||
// Building speeds increase or decrease.
|
||||
progress *= SpeedBuild;
|
||||
oldprogress = order.Data.Built.Progress;
|
||||
order.Data.Built.Progress += progress;
|
||||
// mod is use for round to upper and use it as cache
|
||||
mod = type->Stats[unit.Player->Index].Costs[TimeCost] * 600;
|
||||
|
||||
// Keep the same level of damage while increasing HP.
|
||||
unit.Variable[HP_INDEX].Value +=
|
||||
(order.Data.Built.Progress * unit.Variable[HP_INDEX].Max + (mod - n - 1)) / (mod - n) -
|
||||
(oldprogress * unit.Variable[HP_INDEX].Max + (mod - n - 1)) / (mod - n);
|
||||
if (unit.Variable[HP_INDEX].Value > unit.Stats->Variables[HP_INDEX].Max) {
|
||||
unit.Variable[HP_INDEX].Value = unit.Stats->Variables[HP_INDEX].Max;
|
||||
}
|
||||
if (unit.Variable[SHIELD_INDEX].Max > 0)
|
||||
{
|
||||
unit.Variable[SHIELD_INDEX].Value +=
|
||||
(order.Data.Built.Progress * unit.Variable[SHIELD_INDEX].Max + (mod - sn - 1)) / (mod - sn) -
|
||||
(oldprogress * unit.Variable[SHIELD_INDEX].Max + (mod - sn - 1)) / (mod - sn);
|
||||
if (unit.Variable[SHIELD_INDEX].Value > unit.Stats->Variables[SHIELD_INDEX].Max) {
|
||||
unit.Variable[SHIELD_INDEX].Value = unit.Stats->Variables[SHIELD_INDEX].Max;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if construction should be canceled...
|
||||
if (order.Data.Built.Cancel || order.Data.Built.Progress < 0) {
|
||||
DebugPrint("%d: %s canceled.\n" _C_ unit.Player->Index _C_ unit.Type->Name.c_str());
|
||||
// Drop out unit
|
||||
if ((worker = order.Data.Built.Worker)) {
|
||||
|
||||
worker->CurrentOrder()->ClearGoal();
|
||||
worker->ClearAction();
|
||||
//worker->State = 0;
|
||||
|
||||
unit.CurrentOrder()->Data.Built.Worker = NoUnitP;
|
||||
// HACK: make sure the sight is updated correctly
|
||||
unit.CurrentSightRange = 1;
|
||||
DropOutOnSide(*worker, LookingW, &unit);
|
||||
unit.CurrentSightRange = 0;
|
||||
}
|
||||
|
||||
// Player gets back 75% of the original cost for a building.
|
||||
unit.Player->AddCostsFactor(unit.Stats->Costs, CancelBuildingCostsFactor);
|
||||
// Cancel building
|
||||
LetUnitDie(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if building ready. Note we can both build and repair.
|
||||
//
|
||||
//if (unit.CurrentOrder()->Data.Built.Progress >= unit.Stats->Costs[TimeCost] * 600 ||
|
||||
if (!order.Data.Built.Worker->Anim.Unbreakable && (order.Data.Built.Progress >= mod ||
|
||||
unit.Variable[HP_INDEX].Value >= unit.Stats->Variables[HP_INDEX].Max)) {
|
||||
DebugPrint("%d: Building %s(%s) ready.\n" _C_ unit.Player->Index
|
||||
_C_ unit.Type->Ident.c_str() _C_ unit.Type->Name.c_str() );
|
||||
if (unit.Variable[HP_INDEX].Value > unit.Stats->Variables[HP_INDEX].Max) {
|
||||
unit.Variable[HP_INDEX].Value = unit.Stats->Variables[HP_INDEX].Max;
|
||||
}
|
||||
if (order.Execute(unit)) {
|
||||
order.ClearGoal();
|
||||
unit.ClearAction();
|
||||
// HACK: the building is ready now
|
||||
unit.Player->UnitTypesCount[type->Slot]++;
|
||||
unit.Constructed = 0;
|
||||
if (unit.Frame < 0) {
|
||||
unit.Frame = -1;
|
||||
} else {
|
||||
unit.Frame = 0;
|
||||
}
|
||||
|
||||
if ((worker = unit.CurrentOrder()->Data.Built.Worker)) {
|
||||
// Bye bye worker.
|
||||
if (type->BuilderLost) {
|
||||
// FIXME: enough?
|
||||
LetUnitDie(*worker);
|
||||
worker = NULL;
|
||||
// Drop out the worker.
|
||||
} else {
|
||||
worker->ClearAction();
|
||||
worker->SubAction = 0;//may be 40
|
||||
// HACK: make sure the sight is updated correctly
|
||||
unit.CurrentSightRange = 1;
|
||||
DropOutOnSide(*worker, LookingW, &unit);
|
||||
|
||||
worker->CurrentOrder()->ClearGoal();
|
||||
|
||||
//
|
||||
// If we can harvest from the new building, do it.
|
||||
//
|
||||
if (worker->Type->ResInfo[type->GivesResource]) {
|
||||
CommandResource(*worker, unit, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type->GivesResource) {
|
||||
// Set to Zero as it's part of a union
|
||||
memset(&unit.CurrentOrder()->Data, 0, sizeof(unit.CurrentOrder()->Data));
|
||||
// Has StartingResources, Use those
|
||||
unit.ResourcesHeld = type->StartingResources;
|
||||
}
|
||||
|
||||
unit.Player->Notify(NotifyGreen, unit.tilePos.x, unit.tilePos.y,
|
||||
_("New %s done"), type->Name.c_str());
|
||||
if (unit.Player == ThisPlayer) {
|
||||
if (unit.Type->Sound.Ready.Sound) {
|
||||
PlayUnitSound(unit, VoiceReady);
|
||||
} else if (worker) {
|
||||
PlayUnitSound(*worker, VoiceWorkCompleted);
|
||||
} else {
|
||||
PlayUnitSound(unit, VoiceBuilding);
|
||||
}
|
||||
}
|
||||
|
||||
if (unit.Player->AiEnabled) {
|
||||
/* Worker can be NULL */
|
||||
AiWorkComplete(worker, unit);
|
||||
}
|
||||
|
||||
// FIXME: Vladi: this is just a hack to test wall fixing,
|
||||
// FIXME: also not sure if the right place...
|
||||
// FIXME: Johns: hardcoded unit-type wall / more races!
|
||||
if (unit.Type == UnitTypeOrcWall || unit.Type == UnitTypeHumanWall) {
|
||||
Map.SetWall(unit.tilePos, unit.Type == UnitTypeHumanWall);
|
||||
unit.Remove(NULL);
|
||||
UnitLost(unit);
|
||||
UnitClearOrders(unit);
|
||||
unit.Release();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateForNewUnit(unit, 0);
|
||||
|
||||
// Set the direction of the building if it supports them
|
||||
if (unit.Type->NumDirections > 1) {
|
||||
if (unit.Type->Wall) { // Special logic for walls
|
||||
CorrectWallDirections(unit);
|
||||
CorrectWallNeighBours(unit);
|
||||
} else {
|
||||
unit.Direction = (MyRand() >> 8) & 0xFF; // random heading
|
||||
}
|
||||
UnitUpdateHeading(unit);
|
||||
}
|
||||
|
||||
if (IsOnlySelected(unit) || unit.Player == ThisPlayer) {
|
||||
SelectedUnitChanged();
|
||||
}
|
||||
unit.CurrentSightRange = unit.Stats->Variables[SIGHTRANGE_INDEX].Max;
|
||||
MapMarkUnitSight(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateConstructionFrame(unit);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -62,69 +62,45 @@
|
|||
*/
|
||||
static void RepairUnit(CUnit &unit, CUnit &goal)
|
||||
{
|
||||
CPlayer *player;
|
||||
int animlength;
|
||||
int hp;
|
||||
if (goal.CurrentAction() == UnitActionBuilt) {
|
||||
COrder_Built &order = *static_cast<COrder_Built *>(goal.CurrentOrder());
|
||||
|
||||
order.ProgressHp(goal, 100 * unit.CurrentOrder()->Data.Repair.Cycles);
|
||||
unit.CurrentOrder()->Data.Repair.Cycles = 0;
|
||||
return ;
|
||||
}
|
||||
CPlayer *player = unit.Player;
|
||||
char buf[100];
|
||||
|
||||
player = unit.Player;
|
||||
// Calculate the repair costs.
|
||||
Assert(goal.Stats->Variables[HP_INDEX].Max);
|
||||
|
||||
if (goal.CurrentAction() != UnitActionBuilt) {
|
||||
//
|
||||
// Calculate the repair costs.
|
||||
//
|
||||
Assert(goal.Stats->Variables[HP_INDEX].Max);
|
||||
|
||||
//
|
||||
// Check if enough resources are available
|
||||
//
|
||||
for (int i = 1; i < MaxCosts; ++i) {
|
||||
if (player->Resources[i] < goal.Type->RepairCosts[i]) {
|
||||
snprintf(buf, 100, _("We need more %s for repair!"),
|
||||
DefaultResourceNames[i].c_str());
|
||||
player->Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y, buf);
|
||||
if (player->AiEnabled) {
|
||||
// FIXME: call back to AI?
|
||||
unit.CurrentOrder()->ClearGoal();
|
||||
if (!unit.RestoreOrder()) {
|
||||
unit.ClearAction();
|
||||
unit.State = 0;
|
||||
}
|
||||
// Check if enough resources are available
|
||||
for (int i = 1; i < MaxCosts; ++i) {
|
||||
if (player->Resources[i] < goal.Type->RepairCosts[i]) {
|
||||
snprintf(buf, 100, _("We need more %s for repair!"),
|
||||
DefaultResourceNames[i].c_str());
|
||||
player->Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y, buf);
|
||||
if (player->AiEnabled) {
|
||||
// FIXME: call back to AI?
|
||||
unit.CurrentOrder()->ClearGoal();
|
||||
if (!unit.RestoreOrder()) {
|
||||
unit.ClearAction();
|
||||
unit.State = 0;
|
||||
}
|
||||
// FIXME: We shouldn't animate if no resources are available.
|
||||
return;
|
||||
}
|
||||
// FIXME: We shouldn't animate if no resources are available.
|
||||
return;
|
||||
}
|
||||
//
|
||||
// Subtract the resources
|
||||
//
|
||||
player->SubCosts(goal.Type->RepairCosts);
|
||||
}
|
||||
//
|
||||
// Subtract the resources
|
||||
//
|
||||
player->SubCosts(goal.Type->RepairCosts);
|
||||
|
||||
goal.Variable[HP_INDEX].Value += goal.Type->RepairHP;
|
||||
if (goal.Variable[HP_INDEX].Value > goal.Variable[HP_INDEX].Max) {
|
||||
goal.Variable[HP_INDEX].Value = goal.Variable[HP_INDEX].Max;
|
||||
}
|
||||
} else {
|
||||
int costs = goal.Stats->Costs[TimeCost] * 600;
|
||||
// hp is the current damage taken by the unit.
|
||||
hp = (goal.CurrentOrder()->Data.Built.Progress * goal.Variable[HP_INDEX].Max) /
|
||||
costs - goal.Variable[HP_INDEX].Value;
|
||||
//
|
||||
// Calculate the length of the attack (repair) anim.
|
||||
//
|
||||
animlength = unit.CurrentOrder()->Data.Repair.Cycles;
|
||||
unit.CurrentOrder()->Data.Repair.Cycles = 0;
|
||||
|
||||
// FIXME: implement this below:
|
||||
//unit.Data.Built.Worker->Type->BuilderSpeedFactor;
|
||||
goal.CurrentOrder()->Data.Built.Progress += 100 * animlength * SpeedBuild;
|
||||
// Keep the same level of damage while increasing HP.
|
||||
goal.Variable[HP_INDEX].Value =
|
||||
(goal.CurrentOrder()->Data.Built.Progress * goal.Stats->Variables[HP_INDEX].Max) /
|
||||
costs - hp;
|
||||
if (goal.Variable[HP_INDEX].Value > goal.Variable[HP_INDEX].Max) {
|
||||
goal.Variable[HP_INDEX].Value = goal.Variable[HP_INDEX].Max;
|
||||
}
|
||||
goal.Variable[HP_INDEX].Value += goal.Type->RepairHP;
|
||||
if (goal.Variable[HP_INDEX].Value > goal.Variable[HP_INDEX].Max) {
|
||||
goal.Variable[HP_INDEX].Value = goal.Variable[HP_INDEX].Max;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,14 +176,28 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
|
|||
return order;
|
||||
}
|
||||
|
||||
/* static */ COrder* COrder::NewActionBuilt()
|
||||
/* static */ COrder* COrder::NewActionBuilt(CUnit &builder, CUnit &unit)
|
||||
{
|
||||
COrder *order = new COrder;
|
||||
COrder_Built* order = new COrder_Built();
|
||||
|
||||
order->Action = UnitActionBuilt;
|
||||
|
||||
// Make sure the bulding doesn't cancel itself out right away.
|
||||
|
||||
order->Data.Progress = 0;//FIXME ? 100 : 0
|
||||
unit.Variable[HP_INDEX].Value = 1;
|
||||
if (unit.Variable[SHIELD_INDEX].Max) {
|
||||
unit.Variable[SHIELD_INDEX].Value = 1;
|
||||
}
|
||||
order->UpdateConstructionFrame(unit);
|
||||
|
||||
if (unit.Type->BuilderOutside == false) {
|
||||
order->Data.Worker = &builder;
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
/* static */ COrder* COrder::NewActionDie()
|
||||
{
|
||||
COrder *order = new COrder;
|
||||
|
@ -460,6 +474,14 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
|
|||
return order;
|
||||
}
|
||||
|
||||
/* static */ COrder* COrder::NewActionBuilt()
|
||||
{
|
||||
COrder *order = new COrder_Built;
|
||||
|
||||
order->Action = UnitActionBuilt;
|
||||
return order;
|
||||
}
|
||||
|
||||
/* static */ COrder* COrder::NewActionFollow()
|
||||
{
|
||||
COrder *order = new COrder;
|
||||
|
@ -518,7 +540,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
|
|||
|
||||
/* static */ COrder* COrder::NewActionSpellCast()
|
||||
{
|
||||
COrder *order = new COrder;
|
||||
COrder *order = new COrder_SpellCast;
|
||||
|
||||
order->Action = UnitActionSpellCast;
|
||||
return order;
|
||||
|
@ -655,17 +677,13 @@ bool COrder::CheckRange() const
|
|||
return (Range <= Map.Info.MapWidth || Range <= Map.Info.MapHeight);
|
||||
}
|
||||
|
||||
void COrder::FillSeenValues(CUnit &unit) const
|
||||
/* virtual */ void COrder::FillSeenValues(CUnit &unit) const
|
||||
{
|
||||
unit.Seen.State = (Action == UnitActionBuilt) | ((Action == UnitActionUpgradeTo) << 1);
|
||||
unit.Seen.State = ((Action == UnitActionUpgradeTo) << 1);
|
||||
if (unit.CurrentAction() == UnitActionDie) {
|
||||
unit.Seen.State = 3;
|
||||
}
|
||||
if (Action == UnitActionBuilt) {
|
||||
unit.Seen.CFrame = Data.Built.Frame;
|
||||
} else {
|
||||
unit.Seen.CFrame = NULL;
|
||||
}
|
||||
unit.Seen.CFrame = NULL;
|
||||
}
|
||||
|
||||
bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/)
|
||||
|
|
|
@ -471,7 +471,7 @@ void CommandDismiss(CUnit &unit)
|
|||
{
|
||||
// Check if building is still under construction? (NETWORK!)
|
||||
if (unit.CurrentAction() == UnitActionBuilt) {
|
||||
unit.CurrentOrder()->Data.Built.Cancel = 1;
|
||||
unit.CurrentOrder()->Cancel(unit);
|
||||
} else {
|
||||
DebugPrint("Suicide unit ... \n");
|
||||
LetUnitDie(unit);
|
||||
|
|
|
@ -31,16 +31,14 @@
|
|||
#define __ACTIONS_H__
|
||||
|
||||
//@{
|
||||
#ifndef __UNIT_CACHE_H__
|
||||
#include "unit_cache.h"
|
||||
#ifndef __UNIT_H__
|
||||
#include "unit.h"
|
||||
#endif
|
||||
|
||||
#ifndef __VEC2I_H__
|
||||
#include "vec2i.h"
|
||||
#endif
|
||||
|
||||
//#include "vec2i.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Declarations
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -124,6 +122,7 @@ public:
|
|||
virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
|
||||
|
||||
virtual void UpdateUnitVariables(CUnit &unit) const;
|
||||
virtual void FillSeenValues(CUnit &unit) const;
|
||||
|
||||
|
||||
void ReleaseRefs(CUnit &owner);
|
||||
|
@ -156,7 +155,6 @@ public:
|
|||
void NewResetPath() { Data.Move.Fast = 1; Data.Move.Length = 0; }
|
||||
void SaveDataMove(CFile &file) const;
|
||||
|
||||
void FillSeenValues(CUnit &unit) const;
|
||||
|
||||
bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/);
|
||||
void AiUnitKilled(CUnit &unit);
|
||||
|
@ -168,6 +166,7 @@ public:
|
|||
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);
|
||||
static COrder* NewActionMove(const Vec2i &pos);
|
||||
|
@ -235,12 +234,6 @@ public:
|
|||
#define MAX_PATH_LENGTH 28 /// max length of precalculated path
|
||||
char Path[MAX_PATH_LENGTH]; /// directions of stored path
|
||||
} Move; /// ActionMove,...
|
||||
struct _order_built_ {
|
||||
CUnit *Worker; /// Worker building this unit
|
||||
int Progress; /// Progress counter, in 1/100 cycles.
|
||||
int Cancel; /// Cancel construction
|
||||
CConstructionFrame *Frame; /// Construction frame
|
||||
} Built; /// ActionBuilt,...
|
||||
struct _order_build_ {
|
||||
int Cycles; /// Cycles unit has been building for
|
||||
} Build; /// ActionBuild
|
||||
|
@ -260,6 +253,43 @@ public:
|
|||
} Data; /// Storage room for different commands
|
||||
};
|
||||
|
||||
class COrder_Built : public COrder
|
||||
{
|
||||
friend COrder* COrder::NewActionBuilt(CUnit &builder, CUnit &unit);
|
||||
public:
|
||||
virtual COrder_Built *Clone() const;
|
||||
|
||||
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);
|
||||
virtual void Cancel(CUnit &unit);
|
||||
|
||||
virtual void UpdateUnitVariables(CUnit &unit) const;
|
||||
virtual void FillSeenValues(CUnit &unit) const;
|
||||
|
||||
void Progress(CUnit & unit, int amount);
|
||||
void ProgressHp(CUnit &unit, int amount);
|
||||
|
||||
const CConstructionFrame& GetFrame() const { return *Data.Frame; }
|
||||
const CUnitPtr &GetWorker() const { return Data.Worker; }
|
||||
CUnit *GetWorkerPtr() { return Data.Worker; }
|
||||
|
||||
private:
|
||||
void Boost(CUnit &building, int amount, int varIndex) const;
|
||||
void UpdateConstructionFrame(CUnit &unit);
|
||||
|
||||
private:
|
||||
struct {
|
||||
CUnitPtr Worker; /// Worker building this unit
|
||||
int Progress; /// Progress counter, in 1/100 cycles.
|
||||
int Cancel; /// Cancel construction
|
||||
const CConstructionFrame *Frame; /// Construction frame
|
||||
} Data; /// ActionBuilt,...
|
||||
};
|
||||
|
||||
|
||||
|
||||
class COrder_Research : public COrder
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -284,6 +284,11 @@ extern void SaveCcl(CFile *file); /// Save CCL module
|
|||
extern void SavePreferences(); /// Save user preferences
|
||||
extern int CclCommand(const std::string &command, bool exitOnError = true);
|
||||
|
||||
|
||||
CUnit *CclGetUnitFromRef(lua_State *l);
|
||||
|
||||
|
||||
|
||||
extern NumberDesc *Damage; /// Damage calculation for missile.
|
||||
|
||||
/// transform string in corresponding index.
|
||||
|
|
|
@ -354,8 +354,6 @@
|
|||
#include "player.h"
|
||||
#endif
|
||||
|
||||
#include "actions.h"
|
||||
|
||||
#include "vec2i.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -546,7 +544,7 @@ public:
|
|||
/* Seen stuff. */
|
||||
int VisCount[PlayerMax]; /// Unit visibility counts
|
||||
struct _seen_stuff_ {
|
||||
CConstructionFrame *CFrame; /// Seen construction frame
|
||||
const CConstructionFrame *CFrame; /// Seen construction frame
|
||||
int Frame; /// last seen frame/stage of buildings
|
||||
CUnitType *Type; /// Pointer to last seen unit-type
|
||||
int X; /// Last unit->X Seen
|
||||
|
@ -1105,6 +1103,9 @@ extern int CanTransport(const CUnit &transporter, const CUnit &unit);
|
|||
|
||||
/// Generate a unit reference, a printable unique string for unit
|
||||
extern std::string UnitReference(const CUnit &unit);
|
||||
/// Generate a unit reference, a printable unique string for unit
|
||||
extern std::string UnitReference(const CUnitPtr &unit);
|
||||
|
||||
/// Save an order
|
||||
extern void SaveOrder(const COrder &order, const CUnit &unit, CFile *file);
|
||||
/// save unit-structure
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "map.h"
|
||||
#include "tileset.h"
|
||||
#include "minimap.h"
|
||||
#include "actions.h"
|
||||
#include "results.h"
|
||||
#include "ui.h"
|
||||
#include "player.h"
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "unittype.h"
|
||||
#include "unit.h"
|
||||
#include "pathfinder.h"
|
||||
#include "actions.h"
|
||||
|
||||
//astar.cpp
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "missile.h"
|
||||
#include "sound.h"
|
||||
#include "ui.h"
|
||||
#include "actions.h"
|
||||
#include "iolib.h"
|
||||
|
||||
#include "util.h"
|
||||
|
|
|
@ -165,7 +165,7 @@ void ChangeSelectedUnits(CUnit **units, int count)
|
|||
if (count == 1 && units[0]->Type->ClicksToExplode &&
|
||||
!units[0]->Type->IsNotSelectable) {
|
||||
HandleSuicideClick(*units[0]);
|
||||
if (units[0]->CurrentAction() == UnitActionDie) {
|
||||
if (!units[0]->IsAlive()) {
|
||||
NetworkSendSelection(units, count);
|
||||
return ;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ int SelectUnitsByType(CUnit &base)
|
|||
|
||||
// if unit is a cadaver or hidden (not on map)
|
||||
// no unit can be selected.
|
||||
if (base.Removed || base.CurrentAction() == UnitActionDie) {
|
||||
if (base.Removed || base.IsAlive() == false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ int ToggleUnitsByType(CUnit &base)
|
|||
|
||||
// if unit is a cadaver or hidden (not on map)
|
||||
// no unit can be selected.
|
||||
if (base.Removed || base.CurrentAction() == UnitActionDie) {
|
||||
if (base.Removed || base.IsAlive() == false) {
|
||||
return 0;
|
||||
}
|
||||
// if unit isn't belonging to the player, or is a static unit
|
||||
|
@ -709,7 +709,7 @@ CUnit**table, int num_units = UnitMax)
|
|||
continue;
|
||||
}
|
||||
// FIXME: Can we get this?
|
||||
if (!unit.Removed && unit.CurrentAction() != UnitActionDie) {
|
||||
if (!unit.Removed && unit.IsAlive()) {
|
||||
SelectSingleUnit(unit);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "commands.h"
|
||||
#include "video.h"
|
||||
#include "font.h"
|
||||
#include "actions.h"
|
||||
#include "guichan/key.h"
|
||||
#include "guichan/sdl/sdlinput.h"
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "interface.h"
|
||||
#include "network.h"
|
||||
#include "player.h"
|
||||
#include "actions.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "ai.h"
|
||||
#include "widgets.h"
|
||||
#include "replay.h"
|
||||
#include "actions.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Defines
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "network.h"
|
||||
#include "menus.h"
|
||||
#include "spells.h"
|
||||
#include "actions.h"
|
||||
#ifdef DEBUG
|
||||
#include "../ai/ai_local.h"
|
||||
#endif
|
||||
|
@ -285,7 +286,7 @@ UStrInt GetComponent(const CUnit &unit, int index, EnumVariable e, int t)
|
|||
**
|
||||
** @return The desired unit.
|
||||
*/
|
||||
const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
|
||||
static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
|
||||
{
|
||||
switch (e) {
|
||||
case UnitRefItSelf:
|
||||
|
@ -296,7 +297,9 @@ const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
|
|||
return unit.Container;
|
||||
case UnitRefWorker :
|
||||
if (unit.CurrentAction() == UnitActionBuilt) {
|
||||
return unit.CurrentOrder()->Data.Built.Worker;
|
||||
COrder_Built &order = *static_cast<COrder_Built*>(unit.CurrentOrder());
|
||||
|
||||
return order.GetWorkerPtr();
|
||||
} else {
|
||||
return NoUnitP;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "network.h"
|
||||
#include "spells.h"
|
||||
#include "widgets.h"
|
||||
#include "actions.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "unittype.h"
|
||||
#include "map.h"
|
||||
#include "player.h"
|
||||
#include "actions.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
|
|
@ -155,53 +155,6 @@ static void CclGetPos(lua_State *l, T *x , T *y, const int offset = -1)
|
|||
lua_pop(l, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse built
|
||||
**
|
||||
** @param l Lua state.
|
||||
** @param order Unit pointer which should be filled with the data.
|
||||
*/
|
||||
static void CclParseBuilt(lua_State *l, const CUnit &unit, 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, "worker")) {
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
order->Data.Built.Worker = CclGetUnitFromRef(l);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "progress")) {
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
order->Data.Built.Progress = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "cancel")) {
|
||||
order->Data.Built.Cancel = 1;
|
||||
--j;
|
||||
} else if (!strcmp(value, "frame")) {
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
int frame = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
CConstructionFrame *cframe = unit.Type->Construction->Frames;
|
||||
while (frame--) {
|
||||
cframe = cframe->Next;
|
||||
}
|
||||
order->Data.Built.Frame = cframe;
|
||||
} else {
|
||||
LuaError(l, "ParseBuilt: Unsupported tag: %s" _C_ value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Parse res worker data
|
||||
**
|
||||
|
@ -419,11 +372,6 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
|
|||
this->Arg1.Resource.Pos = invalidPos;
|
||||
this->Arg1.Resource.Mine = CclGetUnitFromRef(l);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "data-built")) {
|
||||
++j;
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
CclParseBuilt(l, unit, this);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "data-res-worker")) {
|
||||
++j;
|
||||
lua_rawgeti(l, -1, j + 1);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "unit.h"
|
||||
#include "unit_manager.h"
|
||||
#include "player.h"
|
||||
#include "actions.h"
|
||||
#include "luacallback.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -2158,22 +2159,7 @@ static int CclDefineDecorations(lua_State *l)
|
|||
|
||||
/* virtual */ void COrder::UpdateUnitVariables(CUnit &unit) const
|
||||
{
|
||||
const CUnitType *type = unit.Type;
|
||||
|
||||
switch (unit.CurrentAction()) {
|
||||
// Build
|
||||
case UnitActionBuilt:
|
||||
unit.Variable[BUILD_INDEX].Value = unit.CurrentOrder()->Data.Built.Progress;
|
||||
unit.Variable[BUILD_INDEX].Max = type->Stats[unit.Player->Index].Costs[TimeCost] * 600;
|
||||
|
||||
// This should happen when building unit with several peons
|
||||
// Maybe also with only one.
|
||||
// FIXME : Should be better to fix it in action_{build,repair}.c ?
|
||||
if (unit.Variable[BUILD_INDEX].Value > unit.Variable[BUILD_INDEX].Max) {
|
||||
// assume value is wrong.
|
||||
unit.Variable[BUILD_INDEX].Value = unit.Variable[BUILD_INDEX].Max;
|
||||
}
|
||||
break;
|
||||
// Training
|
||||
case UnitActionTrain:
|
||||
unit.Variable[TRAINING_INDEX].Value = unit.CurrentOrder()->Data.Train.Ticks;
|
||||
|
|
|
@ -266,7 +266,9 @@ unsigned int CUnit::CurrentAction() const
|
|||
|
||||
void CUnit::ClearAction()
|
||||
{
|
||||
CurrentOrder()->Action = UnitActionStill;
|
||||
delete CurrentOrder();
|
||||
Orders[0] = COrder::NewActionStill();
|
||||
|
||||
SubAction = 0;
|
||||
if (Selected) {
|
||||
SelectedUnitChanged();
|
||||
|
@ -2821,16 +2823,6 @@ void LetUnitDie(CUnit &unit)
|
|||
unit.Goal = NULL;
|
||||
}
|
||||
|
||||
// During resource build, the worker holds the resource amount,
|
||||
// but if canceling building the platform, the worker is already
|
||||
// outside.
|
||||
if (type->GivesResource &&
|
||||
unit.CurrentAction() == UnitActionBuilt &&
|
||||
unit.CurrentOrder()->Data.Built.Worker) {
|
||||
// Restore value for oil-patch
|
||||
unit.ResourcesHeld = unit.CurrentOrder()->Data.Built.Worker->ResourcesHeld;
|
||||
}
|
||||
|
||||
// Transporters lose or save their units and building their workers
|
||||
if (unit.UnitInside && unit.Type->SaveCargo)
|
||||
DropOutAll(unit);
|
||||
|
@ -2842,7 +2834,6 @@ void LetUnitDie(CUnit &unit)
|
|||
UnitClearOrders(unit);
|
||||
|
||||
|
||||
|
||||
// Unit has death animation.
|
||||
|
||||
// Not good: UnitUpdateHeading(unit);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "interface.h"
|
||||
#include "font.h"
|
||||
#include "ui.h"
|
||||
#include "actions.h"
|
||||
#include "script.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -173,7 +174,7 @@ void DrawUnitSelection(const CViewport *vp, const CUnit &unit)
|
|||
|
||||
const CUnitType &type = *unit.Type;
|
||||
const PixelPos screenPos = vp->TilePosToScreen_TopLeft(unit.tilePos);
|
||||
const int x = screenPos.x + unit.IX +type.TileWidth * PixelTileSize.x / 2
|
||||
const int x = screenPos.x + unit.IX + type.TileWidth * PixelTileSize.x / 2
|
||||
- type.BoxWidth / 2 - (type.Width - type.Sprite->Width) / 2;
|
||||
const int y = screenPos.y + unit.IY + type.TileHeight * PixelTileSize.y / 2
|
||||
- type.BoxHeight / 2 - (type.Height - type.Sprite->Height) / 2;
|
||||
|
@ -1080,7 +1081,7 @@ void CUnit::Draw(const CViewport *vp) const
|
|||
int constructed;
|
||||
CPlayerColorGraphic *sprite;
|
||||
ResourceInfo *resinfo;
|
||||
CConstructionFrame *cframe;
|
||||
const CConstructionFrame *cframe;
|
||||
CUnitType *type;
|
||||
|
||||
/*
|
||||
|
@ -1113,8 +1114,14 @@ void CUnit::Draw(const CViewport *vp) const
|
|||
if (state == 2) {
|
||||
type = this->CurrentOrder()->Arg1.Type;
|
||||
}
|
||||
// This is trash unless the unit is being built, and that's when we use it.
|
||||
cframe = this->CurrentOrder()->Data.Built.Frame;
|
||||
|
||||
if (this->CurrentAction() == UnitActionBuilt) {
|
||||
COrder_Built &order = *static_cast<COrder_Built*>(this->CurrentOrder());
|
||||
|
||||
cframe = &order.GetFrame();
|
||||
} else {
|
||||
cframe = NULL;
|
||||
}
|
||||
} else {
|
||||
const Vec2i seenTilePos = {this->Seen.X, this->Seen.Y};
|
||||
const PixelPos &screenPos = vp->TilePosToScreen_TopLeft(seenTilePos);
|
||||
|
@ -1257,8 +1264,13 @@ void CUnitDrawProxy::operator=(const CUnit *unit)
|
|||
}
|
||||
|
||||
if (unit->Constructed) {
|
||||
// This is trash unless the unit is being built, and that's when we use it.
|
||||
cframe = unit->CurrentOrder()->Data.Built.Frame;
|
||||
if (unit->CurrentAction() == UnitActionBuilt) {
|
||||
COrder_Built &order = *static_cast<COrder_Built*>(unit->CurrentOrder());
|
||||
|
||||
cframe = &order.GetFrame();
|
||||
} else {
|
||||
cframe = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IY = unit->Seen.IY;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "spells.h"
|
||||
#include "construct.h"
|
||||
#include "iolib.h"
|
||||
#include "actions.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
@ -61,6 +62,20 @@ std::string UnitReference(const CUnit &unit)
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
** Generate a unit reference, a printable unique string for unit.
|
||||
*/
|
||||
std::string UnitReference(const CUnitPtr &unit)
|
||||
{
|
||||
Assert(unit != NULL);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "U" << std::setfill('0') << std::setw(4) << std::uppercase <<
|
||||
std::hex << unit->Slot;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Save an order.
|
||||
**
|
||||
|
@ -108,9 +123,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
|
|||
case UnitActionUpgradeTo:
|
||||
file.printf("\"action-upgrade-to\",");
|
||||
break;
|
||||
case UnitActionBuilt:
|
||||
file.printf("\"action-built\",");
|
||||
break;
|
||||
case UnitActionBoard:
|
||||
file.printf("\"action-board\",");
|
||||
break;
|
||||
|
@ -203,28 +215,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
|
|||
file.printf("}");
|
||||
break;
|
||||
case UnitActionBuilt:
|
||||
{
|
||||
CConstructionFrame *cframe;
|
||||
int frame;
|
||||
|
||||
cframe = unit.Type->Construction->Frames;
|
||||
frame = 0;
|
||||
while (cframe != order.Data.Built.Frame) {
|
||||
cframe = cframe->Next;
|
||||
++frame;
|
||||
}
|
||||
file.printf(",\n \"data-built\", {");
|
||||
|
||||
if (order.Data.Built.Worker) {
|
||||
file.printf("\"worker\", \"%s\", ", UnitReference(*order.Data.Built.Worker).c_str());
|
||||
}
|
||||
file.printf("\"progress\", %d, \"frame\", %d", order.Data.Built.Progress, frame);
|
||||
if (order.Data.Built.Cancel) {
|
||||
file.printf(", \"cancel\"");
|
||||
}
|
||||
file.printf("}");
|
||||
break;
|
||||
}
|
||||
case UnitActionResearch:
|
||||
break;
|
||||
case UnitActionUpgradeTo:
|
||||
|
|
Loading…
Add table
Reference in a new issue