2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <http://www.gnu.org/licenses/>.
8 /** @file logic_signals_cmd.cpp Commands for modifying logic signal programs. */
10 #include "logic_signals.h"
11 #include "core/bitmath_func.hpp"
12 #include "window_func.h"
13 #include "command_func.h"
15 #include "table/strings.h"
16 #include "company_func.h"
19 * The main command for editing a signal program.
20 * @param tile The tile which contains the edited signal.
21 * @param flags Internal command handler stuff.
22 * @param p1 Bitstuffed items
23 * - p1 = (bit 0-2) - The Track part of the signal program tile.
24 * - p1 = (bit 3-5) - Subcommand to execute.
25 * - p1 = (bit 6-7) - The value to set to the signal program.
26 * @param p2 Target SignalReference for linking of two signals
28 * @return the cost of this operation (which is free), or an error
30 CommandCost
CmdProgramLogicSignal(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char* text
)
32 const auto track
= Extract
<Track
, 0, 3>(p1
);
33 const uint32 sub_cmd
= GB(p1
, 3, 3);
34 const uint32 value
= GB(p1
, 6, 2);
36 // Start by checking tile ownership.
37 CommandCost ret
= CheckTileOwnership(tile
);
38 if (ret
.Failed()) return ret
;
40 SignalProgram
* program
= FindSignalProgram(tile
, track
);
43 if (flags
& DC_EXEC
) {
44 program
->own_default_state
= static_cast<SignalState
>(value
);
46 } else if (sub_cmd
== 2) {
47 if (flags
& DC_EXEC
) {
48 program
->trigger_state
= static_cast<SignalState
>(value
);
50 } else if (sub_cmd
== 3) {
51 if (flags
& DC_EXEC
) {
52 program
->signal_op
= static_cast<SignalOperator
>(value
);
54 } else if (sub_cmd
== 4) {
55 const TileIndex target_tile
= p2
;
56 const Track target_track
= SignalTrackFromTile(target_tile
);
58 if (tile
== target_tile
&& track
== target_track
) {
59 return CommandError(STR_ERROR_LINK_SIGNAL_TO_ITSELF
);
62 if (!IsPlainRailTile(target_tile
) || !HasSignalOnTrack(target_tile
, target_track
)) {
63 return CommandError(STR_ERROR_LINK_SIGNAL_NO_SIGNAL
);
66 if (CheckTileOwnership(target_tile
).Failed()) {
67 return CommandError(STR_ERROR_OWNED_BY
);
70 if (flags
& DC_EXEC
) {
71 program
->AddLink(target_tile
, target_track
);
73 } else if (sub_cmd
== 5) {
74 if (flags
& DC_EXEC
) {
75 program
->ClearAllLinks();
79 if (flags
& DC_EXEC
) {
80 // Invalidate any open windows if something was changed.
81 InvalidateWindowData(WC_SIGNAL_PROGRAM
, GetSignalReference(tile
, track
));
83 // Re-evaluate the signal state too.
84 program
->InputChanged(1);
87 // No cost, this fun is free :)