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; |
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; |
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 } |