コード例 #1
0
ファイル: newgrf_canal.cpp プロジェクト: dolly22/openttd-sai
static uint32 CanalGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
{
	TileIndex tile = object->u.canal.tile;

	switch (variable) {
		/* Height of tile */
		case 0x80: {
			uint z = GetTileZ(tile) / TILE_HEIGHT;
			/* Return consistent height within locks */
			if (IsTileType(tile, MP_WATER) && IsLock(tile) && GetSection(tile) >= 8) z--;
			return z;
		}

		/* Terrain type */
		case 0x81: return GetTerrainType(tile);

		/* Random data for river or canal tiles, otherwise zero */
		case 0x83: return IsTileType(tile, MP_WATER) ? GetWaterTileRandomBits(tile) : 0;
	}

	DEBUG(grf, 1, "Unhandled canal variable 0x%02X", variable);

	*available = false;
	return UINT_MAX;
}
コード例 #2
0
void TileLoopClearHelper(TileIndex tile)
{
	bool self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
	bool dirty = false;

	bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
	if (GetFenceSW(tile) == 0) {
		if (self != neighbour) {
			SetFenceSW(tile, 3);
			dirty = true;
		}
	} else {
		if (self == 0 && neighbour == 0) {
			SetFenceSW(tile, 0);
			dirty = true;
		}
	}

	neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
	if (GetFenceSE(tile) == 0) {
		if (self != neighbour) {
			SetFenceSE(tile, 3);
			dirty = true;
		}
	} else {
		if (self == 0 && neighbour == 0) {
			SetFenceSE(tile, 0);
			dirty = true;
		}
	}

	if (dirty) MarkTileDirtyByTile(tile);
}
コード例 #3
0
ファイル: clear_cmd.cpp プロジェクト: M3Henry/openttd
static void UpdateFences(TileIndex tile)
{
	assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
	bool dirty = false;

	bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
	if (!neighbour && GetFence(tile, DIAGDIR_SW) == 0) {
		SetFence(tile, DIAGDIR_SW, 3);
		dirty = true;
	}

	neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
	if (!neighbour && GetFence(tile, DIAGDIR_SE) == 0) {
		SetFence(tile, DIAGDIR_SE, 3);
		dirty = true;
	}

	neighbour = (IsTileType(TILE_ADDXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, -1, 0), CLEAR_FIELDS));
	if (!neighbour && GetFence(tile, DIAGDIR_NE) == 0) {
		SetFence(tile, DIAGDIR_NE, 3);
		dirty = true;
	}

	neighbour = (IsTileType(TILE_ADDXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, -1), CLEAR_FIELDS));
	if (!neighbour && GetFence(tile, DIAGDIR_NW) == 0) {
		SetFence(tile, DIAGDIR_NW, 3);
		dirty = true;
	}

	if (dirty) MarkTileDirtyByTile(tile);
}
コード例 #4
0
ファイル: ship_cmd.cpp プロジェクト: IchiroWang/OpenTTD
/**
 * Determine the effective #WaterClass for a ship travelling on a tile.
 * @param tile Tile of interest
 * @return the waterclass to be used by the ship.
 */
WaterClass GetEffectiveWaterClass(TileIndex tile)
{
	if (HasTileWaterClass(tile)) return GetWaterClass(tile);
	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
		assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER);
		return WATER_CLASS_CANAL;
	}
	if (IsTileType(tile, MP_RAILWAY)) {
		assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
		return WATER_CLASS_SEA;
	}
	NOT_REACHED();
}
コード例 #5
0
/**
 * Finds the distance for the closest tile with water/land given a tile
 * @param tile  the tile to find the distance too
 * @param water whether to find water or land
 * @return distance to nearest water (max 0x7F) / land (max 0x1FF; 0x200 if there is no land)
 */
