diff options
author | Darkvater <Darkvater@openttd.org> | 2005-05-09 22:33:00 +0000 |
---|---|---|
committer | Darkvater <Darkvater@openttd.org> | 2005-05-09 22:33:00 +0000 |
commit | 6d349b6284f2d7fe65517b03bb310eb508eb3d3a (patch) | |
tree | adf0a3467d8519f1ef67e90a0a06731ea8c4dc1a | |
parent | f9fdddb0ad04bb3e1c441884696b08182b82e447 (diff) | |
download | openttd-6d349b6284f2d7fe65517b03bb310eb508eb3d3a.tar.xz |
(svn r2288) - CodeChange: protected the next batch of commands (41 so far, out of 115).
- CodeChange: changed the airport gui airport-type checking. Added function GetValidAirports() that returns bitmasked availibility, is also used for checking.
- CodeChange: to check tree-planting, 2 const arrays have been moved to table/tree_land.h (type and count)
- CodeChange: added IsTownIndex() in following of IsStationIndex(), etc.
- Fix (regression): road tunnels did not work anymore, forgot that their type was 0x200 (documented now)
-rw-r--r-- | airport.h | 16 | ||||
-rw-r--r-- | airport_gui.c | 25 | ||||
-rw-r--r-- | command.c | 2 | ||||
-rw-r--r-- | misc_gui.c | 3 | ||||
-rw-r--r-- | road_cmd.c | 187 | ||||
-rw-r--r-- | station_cmd.c | 79 | ||||
-rw-r--r-- | table/tree_land.h | 9 | ||||
-rw-r--r-- | town.h | 5 | ||||
-rw-r--r-- | train_cmd.c | 102 | ||||
-rw-r--r-- | tree_cmd.c | 20 | ||||
-rw-r--r-- | tunnelbridge_cmd.c | 4 | ||||
-rw-r--r-- | water_cmd.c | 25 |
12 files changed, 261 insertions, 216 deletions
@@ -48,4 +48,20 @@ void InitializeAirports(void); void UnInitializeAirports(void); const AirportFTAClass* GetAirport(const byte airport_type); +/** Get buildable airport bitmask. + * @return get all buildable airports at this given time, bitmasked. + * Bit 0 means the small airport is buildable, etc. + * @todo set availability of airports by year, instead of airplane + */ +static inline uint32 GetValidAirports(void) +{ + uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft() + + // 1980-1-1 is --> 21915 + // 1990-1-1 is --> 25568 + if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980 + if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990 + return bytemask; +} + #endif /* AIRPORT_H */ diff --git a/airport_gui.c b/airport_gui.c index f807ed2ee..cbb904fba 100644 --- a/airport_gui.c +++ b/airport_gui.c @@ -135,24 +135,25 @@ void ShowBuildAirToolbar(void) static void BuildAirportPickerWndProc(Window *w, WindowEvent *e) { - switch(e->event) { + switch (e->event) { case WE_PAINT: { int sel; int rad = 4; // default catchment radious + uint32 avail_airports; - if (WP(w,def_d).close) - return; - w->disabled_state = 0; + if (WP(w,def_d).close) return; sel = _selected_airport_type; - // FIXME -- BuildAirportPickerWndProc - set availability of airports by year, instead of airplane - if (!(_avail_aircraft & 1)) { w->disabled_state |= (1<<3); if (sel == AT_SMALL) sel = AT_LARGE; } - if (!(_avail_aircraft & 2)) { w->disabled_state |= (1<<4); if (sel == AT_LARGE) sel = AT_SMALL; } - if (!(_avail_aircraft & 4)) { w->disabled_state |= (1<<5); } // heliport - // 1980-1-1 is --> 21915 - // 1990-1-1 is --> 25568 - if (_date < 21915) {w->disabled_state |= (1<<6);} // metropilitan airport 1980 - if (_date < 25568) {w->disabled_state |= (1<<7);} // international airport 1990 + avail_airports = GetValidAirports(); + + if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE; + if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL; + + /* 'Country Airport' starts at widget 3, and if its bit is set, it is available, + * so take its opposite value to set the disabled_state. There are only 5 available + * airports, so XOr with 0x1F (1 1111) */ + w->disabled_state = (avail_airports ^ 0x1F) << 3; + _selected_airport_type = sel; // select default the coverage area to 'Off' (8) w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage); @@ -189,7 +189,6 @@ static CommandProc * const _command_proc_table[] = { NULL, /* 20 */ CmdBuildRoadStop, /* 21 */ NULL, /* 22 */ - /***************************************************/ CmdBuildLongRoad, /* 23 */ CmdRemoveLongRoad, /* 24 */ CmdBuildRoad, /* 25 */ @@ -209,6 +208,7 @@ static CommandProc * const _command_proc_table[] = { CmdTrainGotoDepot, /* 39 */ CmdForceTrainProceed, /* 40 */ CmdReverseTrainDirection, /* 41 */ + /***************************************************/ CmdModifyOrder, /* 42 */ CmdSkipOrder, /* 43 */ diff --git a/misc_gui.c b/misc_gui.c index 887e26e3c..e30e0b0b3 100644 --- a/misc_gui.c +++ b/misc_gui.c @@ -5,6 +5,7 @@ #include "strings.h" #include "table/sprites.h" #include "table/strings.h" +#include "table/tree_land.h" #include "map.h" #include "window.h" #include "gui.h" @@ -271,8 +272,6 @@ void ShowAboutWindow(void) static int _tree_to_plant; -static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32}; -static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9}; static const uint32 _tree_sprites[] = { 0x655,0x663,0x678,0x62B,0x647,0x639,0x64E,0x632,0x67F,0x68D,0x69B,0x6A9, 0x6AF,0x6D2,0x6D9,0x6C4,0x6CB,0x6B6,0x6BD,0x6E0, diff --git a/road_cmd.c b/road_cmd.c index 762547c2e..0a89492da 100644 --- a/road_cmd.c +++ b/road_cmd.c @@ -124,8 +124,10 @@ uint GetRoadBitsByTile(TileIndex tile) return (byte)(r | (r >> 8)); } -/* Delete a piece of road - * p1 = piece type +/** Delete a piece of road. + * @param x,y tile coordinates for road construction + * @param p1 road piece flags + * @param p2 unused */ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -137,13 +139,16 @@ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) TileIndex tile; byte owner; Town *t; - /* true if the roadpiece was always removeable, - false if it was a center piece. Affects town ratings drop - */ + /* true if the roadpiece was always removeable, + * false if it was a center piece. Affects town ratings drop */ bool edge_road; + byte pieces = (byte)p1; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + /* Road pieces are max 4 bitset values (NE, NW, SE, SW) */ + if (pieces >> 4) return CMD_ERROR; + FindLandscapeHeight(&ti, x, y); tile = ti.tile; @@ -169,10 +174,9 @@ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) { bool b; _road_special_gettrackstatus = true; - b = CheckAllowRemoveRoad(tile, p1, &edge_road); + b = CheckAllowRemoveRoad(tile, pieces, &edge_road); _road_special_gettrackstatus = false; - if (!b) - return CMD_ERROR; + if (!b) return CMD_ERROR; } if (ti.type == MP_TUNNELBRIDGE) { @@ -180,9 +184,9 @@ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; if ((ti.map5 & 0xE9) == 0xE8) { - if (p1 & 10) goto return_error; + if (pieces & 10) goto return_error; } else if ((ti.map5 & 0xE9) == 0xE9) { - if (p1 & 5) goto return_error; + if (pieces & 5) goto return_error; } else goto return_error; @@ -202,7 +206,7 @@ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) // XXX - change cascading ifs to switch when doing rewrite if ((ti.map5 & 0xF0) == 0) { // normal road - uint c = p1, t2; + byte c = pieces, t2; if (ti.tileh != 0 && (ti.map5 == 5 || ti.map5 == 10)) { c |= (c & 0xC) >> 2; @@ -235,10 +239,10 @@ int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (!(ti.map5 & 8)) { c = 2; - if (p1 & 5) goto return_error; + if (pieces & 5) goto return_error; } else { c = 1; - if (p1 & 10) goto return_error; + if (pieces & 10) goto return_error; } cost = _price.remove_road * 2; @@ -340,30 +344,33 @@ static uint32 CheckRoadSlope(int tileh, byte *pieces, byte existing) return CMD_ERROR; } -/* Build a piece of road - * p1 = piece flags - * p2 = town which is building the road +/** Build a piece of road. + * @param x,y tile coordinates for road construction + * @param p1 road piece flags + * @param p2 the town that is building the road (0 if not applicable) */ - int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) { TileInfo ti; int32 cost; byte pieces = (byte)p1, existing = 0; - uint tile; + TileIndex tile; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero + * if a non-player is building the road */ + if ((pieces >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR; + FindLandscapeHeight(&ti, x, y); tile = ti.tile; // allow building road under bridge - if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) - return CMD_ERROR; + if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) return CMD_ERROR; if (ti.type == MP_STREET) { if (!(ti.map5 & 0xF0)) { - if ( ((pieces) & (byte)(ti.map5)) == (pieces)) + if ( (pieces & (byte)(ti.map5)) == (pieces)) return_cmd_error(STR_1007_ALREADY_BUILT); existing = ti.map5; } else { @@ -433,12 +440,12 @@ int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) return cost; } else { do_clear:; - if (DoCommandByTile(tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) + if (CmdFailed(DoCommandByTile(tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR))) return CMD_ERROR; } cost = CheckRoadSlope(ti.tileh, &pieces, existing); - if (cost == CMD_ERROR) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION); + if (CmdFailed(cost)) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION); if (cost && (!_patches.build_on_slopes || (!_patches.ainew_active && _is_ai_player))) return CMD_ERROR; @@ -494,123 +501,130 @@ int32 DoConvertStreetRail(uint tile, uint totype, bool exec) } -// Build a long piece of road. -// x,y = end tile -// p1 = start tile -// p2&1 = start tile starts in the 2nd half -// p2&2 = end tile starts in the 2nd half -// p2&4 = direction (0 = along x, 1=along y) +/** Build a long piece of road. + * @param x,y end tile of drag + * @param p1 start tile of drag + * @param p2 various bitstuffed elements + * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) + * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) + * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) + */ int32 CmdBuildLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - uint start_tile, end_tile, tile; - int mode; - int32 cost,ret; + TileIndex start_tile, end_tile, tile; + int32 cost, ret; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + if (p1 > MapSize()) return CMD_ERROR; + start_tile = p1; end_tile = TILE_FROM_XY(x, y); - if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) { - uint t = start_tile; start_tile = end_tile; end_tile = t; + /* Only drag in X or Y direction dictated by the direction variable */ + if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis + if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis + + /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ + if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) { + TileIndex t = start_tile; + start_tile = end_tile; + end_tile = t; p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0; } cost = 0; tile = start_tile; // Start tile is the small number. - for(;;) { - mode = (p2&4) ? 5 : 10; - - if (tile == start_tile && (p2&1)) - mode &= (4+2); - else if (tile == end_tile && !(p2&2)) - mode &= (1+8); - - ret = DoCommandByTile(tile, mode, 0, flags, CMD_BUILD_ROAD); - if (ret == CMD_ERROR) { - if (_error_message != STR_1007_ALREADY_BUILT) - return CMD_ERROR; - } else { + for (;;) { + uint bits = HASBIT(p2, 2) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE; + if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; + if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; + + ret = DoCommandByTile(tile, bits, 0, flags, CMD_BUILD_ROAD); + if (CmdFailed(ret)) { + if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; + } else cost += ret; - } - if (tile == end_tile) - break; + if (tile == end_tile) break; - tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0); + tile += HASBIT(p2, 2) ? TILE_XY(0, 1) : TILE_XY(1, 0); } - // already built? - if (cost == 0) - return CMD_ERROR; - - return cost; + return (cost == 0) ? CMD_ERROR : cost; } -// Remove a long piece of road. -// x,y = end tile -// p1 = start tile -// p2&1 = start tile starts in the 2nd half -// p2&2 = end tile starts in the 2nd half -// p2&4 = direction (0 = along x, 1=along y) +/** Remove a long piece of road. + * @param x,y end tile of drag + * @param p1 start tile of drag + * @param p2 various bitstuffed elements + * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) + * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) + * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) + */ int32 CmdRemoveLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - uint start_tile, end_tile, tile; - int32 cost,ret; + TileIndex start_tile, end_tile, tile; + int32 cost, ret; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + if (p1 > MapSize()) return CMD_ERROR; + start_tile = p1; end_tile = TILE_FROM_XY(x, y); - if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) { - uint t = start_tile; start_tile = end_tile; end_tile = t; + /* Only drag in X or Y direction dictated by the direction variable */ + if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis + if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis + + /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ + if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) { + TileIndex t = start_tile; + start_tile = end_tile; + end_tile = t; p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0; } cost = 0; tile = start_tile; // Start tile is the small number. - for(;;) { - uint bits = (p2 & 4) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE; - if (tile == end_tile && !(p2&2)) bits &= ROAD_NW | ROAD_NE; - if (tile == start_tile && (p2&1)) bits &= ROAD_SE | ROAD_SW; + for (;;) { + uint bits = HASBIT(p2, 2) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE; + if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; + if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; // try to remove the halves. if (bits) { ret = DoCommandByTile(tile, bits, 0, flags, CMD_REMOVE_ROAD); - if (ret != CMD_ERROR) - cost += ret; + if (!CmdFailed(ret)) cost += ret; } - if (tile == end_tile) - break; + if (tile == end_tile) break; - tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0); + tile += HASBIT(p2, 2) ? TILE_XY(0, 1) : TILE_XY(1, 0); } - // already built? - if (cost == 0) - return CMD_ERROR; - - return cost; + return (cost == 0) ? CMD_ERROR : cost; } -/* Build a road depot - * p1 - direction (0-3) - * p2 - unused +/** Build a road depot. + * @param x,y tile coordinates where the depot will be built + * @param p1 depot direction (0 through 3), where 0 is NW, 1 is NE, etc. + * @param p2 unused */ - int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { TileInfo ti; int32 cost; Depot *dep; - uint tile; + TileIndex tile; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + if (p2 > 3) return CMD_ERROR; // check direction + FindLandscapeHeight(&ti, x, y); tile = ti.tile; @@ -624,8 +638,7 @@ int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) } cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (cost == CMD_ERROR) - return CMD_ERROR; + if (CmdFailed(cost)) return CMD_ERROR; dep = AllocateDepot(); if (dep == NULL) diff --git a/station_cmd.c b/station_cmd.c index 2784d6568..c4ab26376 100644 --- a/station_cmd.c +++ b/station_cmd.c @@ -1432,7 +1432,7 @@ void FindRoadStationSpot(bool truck_station, Station *st, RoadStop ***currstop, /** Build a bus station * @param x,y coordinates to build bus station at - * @param p1 direction the busstop exit is pointing towards + * @param p1 busstop entrance direction (0 through 3), where 0 is NW, 1 is NE, etc. * @param p2 0 for Bus stops, 1 for truck stops */ int32 CmdBuildRoadStop(int x, int y, uint32 flags, uint32 p1, uint32 p2) @@ -1655,21 +1655,25 @@ static const byte * const _airport_map5_tiles[] = { _airport_map5_tiles_international, // International Airport (xlarge) }; -/* Place an Airport - * p1 - airport type - * p2 - unused +/** Place an Airport. + * @param x,y tile coordinates where airport will be built + * @param p1 airport type, @see airport.h + * @param p2 unused */ int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - uint tile; + TileIndex tile; Town *t; Station *st; int32 cost; - int w,h; + int w, h; bool airport_upgrade = true; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + /* Check if a valid, buildable airport was chosen for construction */ + if (!HASBIT(GetValidAirports(), p1)) return CMD_ERROR; + tile = TILE_FROM_XY(x,y); if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) @@ -1694,17 +1698,15 @@ int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2) h = _airport_size_y[p1]; cost = CheckFlatLandBelow(tile, w, h, flags, 0, NULL); - if (cost == CMD_ERROR) - return CMD_ERROR; + if (cost == CMD_ERROR) return CMD_ERROR; st = GetStationAround(tile, w, h, -1); - if (st == CHECK_STATIONS_ERR) - return CMD_ERROR; + if (st == CHECK_STATIONS_ERR) return CMD_ERROR; /* Find a station close to us */ if (st == NULL) { st = GetClosestStationFromTile(tile, 8, _current_player); - if (st!=NULL && st->facilities) st = NULL; + if (st != NULL && st->facilities) st = NULL; } if (st != NULL) { @@ -1720,8 +1722,7 @@ int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2) airport_upgrade = false; st = AllocateStation(); - if (st == NULL) - return CMD_ERROR; + if (st == NULL) return CMD_ERROR; st->town = t; @@ -1732,7 +1733,7 @@ int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2) // if airport type equals Heliport then generate // type 5 name, which is heliport, otherwise airport names (1) - if (!GenerateStationName(st, tile, p1 == AT_HELIPORT ? 5 : 1)) + if (!GenerateStationName(st, tile, (p1 == AT_HELIPORT) ? 5 : 1)) return CMD_ERROR; if (flags & DC_EXEC) @@ -1828,10 +1829,11 @@ END_TILE_LOOP(tile_cur, w,h,tile) return cost; } -/* Build a buoy - * p1,p2 unused +/** Build a buoy. + * @param x,y tile coordinates of bouy construction + * @param p1 unused + * @param p2 unused */ - int32 CmdBuildBuoy(int x, int y, uint32 flags, uint32 p1, uint32 p2) { TileInfo ti; @@ -1845,14 +1847,12 @@ int32 CmdBuildBuoy(int x, int y, uint32 flags, uint32 p1, uint32 p2) return_cmd_error(STR_304B_SITE_UNSUITABLE); st = AllocateStation(); - if (st == NULL) - return CMD_ERROR; + if (st == NULL) return CMD_ERROR; st->town = ClosestTownFromTile(ti.tile, (uint)-1); st->sign.width_1 = 0; - if (!GenerateStationName(st, ti.tile, 4)) - return CMD_ERROR; + if (!GenerateStationName(st, ti.tile, 4)) return CMD_ERROR; if (flags & DC_EXEC) { StationInitialize(st, ti.tile); @@ -1946,12 +1946,17 @@ static const TileIndexDiffC _dock_tileoffs_chkaround[] = { static const byte _dock_w_chk[4] = { 2,1,2,1 }; static const byte _dock_h_chk[4] = { 1,2,1,2 }; +/** Build a dock/haven. + * @param x,y tile coordinates where dock will be built + * @param p1 unused + * @param p2 unused + */ int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) { TileInfo ti; int direction; int32 cost; - uint tile, tile_cur; + TileIndex tile, tile_cur; Station *st; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); @@ -1964,25 +1969,20 @@ int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) (direction++,ti.tileh) != 6) return_cmd_error(STR_304B_SITE_UNSUITABLE); - if (!EnsureNoVehicle(ti.tile)) - return CMD_ERROR; + if (!EnsureNoVehicle(ti.tile)) return CMD_ERROR; cost = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (cost == CMD_ERROR) - return CMD_ERROR; + if (CmdFailed(cost)) return CMD_ERROR; tile_cur = (tile=ti.tile) + TileOffsByDir(direction); - if (!EnsureNoVehicle(tile_cur)) - return CMD_ERROR; + if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR; FindLandscapeHeightByTile(&ti, tile_cur); - if (ti.tileh != 0 || ti.type != MP_WATER) - return_cmd_error(STR_304B_SITE_UNSUITABLE); + if (ti.tileh != 0 || ti.type != MP_WATER) return_cmd_error(STR_304B_SITE_UNSUITABLE); cost = DoCommandByTile(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (cost == CMD_ERROR) - return CMD_ERROR; + if (CmdFailed(cost)) return CMD_ERROR; tile_cur = tile_cur + TileOffsByDir(direction); FindLandscapeHeightByTile(&ti, tile_cur); @@ -1993,8 +1993,7 @@ int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) st = GetStationAround( tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), _dock_w_chk[direction], _dock_h_chk[direction], -1); - if (st == CHECK_STATIONS_ERR) - return CMD_ERROR; + if (st == CHECK_STATIONS_ERR) return CMD_ERROR; /* Find a station close to us */ if (st == NULL) { @@ -2006,17 +2005,14 @@ int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (st->owner != OWNER_NONE && st->owner != _current_player) return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); - if (!CheckStationSpreadOut(st, tile, 1, 1)) - return CMD_ERROR; + if (!CheckStationSpreadOut(st, tile, 1, 1)) return CMD_ERROR; - if (st->dock_tile != 0) - return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK); + if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK); } else { Town *t; st = AllocateStation(); - if (st == NULL) - return CMD_ERROR; + if (st == NULL) return CMD_ERROR; st->town = t = ClosestTownFromTile(tile, (uint)-1); @@ -2025,8 +2021,7 @@ int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2) st->sign.width_1 = 0; - if (!GenerateStationName(st, tile, 3)) - return CMD_ERROR; + if (!GenerateStationName(st, tile, 3)) return CMD_ERROR; if (flags & DC_EXEC) StationInitialize(st, tile); diff --git a/table/tree_land.h b/table/tree_land.h index 7b3588a7c..f915ae68b 100644 --- a/table/tree_land.h +++ b/table/tree_land.h @@ -1,3 +1,6 @@ +#ifndef TREE_LAND_H +#define TREE_LAND_H + static const SpriteID _tree_sprites_1[4] = { 0x118D, 0x11A0, @@ -5,6 +8,9 @@ static const SpriteID _tree_sprites_1[4] = { 0x11C6, }; +static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32}; +static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9}; + static const byte _tree_layout_xy[4][8] = { {9, 3, 1, 8, 0, 0, 8, 9}, {4, 4, 9, 1, 6, 9, 0, 9}, @@ -211,3 +217,6 @@ static const PalSpriteID _tree_layout_sprite[164+(79-48+1)][4] = { { 0x716, 0x716, 0x6f3, 0x6ec}, /* 30 */ { 0x716, 0x701, 0x6fa, 0x716}, /* 31 */ }; + +#endif /* TREE_LAND_H */ + @@ -157,6 +157,11 @@ static inline uint16 GetTownPoolSize(void) return _town_pool.total_items; } +static inline bool IsTownIndex(uint index) +{ + return index < GetTownPoolSize(); +} + #define FOR_ALL_TOWNS_FROM(t, start) for (t = GetTown(start); t != NULL; t = (t->index + 1 < GetTownPoolSize()) ? GetTown(t->index + 1) : NULL) #define FOR_ALL_TOWNS(t) FOR_ALL_TOWNS_FROM(t, 0) diff --git a/train_cmd.c b/train_cmd.c index 7b8d06cc5..2a7693fc0 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -517,10 +517,11 @@ void AddRearEngineToMultiheadedTrain(Vehicle *v, Vehicle *u, bool building) VehiclePositionChanged(u); } -/* Build a railroad vehicle - * p1 = vehicle type id +/** Build a railroad vehicle. + * @param x,y tile coordinates (depot) where rail-vehicle is built + * @param p1 engine type id + * @param p2 unused */ - int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) { const RailVehicleInfo *rvi; @@ -530,8 +531,11 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) Engine *e; TileIndex tile = TILE_FROM_XY(x,y); + /* Check if the engine-type is valid (for the player) */ if (!IsEngineBuildable(p1, VEH_Train)) return CMD_ERROR; + /* Check if the train is actually being built in a depot belonging + * to the player. Doesn't matter if only the cost is queried */ if (!(flags & DC_QUERY_COST)) { if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR; if (_map_owner[tile] != _current_player) return CMD_ERROR; @@ -543,9 +547,7 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) rvi = RailVehInfo(p1); - if (rvi->flags & RVI_WAGON) { - return CmdBuildRailWagon(p1, tile, flags); - } + if (rvi->flags & RVI_WAGON) return CmdBuildRailWagon(p1, tile, flags); value = EstimateTrainCost(rvi); @@ -694,10 +696,12 @@ static Vehicle *FindGoodVehiclePos(const Vehicle *src) return NULL; } -/* p1 & 0xffff = source vehicle index - * p1 & 0xffff0000 = what wagon to put the wagon AFTER, - * 0xffff0000 to make a new line - * p2 & 1 = move all vehicles following the vehicle.. +/** Move a rail vehicle around inside the depot. + * @param x,y unused + * @param p1 various bitstuffed elements + * - p1 (bit 0 - 15) source vehicle index (p1 & 0xFFFF) + * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER (p1 & 0xFFFF0000) XXX - 0xFFFF0000 to make a new line + * @param p2 (bit 0) move all vehicles following the source vehicle */ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -721,8 +725,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) } // don't move the same vehicle.. - if (src == dst) - return 0; + if (src == dst) return 0; /* the player must be the owner */ if (!CheckOwnership(src->owner) || (dst!=NULL && !CheckOwnership(dst->owner))) @@ -741,16 +744,14 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) for (u = dst_head; u != NULL; u = u->next) u->first = NULL; } - /* check if all vehicles in the source train are stopped */ - if (CheckTrainStoppedInDepot(src_head) < 0) - return CMD_ERROR; + /* check if all vehicles in the source train are stopped inside a depot */ + if (CheckTrainStoppedInDepot(src_head) < 0) return CMD_ERROR; /* check if all the vehicles in the dest train are stopped, * and that the length of the dest train is no longer than XXX vehicles */ if (dst_head != NULL) { int num = CheckTrainStoppedInDepot(dst_head); - if (num < 0) - return CMD_ERROR; + if (num < 0) return CMD_ERROR; if (num > (_patches.mammoth_trains ? 100 : 9) && dst_head->subtype == TS_Front_Engine ) return_cmd_error(STR_8819_TRAIN_TOO_LONG); @@ -768,8 +769,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) } // when moving all wagons, we can't have the same src_head and dst_head - if (p2 & 1 && src_head == dst_head) - return 0; + if (HASBIT(p2, 0) && src_head == dst_head) return 0; // moving a loco to a new line?, then we need to assign a unitnumber. if (dst == NULL && src->subtype != TS_Front_Engine && is_loco) { @@ -784,7 +784,7 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) /* do it? */ if (flags & DC_EXEC) { - if (p2 & 1) { + if (HASBIT(p2, 0)) { // unlink ALL wagons if (src != src_head) { Vehicle *v = src_head; @@ -859,7 +859,11 @@ int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) return 0; } -/* p1 = train to start / stop */ +/** Start/Stop a train. + * @param x,y unused + * @param p1 train to start/stop + * @param p2 unused + */ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; @@ -868,8 +872,7 @@ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2) v = GetVehicle(p1); - if (v->type != VEH_Train || !CheckOwnership(v->owner)) - return CMD_ERROR; + if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; if (flags & DC_EXEC) { v->u.rail.days_since_order_progr = 0; @@ -901,15 +904,15 @@ static Vehicle *GetRearEngine(const Vehicle *v, uint16 engine) return NULL; } -/** - * Sell a (single) train wagon/engine. +/** Sell a (single) train wagon/engine. + * @param x,y unused * @param p1 the wagon/engine index * @param p2 the selling mode - * - 0: only sell the single dragged wagon/engine (and any belonging rear-engines) - * - 1: sell the vehicle and all vehicles following it in the chain - if the wagon is dragged, don't delete the possibly belonging rear-engine to some front - * - 2: when selling attached locos, rearrange all vehicles after it to separate lines; - * all wagons of the same type will go on the same line. Used by the AI currently + * - p2 = 0: only sell the single dragged wagon/engine (and any belonging rear-engines) + * - p2 = 1: sell the vehicle and all vehicles following it in the chain + if the wagon is dragged, don't delete the possibly belonging rear-engine to some front + * - p2 = 2: when selling attached locos, rearrange all vehicles after it to separate lines; + * all wagons of the same type will go on the same line. Used by the AI currently */ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) { @@ -920,16 +923,14 @@ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) v = GetVehicle(p1); - if (v->type != VEH_Train || !CheckOwnership(v->owner)) - return CMD_ERROR; + if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); first = GetFirstVehicleInChain(v); // make sure the vehicle is stopped in the depot - if (CheckTrainStoppedInDepot(first) < 0) - return CMD_ERROR; + if (CheckTrainStoppedInDepot(first) < 0) return CMD_ERROR; if ((flags & DC_EXEC) && v == first && first->subtype == TS_Front_Engine) { DeleteWindowById(WC_VEHICLE_VIEW, first->index); @@ -1226,8 +1227,12 @@ static void ReverseTrainDirection(Vehicle *v) CLRBIT(v->u.rail.flags, VRF_REVERSING); } -/* p1 = vehicle */ -int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) +/** Reverse train. + * @param x,y unused + * @param p1 train to reverse + * @param p2 unused + */ + int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; @@ -1235,16 +1240,14 @@ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) v = GetVehicle(p1); - if (v->type != VEH_Train || !CheckOwnership(v->owner)) - return CMD_ERROR; + if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; _error_message = STR_EMPTY; // if (v->u.rail.track & 0x80 || IsTileDepotType(v->tile, TRANSPORT_RAIL)) // return CMD_ERROR; - if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) - return CMD_ERROR; + if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) return CMD_ERROR; if (flags & DC_EXEC) { if (_patches.realistic_acceleration && v->cur_speed != 0) { @@ -1258,6 +1261,11 @@ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) return 0; } +/** Force a train through a red signal + * @param x,y unused + * @param p1 train to ignore the red signal + * @param p2 unused + */ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; @@ -1266,8 +1274,7 @@ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2) v = GetVehicle(p1); - if (v->type != VEH_Train || !CheckOwnership(v->owner)) - return CMD_ERROR; + if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50; @@ -1421,6 +1428,11 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) return tfdd; } +/** Send a train to a depot + * @param x,y unused + * @param p1 train to send to the depot + * @param p2 unused + */ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { Vehicle *v; @@ -1430,11 +1442,9 @@ int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) v = GetVehicle(p1); - if (v->type != VEH_Train || !CheckOwnership(v->owner)) - return CMD_ERROR; + if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR; - if (v->vehstatus & VS_CRASHED) - return CMD_ERROR; + if (v->vehstatus & VS_CRASHED) return CMD_ERROR; if (v->current_order.type == OT_GOTO_DEPOT) { if (flags & DC_EXEC) { diff --git a/tree_cmd.c b/tree_cmd.c index a29663d6f..921878ece 100644 --- a/tree_cmd.c +++ b/tree_cmd.c @@ -1,6 +1,7 @@ #include "stdafx.h" #include "ttd.h" #include "table/strings.h" +#include "table/tree_land.h" #include "map.h" #include "tile.h" #include "viewport.h" @@ -142,11 +143,11 @@ void GenerateTrees(void) } while (--i); } -/* Plant a tree - * p1 = tree type, -1 means random. - * p2 = end tile +/** Plant a tree. + * @param x,y start tile of area-drag of tree plantation + * @param p1 tree type, -1 means random. + * @param p2 end tile of area-drag */ - int32 CmdPlantTree(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) { int32 cost; @@ -155,7 +156,9 @@ int32 CmdPlantTree(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) int x; int y; - if (p2 >= MapSize()) return CMD_ERROR; + if (p2 > MapSize()) return CMD_ERROR; + /* Check the tree type. It can be random or some valid value within the current climate */ + if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_opt.landscape] >= _tree_count_by_landscape[_opt.landscape]) return CMD_ERROR; SET_EXPENSES_TYPE(EXPENSES_OTHER); @@ -254,8 +257,7 @@ int32 CmdPlantTree(int ex, int ey, uint32 flags, uint32 p1, uint32 p2) } } - if (cost == 0) return CMD_ERROR; - return cost; + return (cost == 0) ? CMD_ERROR : cost; } typedef struct TreeListEnt { @@ -263,10 +265,6 @@ typedef struct TreeListEnt { byte x,y; } TreeListEnt; - -#include "table/tree_land.h" - - static void DrawTile_Trees(TileInfo *ti) { uint16 m2; diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index 6cc1f946e..3fd0c92ca 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -533,7 +533,7 @@ static int32 DoBuildTunnel(int x, int y, int x2, int y2, uint32 flags, uint exc_ /** Build Tunnel. * @param x,y start tile coord of tunnel - * @param p1 railtype + * @param p1 railtype, 0x200 for road tunnel * @param p2 unused (XXX - ptr to uint that recieves end tile; wtf?????) */ int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) @@ -547,7 +547,7 @@ int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); - if (!ValParamRailtype(p1)) return CMD_ERROR; + if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; _build_tunnel_railtype = (byte)(p1 & 0xFF); _build_tunnel_bh = (byte)(p1 >> 8); diff --git a/water_cmd.c b/water_cmd.c index a3c8fcd3f..55a9e7188 100644 --- a/water_cmd.c +++ b/water_cmd.c @@ -22,42 +22,41 @@ static bool IsClearWaterTile(uint tile) return (ti.type == MP_WATER && ti.tileh == 0 && ti.map5 == 0); } -/* Build a ship depot - * p1 - direction +/** Build a ship depot. + * @param x,y tile coordinates where ship depot is built + * @param p1 depot direction (0 through 3), where 0 is NW, 1 is NE, etc. + * @param p2 unused */ - int32 CmdBuildShipDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) { - uint tile, tile2; + TileIndex tile, tile2; int32 cost, ret; Depot *depot; SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); + if (p1 > 3) return CMD_ERROR; + tile = TILE_FROM_XY(x,y); - if (!EnsureNoVehicle(tile)) - return CMD_ERROR; + if (!EnsureNoVehicle(tile)) return CMD_ERROR; tile2 = tile + (p1 ? TILE_XY(0,1) : TILE_XY(1,0)); - if (!EnsureNoVehicle(tile2)) - return CMD_ERROR; + if (!EnsureNoVehicle(tile2)) return CMD_ERROR; if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2)) return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER); ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (ret == CMD_ERROR) return CMD_ERROR; + if (CmdFailed(ret)) return CMD_ERROR; ret = DoCommandByTile(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (ret == CMD_ERROR) - return CMD_ERROR; + if (CmdFailed(ret)) return CMD_ERROR; // pretend that we're not making land from the water even though we actually are. cost = 0; depot = AllocateDepot(); - if (depot == NULL) - return CMD_ERROR; + if (depot == NULL) return CMD_ERROR; if (flags & DC_EXEC) { depot->xy = tile; |