예제 #1
0
		Client::~Client() {
			SPADES_MARK_FUNCTION();
			
			NetLog("Disconnecting");
			if(logStream) {
				SPLog("Closing netlog");
				logStream.reset();
			}
			
			if(net){
				SPLog("Disconnecting");
				net->Disconnect();
				net.reset();
			}
			
			SPLog("Disconnected");
			
			RemoveAllLocalEntities();
			RemoveAllCorpses();
			
			renderer->SetGameMap(nullptr);
            audioDevice->SetGameMap(nullptr);
			
			for(size_t i = 0; i < clientPlayers.size(); i++) {
				if(clientPlayers[i]) {
					clientPlayers[i]->Invalidate();
				}
			}
			clientPlayers.clear();
			
			
			scriptedUI->ClientDestroyed();
			tcView.reset();
			limbo.reset();
			scoreboard.reset();
			mapView.reset();
			largeMapView.reset();
			chatWindow.reset();
			killfeedWindow.reset();
			paletteView.reset();
			centerMessageView.reset();
			hurtRingView.reset();
			designFont.Set(nullptr);
			textFont.Set(nullptr);
			bigTextFont.Set(nullptr);
			world.reset();
		}
		void Client::PlayerDropIntel(spades::client::Player *p) {
			std::string msg;
			{
				std::string holderName = chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId());
				std::string otherTeamName = chatWindow->TeamColorMessage(world->GetTeam(1 - p->GetTeamId()).name,
																		 1 - p->GetTeamId());
				msg = _Tr("Client", "{0} dropped {1}'s intel", holderName, otherTeamName);
				chatWindow->AddMessage(msg);
			}
			
			if ((int)cg_centerMessage != 0){
				std::string holderName = p->GetName();
				std::string otherTeamName = world->GetTeam(1 - p->GetTeamId()).name;
				msg = _Tr("Client", "{0} dropped {1}'s Intel", holderName, otherTeamName);
				NetLog("%s", msg.c_str());
				centerMessageView->AddMessage(msg);
			}
		}
		void Client::PlayerLeaving(spades::client::Player *p) {
			{
				std::string msg;
				msg = _Tr("Client", "Player {0} has left", chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId()));
				chatWindow->AddMessage(msg);
			}
			{
				std::string msg;
				msg = _Tr("Client", "Player {0} has left", p->GetName());
				
				auto col = p->GetTeamId() < 2 ?
				world->GetTeam(p->GetTeamId()).color :
				IntVector3::Make(255, 255, 255);
				
				NetLog("%s", msg.c_str());
				scriptedUI->RecordChatLog(msg,
										  MakeVector4(col.x / 255.f, col.y / 255.f,
													  col.z / 255.f, 0.8f));
			}
		}