uint GetClosestWaterDistance(TileIndex tile, bool water)
{
	if (HasTileWaterGround(tile) == water) return 0;

	uint max_dist = water ? 0x7F : 0x200;

	int x = TileX(tile);
	int y = TileY(tile);

	uint max_x = MapMaxX();
	uint max_y = MapMaxY();
	uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;

	/* go in a 'spiral' with increasing manhattan distance in each iteration */
	for (uint dist = 1; dist < max_dist; dist++) {
		/* next 'diameter' */
		y--;

		/* going counter-clockwise around this square */
		for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
			static const int8 ddx[DIAGDIR_END] = { -1,  1,  1, -1};
			static const int8 ddy[DIAGDIR_END] = {  1,  1, -1, -1};

			int dx = ddx[dir];
			int dy = ddy[dir];

			/* each side of this square has length 'dist' */
			for (uint a = 0; a < dist; a++) {
				/* MP_VOID tiles are not checked (interval is [min; max) for IsInsideMM())*/
				if (IsInsideMM(x, min_xy, max_x) && IsInsideMM(y, min_xy, max_y)) {
					TileIndex t = TileXY(x, y);
					if (HasTileWaterGround(t) == water) return dist;
				}
				x += dx;
				y += dy;
			}
		}
	}

	if (!water) {
		/* no land found - is this a water-only map? */
		for (TileIndex t = 0; t < MapSize(); t++) {
			if (!IsTileType(t, MP_VOID) && !IsTileType(t, MP_WATER)) return 0x1FF;
		}
	}

	return max_dist;
}
コード例 #6
0
ファイル: station.cpp プロジェクト: koreapyj/openttd-yacd
/**
 * Callback function for Station::RecomputeIndustriesNear()
 * Tests whether tile is an industry and possibly adds
 * the industry to station's industries_near list.
 * @param ind_tile tile to check
 * @param user_data pointer to RectAndIndustryVector
 * @return always false, we want to search all tiles
 */
static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
{
	/* Only process industry tiles */
	if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;

	RectAndIndustryVector *riv = (RectAndIndustryVector *)user_data;
	Industry *ind = Industry::GetByTile(ind_tile);

	/* Don't check further if this industry is already in the list */
	if (riv->industries_near->Contains(ind)) return false;

	/* Only process tiles in the station acceptance rectangle */
	int x = TileX(ind_tile);
	int y = TileY(ind_tile);
	if (x < riv->rect.left || x > riv->rect.right || y < riv->rect.top || y > riv->rect.bottom) return false;

	/* Include only industries that can accept cargo */
	uint cargo_index;
	for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
		if (ind->accepts_cargo[cargo_index] != CT_INVALID) break;
	}
	if (cargo_index >= lengthof(ind->accepts_cargo)) return false;

	*riv->industries_near->Append() = ind;

	return false;
}
コード例 #7
0
ファイル: road.cpp プロジェクト: benjeffery/openttd
/**
 * Return if the tile is a valid tile for a crossing.
 *
 * @param tile the curent tile
 * @param ax the axis of the road over the rail
 * @return true if it is a valid tile
 */
static bool IsPossibleCrossing(const TileIndex tile, Axis ax)
{
	return (IsTileType(tile, MP_RAILWAY) &&
		GetRailTileType(tile) == RAIL_TILE_NORMAL &&
		GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) &&
		GetFoundationSlope(tile) == SLOPE_FLAT);
}
コード例 #8
0
ファイル: waypoint_cmd.cpp プロジェクト: Ayutac/OpenTTD
/**
 * Check whether the given tile is suitable for a waypoint.
 * @param tile the tile to check for suitability
 * @param axis the axis of the waypoint
 * @param waypoint Waypoint the waypoint to check for is already joined to. If we find another waypoint it can join to it will throw an error.
 */
