View Javadoc

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 }