src/vehicle.cpp
branchcpp_gui
changeset 6308 646711c5feaa
parent 6307 f40e88cff863
equal deleted inserted replaced
6307:f40e88cff863 6308:646711c5feaa
   186 		Swap(x1, x2);
   186 		Swap(x1, x2);
   187 		Swap(y1, y2);
   187 		Swap(y1, y2);
   188 	}
   188 	}
   189 	FOR_ALL_VEHICLES(veh) {
   189 	FOR_ALL_VEHICLES(veh) {
   190 		if (without_crashed && (veh->vehstatus & VS_CRASHED) != 0) continue;
   190 		if (without_crashed && (veh->vehstatus & VS_CRASHED) != 0) continue;
   191 		if ((veh->type == VEH_TRAIN || veh->type == VEH_ROAD) && (z==0xFF || veh->z_pos == z)) {
   191 		if ((veh->type == VEH_TRAIN || veh->type == VEH_ROAD) && (z == 0xFF || veh->z_pos == z)) {
   192 			if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 &&
   192 			if ((veh->x_pos >> 4) >= x1 && (veh->x_pos >> 4) <= x2 &&
   193 					(veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) {
   193 					(veh->y_pos >> 4) >= y1 && (veh->y_pos >> 4) <= y2) {
   194 				return veh;
   194 				return veh;
   195 			}
   195 			}
   196 		}
   196 		}
   197 	}
   197 	}
   198 	return NULL;
   198 	return NULL;
   249 					/* In the case of a helicopter we will update the rotor sprites */
   249 					/* In the case of a helicopter we will update the rotor sprites */
   250 					if (v->subtype == AIR_HELICOPTER) {
   250 					if (v->subtype == AIR_HELICOPTER) {
   251 						Vehicle *rotor = shadow->next;
   251 						Vehicle *rotor = shadow->next;
   252 						rotor->cur_image = GetRotorImage(v);
   252 						rotor->cur_image = GetRotorImage(v);
   253 					}
   253 					}
       
   254 
       
   255 					UpdateAircraftCache(v);
   254 				}
   256 				}
   255 				break;
   257 				break;
   256 			default: break;
   258 			default: break;
   257 		}
   259 		}
   258 
   260 
   417 {
   419 {
   418 	Vehicle **old_hash, **new_hash;
   420 	Vehicle **old_hash, **new_hash;
   419 	int old_x = v->left_coord;
   421 	int old_x = v->left_coord;
   420 	int old_y = v->top_coord;
   422 	int old_y = v->top_coord;
   421 
   423 
   422 	new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(x,y)];
   424 	new_hash = (x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(x, y)];
   423 	old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(old_x, old_y)];
   425 	old_hash = (old_x == INVALID_COORD) ? NULL : &_vehicle_position_hash[GEN_HASH(old_x, old_y)];
   424 
   426 
   425 	if (old_hash == new_hash) return;
   427 	if (old_hash == new_hash) return;
   426 
   428 
   427 	/* remove from hash table? */
   429 	/* remove from hash table? */
   566 	}
   568 	}
   567 }
   569 }
   568 
   570 
   569 void DestroyVehicle(Vehicle *v)
   571 void DestroyVehicle(Vehicle *v)
   570 {
   572 {
       
   573 	if (IsValidStationID(v->last_station_visited)) {
       
   574 		GetStation(v->last_station_visited)->loading_vehicles.remove(v);
       
   575 	}
       
   576 
   571 	if (IsEngineCountable(v)) {
   577 	if (IsEngineCountable(v)) {
   572 		GetPlayer(v->owner)->num_engines[v->engine_type]--;
   578 		GetPlayer(v->owner)->num_engines[v->engine_type]--;
   573 		if (v->owner == _local_player) InvalidateAutoreplaceWindow(v->engine_type);
   579 		if (v->owner == _local_player) InvalidateAutoreplaceWindow(v->engine_type);
   574 	}
   580 	}
   575 
   581 
   765 {
   771 {
   766 	return HASBIT(EngInfo(engine_type)->refit_mask, cid_to);
   772 	return HASBIT(EngInfo(engine_type)->refit_mask, cid_to);
   767 }
   773 }
   768 
   774 
   769 /** Find the first cargo type that an engine can be refitted to.
   775 /** Find the first cargo type that an engine can be refitted to.
   770  * @param engine Which engine to find cargo for.
   776  * @param engine_type Which engine to find cargo for.
   771  * @return A climate dependent cargo type. CT_INVALID is returned if not refittable.
   777  * @return A climate dependent cargo type. CT_INVALID is returned if not refittable.
   772  */
   778  */
   773 CargoID FindFirstRefittableCargo(EngineID engine_type)
   779 CargoID FindFirstRefittableCargo(EngineID engine_type)
   774 {
   780 {
   775 	uint32 refit_mask = EngInfo(engine_type)->refit_mask;
   781 	uint32 refit_mask = EngInfo(engine_type)->refit_mask;
   782 
   788 
   783 	return CT_INVALID;
   789 	return CT_INVALID;
   784 }
   790 }
   785 
   791 
   786 /** Learn the price of refitting a certain engine
   792 /** Learn the price of refitting a certain engine
   787 * @param engine Which engine to refit
   793 * @param engine_type Which engine to refit
   788 * @return Price for refitting
   794 * @return Price for refitting
   789 */
   795 */
   790 int32 GetRefitCost(EngineID engine_type)
   796 int32 GetRefitCost(EngineID engine_type)
   791 {
   797 {
   792 	int32 base_cost = 0;
   798 	int32 base_cost = 0;
  1835 
  1841 
  1836 	v = v_front;
  1842 	v = v_front;
  1837 
  1843 
  1838 	do {
  1844 	do {
  1839 
  1845 
       
  1846 		if (!(flags & DC_EXEC)) {
       
  1847 			/* Get the refit cost.
       
  1848 			 * This is only needed when estimating as when the command is executed, the cost from the refit command is used.
       
  1849 			 * This needs to be done for every single unit, so it should be done before checking if it's a multiheaded engine. */
       
  1850 			CargoID new_cargo_type = GetEngineCargoType(v->engine_type);
       
  1851 
       
  1852 			if (new_cargo_type != v->cargo_type && new_cargo_type != CT_INVALID) {
       
  1853 				total_cost += GetRefitCost(v->engine_type);
       
  1854 			}
       
  1855 		}
       
  1856 
  1840 		if (IsMultiheaded(v) && !IsTrainEngine(v)) {
  1857 		if (IsMultiheaded(v) && !IsTrainEngine(v)) {
  1841 			/* we build the rear ends of multiheaded trains with the front ones */
  1858 			/* we build the rear ends of multiheaded trains with the front ones */
  1842 			continue;
  1859 			continue;
  1843 		}
  1860 		}
  1844 
  1861 
  1857 			do {
  1874 			do {
  1858 				if (v2->cargo_type != w2->cargo_type || v2->cargo_subtype != w2->cargo_subtype) {
  1875 				if (v2->cargo_type != w2->cargo_type || v2->cargo_subtype != w2->cargo_subtype) {
  1859 					/* We can't pay for refitting because we can't estimate refitting costs for a vehicle before it's build.
  1876 					/* We can't pay for refitting because we can't estimate refitting costs for a vehicle before it's build.
  1860 					 * If we pay for it anyway, the cost and the estimated cost will not be the same and we will have an assert.
  1877 					 * If we pay for it anyway, the cost and the estimated cost will not be the same and we will have an assert.
  1861 					 * We need to check the whole chain if it is a train because some newgrf articulated engines can refit some units only (and not the front) */
  1878 					 * We need to check the whole chain if it is a train because some newgrf articulated engines can refit some units only (and not the front) */
  1862 					DoCommand(0, w->index, v2->cargo_type | (v2->cargo_subtype << 8), flags, GetCmdRefitVeh(v));
  1879 					total_cost += DoCommand(0, w->index, v2->cargo_type | (v2->cargo_subtype << 8), flags, GetCmdRefitVeh(v));
  1863 					break; // We learned that the engine in question needed a refit. No need to check anymore
  1880 					break; // We learned that the engine in question needed a refit. No need to check anymore
  1864 				}
  1881 				}
  1865 			} while (v->type == VEH_TRAIN && (w2 = w2->next) != NULL && (v2 = v2->next) != NULL);
  1882 			} while (v->type == VEH_TRAIN && (w2 = w2->next) != NULL && (v2 = v2->next) != NULL);
  1866 
  1883 
  1867 			if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1884 			if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1902 }
  1919 }
  1903 
  1920 
  1904 /** Generates a list of vehicles inside a depot
  1921 /** Generates a list of vehicles inside a depot
  1905  * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0)
  1922  * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0)
  1906  * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL
  1923  * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL
  1907  * @param Type type of vehicle
  1924  * @param type Type of vehicle
  1908  * @param tile The tile the depot is located in
  1925  * @param tile The tile the depot is located in
  1909  * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced)
  1926  * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced)
  1910  * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array
  1927  * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array
  1911  * @param *engine_count The number of engines stored in the list
  1928  * @param *engine_count The number of engines stored in the list
  1912  * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced)
  1929  * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced)
  1984 /**
  2001 /**
  1985 * @param sort_list list to store the list in. Either NULL or the length length_of_array tells
  2002 * @param sort_list list to store the list in. Either NULL or the length length_of_array tells
  1986 * @param length_of_array informs the length allocated for sort_list. This is not the same as the number of vehicles in the list. Needs to be 0 when sort_list is NULL
  2003 * @param length_of_array informs the length allocated for sort_list. This is not the same as the number of vehicles in the list. Needs to be 0 when sort_list is NULL
  1987 * @param type type of vehicle
  2004 * @param type type of vehicle
  1988 * @param owner PlayerID of owner to generate a list for
  2005 * @param owner PlayerID of owner to generate a list for
  1989 * @param index This parameter got different meanings depending on window_type
  2006 * @param index This parameter has different meanings depending on window_type
  1990 			VLW_STATION_LIST:  index of station to generate a list for
  2007     <ul>
  1991 			VLW_SHARED_ORDERS: index of order to generate a list for
  2008       <li>VLW_STATION_LIST:  index of station to generate a list for</li>
  1992 			VLW_STANDARD: not used
  2009       <li>VLW_SHARED_ORDERS: index of order to generate a list for<li>
  1993 			VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for
  2010       <li>VLW_STANDARD: not used<li>
       
  2011       <li>VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for</li>
       
  2012     </ul>
  1994 * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
  2013 * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
  1995 * @return the number of vehicles added to the list
  2014 * @return the number of vehicles added to the list
  1996 */
  2015 */
  1997 uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type)
  2016 uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type)
  1998 {
  2017 {
  2086 /** send all vehicles of type to depots
  2105 /** send all vehicles of type to depots
  2087  * @param type type of vehicle
  2106  * @param type type of vehicle
  2088  * @param flags the flags used for DoCommand()
  2107  * @param flags the flags used for DoCommand()
  2089  * @param service should the vehicles only get service in the depots
  2108  * @param service should the vehicles only get service in the depots
  2090  * @param owner PlayerID of owner of the vehicles to send
  2109  * @param owner PlayerID of owner of the vehicles to send
  2091  * @param VLW_flag tells what kind of list requested the goto depot
  2110  * @param vlw_flag tells what kind of list requested the goto depot
  2092  * @return 0 for success and CMD_ERROR if no vehicle is able to go to depot
  2111  * @return 0 for success and CMD_ERROR if no vehicle is able to go to depot
  2093  */
  2112  */
  2094 int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
  2113 int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
  2095 {
  2114 {
  2096 	const Vehicle **sort_list = NULL;
  2115 	const Vehicle **sort_list = NULL;
  2217 					case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN;    break;
  2236 					case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN;    break;
  2218 					default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning
  2237 					default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning
  2219 				}
  2238 				}
  2220 
  2239 
  2221 				SetDParam(0, v->unitnumber);
  2240 				SetDParam(0, v->unitnumber);
  2222 				AddNewsItem(string, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),	v->index, 0);
  2241 				AddNewsItem(string, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
  2223 			}
  2242 			}
  2224 		}
  2243 		}
  2225 	}
  2244 	}
  2226 }
  2245 }
  2227 
  2246 
  2446 	}
  2465 	}
  2447 
  2466 
  2448 	return unit;
  2467 	return unit;
  2449 }
  2468 }
  2450 
  2469 
  2451 static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
  2470 
  2452 {
  2471 const Livery *GetEngineLivery(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
  2453 	SpriteID map = PAL_NONE;
  2472 {
  2454 	const Player *p = GetPlayer(player);
  2473 	const Player *p = GetPlayer(player);
  2455 	LiveryScheme scheme = LS_DEFAULT;
  2474 	LiveryScheme scheme = LS_DEFAULT;
  2456 	CargoID cargo_type = v == NULL ? (CargoID)CT_INVALID : v->cargo_type;
  2475 	CargoID cargo_type = v == NULL ? (CargoID)CT_INVALID : v->cargo_type;
  2457 
       
  2458 	/* Check if we should use the colour map callback */
       
  2459 	if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_COLOUR_REMAP)) {
       
  2460 		uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
       
  2461 		/* A return value of 0xC000 is stated to "use the default two-color
       
  2462 		 * maps" which happens to be the failure action too... */
       
  2463 		if (callback != CALLBACK_FAILED && callback != 0xC000) {
       
  2464 			map = GB(callback, 0, 14);
       
  2465 			/* If bit 14 is set, then the company colours are applied to the
       
  2466 			 * map else it's returned as-is. */
       
  2467 			if (!HASBIT(callback, 14)) return map;
       
  2468 		}
       
  2469 	}
       
  2470 
  2476 
  2471 	/* The default livery is always available for use, but its in_use flag determines
  2477 	/* The default livery is always available for use, but its in_use flag determines
  2472 	 * whether any _other_ liveries are in use. */
  2478 	 * whether any _other_ liveries are in use. */
  2473 	if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) {
  2479 	if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) {
  2474 		/* Determine the livery scheme to use */
  2480 		/* Determine the livery scheme to use */
  2542 
  2548 
  2543 		/* Switch back to the default scheme if the resolved scheme is not in use */
  2549 		/* Switch back to the default scheme if the resolved scheme is not in use */
  2544 		if (!p->livery[scheme].in_use) scheme = LS_DEFAULT;
  2550 		if (!p->livery[scheme].in_use) scheme = LS_DEFAULT;
  2545 	}
  2551 	}
  2546 
  2552 
       
  2553 	return &p->livery[scheme];
       
  2554 }
       
  2555 
       
  2556 
       
  2557 static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
       
  2558 {
       
  2559 	SpriteID map = PAL_NONE;
       
  2560 
       
  2561 	/* Check if we should use the colour map callback */
       
  2562 	if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_COLOUR_REMAP)) {
       
  2563 		uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
       
  2564 		/* A return value of 0xC000 is stated to "use the default two-color
       
  2565 		 * maps" which happens to be the failure action too... */
       
  2566 		if (callback != CALLBACK_FAILED && callback != 0xC000) {
       
  2567 			map = GB(callback, 0, 14);
       
  2568 			/* If bit 14 is set, then the company colours are applied to the
       
  2569 			 * map else it's returned as-is. */
       
  2570 			if (!HASBIT(callback, 14)) return map;
       
  2571 		}
       
  2572 	}
       
  2573 
  2547 	bool twocc = HASBIT(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
  2574 	bool twocc = HASBIT(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
  2548 
  2575 
  2549 	if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOR_START;
  2576 	if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOR_START;
  2550 
  2577 
  2551 	map += p->livery[scheme].colour1;
  2578 	const Livery *livery = GetEngineLivery(engine_type, player, parent_engine_type, v);
  2552 	if (twocc) map += p->livery[scheme].colour2 * 16;
  2579 
       
  2580 	map += livery->colour1;
       
  2581 	if (twocc) map += livery->colour2 * 16;
  2553 
  2582 
  2554 	return map;
  2583 	return map;
  2555 }
  2584 }
  2556 
  2585 
  2557 SpriteID GetEnginePalette(EngineID engine_type, PlayerID player)
  2586 SpriteID GetEnginePalette(EngineID engine_type, PlayerID player)
  2897 
  2926 
  2898 void Vehicle::BeginLoading()
  2927 void Vehicle::BeginLoading()
  2899 {
  2928 {
  2900 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  2929 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  2901 	current_order.type = OT_LOADING;
  2930 	current_order.type = OT_LOADING;
       
  2931 	GetStation(this->last_station_visited)->loading_vehicles.push_back(this);
  2902 }
  2932 }
  2903 
  2933 
  2904 void Vehicle::LeaveStation()
  2934 void Vehicle::LeaveStation()
  2905 {
  2935 {
  2906 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  2936 	assert(IsTileType(tile, MP_STATION) || type == VEH_SHIP);
  2907 	assert(current_order.type == OT_LOADING);
  2937 	assert(current_order.type == OT_LOADING);
  2908 	current_order.type = OT_LEAVESTATION;
  2938 	current_order.type = OT_LEAVESTATION;
  2909 	current_order.flags = 0;
  2939 	current_order.flags = 0;
  2910 }
  2940 	GetStation(this->last_station_visited)->loading_vehicles.remove(this);
       
  2941 }