static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *waypoint)
{
	/* if waypoint is set, then we have special handling to allow building on top of already existing waypoints.
	 * so waypoint points to INVALID_STATION if we can build on any waypoint.
	 * Or it points to a waypoint if we're only allowed to build on exactly that waypoint. */
	if (waypoint != NULL && IsTileType(tile, MP_STATION)) {
		if (!IsRailWaypoint(tile)) {
			return ClearTile_Station(tile, DC_AUTO); // get error message
		} else {
			StationID wp = GetStationIndex(tile);
			if (*waypoint == INVALID_STATION) {
				*waypoint = wp;
			} else if (*waypoint != wp) {
				return_cmd_error(STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING);
			}
		}
	}

	if (GetAxisForNewWaypoint(tile) != axis) return_cmd_error(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK);

	Owner owner = GetTileOwner(tile);
	CommandCost ret = CheckOwnership(owner);
	if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile);
	if (ret.Failed()) return ret;

	Slope tileh = GetTileSlope(tile);
	if (tileh != SLOPE_FLAT &&
			(!_settings_game.construction.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
		return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
	}

	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);

	return CommandCost();
}
コード例 #9
0
ファイル: town_sl.cpp プロジェクト: Johnnei/OpenTTD
/**
 * Rebuild all the cached variables of towns.
 */
void RebuildTownCaches()
{
	Town *town;
	InitializeBuildingCounts();

	/* Reset town population and num_houses */
	FOR_ALL_TOWNS(town) {
		town->cache.population = 0;
		town->cache.num_houses = 0;
	}

	for (TileIndex t = 0; t < MapSize(); t++) {
		if (!IsTileType(t, MP_HOUSE)) continue;

		HouseID house_id = GetHouseType(t);
		town = Town::GetByTile(t);
		IncreaseBuildingCount(town, house_id);
		if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population;

		/* Increase the number of houses for every house, but only once. */
		if (GetHouseNorthPart(house_id) == 0) town->cache.num_houses++;
	}

	/* Update the population and num_house dependent values */
	FOR_ALL_TOWNS(town) {
		UpdateTownRadius(town);
		UpdateTownCargoes(town);
	}
	UpdateTownCargoBitmap();
}
コード例 #10
0
ファイル: effectvehicle.cpp プロジェクト: Johnnei/OpenTTD
static bool BubbleTick(EffectVehicle *v)
{
	uint anim_state;

	v->progress++;
	if ((v->progress & 3) != 0) return true;

	if (v->spritenum == 0) {
		v->cur_image++;
		if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
			v->UpdatePositionAndViewport();
			return true;
		}
		if (v->animation_substate != 0) {
			v->spritenum = GB(Random(), 0, 2) + 1;
		} else {
			v->spritenum = 6;
		}
		anim_state = 0;
	} else {
		anim_state = v->animation_state + 1;
	}

	const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][anim_state];

	if (b->y == 4 && b->x == 0) {
		delete v;
		return false;
	}

	if (b->y == 4 && b->x == 1) {
		if (v->z_pos > 180 || Chance16I(1, 96, Random())) {
			v->spritenum = 5;
			if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_2F_POP, v);
		}
		anim_state = 0;
	}

	if (b->y == 4 && b->x == 2) {
		TileIndex tile;

		anim_state++;
		if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_31_EXTRACT, v);

		tile = TileVirtXY(v->x_pos, v->y_pos);
		if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile);
	}

	v->animation_state = anim_state;
	b = &_bubble_movement[v->spritenum - 1][anim_state];

	v->x_pos += b->x;
	v->y_pos += b->y;
	v->z_pos += b->z;
	v->cur_image = SPR_BUBBLE_0 + b->image;

	v->UpdatePositionAndViewport();

	return true;
}
コード例 #11
0
ファイル: npf.cpp プロジェクト: andrew889/OpenTTD
/**
 * Finds out if a given company's vehicles are allowed to enter a given tile.
 * @param owner    The owner of the vehicle.
 * @param tile     The tile that is about to be entered.
 * @param enterdir The direction in which the vehicle wants to enter the tile.
 * @return         true if the vehicle can enter the tile.
 * @todo           This function should be used in other places than just NPF,
 *                 maybe moved to another file too.
 */
