* Returns the engine associated to a certain internal_id, resp. allocates it. * @param file NewGRF that wants to change the engine. * @param type Vehicle type. * @param internal_id Engine ID inside the NewGRF. * @param static_access If the engine is not present, return nullptr instead of allocating a new engine. (Used for static Action 0x04). * @return The requested engine. */
| 212 | * @return The requested engine. |
| 213 | */ |
| 214 | Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access) |
| 215 | { |
| 216 | /* Hack for add-on GRFs that need to modify another GRF's engines. This lets |
| 217 | * them use the same engine slots. */ |
| 218 | uint32_t scope_grfid = INVALID_GRFID; // If not using dynamic_engines, all newgrfs share their ID range |
| 219 | if (_settings_game.vehicle.dynamic_engines) { |
| 220 | /* If dynamic_engies is enabled, there can be multiple independent ID ranges. */ |
| 221 | scope_grfid = file->grfid; |
| 222 | if (auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) { |
| 223 | scope_grfid = it->second; |
| 224 | const GRFFile *grf_match = GetFileByGRFID(scope_grfid); |
| 225 | if (grf_match == nullptr) { |
| 226 | GrfMsg(5, "Tried mapping from GRFID {:x} to {:x} but target is not loaded", std::byteswap(file->grfid), std::byteswap(scope_grfid)); |
| 227 | } else { |
| 228 | GrfMsg(5, "Mapping from GRFID {:x} to {:x}", std::byteswap(file->grfid), std::byteswap(scope_grfid)); |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | /* Check if the engine is registered in the override manager */ |
| 233 | EngineID engine = _engine_mngr.GetID(type, internal_id, scope_grfid); |
| 234 | if (engine != EngineID::Invalid()) { |
| 235 | Engine *e = Engine::Get(engine); |
| 236 | if (!e->grf_prop.HasGrfFile()) { |
| 237 | e->grf_prop.SetGRFFile(file); |
| 238 | } |
| 239 | return e; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | /* Check if there is an unreserved slot */ |
| 244 | EngineID engine = _engine_mngr.UseUnreservedID(type, internal_id, scope_grfid, static_access); |
| 245 | if (engine != EngineID::Invalid()) { |
| 246 | Engine *e = Engine::Get(engine); |
| 247 | |
| 248 | if (!e->grf_prop.HasGrfFile()) { |
| 249 | e->grf_prop.SetGRFFile(file); |
| 250 | GrfMsg(5, "Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->index, std::byteswap(file->grfid), type, internal_id); |
| 251 | } |
| 252 | |
| 253 | return e; |
| 254 | } |
| 255 | |
| 256 | if (static_access) return nullptr; |
| 257 | |
| 258 | if (!Engine::CanAllocateItem()) { |
| 259 | GrfMsg(0, "Can't allocate any more engines"); |
| 260 | return nullptr; |
| 261 | } |
| 262 | |
| 263 | size_t engine_pool_size = Engine::GetPoolSize(); |
| 264 | |
| 265 | /* ... it's not, so create a new one based off an existing engine */ |
| 266 | Engine *e = new Engine(type, internal_id); |
| 267 | e->grf_prop.SetGRFFile(file); |
| 268 | |
| 269 | /* Reserve the engine slot */ |
| 270 | _engine_mngr.SetID(type, internal_id, scope_grfid, std::min<uint8_t>(internal_id, _engine_counts[type]), e->index); |
| 271 |
no test coverage detected