Merge branch 'master' into 1.11
This commit is contained in:
1428
projects/openttd_vs140.vcxproj
Normal file
1428
projects/openttd_vs140.vcxproj
Normal file
File diff suppressed because it is too large
Load Diff
3281
projects/openttd_vs140.vcxproj.filters
Normal file
3281
projects/openttd_vs140.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
1428
projects/openttd_vs141.vcxproj
Normal file
1428
projects/openttd_vs141.vcxproj
Normal file
File diff suppressed because it is too large
Load Diff
3281
projects/openttd_vs141.vcxproj.filters
Normal file
3281
projects/openttd_vs141.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
1428
projects/openttd_vs142.vcxproj
Normal file
1428
projects/openttd_vs142.vcxproj
Normal file
File diff suppressed because it is too large
Load Diff
3281
projects/openttd_vs142.vcxproj.filters
Normal file
3281
projects/openttd_vs142.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,8 @@ void DrawAircraftDetails(const Aircraft *v, int left, int right, int y)
|
||||
SetDParam(0, u->engine_type);
|
||||
SetDParam(1, u->build_year);
|
||||
SetDParam(2, u->value);
|
||||
DrawString(left, right, y, STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
if (_settings_client.gui.newgrf_developer_tools) SetDParam(3, v->index); // CM
|
||||
DrawString(left, right, y, _settings_client.gui.newgrf_developer_tools ? STR_CM_VEHICLE_INFO_BUILT_VALUE_WITH_ID : STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
|
||||
SetDParam(0, u->cargo_type);
|
||||
SetDParam(1, u->cargo_cap);
|
||||
|
||||
@@ -10,8 +10,14 @@
|
||||
#include "../fileio_type.h"
|
||||
#include "../map_type.h"
|
||||
#include "../map_func.h"
|
||||
#include "../strings_func.h"
|
||||
#include "../town.h"
|
||||
#include "../tree_map.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, byte **map);
|
||||
@@ -108,4 +114,87 @@ bool ConTreeMap(byte argc, char *argv[]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void (*UpdateTownGrowthRate)(Town *t);
|
||||
|
||||
bool ConResetTownGrowth(byte argc, char *argv[]) {
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Resets growth to normal for all towns.");
|
||||
IConsoleHelp("Usage: 'cmresettowngrowth'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc > 1) return false;
|
||||
|
||||
for (Town *town : Town::Iterate()) {
|
||||
ClrBit(town->flags, TOWN_CUSTOM_GROWTH);
|
||||
UpdateTownGrowthRate(town);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct FakeCommand {
|
||||
Date date;
|
||||
DateFract date_fract;
|
||||
uint company_id;
|
||||
uint cmd;
|
||||
TileIndex tile;
|
||||
uint32 p1, p2;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
static std::queue<FakeCommand> _fake_commands;
|
||||
|
||||
void ExecuteFakeCommands(Date date, DateFract date_fract) {
|
||||
auto backup_company = _current_company;
|
||||
while (!_fake_commands.empty() && _fake_commands.front().date <= date && _fake_commands.front().date_fract <= date_fract) {
|
||||
auto &x = _fake_commands.front();
|
||||
if (x.date < date || x.date_fract < date_fract) IConsolePrintF(CC_WARNING,
|
||||
"Queued command is earlier than execution date: %d/%hu vs %d/%hu",
|
||||
x.date, x.date_fract, date, date_fract);
|
||||
fprintf(stderr, "Executing command: company=%u cmd=%u tile=%u p1=%u p2=%u text=%s ... ", x.company_id, x.cmd, x.tile, x.p1, x.p2, x.text.c_str());
|
||||
_current_company = (CompanyID)x.company_id;
|
||||
auto res = DoCommandPInternal(x.tile, x.p1, x.p2, x.cmd | CMD_NETWORK_COMMAND, nullptr, x.text.c_str(), false, false);
|
||||
if (res.Failed()) {
|
||||
if (res.GetErrorMessage() != INVALID_STRING_ID) {
|
||||
char buf[DRAW_STRING_BUFFER];
|
||||
GetString(buf, res.GetErrorMessage(), lastof(buf));
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
} else {
|
||||
fprintf(stderr, "FAIL\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
_fake_commands.pop();
|
||||
}
|
||||
_current_company = backup_company;
|
||||
}
|
||||
|
||||
bool ConLoadCommands(byte argc, char *argv[]) {
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Loads a file with command queue to execute");
|
||||
IConsoleHelp("Usage: 'cmloadcommands <file>'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc != 2) return false;
|
||||
|
||||
std::queue<FakeCommand>().swap(_fake_commands); // clear queue
|
||||
|
||||
std::ifstream file(argv[1], std::ios::in);
|
||||
std::string str;
|
||||
while(std::getline(file, str))
|
||||
{
|
||||
std::istringstream ss(str);
|
||||
FakeCommand cmd;
|
||||
ss >> cmd.date >> cmd.date_fract >> cmd.company_id >> cmd.cmd >> cmd.p1 >> cmd.p2 >> cmd.tile;
|
||||
std::string s;
|
||||
ss.get();
|
||||
std::getline(ss, cmd.text);
|
||||
// fprintf(stderr, "PARSED: company=%u cmd=%u tile=%u p1=%u p2=%u text=%s\n", cmd.company_id, cmd.cmd, cmd.tile, cmd.p1, cmd.p2, cmd.text.c_str());
|
||||
_fake_commands.push(cmd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#ifndef CM_CONSOLE_CMDS_HPP
|
||||
#define CM_CONSOLE_CMDS_HPP
|
||||
|
||||
#include "../date_type.h"
|
||||
|
||||
namespace citymania {
|
||||
|
||||
bool ConStep(byte argc, char *argv[]);
|
||||
bool ConExport(byte argc, char *argv[]);
|
||||
bool ConTreeMap(byte argc, char *argv[]);
|
||||
bool ConResetTownGrowth(byte argc, char *argv[]);
|
||||
bool ConLoadCommands(byte argc, char *argv[]);
|
||||
void ExecuteFakeCommands(Date date, DateFract date_fract);
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "cm_highlight.hpp"
|
||||
|
||||
// #include "cm_blueprint.hpp"
|
||||
#include "cm_main.hpp"
|
||||
#include "cm_station_gui.hpp"
|
||||
#include "cm_zoning.hpp"
|
||||
|
||||
#include "../core/math_func.hpp"
|
||||
#include "../table/bridge_land.h"
|
||||
#include "../command_func.h"
|
||||
#include "../house.h"
|
||||
#include "../industry.h"
|
||||
#include "../landscape.h"
|
||||
#include "../newgrf_railtype.h"
|
||||
#include "../newgrf_station.h"
|
||||
#include "../town.h"
|
||||
#include "../town_kdtree.h"
|
||||
#include "../tilearea_type.h"
|
||||
#include "../tilehighlight_type.h"
|
||||
#include "../tilehighlight_func.h"
|
||||
#include "../viewport_func.h"
|
||||
#include "../table/track_land.h"
|
||||
|
||||
@@ -36,6 +41,17 @@ extern RailType _cur_railtype;
|
||||
RoadBits FindRailsToConnect(TileIndex tile);
|
||||
extern DiagDirection _build_depot_direction; ///< Currently selected depot direction
|
||||
extern uint32 _realtime_tick;
|
||||
extern void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec);
|
||||
|
||||
struct RailStationGUISettings {
|
||||
Axis orientation; ///< Currently selected rail station orientation
|
||||
|
||||
bool newstations; ///< Are custom station definitions available?
|
||||
StationClassID station_class; ///< Currently selected custom station class (if newstations is \c true )
|
||||
byte station_type; ///< %Station type within the currently selected custom station class (if newstations is \c true )
|
||||
byte station_count; ///< Number of custom stations (if newstations is \c true )
|
||||
};
|
||||
extern RailStationGUISettings _railstation; ///< Settings of the station builder GUI
|
||||
|
||||
|
||||
namespace citymania {
|
||||
@@ -71,27 +87,58 @@ const byte _tileh_to_sprite[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18, 0,
|
||||
};
|
||||
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_depot(DiagDirection ddir) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_DEPOT);
|
||||
oh.u.depot.ddir = ddir;
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_depot(SpriteID palette, DiagDirection ddir) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_DEPOT, palette);
|
||||
oh.u.rail.depot.ddir = ddir;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail(Track track) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_TRACK);
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_track(SpriteID palette, Track track) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_TRACK, palette);
|
||||
oh.u.rail.track = track;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_station(SpriteID palette, Axis axis, byte section) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_STATION, palette);
|
||||
oh.u.rail.station.axis = axis;
|
||||
oh.u.rail.station.section = section;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_signal(SpriteID palette, uint pos, SignalType type, SignalVariant variant) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_SIGNAL, palette);
|
||||
oh.u.rail.signal.pos = pos;
|
||||
oh.u.rail.signal.type = type;
|
||||
oh.u.rail.signal.variant = variant;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_bridge_head(SpriteID palette, DiagDirection ddir, BridgeType type) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_BRIDGE_HEAD, palette);
|
||||
oh.u.rail.bridge_head.ddir = ddir;
|
||||
oh.u.rail.bridge_head.type = type;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectTileHighlight ObjectTileHighlight::make_rail_tunnel_head(SpriteID palette, DiagDirection ddir) {
|
||||
auto oh = ObjectTileHighlight(Type::RAIL_TUNNEL_HEAD, palette);
|
||||
oh.u.rail.tunnel_head.ddir = ddir;
|
||||
return oh;
|
||||
}
|
||||
|
||||
bool ObjectHighlight::operator==(const ObjectHighlight& oh) {
|
||||
if (this->type != oh.type) return false;
|
||||
switch (this->type) {
|
||||
case Type::RAIL_DEPOT: return this->u.depot.tile == oh.u.depot.tile && this->u.depot.ddir == oh.u.depot.ddir;
|
||||
default: return true;
|
||||
}
|
||||
return true;
|
||||
return (this->tile == oh.tile
|
||||
&& this->end_tile == oh.end_tile
|
||||
&& this->axis == oh.axis
|
||||
&& this->ddir == oh.ddir
|
||||
&& this->blueprint == oh.blueprint);
|
||||
// switch (this->type) {
|
||||
// case Type::RAIL_DEPOT: return this->tile == oh.tile && this->ddir == oh.ddir;
|
||||
// default: return true;
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
|
||||
bool ObjectHighlight::operator!=(const ObjectHighlight& oh) {
|
||||
@@ -99,13 +146,28 @@ bool ObjectHighlight::operator!=(const ObjectHighlight& oh) {
|
||||
}
|
||||
|
||||
|
||||
ObjectHighlight ObjectHighlight::make_depot(TileIndex tile, DiagDirection ddir) {
|
||||
auto oh = ObjectHighlight(ObjectHighlight::Type::RAIL_DEPOT);
|
||||
oh.u.depot.tile = tile;
|
||||
oh.u.depot.ddir = ddir;
|
||||
ObjectHighlight ObjectHighlight::make_rail_depot(TileIndex tile, DiagDirection ddir) {
|
||||
auto oh = ObjectHighlight{ObjectHighlight::Type::RAIL_DEPOT};
|
||||
oh.tile = tile;
|
||||
oh.ddir = ddir;
|
||||
return oh;
|
||||
}
|
||||
|
||||
ObjectHighlight ObjectHighlight::make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis) {
|
||||
auto oh = ObjectHighlight{ObjectHighlight::Type::RAIL_STATION};
|
||||
oh.tile = start_tile;
|
||||
oh.end_tile = end_tile;
|
||||
oh.axis = axis;
|
||||
return oh;
|
||||
}
|
||||
|
||||
// ObjectHighlight ObjectHighlight::make_blueprint(TileIndex tile, sp<Blueprint> blueprint) {
|
||||
// auto oh = ObjectHighlight{ObjectHighlight::Type::BLUEPRINT};
|
||||
// oh.tile = tile;
|
||||
// oh.blueprint = blueprint;
|
||||
// return oh;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Try to add an additional rail-track at the entrance of a depot
|
||||
* @param tile Tile to use for adding the rail-track
|
||||
@@ -118,7 +180,7 @@ void ObjectHighlight::PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Tra
|
||||
if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return;
|
||||
if ((GetTrackBits(tile) & DiagdirReachesTracks(dir)) == 0) return;
|
||||
|
||||
this->tiles.insert(std::make_pair(tile, ObjectTileHighlight::make_rail(track)));
|
||||
this->tiles.insert(std::make_pair(tile, ObjectTileHighlight::make_rail_track(PALETTE_TINT_WHITE, track)));
|
||||
}
|
||||
|
||||
/** Additional pieces of track to add at the entrance of a depot. */
|
||||
@@ -135,22 +197,84 @@ static const DiagDirection _place_depot_extra_dir[12] = {
|
||||
DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_NW, DIAGDIR_NE,
|
||||
};
|
||||
|
||||
static bool CanBuild(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd) {
|
||||
return DoCommandPInternal(
|
||||
tile,
|
||||
p1,
|
||||
p2,
|
||||
cmd,
|
||||
nullptr, // callback
|
||||
nullptr, // text
|
||||
true, // my_cmd
|
||||
true // estimate_only
|
||||
).Succeeded();
|
||||
}
|
||||
|
||||
void ObjectHighlight::UpdateTiles() {
|
||||
this->tiles.clear();
|
||||
switch (this->type) {
|
||||
case Type::NONE:
|
||||
break;
|
||||
|
||||
case Type::RAIL_DEPOT: {
|
||||
auto dir = this->u.depot.ddir;
|
||||
this->tiles.insert(std::make_pair(this->u.depot.tile, ObjectTileHighlight::make_depot(dir)));
|
||||
auto tile = this->u.depot.tile + TileOffsByDiagDir(dir);
|
||||
auto dir = this->ddir;
|
||||
|
||||
auto palette = (CanBuild(
|
||||
this->tile,
|
||||
_cur_railtype,
|
||||
dir,
|
||||
CMD_BUILD_TRAIN_DEPOT
|
||||
) ? PALETTE_TINT_WHITE : PALETTE_TINT_RED_DEEP);
|
||||
|
||||
this->tiles.insert(std::make_pair(this->tile, ObjectTileHighlight::make_rail_depot(palette, dir)));
|
||||
auto tile = this->tile + TileOffsByDiagDir(dir);
|
||||
if (IsTileType(tile, MP_RAILWAY) && IsCompatibleRail(GetRailType(tile), _cur_railtype)) {
|
||||
PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir], _place_depot_extra_track[dir]);
|
||||
PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir + 4], _place_depot_extra_track[dir + 4]);
|
||||
PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir + 8], _place_depot_extra_track[dir + 8]);
|
||||
this->PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir], _place_depot_extra_track[dir]);
|
||||
this->PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir + 4], _place_depot_extra_track[dir + 4]);
|
||||
this->PlaceExtraDepotRail(tile, _place_depot_extra_dir[dir + 8], _place_depot_extra_track[dir + 8]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case Type::RAIL_STATION: {
|
||||
auto ta = OrthogonalTileArea(this->tile, this->end_tile);
|
||||
auto numtracks = ta.w;
|
||||
auto plat_len = ta.h;
|
||||
if (this->axis == AXIS_X) Swap(numtracks, plat_len);
|
||||
|
||||
auto palette = (CanBuild(
|
||||
this->tile,
|
||||
_cur_railtype
|
||||
| (this->axis << 6)
|
||||
| ((uint32)numtracks << 8)
|
||||
| ((uint32)plat_len << 16),
|
||||
NEW_STATION << 16,
|
||||
CMD_BUILD_RAIL_STATION
|
||||
) ? PALETTE_TINT_WHITE : PALETTE_TINT_RED_DEEP);
|
||||
|
||||
auto layout_ptr = AllocaM(byte, (int)numtracks * plat_len);
|
||||
GetStationLayout(layout_ptr, numtracks, plat_len, nullptr); // TODO statspec
|
||||
|
||||
auto tile_delta = (this->axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
||||
TileIndex tile_track = this->tile;
|
||||
do {
|
||||
TileIndex tile = tile_track;
|
||||
int w = plat_len;
|
||||
do {
|
||||
byte layout = *layout_ptr++;
|
||||
this->tiles.insert(std::make_pair(tile, ObjectTileHighlight::make_rail_station(palette, this->axis, layout & ~1)));
|
||||
tile += tile_delta;
|
||||
} while (--w);
|
||||
tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
|
||||
} while (--numtracks);
|
||||
|
||||
break;
|
||||
}
|
||||
// case Type::BLUEPRINT:
|
||||
// if (this->blueprint && this->tile != INVALID_TILE)
|
||||
// this->tiles = this->blueprint->GetTiles(this->tile);
|
||||
// break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +286,43 @@ void ObjectHighlight::MarkDirty() {
|
||||
}
|
||||
|
||||
|
||||
void DrawTrainDepotSprite(const TileInfo *ti, RailType railtype, DiagDirection ddir)
|
||||
SpriteID GetTintBySelectionColour(SpriteID colour, bool deep=false) {
|
||||
switch(colour) {
|
||||
case SPR_PALETTE_ZONING_RED: return (deep ? PALETTE_TINT_RED_DEEP : PALETTE_TINT_RED);
|
||||
case SPR_PALETTE_ZONING_ORANGE: return (deep ? PALETTE_TINT_ORANGE_DEEP : PALETTE_TINT_ORANGE);
|
||||
case SPR_PALETTE_ZONING_GREEN: return (deep ? PALETTE_TINT_GREEN_DEEP : PALETTE_TINT_GREEN);
|
||||
case SPR_PALETTE_ZONING_LIGHT_BLUE: return (deep ? PALETTE_TINT_CYAN_DEEP : PALETTE_TINT_CYAN);
|
||||
case SPR_PALETTE_ZONING_YELLOW: return PALETTE_TINT_YELLOW;
|
||||
// case SPR_PALETTE_ZONING__: return PALETTE_TINT_YELLOW_WHITE;
|
||||
case SPR_PALETTE_ZONING_WHITE: return PALETTE_TINT_WHITE;
|
||||
default: return PAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
SpriteID GetSelectionColourByTint(SpriteID colour) {
|
||||
switch(colour) {
|
||||
case PALETTE_TINT_RED_DEEP:
|
||||
case PALETTE_TINT_RED:
|
||||
return SPR_PALETTE_ZONING_RED;
|
||||
case PALETTE_TINT_ORANGE_DEEP:
|
||||
case PALETTE_TINT_ORANGE:
|
||||
return SPR_PALETTE_ZONING_ORANGE;
|
||||
case PALETTE_TINT_GREEN_DEEP:
|
||||
case PALETTE_TINT_GREEN:
|
||||
return SPR_PALETTE_ZONING_GREEN;
|
||||
case PALETTE_TINT_CYAN_DEEP:
|
||||
case PALETTE_TINT_CYAN:
|
||||
return SPR_PALETTE_ZONING_LIGHT_BLUE;
|
||||
case PALETTE_TINT_YELLOW:
|
||||
return SPR_PALETTE_ZONING_YELLOW;
|
||||
// returnase SPR_PALETTE_ZONING__: return PALETTE_TINT_YELLOW_WHITE;
|
||||
case PALETTE_TINT_WHITE:
|
||||
return SPR_PALETTE_ZONING_WHITE;
|
||||
default: return PAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTrainDepotSprite(SpriteID palette, const TileInfo *ti, RailType railtype, DiagDirection ddir)
|
||||
{
|
||||
const DrawTileSprites *dts = &_depot_gfx_table[ddir];
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(railtype);
|
||||
@@ -170,13 +330,13 @@ void DrawTrainDepotSprite(const TileInfo *ti, RailType railtype, DiagDirection d
|
||||
uint32 offset = rti->GetRailtypeSpriteOffset();
|
||||
|
||||
if (image != SPR_FLAT_GRASS_TILE) image += offset;
|
||||
PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
|
||||
// PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
|
||||
|
||||
// DrawSprite(image, PAL_NONE, x, y);
|
||||
|
||||
switch (ddir) {
|
||||
case DIAGDIR_SW: DrawAutorailSelection(ti, HT_DIR_X, PAL_NONE); break;
|
||||
case DIAGDIR_SE: DrawAutorailSelection(ti, HT_DIR_Y, PAL_NONE); break;
|
||||
case DIAGDIR_SW: DrawAutorailSelection(ti, HT_DIR_X, GetSelectionColourByTint(palette)); break;
|
||||
case DIAGDIR_SE: DrawAutorailSelection(ti, HT_DIR_Y, GetSelectionColourByTint(palette)); break;
|
||||
default: break;
|
||||
}
|
||||
// if (rti->UsesOverlay()) {
|
||||
@@ -191,27 +351,208 @@ void DrawTrainDepotSprite(const TileInfo *ti, RailType railtype, DiagDirection d
|
||||
int depot_sprite = GetCustomRailSprite(rti, INVALID_TILE, RTSG_DEPOT);
|
||||
if (depot_sprite != 0) offset = depot_sprite - SPR_RAIL_DEPOT_SE_1;
|
||||
|
||||
DrawRailTileSeq(ti, dts, TO_INVALID, offset, 0, PALETTE_TINT_WHITE);
|
||||
DrawRailTileSeq(ti, dts, TO_INVALID, offset, 0, palette);
|
||||
}
|
||||
|
||||
void DrawTrainStationSprite(SpriteID palette, const TileInfo *ti, RailType railtype, Axis axis, byte section) {
|
||||
int32 total_offset = 0;
|
||||
PaletteID pal = COMPANY_SPRITE_COLOUR(_local_company);
|
||||
const DrawTileSprites *t = GetStationTileLayout(STATION_RAIL, section + (axis == AXIS_X ? 0 : 1));
|
||||
const RailtypeInfo *rti = nullptr;
|
||||
|
||||
if (railtype != INVALID_RAILTYPE) {
|
||||
rti = GetRailTypeInfo(railtype);
|
||||
total_offset = rti->GetRailtypeSpriteOffset();
|
||||
}
|
||||
|
||||
DrawAutorailSelection(ti, (axis == AXIS_X ? HT_DIR_X : HT_DIR_Y), GetSelectionColourByTint(palette));
|
||||
|
||||
// if (roadtype != INVALID_ROADTYPE) {
|
||||
// const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype);
|
||||
// if (image >= 4) {
|
||||
// /* Drive-through stop */
|
||||
// uint sprite_offset = 5 - image;
|
||||
|
||||
// /* Road underlay takes precedence over tram */
|
||||
// if (rti->UsesOverlay()) {
|
||||
// SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND);
|
||||
// DrawSprite(ground + sprite_offset, PAL_NONE, x, y);
|
||||
|
||||
// SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY);
|
||||
// if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y);
|
||||
// } else if (RoadTypeIsTram(roadtype)) {
|
||||
// DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
|
||||
// }
|
||||
// } else {
|
||||
// /* Drive-in stop */
|
||||
// if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) {
|
||||
// SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP);
|
||||
// DrawSprite(ground + image, PAL_NONE, x, y);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/* Default waypoint has no railtype specific sprites */
|
||||
// DrawRailTileSeq(ti, t, TO_INVALID, (st == STATION_WAYPOINT ? 0 : total_offset), 0, PALETTE_TINT_WHITE);
|
||||
DrawRailTileSeq(ti, t, TO_INVALID, total_offset, 0, palette);
|
||||
}
|
||||
|
||||
enum SignalOffsets { // from rail_cmd.cpp
|
||||
SIGNAL_TO_SOUTHWEST,
|
||||
SIGNAL_TO_NORTHEAST,
|
||||
SIGNAL_TO_SOUTHEAST,
|
||||
SIGNAL_TO_NORTHWEST,
|
||||
SIGNAL_TO_EAST,
|
||||
SIGNAL_TO_WEST,
|
||||
SIGNAL_TO_SOUTH,
|
||||
SIGNAL_TO_NORTH,
|
||||
};
|
||||
|
||||
/**
|
||||
* copied from rail_cmd.cpp
|
||||
* Get surface height in point (x,y)
|
||||
* On tiles with halftile foundations move (x,y) to a safe point wrt. track
|
||||
*/
|
||||
static uint GetSaveSlopeZ(uint x, uint y, Track track)
|
||||
{
|
||||
switch (track) {
|
||||
case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break;
|
||||
case TRACK_LOWER: x |= 0xF; y |= 0xF; break;
|
||||
case TRACK_LEFT: x |= 0xF; y &= ~0xF; break;
|
||||
case TRACK_RIGHT: x &= ~0xF; y |= 0xF; break;
|
||||
default: break;
|
||||
}
|
||||
return GetSlopePixelZ(x, y);
|
||||
}
|
||||
|
||||
void DrawSignal(const TileInfo *ti, RailType railtype, uint pos, SignalType type, SignalVariant variant) {
|
||||
// reference: DraawSingleSignal in rail_cmd.cpp
|
||||
bool side;
|
||||
switch (_settings_game.construction.train_signal_side) {
|
||||
case 0: side = false; break; // left
|
||||
case 2: side = true; break; // right
|
||||
default: side = _settings_game.vehicle.road_side != 0; break; // driving side
|
||||
}
|
||||
static const Point SignalPositions[2][12] = {
|
||||
{ // Signals on the left side
|
||||
/* LEFT LEFT RIGHT RIGHT UPPER UPPER */
|
||||
{ 8, 5}, {14, 1}, { 1, 14}, { 9, 11}, { 1, 0}, { 3, 10},
|
||||
/* LOWER LOWER X X Y Y */
|
||||
{11, 4}, {14, 14}, {11, 3}, { 4, 13}, { 3, 4}, {11, 13}
|
||||
}, { // Signals on the right side
|
||||
/* LEFT LEFT RIGHT RIGHT UPPER UPPER */
|
||||
{14, 1}, {12, 10}, { 4, 6}, { 1, 14}, {10, 4}, { 0, 1},
|
||||
/* LOWER LOWER X X Y Y */
|
||||
{14, 14}, { 5, 12}, {11, 13}, { 4, 3}, {13, 4}, { 3, 11}
|
||||
}
|
||||
};
|
||||
|
||||
uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side][pos].x;
|
||||
uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][pos].y;
|
||||
|
||||
static const Track pos_track[] = {
|
||||
TRACK_LEFT, TRACK_LEFT, TRACK_RIGHT, TRACK_RIGHT,
|
||||
TRACK_UPPER, TRACK_UPPER, TRACK_LOWER, TRACK_LOWER,
|
||||
TRACK_X, TRACK_X, TRACK_Y, TRACK_Y,
|
||||
};
|
||||
static const SignalOffsets pos_offset[] = {
|
||||
SIGNAL_TO_NORTH, SIGNAL_TO_SOUTH, SIGNAL_TO_NORTH, SIGNAL_TO_SOUTH,
|
||||
SIGNAL_TO_WEST, SIGNAL_TO_EAST, SIGNAL_TO_WEST, SIGNAL_TO_EAST,
|
||||
SIGNAL_TO_SOUTHWEST, SIGNAL_TO_NORTHEAST, SIGNAL_TO_SOUTHEAST, SIGNAL_TO_NORTHWEST,
|
||||
};
|
||||
|
||||
auto track = pos_track[pos];
|
||||
auto image = pos_offset[pos];
|
||||
static const SignalState condition = SIGNAL_STATE_GREEN;
|
||||
|
||||
auto rti = GetRailTypeInfo(railtype);
|
||||
SpriteID sprite = GetCustomSignalSprite(rti, ti->tile, type, variant, condition);
|
||||
if (sprite != 0) {
|
||||
sprite += image;
|
||||
} else {
|
||||
/* Normal electric signals are stored in a different sprite block than all other signals. */
|
||||
sprite = (type == SIGTYPE_NORMAL && variant == SIG_ELECTRIC) ? SPR_ORIGINAL_SIGNALS_BASE : SPR_SIGNALS_BASE - 16;
|
||||
sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0);
|
||||
}
|
||||
|
||||
AddSortableSpriteToDraw(sprite, PALETTE_TINT_WHITE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
|
||||
}
|
||||
|
||||
// copied from tunnelbridge_cmd.cpp
|
||||
static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
|
||||
{
|
||||
const BridgeSpec *bridge = GetBridgeSpec(index);
|
||||
assert(table < BRIDGE_PIECE_INVALID);
|
||||
if (bridge->sprite_table == nullptr || bridge->sprite_table[table] == nullptr) {
|
||||
return _bridge_sprite_table[index][table];
|
||||
} else {
|
||||
return bridge->sprite_table[table];
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBridgeHead(const TileInfo *ti, RailType railtype, DiagDirection ddir, BridgeType type) {
|
||||
auto rti = GetRailTypeInfo(railtype);
|
||||
int base_offset = rti->bridge_offset;
|
||||
const PalSpriteID *psid;
|
||||
|
||||
/* HACK Wizardry to convert the bridge ramp direction into a sprite offset */
|
||||
base_offset += (6 - ddir) % 4;
|
||||
|
||||
/* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
|
||||
if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
|
||||
psid = &GetBridgeSpriteTable(type, BRIDGE_PIECE_HEAD)[base_offset];
|
||||
|
||||
AddSortableSpriteToDraw(psid->sprite, PALETTE_TINT_WHITE, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
|
||||
// DrawAutorailSelection(ti, (ddir == DIAGDIR_SW || ddir == DIAGDIR_NE ? HT_DIR_X : HT_DIR_Y), PAL_NONE);
|
||||
}
|
||||
|
||||
void DrawTunnelHead(const TileInfo *ti, RailType railtype, DiagDirection ddir) {
|
||||
auto rti = GetRailTypeInfo(railtype);
|
||||
|
||||
SpriteID image;
|
||||
SpriteID railtype_overlay = 0;
|
||||
|
||||
image = rti->base_sprites.tunnel;
|
||||
if (rti->UsesOverlay()) {
|
||||
/* Check if the railtype has custom tunnel portals. */
|
||||
railtype_overlay = GetCustomRailSprite(rti, ti->tile, RTSG_TUNNEL_PORTAL);
|
||||
if (railtype_overlay != 0) image = SPR_RAILTYPE_TUNNEL_BASE; // Draw blank grass tunnel base.
|
||||
}
|
||||
|
||||
image += ddir * 2;
|
||||
AddSortableSpriteToDraw(image, PALETTE_TINT_WHITE, ti->x, ti->y, 16, 16, 0, ti->z);
|
||||
}
|
||||
|
||||
void ObjectHighlight::Draw(const TileInfo *ti) {
|
||||
this->UpdateTiles();
|
||||
auto range = this->tiles.equal_range(ti->tile);
|
||||
for (auto t = range.first; t != range.second; t++) {
|
||||
auto &oth = t->second;
|
||||
switch (oth.type) {
|
||||
case ObjectTileHighlight::Type::RAIL_DEPOT:
|
||||
DrawTrainDepotSprite(ti, _cur_railtype, oth.u.depot.ddir);
|
||||
DrawTrainDepotSprite(oth.palette, ti, _cur_railtype, oth.u.rail.depot.ddir);
|
||||
break;
|
||||
case ObjectTileHighlight::Type::RAIL_TRACK: {
|
||||
auto hs = (HighLightStyle)oth.u.rail.track;
|
||||
DrawAutorailSelection(ti, hs, PAL_NONE);
|
||||
break;
|
||||
}
|
||||
case ObjectTileHighlight::Type::RAIL_STATION:
|
||||
DrawTrainStationSprite(oth.palette, ti, _cur_railtype, oth.u.rail.station.axis, oth.u.rail.station.section);
|
||||
break;
|
||||
case ObjectTileHighlight::Type::RAIL_SIGNAL:
|
||||
DrawSignal(ti, _cur_railtype, oth.u.rail.signal.pos, oth.u.rail.signal.type, oth.u.rail.signal.variant);
|
||||
break;
|
||||
case ObjectTileHighlight::Type::RAIL_BRIDGE_HEAD:
|
||||
DrawBridgeHead(ti, _cur_railtype, oth.u.rail.bridge_head.ddir, oth.u.rail.bridge_head.type);
|
||||
break;
|
||||
case ObjectTileHighlight::Type::RAIL_TUNNEL_HEAD:
|
||||
DrawTunnelHead(ti, _cur_railtype, oth.u.rail.tunnel_head.ddir);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// fprintf(stderr, "TILEH DRAW %d %d %d\n", ti->tile, (int)i, (int)this->tiles.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -294,19 +635,6 @@ SpriteID GetIndustryZoningPalette(TileIndex tile) {
|
||||
return PAL_NONE;
|
||||
}
|
||||
|
||||
SpriteID GetTintBySelectionColour(SpriteID colour, bool deep=false) {
|
||||
switch(colour) {
|
||||
case SPR_PALETTE_ZONING_RED: return (deep ? PALETTE_TINT_RED_DEEP : PALETTE_TINT_RED);
|
||||
case SPR_PALETTE_ZONING_ORANGE: return (deep ? PALETTE_TINT_ORANGE_DEEP : PALETTE_TINT_ORANGE);
|
||||
case SPR_PALETTE_ZONING_GREEN: return (deep ? PALETTE_TINT_GREEN_DEEP : PALETTE_TINT_GREEN);
|
||||
case SPR_PALETTE_ZONING_LIGHT_BLUE: return (deep ? PALETTE_TINT_CYAN_DEEP : PALETTE_TINT_CYAN);
|
||||
case SPR_PALETTE_ZONING_YELLOW: return PALETTE_TINT_YELLOW;
|
||||
// case SPR_PALETTE_ZONING__: return PALETTE_TINT_YELLOW_WHITE;
|
||||
case SPR_PALETTE_ZONING_WHITE: return PALETTE_TINT_WHITE;
|
||||
default: return PAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th) {
|
||||
bool draw_selection = ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0);
|
||||
const Station *highlight_station = _viewport_highlight_station;
|
||||
@@ -314,17 +642,20 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th)
|
||||
if (_highlight_station_to_join) highlight_station = _highlight_station_to_join;
|
||||
|
||||
if (draw_selection) {
|
||||
auto b = CalcTileBorders(ti->tile, [](TileIndex t) {
|
||||
auto x = TileX(t) * TILE_SIZE, y = TileY(t) * TILE_SIZE;
|
||||
return IsInsideSelectedRectangle(x, y);
|
||||
});
|
||||
const SpriteID pal[] = {SPR_PALETTE_ZONING_RED, SPR_PALETTE_ZONING_YELLOW, SPR_PALETTE_ZONING_LIGHT_BLUE, SPR_PALETTE_ZONING_GREEN};
|
||||
auto color = pal[(int)_station_building_status];
|
||||
if (_thd.make_square_red) color = SPR_PALETTE_ZONING_RED;
|
||||
if (b.first != ZoningBorder::NONE)
|
||||
th.add_border(b.first, color);
|
||||
// const SpriteID pal[] = {SPR_PALETTE_ZONING_RED, SPR_PALETTE_ZONING_YELLOW, SPR_PALETTE_ZONING_LIGHT_BLUE, SPR_PALETTE_ZONING_GREEN};
|
||||
// auto color = pal[(int)_station_building_status];
|
||||
// if (_thd.make_square_red) color = SPR_PALETTE_ZONING_RED;
|
||||
if (_thd.make_square_red) {
|
||||
auto b = CalcTileBorders(ti->tile, [](TileIndex t) {
|
||||
auto x = TileX(t) * TILE_SIZE, y = TileY(t) * TILE_SIZE;
|
||||
return IsInsideSelectedRectangle(x, y);
|
||||
});
|
||||
if (b.first != ZoningBorder::NONE)
|
||||
th.add_border(b.first, SPR_PALETTE_ZONING_RED);
|
||||
}
|
||||
if (IsInsideSelectedRectangle(TileX(ti->tile) * TILE_SIZE, TileY(ti->tile) * TILE_SIZE)) {
|
||||
th.ground_pal = GetTintBySelectionColour(color);
|
||||
// th.ground_pal = GetTintBySelectionColour(color);
|
||||
th.ground_pal = th.structure_pal = (_thd.make_square_red ? PALETTE_TINT_RED : PAL_NONE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -529,6 +860,7 @@ TileHighlight GetTileHighlight(const TileInfo *ti) {
|
||||
}
|
||||
|
||||
SetStationSelectionHighlight(ti, th);
|
||||
// SetBlueprintHighlight(ti, th);
|
||||
|
||||
return th;
|
||||
}
|
||||
@@ -549,6 +881,8 @@ void DrawTileZoning(const TileInfo *ti, const TileHighlight &th) {
|
||||
bool DrawTileSelection(const TileInfo *ti, const TileHighlightType &tht) {
|
||||
_thd.cm.Draw(ti);
|
||||
|
||||
// if (_thd.drawstyle == CM_HT_BLUEPRINT_PLACE) return true;
|
||||
|
||||
if ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0) {
|
||||
// station selector, handled by DrawTileZoning
|
||||
return true;
|
||||
@@ -612,17 +946,65 @@ DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt) {
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
TileIndex _autodetection_tile = INVALID_TILE;
|
||||
DiagDirDiff _autodetection_rotation = DIAGDIRDIFF_SAME;
|
||||
|
||||
static DiagDirDiff GetAutodetectionRotation() {
|
||||
auto pt = GetTileBelowCursor();
|
||||
auto tile = TileVirtXY(pt.x, pt.y);
|
||||
|
||||
if (tile != _autodetection_tile) {
|
||||
_autodetection_tile = tile;
|
||||
_autodetection_rotation = DIAGDIRDIFF_SAME;
|
||||
}
|
||||
|
||||
return _autodetection_rotation;
|
||||
}
|
||||
|
||||
void RotateAutodetection() {
|
||||
auto rotation = GetAutodetectionRotation();
|
||||
if (rotation == DIAGDIRDIFF_90LEFT) rotation = DIAGDIRDIFF_SAME;
|
||||
else rotation++;
|
||||
_autodetection_rotation = rotation;
|
||||
::UpdateTileSelection();
|
||||
}
|
||||
|
||||
void ResetRotateAutodetection() {
|
||||
_autodetection_tile = INVALID_TILE;
|
||||
_autodetection_rotation = DIAGDIRDIFF_SAME;
|
||||
}
|
||||
|
||||
DiagDirection AddAutodetectionRotation(DiagDirection ddir) {
|
||||
return ChangeDiagDir(ddir, GetAutodetectionRotation());
|
||||
}
|
||||
|
||||
HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) {
|
||||
_thd.cm_new = ObjectHighlight(ObjectHighlight::Type::NONE);
|
||||
auto pt = GetTileBelowCursor();
|
||||
auto tile = (pt.x == -1 ? INVALID_TILE : TileVirtXY(pt.x, pt.y));
|
||||
// fprintf(stderr, "UPDATE %d %d %d %d\n", tile, _thd.size.x, _thd.size.y, (int)((_thd.place_mode & HT_DRAG_MASK) == HT_RECT));
|
||||
// if (_thd.place_mode == CM_HT_BLUEPRINT_PLACE) {
|
||||
// UpdateBlueprintTileSelection(pt, tile);
|
||||
// new_drawstyle = CM_HT_BLUEPRINT_PLACE;
|
||||
// } else
|
||||
if ((_thd.place_mode & HT_DRAG_MASK) == HT_RECT &&
|
||||
_cursor.sprite_seq[0].sprite == GetRailTypeInfo(_cur_railtype)->cursor.depot) {
|
||||
auto dir = _build_depot_direction;
|
||||
auto pt = GetTileBelowCursor();
|
||||
auto tile = TileVirtXY(pt.x, pt.y);
|
||||
if (pt.x != -1) {
|
||||
if (dir >= DiagDirection::DIAGDIR_END)
|
||||
dir = AutodetectRailObjectDirection(tile, pt);
|
||||
_thd.cm_new = ObjectHighlight::make_depot(tile, dir);
|
||||
if (dir >= DiagDirection::DIAGDIR_END) {
|
||||
dir = AddAutodetectionRotation(AutodetectRailObjectDirection(tile, pt));
|
||||
}
|
||||
_thd.cm_new = ObjectHighlight::make_rail_depot(tile, dir);
|
||||
}
|
||||
new_drawstyle = HT_RECT;
|
||||
} else if (((_thd.place_mode & HT_DRAG_MASK) == HT_RECT || ((_thd.place_mode & HT_DRAG_MASK) == HT_SPECIAL && (_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT)) && _thd.new_outersize.x > 0 && !_thd.make_square_red) { // station
|
||||
if (_thd.size.x >= (int)TILE_SIZE && _thd.size.y >= (int)TILE_SIZE) {
|
||||
auto start_tile = TileXY(_thd.new_pos.x / TILE_SIZE, _thd.new_pos.y / TILE_SIZE);
|
||||
auto end_tile = TileXY(
|
||||
std::min((_thd.new_pos.x + _thd.new_size.x) / TILE_SIZE, MapSizeX()) - 1,
|
||||
std::min((_thd.new_pos.y + _thd.new_size.y) / TILE_SIZE, MapSizeY()) - 1
|
||||
);
|
||||
_thd.cm_new = ObjectHighlight::make_rail_station(start_tile, end_tile, _railstation.orientation);
|
||||
}
|
||||
new_drawstyle = HT_RECT;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,9 @@ void SetIndustryForbiddenTilesHighlight(IndustryType type);
|
||||
|
||||
PaletteID GetTreeShadePal(TileIndex tile);
|
||||
|
||||
void RotateAutodetection();
|
||||
void ResetRotateAutodetection();
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,36 +1,155 @@
|
||||
#ifndef CITYMANIA_HIGHLIGHT_TYPE_HPP
|
||||
#define CITYMANIA_HIGHLIGHT_TYPE_HPP
|
||||
|
||||
#include "../bridge.h"
|
||||
#include "../direction_type.h"
|
||||
#include "../map_func.h"
|
||||
#include "../signal_type.h"
|
||||
#include "../station_type.h"
|
||||
#include "../tile_cmd.h"
|
||||
#include "../tile_type.h"
|
||||
#include "../track_type.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace citymania {
|
||||
|
||||
|
||||
class ObjectTileHighlight {
|
||||
public:
|
||||
enum class Type {
|
||||
RAIL_DEPOT = 0,
|
||||
RAIL_TRACK = 1,
|
||||
BEGIN = 0,
|
||||
RAIL_DEPOT = BEGIN,
|
||||
RAIL_TRACK,
|
||||
RAIL_STATION,
|
||||
RAIL_SIGNAL,
|
||||
RAIL_BRIDGE_HEAD,
|
||||
RAIL_TUNNEL_HEAD,
|
||||
END,
|
||||
};
|
||||
|
||||
Type type;
|
||||
SpriteID palette;
|
||||
|
||||
union {
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
} depot;
|
||||
struct {
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
} depot;
|
||||
Track track;
|
||||
struct {
|
||||
Axis axis;
|
||||
byte section;
|
||||
} station;
|
||||
struct {
|
||||
uint pos;
|
||||
SignalType type;
|
||||
SignalVariant variant;
|
||||
} signal;
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
TileIndex other_end;
|
||||
BridgeType type;
|
||||
} bridge_head;
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
} tunnel_head;
|
||||
} rail;
|
||||
} u;
|
||||
|
||||
ObjectTileHighlight(Type type): type{type} {}
|
||||
static ObjectTileHighlight make_depot(DiagDirection ddir);
|
||||
static ObjectTileHighlight make_rail(Track track);
|
||||
ObjectTileHighlight(Type type, SpriteID palette): type{type}, palette{palette} {}
|
||||
static ObjectTileHighlight make_rail_depot(SpriteID palette, DiagDirection ddir);
|
||||
static ObjectTileHighlight make_rail_track(SpriteID palette, Track track);
|
||||
static ObjectTileHighlight make_rail_station(SpriteID palette, Axis axis, byte section);
|
||||
static ObjectTileHighlight make_rail_signal(SpriteID palette, uint pos, SignalType type, SignalVariant variant);
|
||||
static ObjectTileHighlight make_rail_bridge_head(SpriteID palette, DiagDirection ddir, BridgeType type);
|
||||
static ObjectTileHighlight make_rail_tunnel_head(SpriteID palette, DiagDirection ddir);
|
||||
};
|
||||
|
||||
class TileIndexDiffCCompare{
|
||||
public:
|
||||
bool operator()(const TileIndexDiffC &a, const TileIndexDiffC &b) const {
|
||||
if (a.x < b.x) return true;
|
||||
if (a.x == b.x && a.y < b.y) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class Blueprint {
|
||||
public:
|
||||
class Item {
|
||||
public:
|
||||
enum class Type {
|
||||
BEGIN = 0,
|
||||
RAIL_DEPOT = BEGIN,
|
||||
RAIL_TRACK,
|
||||
RAIL_STATION,
|
||||
RAIL_STATION_PART,
|
||||
RAIL_SIGNAL,
|
||||
RAIL_BRIDGE,
|
||||
RAIL_TUNNEL,
|
||||
END,
|
||||
};
|
||||
Type type;
|
||||
TileIndexDiffC tdiff;
|
||||
union {
|
||||
struct {
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
} depot;
|
||||
struct {
|
||||
uint16 length;
|
||||
Trackdir start_dir;
|
||||
} track;
|
||||
struct {
|
||||
StationID id;
|
||||
bool has_part;
|
||||
} station;
|
||||
struct {
|
||||
Axis axis;
|
||||
StationID id;
|
||||
} station_part;
|
||||
struct {
|
||||
uint pos;
|
||||
SignalType type;
|
||||
SignalVariant variant;
|
||||
} signal;
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
TileIndexDiffC other_end;
|
||||
BridgeType type;
|
||||
} bridge;
|
||||
struct {
|
||||
DiagDirection ddir;
|
||||
TileIndexDiffC other_end;
|
||||
} tunnel;
|
||||
} rail;
|
||||
} u;
|
||||
Item(Type type, TileIndexDiffC tdiff)
|
||||
: type{type}, tdiff{tdiff} {}
|
||||
};
|
||||
|
||||
std::vector<Item> items;
|
||||
std::set<TileIndexDiffC, TileIndexDiffCCompare> tiles;
|
||||
|
||||
Blueprint() {}
|
||||
|
||||
void Clear() {
|
||||
this->items.clear();
|
||||
this->tiles.clear();
|
||||
}
|
||||
|
||||
void Add(Item item);
|
||||
|
||||
bool HasTile(TileIndexDiffC tdiff) {
|
||||
return (this->tiles.find(tdiff) != this->tiles.end());
|
||||
}
|
||||
|
||||
sp<Blueprint> Rotate();
|
||||
|
||||
std::multimap<TileIndex, ObjectTileHighlight> GetTiles(TileIndex tile);
|
||||
};
|
||||
|
||||
class ObjectHighlight {
|
||||
@@ -38,28 +157,31 @@ public:
|
||||
enum class Type {
|
||||
NONE = 0,
|
||||
RAIL_DEPOT = 1,
|
||||
RAIL_STATION = 2,
|
||||
// BLUEPRINT = 2,
|
||||
};
|
||||
|
||||
protected:
|
||||
Type type;
|
||||
union {
|
||||
struct {
|
||||
TileIndex tile;
|
||||
DiagDirection ddir;
|
||||
} depot;
|
||||
} u;
|
||||
TileIndex tile = INVALID_TILE;
|
||||
TileIndex end_tile = INVALID_TILE;
|
||||
Axis axis = INVALID_AXIS;
|
||||
DiagDirection ddir = INVALID_DIAGDIR;
|
||||
sp<Blueprint> blueprint = nullptr;
|
||||
|
||||
protected:
|
||||
bool tiles_updated = false;
|
||||
std::multimap<TileIndex, ObjectTileHighlight> tiles;
|
||||
void UpdateTiles();
|
||||
void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track);
|
||||
|
||||
public:
|
||||
ObjectHighlight(Type type = Type::NONE): type{type} { /* get rid of uninitualized warning */ this->u.depot.tile = INVALID_TILE; }
|
||||
ObjectHighlight(Type type = Type::NONE): type{type} {}
|
||||
bool operator==(const ObjectHighlight& oh);
|
||||
bool operator!=(const ObjectHighlight& oh);
|
||||
|
||||
static ObjectHighlight make_depot(TileIndex tile, DiagDirection ddir);
|
||||
static ObjectHighlight make_rail_depot(TileIndex tile, DiagDirection ddir);
|
||||
static ObjectHighlight make_rail_station(TileIndex start_tile, TileIndex end_tile, Axis axis);
|
||||
// static ObjectHighlight make_blueprint(TileIndex tile, sp<Blueprint> blueprint);
|
||||
|
||||
void Draw(const TileInfo *ti);
|
||||
void MarkDirty();
|
||||
|
||||
@@ -34,6 +34,9 @@ bool _fn_mod = false;
|
||||
bool _remove_mod = false;
|
||||
bool _estimate_mod = false;
|
||||
|
||||
bool _middle_button_down; ///< Is middle mouse button pressed?
|
||||
bool _middle_button_clicked; ///< Is middle mouse button clicked?
|
||||
|
||||
static uint32 _effective_actions = 0;
|
||||
static std::optional<std::chrono::steady_clock::time_point> _first_effective_tick = {};
|
||||
static std::queue<std::chrono::steady_clock::time_point> _last_actions;
|
||||
|
||||
@@ -259,6 +259,9 @@ void DecodeSettings(BitIStream &bs, Settings &settings) {
|
||||
uint16 _last_client_version = 1512;
|
||||
|
||||
static u8vector EncodeData() {
|
||||
// Skip if game is not initialized for some reason (i.e. -d desync)
|
||||
if (!_game) return {};
|
||||
|
||||
BitOStream bs;
|
||||
bs.Reserve(1000);
|
||||
bs.WriteBytes(SAVEGAME_DATA_FORMAT_VERSION, 2);
|
||||
|
||||
@@ -8,16 +8,28 @@
|
||||
#include "../command_type.h"
|
||||
#include "../command_func.h"
|
||||
#include "../company_func.h"
|
||||
#include "../industry_map.h"
|
||||
#include "../industry.h"
|
||||
#include "../landscape.h"
|
||||
#include "../newgrf_station.h" // StationClassID
|
||||
#include "../newgrf_house.h" // GetHouseCallback
|
||||
#include "../newgrf_cargo.h" // GetCargoTranslation
|
||||
#include "../object_type.h"
|
||||
#include "../object_map.h"
|
||||
#include "../station_base.h"
|
||||
#include "../strings_func.h" // GetString, SetDParam
|
||||
#include "../tilehighlight_type.h"
|
||||
#include "../town_map.h"
|
||||
#include "../town.h"
|
||||
#include "../viewport_func.h"
|
||||
#include "../viewport_kdtree.h"
|
||||
#include "../window_gui.h"
|
||||
#include "../zoom_type.h"
|
||||
#include "../zoom_func.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
extern const Station *_viewport_highlight_station;
|
||||
extern TileHighlightData _thd;
|
||||
extern void MarkCatchmentTilesDirty();
|
||||
@@ -332,21 +344,21 @@ static void FindStationsAroundSelection(const TileArea &location)
|
||||
_station_building_status = (adjacent == nullptr ? StationBuildingStatus::NEW : StationBuildingStatus::JOIN);
|
||||
}
|
||||
|
||||
void CheckRedrawStationCoverage() {
|
||||
bool CheckRedrawStationCoverage() {
|
||||
// static bool last_ctrl_pressed = false;
|
||||
static TileArea last_location;
|
||||
static bool last_station_mode = false;
|
||||
static bool last_coverage = false;
|
||||
static bool last_fn_mod = false;
|
||||
TileArea location(TileVirtXY(_thd.pos.x, _thd.pos.y), _thd.size.x / TILE_SIZE - 1, _thd.size.y / TILE_SIZE - 1);
|
||||
bool station_mode = ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0);
|
||||
bool location_changed = (location.tile != last_location.tile || location.w != last_location.w || location.h != last_location.h);
|
||||
bool mode_changed = (last_station_mode != station_mode);
|
||||
// if (!location_changed && _ctrl_pressed == last_ctrl_pressed && !mode_changed)
|
||||
// return;
|
||||
if (!location_changed && citymania::_fn_mod == last_fn_mod && !mode_changed)
|
||||
return false;
|
||||
|
||||
// last_ctrl_pressed = _ctrl_pressed;
|
||||
// last_location = location;
|
||||
// last_station_mode = station_mode;
|
||||
last_fn_mod = citymania::_fn_mod;
|
||||
last_location = location;
|
||||
last_station_mode = station_mode;
|
||||
|
||||
if (citymania::_fn_mod) {
|
||||
Station *st = nullptr;
|
||||
@@ -363,6 +375,7 @@ void CheckRedrawStationCoverage() {
|
||||
FindStationsAroundSelection(location);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -380,4 +393,133 @@ void AbortStationPlacement() {
|
||||
}
|
||||
|
||||
|
||||
uint GetMonthlyFrom256Tick(uint amount) {
|
||||
return ((amount * DAY_TICKS * 30) >> 8);
|
||||
}
|
||||
|
||||
uint GetAverageHouseProduction(byte amount) {
|
||||
static const uint AVG[2][256] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 42, 45, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 90, 95, 100, 105, 110, 115, 120, 126, 132, 138, 144, 150, 156, 162, 168, 175, 182, 189, 196, 203, 210, 217, 224, 232, 240, 248, 256, 264, 272, 280, 288, 297, 306, 315, 324, 333, 342, 351, 360, 370, 380, 390, 400, 410, 420, 430, 440, 451, 462, 473, 484, 495, 506, 517, 528, 540, 552, 564, 576, 588, 600, 612, 624, 637, 650, 663, 676, 689, 702, 715, 728, 742, 756, 770, 784, 798, 812, 826, 840, 855, 870, 885, 900, 915, 930, 945, 960, 976, 992, 1008, 1024, 1040, 1056, 1072, 1088, 1105, 1122, 1139, 1156, 1173, 1190, 1207, 1224, 1242, 1260, 1278, 1296, 1314, 1332, 1350, 1368, 1387, 1406, 1425, 1444, 1463, 1482, 1501, 1520, 1540, 1560, 1580, 1600, 1620, 1640, 1660, 1680, 1701, 1722, 1743, 1764, 1785, 1806, 1827, 1848, 1870, 1892, 1914, 1936, 1958, 1980, 2002, 2024, 2047, 2070, 2093, 2116, 2139, 2162, 2185, 2208, 2232, 2256, 2280, 2304, 2328, 2352, 2376, 2400, 2425, 2450, 2475, 2500, 2525, 2550, 2575, 2600, 2626, 2652, 2678, 2704, 2730, 2756, 2782, 2808, 2835, 2862, 2889, 2916, 2943, 2970, 2997, 3024, 3052, 3080, 3108, 3136, 3164, 3192, 3220, 3248, 3277, 3306, 3335, 3364, 3393, 3422, 3451, 3480, 3510, 3540, 3570, 3600, 3630, 3660, 3690, 3720, 3751, 3782, 3813, 3844, 3875, 3906, 3937, 3968, 4000, 4032, 4064, 4096, 4128, 4160, 4192},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 246, 252, 258, 264, 270, 276, 282, 288, 294, 300, 306, 312, 318, 324, 330, 336, 343, 350, 357, 364, 371, 378, 385, 392, 399, 406, 413, 420, 427, 434, 441, 448, 456, 464, 472, 480, 488, 496, 504, 512, 520, 528, 536, 544, 552, 560, 568, 576, 585, 594, 603, 612, 621, 630, 639, 648, 657, 666, 675, 684, 693, 702, 711, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 891, 902, 913, 924, 935, 946, 957, 968, 979, 990, 1001, 1012, 1023, 1034, 1045, 1056, 1068, 1080, 1092, 1104, 1116, 1128, 1140, 1152, 1164, 1176, 1188, 1200, 1212, 1224, 1236, 1248, 1261, 1274, 1287, 1300, 1313, 1326, 1339, 1352, 1365, 1378, 1391, 1404, 1417, 1430, 1443, 1456, 1470, 1484, 1498, 1512, 1526, 1540, 1554, 1568, 1582, 1596, 1610, 1624, 1638, 1652, 1666, 1680, 1695, 1710, 1725, 1740, 1755, 1770, 1785, 1800, 1815, 1830, 1845, 1860, 1875, 1890, 1905, 1920, 1936, 1952, 1968, 1984, 2000, 2016, 2032, 2048, 2064, 2080, 2096, 2112, 2128, 2144, 2160}
|
||||
};
|
||||
if (amount == 0) return 0;
|
||||
switch (_settings_game.economy.town_cargogen_mode) {
|
||||
case TCGM_ORIGINAL:
|
||||
return GetMonthlyFrom256Tick(AVG[EconomyIsInRecession() ? 1 : 0][amount]);
|
||||
case TCGM_BITCOUNT: {
|
||||
uint amt = (amount + 7) / 8;
|
||||
if (EconomyIsInRecession()) amt += 2;
|
||||
else amt *= 2;
|
||||
return GetMonthlyFrom256Tick(amt * 16);
|
||||
}
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced)
|
||||
{
|
||||
if (!IsHouseCompleted(tile)) return;
|
||||
|
||||
HouseID house_id = GetHouseType(tile);
|
||||
const HouseSpec *hs = HouseSpec::Get(house_id);
|
||||
Town *t = Town::GetByTile(tile);
|
||||
|
||||
if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
|
||||
for (uint i = 0; i < 256; i++) {
|
||||
uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, house_id, t, tile);
|
||||
|
||||
if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
|
||||
|
||||
CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile);
|
||||
|
||||
if (cargo == CT_INVALID) continue;
|
||||
produced[cargo] += GetMonthlyFrom256Tick((uint)GB(callback, 0, 8)) ;
|
||||
}
|
||||
} else {
|
||||
produced[CT_PASSENGERS] += GetAverageHouseProduction(hs->population);
|
||||
produced[CT_MAIL] += GetAverageHouseProduction(hs->mail_generation);
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to ::GetProductionAroundTiles but counts production total
|
||||
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad)
|
||||
{
|
||||
static const uint HQ_AVG_POP[2][5] = {
|
||||
{48, 64, 84, 128, 384},
|
||||
{48, 64, 84, 128, 256},
|
||||
};
|
||||
static const uint HQ_AVG_MAIL[2][5] = {
|
||||
{36, 48, 64, 96, 264},
|
||||
{36, 48, 64, 96, 196}
|
||||
};
|
||||
|
||||
CargoArray produced;
|
||||
std::set<IndustryID> industries;
|
||||
TileArea ta = TileArea(tile, w, h).Expand(rad);
|
||||
|
||||
/* Loop over all tiles to get the produced cargo of
|
||||
* everything except industries */
|
||||
TILE_AREA_LOOP(tile, ta) {
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_INDUSTRY:
|
||||
industries.insert(GetIndustryIndex(tile));
|
||||
break;
|
||||
case MP_HOUSE:
|
||||
AddProducedCargo_Town(tile, produced);
|
||||
break;
|
||||
case MP_OBJECT:
|
||||
if (IsObjectType(tile, OBJECT_HQ)) {
|
||||
produced[CT_PASSENGERS] += GetMonthlyFrom256Tick(HQ_AVG_POP[EconomyIsInRecession() ? 1 : 0][GetAnimationFrame(tile)]);
|
||||
produced[CT_MAIL] += GetMonthlyFrom256Tick(HQ_AVG_MAIL[EconomyIsInRecession() ? 1 : 0][GetAnimationFrame(tile)]);
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop over the seen industries. They produce cargo for
|
||||
* anything that is within 'rad' of any one of their tiles.
|
||||
*/
|
||||
for (IndustryID industry : industries) {
|
||||
const Industry *i = Industry::Get(industry);
|
||||
/* Skip industry with neutral station */
|
||||
if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue;
|
||||
|
||||
for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
|
||||
CargoID cargo = i->produced_cargo[j];
|
||||
if (cargo != CT_INVALID) produced[cargo] += ((uint)i->last_month_production[j]) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return produced;
|
||||
}
|
||||
|
||||
std::string GetStationCoverageProductionText(TileIndex tile, int w, int h, int rad, StationCoverageType sct) {
|
||||
auto production = GetProductionAroundTiles(tile, w, h, rad);
|
||||
|
||||
std::ostringstream s;
|
||||
char buffer[DRAW_STRING_BUFFER];
|
||||
GetString(buffer, STR_CM_STATION_BUILD_SUPPLIES, lastof(buffer));
|
||||
s << buffer;
|
||||
bool first = true;
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
switch (sct) {
|
||||
case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(i, CC_PASSENGERS)) continue; break;
|
||||
case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(i, CC_PASSENGERS)) continue; break;
|
||||
case SCT_ALL: break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
if (production[i] == 0) continue;
|
||||
if (!first) s << ", ";
|
||||
first = false;
|
||||
SetDParam(0, i);
|
||||
SetDParam(1, production[i] >> 8);
|
||||
// GetString(buffer, STR_CM_STATION_BUILD_SUPPLIES_CARGO, lastof(buffer));
|
||||
GetString(buffer, STR_JUST_CARGO, lastof(buffer));
|
||||
s << buffer;
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "../core/geometry_type.hpp"
|
||||
#include "../command_type.h"
|
||||
#include "../station_gui.h"
|
||||
#include "../station_type.h"
|
||||
|
||||
namespace citymania {
|
||||
@@ -28,9 +29,11 @@ void PlaceAirport(TileIndex tile);
|
||||
void SelectStationToJoin(const Station *station);
|
||||
// const Station *GetStationToJoin();
|
||||
void MarkCoverageHighlightDirty();
|
||||
void CheckRedrawStationCoverage();
|
||||
bool CheckRedrawStationCoverage();
|
||||
void AbortStationPlacement();
|
||||
|
||||
std::string GetStationCoverageProductionText(TileIndex tile, int w, int h, int rad, StationCoverageType sct);
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
#endif
|
||||
|
||||
@@ -590,8 +590,6 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
|
||||
AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
|
||||
Game::NewEvent(new ScriptEventCompanyNew(c->index));
|
||||
|
||||
if (!is_ai) UpdateAllTownVirtCoords(); //coloured rating
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -862,6 +860,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
* all clients so everything is in sync */
|
||||
SyncCompanySettings();
|
||||
|
||||
UpdateAllTownVirtCoords(); // CityMania (for colouring towns)
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
|
||||
@@ -2459,4 +2459,6 @@ void IConsoleStdLibRegister()
|
||||
IConsoleCmdRegister("cmexport", citymania::ConExport);
|
||||
IConsoleCmdRegister("cmstep", citymania::ConStep, ConHookNoNetwork);
|
||||
IConsoleCmdRegister("cmtreemap", citymania::ConTreeMap, ConHookNoNetwork);
|
||||
IConsoleCmdRegister("cmresettowngrowth", citymania::ConResetTownGrowth, ConHookNoNetwork);
|
||||
IConsoleCmdRegister("cmloadcommands", citymania::ConLoadCommands, ConHookNoNetwork);
|
||||
}
|
||||
|
||||
@@ -105,13 +105,17 @@ enum WindowKeyCodes {
|
||||
|
||||
WKC_L_BRACE = 154, ///< { Left brace
|
||||
WKC_R_BRACE = 155, ///< } Right brace
|
||||
|
||||
|
||||
WKC_L_PAREN = 157, ///< ( Left parentheses
|
||||
WKC_R_PAREN = 158, ///< ) Right parentheses
|
||||
WKC_PLUS = 159, ///< + Plus
|
||||
WKC_EXCLAIM = 160, ///< ! Exclamation mark
|
||||
WKC_ASTERISK = 161, ///< * Asterisk
|
||||
WKC_DOLLAR = 162, ///< $ Dollar sign
|
||||
|
||||
CM_WKC_MOUSE_MIDDLE = 0x703, ///< CityMania: special code for middle mouse button
|
||||
CM_WKC_MOUSE_OTHER_START = 0x704, ///< CityMania: start of the numbered buttons (whatever number driver reports), starts as MOUSE_4 hotkey
|
||||
CM_WKC_MOUSE_OTHER_END = 0x71f, ///< CityMania: 30 buttons should be enough for any mouse, right? ;)
|
||||
};
|
||||
|
||||
/** A single sprite of a list of animated cursors */
|
||||
|
||||
@@ -95,6 +95,35 @@ static const KeycodeNames _keycode_to_name[] = {
|
||||
{"R_PAREN", WKC_R_PAREN},
|
||||
{"EXCLAIM", WKC_EXCLAIM},
|
||||
{"ASTERISK", WKC_ASTERISK},
|
||||
|
||||
{"MOUSE_MIDDLE", CM_WKC_MOUSE_MIDDLE},
|
||||
{"MOUSE_4", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 0)},
|
||||
{"MOUSE_5", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 1)},
|
||||
{"MOUSE_6", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 2)},
|
||||
{"MOUSE_7", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 3)},
|
||||
{"MOUSE_8", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 4)},
|
||||
{"MOUSE_9", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 5)},
|
||||
{"MOUSE_10", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 6)},
|
||||
{"MOUSE_11", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 7)},
|
||||
{"MOUSE_12", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 8)},
|
||||
{"MOUSE_13", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 9)},
|
||||
{"MOUSE_14", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 10)},
|
||||
{"MOUSE_15", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 11)},
|
||||
{"MOUSE_16", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 12)},
|
||||
{"MOUSE_17", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 13)},
|
||||
{"MOUSE_18", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 14)},
|
||||
{"MOUSE_19", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 15)},
|
||||
{"MOUSE_20", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 16)},
|
||||
{"MOUSE_21", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 17)},
|
||||
{"MOUSE_22", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 18)},
|
||||
{"MOUSE_23", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 19)},
|
||||
{"MOUSE_24", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 20)},
|
||||
{"MOUSE_25", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 21)},
|
||||
{"MOUSE_26", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 22)},
|
||||
{"MOUSE_27", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 23)},
|
||||
{"MOUSE_28", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 24)},
|
||||
{"MOUSE_29", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 25)},
|
||||
{"MOUSE_30", (WindowKeyCodes)(CM_WKC_MOUSE_OTHER_START + 26)},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -3927,6 +3927,7 @@ STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit t
|
||||
STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA}
|
||||
|
||||
STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}
|
||||
STR_CM_VEHICLE_INFO_BUILT_VALUE_WITH_ID :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}{BLACK} ID: {LTBLUE}{NUM}
|
||||
STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Capacity: {LTBLUE}None{STRING}
|
||||
STR_VEHICLE_INFO_CAPACITY :{BLACK}Capacity: {LTBLUE}{CARGO_LONG}{3:STRING}
|
||||
STR_VEHICLE_INFO_CAPACITY_MULT :{BLACK}Capacity: {LTBLUE}{CARGO_LONG}{3:STRING} (x{4:NUM})
|
||||
@@ -3951,7 +3952,9 @@ STR_QUERY_RENAME_AIRCRAFT_CAPTION :{WHITE}Name air
|
||||
|
||||
# Extra buttons for train details windows
|
||||
STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE :{LTBLUE}{ENGINE}{BLACK} Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}
|
||||
STR_CM_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_WITH_ID :{LTBLUE}{ENGINE}{BLACK} Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}{BLACK} ID: {LTBLUE}{NUM}
|
||||
STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE :{LTBLUE}{ENGINE}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}
|
||||
STR_CM_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_WITH_ID :{LTBLUE}{ENGINE}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}{BLACK} ID: {LTBLUE}{NUM}
|
||||
|
||||
STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT :{BLACK}Total cargo capacity of this train:
|
||||
STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY :{LTBLUE}- {CARGO_LONG} ({CARGO_SHORT})
|
||||
@@ -5616,3 +5619,4 @@ STR_CM_CONFIG_SETTING_SHADED_TREES_SERVER : As server
|
||||
STR_CM_CONFIG_SETTING_SHOW_APM : Show APM counter: {STRING2}
|
||||
STR_CM_CONFIG_SETTING_SHOW_APM_HELPTEXT : Adds APM (actions per minute) counter to the statusbar.
|
||||
STR_CM_STATUSBAR_APM : {WHITE}APM: {NUM} AVG: {NUM}
|
||||
STR_CM_STATION_BUILD_SUPPLIES :{BLACK}Supplies: {GOLD}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
|
||||
#include "citymania/cm_highlight.hpp"
|
||||
#include "citymania/cm_main.hpp"
|
||||
#include "citymania/cm_console_cmds.hpp"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <system_error>
|
||||
@@ -1516,6 +1517,7 @@ void GameLoop()
|
||||
* We do this here, because it means that the network is really closed */
|
||||
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR);
|
||||
}
|
||||
citymania::ExecuteFakeCommands(_date, _date_fract);
|
||||
/* Singleplayer */
|
||||
StateGameLoop();
|
||||
}
|
||||
|
||||
117
src/rail_gui.cpp
117
src/rail_gui.cpp
@@ -43,6 +43,7 @@
|
||||
#include "widgets/rail_widget.h"
|
||||
|
||||
#include "citymania/cm_hotkeys.hpp"
|
||||
#include "citymania/cm_highlight.hpp"
|
||||
#include "citymania/cm_station_gui.hpp"
|
||||
|
||||
#include "safeguards.h"
|
||||
@@ -508,30 +509,6 @@ RoadBits FindRailsToConnect(TileIndex tile) {
|
||||
return passing;
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects orientation for rail object (depot)
|
||||
*/
|
||||
DiagDirection AutodetectRailObjectDirection(TileIndex tile) {
|
||||
RoadBits bits = FindRailsToConnect(tile);
|
||||
// FIXME after this point repeats road autodetection
|
||||
if (HasExactlyOneBit(bits)) return RoadBitsToDiagDir(bits);
|
||||
if (bits == ROAD_NONE) bits = ROAD_ALL;
|
||||
RoadBits frac_bits = DiagDirToRoadBits(TileFractCoordsToDiagDir());
|
||||
if (HasExactlyOneBit(frac_bits & bits)) {
|
||||
return RoadBitsToDiagDir(frac_bits & bits);
|
||||
}
|
||||
frac_bits |= MirrorRoadBits(frac_bits);
|
||||
if (HasExactlyOneBit(frac_bits & bits)) {
|
||||
return RoadBitsToDiagDir(frac_bits & bits);
|
||||
}
|
||||
for (DiagDirection ddir = DIAGDIR_BEGIN; ddir < DIAGDIR_END; ddir++) {
|
||||
if (DiagDirToRoadBits(ddir) & bits) {
|
||||
return ddir;
|
||||
}
|
||||
}
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
/** Rail toolbar management class. */
|
||||
struct BuildRailToolbarWindow : Window {
|
||||
RailType railtype; ///< Rail type to build.
|
||||
@@ -719,6 +696,7 @@ struct BuildRailToolbarWindow : Window {
|
||||
|
||||
case WID_RAT_BUILD_DEPOT:
|
||||
if (HandlePlacePushButton(this, WID_RAT_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, HT_RECT | (HighLightStyle)_build_depot_direction)) {
|
||||
citymania::ResetRotateAutodetection();
|
||||
ShowBuildTrainDepotPicker(this);
|
||||
this->last_user_action = widget;
|
||||
}
|
||||
@@ -850,7 +828,8 @@ struct BuildRailToolbarWindow : Window {
|
||||
case WID_RAT_BUILD_DEPOT:
|
||||
ddir = _build_depot_direction;
|
||||
if (ddir == DIAGDIR_NW + 1) {
|
||||
ddir = AutodetectRailObjectDirection(tile);
|
||||
assert(_thd.cm.type == citymania::ObjectHighlight::Type::RAIL_DEPOT);
|
||||
ddir = _thd.cm.ddir;
|
||||
}
|
||||
DoCommandP(tile, _cur_railtype, ddir,
|
||||
CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT),
|
||||
@@ -1120,7 +1099,14 @@ static void HandleStationPlacement(TileIndex start, TileIndex end)
|
||||
ShowSelectStationIfNeeded(cmdcont, ta);
|
||||
}
|
||||
|
||||
|
||||
struct BuildRailStationWindow : public PickerWindowBase {
|
||||
/* CityMania code start */
|
||||
public:
|
||||
enum class Hotkey : int {
|
||||
ROTATE,
|
||||
};
|
||||
/* CityMania code end */
|
||||
private:
|
||||
uint line_height; ///< Height of a single line in the newstation selection matrix (#WID_BRAS_NEWST_LIST widget).
|
||||
uint coverage_height; ///< Height of the coverage texts.
|
||||
@@ -1727,6 +1713,30 @@ public:
|
||||
{
|
||||
CheckRedrawStationCoverage(this);
|
||||
}
|
||||
|
||||
/* CityMania code start */
|
||||
EventState OnHotkey(int hotkey) override
|
||||
{
|
||||
switch ((BuildRailStationWindow::Hotkey)hotkey) {
|
||||
/* Indicate to the OnClick that the action comes from a hotkey rather
|
||||
* then from a click and that the CTRL state should be ignored. */
|
||||
case BuildRailStationWindow::Hotkey::ROTATE:
|
||||
this->RaiseWidget(_railstation.orientation + WID_BRAS_PLATFORM_DIR_X);
|
||||
_railstation.orientation = OtherAxis(_railstation.orientation);
|
||||
this->LowerWidget(_railstation.orientation + WID_BRAS_PLATFORM_DIR_X);
|
||||
this->SetDirty();
|
||||
DeleteWindowById(WC_SELECT_STATION, 0);
|
||||
return ES_HANDLED;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
return ES_NOT_HANDLED;
|
||||
}
|
||||
|
||||
static HotkeyList hotkeys;
|
||||
/* CityMania code end */
|
||||
};
|
||||
|
||||
Listing BuildRailStationWindow::last_sorting = { false, 0 };
|
||||
@@ -1841,12 +1851,21 @@ static const NWidgetPart _nested_station_builder_widgets[] = {
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
/* CityMania code start */
|
||||
static Hotkey build_station_hotkeys[] = {
|
||||
Hotkey(CM_WKC_MOUSE_MIDDLE, "rotate", (int)BuildRailStationWindow::Hotkey::ROTATE),
|
||||
HOTKEY_LIST_END
|
||||
};
|
||||
HotkeyList BuildRailStationWindow::hotkeys("cm_build_rail_station", build_station_hotkeys);
|
||||
/* CityMania code end */
|
||||
|
||||
/** High level window description of the station-build window (default & newGRF) */
|
||||
static WindowDesc _station_builder_desc(
|
||||
WDP_AUTO, "build_station_rail", 350, 0,
|
||||
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_station_builder_widgets, lengthof(_nested_station_builder_widgets)
|
||||
_nested_station_builder_widgets, lengthof(_nested_station_builder_widgets),
|
||||
&BuildRailStationWindow::hotkeys // CityMania addition
|
||||
);
|
||||
|
||||
/** Open station build window */
|
||||
@@ -2069,7 +2088,15 @@ static void ShowSignalBuilder(Window *parent)
|
||||
new BuildSignalWindow(&_signal_builder_desc, parent);
|
||||
}
|
||||
|
||||
|
||||
struct BuildRailDepotWindow : public PickerWindowBase {
|
||||
/* CityMania code start */
|
||||
public:
|
||||
enum class Hotkey : int {
|
||||
ROTATE,
|
||||
};
|
||||
/* CityMania code end */
|
||||
|
||||
BuildRailDepotWindow(WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent)
|
||||
{
|
||||
this->InitNested(TRANSPORT_RAIL);
|
||||
@@ -2116,8 +2143,43 @@ struct BuildRailDepotWindow : public PickerWindowBase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* CityMania code start */
|
||||
EventState OnHotkey(int hotkey) override
|
||||
{
|
||||
switch ((BuildRailDepotWindow::Hotkey)hotkey) {
|
||||
/* Indicate to the OnClick that the action comes from a hotkey rather
|
||||
* then from a click and that the CTRL state should be ignored. */
|
||||
case BuildRailDepotWindow::Hotkey::ROTATE:
|
||||
if (_build_depot_direction < DIAGDIR_END) {
|
||||
this->RaiseWidget(_build_depot_direction + WID_BRAD_DEPOT_NE);
|
||||
_build_depot_direction = ChangeDiagDir(_build_depot_direction, DIAGDIRDIFF_90RIGHT);
|
||||
this->LowerWidget(_build_depot_direction + WID_BRAD_DEPOT_NE);
|
||||
} else {
|
||||
citymania::RotateAutodetection();
|
||||
}
|
||||
this->SetDirty();
|
||||
return ES_HANDLED;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
return ES_NOT_HANDLED;
|
||||
}
|
||||
|
||||
static HotkeyList hotkeys;
|
||||
/* CityMania code end */
|
||||
};
|
||||
|
||||
/* CityMania code start */
|
||||
static Hotkey build_depot_hotkeys[] = {
|
||||
Hotkey(CM_WKC_MOUSE_MIDDLE, "rotate", (int)BuildRailDepotWindow::Hotkey::ROTATE),
|
||||
HOTKEY_LIST_END
|
||||
};
|
||||
HotkeyList BuildRailDepotWindow::hotkeys("cm_build_rail_depot", build_depot_hotkeys);
|
||||
/* CityMania code end */
|
||||
|
||||
/** Nested widget definition of the build rail depot window */
|
||||
static const NWidgetPart _nested_build_depot_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
@@ -2159,7 +2221,8 @@ static WindowDesc _build_depot_desc(
|
||||
WDP_AUTO, nullptr, 0, 0,
|
||||
WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_build_depot_widgets, lengthof(_nested_build_depot_widgets)
|
||||
_nested_build_depot_widgets, lengthof(_nested_build_depot_widgets),
|
||||
&BuildRailDepotWindow::hotkeys // CityMania addition
|
||||
);
|
||||
|
||||
static void ShowBuildTrainDepotPicker(Window *parent)
|
||||
|
||||
@@ -36,7 +36,8 @@ void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y)
|
||||
SetDParam(0, v->engine_type);
|
||||
SetDParam(1, v->build_year);
|
||||
SetDParam(2, v->value);
|
||||
DrawString(left, right, y + y_offset, STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
if (_settings_client.gui.newgrf_developer_tools) SetDParam(3, v->index); // CM
|
||||
DrawString(left, right, y + y_offset, _settings_client.gui.newgrf_developer_tools ? STR_CM_VEHICLE_INFO_BUILT_VALUE_WITH_ID : STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
|
||||
if (v->HasArticulatedPart()) {
|
||||
CargoArray max_cargo;
|
||||
|
||||
@@ -66,7 +66,8 @@ void DrawShipDetails(const Vehicle *v, int left, int right, int y)
|
||||
SetDParam(0, v->engine_type);
|
||||
SetDParam(1, v->build_year);
|
||||
SetDParam(2, v->value);
|
||||
DrawString(left, right, y, STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
if (_settings_client.gui.newgrf_developer_tools) SetDParam(3, v->index); // CM
|
||||
DrawString(left, right, y, _settings_client.gui.newgrf_developer_tools ? STR_CM_VEHICLE_INFO_BUILT_VALUE_WITH_ID : STR_VEHICLE_INFO_BUILT_VALUE);
|
||||
|
||||
SetDParam(0, v->cargo_type);
|
||||
SetDParam(1, v->cargo_cap);
|
||||
|
||||
@@ -60,6 +60,13 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageTyp
|
||||
TileIndex tile = TileVirtXY(_thd.pos.x, _thd.pos.y);
|
||||
CargoTypes cargo_mask = 0;
|
||||
if (_thd.drawstyle == HT_RECT && tile < MapSize()) {
|
||||
/* CityMania code begin */
|
||||
if (supplies) {
|
||||
auto s = citymania::GetStationCoverageProductionText(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE, rad, sct);
|
||||
return DrawStringMultiLine(left, right, top, INT32_MAX, s.c_str());
|
||||
}
|
||||
/* CityMania code end */
|
||||
|
||||
CargoArray cargoes;
|
||||
if (supplies) {
|
||||
cargoes = GetProductionAroundTiles(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE, rad);
|
||||
@@ -146,10 +153,13 @@ static void FindStationsAroundSelection()
|
||||
*/
|
||||
void CheckRedrawStationCoverage(const Window *w)
|
||||
{
|
||||
/* CityMania code begin */
|
||||
if (_settings_client.gui.cm_use_improved_station_join) {
|
||||
citymania::CheckRedrawStationCoverage();
|
||||
if (citymania::CheckRedrawStationCoverage()) w->SetDirty();
|
||||
return;
|
||||
}
|
||||
/* CityMania code end */
|
||||
|
||||
/* Test if ctrl state changed */
|
||||
static bool _last_fn_pressed;
|
||||
if (citymania::_fn_mod != _last_fn_pressed) {
|
||||
|
||||
@@ -4143,3 +4143,7 @@ void ResetHouses()
|
||||
/* Reset any overrides that have been set. */
|
||||
_house_mngr.ResetOverride();
|
||||
}
|
||||
|
||||
namespace citymania {
|
||||
auto UpdateTownGrowthRate = &::UpdateTownGrowthRate;
|
||||
}
|
||||
|
||||
@@ -223,15 +223,18 @@ static void TrainDetailsCargoTab(const CargoSummaryItem *item, int left, int rig
|
||||
*/
|
||||
static void TrainDetailsInfoTab(const Vehicle *v, int left, int right, int y)
|
||||
{
|
||||
|
||||
if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) {
|
||||
SetDParam(0, v->engine_type);
|
||||
SetDParam(1, v->value);
|
||||
DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE);
|
||||
if (_settings_client.gui.newgrf_developer_tools) SetDParam(2, v->index); // CM
|
||||
DrawString(left, right, y, _settings_client.gui.newgrf_developer_tools ? STR_CM_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_WITH_ID : STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE);
|
||||
} else {
|
||||
SetDParam(0, v->engine_type);
|
||||
SetDParam(1, v->build_year);
|
||||
SetDParam(2, v->value);
|
||||
DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE);
|
||||
if (_settings_client.gui.newgrf_developer_tools) SetDParam(3, v->index); // CM
|
||||
DrawString(left, right, y, _settings_client.gui.newgrf_developer_tools ? STR_CM_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE_WITH_ID : STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -354,7 +354,8 @@ static void QZ_MouseMovedEvent(int x, int y)
|
||||
}
|
||||
|
||||
|
||||
static void QZ_MouseButtonEvent(int button, BOOL down)
|
||||
static void
|
||||
QZ_MouseButtonEvent(int button, BOOL down)
|
||||
{
|
||||
switch (button) {
|
||||
case 0:
|
||||
@@ -376,6 +377,18 @@ static void QZ_MouseButtonEvent(int button, BOOL down)
|
||||
}
|
||||
HandleMouseEvents();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0);
|
||||
break;
|
||||
|
||||
default: {
|
||||
int cm_button = CM_WKC_MOUSE_OTHER_START + button - 3;
|
||||
if (!down && cm_button >= CM_WKC_MOUSE_OTHER_START && cm_button < CM_WKC_MOUSE_OTHER_END) {
|
||||
HandleKeypress(cm_button, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,11 +498,11 @@ static bool QZ_PollEvent()
|
||||
QZ_MouseButtonEvent(1, NO);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
// #if 0 CityMania uses this!
|
||||
/* This is not needed since openttd currently only use two buttons */
|
||||
case NSOtherMouseDown:
|
||||
pt = QZ_GetMouseLocation(event);
|
||||
if (!QZ_MouseIsInsideView(&pt)) {
|
||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
||||
if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
|
||||
[ NSApp sendEvent:event ];
|
||||
break;
|
||||
}
|
||||
@@ -499,8 +512,8 @@ static bool QZ_PollEvent()
|
||||
break;
|
||||
|
||||
case NSOtherMouseUp:
|
||||
pt = QZ_GetMouseLocation(event);
|
||||
if (!QZ_MouseIsInsideView(&pt)) {
|
||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
||||
if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
|
||||
[ NSApp sendEvent:event ];
|
||||
break;
|
||||
}
|
||||
@@ -508,7 +521,7 @@ static bool QZ_PollEvent()
|
||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
||||
QZ_MouseButtonEvent([ event buttonNumber ], NO);
|
||||
break;
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
case NSKeyDown: {
|
||||
/* Quit, hide and minimize */
|
||||
|
||||
@@ -417,7 +417,7 @@ bool VideoDriver_SDL_Base::PollEvent()
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (_rightclick_emulate && SDL_GetModState() & KMOD_CTRL) {
|
||||
if (_rightclick_emulate && (SDL_GetModState() & KMOD_CTRL) && ev.button.button == SDL_BUTTON_LEFT) {
|
||||
ev.button.button = SDL_BUTTON_RIGHT;
|
||||
}
|
||||
|
||||
@@ -437,6 +437,17 @@ bool VideoDriver_SDL_Base::PollEvent()
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (ev.button.button == SDL_BUTTON_MIDDLE) {
|
||||
HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0);
|
||||
break;
|
||||
} else if (ev.button.button > SDL_BUTTON_RIGHT) {
|
||||
int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 4;
|
||||
if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) {
|
||||
HandleKeypress(button, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_rightclick_emulate) {
|
||||
_right_button_down = false;
|
||||
_left_button_down = false;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "sdl_v.h"
|
||||
#include <SDL.h>
|
||||
|
||||
#include "../../citymania/cm_hotkeys.hpp"
|
||||
#include "../citymania/cm_hotkeys.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
@@ -500,7 +500,7 @@ bool VideoDriver_SDL::PollEvent()
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (_rightclick_emulate && SDL_GetModState() & KMOD_CTRL) {
|
||||
if (_rightclick_emulate && (SDL_GetModState() & KMOD_CTRL) && ev.button.button == SDL_BUTTON_LEFT) {
|
||||
ev.button.button = SDL_BUTTON_RIGHT;
|
||||
}
|
||||
|
||||
@@ -523,6 +523,17 @@ bool VideoDriver_SDL::PollEvent()
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (ev.button.button == SDL_BUTTON_MIDDLE) {
|
||||
HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0);
|
||||
break;
|
||||
} else if (ev.button.button > SDL_BUTTON_WHEELDOWN) {
|
||||
int button = CM_WKC_MOUSE_OTHER_START + ev.button.button - 4;
|
||||
if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) {
|
||||
HandleKeypress(button, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_rightclick_emulate) {
|
||||
_right_button_down = false;
|
||||
_left_button_down = false;
|
||||
|
||||
@@ -453,6 +453,22 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
HandleMouseEvents();
|
||||
return 0;
|
||||
|
||||
/* CityMania code start */
|
||||
case WM_MBUTTONUP:
|
||||
ReleaseCapture();
|
||||
HandleKeypress(CM_WKC_MOUSE_MIDDLE, 0);
|
||||
return 0;
|
||||
|
||||
case WM_XBUTTONUP: {
|
||||
ReleaseCapture();
|
||||
int button = CM_WKC_MOUSE_OTHER_START + GET_XBUTTON_WPARAM(wParam) - 1;
|
||||
if (button >= CM_WKC_MOUSE_OTHER_START && button < CM_WKC_MOUSE_OTHER_END) {
|
||||
HandleKeypress(button, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* CityMania code end */
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
UndrawMouseCursor();
|
||||
_cursor.in_window = false;
|
||||
|
||||
@@ -2983,6 +2983,7 @@ static void MouseLoop(MouseClick click, int mousewheel)
|
||||
case MC_HOVER:
|
||||
DispatchHoverEvent(w, x - w->left, y - w->top);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user