static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
{
	if (IsTileType(tile, MP_RAILWAY) || // Rail tile (also rail depot)
			HasStationTileRail(tile) ||     // Rail station tile/waypoint
			IsRoadDepotTile(tile) ||        // Road depot tile
			IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
		return IsTileOwner(tile, owner);  // You need to own these tiles entirely to use them
	}

	switch (GetTileType(tile)) {
		case MP_ROAD:
			/* rail-road crossing : are we looking at the railway part? */
			if (IsLevelCrossing(tile) &&
					DiagDirToAxis(enterdir) != GetCrossingRoadAxis(tile)) {
				return IsTileOwner(tile, owner); // Railway needs owner check, while the street is public
			}
			break;

		case MP_TUNNELBRIDGE:
			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
				return IsTileOwner(tile, owner);
			}
			break;

		default:
			break;
	}

	return true; // no need to check
}
コード例 #12
0
void CopyPastePlaceRailWaypoint(GenericTileIndex tile, StationID sid, Axis axis, RailType rt, StationGfx gfx, StationClassID stat_class, byte stat_type, int specindex, bool adjacent)
{
	if (IsMainMapTile(tile)) {
		TileIndex t = AsMainMapTile(tile);
		/* check if required track is already there, try to build one if not */
		if (!IsTileOwner(t, _current_company) ||
				(!IsRailWaypointTile(tile) && !IsPlainRailTile(tile)) ||
				GetRailType(t) != rt ||
				(IsTileType(t, MP_STATION) ? GetRailStationAxis(tile) != axis : !HasBit(GetTrackBits(t), AxisToTrack(axis)))) {
			CopyPastePlaceTracks(tile, rt, AxisToTrackBits(axis));
			if (_current_pasting->last_result.Failed()) return;
		}
		/* build the waypoint */
		_station_cmd_specindex_to_paste = specindex;
		uint32 p1 = 0;
		SB(p1, 0, 4, rt);
		SB(p1, 4, 1, axis);
		SB(p1, 8, 8, 1);  // width
		SB(p1, 16, 8, 1); // height
		SB(p1, 24, 1, adjacent);
		uint32 p2 = 0;
		SB(p2, 0, 8, stat_class);
		SB(p2, 8, 8, stat_type);
		SB(p2, 16, 16, sid);
		_current_pasting->DoCommand(t, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT));
	} else {
		MakeRailWaypoint(tile, OWNER_NONE, sid, axis, gfx & ~1, rt);
		assert(IsInsideMM(specindex, 0, MAX_UVALUE(byte) + 1));
		SetCustomStationSpecIndex(tile, (byte)specindex);
		_clipboard_stations_builder.AddRailPart(sid, stat_class, stat_type, (byte)specindex);
	}
}
コード例 #13
0
ファイル: newgrf_canal.cpp プロジェクト: Ayutac/OpenTTD
/* virtual */ uint32 CanalScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
{
	switch (variable) {
		/* Height of tile */
		case 0x80: {
			int z = GetTileZ(this->tile);
			/* Return consistent height within locks */
			if (IsTileType(this->tile, MP_WATER) && IsLock(this->tile) && GetLockPart(this->tile) == LOCK_PART_UPPER) z--;
			return z;
		}

		/* Terrain type */
		case 0x81: return GetTerrainType(this->tile);

		/* Dike map: Connectivity info for river and canal tiles
		 *
		 * Assignment of bits to directions defined in agreement with
		 * http://projects.tt-forums.net/projects/ttdpatch/repository/revisions/2367/entry/trunk/patches/water.asm#L879
		 *         7
		 *      3     0
		 *   6     *     4
		 *      2     1
		 *         5
		 */
		case 0x82: {
			uint32 connectivity =
				  (!IsWateredTile(TILE_ADDXY(tile, -1,  0), DIR_SW) << 0)  // NE
				+ (!IsWateredTile(TILE_ADDXY(tile,  0,  1), DIR_NW) << 1)  // SE
				+ (!IsWateredTile(TILE_ADDXY(tile,  1,  0), DIR_NE) << 2)  // SW
				+ (!IsWateredTile(TILE_ADDXY(tile,  0, -1), DIR_SE) << 3)  // NW
				+ (!IsWateredTile(TILE_ADDXY(tile, -1,  1), DIR_W)  << 4)  // E
				+ (!IsWateredTile(TILE_ADDXY(tile,  1,  1), DIR_N)  << 5)  // S
				+ (!IsWateredTile(TILE_ADDXY(tile,  1, -1), DIR_E)  << 6)  // W
				+ (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)  << 7); // N
			return connectivity;
		}

		/* Random data for river or canal tiles, otherwise zero */
		case 0x83: return IsTileType(this->tile, MP_WATER) ? GetWaterTileRandomBits(this->tile) : 0;
	}

	DEBUG(grf, 1, "Unhandled canal variable 0x%02X", variable);

	*available = false;
	return UINT_MAX;
}
コード例 #14
0
/* static */ bool AIRoad::RemoveRoadStation(TileIndex tile)
{
	EnforcePrecondition(false, ::IsValidTile(tile));
	EnforcePrecondition(false, IsTileType(tile, MP_STATION));
	EnforcePrecondition(false, IsRoadStop(tile));

	return AIObject::DoCommand(tile, 1 | 1 << 8, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
}
コード例 #15
0
/* static */ bool AIRoad::RemoveRoadDepot(TileIndex tile)
{
	EnforcePrecondition(false, ::IsValidTile(tile));
	EnforcePrecondition(false, IsTileType(tile, MP_ROAD))
	EnforcePrecondition(false, GetRoadTileType(tile) == ROAD_TILE_DEPOT);

	return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
}
コード例 #16
0
/**
 * Checks whether the 'next' tile is still part of the road same drive through
 * stop 'rs' in the same direction for the same vehicle.
 * @param rs   the road stop tile to check against
 * @param next the 'next' tile to check
 * @return true if the 'next' tile is part of the road stop at 'next'.
 */
/* static */ bool RoadStop::IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next)
{
	return IsTileType(next, MP_STATION) &&
			GetStationIndex(next) == GetStationIndex(rs) &&
			GetStationType(next) == GetStationType(rs) &&
			GetRoadStopDir(next) == GetRoadStopDir(rs) &&
			IsDriveThroughStopTile(next);
}
コード例 #17
0
/**
 * Check whether the given tile is suitable for a waypoint.
 * @param tile the tile to check for suitability
 * @param axis the axis of the waypoint
 * @param waypoint Waypoint the waypoint to check for is already joined to. If we find another waypoint it can join to it will throw an error.
 * @param flags flags for the command
 */
