1 package cz.cuni.amis.pogamut.udk.bot.command;
2
3 import java.util.logging.Logger;
4
5 import javax.vecmath.Vector3d;
6
7 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
8 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
9 import cz.cuni.amis.pogamut.base3d.worldview.object.Rotation;
10 import cz.cuni.amis.pogamut.udk.bot.impl.UDKBot;
11 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Configuration;
12 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.ContinuousMove;
13 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Dodge;
14 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Jump;
15 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Move;
16 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Item;
17 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Player;
18 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Self;
19 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
20
21 /**
22 * Class providing Pogamut2 UT2004 advanced locomotion commands for the bot -
23 * strafing, advanced turning, dodging...
24 *
25 * @author Michal 'Knight' Bida
26 */
27 public class AdvancedLocomotion extends SimpleLocomotion {
28
29 /**
30 * Self object holding information about our agent.
31 **/
32 Self self = null;
33
34 /**
35 * Used to set focus when strafing left and right, holds the distance of
36 * focus location.
37 */
38 private static final double FOCUS_DISTANCE = 3000;
39
40 /**
41 * Makes the bot to move through first location to second location (may be
42 * specified directly or some ILocated object may be supplied - carefull
43 * with objects traversability). Usage is when you want to have your bot to
44 * move really smooth. Where is the problem? If you would want to achive the
45 * same thing with 2 moveTo functions (first move to location1, when there
46 * move to location2), there may be a little lag - you have to check if you
47 * are already at first location and etc. This function can solve this
48 * problem as the check is done in UnrealScript.
49 *
50 * (issues GB MOVE command)
51 *
52 * @param firstLocation
53 * First location we will go through.
54 * @param secondLocation
55 * Second location we will go to (after reaching first).
56 *
57 * @see moveContinuous()
58 */
59 public void moveAlong(ILocated firstLocation, ILocated secondLocation) {
60 Move moveAlong = new Move();
61
62 moveAlong.setFirstLocation(firstLocation.getLocation());
63 moveAlong.setSecondLocation(secondLocation.getLocation());
64
65 agent.getAct().act(moveAlong);
66 }
67
68 /**
69 * This makes the bot to run straight ahead continuously. Will stop when
70 * other move command is issued - stopMovement, strafeTo, moveTo, moveAlong
71 * even turn commands will interrupt this.
72 *
73 * (issues GB CMOVE command)
74 *
75 * @see moveAlong(ILocated, ILocated)
76 *
77 */
78 public void moveContinuos() {
79 agent.getAct().act(new ContinuousMove());
80 }
81
82 /**
83 * Bot strafes right. The length of the strafe is specified by distance
84 * attribute (in UT units, 1 UT unit equals roughly 1 cm). The bot will be
85 * looking to object specified by the attribute focusId.
86 *
87 * @param distance
88 * - how far the bot strafes (in UT units, 1 UT unit equals
89 * roughly 1 cm).
90 * @param focusId
91 * - UnrealId of the object that should be the bot focus.
92 * @see strafeLeft(double,ILocated)
93 */
94 public void strafeRight(double distance, UnrealId focusId) {
95 if (self == null) {
96 self = agent.getWorldView().getSingle(Self.class);
97 }
98 if (self != null) {
99 Location startLoc = self.getLocation();
100 Location directionVector = self.getRotation().toLocation();
101 Location targetVec = directionVector.cross(new Location(0, 0, 1))
102 .getNormalized().scale(-distance);
103
104 agent.getAct().act(
105 new Move().setFirstLocation(startLoc.add(targetVec))
106 .setFocusTarget(focusId));
107 }
108 }
109
110 /**
111 * Bot strafes right. The length of the strafe is specified by distance
112 * attribute (in UT units, 1 UT unit equals roughly 1 cm). The bot will be
113 * looking to location specified by the attribute focusLocation.
114 *
115 * @param distance
116 * - how far the bot strafes (in UT units, 1 UT unit equals
117 * roughly 1 cm).
118 * @param focusLocation
119 * - location where the bot should look
120 * @see strafeLeft(double,ILocated)
121 */
122 public void strafeRight(double distance, ILocated focusLocation) {
123 if (self == null) {
124 self = agent.getWorldView().getSingle(Self.class);
125 }
126 if (self != null) {
127 Location startLoc = self.getLocation();
128 Location directionVector = self.getRotation().toLocation();
129 Location targetVec = directionVector.cross(new Location(0, 0, 1))
130 .getNormalized().scale(-distance);
131
132 agent.getAct().act(
133 new Move().setFirstLocation(startLoc.add(targetVec))
134 .setFocusLocation(focusLocation.getLocation()));
135 }
136 }
137
138 /**
139 * Bot strafes right. The length of the strafe is specified by distance
140 * attribute (in UT units, 1 UT unit equals roughly 1 cm). Note that this
141 * will reset the bot focus. The bot will be looking straight ahead (however
142 * if the strafe is really long - more than 500 UT units - it will be
143 * visible the bot is turning slightly performing the strafe).
144 *
145 * @param distance
146 * - how far the bot strafes (in UT units, 1 UT unit equals
147 * roughly 1 cm).
148 * @see strafeLeft(double)
149 */
150 public void strafeRight(double distance) {
151 if (self == null) {
152 self = agent.getWorldView().getSingle(Self.class);
153 }
154 if (self != null) {
155 Location startLoc = self.getLocation();
156 Location directionVector = self.getRotation().toLocation();
157 Location targetVec = directionVector.cross(new Location(0, 0, 1))
158 .getNormalized().scale(-distance);
159
160 agent.getAct().act(
161 new Move().setFirstLocation(startLoc.add(targetVec))
162 .setFocusLocation(
163 startLoc.add(directionVector
164 .getNormalized().scale(
165 FOCUS_DISTANCE))));
166 }
167 }
168
169 /**
170 * Bot strafes left. The length of the strafe is specified by distance
171 * attribute (in UT units, 1 UT unit equals roughly 1 cm). The bot will be
172 * looking to object specified by the attribute focusId.
173 *
174 * @param distance
175 * - how far the bot strafes (in UT units, 1 UT unit equals
176 * roughly 1 cm).
177 * @param focusId
178 * - UnrealId of the object that should be the bot focus.
179 * @see strafeRight(double,ILocated)
180 */
181 public void strafeLeft(double distance, UnrealId focusId) {
182 if (self == null) {
183 self = agent.getWorldView().getSingle(Self.class);
184 }
185 if (self != null) {
186 Location startLoc = self.getLocation();
187 Location directionVector = self.getRotation().toLocation();
188 Location targetVec = directionVector.cross(new Location(0, 0, 1))
189 .getNormalized().scale(distance);
190
191 agent.getAct().act(
192 new Move().setFirstLocation(startLoc.add(targetVec))
193 .setFocusTarget(focusId));
194 }
195 }
196
197 /**
198 * Bot strafes left. The length of the strafe is specified by distance
199 * attribute (in UT units, 1 UT unit equals roughly 1 cm). The bot will be
200 * looking to location specified by the attribute focusLocation.
201 *
202 * @param distance
203 * - how far the bot strafes (in UT units, 1 UT unit equals
204 * roughly 1 cm).
205 * @param focusLocation
206 * - location where the bot should look
207 * @see strafeRight(double,ILocated)
208 */
209 public void strafeLeft(double distance, ILocated focusLocation) {
210 if (self == null) {
211 self = agent.getWorldView().getSingle(Self.class);
212 }
213 if (self != null) {
214 Location startLoc = self.getLocation();
215 Location directionVector = self.getRotation().toLocation();
216 Location targetVec = directionVector.cross(new Location(0, 0, 1))
217 .getNormalized().scale(distance);
218
219 agent.getAct().act(
220 new Move().setFirstLocation(startLoc.add(targetVec))
221 .setFocusLocation(focusLocation.getLocation()));
222 }
223 }
224
225 /**
226 * Bot strafes left. The length of the strafe is specified by distance
227 * attribute (in UT units, 1 UT unit equals roughly 1 cm). Note that this
228 * will reset the bot focus. The bot will be looking straight ahead (however
229 * if the strafe is really long - more than 500 UT units - it will be
230 * visible the bot is turning slightly performing the strafe).
231 *
232 * @param distance
233 * - how far the bot strafes (in UT units, 1 UT unit equals
234 * roughly 1 cm).
235 * @see strafeRight(double)
236 */
237 public void strafeLeft(double distance) {
238 if (self == null) {
239 self = agent.getWorldView().getSingle(Self.class);
240 }
241 if (self != null) {
242 Location startLoc = self.getLocation();
243 Location directionVector = self.getRotation().toLocation();
244 Location targetVec = directionVector.cross(new Location(0, 0, 1))
245 .getNormalized().scale(distance);
246
247 agent.getAct().act(
248 new Move().setFirstLocation(startLoc.add(targetVec))
249 .setFocusLocation(
250 startLoc.add(directionVector
251 .getNormalized().scale(
252 FOCUS_DISTANCE))));
253 }
254 }
255
256 /**
257 * Makes the bot to move to location while looking at focusLocation. (issues
258 * GB STRAFE command)
259 *
260 * @param location
261 * Location we will strafe to.
262 * @param focusLocation
263 * Location we will look at while strafing.
264 *
265 * @see strafeTo(ILocated, UnrealId)
266 */
267 public void strafeTo(ILocated location, ILocated focusLocation) {
268 Move move = new Move().setFirstLocation(location.getLocation())
269 .setFocusLocation(focusLocation.getLocation());
270 agent.getAct().act(move);
271 }
272
273 /**
274 * Makes the bot to move at location, while looking at focus object. Note
275 * that when you support focus object, the bot will update his focus (place
276 * he is looking at) according to focus object location (this will be
277 * provided by GB UnrealScript code). Usefull when you want to track some
278 * player position while moving somewhere else. (issues GB STRAFE command)
279 *
280 * @param location
281 * Location we will strafe to.
282 * @param focus
283 * Object with UrealId. We will look at this location while
284 * strafing. We will update our focus location according to the
285 * current position of this obejct in UT.
286 *
287 * @see strafeTo(ILocated, ILocated)
288 *
289 * @todo To check if supported object is also ILocated? see below
290 */
291 public void strafeTo(ILocated location, UnrealId focus) {
292 Move move = new Move().setFirstLocation(location.getLocation())
293 .setFocusTarget(focus);
294 // TODO: To check if this object is also ILocated?
295 // How this could be done? We need to check if supported IWorldObject
296 // implements interface ILocated
297 /*
298 * ILocated tmpILocatedCheck; if (tmpILocatedCheck.getClass() ==
299 * focus.getClass().getInterfaces()[0]) {
300 *
301 * }
302 */
303 agent.getAct().act(move);
304 }
305
306 /**
307 * Makes the bot to double jump instantly (issues GB JUMP command)
308 *
309 * @todo How to convince javadoc see to link to method in super class
310 * @see jump()
311 * @see dodge(Vector3d)
312 */
313 public void doubleJump() {
314 Jump jump = new Jump();
315 jump.setDoubleJump(true);
316 agent.getAct().act(jump);
317 }
318
319 /**
320 * Makes the bot to double jump instantly (issues GB JUMP command) with custom settings.
321 * <p><p>
322 * See also {@link SimpleLocomotion#jump()}.
323 *
324 * TODO: NOT WORKING, GameBotsUDK must be altered to provide additional JUMP command attributes
325 *
326 * @param secondJumpDelay After time specified here, the bot performs second jump of a double jump (if DoubleJump is true). Time is in seconds. GB2004 default is 0.5s.
327 * @param jumpZ Force vector specifying how big the jump should be. Can't be set more than 2 * JumpZ = 680 for double jump.
328 *
329 * @see jump()
330 * @see dodge(Vector3d)
331 */
332 public void doubleJump(double secondJumpDelay, double jumpZ) {
333 Jump jump = new Jump();
334 jump.setDoubleJump(true);
335
336 // TODO: IMPLEMENT FOR UDK!
337 //jump.setDelay(secondJumpDelay);
338 //jump.setForce(jumpZ);
339 agent.getAct().act(jump);
340 }
341
342 /**
343 * Makes the bot to dodge in the selected direction (this is in fact single
344 * jump that is executed to selected direction). (issues GB DODGE command)
345 *
346 * @param direction
347 * Vector (that will be normalized) that specifies direction of
348 * the jump.
349 *
350 * @see jump()
351 * @see doubleJump()
352 */
353 public void dodge(Vector3d direction) {
354 agent.getAct().act(new Dodge(direction));
355 }
356
357 /**
358 * Sets the speed multiplier for the bot. By this number the bots default
359 * speed will be multiplied by. (issues GB CONF command)
360 *
361 * @param speedMultiplier
362 * Ranges from 0.1 to 2 (max may be set in ini in [RemoteBot]
363 * MaxSpeed)
364 *
365 * @see setRotationSpeed(Rotation)
366 */
367 public void setSpeed(double speedMultiplier) {
368 Configuration configure = new Configuration();
369 configure.setSpeedMultiplier(speedMultiplier);
370 agent.getAct().act(configure);
371 }
372
373 /**
374 * Sets the rotation speed (rotation rate) for the bot. Default rotation
375 * rate can be set in GameBots INI file in UT2004/System directory ( look
376 * for DefaultRotationRate attribute). Default rotation rate is now
377 * Pitch=3072, Yaw=60000, Roll=2048 (pitch = up/down, yaw = left/right, roll
378 * = equivalent of doing a cartwheel).
379 *
380 * (issues GB CONF command)
381 *
382 * @param newRotationRate
383 * Default is Pitch=3072, Yaw=60000, Roll=2048. To achieve best
384 * results we suggest to multiply the default setting.
385 *
386 * @see setSpeed(double)
387 */
388 public void setRotationSpeed(Rotation newRotationRate) {
389 Configuration configure = new Configuration();
390 configure.setRotationRate(newRotationRate);
391 agent.getAct().act(configure);
392 }
393
394 /**
395 * Constructor. Setups the command module based on given agent and logger.
396 *
397 * @param agent
398 * AbstractUT2004Bot we will send commands for
399 * @param log
400 * Logger to be used for logging runtime/debug info.
401 */
402 public AdvancedLocomotion(UDKBot agent, Logger log) {
403 super(agent, log);
404 }
405
406 @Override
407 public void jump() {
408 super.jump();
409 }
410
411 @Override
412 public void moveTo(ILocated location) {
413 super.moveTo(location);
414 }
415
416 @Override
417 public void setRun() {
418 super.setRun();
419 }
420
421 @Override
422 public void setWalk() {
423 super.setWalk();
424 }
425
426 @Override
427 public void stopMovement() {
428 super.stopMovement();
429 }
430
431 @Override
432 public void turnHorizontal(int amount) {
433 super.turnHorizontal(amount);
434 }
435
436 @Override
437 public void turnTo(ILocated location) {
438 super.turnTo(location);
439 }
440
441 @Override
442 public void turnTo(Player player) {
443 super.turnTo(player);
444 }
445
446 @Override
447 public void turnTo(Item item) {
448 super.turnTo(item);
449 }
450
451 @Override
452 public void turnVertical(int amount) {
453 super.turnVertical(amount);
454 }
455
456 }