예제 #4
0
		void Client::ServerSentMessage(const std::string &msg) {
			NetLog("%s", msg.c_str());
			scriptedUI->RecordChatLog(msg, Vector4::Make(1.f, 1.f, 1.f, 0.8f));
			
			if(cg_serverAlert) {
				if(msg.substr(0, 3) == "N% ") {
					ShowAlert(msg.substr(3), AlertType::Notice);
					return;
				}
				if(msg.substr(0, 3) == "!% ") {
					ShowAlert(msg.substr(3), AlertType::Error);
					return;
				}
				if(msg.substr(0, 3) == "%% ") {
					ShowAlert(msg.substr(3), AlertType::Warning);
					return;
				}
			}
			
			chatWindow->AddMessage(msg);
		}
		void Client::TeamCapturedTerritory(int teamId,
										   int terId) {
			TCGameMode::Territory *ter = static_cast<TCGameMode *>(world->GetMode())->GetTerritory(terId);
			int old = ter->ownerTeamId;
			std::string msg;
			std::string teamName = chatWindow->TeamColorMessage(world->GetTeam(teamId).name,
																teamId);
			if(old < 2){
				std::string otherTeam = chatWindow->TeamColorMessage(world->GetTeam(old).name,
																	 old);
				msg = _Tr("Client", "{0} captured {1}'s territory", teamName, otherTeam);
			}else{
				msg = _Tr("Client", "{0} captured an neutral territory", teamName);
			}
			chatWindow->AddMessage(msg);
			
			if ((int)cg_centerMessage != 0){
				teamName = world->GetTeam(teamId).name;
				if (old < 2){
					std::string otherTeam = world->GetTeam(old).name;
					msg = _Tr("Client", "{0} captured {1}'s Territory", teamName, otherTeam);
				}
				else{
					msg = _Tr("Client", "{0} captured an Neutral Territory", teamName);
				}
				NetLog("%s", msg.c_str());
				centerMessageView->AddMessage(msg);
			}

			if(world->GetLocalPlayer() && !IsMuted()){
				if(teamId == world->GetLocalPlayer()->GetTeamId()){
					Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Feedback/TC/YourTeamCaptured.wav");
					audioDevice->PlayLocal(chunk, AudioParam());
				}else{
					Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Feedback/TC/EnemyCaptured.wav");
					audioDevice->PlayLocal(chunk, AudioParam());
				}
			}
			
		}
		void Client::PlayerPickedIntel(spades::client::Player *p) {
			std::string msg;
			{
				std::string holderName = chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId());
				std::string otherTeamName = chatWindow->TeamColorMessage(world->GetTeam(1 - p->GetTeamId()).name,
																		 1 - p->GetTeamId());
				msg = _Tr("Client", "{0} picked up {1}'s intel", holderName, otherTeamName);
				chatWindow->AddMessage(msg);
			}
			
			if ((int)cg_centerMessage != 0){
				std::string holderName = p->GetName();
				std::string otherTeamName = world->GetTeam(1 - p->GetTeamId()).name;
				msg = _Tr("Client", "{0} picked up {1}'s Intel.", holderName, otherTeamName);
				NetLog("%s", msg.c_str());
				centerMessageView->AddMessage(msg);
			}
			
			if(!IsMuted()) {
				Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Feedback/CTF/PickedUp.wav");
				audioDevice->PlayLocal(chunk, AudioParam());
			}
		}
		void Client::TeamWon(int teamId){
			std::string msg;
			msg = chatWindow->TeamColorMessage(world->GetTeam(teamId).name,
											   teamId);
			msg = _Tr("Client", "{0} wins!", msg);
			chatWindow->AddMessage(msg);
			
			msg = world->GetTeam(teamId).name;
			msg = _Tr("Client", "{0} Wins!", msg);
			NetLog("%s", msg.c_str());
			centerMessageView->AddMessage(msg);
			
			scriptedUI->RecordChatLog(msg, MakeVector4(1.f, 1.f, 1.f, 0.8f));
			
			if(world->GetLocalPlayer()){
				if(teamId == world->GetLocalPlayer()->GetTeamId()){
					Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Feedback/Win.wav");
					audioDevice->PlayLocal(chunk, AudioParam());
				}else{
					Handle<IAudioChunk> chunk = audioDevice->RegisterSound("Sounds/Feedback/Lose.wav");
					audioDevice->PlayLocal(chunk, AudioParam());
				}
			}
		}
예제 #8
0
		void Client::RunFrame(float dt) {
			SPADES_MARK_FUNCTION();
			
			fpsCounter.MarkFrame();
			
			if(frameToRendererInit > 0){
				// waiting for renderer initialization
				
				DrawStartupScreen();
				
				frameToRendererInit--;
				if(frameToRendererInit == 0){
					DoInit();
					
				}else{
					return;
				}
			}
			
			timeSinceInit += std::min(dt, .03f);
			
			// update network
			try{
				if(net->GetStatus() == NetClientStatusConnected)
					net->DoEvents(0);
				else
					net->DoEvents(10);
			}catch(const std::exception& ex){
				if(net->GetStatus() == NetClientStatusNotConnected){
					SPLog("Disconnected because of error:\n%s", ex.what());
					NetLog("Disconnected because of error:\n%s", ex.what());
					throw;
				}else{
					SPLog("Exception while processing network packets (ignored):\n%s", ex.what());
				}
			}
			
			hurtRingView->Update(dt);
			centerMessageView->Update(dt);
			mapView->Update(dt);
			largeMapView->Update(dt);
			
			UpdateAutoFocus(dt);
			
			if(world){
				UpdateWorld(dt);
			}else{
				renderer->SetFogColor(MakeVector3(0.f, 0.f, 0.f));
			}
			
			chatWindow->Update(dt);
			killfeedWindow->Update(dt);
			limbo->Update(dt);
			
			// CreateSceneDefinition also can be used for sounds
			SceneDefinition sceneDef = CreateSceneDefinition();
			lastSceneDef = sceneDef;
			
			// Update sounds
			try{
				audioDevice->Respatialize(sceneDef.viewOrigin,
										  sceneDef.viewAxis[2],
										  sceneDef.viewAxis[1]);
			}catch(const std::exception& ex){
				SPLog("Audio subsystem returned error (ignored):\n%s",
					  ex.what());
			}
			
			// render scene
			DrawScene();
			
			// draw 2d
			Draw2D();
			
			// draw scripted GUI
			scriptedUI->RunFrame(dt);
			if(scriptedUI->WantsClientToBeClosed())
				readyToClose = true;
			
			// Well done!
			renderer->FrameDone();
			renderer->Flip();
            
            // reset all "delayed actions" (in case we forget to reset these)
            hasDelayedReload = false;
			
			time += dt;
		}