static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *waypoint, DoCommandFlag flags)
{
	/* if waypoint is set, then we have special handling to allow building on top of already existing waypoints.
	 * so waypoint points to INVALID_STATION if we can build on any waypoint.
	 * Or it points to a waypoint if we're only allowed to build on exactly that waypoint. */
	if (waypoint != NULL && IsTileType(tile, MP_STATION)) {
		if (!IsRailWaypoint(tile)) {
			return ClearTile_Station(tile, DC_AUTO); // get error message
		} else {
			StationID wp = GetStationIndex(tile);
			if (*waypoint == INVALID_STATION) {
				*waypoint = wp;
			} else if (*waypoint != wp) {
				return_cmd_error(STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING);
			}
		}
	}

	/* When pasting a waypoint, there may be no track yet (it will be placed when DC_EXEC'ing).
	 * Ignore that so we can calculate the cost more precisely. */
	bool ignore_lack_of_tracks = (flags & DC_PASTE) && !(flags & DC_EXEC);

	if (!ignore_lack_of_tracks || IsTileType(tile, MP_RAILWAY)) {
		if (GetAxisForNewWaypoint(tile) != axis) return_cmd_error(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK);
	}

	Owner owner = GetTileOwner(tile);
	if (!ignore_lack_of_tracks || owner != OWNER_NONE) {
		CommandCost ret = CheckOwnership(owner);
		if (ret.Failed()) return ret;
	}

	CommandCost ret = EnsureNoVehicleOnGround(tile);
	if (ret.Failed()) return ret;

	Slope tileh = GetTileSlope(tile);
	if (tileh != SLOPE_FLAT &&
			(!_settings_game.construction.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
		return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
	}

	if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);

	return CommandCost();
}
コード例 #18
0
ファイル: script_road.cpp プロジェクト: benjeffery/openttd
/* static */ bool ScriptRoad::RemoveRoadStation(TileIndex tile)
{
	EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
	EnforcePrecondition(false, ::IsValidTile(tile));
	EnforcePrecondition(false, IsTileType(tile, MP_STATION));
	EnforcePrecondition(false, IsRoadStop(tile));

	return ScriptObject::DoCommand(tile, 1 | 1 << 8, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
}
コード例 #19
0
ファイル: station.cpp プロジェクト: koreapyj/openttd-yacd
/**
 * Check whether station tiles of the given station id exist in the given rectangle
 * @param st_id    Station ID to look for in the rectangle
 * @param left_a   Minimal tile X edge of the rectangle
 * @param top_a    Minimal tile Y edge of the rectangle
 * @param right_a  Maximal tile X edge of the rectangle (inclusive)
 * @param bottom_a Maximal tile Y edge of the rectangle (inclusive)
 * @return \c true if a station tile with the given \a st_id exists in the rectangle, \c false otherwise
 */
/* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
{
	TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a));
	TILE_AREA_LOOP(tile, ta) {
		if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
	}

	return false;
}
コード例 #20
0
static void TPFModeShip(TrackPathFinder *tpf, TileIndex tile, DiagDirection direction)
{
    if (IsTileType(tile, MP_TUNNELBRIDGE)) {
        /* wrong track type */
        if (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) return;

        DiagDirection dir = GetTunnelBridgeDirection(tile);
        /* entering tunnel / bridge? */
        if (dir == direction) {
            TileIndex endtile = GetOtherTunnelBridgeEnd(tile);

            tpf->rd.cur_length += GetTunnelBridgeLength(tile, endtile) + 1;

            tile = endtile;
        } else {
            /* leaving tunnel / bridge? */
            if (ReverseDiagDir(dir) != direction) return;
        }
    }

    /* This addition will sometimes overflow by a single tile.
     * The use of TILE_MASK here makes sure that we still point at a valid
     * tile, and then this tile will be in the sentinel row/col, so GetTileTrackStatus will fail. */
    tile = TILE_MASK(tile + TileOffsByDiagDir(direction));

    if (++tpf->rd.cur_length > 50) return;

    TrackBits bits = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(direction);
    if (bits == TRACK_BIT_NONE) return;

    assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());

    bool only_one_track = true;
    do {
        Track track = RemoveFirstTrack(&bits);
        if (bits != TRACK_BIT_NONE) only_one_track = false;
        RememberData rd = tpf->rd;

        /* Change direction 4 times only */
        if (!only_one_track && track != tpf->rd.last_choosen_track) {
            if (++tpf->rd.depth > 4) {
                tpf->rd = rd;
                return;
            }
            tpf->rd.last_choosen_track = track;
        }

        tpf->the_dir = TrackEnterdirToTrackdir(track, direction);

        if (!ShipTrackFollower(tile, tpf, tpf->rd.cur_length)) {
            TPFModeShip(tpf, tile, TrackdirToExitdir(tpf->the_dir));
        }

        tpf->rd = rd;
    } while (bits != TRACK_BIT_NONE);
}
コード例 #21
0
ファイル: water_cmd.cpp プロジェクト: Voxar/OpenTTD
void MakeWaterKeepingClass(TileIndex tile, Owner o)
{
	assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile) || IsOilRig(tile))) || IsTileType(tile, MP_INDUSTRY));

	WaterClass wc = GetWaterClass(tile);

	/* Autoslope might turn an originally canal or river tile into land */
	uint z;
	if (GetTileSlope(tile, &z) != SLOPE_FLAT) wc = WATER_CLASS_INVALID;

	if (wc == WATER_CLASS_SEA && z > 0) wc = WATER_CLASS_CANAL;

	switch (wc) {
		case WATER_CLASS_SEA:   MakeSea(tile);                break;
		case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
		case WATER_CLASS_RIVER: MakeRiver(tile, Random());    break;
		default:                DoClearSquare(tile);          break;
	}
}
コード例 #22
0
ファイル: object_sl.cpp プロジェクト: M3Henry/openttd
static void Ptrs_OBJS()
{
	Object *o;
	FOR_ALL_OBJECTS(o) {
		SlObject(o, _object_desc);
		if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) {
			/* Due to a small bug stale objects could remain. */
			delete o;
		}
	}
}
コード例 #23
0
    inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
    {
        if (m_dest_station != INVALID_STATION) {
            return IsTileType(tile, MP_STATION) &&
                   GetStationIndex(tile) == m_dest_station &&
                   (m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
                   (m_non_artic || IsDriveThroughStopTile(tile));
        }

        return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
    }
コード例 #24
0
ファイル: station.cpp プロジェクト: jemmyw/openttd
/**
 * Check whether station tiles of the given station id exist in the given rectangle
 * @param st_id    Station ID to look for in the rectangle
 * @param left_a   Minimal tile X edge of the rectangle
 * @param top_a    Minimal tile Y edge of the rectangle
 * @param right_a  Maximal tile X edge of the rectangle (inclusive)
 * @param bottom_a Maximal tile Y edge of the rectangle (inclusive)
 * @return \c true if a station tile with the given \a st_id exists in the rectangle, \c false otherwise
 */
/* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
{
	TileIndex top_left = TileXY(left_a, top_a);
	int width = right_a - left_a + 1;
	int height = bottom_a - top_a + 1;

	TILE_LOOP(tile, width, height, top_left) {
		if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
	}

	return false;
}
コード例 #25
0
ファイル: town_sl.cpp プロジェクト: Johnnei/OpenTTD
/**
 * Check and update town and house values.
 *
 * Checked are the HouseIDs. Updated are the
 * town population the number of houses per
 * town, the town radius and the max passengers
 * of the town.
 */
void UpdateHousesAndTowns()
{
	for (TileIndex t = 0; t < MapSize(); t++) {
		if (!IsTileType(t, MP_HOUSE)) continue;

		HouseID house_id = GetCleanHouseType(t);
		if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
			/* The specs for this type of house are not available any more, so
			 * replace it with the substitute original house type. */
			house_id = _house_mngr.GetSubstituteID(house_id);
			SetHouseType(t, house_id);
		}
	}

	/* Check for cases when a NewGRF has set a wrong house substitute type. */
	for (TileIndex t = 0; t < MapSize(); t++) {
		if (!IsTileType(t, MP_HOUSE)) continue;

		HouseID house_type = GetCleanHouseType(t);
		TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
		if (t == north_tile) {
			const HouseSpec *hs = HouseSpec::Get(house_type);
			bool valid_house = true;
			if (hs->building_flags & TILE_SIZE_2x1) {
				TileIndex tile = t + TileDiffXY(1, 0);
				if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
			} else if (hs->building_flags & TILE_SIZE_1x2) {
				TileIndex tile = t + TileDiffXY(0, 1);
				if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
			} else if (hs->building_flags & TILE_SIZE_2x2) {
				TileIndex tile = t + TileDiffXY(0, 1);
				if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
				tile = t + TileDiffXY(1, 0);
				if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false;
				tile = t + TileDiffXY(1, 1);
				if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false;
			}
			/* If not all tiles of this house are present remove the house.
			 * The other tiles will get removed later in this loop because
			 * their north tile is not the correct type anymore. */
			if (!valid_house) DoClearSquare(t);
		} else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
			/* This tile should be part of a multi-tile building but the
			 * north tile of this house isn't on the map. */
			DoClearSquare(t);
		}
	}

	RebuildTownCaches();
}
コード例 #26
0
/**
 * Build a piece of canal.
 * @param tile end tile of stretch-dragging
 * @param flags type of operation
 * @param p1 start tile of stretch-dragging
 * @param p2 waterclass to build. sea and river can only be built in scenario editor
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	WaterClass wc = Extract<WaterClass, 0, 2>(p2);
	if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;

	/* Outside of the editor you can only build canals, not oceans */
	if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;

	TileArea ta(tile, p1);

	/* Outside the editor you can only drag canals, and not areas */
	if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR;

	CommandCost cost(EXPENSES_CONSTRUCTION);
	TILE_AREA_LOOP(tile, ta) {
		CommandCost ret;

		Slope slope = GetTileSlope(tile, NULL);
		if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) {
			return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
		}

		/* can't make water of water! */
		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;

		ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
		if (ret.Failed()) return ret;
		cost.AddCost(ret);

		if (flags & DC_EXEC) {
			switch (wc) {
				case WATER_CLASS_RIVER:
					MakeRiver(tile, Random());
					break;

				case WATER_CLASS_SEA:
					if (TileHeight(tile) == 0) {
						MakeSea(tile);
						break;
					}
					/* FALL THROUGH */

				default:
					MakeCanal(tile, _current_company, Random());
					break;
			}
			MarkTileDirtyByTile(tile);
			MarkCanalsAndRiversAroundDirty(tile);
		}

		cost.AddCost(_price[PR_BUILD_CANAL]);
	}
