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 "unittype.h"
00041 #include "animation.h"
00042 #include "player.h"
00043 #include "unit.h"
00044 #include "map.h"
00045 #include "actions.h"
00046 #include "pathfinder.h"
00047 #include "sound.h"
00048 #include "interface.h"
00049 #include "map.h"
00050 #include "ai.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00068 bool CanMove(const CUnit *unit)
00069 {
00070 Assert(unit);
00071 Assert(unit->Type);
00072 return unit->Type->Animations && unit->Type->Animations->Move;
00073 }
00074
00075
00084 int DoActionMove(CUnit *unit)
00085 {
00086 int xd;
00087 int yd;
00088 int d;
00089 int x;
00090 int y;
00091 int move;
00092
00093 Assert(CanMove(unit));
00094 if (!unit->Moving &&
00095 (unit->Type->Animations->Move != unit->Anim.CurrAnim || !unit->Anim.Wait)) {
00096 Assert(!unit->Anim.Unbreakable);
00097
00098
00099 unit->IX = unit->IY = 0;
00100
00101 UnmarkUnitFieldFlags(unit);
00102 d = NextPathElement(unit, &xd, &yd);
00103 MarkUnitFieldFlags(unit);
00104 switch (d) {
00105 case PF_UNREACHABLE:
00106 if (unit->Player->AiEnabled) {
00107 AiCanNotMove(unit);
00108 }
00109 unit->Moving = 0;
00110 return d;
00111 case PF_REACHED:
00112 unit->Moving = 0;
00113 return d;
00114 case PF_WAIT:
00115
00116
00117 unit->Frame = unit->Type->StillFrame;
00118 UnitUpdateHeading(unit);
00119 unit->Wait = 10;
00120
00121 unit->Moving = 0;
00122 return d;
00123 default:
00124 unit->Moving = 1;
00125 break;
00126 }
00127 x = unit->X;
00128 y = unit->Y;
00129
00130
00131
00132
00133 if (unit->Type->CanTransport &&
00134 ((Map.WaterOnMap(x, y) && Map.CoastOnMap(x + xd, y + yd)) ||
00135 (Map.CoastOnMap(x, y) && Map.WaterOnMap(x + xd, y + yd)))) {
00136 PlayUnitSound(unit, VoiceDocking);
00137 }
00138
00139 x = unit->X + xd;
00140 y = unit->Y + yd;
00141 unit->MoveToXY(x, y);
00142
00143
00144 if (unit->Selected && !Map.IsFieldVisible(ThisPlayer, x, y)) {
00145 if (NumSelected == 1) {
00146 CancelBuildingMode();
00147 }
00148 if (!ReplayRevealMap) {
00149 UnSelectUnit(unit);
00150 SelectionChanged();
00151 }
00152 }
00153
00154 unit->IX = -xd * TileSizeX;
00155 unit->IY = -yd * TileSizeY;
00156 unit->Frame = unit->Type->StillFrame;
00157 UnitHeadingFromDeltaXY(unit, xd, yd);
00158 } else {
00159 xd = Heading2X[unit->Direction / NextDirection];
00160 yd = Heading2Y[unit->Direction / NextDirection];
00161 d = unit->Data.Move.Length + 1;
00162 }
00163
00164 move = UnitShowAnimationScaled(unit, unit->Type->Animations->Move,
00165 Map.Field(unit->X, unit->Y)->Cost);
00166
00167 unit->IX += xd * move;
00168 unit->IY += yd * move;
00169
00170
00171
00172
00173 if (!unit->Anim.Unbreakable && !unit->IX && !unit->IY) {
00174 unit->Moving = 0;
00175 }
00176
00177 return d;
00178 }
00179
00190 void HandleActionMove(CUnit *unit)
00191 {
00192 CUnit *goal;
00193
00194 Assert(unit);
00195 Assert(CanMove(unit));
00196
00197 if (unit->Wait) {
00198 unit->Wait--;
00199 return;
00200 }
00201
00202 if (!unit->SubAction) {
00203 unit->SubAction = 1;
00204 NewResetPath(unit);
00205
00206 Assert(unit->State == 0);
00207 }
00208
00209
00210
00211 switch (DoActionMove(unit)) {
00212 case PF_UNREACHABLE:
00213
00214
00215
00216 if (unit->Orders[0]->Range <= Map.Info.MapWidth ||
00217 unit->Orders[0]->Range <= Map.Info.MapHeight) {
00218 unit->Orders[0]->Range++;
00219 break;
00220 }
00221
00222 case PF_REACHED:
00223
00224 if ((goal = unit->Orders[0]->Goal)) {
00225 goal->RefsDecrease();
00226 unit->Orders[0]->Goal = NoUnitP;
00227 }
00228 unit->ClearAction();
00229 return;
00230
00231 default:
00232 break;
00233 }
00234
00235
00236
00237
00238 if ((goal = unit->Orders[0]->Goal) && goal->Destroyed) {
00239 DebugPrint("Goal dead\n");
00240 unit->Orders[0]->X = goal->X + goal->Type->TileWidth / 2;
00241 unit->Orders[0]->Y = goal->Y + goal->Type->TileHeight / 2;
00242 unit->Orders[0]->Goal = NoUnitP;
00243 goal->RefsDecrease();
00244 NewResetPath(unit);
00245 }
00246 }
00247