Skip to content

Commit 81f20a3

Browse files
committed
Add button to GM chat dialog to revert to scripted chat
Add a Script button to GM chat dialogs for entities with comms scripts or callbacks. When clicked, the button closes the GM chat and opens a standard chat channel from the player ship to the entity with no hailing delay. This either launches any configured scripted chat on the receiving entity or closes the channel.
1 parent 15571e2 commit 81f20a3

File tree

4 files changed

+81
-20
lines changed

4 files changed

+81
-20
lines changed

src/screens/gm/chatDialog.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
#include "screenComponents/radarView.h"
1010

11+
#include "gui/gui2_button.h"
1112
#include "gui/gui2_textentry.h"
1213
#include "gui/gui2_scrolltext.h"
1314

1415
GameMasterChatDialog::GameMasterChatDialog(GuiContainer* owner, GuiRadarView* radar, sp::ecs::Entity player)
15-
: GuiResizableDialog(owner, "", ""), player(player)
16+
: GuiResizableDialog(owner, "GM_CHAT_DIALOG", ""), player(player)
1617
{
1718
this->radar = radar;
1819

@@ -36,6 +37,32 @@ GameMasterChatDialog::GameMasterChatDialog(GuiContainer* owner, GuiRadarView* ra
3637
}
3738
);
3839

40+
auto status_bar = new GuiElement(contents, "GM_CHAT_STATUS_BAR");
41+
status_bar->setSize(GuiElement::GuiSizeMax, 25.0f)->setMargins(0.0f, 10.0f, 0.0f, 0.0f);
42+
status_bar->setAttribute("layout", "horizontalright");
43+
44+
use_comms_script = new GuiButton(status_bar, "GM_CHAT_SCRIPT", tr("Use comms script"),
45+
[this]()
46+
{
47+
if (this->player)
48+
{
49+
// If the player's comms target can successfully open a scripted
50+
// comms channel with the player, do so immediately and close this
51+
// GM chat.
52+
if (auto transmitter = this->player.getComponent<CommsTransmitter>())
53+
{
54+
if (CommsSystem::openChannel(this->player, transmitter->target))
55+
{
56+
this->disableComms(tr("chatGM", "Target - Using scripted comms"));
57+
transmitter->state = CommsTransmitter::State::ChannelOpen;
58+
this->onClose();
59+
}
60+
}
61+
}
62+
}
63+
);
64+
use_comms_script->setTextSize(20.0f)->setSize(135.0f, 25.0f)->setMargins(0.0f, 0.0f, 10.0f, 0.0f)->hide();
65+
3966
min_size.y += 100;
4067

