CUnit* CUnitLoader::LoadUnit(const UnitLoadParams& cparams) { CUnit* unit = NULL; UnitLoadParams& params = const_cast<UnitLoadParams&>(cparams); { GML_RECMUTEX_LOCK(sel); // LoadUnit - for anti deadlock purposes. GML_RECMUTEX_LOCK(quad); // LoadUnit - make sure other threads cannot access an incomplete unit const UnitDef* ud = params.unitDef; if (ud == NULL) return unit; // need to check this BEFORE creating the instance if (!unitHandler->CanAddUnit(cparams.unitID)) return unit; if (params.teamID < 0) { // FIXME use gs->gaiaTeamID ? (once it is always enabled) if ((params.teamID = teamHandler->GaiaTeamID()) < 0) throw content_error("Invalid team and no gaia team to put unit in"); } if (ud->IsTransportUnit()) { unit = new CTransportUnit(); } else if (ud->IsFactoryUnit()) { // special static builder structures that can always be given // move orders (which are passed on to all mobile buildees) unit = new CFactory(); } else if (ud->IsMobileBuilderUnit() || ud->IsStaticBuilderUnit()) { // all other types of non-structure "builders", including hubs and // nano-towers (the latter should not have any build-options at all, // whereas the former should be unable to build any mobile units) unit = new CBuilder(); } else if (ud->IsBuildingUnit()) { // static non-builder structures if (ud->IsExtractorUnit()) { unit = new CExtractorBuilding(); } else { unit = new CBuilding(); } } else { // regular mobile unit unit = new CUnit(); } unit->PreInit(params); if (ud->IsTransportUnit()) { new CTransportCAI(unit); } else if (ud->IsFactoryUnit()) { new CFactoryCAI(unit); } else if (ud->IsMobileBuilderUnit() || ud->IsStaticBuilderUnit()) { new CBuilderCAI(unit); } else if (ud->IsStrafingAirUnit()) { // non-hovering fighter or bomber aircraft; coupled to StrafeAirMoveType new CAirCAI(unit); } else if (ud->IsAirUnit()) { // all other aircraft; coupled to HoverAirMoveType new CMobileCAI(unit); } else if (ud->IsGroundUnit()) { new CMobileCAI(unit); } else { new CCommandAI(unit); } } unit->PostInit(params.builder); (eventBatchHandler->GetUnitCreatedDestroyedBatch()).enqueue(EventBatchHandler::UD(unit, unit->isCloaked)); if (params.flattenGround) { FlattenGround(unit); } return unit; }
CUnit* CUnitLoader::LoadUnit(const UnitDef* ud, const float3& pos, int team, bool build, int facing, const CUnit* builder) { CUnit* unit = NULL; SCOPED_TIMER("UnitLoader::LoadUnit"); { GML_RECMUTEX_LOCK(sel); // LoadUnit - for anti deadlock purposes. GML_RECMUTEX_LOCK(quad); // LoadUnit - make sure other threads cannot access an incomplete unit if (team < 0) { team = teamHandler->GaiaTeamID(); // FIXME use gs->gaiaTeamID ? (once it is always enabled) if (team < 0) throw content_error("Invalid team and no gaia team to put unit in"); } if (ud->IsTransportUnit()) { unit = new CTransportUnit(); } else if (ud->IsFactoryUnit()) { // special static builder structures that can always be given // move orders (which are passed on to all mobile buildees) unit = new CFactory(); } else if (ud->IsMobileBuilderUnit() || ud->IsStaticBuilderUnit()) { // all other types of non-structure "builders", including hubs and // nano-towers (the latter should not have any build-options at all, // whereas the former should be unable to build any mobile units) unit = new CBuilder(); } else if (ud->IsBuildingUnit()) { // static non-builder structures if (ud->IsExtractorUnit()) { unit = new CExtractorBuilding(); } else { unit = new CBuilding(); } } else { // regular mobile unit unit = new CUnit(); } unit->PreInit(ud, team, facing, pos, build); if (ud->IsTransportUnit()) { new CTransportCAI(unit); } else if (ud->IsFactoryUnit()) { new CFactoryCAI(unit); } else if (ud->IsMobileBuilderUnit() || ud->IsStaticBuilderUnit()) { new CBuilderCAI(unit); } else if (ud->IsNonHoveringAirUnit()) { // non-hovering fighter or bomber aircraft; coupled to StrafeAirMoveType new CAirCAI(unit); } else if (ud->IsAirUnit()) { // all other aircraft; coupled to HoverAirMoveType new CMobileCAI(unit); } else if (ud->IsGroundUnit()) { new CMobileCAI(unit); } else { new CCommandAI(unit); } } unit->PostInit(builder); (eventBatchHandler->GetUnitCreatedDestroyedBatch()).enqueue(EventBatchHandler::UD(unit, unit->isCloaked)); return unit; }