1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #include "BannerSetStyleAction.h"
11 
12 #include "../Context.h"
13 #include "../management/Finance.h"
14 #include "../util/Util.h"
15 #include "../windows/Intent.h"
16 #include "../world/Banner.h"
17 #include "GameAction.h"
18 
BannerSetStyleAction(BannerSetStyleType type,uint8_t bannerIndex,uint8_t parameter)19 BannerSetStyleAction::BannerSetStyleAction(BannerSetStyleType type, uint8_t bannerIndex, uint8_t parameter)
20     : _type(type)
21     , _bannerIndex(bannerIndex)
22     , _parameter(parameter)
23 {
24 }
25 
AcceptParameters(GameActionParameterVisitor & visitor)26 void BannerSetStyleAction::AcceptParameters(GameActionParameterVisitor& visitor)
27 {
28     visitor.Visit("id", _bannerIndex);
29     visitor.Visit("type", _type);
30     visitor.Visit("parameter", _parameter);
31 }
32 
GetActionFlags() const33 uint16_t BannerSetStyleAction::GetActionFlags() const
34 {
35     return GameAction::GetActionFlags() | GameActions::Flags::AllowWhilePaused;
36 }
37 
Serialise(DataSerialiser & stream)38 void BannerSetStyleAction::Serialise(DataSerialiser& stream)
39 {
40     GameAction::Serialise(stream);
41 
42     stream << DS_TAG(_type) << DS_TAG(_bannerIndex) << DS_TAG(_parameter);
43 }
44 
Query() const45 GameActions::Result::Ptr BannerSetStyleAction::Query() const
46 {
47     auto res = MakeResult();
48 
49     auto banner = GetBanner(_bannerIndex);
50     if (banner == nullptr)
51     {
52         log_error("Invalid banner index: index = %u", _bannerIndex);
53         return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
54     }
55 
56     res->Expenditure = ExpenditureType::Landscaping;
57     auto location = banner->position.ToCoordsXY().ToTileCentre();
58     res->Position = { location, tile_element_height(location) };
59 
60     TileElement* tileElement = banner_get_tile_element(_bannerIndex);
61 
62     if (tileElement == nullptr)
63     {
64         log_error("Could not find banner index = %u", _bannerIndex);
65         return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
66     }
67 
68     switch (_type)
69     {
70         case BannerSetStyleType::PrimaryColour:
71             if (_parameter > 31)
72             {
73                 log_error("Invalid primary colour: colour = %u", _parameter);
74                 return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
75             }
76             break;
77 
78         case BannerSetStyleType::TextColour:
79             if (_parameter > 13)
80             {
81                 log_error("Invalid text colour: colour = %u", _parameter);
82                 return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
83             }
84             break;
85         case BannerSetStyleType::NoEntry:
86             if (tileElement->AsBanner() == nullptr)
87             {
88                 log_error("Tile element was not a banner.");
89                 return MakeResult(GameActions::Status::Unknown, STR_CANT_REPAINT_THIS, STR_NONE);
90             }
91             break;
92         default:
93             log_error("Invalid type: %u", _type);
94             return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
95     }
96     return res;
97 }
98 
Execute() const99 GameActions::Result::Ptr BannerSetStyleAction::Execute() const
100 {
101     auto res = MakeResult();
102 
103     auto banner = GetBanner(_bannerIndex);
104     if (banner == nullptr)
105     {
106         log_error("Invalid banner index: index = %u", _bannerIndex);
107         return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
108     }
109 
110     res->Expenditure = ExpenditureType::Landscaping;
111     auto location = banner->position.ToCoordsXY().ToTileCentre();
112     res->Position = { location, tile_element_height(location) };
113 
114     TileElement* tileElement = banner_get_tile_element(_bannerIndex);
115 
116     if (tileElement == nullptr)
117     {
118         log_error("Could not find banner index = %u", _bannerIndex);
119         return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
120     }
121 
122     switch (_type)
123     {
124         case BannerSetStyleType::PrimaryColour:
125             banner->colour = _parameter;
126             break;
127         case BannerSetStyleType::TextColour:
128             banner->text_colour = _parameter;
129             break;
130         case BannerSetStyleType::NoEntry:
131         {
132             BannerElement* bannerElement = tileElement->AsBanner();
133             if (bannerElement == nullptr)
134             {
135                 log_error("Tile element was not a banner.");
136                 return MakeResult(GameActions::Status::Unknown, STR_CANT_REPAINT_THIS, STR_NONE);
137             }
138 
139             banner->flags &= ~BANNER_FLAG_NO_ENTRY;
140             banner->flags |= (_parameter != 0) ? BANNER_FLAG_NO_ENTRY : 0;
141             uint8_t allowedEdges = 0xF;
142             if (banner->flags & BANNER_FLAG_NO_ENTRY)
143             {
144                 allowedEdges &= ~(1 << bannerElement->GetPosition());
145             }
146             bannerElement->SetAllowedEdges(allowedEdges);
147             break;
148         }
149         default:
150             log_error("Invalid type: %u", _type);
151             return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_REPAINT_THIS, STR_NONE);
152     }
153 
154     auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
155     intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex);
156     context_broadcast_intent(&intent);
157 
158     return res;
159 }
160