mirror of https://github.com/OpenTTD/OpenTTD
(svn r1783) -Add: Dynamic vehicles (now up to 64k of vehicles)
parent
88ebe22d8b
commit
42f98c7eec
2
misc.c
2
misc.c
|
@ -604,7 +604,7 @@ void IncreaseDate(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ctr = _vehicle_id_ctr_day;
|
ctr = _vehicle_id_ctr_day;
|
||||||
for (i = 0; i != (_vehicles_size / vehicles_per_day) + 1 && ctr != _vehicles_size; i++) {
|
for (i = 0; i != ((uint)GetVehiclePoolSize() / vehicles_per_day) + 1 && ctr != GetVehiclePoolSize(); i++) {
|
||||||
Vehicle *v = GetVehicle(ctr++);
|
Vehicle *v = GetVehicle(ctr++);
|
||||||
if ((t = v->type) != 0)
|
if ((t = v->type) != 0)
|
||||||
_on_new_vehicle_day_proc[t - 0x10](v);
|
_on_new_vehicle_day_proc[t - 0x10](v);
|
||||||
|
|
|
@ -797,6 +797,9 @@ static void FixVehicle(OldVehicle *o, int num)
|
||||||
if (o->type == 0)
|
if (o->type == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!AddBlockIfNeeded(&_vehicle_pool, i))
|
||||||
|
error("Vehicles: failed loading savegame: too many vehicles");
|
||||||
|
|
||||||
n = GetVehicle(i);
|
n = GetVehicle(i);
|
||||||
|
|
||||||
n->type = o->type;
|
n->type = o->type;
|
||||||
|
|
|
@ -942,7 +942,11 @@ static void *IntToReference(uint r, uint t)
|
||||||
|
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case REF_ORDER: return GetOrder(r - 1);
|
case REF_ORDER: return GetOrder(r - 1);
|
||||||
case REF_VEHICLE: return GetVehicle(r - 1);
|
case REF_VEHICLE: {
|
||||||
|
if (!AddBlockIfNeeded(&_vehicle_pool, r - 1))
|
||||||
|
error("Vehicles: failed loading savegame: too many vehicles");
|
||||||
|
return GetVehicle(r - 1);
|
||||||
|
}
|
||||||
case REF_STATION: {
|
case REF_STATION: {
|
||||||
if (!AddBlockIfNeeded(&_station_pool, r - 1))
|
if (!AddBlockIfNeeded(&_station_pool, r - 1))
|
||||||
error("Stations: failed loading savegame: too many stations");
|
error("Stations: failed loading savegame: too many stations");
|
||||||
|
@ -962,6 +966,9 @@ static void *IntToReference(uint r, uint t)
|
||||||
and the index was not - 1.. correct for this */
|
and the index was not - 1.. correct for this */
|
||||||
if (r == INVALID_VEHICLE)
|
if (r == INVALID_VEHICLE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (!AddBlockIfNeeded(&_vehicle_pool, r))
|
||||||
|
error("Vehicles: failed loading savegame: too many vehicles");
|
||||||
return GetVehicle(r);
|
return GetVehicle(r);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
2
ttd.c
2
ttd.c
|
@ -496,7 +496,6 @@ static void InitializeDynamicVariables(void)
|
||||||
{
|
{
|
||||||
/* Dynamic stuff needs to be initialized somewhere... */
|
/* Dynamic stuff needs to be initialized somewhere... */
|
||||||
_roadstops_size = lengthof(_roadstops);
|
_roadstops_size = lengthof(_roadstops);
|
||||||
_vehicles_size = lengthof(_vehicles);
|
|
||||||
_sign_size = lengthof(_sign_list);
|
_sign_size = lengthof(_sign_list);
|
||||||
_orders_size = lengthof(_orders);
|
_orders_size = lengthof(_orders);
|
||||||
|
|
||||||
|
@ -512,6 +511,7 @@ static void UnInitializeDynamicVariables(void)
|
||||||
CleanPool(&_town_pool);
|
CleanPool(&_town_pool);
|
||||||
CleanPool(&_industry_pool);
|
CleanPool(&_industry_pool);
|
||||||
CleanPool(&_station_pool);
|
CleanPool(&_station_pool);
|
||||||
|
CleanPool(&_vehicle_pool);
|
||||||
|
|
||||||
free(_station_sort);
|
free(_station_sort);
|
||||||
free(_vehicle_sort);
|
free(_vehicle_sort);
|
||||||
|
|
85
vehicle.c
85
vehicle.c
|
@ -17,9 +17,27 @@
|
||||||
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
|
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VEHICLES_MIN_FREE_FOR_AI = 90
|
/* Max vehicles: 64000 (512 * 125) */
|
||||||
|
VEHICLES_POOL_BLOCK_SIZE_BITS = 9, /* In bits, so (1 << 9) == 512 */
|
||||||
|
VEHICLES_POOL_MAX_BLOCKS = 125,
|
||||||
|
|
||||||
|
BLOCKS_FOR_SPECIAL_VEHICLES = 2, //! Blocks needed for special vehicles
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if a new block is added to the vehicle-pool
|
||||||
|
*/
|
||||||
|
static void VehiclePoolNewBlock(uint start_item)
|
||||||
|
{
|
||||||
|
Vehicle *v;
|
||||||
|
|
||||||
|
FOR_ALL_VEHICLES_FROM(v, start_item)
|
||||||
|
v->index = start_item++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the vehicle-pool */
|
||||||
|
MemoryPool _vehicle_pool = { "Vehicle", VEHICLES_POOL_MAX_BLOCKS, VEHICLES_POOL_BLOCK_SIZE_BITS, sizeof(Vehicle), &VehiclePoolNewBlock, 0, 0, NULL };
|
||||||
|
|
||||||
void VehicleServiceInDepot(Vehicle *v)
|
void VehicleServiceInDepot(Vehicle *v)
|
||||||
{
|
{
|
||||||
v->date_of_last_service = _date;
|
v->date_of_last_service = _date;
|
||||||
|
@ -205,51 +223,44 @@ static Vehicle *InitializeVehicle(Vehicle *v)
|
||||||
|
|
||||||
Vehicle *ForceAllocateSpecialVehicle(void)
|
Vehicle *ForceAllocateSpecialVehicle(void)
|
||||||
{
|
{
|
||||||
Vehicle *v;
|
/* This stays a strange story.. there should always be room for special
|
||||||
FOR_ALL_VEHICLES_FROM(v, NUM_NORMAL_VEHICLES) {
|
* vehicles (special effects all over the map), but with 65k of vehicles
|
||||||
if (v->type == 0)
|
* is this realistic to double-check for that? For now we just reserve
|
||||||
return InitializeVehicle(v);
|
* BLOCKS_FOR_SPECIAL_VEHICLES times block_size vehicles that may only
|
||||||
}
|
* be used for special vehicles.. should work nicely :) */
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Vehicle *ForceAllocateVehicle(void)
|
|
||||||
{
|
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
|
|
||||||
FOR_ALL_VEHICLES(v) {
|
FOR_ALL_VEHICLES(v) {
|
||||||
if (v->index >= NUM_NORMAL_VEHICLES)
|
/* No more room for the special vehicles, return NULL */
|
||||||
|
if (v->index >= (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (v->type == 0)
|
if (v->type == 0)
|
||||||
return InitializeVehicle(v);
|
return InitializeVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vehicle *AllocateVehicle(void)
|
Vehicle *AllocateVehicle(void)
|
||||||
{
|
{
|
||||||
|
/* See note by ForceAllocateSpecialVehicle() why we skip the
|
||||||
|
* first blocks */
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
int num;
|
|
||||||
|
|
||||||
if (IS_HUMAN_PLAYER(_current_player)) {
|
|
||||||
num = 0;
|
|
||||||
|
|
||||||
FOR_ALL_VEHICLES(v) {
|
|
||||||
if (v->index >= NUM_NORMAL_VEHICLES)
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
FOR_ALL_VEHICLES_FROM(v, (1 << _vehicle_pool.block_size_bits) * BLOCKS_FOR_SPECIAL_VEHICLES) {
|
||||||
if (v->type == 0)
|
if (v->type == 0)
|
||||||
num++;
|
return InitializeVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num <= VEHICLES_MIN_FREE_FOR_AI)
|
/* Check if we can add a block to the pool */
|
||||||
|
if (AddBlockToPool(&_vehicle_pool))
|
||||||
|
return AllocateVehicle();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ForceAllocateVehicle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
||||||
{
|
{
|
||||||
int x,y,x2,y2;
|
int x,y,x2,y2;
|
||||||
|
@ -330,19 +341,20 @@ void UpdateVehiclePosHash(Vehicle *v, int x, int y)
|
||||||
|
|
||||||
void InitializeVehicles(void)
|
void InitializeVehicles(void)
|
||||||
{
|
{
|
||||||
Vehicle *v;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Clean the vehicle pool, and reserve enough blocks
|
||||||
|
* for the special vehicles, plus one for all the other
|
||||||
|
* vehicles (which is increased on-the-fly) */
|
||||||
|
CleanPool(&_vehicle_pool);
|
||||||
|
AddBlockToPool(&_vehicle_pool);
|
||||||
|
for (i = 0; i < BLOCKS_FOR_SPECIAL_VEHICLES; i++)
|
||||||
|
AddBlockToPool(&_vehicle_pool);
|
||||||
|
|
||||||
// clear it...
|
// clear it...
|
||||||
memset(&_vehicles, 0, sizeof(_vehicles[0]) * _vehicles_size);
|
|
||||||
memset(&_waypoints, 0, sizeof(_waypoints));
|
memset(&_waypoints, 0, sizeof(_waypoints));
|
||||||
memset(&_depots, 0, sizeof(_depots));
|
memset(&_depots, 0, sizeof(_depots));
|
||||||
|
|
||||||
// setup indexes..
|
|
||||||
i = 0;
|
|
||||||
FOR_ALL_VEHICLES(v)
|
|
||||||
v->index = i++;
|
|
||||||
|
|
||||||
memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash));
|
memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2034,9 +2046,14 @@ static void Load_VEHS(void)
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
|
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
Vehicle *v = GetVehicle(index);
|
Vehicle *v;
|
||||||
|
|
||||||
|
if (!AddBlockIfNeeded(&_vehicle_pool, index))
|
||||||
|
error("Vehicles: failed loading savegame: too many vehicles");
|
||||||
|
|
||||||
|
v = GetVehicle(index);
|
||||||
SlObject(v, _veh_descs[SlReadByte()]);
|
SlObject(v, _veh_descs[SlReadByte()]);
|
||||||
|
|
||||||
if (v->type == VEH_Train)
|
if (v->type == VEH_Train)
|
||||||
v->u.rail.first_engine = 0xffff;
|
v->u.rail.first_engine = 0xffff;
|
||||||
|
|
||||||
|
@ -2088,7 +2105,7 @@ static void Load_VEHS(void)
|
||||||
|
|
||||||
/* This is to ensure all pointers are within the limits of
|
/* This is to ensure all pointers are within the limits of
|
||||||
_vehicles_size */
|
_vehicles_size */
|
||||||
if (_vehicle_id_ctr_day >= _vehicles_size)
|
if (_vehicle_id_ctr_day >= GetVehiclePoolSize())
|
||||||
_vehicle_id_ctr_day = 0;
|
_vehicle_id_ctr_day = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
vehicle.h
43
vehicle.h
|
@ -1,6 +1,7 @@
|
||||||
#ifndef VEHICLE_H
|
#ifndef VEHICLE_H
|
||||||
#define VEHICLE_H
|
#define VEHICLE_H
|
||||||
|
|
||||||
|
#include "pool.h"
|
||||||
#include "vehicle_gui.h"
|
#include "vehicle_gui.h"
|
||||||
#include "order.h"
|
#include "order.h"
|
||||||
|
|
||||||
|
@ -359,34 +360,42 @@ byte GetDirectionTowards(Vehicle *v, int x, int y);
|
||||||
#define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL);
|
#define END_ENUM_WAGONS(v) } while ( (v=v->next) != NULL);
|
||||||
|
|
||||||
/* vehicle.c */
|
/* vehicle.c */
|
||||||
enum {
|
|
||||||
NUM_NORMAL_VEHICLES = 2048,
|
|
||||||
NUM_SPECIAL_VEHICLES = 512,
|
|
||||||
NUM_VEHICLES = NUM_NORMAL_VEHICLES + NUM_SPECIAL_VEHICLES
|
|
||||||
};
|
|
||||||
|
|
||||||
VARDEF Vehicle _vehicles[NUM_VEHICLES];
|
|
||||||
VARDEF uint _vehicles_size;
|
|
||||||
|
|
||||||
VARDEF SortStruct *_vehicle_sort;
|
VARDEF SortStruct *_vehicle_sort;
|
||||||
|
|
||||||
static inline Vehicle *GetVehicle(uint index)
|
extern MemoryPool _vehicle_pool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the pointer to the vehicle with index 'index'
|
||||||
|
*/
|
||||||
|
static inline Vehicle *GetVehicle(VehicleID index)
|
||||||
{
|
{
|
||||||
assert(index < _vehicles_size);
|
return (Vehicle*)GetItemFromPool(&_vehicle_pool, index);
|
||||||
return &_vehicles[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current size of the VehiclePool
|
||||||
|
*/
|
||||||
|
static inline uint16 GetVehiclePoolSize(void)
|
||||||
|
{
|
||||||
|
return _vehicle_pool.total_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOR_ALL_VEHICLES_FROM(v, start) for (v = GetVehicle(start); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL)
|
||||||
|
#define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an index is a vehicle-index (so between 0 and max-vehicles)
|
||||||
|
*
|
||||||
|
* @return Returns true if the vehicle-id is in range
|
||||||
|
*/
|
||||||
static inline bool IsVehicleIndex(uint index)
|
static inline bool IsVehicleIndex(uint index)
|
||||||
{
|
{
|
||||||
if (index < _vehicles_size)
|
if (index < GetVehiclePoolSize())
|
||||||
return true;
|
return true;
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++)
|
|
||||||
#define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++)
|
|
||||||
|
|
||||||
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
|
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
|
||||||
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
|
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station)
|
||||||
if (!(vl->flags & VL_REBUILD)) return;
|
if (!(vl->flags & VL_REBUILD)) return;
|
||||||
|
|
||||||
/* Create array for sorting */
|
/* Create array for sorting */
|
||||||
_vehicle_sort = realloc(_vehicle_sort, _vehicles_size * sizeof(_vehicle_sort[0]));
|
_vehicle_sort = realloc(_vehicle_sort, GetVehiclePoolSize() * sizeof(_vehicle_sort[0]));
|
||||||
if (_vehicle_sort == NULL)
|
if (_vehicle_sort == NULL)
|
||||||
error("Could not allocate memory for the vehicle-sorting-list");
|
error("Could not allocate memory for the vehicle-sorting-list");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue