1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <tankgraph/TankKeyboardControlUtil.h>
22 #include <tank/Tank.h>
23 #include <tank/TankPosition.h>
24 #include <tank/TankState.h>
25 #include <tank/TankAccessories.h>
26 #include <tankgraph/TargetRendererImplTank.h>
27 #include <target/TargetShield.h>
28 #include <target/TargetLife.h>
29 #include <coms/ComsMessageSender.h>
30 #include <coms/ComsPlayedMoveMessage.h>
31 #include <coms/ComsDefenseMessage.h>
32 #include <client/ScorchedClient.h>
33 #include <client/ClientState.h>
34 #include <weapons/AccessoryStore.h>
35 #include <common/Keyboard.h>
36 #include <common/Line.h>
37 #include <landscapemap/LandscapeMaps.h>
38 #include <graph/OptionsDisplay.h>
39 #include <graph/MainCamera.h>
40 #include <sound/Sound.h>
42 VirtualSoundSource
*TankKeyboardControlUtil::elevateSound_(0);
43 VirtualSoundSource
*TankKeyboardControlUtil::rotateSound_(0);
44 VirtualSoundSource
*TankKeyboardControlUtil::startSound_(0);
45 VirtualSoundSource
*TankKeyboardControlUtil::powerSound_(0);
47 TankKeyboardControlUtil::TankKeyboardControlUtil()
51 TankKeyboardControlUtil::~TankKeyboardControlUtil()
55 void TankKeyboardControlUtil::keyboardCheck(
58 float frameTime
, char *buffer
,
59 unsigned int keyState
)
62 if (!elevateSound_
) elevateSound_
=
63 new VirtualSoundSource(VirtualSoundPriority::eRotation
, true, false);
64 elevateSound_
->setPosition(tank
->getPosition().getTankPosition().asVector());
65 if (!rotateSound_
) rotateSound_
=
66 new VirtualSoundSource(VirtualSoundPriority::eRotation
, true, false);
67 rotateSound_
->setPosition(tank
->getPosition().getTankPosition().asVector());
68 if (!startSound_
) startSound_
=
69 new VirtualSoundSource(VirtualSoundPriority::eRotation
, false, false);
70 startSound_
->setPosition(tank
->getPosition().getTankPosition().asVector());
71 if (!powerSound_
) powerSound_
=
72 new VirtualSoundSource(VirtualSoundPriority::eRotation
, true, false);
73 powerSound_
->setPosition(tank
->getPosition().getTankPosition().asVector());
76 moveLeftRight(tank
, buffer
, keyState
, frameTime
);
77 moveUpDown(tank
, buffer
, keyState
, frameTime
);
78 movePower(tank
, buffer
, keyState
, frameTime
);
80 KEYBOARDKEY("FIRE_WEAPON", fireKey
);
81 if (fireKey
->keyDown(buffer
, keyState
, false))
83 // Only allow the standard fire key when we are not selecting a point
85 Accessory
*currentWeapon
=
86 tank
->getAccessories().getWeapons().getCurrent();
88 currentWeapon
->getPositionSelect() == Accessory::ePositionSelectNone
)
94 KEYBOARDKEY("AUTO_AIM", aimKey
);
95 if (aimKey
->keyDown(buffer
, keyState
))
100 KEYBOARDKEY("ENABLE_PARACHUTES", parachuteKey
);
101 if (parachuteKey
->keyDown(buffer
, keyState
, false))
103 std::list
<Accessory
*> ¶chutes
=
104 tank
->getAccessories().getAllAccessoriesByType(
105 AccessoryPart::AccessoryParachute
);
106 if (parachutes
.size() == 1)
108 parachutesUpDown(tank
, parachutes
.front()->getAccessoryId());
112 KEYBOARDKEY("ENABLE_SHIELDS", shieldKey
);
113 if (shieldKey
->keyDown(buffer
, keyState
, false))
115 if (!tank
->getShield().getCurrentShield())
117 std::list
<Accessory
*> &shields
=
118 tank
->getAccessories().getAllAccessoriesByType(
119 AccessoryPart::AccessoryShield
);
120 if (shields
.size() == 1)
122 shieldsUpDown(tank
, shields
.front()->getAccessoryId());
127 KEYBOARDKEY("USE_BATTERY", batteryKey
);
128 if (batteryKey
->keyDown(buffer
, keyState
, false))
130 if (tank
->getLife().getLife() <
131 tank
->getLife().getMaxLife())
133 std::list
<Accessory
*> &entries
=
134 tank
->getAccessories().getAllAccessoriesByType(
135 AccessoryPart::AccessoryBattery
);
136 if (!entries
.empty())
138 useBattery(tank
, entries
.front()->getAccessoryId());
143 KEYBOARDKEY("UNDO_MOVE", undoKey
);
144 if (undoKey
->keyDown(buffer
, keyState
, false))
146 tank
->getPosition().undo();
149 KEYBOARDKEY("CHANGE_UP_WEAPON", weaponUpKey
);
150 KEYBOARDKEY("CHANGE_DOWN_WEAPON", weaponDownKey
);
151 bool upWeapon
= weaponUpKey
->keyDown(buffer
, keyState
, false);
152 bool downWeapon
= weaponDownKey
->keyDown(buffer
, keyState
, false);
153 if (upWeapon
|| downWeapon
)
164 TargetRendererImplTankHUD::setText("Weapon : ",
165 tank
->getAccessories().getWeapons().getWeaponString());
169 void TankKeyboardControlUtil::nextWeapon(Tank
*tank
)
171 std::list
<Accessory
*> &result
=
172 tank
->getAccessories().getAllAccessoriesByType(
173 AccessoryPart::AccessoryWeapon
);
174 ScorchedClient::instance()->getAccessoryStore().sortList(result
,
175 OptionsDisplay::instance()->getAccessorySortKey());
177 std::list
<Accessory
*>::iterator itor
;
178 for (itor
= result
.begin();
179 itor
!= result
.end();
182 if (tank
->getAccessories().getWeapons().getCurrent() == (*itor
))
184 if (++itor
== result
.end())
186 itor
= result
.begin();
188 tank
->getAccessories().getWeapons().setWeapon(*itor
);
194 void TankKeyboardControlUtil::prevWeapon(Tank
*tank
)
196 std::list
<Accessory
*> &result
=
197 tank
->getAccessories().getAllAccessoriesByType(
198 AccessoryPart::AccessoryWeapon
);
199 ScorchedClient::instance()->getAccessoryStore().sortList(result
,
200 OptionsDisplay::instance()->getAccessorySortKey());
202 std::list
<Accessory
*>::iterator itor
;
203 for (itor
= result
.begin();
204 itor
!= result
.end();
207 if (tank
->getAccessories().getWeapons().getCurrent() == (*itor
))
209 if (itor
== result
.begin())
215 tank
->getAccessories().getWeapons().setWeapon(*itor
);
221 void TankKeyboardControlUtil::endPlayMove(Tank
*tank
)
223 if (elevateSound_
) elevateSound_
->stop();
224 if (rotateSound_
) rotateSound_
->stop();
225 if (powerSound_
) powerSound_
->stop();
228 void TankKeyboardControlUtil::autoAim(Tank
*tank
)
230 int x
= ScorchedClient::instance()->getGameState().getMouseX();
231 int y
= ScorchedClient::instance()->getGameState().getMouseY();
235 MainCamera::instance()->getCamera().draw();
236 if (MainCamera::instance()->getCamera().
237 getDirectionFromPt((GLfloat
) x
, (GLfloat
) y
, direction
))
239 if (ScorchedClient::instance()->getLandscapeMaps().
240 getGroundMaps().getIntersect(direction
, intersect
))
242 Vector
&position
= tank
->getPosition().getTankPosition().asVector();
244 // Calculate direction
245 Vector direction
= intersect
- position
;
246 float angleXYRads
= atan2f(direction
[1], direction
[0]);
247 float angleXYDegs
= (angleXYRads
/ 3.14f
) * 180.0f
- 90.0f
;
249 tank
->getPosition().rotateGunXY(fixed::fromFloat(angleXYDegs
), false);
252 TargetRendererImplTankAIM::setAimPosition(intersect
);
257 void TankKeyboardControlUtil::moveLeftRight(Tank
*tank
,
258 char *buffer
, unsigned int keyState
, float frameTime
)
260 static bool LRMoving
= false;
261 bool currentLRMoving
= false;
263 KEYBOARDKEY("TURN_RIGHT", rightKey
);
264 KEYBOARDKEY("TURN_RIGHT_SLOW", rightSlowKey
);
265 KEYBOARDKEY("TURN_RIGHT_VSLOW", rightVSlowKey
);
266 KEYBOARDKEY("TURN_RIGHT_FAST", rightFastKey
);
267 KEYBOARDKEY("TURN_LEFT", leftKey
);
268 KEYBOARDKEY("TURN_LEFT_SLOW", leftSlowKey
);
269 KEYBOARDKEY("TURN_LEFT_VSLOW", leftVSlowKey
);
270 KEYBOARDKEY("TURN_LEFT_FAST", leftFastKey
);
272 bool rightK
= rightKey
->keyDown(buffer
, keyState
);
273 bool rightKF
= rightFastKey
->keyDown(buffer
, keyState
);
274 bool rightKS
= rightSlowKey
->keyDown(buffer
, keyState
);
275 bool rightKVS
= rightVSlowKey
->keyDown(buffer
, keyState
);
276 bool leftK
= leftKey
->keyDown(buffer
, keyState
);
277 bool leftKF
= leftFastKey
->keyDown(buffer
, keyState
);
278 bool leftKS
= leftSlowKey
->keyDown(buffer
, keyState
);
279 bool leftKVS
= leftVSlowKey
->keyDown(buffer
, keyState
);
281 if (rightK
|| rightKF
|| rightKS
|| rightKVS
)
283 float mult
= frameTime
;
284 if (rightKF
) mult
*= 4.0f
;
285 else if (rightKS
) mult
*= 0.25f
;
286 else if (rightKVS
) mult
*= 0.05f
;
288 tank
->getPosition().rotateGunXY(fixed::fromFloat(-45.0f
* mult
));
289 currentLRMoving
= true;
293 else if (leftK
|| leftKF
|| leftKS
|| leftKVS
)
295 float mult
= frameTime
;
296 if (leftKF
) mult
*= 4.0f
;
297 else if (leftKS
) mult
*= 0.25f
;
298 else if (leftKVS
) mult
*= 0.05f
;
300 tank
->getPosition().rotateGunXY(fixed::fromFloat(45.0f
* mult
));
301 currentLRMoving
= true;
306 if (LRMoving
!= currentLRMoving
)
308 CACHE_SOUND(sound
, S3D::getDataFile("data/wav/movement/movement.wav"));
309 CACHE_SOUND(turn
, S3D::getDataFile("data/wav/movement/turn.wav"));
312 startSound_
->play(sound
);
313 rotateSound_
->play(turn
);
317 rotateSound_
->stop();
320 LRMoving
= currentLRMoving
;
324 void TankKeyboardControlUtil::leftRightHUD(Tank
*tank
)
326 float rot
= tank
->getPosition().getRotationGunXY().asFloat() / 360.0f
;
327 TargetRendererImplTankHUD::setText("Rot:",
328 tank
->getPosition().getRotationString(), rot
* 100.0f
);
331 void TankKeyboardControlUtil::moveUpDown(Tank
*tank
,
332 char *buffer
, unsigned int keyState
, float frameTime
)
334 static bool UDMoving
= false;
335 bool currentUDMoving
= false;
337 KEYBOARDKEY("ROTATE_UP", staticUpKey
);
338 KEYBOARDKEY("ROTATE_UP_SLOW", staticUpSlowKey
);
339 KEYBOARDKEY("ROTATE_UP_VSLOW", staticUpVSlowKey
);
340 KEYBOARDKEY("ROTATE_UP_FAST", staticUpFastKey
);
341 KEYBOARDKEY("ROTATE_DOWN", staticDownKey
);
342 KEYBOARDKEY("ROTATE_DOWN_SLOW", staticDownSlowKey
);
343 KEYBOARDKEY("ROTATE_DOWN_VSLOW", staticDownVSlowKey
);
344 KEYBOARDKEY("ROTATE_DOWN_FAST", staticDownFastKey
);
346 KeyboardKey
*upKey
= staticUpKey
;
347 KeyboardKey
*upSlowKey
= staticUpSlowKey
;
348 KeyboardKey
*upVSlowKey
= staticUpVSlowKey
;
349 KeyboardKey
*upFastKey
= staticUpFastKey
;
350 KeyboardKey
*downKey
= staticDownKey
;
351 KeyboardKey
*downSlowKey
= staticDownSlowKey
;
352 KeyboardKey
*downVSlowKey
= staticDownVSlowKey
;
353 KeyboardKey
*downFastKey
= staticDownFastKey
;
354 if (OptionsDisplay::instance()->getInvertElevation())
356 upKey
= staticDownKey
;
357 upSlowKey
= staticDownSlowKey
;
358 upVSlowKey
= staticDownVSlowKey
;
359 upFastKey
= staticDownFastKey
;
360 downKey
= staticUpKey
;
361 downSlowKey
= staticUpSlowKey
;
362 downVSlowKey
= staticUpVSlowKey
;
363 downFastKey
= staticUpFastKey
;
366 bool upK
= upKey
->keyDown(buffer
, keyState
);
367 bool upKS
= upSlowKey
->keyDown(buffer
, keyState
);
368 bool upKVS
= upVSlowKey
->keyDown(buffer
, keyState
);
369 bool upKF
= upFastKey
->keyDown(buffer
, keyState
);
370 bool downK
= downKey
->keyDown(buffer
, keyState
);
371 bool downKS
= downSlowKey
->keyDown(buffer
, keyState
);
372 bool downKVS
= downVSlowKey
->keyDown(buffer
, keyState
);
373 bool downKF
= downFastKey
->keyDown(buffer
, keyState
);
375 if (upK
|| upKS
|| upKF
|| upKVS
)
377 float mult
= frameTime
;
378 if (upKF
) mult
*= 4.0f
;
379 else if (upKS
) mult
*= 0.25f
;
380 else if (upKVS
) mult
*= 0.05f
;
382 tank
->getPosition().rotateGunYZ(fixed::fromFloat(-45.0f
* mult
));
383 currentUDMoving
= true;
387 else if (downK
|| downKS
|| downKF
|| downKVS
)
389 float mult
= frameTime
;
390 if (downKF
) mult
*= 4.0f
;
391 else if (downKS
) mult
*= 0.25f
;
392 else if (downKVS
) mult
*= 0.05f
;
394 tank
->getPosition().rotateGunYZ(fixed::fromFloat(45.0f
* mult
));
395 currentUDMoving
= true;
400 if (UDMoving
!= currentUDMoving
)
402 CACHE_SOUND(sound
, S3D::getDataFile("data/wav/movement/movement.wav"));
403 CACHE_SOUND(elevate
, S3D::getDataFile("data/wav/movement/elevate.wav"));
406 startSound_
->play(sound
);
407 elevateSound_
->play(elevate
);
411 elevateSound_
->stop();
414 UDMoving
= currentUDMoving
;
418 void TankKeyboardControlUtil::upDownHUD(Tank
*tank
)
420 float rot
= tank
->getPosition().getRotationGunYZ().asFloat() / 90.0f
;
421 TargetRendererImplTankHUD::setText("Ele:",
422 tank
->getPosition().getElevationString(), rot
* 100.0f
);
425 void TankKeyboardControlUtil::movePower(Tank
*tank
,
426 char *buffer
, unsigned int keyState
, float frameTime
)
428 static bool PMoving
= false;
429 bool currentPMoving
= false;
431 KEYBOARDKEY("INCREASE_POWER", incKey
);
432 KEYBOARDKEY("INCREASE_POWER_SLOW", incSlowKey
);
433 KEYBOARDKEY("INCREASE_POWER_VSLOW", incVSlowKey
);
434 KEYBOARDKEY("INCREASE_POWER_FAST", incFastKey
);
435 KEYBOARDKEY("DECREASE_POWER", decKey
);
436 KEYBOARDKEY("DECREASE_POWER_SLOW", decSlowKey
);
437 KEYBOARDKEY("DECREASE_POWER_VSLOW", decVSlowKey
);
438 KEYBOARDKEY("DECREASE_POWER_FAST", decFastKey
);
439 bool incK
= incKey
->keyDown(buffer
, keyState
);
440 bool incKS
= incSlowKey
->keyDown(buffer
, keyState
);
441 bool incKVS
= incVSlowKey
->keyDown(buffer
, keyState
);
442 bool incKF
= incFastKey
->keyDown(buffer
, keyState
);
443 bool decK
= decKey
->keyDown(buffer
, keyState
);
444 bool decKS
= decSlowKey
->keyDown(buffer
, keyState
);
445 bool decKVS
= decVSlowKey
->keyDown(buffer
, keyState
);
446 bool decKF
= decFastKey
->keyDown(buffer
, keyState
);
448 if (incK
|| incKS
|| incKF
|| incKVS
)
450 float mult
= frameTime
;
451 if (incKF
) mult
*= 4.0f
;
452 else if (incKS
) mult
*= 0.25f
;
453 else if (incKVS
) mult
*= 0.05f
;
455 tank
->getPosition().changePower(fixed::fromFloat(250.0f
* mult
));
456 currentPMoving
= true;
460 else if (decK
|| decKS
|| decKF
|| decKVS
)
462 float mult
= frameTime
;
463 if (decKF
) mult
*= 4.0f
;
464 else if (decKS
) mult
*= 0.25f
;
465 else if (decKVS
) mult
*= 0.05f
;
467 tank
->getPosition().changePower(fixed::fromFloat(-250.0f
* mult
));
468 currentPMoving
= true;
473 if (PMoving
!= currentPMoving
)
475 CACHE_SOUND(power
, S3D::getDataFile("data/wav/movement/power.wav"));
478 powerSound_
->play(power
);
485 PMoving
= currentPMoving
;
489 void TankKeyboardControlUtil::powerHUD(Tank
*tank
)
491 float power
= tank
->getPosition().getPower().asFloat() /
492 tank
->getPosition().getMaxPower().asFloat();
493 TargetRendererImplTankHUD::setText("Pwr:",
494 tank
->getPosition().getPowerString(), power
* 100.0f
);
498 void TankKeyboardControlUtil::fireShot(Tank
*tank
)
500 Accessory
*currentWeapon
=
501 tank
->getAccessories().getWeapons().getCurrent();
504 // send message saying we are finished with shot
505 ComsPlayedMoveMessage
comsMessage(tank
->getPlayerId(), ComsPlayedMoveMessage::eShot
);
507 currentWeapon
->getAccessoryId(),
508 tank
->getPosition().getRotationGunXY(),
509 tank
->getPosition().getRotationGunYZ(),
510 tank
->getPosition().getPower(),
511 tank
->getPosition().getSelectPositionX(),
512 tank
->getPosition().getSelectPositionY());
514 // If so we send this move to the server
515 ComsMessageSender::sendToServer(comsMessage
);
517 // Stimulate into the next state waiting for all the shots
518 ScorchedClient::instance()->getGameState().stimulate(ClientState::StimWait
);
522 void TankKeyboardControlUtil::skipShot(Tank
*tank
)
524 // send message saying we are finished with shot
525 ComsPlayedMoveMessage
comsMessage(tank
->getPlayerId(), ComsPlayedMoveMessage::eSkip
);
527 // Check if we are running in a NET/LAN environment
528 // If so we send this move to the server
529 ComsMessageSender::sendToServer(comsMessage
);
531 // Stimulate into the next state waiting for all the shots
532 ScorchedClient::instance()->getGameState().stimulate(ClientState::StimWait
);
535 void TankKeyboardControlUtil::resign(Tank
*tank
)
537 // send message saying we are finished with shot
538 ComsPlayedMoveMessage
comsMessage(tank
->getPlayerId(), ComsPlayedMoveMessage::eResign
);
540 // Check if we are running in a NET/LAN environment
541 // If so we send this move to the server
542 ComsMessageSender::sendToServer(comsMessage
);
544 // Stimulate into the next state waiting for all the shots
545 ScorchedClient::instance()->getGameState().stimulate(ClientState::StimWait
);
548 void TankKeyboardControlUtil::parachutesUpDown(Tank
*tank
, unsigned int paraId
)
550 ComsDefenseMessage
defenseMessage(
552 (paraId
!=0)?ComsDefenseMessage::eParachutesUp
:ComsDefenseMessage::eParachutesDown
,
554 ComsMessageSender::sendToServer(defenseMessage
);
557 void TankKeyboardControlUtil::shieldsUpDown(Tank
*tank
, unsigned int shieldId
)
559 ComsDefenseMessage
defenseMessage(
561 (shieldId
!=0)?ComsDefenseMessage::eShieldUp
:ComsDefenseMessage::eShieldDown
,
563 ComsMessageSender::sendToServer(defenseMessage
);
566 void TankKeyboardControlUtil::useBattery(Tank
*tank
, unsigned int batteryId
)
568 ComsDefenseMessage
defenseMessage(
570 ComsDefenseMessage::eBatteryUse
,
572 ComsMessageSender::sendToServer(defenseMessage
);