waypoint.c
changeset 4077 d4d440dd8925
parent 4052 d6f167c6e9cb
child 4261 28670f743746
equal deleted inserted replaced
4076:a6650b616430 4077:d4d440dd8925
    32  */
    32  */
    33 static void WaypointPoolNewBlock(uint start_item)
    33 static void WaypointPoolNewBlock(uint start_item)
    34 {
    34 {
    35 	Waypoint *wp;
    35 	Waypoint *wp;
    36 
    36 
    37 	FOR_ALL_WAYPOINTS_FROM(wp, start_item)
    37 	FOR_ALL_WAYPOINTS_FROM(wp, start_item) wp->index = start_item++;
    38 		wp->index = start_item++;
       
    39 }
    38 }
    40 
    39 
    41 /* Initialize the town-pool */
    40 /* Initialize the town-pool */
    42 MemoryPool _waypoint_pool = { "Waypoints", WAYPOINT_POOL_MAX_BLOCKS, WAYPOINT_POOL_BLOCK_SIZE_BITS, sizeof(Waypoint), &WaypointPoolNewBlock, NULL, 0, 0, NULL };
    41 MemoryPool _waypoint_pool = { "Waypoints", WAYPOINT_POOL_MAX_BLOCKS, WAYPOINT_POOL_BLOCK_SIZE_BITS, sizeof(Waypoint), &WaypointPoolNewBlock, NULL, 0, 0, NULL };
    43 
    42 
    48 
    47 
    49 	FOR_ALL_WAYPOINTS(wp) {
    48 	FOR_ALL_WAYPOINTS(wp) {
    50 		if (wp->xy == 0) {
    49 		if (wp->xy == 0) {
    51 			uint index = wp->index;
    50 			uint index = wp->index;
    52 
    51 
    53 			memset(wp, 0, sizeof(Waypoint));
    52 			memset(wp, 0, sizeof(*wp));
    54 			wp->index = index;
    53 			wp->index = index;
    55 
    54 
    56 			return wp;
    55 			return wp;
    57 		}
    56 		}
    58 	}
    57 	}
    59 
    58 
    60 	/* Check if we can add a block to the pool */
    59 	/* Check if we can add a block to the pool */
    61 	if (AddBlockToPool(&_waypoint_pool))
    60 	if (AddBlockToPool(&_waypoint_pool)) return AllocateWaypoint();
    62 		return AllocateWaypoint();
       
    63 
    61 
    64 	return NULL;
    62 	return NULL;
    65 }
    63 }
    66 
    64 
    67 /* Update the sign for the waypoint */
    65 /* Update the sign for the waypoint */
    86 void UpdateAllWaypointSigns(void)
    84 void UpdateAllWaypointSigns(void)
    87 {
    85 {
    88 	Waypoint *wp;
    86 	Waypoint *wp;
    89 
    87 
    90 	FOR_ALL_WAYPOINTS(wp) {
    88 	FOR_ALL_WAYPOINTS(wp) {
    91 		if (wp->xy)
    89 		if (wp->xy != 0) UpdateWaypointSign(wp);
    92 			UpdateWaypointSign(wp);
       
    93 	}
    90 	}
    94 }
    91 }
    95 
    92 
    96 /* Set the default name for a waypoint */
    93 /* Set the default name for a waypoint */
    97 static void MakeDefaultWaypointName(Waypoint* wp)
    94 static void MakeDefaultWaypointName(Waypoint* wp)
   104 
   101 
   105 	memset(used_waypoint, 0, sizeof(used_waypoint));
   102 	memset(used_waypoint, 0, sizeof(used_waypoint));
   106 
   103 
   107 	/* Find an unused waypoint number belonging to this town */
   104 	/* Find an unused waypoint number belonging to this town */
   108 	FOR_ALL_WAYPOINTS(local_wp) {
   105 	FOR_ALL_WAYPOINTS(local_wp) {
   109 		if (wp == local_wp)
   106 		if (wp == local_wp) continue;
   110 			continue;
       
   111 
   107 
   112 		if (local_wp->xy && local_wp->string == STR_NULL && local_wp->town_index == wp->town_index)
   108 		if (local_wp->xy && local_wp->string == STR_NULL && local_wp->town_index == wp->town_index)
   113 			used_waypoint[local_wp->town_cn] = true;
   109 			used_waypoint[local_wp->town_cn] = true;
   114 	}
   110 	}
   115 
   111 
   122 
   118 
   123 /* Find a deleted waypoint close to a tile. */
   119 /* Find a deleted waypoint close to a tile. */
   124 static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
   120 static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
   125 {
   121 {
   126 	Waypoint *wp, *best = NULL;
   122 	Waypoint *wp, *best = NULL;
   127 	uint thres = 8, cur_dist;
   123 	uint thres = 8;
   128 
   124 
   129 	FOR_ALL_WAYPOINTS(wp) {
   125 	FOR_ALL_WAYPOINTS(wp) {
   130 		if (wp->deleted && wp->xy) {
   126 		if (wp->deleted && wp->xy != 0) {
   131 			cur_dist = DistanceManhattan(tile, wp->xy);
   127 			uint cur_dist = DistanceManhattan(tile, wp->xy);
       
   128 
   132 			if (cur_dist < thres) {
   129 			if (cur_dist < thres) {
   133 				thres = cur_dist;
   130 				thres = cur_dist;
   134 				best = wp;
   131 				best = wp;
   135 			}
   132 			}
   136 		}
   133 		}
   188 				(axis = AXIS_Y, GetTrackBits(tile) != TRACK_BIT_Y)
   185 				(axis = AXIS_Y, GetTrackBits(tile) != TRACK_BIT_Y)
   189 			)) {
   186 			)) {
   190 		return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
   187 		return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
   191 	}
   188 	}
   192 
   189 
   193 	if (!CheckTileOwnership(tile))
   190 	if (!CheckTileOwnership(tile)) return CMD_ERROR;
   194 		return CMD_ERROR;
       
   195 
       
   196 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   191 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
   197 
   192 
   198 	tileh = GetTileSlope(tile, NULL);
   193 	tileh = GetTileSlope(tile, NULL);
   199 	if (tileh != SLOPE_FLAT) {
   194 	if (tileh != SLOPE_FLAT &&
   200 		if (!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))
   195 			(!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
   201 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   196 		return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   202 	}
   197 	}
   203 
   198 
   204 	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
   199 	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
   205 	wp = FindDeletedWaypointCloseTo(tile);
   200 	wp = FindDeletedWaypointCloseTo(tile);
   206 	if (wp == NULL) {
   201 	if (wp == NULL) {
   253 
   248 
   254 	order.type = OT_GOTO_WAYPOINT;
   249 	order.type = OT_GOTO_WAYPOINT;
   255 	order.station = wp->index;
   250 	order.station = wp->index;
   256 	DeleteDestinationFromVehicleOrder(order);
   251 	DeleteDestinationFromVehicleOrder(order);
   257 
   252 
   258 	if (wp->string != STR_NULL)
   253 	if (wp->string != STR_NULL) DeleteName(wp->string);
   259 		DeleteName(wp->string);
       
   260 
   254 
   261 	RedrawWaypointSign(wp);
   255 	RedrawWaypointSign(wp);
   262 }
   256 }
   263 
   257 
   264 /* Daily loop for waypoints */
   258 /* Daily loop for waypoints */
   266 {
   260 {
   267 	Waypoint *wp;
   261 	Waypoint *wp;
   268 
   262 
   269 	/* Check if we need to delete a waypoint */
   263 	/* Check if we need to delete a waypoint */
   270 	FOR_ALL_WAYPOINTS(wp) {
   264 	FOR_ALL_WAYPOINTS(wp) {
   271 		if (wp->deleted && !--wp->deleted) {
   265 		if (wp->deleted != 0 && --wp->deleted == 0) DoDeleteWaypoint(wp);
   272 			DoDeleteWaypoint(wp);
       
   273 		}
       
   274 	}
   266 	}
   275 }
   267 }
   276 
   268 
   277 /* Remove a waypoint */
   269 /* Remove a waypoint */
   278 int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove)
   270 int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove)
   279 {
   271 {
   280 	Waypoint *wp;
   272 	Waypoint *wp;
   281 
   273 
   282 	/* Make sure it's a waypoint */
   274 	/* Make sure it's a waypoint */
   283 	if (!IsTileType(tile, MP_RAILWAY) || !IsRailWaypoint(tile))
   275 	if (!IsTileType(tile, MP_RAILWAY) ||
       
   276 			!IsRailWaypoint(tile) ||
       
   277 			(!CheckTileOwnership(tile) && _current_player != OWNER_WATER) ||
       
   278 			!EnsureNoVehicle(tile)) {
   284 		return CMD_ERROR;
   279 		return CMD_ERROR;
   285 
   280 	}
   286 	if (!CheckTileOwnership(tile) && !(_current_player == OWNER_WATER))
       
   287 		return CMD_ERROR;
       
   288 
       
   289 	if (!EnsureNoVehicle(tile))
       
   290 		return CMD_ERROR;
       
   291 
   281 
   292 	if (flags & DC_EXEC) {
   282 	if (flags & DC_EXEC) {
   293 		wp = GetWaypointByTile(tile);
   283 		wp = GetWaypointByTile(tile);
   294 
   284 
   295 		wp->deleted = 30; // let it live for this many days before we do the actual deletion.
   285 		wp->deleted = 30; // let it live for this many days before we do the actual deletion.
   325  * @param p2 unused
   315  * @param p2 unused
   326  */
   316  */
   327 int32 CmdRenameWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   317 int32 CmdRenameWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   328 {
   318 {
   329 	Waypoint *wp;
   319 	Waypoint *wp;
   330 	StringID str;
       
   331 
   320 
   332 	if (!IsWaypointIndex(p1)) return CMD_ERROR;
   321 	if (!IsWaypointIndex(p1)) return CMD_ERROR;
   333 
   322 
   334 	if (_cmd_text[0] != '\0') {
   323 	if (_cmd_text[0] != '\0') {
   335 		str = AllocateNameUnique(_cmd_text, 0);
   324 		StringID str = AllocateNameUnique(_cmd_text, 0);
   336 		if (str == 0)
   325 
   337 			return CMD_ERROR;
   326 		if (str == 0) return CMD_ERROR;
   338 
   327 
   339 		if (flags & DC_EXEC) {
   328 		if (flags & DC_EXEC) {
   340 			wp = GetWaypoint(p1);
   329 			wp = GetWaypoint(p1);
   341 			if (wp->string != STR_NULL)
   330 			if (wp->string != STR_NULL) DeleteName(wp->string);
   342 				DeleteName(wp->string);
       
   343 
   331 
   344 			wp->string = str;
   332 			wp->string = str;
   345 			wp->town_cn = 0;
   333 			wp->town_cn = 0;
   346 
   334 
   347 			UpdateWaypointSign(wp);
   335 			UpdateWaypointSign(wp);
   350 			DeleteName(str);
   338 			DeleteName(str);
   351 		}
   339 		}
   352 	} else {
   340 	} else {
   353 		if (flags & DC_EXEC) {
   341 		if (flags & DC_EXEC) {
   354 			wp = GetWaypoint(p1);
   342 			wp = GetWaypoint(p1);
   355 			if (wp->string != STR_NULL)
   343 			if (wp->string != STR_NULL) DeleteName(wp->string);
   356 				DeleteName(wp->string);
       
   357 
   344 
   358 			MakeDefaultWaypointName(wp);
   345 			MakeDefaultWaypointName(wp);
   359 			UpdateWaypointSign(wp);
   346 			UpdateWaypointSign(wp);
   360 			MarkWholeScreenDirty();
   347 			MarkWholeScreenDirty();
   361 		}
   348 		}
   393 {
   380 {
   394 	Waypoint *wp;
   381 	Waypoint *wp;
   395 
   382 
   396 	/* Convert the old 'town_or_string', to 'string' / 'town' / 'town_cn' */
   383 	/* Convert the old 'town_or_string', to 'string' / 'town' / 'town_cn' */
   397 	FOR_ALL_WAYPOINTS(wp) {
   384 	FOR_ALL_WAYPOINTS(wp) {
   398 		if (wp->xy == 0)
   385 		if (wp->xy == 0) continue;
   399 			continue;
       
   400 
   386 
   401 		wp->town_index = ClosestTownFromTile(wp->xy, (uint)-1)->index;
   387 		wp->town_index = ClosestTownFromTile(wp->xy, (uint)-1)->index;
   402 		wp->town_cn = 0;
   388 		wp->town_cn = 0;
   403 		if (wp->string & 0xC000) {
   389 		if (wp->string & 0xC000) {
   404 			wp->town_cn = wp->string & 0x3F;
   390 			wp->town_cn = wp->string & 0x3F;