コード例 #27
0
ファイル: clear_cmd.cpp プロジェクト: M3Henry/openttd
void GenerateClearTile()
{
	uint i, gi;
	TileIndex tile;

	/* add rough tiles */
	i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
	gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);

	SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
	do {
		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
		tile = RandomTile();
		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
	} while (--i);

	/* add rocky tiles */
	i = gi;
	do {
		uint32 r = Random();
		tile = RandomTileSeed(r);

		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
			uint j = GB(r, 16, 4) + 5;
			for (;;) {
				TileIndex tile_new;

				SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
				do {
					if (--j == 0) goto get_out;
					tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
				} while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
				tile = tile_new;
			}
get_out:;
		}
	} while (--i);
}
コード例 #28
0
uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile,
		bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
{
	assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE)));

	HouseResolverObject object(house_id, tile, town, callback, param1, param2,
			not_yet_constructed, initial_random_bits, watched_cargo_triggers);

	const SpriteGroup *group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], &object);
	if (group == NULL) return CALLBACK_FAILED;

	return group->GetCallbackResult();
}
コード例 #29
0
/* virtual */ uint32 CanalScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
{
	switch (variable) {
		/* Height of tile */
		case 0x80: {
			int z = GetTileZ(this->tile);
			/* Return consistent height within locks */
			if (IsTileType(this->tile, MP_WATER) && IsLock(this->tile) && GetLockPart(this->tile) == LOCK_PART_UPPER) z--;
			return z;
		}

		/* Terrain type */
		case 0x81: return GetTerrainType(this->tile);

		/* Random data for river or canal tiles, otherwise zero */
		case 0x83: return IsTileType(this->tile, MP_WATER) ? GetWaterTileRandomBits(this->tile) : 0;
	}

	DEBUG(grf, 1, "Unhandled canal variable 0x%02X", variable);

	*available = false;
	return UINT_MAX;
}
コード例 #30
0
ファイル: waypoint_cmd.cpp プロジェクト: Ayutac/OpenTTD
/**
 * Get the axis for a new waypoint. This means that if it is a valid
 * tile to build a waypoint on it returns a valid Axis, otherwise an
 * invalid one.
 * @param tile the tile to look at.
 * @return the axis for the to-be-build waypoint.
 */
Axis GetAxisForNewWaypoint(TileIndex tile)
{
	/* The axis for rail waypoints is easy. */
	if (IsRailWaypointTile(tile)) return GetRailStationAxis(tile);

	/* Non-plain rail type, no valid axis for waypoints. */
	if (!IsTileType(tile, MP_RAILWAY) || GetRailTileType(tile) != RAIL_TILE_NORMAL) return INVALID_AXIS;

	switch (GetTrackBits(tile)) {
		case TRACK_BIT_X: return AXIS_X;
		case TRACK_BIT_Y: return AXIS_Y;
		default:          return INVALID_AXIS;
	}
}