summaryrefslogtreecommitdiffhomepage
path: root/Stars45/RadioTraffic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Stars45/RadioTraffic.cpp')
-rw-r--r--Stars45/RadioTraffic.cpp417
1 files changed, 417 insertions, 0 deletions
diff --git a/Stars45/RadioTraffic.cpp b/Stars45/RadioTraffic.cpp
new file mode 100644
index 0000000..9452d5d
--- /dev/null
+++ b/Stars45/RadioTraffic.cpp
@@ -0,0 +1,417 @@
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: Stars.exe
+ FILE: RadioTraffic.cpp
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Radio message handler class implementation
+*/
+
+#include "MemDebug.h"
+#include "RadioTraffic.h"
+#include "RadioMessage.h"
+#include "RadioView.h"
+#include "RadioVox.h"
+#include "Instruction.h"
+#include "Ship.h"
+#include "Contact.h"
+#include "Element.h"
+#include "Sim.h"
+#include "NetGame.h"
+#include "NetData.h"
+
+#include "Game.h"
+#include "Text.h"
+
+// +----------------------------------------------------------------------+
+
+RadioTraffic* RadioTraffic::radio_traffic = 0;
+
+// +----------------------------------------------------------------------+
+
+RadioTraffic::RadioTraffic()
+{
+ radio_traffic = this;
+}
+
+RadioTraffic::~RadioTraffic()
+{
+ traffic.destroy();
+}
+
+// +----------------------------------------------------------------------+
+
+void
+RadioTraffic::Initialize()
+{
+ if (!radio_traffic)
+ radio_traffic = new(__FILE__,__LINE__) RadioTraffic;
+}
+
+void
+RadioTraffic::Close()
+{
+ delete radio_traffic;
+ radio_traffic = 0;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+RadioTraffic::SendQuickMessage(Ship* ship, int action)
+{
+ if (!ship) return;
+
+ Element* elem = ship->GetElement();
+
+ if (elem) {
+ if (action >= RadioMessage::REQUEST_PICTURE) {
+ Ship* controller = ship->GetController();
+
+ if (controller && !ship->IsStarship()) {
+ RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(controller, ship, action);
+ Transmit(msg);
+ }
+ }
+ else if (action >= RadioMessage::SPLASH_1 && action <= RadioMessage::DISTRESS) {
+ RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage((Element*) 0, ship, action);
+ Transmit(msg);
+ }
+ else {
+ RadioMessage* msg = new(__FILE__,__LINE__) RadioMessage(elem, ship, action);
+
+ if (action == RadioMessage::ATTACK || action == RadioMessage::ESCORT)
+ msg->AddTarget(ship->GetTarget());
+
+ Transmit(msg);
+ }
+ }
+}
+
+// +----------------------------------------------------------------------+
+
+void
+RadioTraffic::Transmit(RadioMessage* msg)
+{
+ if (msg && radio_traffic) {
+ NetGame* net_game = NetGame::GetInstance();
+ if (net_game) {
+ NetCommMsg net_msg;
+ net_msg.SetRadioMessage(msg);
+ net_game->SendData(&net_msg);
+ }
+
+ radio_traffic->SendMessage(msg);
+ }
+}
+
+// +----------------------------------------------------------------------+
+
+void
+RadioTraffic::SendMessage(RadioMessage* msg)
+{
+ if (!msg) return;
+
+ Sim* sim = Sim::GetSim();
+ Ship* player = sim->GetPlayerShip();
+ int iff = 0;
+
+ if (player)
+ iff = player->GetIFF();
+
+ if (msg->DestinationShip()) {
+ traffic.append(msg);
+
+ if (msg->Channel() == 0 || msg->Channel() == iff)
+ DisplayMessage(msg);
+
+ if (!NetGame::IsNetGameClient())
+ msg->DestinationShip()->HandleRadioMessage(msg);
+ }
+
+ else if (msg->DestinationElem()) {
+ traffic.append(msg);
+
+ if (msg->Channel() == 0 || msg->Channel() == iff)
+ DisplayMessage(msg);
+
+ if (!NetGame::IsNetGameClient())
+ msg->DestinationElem()->HandleRadioMessage(msg);
+ }
+
+ else {
+ if (msg->Channel() == 0 || msg->Channel() == iff)
+ DisplayMessage(msg);
+
+ delete msg;
+ }
+}
+
+// +----------------------------------------------------------------------+
+
+Text
+RadioTraffic::TranslateVox(const char* phrase)
+{
+ Text vox = "vox.";
+ vox += phrase;
+ vox.toLower();
+ vox = Game::GetText(vox);
+
+ if (vox.contains("vox.")) // failed to translate
+ return Text(phrase); // return the original text
+
+ return vox;
+}
+
+void
+RadioTraffic::DisplayMessage(RadioMessage* msg)
+{
+ if (!msg) return;
+
+ char txt_buf[256]; txt_buf[0] = 0;
+ char msg_buf[128]; msg_buf[0] = 0;
+ char src_buf[64]; src_buf[0] = 0;
+ char dst_buf[64]; dst_buf[0] = 0;
+ char act_buf[64]; act_buf[0] = 0;
+ int vox_channel = 0;
+
+ Ship* dst_ship = msg->DestinationShip();
+ Element* dst_elem = msg->DestinationElem();
+
+ // BUILD SRC AND DST BUFFERS -------------------
+
+ if (msg->Sender()) {
+ const Ship* sender = msg->Sender();
+
+ // orders to self?
+ if (dst_elem && dst_elem->NumShips() == 1 && dst_elem->GetShip(1) == sender) {
+ if (msg->Action() >= RadioMessage::CALL_ENGAGING) {
+ sprintf_s(src_buf, "%s", sender->Name());
+
+ if (sender->IsStarship())
+ vox_channel = (sender->Identity()%3) + 5;
+ }
+ }
+
+ // orders to other ships:
+ else {
+ if (sender->IsStarship()) {
+ vox_channel = (sender->Identity()%3) + 5;
+ }
+ else {
+ vox_channel = sender->GetElementIndex();
+ }
+
+ if (msg->Action() >= RadioMessage::CALL_ENGAGING) {
+ sprintf_s(src_buf, "%s", sender->Name());
+ }
+ else {
+ sprintf_s(src_buf, "This is %s", sender->Name());
+
+ if (dst_ship) {
+ // internal announcement
+ if (dst_ship->GetElement() == sender->GetElement()) {
+ dst_elem = sender->GetElement();
+ int index = sender->GetElementIndex();
+
+ if (index > 1 && dst_elem) {
+ sprintf_s(dst_buf, "%s Leader", (const char*) dst_elem->Name());
+ sprintf_s(src_buf, "this is %s %d", (const char*) dst_elem->Name(), index);
+ }
+ else {
+ sprintf_s(src_buf, "this is %s leader", (const char*) dst_elem->Name());
+ }
+ }
+
+ else {
+ strcpy_s(dst_buf, (const char*) dst_ship->Name());
+ src_buf[0] = tolower(src_buf[0]);
+ }
+ }
+
+ else if (dst_elem) {
+ // flight
+ if (dst_elem->NumShips() > 1) {
+ sprintf_s(dst_buf, "%s Flight", (const char*) dst_elem->Name());
+
+ // internal announcement
+ if (sender->GetElement() == dst_elem) {
+ int index = sender->GetElementIndex();
+
+ if (index > 1) {
+ sprintf_s(dst_buf, "%s Leader", (const char*) dst_elem->Name());
+ sprintf_s(src_buf, "this is %s %d", (const char*) dst_elem->Name(), index);
+ }
+ else {
+ sprintf_s(src_buf, "this is %s leader", (const char*) dst_elem->Name());
+ }
+ }
+ }
+
+ // solo
+ else {
+ strcpy_s(dst_buf, (const char*) dst_elem->Name());
+ src_buf[0] = tolower(src_buf[0]);
+ }
+ }
+ }
+ }
+ }
+
+ // BUILD ACTION AND TARGET BUFFERS -------------------
+
+ SimObject* target = 0;
+
+ strcpy_s(act_buf, RadioMessage::ActionName(msg->Action()));
+
+ if (msg->TargetList().size() > 0)
+ target = msg->TargetList()[0];
+
+ if (msg->Action() == RadioMessage::ACK ||
+ msg->Action() == RadioMessage::NACK) {
+
+ if (dst_ship == msg->Sender()) {
+ src_buf[0] = 0;
+ dst_buf[0] = 0;
+
+ if (msg->Action() == RadioMessage::ACK)
+ sprintf_s(msg_buf, "%s.", TranslateVox("Acknowledged").data());
+ else
+ sprintf_s(msg_buf, "%s.", TranslateVox("Unable").data());
+ }
+ else if (msg->Sender()) {
+ dst_buf[0] = 0;
+
+ if (msg->Info().length()) {
+ sprintf_s(msg_buf, "%s. %s",
+ TranslateVox(act_buf).data(),
+ (const char*) msg->Info());
+ }
+ else {
+ sprintf_s(msg_buf, "%s.", TranslateVox(act_buf).data());
+ }
+ }
+ else {
+ if (msg->Info().length()) {
+ sprintf_s(msg_buf, "%s. %s",
+ TranslateVox(act_buf).data(),
+ (const char*) msg->Info());
+ }
+ else {
+ sprintf_s(msg_buf, "%s.", TranslateVox(act_buf).data());
+ }
+ }
+ }
+
+ else if (msg->Action() == RadioMessage::MOVE_PATROL) {
+ sprintf_s(msg_buf, "%s.", TranslateVox("Move patrol.").data());
+ }
+
+ else if (target && dst_ship && msg->Sender()) {
+ Contact* c = msg->Sender()->FindContact(target);
+
+ if (c && c->GetIFF(msg->Sender()) > 10) {
+ sprintf_s(msg_buf, "%s %s.", TranslateVox(act_buf).data(), TranslateVox("unknown contact").data());
+ }
+
+ else {
+ sprintf_s(msg_buf, "%s %s.",
+ TranslateVox(act_buf).data(),
+ target->Name());
+ }
+ }
+
+ else if (target) {
+ sprintf_s(msg_buf, "%s %s.",
+ TranslateVox(act_buf).data(),
+ target->Name());
+ }
+
+ else if (msg->Info().length()) {
+ sprintf_s(msg_buf, "%s %s",
+ TranslateVox(act_buf).data(),
+ (const char*) msg->Info());
+ }
+
+ else {
+ strcpy_s(msg_buf, TranslateVox(act_buf).data());
+ }
+
+ char last_char = msg_buf[strlen(msg_buf)-1];
+ if (last_char != '!' && last_char != '.' && last_char != '?')
+ strcat_s(msg_buf, ".");
+
+ // final format:
+ if (dst_buf[0] && src_buf[0]) {
+ sprintf_s(txt_buf, "%s %s. %s", TranslateVox(dst_buf).data(), TranslateVox(src_buf).data(), msg_buf);
+ txt_buf[0] = toupper(txt_buf[0]);
+ }
+
+ else if (src_buf[0]) {
+ sprintf_s(txt_buf, "%s. %s", TranslateVox(src_buf).data(), msg_buf);
+ txt_buf[0] = toupper(txt_buf[0]);
+ }
+
+ else if (dst_buf[0]) {
+ sprintf_s(txt_buf, "%s %s", TranslateVox(dst_buf).data(), msg_buf);
+ txt_buf[0] = toupper(txt_buf[0]);
+ }
+
+ else {
+ strcpy_s(txt_buf, msg_buf);
+ }
+
+ // vox:
+ const char* path[8] = { "1", "1", "2", "3", "4", "5", "6", "7" };
+
+ RadioVox* vox = new(__FILE__,__LINE__) RadioVox(vox_channel, path[vox_channel], txt_buf);
+
+ if (vox) {
+ vox->AddPhrase(dst_buf);
+ vox->AddPhrase(src_buf);
+ vox->AddPhrase(act_buf);
+
+ if (!vox->Start()) {
+ RadioView::Message(txt_buf);
+ delete vox;
+ }
+ }
+}
+
+// +----------------------------------------------------------------------+
+
+void
+RadioTraffic::DiscardMessages()
+{
+ if (radio_traffic)
+ radio_traffic->traffic.destroy();
+}