Ejemplo n.º 1
0
/**
 * Add edges of the neighbouring path tiles.
 * @param xpos X coordinate of the central voxel with a path tile.
 * @param ypos Y coordinate of the central voxel with a path tile.
 * @param zpos Z coordinate of the central voxel with a path tile.
 * @param slope Imploded path slope of the central voxel.
 * @param dirs Edge directions to change (bitset of #TileEdge), usually #EDGE_ALL.
 * @param use_additions Use #_additions rather than #_world.
 * @param add_edges If set, add edges (else, remove them).
 * @return Updated (imploded) slope at the central voxel.
 */
uint8 AddRemovePathEdges(uint16 xpos, uint16 ypos, uint8 zpos, uint8 slope, uint8 dirs, bool use_additions, bool add_edges)
{
	for (TileEdge edge = EDGE_BEGIN; edge < EDGE_COUNT; edge++) {
		if ((dirs & (1 << edge)) == 0) continue; // Skip directions that should not be updated.
		int delta_z = 0;
		if (slope >= PATH_FLAT_COUNT) {
			if (_path_down_from_edge[edge] == slope) {
				delta_z = 1;
			} else if (_path_up_from_edge[edge] != slope) {
				continue;
			}
		}
		Point16 dxy = _tile_dxy[edge];
		if ((dxy.x < 0 && xpos == 0) || (dxy.x > 0 && xpos == _world.GetXSize() - 1)) continue;
		if ((dxy.y < 0 && ypos == 0) || (dxy.y > 0 && ypos == _world.GetYSize() - 1)) continue;

		TileEdge edge2 = (TileEdge)((edge + 2) % 4);
		bool modified = false;
		if (delta_z <= 0 || zpos < WORLD_Z_SIZE - 1) {
			Voxel *v;
			if (use_additions) {
				v = _additions.GetCreateVoxel(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, false);
			} else {
				v = _world.GetCreateVoxel(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, false);
			}
			if (v != nullptr) {
				uint16 number = v->GetInstance();
				if (number == SRI_PATH) { // Valid path.
					v->SetInstanceData(SetPathEdge(v->GetInstanceData(), edge2, add_edges));
					MarkVoxelDirty(xpos + dxy.x, ypos + dxy.y, zpos + delta_z);
					modified = true;
				} else if (number >= SRI_FULL_RIDES) { // A ride instance. Does it have an entrance here?
					if ((v->GetInstanceData() & (1 << edge2)) != 0) modified = true;
				}
			}
		}
		delta_z--;
		if (delta_z >= 0 || zpos > 0) {
			Voxel *v;
			if (use_additions) {
				v = _additions.GetCreateVoxel(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, false);
			} else {
				v = _world.GetCreateVoxel(xpos + dxy.x, ypos + dxy.y, zpos + delta_z, false);
			}
			if (v != nullptr) {
				uint16 number = v->GetInstance();
				if (number == SRI_PATH) { // Valid path.
					v->SetInstanceData(SetPathEdge(v->GetInstanceData(), edge2, add_edges));
					MarkVoxelDirty(xpos + dxy.x, ypos + dxy.y, zpos + delta_z);
					modified = true;
				} else if (number >= SRI_FULL_RIDES) { // A ride instance. Does it have an entrance here?
					if ((v->GetInstanceData() & (1 << edge2)) != 0) modified = true;
				}
			}
		}
		if (modified && slope < PATH_FLAT_COUNT) slope = SetPathEdge(slope, edge, add_edges);
	}
	return slope;
}
Ejemplo n.º 2
0
/**
 * Examine, and perhaps modify a neighbouring path edge or ride connection, to make it connect (or not if not \a add_edges)
 * to the centre examined tile.
 * @param voxel_pos Coordinate of the neighbouring voxel.
 * @param edge Edge to examine, and/or connected to.
 * @param add_edges If set, add edges (else, remove them).
 * @param at_bottom Whether a path connection is expected at the bottom (if \c false, it should be at the top).
 * @param dest_voxel [out] %Voxel containing the neighbouring path, or \c nullptr.
 * @param dest_inst_data [out] New instance of the voxel. Only valid if \a dest_voxel is not \c nullptr.
 * @param dest_status [out] Status of the neighbouring path.
 * @return Neighbouring voxel was (logically) connected to the centre tile.
 */
static bool ExamineNeighbourPathEdge(const XYZPoint16 &voxel_pos, TileEdge edge, bool add_edges, bool at_bottom,
		Voxel **dest_voxel, uint16 *dest_inst_data, PathStatus *dest_status)
{
	Voxel *v;

	*dest_voxel = nullptr;
	*dest_status = PAS_UNUSED;
	*dest_inst_data = PATH_INVALID;

	v = _world.GetCreateVoxel(voxel_pos, false);
	if (v == nullptr) return false;

	uint16 fences = v->GetFences();
	FenceType fence_type = GetFenceType(fences, edge);
	if (fence_type != FENCE_TYPE_INVALID) return false;

	uint16 number = v->GetInstance();
	if (number == SRI_PATH) {
		uint16 instance_data = v->GetInstanceData();
		if (!HasValidPath(instance_data)) return false;

		uint8 slope = GetImplodedPathSlope(instance_data);
		if (at_bottom) {
			if (slope >= PATH_FLAT_COUNT && slope != _path_up_from_edge[edge]) return false;
		} else {
			if (slope != _path_down_from_edge[edge]) return false;
		}

		PathStatus status = _sprite_manager.GetPathStatus(GetPathType(instance_data));
		if (add_edges && status == PAS_QUEUE_PATH) { // Only try to connect to queue paths if they are not yet connected to 2 (or more) neighbours.
			if (GetQuePathEdgeConnectCount(slope) > 1) return false;
		}

		slope = SetPathEdge(slope, edge, add_edges);
		*dest_status = status;
		*dest_voxel = v;
		*dest_inst_data = SetImplodedPathSlope(instance_data, slope);
		return true;

	} else if (number >= SRI_FULL_RIDES) { // A ride instance. Does it have an entrance here?
		if ((v->GetInstanceData() & (1 << edge)) != 0) {
			*dest_status = PAS_QUEUE_PATH;
			return true;
		}
	}
	return false;
}