예제 #9
0
		void Client::SetWorld(spades::client::World *w) {
			SPADES_MARK_FUNCTION();
			
			if(world.get() == w){
				return;
			}
			
			scriptedUI->CloseUI();
			
			RemoveAllCorpses();
			RemoveAllLocalEntities();
			
			lastHealth = 0;
			lastHurtTime = -100.f;
			hurtRingView->ClearAll();
			scoreboardVisible = false;
			flashlightOn = false;
			
			for(size_t i = 0; i < clientPlayers.size(); i++) {
				if(clientPlayers[i]) {
					clientPlayers[i]->Invalidate();
				}
			}
			clientPlayers.clear();
			
			if(world){
				world->SetListener(nullptr);
				renderer->SetGameMap(nullptr);
				audioDevice->SetGameMap(nullptr);
				world = nullptr;
				map = nullptr;
			}
			world.reset(w);
			if(world){
				SPLog("World set");
				
				// initialize player view objects
				clientPlayers.resize(world->GetNumPlayerSlots());
				for(size_t i = 0; i < world->GetNumPlayerSlots(); i++) {
					Player *p = world->GetPlayer(i);
					if(p){
						clientPlayers[i] = new ClientPlayer(p, this);
					}else{
						clientPlayers[i] = nullptr;
					}
				}
				
				world->SetListener(this);
				map = world->GetMap();
				renderer->SetGameMap(map);
				audioDevice->SetGameMap(map);
				NetLog("------ World Loaded ------");
			}else{
				
				SPLog("World removed");
				NetLog("------ World Unloaded ------");
			}
			
			limbo->SetSelectedTeam(2);
			limbo->SetSelectedWeapon(RIFLE_WEAPON);
			
			worldSubFrame = 0.f;
			worldSetTime = time;
			inGameLimbo = false;
		}
