00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037
00038 #include "stratagus.h"
00039 #include "video.h"
00040 #include "sound.h"
00041 #include "unitsound.h"
00042 #include "unittype.h"
00043 #include "animation.h"
00044 #include "player.h"
00045 #include "unit.h"
00046 #include "actions.h"
00047 #include "sound.h"
00048 #include "ai.h"
00049 #include "interface.h"
00050 #include "ui.h"
00051
00052
00053
00054
00055
00060 static int GetProductionCost(CUnitType *type)
00061 {
00062 int *costs = type->ProductionCosts;
00063 return costs[EnergyCost] ? costs[EnergyCost] : costs[MagmaCost];
00064 }
00065
00074 static int CanHandleOrder(CUnit *unit, COrder *order)
00075 {
00076 if (order->Action == UnitActionResource) {
00077
00078 if (!unit->Type->Harvester) {
00079 return 0;
00080 }
00081 return 1;
00082 }
00083 if (order->Action == UnitActionAttack && !unit->Type->CanAttack) {
00084 return 0;
00085 }
00086 if (order->Action == UnitActionBoard && unit->Type->UnitType != UnitTypeLand) {
00087 return 0;
00088 }
00089 return 1;
00090 }
00091
00097 void HandleActionTrain(CUnit *unit)
00098 {
00099 CUnit *nunit;
00100 const CUnitType *type;
00101 CPlayer *player;
00102 int food;
00103 int pcost = GetProductionCost(unit->Orders[0]->Type);
00104
00105
00106
00107
00108 if (!unit->SubAction) {
00109 unit->Data.Train.Ticks = 0;
00110 unit->SubAction = 1;
00111
00112 int costs[MaxCosts];
00113 CalculateRequestedAmount(unit->Type, unit->Orders[0]->Type->ProductionCosts, costs);
00114 unit->Player->AddToUnitsConsumingResources(unit, costs);
00115 } else {
00116 int *costs = unit->Player->UnitsConsumingResourcesActual[unit];
00117 int cost = costs[EnergyCost] ? costs[EnergyCost] : costs[MagmaCost];
00118 unit->Data.Train.Ticks += cost * SpeedTrain;
00119 if (unit->Data.Train.Ticks > pcost) {
00120 unit->Data.Train.Ticks = pcost;
00121 }
00122 }
00123
00124 unit->Type->Animations->Train ?
00125 UnitShowAnimation(unit, unit->Type->Animations->Train) :
00126 UnitShowAnimation(unit, unit->Type->Animations->Still);
00127 if (unit->Wait) {
00128 unit->Wait--;
00129 return;
00130 }
00131
00132 player = unit->Player;
00133
00134 if (unit->Data.Train.Ticks >= pcost) {
00135 unit->Data.Train.Ticks = pcost;
00136
00137
00138
00139
00140 if (NumUnits >= UnitMax) {
00141 unit->Wait = CYCLES_PER_SECOND / 6;
00142 return;
00143 }
00144
00145
00146
00147
00148 food = player->CheckLimits(unit->Orders[0]->Type);
00149 if (food < 0) {
00150 if (food == -3 && unit->Player->AiEnabled) {
00151 AiNeedMoreSupply(unit, unit->Orders[0]->Type);
00152 }
00153
00154 unit->Data.Train.Ticks = pcost;
00155 unit->Wait = CYCLES_PER_SECOND / 6;
00156 return;
00157 }
00158
00159 nunit = MakeUnit(unit->Orders[0]->Type, player);
00160 if (nunit != NoUnitP) {
00161 nunit->X = unit->X;
00162 nunit->Y = unit->Y;
00163 type = unit->Type;
00164
00165
00166
00167
00168 nunit->X = unit->X;
00169 nunit->Y = unit->Y;
00170
00171 player->RemoveFromUnitsConsumingResources(unit);
00172
00173
00174 UpdateForNewUnit(nunit, 0);
00175
00176 DropOutOnSide(nunit, LookingW, type->TileWidth, type->TileHeight);
00177
00178
00179 if (type->DecayRate) {
00180 nunit->TTL = GameCycle + type->DecayRate * 6 * CYCLES_PER_SECOND;
00181 }
00182
00183 player->Notify(NotifyYellow, nunit->X, nunit->Y,
00184 _("New %s ready"), nunit->Type->Name.c_str());
00185 if (player == ThisPlayer) {
00186 PlayUnitSound(nunit, VoiceReady);
00187 }
00188 if (unit->Player->AiEnabled) {
00189 AiTrainingComplete(unit, nunit);
00190 }
00191
00192 if (unit->OrderCount == 1) {
00193 unit->ClearAction();
00194 } else {
00195 unit->OrderFlush = 1;
00196 unit->SubAction = 0;
00197 }
00198
00199 if (!CanHandleOrder(nunit, &unit->NewOrder)) {
00200 DebugPrint("Wrong order for unit\n");
00201
00202
00203 *nunit->Orders[0] = unit->NewOrder;
00204 nunit->Orders[0]->Action = UnitActionMove;
00205 if (nunit->Orders[0]->Goal) {
00206 nunit->Orders[0]->Goal->RefsIncrease();
00207 }
00208 } else {
00209 if (unit->NewOrder.Goal) {
00210 if (unit->NewOrder.Goal->Destroyed) {
00211
00212 DebugPrint("Destroyed unit in train unit\n");
00213 unit->NewOrder.Goal->RefsDecrease();
00214 unit->NewOrder.Goal = NoUnitP;
00215 unit->NewOrder.Action = UnitActionStill;
00216 }
00217 }
00218
00219 *nunit->Orders[0] = unit->NewOrder;
00220
00221
00222
00223
00224 if (nunit->Orders[0]->Goal) {
00225 nunit->Orders[0]->Goal->RefsIncrease();
00226 }
00227 }
00228
00229 if (IsOnlySelected(unit)) {
00230 UI.ButtonPanel.Update();
00231 }
00232 return;
00233 } else {
00234 player->Notify(NotifyYellow, unit->X, unit->Y,
00235 _("Unable to train %s"), unit->Orders[0]->Type->Name.c_str());
00236 }
00237 }
00238
00239 unit->Wait = CYCLES_PER_SECOND / 6;
00240 }
00241