diff options
author | Niels Martin Hansen <nielsm@indvikleren.dk> | 2020-05-22 22:22:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-22 22:22:55 +0200 |
commit | 800ade77021b34adf8daa5ca5de0efaa8df24152 (patch) | |
tree | 7a2eb5c73c926476c81cd782bcb9b42c93bafdc4 /src/story.cpp | |
parent | c972a63c8cbee7fa8d6d5af2cbbecb8c75ee561a (diff) | |
download | openttd-800ade77021b34adf8daa5ca5de0efaa8df24152.tar.xz |
Feature: Push-buttons on storybook pages (#7896)
Allow more direct player-initiated interaction for Game Scripts, by letting the GS put push-buttons on storybook pages. These buttons can either trigger an immediate event, or require the player to first select a tile on the map, or a vehicle.
Additionally this reworks how the storybook pages are layouted and rendered, to allow for slightly more complex layouts, and maybe speeding drawing up a bit.
Diffstat (limited to 'src/story.cpp')
-rw-r--r-- | src/story.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/story.cpp b/src/story.cpp index 0d465fde8..e60c60a9f 100644 --- a/src/story.cpp +++ b/src/story.cpp @@ -21,6 +21,10 @@ #include "goal_base.h" #include "window_func.h" #include "gui.h" +#include "vehicle_base.h" +#include "game/game.hpp" +#include "script/api/script_story_page.hpp" +#include "script/api/script_event_types.hpp" #include "safeguards.h" @@ -47,6 +51,8 @@ INSTANTIATE_POOL_METHODS(StoryPage) */ static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text) { + StoryPageButtonData button_data{ reference }; + switch (type) { case SPET_TEXT: if (StrEmpty(text)) return false; @@ -60,6 +66,18 @@ static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElement /* Reject company specific goals on global pages */ if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false; break; + case SPET_BUTTON_PUSH: + if (!button_data.ValidateColour()) return false; + return true; + case SPET_BUTTON_TILE: + if (!button_data.ValidateColour()) return false; + if (!button_data.ValidateCursor()) return false; + return true; + case SPET_BUTTON_VEHICLE: + if (!button_data.ValidateColour()) return false; + if (!button_data.ValidateCursor()) return false; + if (!button_data.ValidateVehicleType()) return false; + return true; default: return false; } @@ -88,10 +106,94 @@ static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference case SPET_GOAL: pe.referenced_id = (GoalID)reference; break; + case SPET_BUTTON_PUSH: + case SPET_BUTTON_TILE: + case SPET_BUTTON_VEHICLE: + pe.text = stredup(text); + pe.referenced_id = reference; + break; default: NOT_REACHED(); } } +/** Set the button background colour. */ +void StoryPageButtonData::SetColour(Colours button_colour) +{ + assert(button_colour < COLOUR_END); + SB(this->referenced_id, 0, 8, button_colour); +} + +void StoryPageButtonData::SetFlags(StoryPageButtonFlags flags) +{ + SB(this->referenced_id, 24, 8, flags); +} + +/** Set the mouse cursor used while waiting for input for the button. */ +void StoryPageButtonData::SetCursor(StoryPageButtonCursor cursor) +{ + assert(cursor < SPBC_END); + SB(this->referenced_id, 8, 8, cursor); +} + +/** Set the type of vehicles that are accepted by the button */ +void StoryPageButtonData::SetVehicleType(VehicleType vehtype) +{ + assert(vehtype == VEH_INVALID || vehtype < VEH_COMPANY_END); + SB(this->referenced_id, 16, 8, vehtype); +} + +/** Get the button background colour. */ +Colours StoryPageButtonData::GetColour() const +{ + return Extract<Colours, 0, 8>(this->referenced_id); +} + +StoryPageButtonFlags StoryPageButtonData::GetFlags() const +{ + return (StoryPageButtonFlags)GB(this->referenced_id, 24, 8); +} + +/** Get the mouse cursor used while waiting for input for the button. */ +StoryPageButtonCursor StoryPageButtonData::GetCursor() const +{ + return Extract<StoryPageButtonCursor, 8, 8>(this->referenced_id); +} + +/** Get the type of vehicles that are accepted by the button */ +VehicleType StoryPageButtonData::GetVehicleType() const +{ + return (VehicleType)GB(this->referenced_id, 16, 8); +} + +/** Verify that the data stored a valid Colour value */ +bool StoryPageButtonData::ValidateColour() const +{ + return GB(this->referenced_id, 0, 8) < COLOUR_END; +} + +bool StoryPageButtonData::ValidateFlags() const +{ + byte flags = GB(this->referenced_id, 24, 8); + /* Don't allow float left and right together */ + if ((flags & SPBF_FLOAT_LEFT) && (flags & SPBF_FLOAT_RIGHT)) return false; + /* Don't allow undefined flags */ + if (flags & ~(SPBF_FLOAT_LEFT | SPBF_FLOAT_RIGHT)) return false; + return true; +} + +/** Verify that the data stores a valid StoryPageButtonCursor value */ +bool StoryPageButtonData::ValidateCursor() const +{ + return GB(this->referenced_id, 8, 8) < SPBC_END; +} + +/** Verity that the data stored a valid VehicleType value */ +bool StoryPageButtonData::ValidateVehicleType() const +{ + byte vehtype = GB(this->referenced_id, 16, 8); + return vehtype == VEH_INVALID || vehtype < VEH_COMPANY_END; +} + /** * Create a new story page. * @param tile unused. @@ -358,3 +460,44 @@ CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint3 return CommandCost(); } +/** + * Clicked/used a button on a story page. + * @param tile Tile selected, for tile selection buttons, otherwise unused. + * @param flags Type of operation. + * @param p1 Bit 0..15 = story page element id of button. + * @param p2 ID of selected item for buttons that select an item (e.g. vehicle), otherwise unused. + * @param text Unused. + * @return The cost of the operation, or an error. + */ +CommandCost CmdStoryPageButton(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16); + + if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR; + const StoryPageElement *const pe = StoryPageElement::Get(page_element_id); + + /* Check the player belongs to the company that owns the page. */ + const StoryPage *const sp = StoryPage::Get(pe->page); + if (sp->company != INVALID_COMPANY && sp->company != _current_company) return CMD_ERROR; + + switch (pe->type) { + case SPET_BUTTON_PUSH: + /* No validation required */ + if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageButtonClick(_current_company, pe->page, page_element_id)); + break; + case SPET_BUTTON_TILE: + if (!IsValidTile(tile)) return CMD_ERROR; + if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageTileSelect(_current_company, pe->page, page_element_id, tile)); + break; + case SPET_BUTTON_VEHICLE: + if (!Vehicle::IsValidID(p2)) return CMD_ERROR; + if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageVehicleSelect(_current_company, pe->page, page_element_id, (VehicleID)p2)); + break; + default: + /* Invalid page element type, not a button. */ + return CMD_ERROR; + } + + return CommandCost(); +} + |