Accessory sorting due to price.
[scorched3d/parasti.git] / src / client / tankgraph / TankKeyboardControlUtil.cpp
blob7690f6e906c5d712b543f06c7d1ebc1f3d41e9d1
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
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(
56 Tank *tank,
57 const unsigned state,
58 float frameTime, char *buffer,
59 unsigned int keyState)
61 // Create sounds
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());
75 // Check key moves
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
84 // on the landscape.
85 Accessory *currentWeapon =
86 tank->getAccessories().getWeapons().getCurrent();
87 if (currentWeapon &&
88 currentWeapon->getPositionSelect() == Accessory::ePositionSelectNone)
90 fireShot(tank);
94 KEYBOARDKEY("AUTO_AIM", aimKey);
95 if (aimKey->keyDown(buffer, keyState))
97 autoAim(tank);
100 KEYBOARDKEY("ENABLE_PARACHUTES", parachuteKey);
101 if (parachuteKey->keyDown(buffer, keyState, false))
103 std::list<Accessory *> &parachutes =
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)
155 if (downWeapon)
157 prevWeapon(tank);
159 else
161 nextWeapon(tank);
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();
180 itor++)
182 if (tank->getAccessories().getWeapons().getCurrent() == (*itor))
184 if (++itor == result.end())
186 itor = result.begin();
188 tank->getAccessories().getWeapons().setWeapon(*itor);
189 break;
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();
205 itor++)
207 if (tank->getAccessories().getWeapons().getCurrent() == (*itor))
209 if (itor == result.begin())
211 itor = result.end();
214 --itor;
215 tank->getAccessories().getWeapons().setWeapon(*itor);
216 break;
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();
232 Line direction;
233 Vector intersect;
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);
250 leftRightHUD(tank);
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;
291 leftRightHUD(tank);
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;
303 leftRightHUD(tank);
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"));
310 if (currentLRMoving)
312 startSound_->play(sound);
313 rotateSound_->play(turn);
315 else
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;
385 upDownHUD(tank);
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;
397 upDownHUD(tank);
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"));
404 if (currentUDMoving)
406 startSound_->play(sound);
407 elevateSound_->play(elevate);
409 else
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;
458 powerHUD(tank);
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;
470 powerHUD(tank);
473 if (PMoving != currentPMoving)
475 CACHE_SOUND(power, S3D::getDataFile("data/wav/movement/power.wav"));
476 if (currentPMoving)
478 powerSound_->play(power);
480 else
482 powerSound_->stop();
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();
502 if (currentWeapon)
504 // send message saying we are finished with shot
505 ComsPlayedMoveMessage comsMessage(tank->getPlayerId(), ComsPlayedMoveMessage::eShot);
506 comsMessage.setShot(
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(
551 tank->getPlayerId(),
552 (paraId!=0)?ComsDefenseMessage::eParachutesUp:ComsDefenseMessage::eParachutesDown,
553 paraId);
554 ComsMessageSender::sendToServer(defenseMessage);
557 void TankKeyboardControlUtil::shieldsUpDown(Tank *tank, unsigned int shieldId)
559 ComsDefenseMessage defenseMessage(
560 tank->getPlayerId(),
561 (shieldId!=0)?ComsDefenseMessage::eShieldUp:ComsDefenseMessage::eShieldDown,
562 shieldId);
563 ComsMessageSender::sendToServer(defenseMessage);
566 void TankKeyboardControlUtil::useBattery(Tank *tank, unsigned int batteryId)
568 ComsDefenseMessage defenseMessage(
569 tank->getPlayerId(),
570 ComsDefenseMessage::eBatteryUse,
571 batteryId);
572 ComsMessageSender::sendToServer(defenseMessage);