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 */