1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name action_patrol.cpp - The patrol action. */
12 //
13 // (c) Copyright 1998-2005 by Lutz Sammer and Jimmy Salmon
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #include "action/action_patrol.h"
39
40 #include "animation.h"
41 #include "iolib.h"
42 #include "map.h"
43 #include "pathfinder.h"
44 #include "script.h"
45 #include "ui.h"
46 #include "unit.h"
47 #include "unittype.h"
48 #include "video.h"
49
50 /*----------------------------------------------------------------------------
51 -- Functions
52 ----------------------------------------------------------------------------*/
53
NewActionPatrol(const Vec2i & currentPos,const Vec2i & dest)54 /* static */ COrder *COrder::NewActionPatrol(const Vec2i ¤tPos, const Vec2i &dest)
55 {
56 Assert(Map.Info.IsPointOnMap(currentPos));
57 Assert(Map.Info.IsPointOnMap(dest));
58
59 COrder_Patrol *order = new COrder_Patrol();
60
61 order->goalPos = dest;
62 order->WayPoint = currentPos;
63 return order;
64 }
65
66
Save(CFile & file,const CUnit & unit) const67 /* virtual */ void COrder_Patrol::Save(CFile &file, const CUnit &unit) const
68 {
69 file.printf("{\"action-patrol\",");
70
71 if (this->Finished) {
72 file.printf(" \"finished\", ");
73 }
74 file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
75 file.printf(" \"range\", %d,", this->Range);
76
77 if (this->WaitingCycle != 0) {
78 file.printf(" \"waiting-cycle\", %d,", this->WaitingCycle);
79 }
80 file.printf(" \"patrol\", {%d, %d}", this->WayPoint.x, this->WayPoint.y);
81 file.printf("}");
82 }
83
ParseSpecificData(lua_State * l,int & j,const char * value,const CUnit & unit)84 /* virtual */ bool COrder_Patrol::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
85 {
86 if (!strcmp(value, "patrol")) {
87 ++j;
88 lua_rawgeti(l, -1, j + 1);
89 CclGetPos(l, &this->WayPoint.x , &this->WayPoint.y);
90 lua_pop(l, 1);
91 } else if (!strcmp(value, "waiting-cycle")) {
92 ++j;
93 this->WaitingCycle = LuaToNumber(l, -1, j + 1);
94 } else if (!strcmp(value, "range")) {
95 ++j;
96 this->Range = LuaToNumber(l, -1, j + 1);
97 } else if (!strcmp(value, "tile")) {
98 ++j;
99 lua_rawgeti(l, -1, j + 1);
100 CclGetPos(l, &this->goalPos.x , &this->goalPos.y);
101 lua_pop(l, 1);
102 } else {
103 return false;
104 }
105 return true;
106 }
107
IsValid() const108 /* virtual */ bool COrder_Patrol::IsValid() const
109 {
110 return true;
111 }
112
Show(const CViewport & vp,const PixelPos & lastScreenPos) const113 /* virtual */ PixelPos COrder_Patrol::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
114 {
115 const PixelPos pos1 = vp.TilePosToScreen_Center(this->goalPos);
116 const PixelPos pos2 = vp.TilePosToScreen_Center(this->WayPoint);
117
118 Video.DrawLineClip(ColorGreen, lastScreenPos, pos1);
119 Video.FillCircleClip(ColorBlue, pos1, 2);
120 Video.DrawLineClip(ColorBlue, pos1, pos2);
121 Video.FillCircleClip(ColorBlue, pos2, 3);
122 return pos2;
123 }
124
UpdatePathFinderData(PathFinderInput & input)125 /* virtual */ void COrder_Patrol::UpdatePathFinderData(PathFinderInput &input)
126 {
127 input.SetMinRange(0);
128 input.SetMaxRange(this->Range);
129 const Vec2i tileSize(0, 0);
130 input.SetGoal(this->goalPos, tileSize);
131 }
132
133
Execute(CUnit & unit)134 /* virtual */ void COrder_Patrol::Execute(CUnit &unit)
135 {
136 if (unit.Wait) {
137 if (!unit.Waiting) {
138 unit.Waiting = 1;
139 unit.WaitBackup = unit.Anim;
140 }
141 UnitShowAnimation(unit, unit.Type->Animations->Still);
142 unit.Wait--;
143 return;
144 }
145 if (unit.Waiting) {
146 unit.Anim = unit.WaitBackup;
147 unit.Waiting = 0;
148 }
149
150 switch (DoActionMove(unit)) {
151 case PF_FAILED:
152 this->WaitingCycle = 0;
153 break;
154 case PF_UNREACHABLE:
155 // Increase range and try again
156 this->WaitingCycle = 1;
157 this->Range++;
158 break;
159
160 case PF_REACHED:
161 this->WaitingCycle = 1;
162 this->Range = 0;
163 std::swap(this->WayPoint, this->goalPos);
164
165 break;
166 case PF_WAIT:
167 // Wait for a while then give up
168 this->WaitingCycle++;
169 if (this->WaitingCycle == 5) {
170 this->WaitingCycle = 0;
171 this->Range = 0;
172 std::swap(this->WayPoint, this->goalPos);
173
174 unit.pathFinderData->output.Cycles = 0; //moving counter
175 }
176 break;
177 default: // moving
178 this->WaitingCycle = 0;
179 break;
180 }
181
182 if (!unit.Anim.Unbreakable) {
183 if (AutoAttack(unit) || AutoRepair(unit) || AutoCast(unit)) {
184 this->Finished = true;
185 }
186 }
187 }
188
189 /**
190 ** Get goal position
191 */
GetGoalPos() const192 /* virtual */ const Vec2i COrder_Patrol::GetGoalPos() const
193 {
194 const Vec2i invalidPos(-1, -1);
195 if (goalPos != invalidPos) {
196 return goalPos;
197 }
198 if (this->HasGoal()) {
199 return this->GetGoal()->tilePos;
200 }
201 return invalidPos;
202 }
203
204 //@}
205