예제 #10
0
static int luasrc_NetLog (lua_State *L) {
  NetLog(luaL_checkint(L, 1), luaL_checkstring(L, 2));
  return 0;
}
예제 #11
0
		void Client::PlayerKilledPlayer(spades::client::Player *killer,
		                                spades::client::Player *victim, KillType kt) {
			// play hit sound
			if (kt == KillTypeWeapon || kt == KillTypeHeadshot) {
				// don't play on local: see BullethitPlayer
				if (victim != world->GetLocalPlayer()) {
					if (!IsMuted()) {
						Handle<IAudioChunk> c;
						switch (SampleRandomInt(0, 2)) {
							case 0:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh1.opus");
								break;
							case 1:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh2.opus");
								break;
							case 2:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh3.opus");
								break;
						}
						AudioParam param;
						param.volume = 4.f;
						audioDevice->Play(c, victim->GetEye(), param);
					}
				}
			}

			// The local player is dead; initialize the look-you-are-dead cam
			if (victim == world->GetLocalPlayer()) {
				followCameraState.enabled = false;

				Vector3 v = -victim->GetFront();
				followAndFreeCameraState.yaw = atan2(v.y, v.x);
				followAndFreeCameraState.pitch = 30.f * M_PI / 180.f;
			}

			// emit blood (also for local player)
			// FIXME: emiting blood for either
			// client-side or server-side hit?
			switch (kt) {
				case KillTypeGrenade:
				case KillTypeHeadshot:
				case KillTypeMelee:
				case KillTypeWeapon: Bleed(victim->GetEye()); break;
				default: break;
			}

			// create ragdoll corpse
			if (cg_ragdoll && victim->GetTeamId() < 2) {
				Corpse *corp;
				corp = new Corpse(renderer, map, victim);
				if (victim == world->GetLocalPlayer())
					lastMyCorpse = corp;
				if (killer != victim && kt != KillTypeGrenade) {
					Vector3 dir = victim->GetPosition() - killer->GetPosition();
					dir = dir.Normalize();
					if (kt == KillTypeMelee) {
						dir *= 6.f;
					} else {
						if (killer->GetWeapon()->GetWeaponType() == SMG_WEAPON) {
							dir *= 2.8f;
						} else if (killer->GetWeapon()->GetWeaponType() == SHOTGUN_WEAPON) {
							dir *= 4.5f;
						} else {
							dir *= 3.5f;
						}
					}
					corp->AddImpulse(dir);
				} else if (kt == KillTypeGrenade) {
					corp->AddImpulse(MakeVector3(0, 0, -4.f - SampleRandomFloat() * 4.f));
				}
				corp->AddImpulse(victim->GetVelocty() * 32.f);
				corpses.emplace_back(corp);

				if (corpses.size() > corpseHardLimit) {
					corpses.pop_front();
				} else if (corpses.size() > corpseSoftLimit) {
					RemoveInvisibleCorpses();
				}
			}

			// add chat message
			std::string s;
			s = ChatWindow::TeamColorMessage(killer->GetName(), killer->GetTeamId());

			std::string cause;
			bool isFriendlyFire = killer->GetTeamId() == victim->GetTeamId();
			if (killer == victim)
				isFriendlyFire = false;

			Weapon *w =
			  killer ? killer->GetWeapon() : nullptr; // only used in case of KillTypeWeapon
			switch (kt) {
				case KillTypeWeapon:
					switch (w ? w->GetWeaponType() : RIFLE_WEAPON) {
						case RIFLE_WEAPON: cause += _Tr("Client", "Rifle"); break;
						case SMG_WEAPON: cause += _Tr("Client", "SMG"); break;
						case SHOTGUN_WEAPON: cause += _Tr("Client", "Shotgun"); break;
					}
					break;
				case KillTypeFall:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Fall");
					break;
				case KillTypeMelee:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Melee");
					break;
				case KillTypeGrenade:
					cause += _Tr("Client", "Grenade");
					break;
				case KillTypeHeadshot:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Headshot");
					break;
				case KillTypeTeamChange:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Team Change");
					break;
				case KillTypeClassChange:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Weapon Change");
					break;
				default:
					cause += "???";
					break;
			}

			s += " [";
			if (isFriendlyFire)
				s += ChatWindow::ColoredMessage(cause, MsgColorFriendlyFire);
			else if (killer == world->GetLocalPlayer() || victim == world->GetLocalPlayer())
				s += ChatWindow::ColoredMessage(cause, MsgColorGray);
			else
				s += cause;
			s += "] ";

			if (killer != victim) {
				s += ChatWindow::TeamColorMessage(victim->GetName(), victim->GetTeamId());
			}

			killfeedWindow->AddMessage(s);

			// log to netlog
			if (killer != victim) {
				NetLog("%s (%s) [%s] %s (%s)", killer->GetName().c_str(),
				       world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str(),
				       victim->GetName().c_str(), world->GetTeam(victim->GetTeamId()).name.c_str());
			} else {
				NetLog("%s (%s) [%s]", killer->GetName().c_str(),
				       world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str());
			}

			// show big message if player is involved
			if (victim != killer) {
				Player *local = world->GetLocalPlayer();
				if (killer == local || victim == local) {
					std::string msg;
					if (killer == local) {
						if ((int)cg_centerMessage == 2)
							msg = _Tr("Client", "You have killed {0}", victim->GetName());
					} else {
						msg = _Tr("Client", "You were killed by {0}", killer->GetName());
					}
					centerMessageView->AddMessage(msg);
				}
			}
		}