diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 266e4e577c..303954ecba 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -500,6 +500,8 @@ add_files(
textbuf_type.h
texteff.cpp
texteff.hpp
+ texteff_cmd.cpp
+ texteff_cmd.h
textfile_gui.cpp
textfile_gui.h
textfile_type.h
diff --git a/src/command.cpp b/src/command.cpp
index c11289902e..d9b82c7fff 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -46,6 +46,7 @@
#include "station_cmd.h"
#include "story_cmd.h"
#include "subsidy_cmd.h"
+#include "texteff_cmd.h"
#include "terraform_cmd.h"
#include "timetable_cmd.h"
#include "town_cmd.h"
diff --git a/src/command_type.h b/src/command_type.h
index e491677871..996d8acc42 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -372,6 +372,10 @@ enum Commands : uint8_t {
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, ///< update the score of a league table element
CMD_REMOVE_LEAGUE_TABLE_ELEMENT, ///< remove a league table element
+ CMD_CREATE_TEXT_EFFECT, ///< create a new text effect
+ CMD_UPDATE_TEXT_EFFECT, ///< update text effect
+ CMD_REMOVE_TEXT_EFFECT, ///< remove text effect
+
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
};
diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp
index c3495b788b..e23fa587a2 100644
--- a/src/network/network_command.cpp
+++ b/src/network/network_command.cpp
@@ -40,6 +40,7 @@
#include "../station_cmd.h"
#include "../story_cmd.h"
#include "../subsidy_cmd.h"
+#include "../texteff_cmd.h"
#include "../terraform_cmd.h"
#include "../timetable_cmd.h"
#include "../town_cmd.h"
diff --git a/src/script/api/CMakeLists.txt b/src/script/api/CMakeLists.txt
index 28fd71128a..650e7ff343 100644
--- a/src/script/api/CMakeLists.txt
+++ b/src/script/api/CMakeLists.txt
@@ -206,6 +206,7 @@ add_files(
script_subsidylist.hpp
script_testmode.hpp
script_text.hpp
+ script_text_effect.hpp
script_tile.hpp
script_tilelist.hpp
script_town.hpp
@@ -278,6 +279,7 @@ add_files(
script_subsidylist.cpp
script_testmode.cpp
script_text.cpp
+ script_text_effect.cpp
script_tile.cpp
script_tilelist.cpp
script_town.cpp
diff --git a/src/script/api/script_text_effect.cpp b/src/script/api/script_text_effect.cpp
new file mode 100644
index 0000000000..bda1ba4188
--- /dev/null
+++ b/src/script/api/script_text_effect.cpp
@@ -0,0 +1,63 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD 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, version 2.
+ * OpenTTD 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 OpenTTD. If not, see .
+ */
+
+/** @file script_text_effect.cpp Implementation of ScriptTextEffect with multiplayer support. */
+
+#include "../../stdafx.h"
+#include "script_text_effect.hpp"
+#include "script_error.hpp"
+#include "script_map.hpp"
+#include "../script_instance.hpp"
+#include "../../texteff.hpp"
+#include "../../strings_func.h"
+#include "../../tile_map.h"
+#include "../../command_func.h"
+#include "../../texteff_cmd.h"
+
+#include "../../safeguards.h"
+
+/* static */ TextEffectID ScriptTextEffect::CreateAtPosition(SQInteger x, SQInteger y, Text *text, ScriptTextEffectMode mode)
+{
+ ScriptObjectRef counter(text);
+
+ EnforceDeityMode(false);
+ EnforcePrecondition(false, text != nullptr);
+ EnforcePrecondition(false, !text->GetEncodedText().empty());
+ EnforcePrecondition(false, mode == TE_RISING || mode == TE_STATIC);
+
+ return ScriptObject::Command::Do(&ScriptInstance::DoCommandReturnTextEffectID, x, y, (TextEffectMode)mode, text->GetEncodedText());
+}
+
+/* static */ TextEffectID ScriptTextEffect::Create(TileIndex tile, Text *text, ScriptTextEffectMode mode)
+{
+ EnforcePrecondition(false, ScriptMap::IsValidTile(tile));
+
+ int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
+ int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
+
+ return CreateAtPosition(x, y, text, mode);
+}
+
+/* static */ bool ScriptTextEffect::Update(TextEffectID te_id, Text *text)
+{
+ ScriptObjectRef counter(text);
+
+ EnforceDeityMode(false);
+ EnforcePrecondition(false, te_id != INVALID_TE_ID);
+ EnforcePrecondition(false, text != nullptr);
+ EnforcePrecondition(false, !text->GetEncodedText().empty());
+
+ return ScriptObject::Command::Do(te_id, text->GetEncodedText());
+}
+
+/* static */ bool ScriptTextEffect::Remove(TextEffectID te_id)
+{
+ EnforceDeityMode(false);
+ EnforcePrecondition(false, te_id != INVALID_TE_ID);
+
+ return ScriptObject::Command::Do(te_id);
+}
\ No newline at end of file
diff --git a/src/script/api/script_text_effect.hpp b/src/script/api/script_text_effect.hpp
new file mode 100644
index 0000000000..0e7a3e7ca7
--- /dev/null
+++ b/src/script/api/script_text_effect.hpp
@@ -0,0 +1,66 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD 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, version 2.
+ * OpenTTD 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 OpenTTD. If not, see .
+ */
+
+/** @file script_text_effect.hpp Everything to display animated text in the game world. */
+
+#ifndef SCRIPT_TEXT_EFFECT_HPP
+#define SCRIPT_TEXT_EFFECT_HPP
+
+#include "script_object.hpp"
+#include "script_text.hpp"
+#include "../../texteff.hpp"
+
+/**
+ * Class that handles text effect display in the game world.
+ * @api game
+ */
+class ScriptTextEffect : public ScriptObject {
+public:
+ /**
+ * Text effect animation modes.
+ */
+ enum ScriptTextEffectMode {
+ TE_RISING = ::TE_RISING, ///< Text slowly rises upwards
+ TE_STATIC = ::TE_STATIC, ///< Text stays in place
+ };
+
+ /**
+ * Create animated text at a tile location.
+ * @param tile The tile where to show the text.
+ * @param text The text to display.
+ * @param mode The animation mode to use.
+ * @return True if the text effect was created successfully.
+ */
+ static TextEffectID Create(TileIndex tile, Text *text, ScriptTextEffectMode mode);
+
+ /**
+ * Create animated text at the specified location.
+ * @param x X coordinate in the game world.
+ * @param y Y coordinate in the game world.
+ * @param text The text to display.
+ * @param mode The animation mode to use.
+ * @return True if the text effect was created successfully.
+ */
+ static TextEffectID CreateAtPosition(SQInteger x, SQInteger y, Text *text, ScriptTextEffectMode mode);
+
+ /**
+ * Update animated text
+ * @param te_id Text effect ID.
+ * @param text The text to update
+ * @return True if the text effect was updated successfully
+ */
+ static bool Update(TextEffectID te_id, Text *text);
+
+ /**
+ * Update animated text
+ * @param te_id Text effect ID.
+ * @return True if the text effect was removed successfully
+ */
+ static bool Remove(TextEffectID te_id);
+};
+
+#endif /* SCRIPT_TEXT_EFFECT_HPP */
diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp
index 58ba727b62..43b2ec308c 100644
--- a/src/script/script_instance.cpp
+++ b/src/script/script_instance.cpp
@@ -29,6 +29,7 @@
#include "../fileio_func.h"
#include "../league_type.h"
#include "../misc/endian_buffer.hpp"
+#include "../texteff.hpp"
#include "../safeguards.h"
@@ -315,6 +316,10 @@ void ScriptInstance::CollectGarbage()
instance.engine->InsertResult(EndianBufferReader::ToValue(ScriptObject::GetLastCommandResData()));
}
+/* static */ void ScriptInstance::DoCommandReturnTextEffectID(ScriptInstance *instance)
+{
+ instance->engine->InsertResult(EndianBufferReader::ToValue(ScriptObject::GetLastCommandResData()));
+}
ScriptStorage *ScriptInstance::GetStorage()
{
diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp
index 247d89363a..984722a466 100644
--- a/src/script/script_instance.hpp
+++ b/src/script/script_instance.hpp
@@ -143,6 +143,11 @@ public:
*/
static void DoCommandReturnLeagueTableElementID(ScriptInstance &instance);
+ /**
+ * Return a TextEffectID reply for a DoCommand.
+ */
+ static void DoCommandReturnTextEffectID(ScriptInstance *instance);
+
/**
* Get the controller attached to the instance.
*/
diff --git a/src/texteff_cmd.cpp b/src/texteff_cmd.cpp
new file mode 100644
index 0000000000..c4f2f20e0b
--- /dev/null
+++ b/src/texteff_cmd.cpp
@@ -0,0 +1,75 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD 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, version 2.
+ * OpenTTD 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 OpenTTD. If not, see .
+ */
+
+/** @file texteff_cmd.cpp Command handling for text effects */
+
+#include "stdafx.h"
+#include "command_func.h"
+#include "texteff.hpp"
+#include "strings_func.h"
+#include "tile_map.h"
+#include "texteff_cmd.h"
+
+#include "table/strings.h"
+
+#include "safeguards.h"
+#include "landscape.h"
+
+/**
+ * Show a text effect at the specified location.
+ * @param flags operation to perform
+ * @param x X coordinate in the game
+ * @param y Y coordinate in the game
+ * @param mode The animation mode to use
+ * @param text The text to display
+ * @return the cost of this operation or an error
+ */
+std::tuple CmdCreateTextEffect(DoCommandFlags flags, int32_t x, int32_t y, TextEffectMode mode, const EncodedString &text)
+{
+ if (text.empty()) return { CMD_ERROR, INVALID_TE_ID };
+ if (mode != TE_RISING && mode != TE_STATIC) return { CMD_ERROR, INVALID_TE_ID };
+
+ if (flags.Test(DoCommandFlag::Execute)) {
+ Point pt = RemapCoords2(x, y);
+ EncodedString encoded_text = text;
+ TextEffectID te_id;
+
+ if (mode == TE_RISING) {
+ te_id = AddTextEffect(std::move(encoded_text), pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
+ } else {
+ te_id = AddTextEffect(std::move(encoded_text), pt.x, pt.y, 0, TE_STATIC);
+ }
+
+ return { CommandCost(), te_id };
+ }
+
+ return { CommandCost(), INVALID_TE_ID };
+}
+
+CommandCost CmdUpdateTextEffect(DoCommandFlags flags, TextEffectID te_id, const EncodedString &text)
+{
+ if (te_id == INVALID_TE_ID) return CMD_ERROR;
+ if (text.empty()) return CMD_ERROR;
+
+ if (flags.Test(DoCommandFlag::Execute)) {
+ EncodedString encoded_text = text;
+ UpdateTextEffect(te_id, std::move(encoded_text));
+ }
+
+ return CommandCost();
+}
+
+CommandCost CmdRemoveTextEffect(DoCommandFlags flags, TextEffectID te_id)
+{
+ if (te_id == INVALID_TE_ID) return CMD_ERROR;
+
+ if (flags.Test(DoCommandFlag::Execute)) {
+ RemoveTextEffect(te_id);
+ }
+
+ return CommandCost();
+}
diff --git a/src/texteff_cmd.h b/src/texteff_cmd.h
new file mode 100644
index 0000000000..788b667efa
--- /dev/null
+++ b/src/texteff_cmd.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD 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, version 2.
+ * OpenTTD 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 OpenTTD. If not, see .
+ */
+
+/** @file texteff_cmd.h Command declarations for text effects */
+
+#ifndef TEXTEFF_CMD_H
+#define TEXTEFF_CMD_H
+
+#include "command_type.h"
+#include "texteff.hpp"
+
+std::tuple CmdCreateTextEffect(DoCommandFlags flags, int32_t x, int32_t y, TextEffectMode mode, const EncodedString &text);
+CommandCost CmdUpdateTextEffect(DoCommandFlags flags, TextEffectID te_id, const EncodedString &text);
+CommandCost CmdRemoveTextEffect(DoCommandFlags flags, TextEffectID te_id);
+
+DEF_CMD_TRAIT(CMD_CREATE_TEXT_EFFECT, CmdCreateTextEffect, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT)
+DEF_CMD_TRAIT(CMD_UPDATE_TEXT_EFFECT, CmdUpdateTextEffect, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT)
+DEF_CMD_TRAIT(CMD_REMOVE_TEXT_EFFECT, CmdRemoveTextEffect, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT)
+
+#endif /* TEXTEFF_CMD_H */