|
@@ -84,97 +84,97 @@ void UpdateWaypointSign(Waypoint *wp)
|
|
|
void RedrawWaypointSign(Waypoint *wp)
|
|
|
{
|
|
|
MarkAllViewportsDirty(
|
|
|
wp->sign.left - 6,
|
|
|
wp->sign.top,
|
|
|
wp->sign.left + (wp->sign.width_1 << 2) + 12,
|
|
|
wp->sign.top + 48);
|
|
|
}
|
|
|
|
|
|
/* Update all signs */
|
|
|
void UpdateAllWaypointSigns(void)
|
|
|
{
|
|
|
Waypoint *wp;
|
|
|
|
|
|
FOR_ALL_WAYPOINTS(wp) {
|
|
|
if (wp->xy)
|
|
|
UpdateWaypointSign(wp);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Set the default name for a waypoint */
|
|
|
void MakeDefaultWaypointName(Waypoint *wp)
|
|
|
{
|
|
|
Waypoint *local_wp;
|
|
|
bool used_waypoint[MAX_WAYPOINTS_PER_TOWN];
|
|
|
int i;
|
|
|
|
|
|
wp->town_index = ClosestTownFromTile(wp->xy, (uint)-1)->index;
|
|
|
|
|
|
memset(used_waypoint, 0, sizeof(used_waypoint));
|
|
|
|
|
|
/* Find an unused waypoint number belonging to this town */
|
|
|
FOR_ALL_WAYPOINTS(local_wp) {
|
|
|
if (wp == local_wp)
|
|
|
continue;
|
|
|
|
|
|
if (local_wp->xy && local_wp->string == STR_NULL && local_wp->town_index == wp->town_index)
|
|
|
used_waypoint[local_wp->town_cn] = true;
|
|
|
}
|
|
|
|
|
|
/* Find an empty spot */
|
|
|
for (i = 0; used_waypoint[i] && i < MAX_WAYPOINTS_PER_TOWN; i++) {}
|
|
|
|
|
|
wp->string = STR_NULL;
|
|
|
wp->town_cn = i;
|
|
|
}
|
|
|
|
|
|
/* Find a deleted waypoint close to a tile. */
|
|
|
static Waypoint *FindDeletedWaypointCloseTo(uint tile)
|
|
|
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
|
|
|
{
|
|
|
Waypoint *wp, *best = NULL;
|
|
|
uint thres = 8, cur_dist;
|
|
|
|
|
|
FOR_ALL_WAYPOINTS(wp) {
|
|
|
if (wp->deleted && wp->xy) {
|
|
|
cur_dist = DistanceManhattan(tile, wp->xy);
|
|
|
if (cur_dist < thres) {
|
|
|
thres = cur_dist;
|
|
|
best = wp;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return best;
|
|
|
}
|
|
|
|
|
|
/** Convert existing rail to waypoint. Eg build a waypoint station over
|
|
|
* piece of rail
|
|
|
* @param x,y coordinates where waypoint will be built
|
|
|
* @param p1 graphics for waypoint type, bit 8 signifies custom waypoint gfx (& 0x100)
|
|
|
* @param p2 unused
|
|
|
*/
|
|
|
int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
TileIndex tile = TILE_FROM_XY(x, y);
|
|
|
Waypoint *wp;
|
|
|
uint tileh;
|
|
|
uint dir;
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
|
|
|
|
|
/* if custom gfx are used, make sure it is within bounds */
|
|
|
if (p1 > 0x100 + (uint)GetCustomStationsCount(STAT_CLASS_WAYP)) return CMD_ERROR;
|
|
|
|
|
|
if (!IsTileType(tile, MP_RAILWAY) || ((dir = 0, _map5[tile] != 1) && (dir = 1, _map5[tile] != 2)))
|
|
|
return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
|
|
|
|
|
|
if (!CheckTileOwnership(tile))
|
|
|
return CMD_ERROR;
|
|
|
|
|
|
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
|
|
|
|
|
tileh = GetTileSlope(tile, NULL);
|
|
|
if (tileh != 0) {
|
|
|
if (!_patches.build_on_slopes || tileh & 0x10 || !(tileh & (0x3 << dir)) || !(tileh & ~(0x3 << dir)))
|
|
|
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
|
|
|
}
|
|
@@ -198,189 +198,189 @@ int32 CmdBuildTrainWaypoint(int x, int y
|
|
|
_map3_hi[tile] = p1 & 0xff;
|
|
|
}
|
|
|
|
|
|
wp->deleted = 0;
|
|
|
wp->xy = tile;
|
|
|
wp->build_date = _date;
|
|
|
|
|
|
if (wp->town_index == STR_NULL)
|
|
|
MakeDefaultWaypointName(wp);
|
|
|
|
|
|
UpdateWaypointSign(wp);
|
|
|
RedrawWaypointSign(wp);
|
|
|
}
|
|
|
|
|
|
return _price.build_train_depot;
|
|
|
}
|
|
|
|
|
|
/* Internal handler to delete a waypoint */
|
|
|
static void DoDeleteWaypoint(Waypoint *wp)
|
|
|
{
|
|
|
Order order;
|
|
|
|
|
|
wp->xy = 0;
|
|
|
|
|
|
order.type = OT_GOTO_WAYPOINT;
|
|
|
order.station = wp->index;
|
|
|
DeleteDestinationFromVehicleOrder(order);
|
|
|
|
|
|
if (wp->string != STR_NULL)
|
|
|
DeleteName(wp->string);
|
|
|
|
|
|
RedrawWaypointSign(wp);
|
|
|
}
|
|
|
|
|
|
/* Daily loop for waypoints */
|
|
|
void WaypointsDailyLoop(void)
|
|
|
{
|
|
|
Waypoint *wp;
|
|
|
|
|
|
/* Check if we need to delete a waypoint */
|
|
|
FOR_ALL_WAYPOINTS(wp) {
|
|
|
if (wp->deleted && !--wp->deleted) {
|
|
|
DoDeleteWaypoint(wp);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Remove a waypoint */
|
|
|
int32 RemoveTrainWaypoint(uint tile, uint32 flags, bool justremove)
|
|
|
int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove)
|
|
|
{
|
|
|
Waypoint *wp;
|
|
|
|
|
|
/* Make sure it's a waypoint */
|
|
|
if (!IsTileType(tile, MP_RAILWAY) || !IsRailWaypoint(_map5[tile]))
|
|
|
return CMD_ERROR;
|
|
|
|
|
|
if (!CheckTileOwnership(tile) && !(_current_player == OWNER_WATER))
|
|
|
return CMD_ERROR;
|
|
|
|
|
|
if (!EnsureNoVehicle(tile))
|
|
|
return CMD_ERROR;
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
int direction = _map5[tile] & RAIL_WAYPOINT_TRACK_MASK;
|
|
|
|
|
|
wp = GetWaypointByTile(tile);
|
|
|
|
|
|
wp->deleted = 30; // let it live for this many days before we do the actual deletion.
|
|
|
RedrawWaypointSign(wp);
|
|
|
|
|
|
if (justremove) {
|
|
|
ModifyTile(tile, MP_MAP5, 1<<direction);
|
|
|
_map3_lo[tile] &= ~16;
|
|
|
_map3_hi[tile] = 0;
|
|
|
} else {
|
|
|
DoClearSquare(tile);
|
|
|
SetSignalsOnBothDir(tile, direction);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return _price.remove_train_depot;
|
|
|
}
|
|
|
|
|
|
/** Delete a waypoint
|
|
|
* @param x,y coordinates where waypoint is to be deleted
|
|
|
* @param p1 unused
|
|
|
* @param p2 unused
|
|
|
*/
|
|
|
int32 CmdRemoveTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
TileIndex tile = TILE_FROM_XY(x,y);
|
|
|
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
|
|
return RemoveTrainWaypoint(tile, flags, true);
|
|
|
}
|
|
|
|
|
|
/** Rename a waypoint.
|
|
|
* @param x,y unused
|
|
|
* @param p1 id of waypoint
|
|
|
* @param p2 unused
|
|
|
*/
|
|
|
int32 CmdRenameWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
Waypoint *wp;
|
|
|
StringID str;
|
|
|
|
|
|
if (!IsWaypointIndex(p1)) return CMD_ERROR;
|
|
|
|
|
|
if (_cmd_text[0] != '\0') {
|
|
|
str = AllocateNameUnique(_cmd_text, 0);
|
|
|
if (str == 0)
|
|
|
return CMD_ERROR;
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
wp = GetWaypoint(p1);
|
|
|
if (wp->string != STR_NULL)
|
|
|
DeleteName(wp->string);
|
|
|
|
|
|
wp->string = str;
|
|
|
wp->town_cn = 0;
|
|
|
|
|
|
UpdateWaypointSign(wp);
|
|
|
MarkWholeScreenDirty();
|
|
|
} else {
|
|
|
DeleteName(str);
|
|
|
}
|
|
|
} else {
|
|
|
if (flags & DC_EXEC) {
|
|
|
wp = GetWaypoint(p1);
|
|
|
if (wp->string != STR_NULL)
|
|
|
DeleteName(wp->string);
|
|
|
|
|
|
MakeDefaultWaypointName(wp);
|
|
|
UpdateWaypointSign(wp);
|
|
|
MarkWholeScreenDirty();
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/* This hacks together some dummy one-shot Station structure for a waypoint. */
|
|
|
Station *ComposeWaypointStation(uint tile)
|
|
|
Station *ComposeWaypointStation(TileIndex tile)
|
|
|
{
|
|
|
Waypoint *wp = GetWaypointByTile(tile);
|
|
|
static Station stat;
|
|
|
|
|
|
stat.train_tile = stat.xy = wp->xy;
|
|
|
stat.town = GetTown(wp->town_index);
|
|
|
stat.string_id = wp->string == STR_NULL ? /* FIXME? */ 0 : wp->string;
|
|
|
stat.build_date = wp->build_date;
|
|
|
stat.class_id = 6;
|
|
|
stat.stat_id = wp->stat_id;
|
|
|
|
|
|
return &stat;
|
|
|
}
|
|
|
|
|
|
extern uint16 _custom_sprites_base;
|
|
|
|
|
|
/* Draw a waypoint */
|
|
|
void DrawWaypointSprite(int x, int y, int stat_id, int railtype)
|
|
|
{
|
|
|
StationSpec *stat;
|
|
|
uint32 relocation;
|
|
|
DrawTileSprites *cust;
|
|
|
DrawTileSeqStruct const *seq;
|
|
|
uint32 ormod, img;
|
|
|
|
|
|
ormod = SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player));
|
|
|
|
|
|
x += 33;
|
|
|
y += 17;
|
|
|
|
|
|
/* draw default waypoint graphics of ID 0 */
|
|
|
if (stat_id == 0) {
|
|
|
const DrawTrackSeqStruct *dtss = _track_depot_layout_table[4];
|
|
|
|
|
|
img = dtss++->image;
|
|
|
if (img & 0x8000) img = (img & 0x7FFF) + railtype*TRACKTYPE_SPRITE_PITCH;
|
|
|
DrawSprite(img, x, y);
|
|
|
|
|
|
for (; dtss->image != 0; dtss++) {
|
|
|
Point pt = RemapCoords(dtss->subcoord_x, dtss->subcoord_y, 0);
|
|
|
img = dtss->image;
|
|
|
if (img & 0x8000) img |= ormod;
|
|
|
DrawSprite(img, x + pt.x, y + pt.y);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
stat = GetCustomStation(STAT_CLASS_WAYP, stat_id - 1);
|