4168
notification = false;
@@ -44,7 +71,6 @@ GameMasterChatDialog::GameMasterChatDialog(GuiContainer* owner, GuiRadarView* ra
4471
void GameMasterChatDialog::onDraw(sp::RenderTarget& renderer)
4572
{
4673
GuiResizableDialog::onDraw(renderer);
47-
4874
auto transmitter = player.getComponent<CommsTransmitter>();
4975
if (!player)
5076
{
@@ -87,26 +113,36 @@ void GameMasterChatDialog::onDraw(sp::RenderTarget& renderer)
87113
setTitle(tr("chatGM", "**{callsign} - Communicating as {target}**").format({{"callsign", callsign}, {"target", transmitter->target_name}}));
88114
else
89115
setTitle(tr("chatGM", "{callsign} - Communicating as {target}").format({{"callsign", callsign}, {"target", transmitter->target_name}}));
116+
90117
chat_text->enable();
91118
text_entry->enable();
119+
92120
if (chat_text->getText() != transmitter->incomming_message)
93121
{
94122
chat_text->setText(transmitter->incomming_message);
95123
notification = true;
96124
}
125+
97126
if (auto transform = transmitter->target.getComponent<sp::Transform>())
98127
renderer.drawLine(rect.center(), radar->worldToScreen(transform->getPosition()), glm::u8vec4(128, 255, 128, 128));
128+
129+
// Hide the use_comms_script button if the comms target can't use it.
130+
// TODO: Confirm this works if callback is present
131+
if (auto comms_receiver = transmitter->target.getComponent<CommsReceiver>())
132+
use_comms_script->setVisible(!comms_receiver->script.empty() || comms_receiver->callback);
133+
99134
break;
100135
}
136+
101137
if (auto transform = player.getComponent<sp::Transform>())
102138
renderer.drawLine(rect.center(), radar->worldToScreen(transform->getPosition()), glm::u8vec4(128, 255, 128, 128));
103139
}
104140

105141
void GameMasterChatDialog::disableComms(string title)
106142
{
107-
if (notification)
108-
title = "**" + title + "**";
143+
if (notification) title = "**" + title + "**";
109144
setTitle(title);
145+
use_comms_script->hide();
110146
chat_text->disable();
111147
text_entry->enable();
112148
}
@@ -115,9 +151,8 @@ void GameMasterChatDialog::onClose()
115151
{
116152
auto transmitter = player.getComponent<CommsTransmitter>();
117153
if (transmitter && (transmitter->state == CommsTransmitter::State::ChannelOpenGM || transmitter->state == CommsTransmitter::State::BeingHailedByGM))
118-
{
119154
CommsSystem::close(player);
120-
}
155+
121156
hide();
122157
minimize(false);
123158
}

src/screens/gm/chatDialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "gui/gui2_resizabledialog.h"
55
#include "ecs/entity.h"
66

7+
class GuiButton;
78
class GuiTextEntry;
89
class GuiScrollText;
910
class GuiRadarView;
@@ -23,6 +24,7 @@ class GameMasterChatDialog : public GuiResizableDialog
2324

2425
GuiTextEntry* text_entry;
2526
GuiScrollText* chat_text;
27+
GuiButton* use_comms_script;
2628

2729
void disableComms(string title);
2830

src/systems/comms.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,59 @@ static sp::ecs::Entity script_active_entity;
1717
void CommsSystem::update(float delta)
1818
{
1919
for(auto [entity, comms] : sp::ecs::Query<CommsTransmitter>()) {
20-
if (comms.open_delay > 0.0f)
21-
comms.open_delay -= delta;
22-
if (game_server) {
23-
if (comms.state == CommsTransmitter::State::OpeningChannel && comms.open_delay <= 0.0f) {
24-
if (!comms.target) {
20+
if (comms.open_delay > 0.0f) comms.open_delay -= delta;
21+
22+
if (game_server)
23+
{
24+
// If the channel opening delay is expired, determine whether to
25+
// initialize comms with the target.
26+
if (comms.state == CommsTransmitter::State::OpeningChannel && comms.open_delay <= 0.0f)
27+
{
28+
// Exit with a broken channel if the target no longer exists.
29+
if (!comms.target)
30+
{
2531
comms.state = CommsTransmitter::State::ChannelBroken;
26-
}else{
32+
return;
33+
}
34+
else
35+
{
2736
comms.script_replies.clear();
2837
comms.script_replies_dirty = true;
38+
39+
// If the other target is itself a comms transmitter, hail it.
2940
if (auto other_transmitter = comms.target.getComponent<CommsTransmitter>())
3041
{
3142
comms.open_delay = channel_open_time;
3243

33-
if (other_transmitter->state == CommsTransmitter::State::Inactive || other_transmitter->state == CommsTransmitter::State::ChannelFailed || other_transmitter->state == CommsTransmitter::State::ChannelBroken || other_transmitter->state == CommsTransmitter::State::ChannelClosed)
44+
if (other_transmitter->state == CommsTransmitter::State::Inactive
45+
|| other_transmitter->state == CommsTransmitter::State::ChannelFailed
46+
|| other_transmitter->state == CommsTransmitter::State::ChannelBroken
47+
|| other_transmitter->state == CommsTransmitter::State::ChannelClosed)
3448
{
3549
other_transmitter->state = CommsTransmitter::State::BeingHailed;
3650
other_transmitter->target = entity;
51+
3752
if (auto callsign = entity.getComponent<CallSign>())
3853
other_transmitter->target_name = callsign->callsign;
3954
else
4055
other_transmitter->target_name = "?";
4156
}
42-
}else if (gameGlobalInfo->intercept_all_comms_to_gm) {
57+
}
58+
// If all other comms are intercepted by the GM, open a chat
59+
// with the GM.
60+
else if (gameGlobalInfo->intercept_all_comms_to_gm && comms.state != CommsTransmitter::State::ChannelOpen)
4361
comms.state = CommsTransmitter::State::ChannelOpenGM;
44-
}else if (openChannel(entity, comms.target)) {
62+
// Otherwise, open a standard comms channel to the target.
63+
else if (openChannel(entity, comms.target))
4564
comms.state = CommsTransmitter::State::ChannelOpen;
46-
} else {
65+
else
4766
comms.state = CommsTransmitter::State::ChannelFailed;
48-
}
4967
}
5068
}
69+
5170
if (comms.state == CommsTransmitter::State::ChannelOpen || comms.state == CommsTransmitter::State::ChannelOpenPlayer)
5271
{
72+
// Exit with a broken channel if the target no longer exists.
5373
if (!comms.target)
5474
comms.state = CommsTransmitter::State::ChannelBroken;
5575
}
@@ -349,23 +369,28 @@ bool CommsSystem::openChannel(sp::ecs::Entity player, sp::ecs::Entity target)
349369
player.removeComponent<CommsTransmitterEnvironment>();
350370
transmitter->incomming_message = "???";
351371

372+
// comms_script (comms from file) is prioritized over
373+
// comms_callback (comms from inline function). Scenario authors must clear
374+
// comms_script on an entity with a script in order to use comms_callback.
352375
if (script_name != "")
353376
{
354377
auto& env = player.addComponent<CommsTransmitterEnvironment>();
355378
env.script_environment = std::make_unique<sp::script::Environment>(gameGlobalInfo->script_environment_base.get());
356379
setupSubEnvironment(*env.script_environment.get());
357-
// consider "player" deprecated, but keep it for a long time
380+
// Consider "player" deprecated, but keep it for a long time.
358381
env.script_environment->setGlobal("player", player);
359382
env.script_environment->setGlobal("comms_source", player);
360383
env.script_environment->setGlobal("comms_target", target);
361384
i18n::load("locale/" + script_name.replace(".lua", "." + PreferencesManager::get("language", "en") + ".po"));
362385
LuaConsole::checkResult(env.script_environment->runFile<void>(script_name));
363-
}else if (receiver->callback)
386+
}
387+
else if (receiver->callback)
364388
{
365389
receiver->callback.setGlobal("comms_source", player);
366390
receiver->callback.setGlobal("comms_target", transmitter->target);
367391
LuaConsole::checkResult(receiver->callback.call<void>(player, target));
368392
}
393+
369394
script_active_entity = {};
370395
return transmitter->incomming_message != "???";
371396
}

src/systems/comms.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,5 @@ class CommsSystem : public sp::ecs::System
2929
static int luaSetCommsMessage(lua_State* L);
3030
static int luaAddCommsReply(lua_State* L);
3131
static int luaCommsSwitchToGM(lua_State* L);
32-
private:
3332
static bool openChannel(sp::ecs::Entity player, sp::ecs::Entity target);
3433
};

0 commit comments

Comments
 (0)