2014-03-09 21:43:38 +09:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 yvt
|
|
|
|
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
|
|
|
|
|
|
|
|
This file is part of OpenSpades.
|
|
|
|
|
|
|
|
OpenSpades is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
OpenSpades is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Client.h"
|
|
|
|
|
|
|
|
#include <Core/Settings.h>
|
2014-03-11 03:42:04 +09:00
|
|
|
#include <Core/Strings.h>
|
2014-03-09 21:43:38 +09:00
|
|
|
|
|
|
|
#include "IAudioChunk.h"
|
|
|
|
#include "IAudioDevice.h"
|
|
|
|
|
|
|
|
#include "ClientUI.h"
|
|
|
|
#include "PaletteView.h"
|
|
|
|
#include "LimboView.h"
|
|
|
|
#include "MapView.h"
|
|
|
|
#include "Corpse.h"
|
|
|
|
|
|
|
|
#include "World.h"
|
|
|
|
#include "Weapon.h"
|
|
|
|
|
|
|
|
#include "NetClient.h"
|
|
|
|
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_mouseSensitivity, "1");
|
|
|
|
SPADES_SETTING(cg_zoomedMouseSensScale, "0.6");
|
|
|
|
SPADES_SETTING(cg_mouseExpPower, "1");
|
|
|
|
SPADES_SETTING(cg_invertMouseY, "0");
|
|
|
|
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_holdAimDownSight, "0");
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_keyAttack, "LeftMouseButton");
|
|
|
|
SPADES_SETTING(cg_keyAltAttack, "RightMouseButton");
|
|
|
|
SPADES_SETTING(cg_keyToolSpade, "1");
|
|
|
|
SPADES_SETTING(cg_keyToolBlock, "2");
|
|
|
|
SPADES_SETTING(cg_keyToolWeapon, "3");
|
|
|
|
SPADES_SETTING(cg_keyToolGrenade, "4");
|
|
|
|
SPADES_SETTING(cg_keyReloadWeapon, "r");
|
|
|
|
SPADES_SETTING(cg_keyFlashlight, "f");
|
2014-03-13 01:44:58 +09:00
|
|
|
SPADES_SETTING(cg_keyLastTool, "");
|
2014-03-09 21:43:38 +09:00
|
|
|
|
|
|
|
SPADES_SETTING(cg_keyMoveLeft, "a");
|
|
|
|
SPADES_SETTING(cg_keyMoveRight, "d");
|
|
|
|
SPADES_SETTING(cg_keyMoveForward, "w");
|
|
|
|
SPADES_SETTING(cg_keyMoveBackward, "s");
|
|
|
|
SPADES_SETTING(cg_keyJump, "Space");
|
|
|
|
SPADES_SETTING(cg_keyCrouch, "Control");
|
|
|
|
SPADES_SETTING(cg_keySprint, "Shift");
|
|
|
|
SPADES_SETTING(cg_keySneak, "v");
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_keyCaptureColor, "e");
|
|
|
|
SPADES_SETTING(cg_keyGlobalChat, "t");
|
|
|
|
SPADES_SETTING(cg_keyTeamChat, "y");
|
|
|
|
SPADES_SETTING(cg_keyChangeMapScale, "m");
|
|
|
|
SPADES_SETTING(cg_keyToggleMapZoom, "n");
|
|
|
|
SPADES_SETTING(cg_keyScoreboard, "Tab");
|
|
|
|
SPADES_SETTING(cg_keyLimbo, "l");
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_keyScreenshot, "0");
|
|
|
|
SPADES_SETTING(cg_keySceneshot, "9");
|
|
|
|
SPADES_SETTING(cg_keySaveMap, "8");
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_switchToolByWheel, "1");
|
|
|
|
|
|
|
|
SPADES_SETTING(cg_debugCorpse, "0");
|
|
|
|
|
2014-03-11 03:42:04 +09:00
|
|
|
SPADES_SETTING(cg_alerts, "1");
|
|
|
|
|
|
|
|
|
2014-03-09 21:43:38 +09:00
|
|
|
namespace spades {
|
|
|
|
namespace client {
|
|
|
|
|
|
|
|
bool Client::WantsToBeClosed() {
|
|
|
|
return readyToClose;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Client::Closing() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Client::NeedsAbsoluteMouseCoordinate() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if(!world) {
|
|
|
|
// now loading.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if(IsLimboViewActive()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::MouseEvent(float x, float y) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
|
|
|
scriptedUI->MouseEvent(x, y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(IsLimboViewActive()){
|
|
|
|
limbo->MouseEvent(x, y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(IsFollowing()){
|
|
|
|
SPAssert(world != nullptr);
|
|
|
|
/*
|
|
|
|
if(world->GetLocalPlayer() &&
|
|
|
|
world->GetLocalPlayer()->GetTeamId() >= 2 &&
|
|
|
|
followingPlayerId == world->GetLocalPlayerIndex()){
|
|
|
|
// invert dir
|
|
|
|
x = -x; y = -y;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
x = -x;
|
|
|
|
if (!cg_invertMouseY)
|
|
|
|
y = -y;
|
|
|
|
|
|
|
|
followYaw -= x * 0.003f;
|
|
|
|
followPitch -= y * 0.003f;
|
|
|
|
if(followPitch < -M_PI*.45f) followPitch = -static_cast<float>(M_PI)*.45f;
|
|
|
|
if(followPitch > M_PI*.45f) followPitch = static_cast<float>(M_PI) * .45f;
|
|
|
|
followYaw = fmodf(followYaw, static_cast<float>(M_PI)*2.f);
|
|
|
|
}else if(world && world->GetLocalPlayer()){
|
|
|
|
Player *p = world->GetLocalPlayer();
|
|
|
|
float aimDownState = GetAimDownState();
|
|
|
|
if(p->IsAlive()){
|
|
|
|
x /= GetAimDownZoomScale();
|
|
|
|
y /= GetAimDownZoomScale();
|
|
|
|
|
|
|
|
float rad = x * x + y * y;
|
|
|
|
if(rad > 0.f) {
|
|
|
|
if((float)cg_mouseExpPower < 0.001f ||
|
|
|
|
isnan((float)cg_mouseExpPower)) {
|
|
|
|
SPLog("Invalid cg_mouseExpPower value, resetting to 1.0");
|
|
|
|
cg_mouseExpPower = 1.f;
|
|
|
|
}
|
|
|
|
float factor = renderer->ScreenWidth() * .1f;
|
|
|
|
factor *= factor;
|
|
|
|
rad /= factor;
|
|
|
|
rad = powf(rad, (float)cg_mouseExpPower * 0.5f - 0.5f);
|
|
|
|
|
|
|
|
// shouldn't happen...
|
|
|
|
if(isnan(rad)) rad = 1.f;
|
|
|
|
|
|
|
|
x *= rad;
|
|
|
|
y *= rad;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(aimDownState > 0.f) {
|
|
|
|
float scale = cg_zoomedMouseSensScale;
|
|
|
|
scale = powf(scale, aimDownState);
|
|
|
|
x *= scale;
|
|
|
|
y *= scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
x *= (float)cg_mouseSensitivity;
|
|
|
|
y *= (float)cg_mouseSensitivity;
|
|
|
|
|
|
|
|
if(cg_invertMouseY)
|
|
|
|
y = -y;
|
|
|
|
|
|
|
|
p->Turn(x * 0.003f, y * 0.003f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::WheelEvent(float x, float y) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
|
|
|
scriptedUI->WheelEvent(x, y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(y > .5f) {
|
|
|
|
KeyEvent("WheelDown", true);
|
|
|
|
KeyEvent("WheelDown", false);
|
|
|
|
}else if(y < -.5f){
|
|
|
|
KeyEvent("WheelUp", true);
|
|
|
|
KeyEvent("WheelUp", false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::TextInputEvent(const std::string &ch){
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
2014-03-09 23:16:20 +09:00
|
|
|
if (scriptedUI->NeedsInput() && !scriptedUI->isIgnored(ch)) {
|
2014-03-09 21:43:38 +09:00
|
|
|
scriptedUI->TextInputEvent(ch);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we don't get "/" here anymore
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::TextEditingEvent(const std::string &ch,
|
|
|
|
int start, int len) {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
2014-03-09 23:16:20 +09:00
|
|
|
if (scriptedUI->NeedsInput() && !scriptedUI->isIgnored(ch)) {
|
2014-03-09 21:43:38 +09:00
|
|
|
scriptedUI->TextEditingEvent(ch, start, len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Client::AcceptsTextInput() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
|
|
|
return scriptedUI->AcceptsTextInput();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
AABB2 Client::GetTextInputRect() {
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
|
|
|
return scriptedUI->GetTextInputRect();
|
|
|
|
}
|
|
|
|
return AABB2();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this might not be a fast way
|
|
|
|
//lm: ideally we should normalize the key when reading the config.
|
|
|
|
static bool CheckKey(const std::string& cfg,
|
|
|
|
const std::string& input) {
|
|
|
|
if(cfg.empty())
|
|
|
|
return false;
|
|
|
|
std::vector<std::string> keys = Split(cfg,",");
|
|
|
|
static const std::string space1("space");
|
|
|
|
static const std::string space2("spacebar");
|
|
|
|
static const std::string space3("spacekey");
|
|
|
|
for(size_t i = 0; i < keys.size(); i++) {
|
|
|
|
std::string key = keys[i];
|
|
|
|
if(EqualsIgnoringCase(key, space1) ||
|
|
|
|
EqualsIgnoringCase(key, space2) ||
|
|
|
|
EqualsIgnoringCase(key, space3)) {
|
|
|
|
if(input == " ")
|
|
|
|
return true;
|
|
|
|
}else{
|
|
|
|
if(EqualsIgnoringCase(key, input))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::KeyEvent(const std::string& name, bool down){
|
|
|
|
SPADES_MARK_FUNCTION();
|
|
|
|
|
|
|
|
if(scriptedUI->NeedsInput()) {
|
2014-03-09 23:16:20 +09:00
|
|
|
if(!scriptedUI->isIgnored(name)) {
|
|
|
|
scriptedUI->KeyEvent(name, down);
|
|
|
|
}else{
|
|
|
|
if(!down) {
|
|
|
|
scriptedUI->setIgnored("");
|
|
|
|
}
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(name == "Escape"){
|
|
|
|
if(down){
|
|
|
|
if(inGameLimbo){
|
|
|
|
inGameLimbo = false;
|
|
|
|
}else{
|
|
|
|
if(GetWorld() == nullptr){
|
|
|
|
// no world = loading now.
|
|
|
|
// in this case, abort download, and quit the game immediately.
|
|
|
|
readyToClose = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
scriptedUI->EnterClientMenu();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(world){
|
|
|
|
if(IsLimboViewActive()){
|
|
|
|
if(down){
|
|
|
|
limbo->KeyEvent(name);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(IsFollowing()){
|
|
|
|
if(CheckKey(cg_keyAttack, name)){
|
|
|
|
if(down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() >= 2 ||
|
|
|
|
time > lastAliveTime + 1.3f)
|
|
|
|
FollowNextPlayer(false);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}else if(CheckKey(cg_keyAltAttack, name)){
|
|
|
|
if(down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() >= 2) {
|
|
|
|
// spectating
|
|
|
|
followingPlayerId = world->GetLocalPlayerIndex();
|
|
|
|
}else if(time > lastAliveTime + 1.3f){
|
|
|
|
// dead
|
|
|
|
FollowNextPlayer(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(world->GetLocalPlayer()){
|
|
|
|
Player *p = world->GetLocalPlayer();
|
|
|
|
|
|
|
|
if(p->IsAlive() && p->GetTool() == Player::ToolBlock && down) {
|
|
|
|
if(paletteView->KeyInput(name)){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cg_debugCorpse){
|
|
|
|
if(name == "p" && down){
|
|
|
|
Corpse *corp;
|
|
|
|
Player *victim = world->GetLocalPlayer();
|
|
|
|
corp = new Corpse(renderer, map, victim);
|
|
|
|
corp->AddImpulse(victim->GetFront() * 32.f);
|
|
|
|
corpses.emplace_back(corp);
|
|
|
|
|
|
|
|
if(corpses.size() > corpseHardLimit){
|
|
|
|
corpses.pop_front();
|
|
|
|
}else if(corpses.size() > corpseSoftLimit){
|
|
|
|
RemoveInvisibleCorpses();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(CheckKey(cg_keyMoveLeft, name)){
|
|
|
|
playerInput.moveLeft = down;
|
|
|
|
keypadInput.left = down;
|
|
|
|
if(down) playerInput.moveRight = false;
|
|
|
|
else playerInput.moveRight = keypadInput.right;
|
|
|
|
}else if(CheckKey(cg_keyMoveRight, name)){
|
|
|
|
playerInput.moveRight = down;
|
|
|
|
keypadInput.right = down;
|
|
|
|
if(down) playerInput.moveLeft = false;
|
|
|
|
else playerInput.moveLeft = keypadInput.left;
|
|
|
|
}else if(CheckKey(cg_keyMoveForward, name)){
|
|
|
|
playerInput.moveForward = down;
|
|
|
|
keypadInput.forward = down;
|
|
|
|
if(down) playerInput.moveBackward = false;
|
|
|
|
else playerInput.moveBackward = keypadInput.backward;
|
|
|
|
}else if(CheckKey(cg_keyMoveBackward, name)){
|
|
|
|
playerInput.moveBackward = down;
|
|
|
|
keypadInput.backward = down;
|
|
|
|
if(down) playerInput.moveForward = false;
|
|
|
|
else playerInput.moveForward = keypadInput.forward;
|
|
|
|
}else if(CheckKey(cg_keyCrouch, name)){
|
|
|
|
playerInput.crouch = down;
|
|
|
|
}else if(CheckKey(cg_keySprint, name)){
|
|
|
|
playerInput.sprint = down;
|
|
|
|
if(down){
|
|
|
|
if(world->GetLocalPlayer()->IsToolWeapon()){
|
|
|
|
weapInput.secondary = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keySneak, name)){
|
|
|
|
playerInput.sneak = down;
|
|
|
|
}else if(CheckKey(cg_keyJump, name)){
|
|
|
|
playerInput.jump = down;
|
|
|
|
}else if(CheckKey(cg_keyAttack, name)){
|
|
|
|
weapInput.primary = down;
|
|
|
|
}else if(CheckKey(cg_keyAltAttack, name)){
|
2014-03-22 01:37:14 +09:00
|
|
|
auto lastVal = weapInput.secondary;
|
2014-03-09 21:43:38 +09:00
|
|
|
if(world->GetLocalPlayer()->IsToolWeapon() && (!cg_holdAimDownSight)){
|
|
|
|
if(down && !playerInput.sprint && !world->GetLocalPlayer()->GetWeapon()->IsReloading()){
|
|
|
|
weapInput.secondary = !weapInput.secondary;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if(!playerInput.sprint){
|
|
|
|
weapInput.secondary = down;
|
|
|
|
}else{
|
|
|
|
weapInput.secondary = down;
|
|
|
|
}
|
|
|
|
}
|
2014-03-22 01:37:14 +09:00
|
|
|
if(world->GetLocalPlayer()->IsToolWeapon() && weapInput.secondary && !lastVal &&
|
|
|
|
world->GetLocalPlayer()->IsReadyToUseTool() &&
|
|
|
|
!world->GetLocalPlayer()->GetWeapon()->IsReloading()) {
|
|
|
|
AudioParam params;
|
|
|
|
params.volume = 0.08f;
|
|
|
|
Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Weapons/AimDownSightLocal.wav");
|
|
|
|
audioDevice->PlayLocal(chunk, MakeVector3(.4f, -.3f, .5f), params);
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
}else if(CheckKey(cg_keyReloadWeapon, name) && down){
|
|
|
|
Weapon *w = world->GetLocalPlayer()->GetWeapon();
|
|
|
|
if(w->GetAmmo() < w->GetClipSize() &&
|
|
|
|
w->GetStock() > 0 &&
|
|
|
|
(!world->GetLocalPlayer()->IsAwaitingReloadCompletion()) &&
|
|
|
|
(!w->IsReloading()) &&
|
|
|
|
world->GetLocalPlayer()->GetTool() == Player::ToolWeapon){
|
|
|
|
if(world->GetLocalPlayer()->IsToolWeapon()){
|
|
|
|
if(weapInput.secondary) {
|
|
|
|
// if we send WeaponInput after sending Reload,
|
|
|
|
// server might cancel the reload.
|
|
|
|
// https://github.com/infogulch/pyspades/blob/895879ed14ddee47bb278a77be86d62c7580f8b7/pyspades/server.py#343
|
|
|
|
hasDelayedReload = true;
|
|
|
|
weapInput.secondary = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
world->GetLocalPlayer()->Reload();
|
|
|
|
net->SendReload();
|
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keyToolSpade, name) && down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
|
|
|
world->GetLocalPlayer()->IsAlive() &&
|
|
|
|
world->GetLocalPlayer()->IsToolSelectable(Player::ToolSpade)){
|
|
|
|
SetSelectedTool(Player::ToolSpade);
|
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keyToolBlock, name) && down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
2014-03-11 03:42:04 +09:00
|
|
|
world->GetLocalPlayer()->IsAlive()
|
|
|
|
){
|
|
|
|
if(world->GetLocalPlayer()->IsToolSelectable(Player::ToolBlock)) {
|
|
|
|
SetSelectedTool(Player::ToolBlock);
|
|
|
|
}else{
|
|
|
|
if(cg_alerts)
|
|
|
|
ShowAlert(_Tr("Client", "Out of Blocks"), AlertType::Error);
|
|
|
|
else
|
|
|
|
PlayAlertSound();
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keyToolWeapon, name) && down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
2014-03-11 03:42:04 +09:00
|
|
|
world->GetLocalPlayer()->IsAlive()){
|
|
|
|
if(world->GetLocalPlayer()->IsToolSelectable(Player::ToolWeapon)) {
|
|
|
|
SetSelectedTool(Player::ToolWeapon);
|
|
|
|
}else{
|
|
|
|
if(cg_alerts)
|
|
|
|
ShowAlert(_Tr("Client", "Out of Ammo"), AlertType::Error);
|
|
|
|
else
|
|
|
|
PlayAlertSound();
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keyToolGrenade, name) && down){
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
2014-03-11 03:42:04 +09:00
|
|
|
world->GetLocalPlayer()->IsAlive()){
|
|
|
|
if(world->GetLocalPlayer()->IsToolSelectable(Player::ToolGrenade)) {
|
|
|
|
SetSelectedTool(Player::ToolGrenade);
|
|
|
|
}else{
|
|
|
|
if(cg_alerts)
|
|
|
|
ShowAlert(_Tr("Client", "Out of Grenades"), AlertType::Error);
|
|
|
|
else
|
|
|
|
PlayAlertSound();
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
}
|
2014-03-13 01:44:58 +09:00
|
|
|
}else if(CheckKey(cg_keyLastTool, name) && down){
|
|
|
|
if(hasLastTool &&
|
|
|
|
world->GetLocalPlayer()->GetTeamId() < 2 &&
|
|
|
|
world->GetLocalPlayer()->IsAlive() &&
|
|
|
|
world->GetLocalPlayer()->IsToolSelectable(lastTool)){
|
|
|
|
hasLastTool = false;
|
|
|
|
SetSelectedTool(lastTool);
|
|
|
|
}
|
2014-03-09 21:43:38 +09:00
|
|
|
}else if(CheckKey(cg_keyGlobalChat, name) && down){
|
|
|
|
// global chat
|
|
|
|
scriptedUI->EnterGlobalChatWindow();
|
2014-03-09 23:16:20 +09:00
|
|
|
scriptedUI->setIgnored(name);
|
2014-03-09 21:43:38 +09:00
|
|
|
}else if(CheckKey(cg_keyTeamChat, name) && down){
|
|
|
|
// team chat
|
|
|
|
scriptedUI->EnterTeamChatWindow();
|
2014-03-09 23:16:20 +09:00
|
|
|
scriptedUI->setIgnored(name);
|
2014-03-09 21:43:38 +09:00
|
|
|
}else if(name == "/" && down){
|
|
|
|
// command
|
|
|
|
scriptedUI->EnterCommandWindow();
|
2014-03-09 23:16:20 +09:00
|
|
|
scriptedUI->setIgnored(name);
|
2014-03-09 21:43:38 +09:00
|
|
|
}else if(CheckKey(cg_keyCaptureColor, name) && down){
|
|
|
|
CaptureColor();
|
|
|
|
}else if(CheckKey(cg_keyChangeMapScale, name) && down){
|
|
|
|
mapView->SwitchScale();
|
|
|
|
Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Misc/SwitchMapZoom.wav");
|
|
|
|
audioDevice->PlayLocal(chunk, AudioParam());
|
|
|
|
}else if(CheckKey(cg_keyToggleMapZoom, name) && down){
|
|
|
|
if(largeMapView->ToggleZoom()){
|
|
|
|
Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Misc/OpenMap.wav");
|
|
|
|
audioDevice->PlayLocal(chunk, AudioParam());
|
|
|
|
}else{
|
|
|
|
Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Misc/CloseMap.wav");
|
|
|
|
audioDevice->PlayLocal(chunk, AudioParam());
|
|
|
|
}
|
|
|
|
}else if(CheckKey(cg_keyScoreboard, name)){
|
|
|
|
scoreboardVisible = down;
|
|
|
|
}else if(CheckKey(cg_keyLimbo, name) && down){
|
|
|
|
limbo->SetSelectedTeam(world->GetLocalPlayer()->GetTeamId());
|
|
|
|
limbo->SetSelectedWeapon(world->GetLocalPlayer()->GetWeapon()->GetWeaponType());
|
|
|
|
inGameLimbo = true;
|
|
|
|
}else if(CheckKey(cg_keySceneshot, name) && down){
|
|
|
|
TakeScreenShot(true);
|
|
|
|
}else if(CheckKey(cg_keyScreenshot, name) && down){
|
|
|
|
TakeScreenShot(false);
|
|
|
|
}else if(CheckKey(cg_keySaveMap, name) && down){
|
|
|
|
TakeMapShot();
|
|
|
|
}else if(CheckKey(cg_keyFlashlight, name) && down){
|
|
|
|
flashlightOn = !flashlightOn;
|
|
|
|
flashlightOnTime = time;
|
|
|
|
Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Player/Flashlight.wav");
|
|
|
|
audioDevice->PlayLocal(chunk, AudioParam());
|
|
|
|
}else if(cg_switchToolByWheel && down) {
|
|
|
|
bool rev = (int)cg_switchToolByWheel > 0;
|
|
|
|
if(name == (rev ? "WheelDown":"WheelUp")) {
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
|
|
|
world->GetLocalPlayer()->IsAlive()){
|
|
|
|
Player::ToolType t = world->GetLocalPlayer()->GetTool();
|
|
|
|
do{
|
|
|
|
switch(t){
|
|
|
|
case Player::ToolSpade:
|
|
|
|
t = Player::ToolGrenade;
|
|
|
|
break;
|
|
|
|
case Player::ToolBlock:
|
|
|
|
t = Player::ToolSpade;
|
|
|
|
break;
|
|
|
|
case Player::ToolWeapon:
|
|
|
|
t = Player::ToolBlock;
|
|
|
|
break;
|
|
|
|
case Player::ToolGrenade:
|
|
|
|
t = Player::ToolWeapon;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}while(!world->GetLocalPlayer()->IsToolSelectable(t));
|
|
|
|
SetSelectedTool(t);
|
|
|
|
}
|
|
|
|
}else if(name == (rev ? "WheelUp":"WheelDown")) {
|
|
|
|
if(world->GetLocalPlayer()->GetTeamId() < 2 &&
|
|
|
|
world->GetLocalPlayer()->IsAlive()){
|
|
|
|
Player::ToolType t = world->GetLocalPlayer()->GetTool();
|
|
|
|
do{
|
|
|
|
switch(t){
|
|
|
|
case Player::ToolSpade:
|
|
|
|
t = Player::ToolBlock;
|
|
|
|
break;
|
|
|
|
case Player::ToolBlock:
|
|
|
|
t = Player::ToolWeapon;
|
|
|
|
break;
|
|
|
|
case Player::ToolWeapon:
|
|
|
|
t = Player::ToolGrenade;
|
|
|
|
break;
|
|
|
|
case Player::ToolGrenade:
|
|
|
|
t = Player::ToolSpade;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}while(!world->GetLocalPlayer()->IsToolSelectable(t));
|
|
|
|
SetSelectedTool(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
// limbo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|