/** * @brief Sells the given aircraft with all the equipment. * @param aircraft The aircraft to sell * @return @c true if the aircraft could get sold, @c false otherwise */ bool BS_SellAircraft (aircraft_t* aircraft) { int j; if (AIR_GetTeamSize(aircraft) > 0) return false; if (!AIR_IsAircraftInBase(aircraft)) return false; /* sell off any items which are mounted on it */ for (j = 0; j < aircraft->maxWeapons; j++) { const aircraftSlot_t* slot = &aircraft->weapons[j]; BS_ProcessCraftItemSale(slot->item, 1); BS_ProcessCraftItemSale(slot->ammo, 1); } BS_ProcessCraftItemSale(aircraft->shield.item, 1); /* there should be no ammo here, but checking can't hurt */ BS_ProcessCraftItemSale(aircraft->shield.ammo, 1); for (j = 0; j < aircraft->maxElectronics; j++) { const aircraftSlot_t* slot = &aircraft->electronics[j]; BS_ProcessCraftItemSale(slot->item, 1); /* there should be no ammo here, but checking can't hurt */ BS_ProcessCraftItemSale(slot->ammo, 1); } /* the capacities are also updated here */ BS_AddAircraftToMarket(aircraft, 1); CP_UpdateCredits(ccs.credits + BS_GetAircraftSellingPrice(aircraft)); AIR_DeleteAircraft(aircraft); return true; }
/** * @brief Actions to perform when destroying one hangar. * @param[in] base Pointer to the base where hangar is destroyed. * @param[in] capacity Type of hangar capacity: CAP_AIRCRAFT_SMALL or CAP_AIRCRAFT_BIG * @note called when player destroy its building or hangar is destroyed during base attack. * @note These actions will be performed after we actually remove the building. * @pre we checked before calling this function that all parameters are valid. * @pre building is not under construction. * @sa B_BuildingDestroy_f * @todo If player choose to destroy the building, a popup should ask him if he wants to sell aircraft in it. */ void CAP_RemoveAircraftExceedingCapacity (base_t* base, baseCapacities_t capacity) { linkedList_t *awayAircraft = nullptr; int numAwayAircraft; int randomNum; /* destroy aircraft only if there's not enough hangar (hangar is already destroyed) */ if (CAP_GetFreeCapacity(base, capacity) >= 0) return; /* destroy one aircraft (must not be sold: may be destroyed by aliens) */ AIR_ForeachFromBase(aircraft, base) { const int aircraftSize = aircraft->size; switch (aircraftSize) { case AIRCRAFT_SMALL: if (capacity != CAP_AIRCRAFT_SMALL) continue; break; case AIRCRAFT_LARGE: if (capacity != CAP_AIRCRAFT_BIG) continue; break; default: cgi->Com_Error(ERR_DROP, "B_RemoveAircraftExceedingCapacity: Unknown type of aircraft '%i'", aircraftSize); } /* Only aircraft in hangar will be destroyed by hangar destruction */ if (!AIR_IsAircraftInBase(aircraft)) { if (AIR_IsAircraftOnGeoscape(aircraft)) cgi->LIST_AddPointer(&awayAircraft, (void*)aircraft); continue; } /* Remove aircraft and aircraft items, but do not fire employees */ AIR_DeleteAircraft(aircraft); cgi->LIST_Delete(&awayAircraft); return; } numAwayAircraft = cgi->LIST_Count(awayAircraft); if (!numAwayAircraft) return; /* All aircraft are away from base, pick up one and change it's homebase */ randomNum = rand() % numAwayAircraft; if (!CL_DisplayHomebasePopup((aircraft_t*)cgi->LIST_GetByIdx(awayAircraft, randomNum), false)) { aircraft_t *aircraft = (aircraft_t*)cgi->LIST_GetByIdx(awayAircraft, randomNum); /* No base can hold this aircraft */ UFO_NotifyPhalanxAircraftRemoved(aircraft); if (!MapIsWater(GEO_GetColor(aircraft->pos, MAPTYPE_TERRAIN, nullptr))) CP_SpawnRescueMission(aircraft, nullptr); else { /* Destroy the aircraft and everything onboard - the aircraft pointer * is no longer valid after this point */ /* Pilot skills; really kill pilot in this case? */ AIR_DestroyAircraft(aircraft); } } cgi->LIST_Delete(&awayAircraft); }
TEST_F(CampaignTest, testAircraftHandling) { const vec2_t destination = { 10, 10 }; base_t* base; aircraft_t* aircraft; aircraft_t* newAircraft; aircraft_t* aircraftTemplate; int firstIdx; int initialCount; int count; int newFound; base = CreateBase("unittestaircraft", destination); ASSERT_TRUE(nullptr != base); /** @todo we should not assume that initial base has aircraft. It's a campaign parameter */ aircraft = AIR_GetFirstFromBase(base); ASSERT_TRUE(nullptr != aircraft); /* aircraft should have a template */ aircraftTemplate = aircraft->tpl; ASSERT_TRUE(nullptr != aircraftTemplate); firstIdx = aircraft->idx; initialCount = AIR_BaseCountAircraft(base); /* test deletion (part 1) */ AIR_DeleteAircraft(aircraft); count = AIR_BaseCountAircraft(base); ASSERT_EQ(count, initialCount - 1); /* test addition (part 1) */ newAircraft = AIR_NewAircraft(base, aircraftTemplate); ASSERT_TRUE(nullptr != newAircraft); count = AIR_BaseCountAircraft(base); ASSERT_EQ(count, initialCount); /* new aircraft assigned to the right base */ ASSERT_EQ(newAircraft->homebase, base); newFound = 0; AIR_Foreach(a) { /* test deletion (part 2) */ ASSERT_NE(firstIdx, a->idx); /* for test addition (part 2) */ if (a->idx == newAircraft->idx) newFound++; } /* test addition (part 2) */ ASSERT_EQ(newFound, 1); /* check if AIR_Foreach iterates through all aircraft */ AIR_Foreach(a) { AIR_DeleteAircraft(a); } aircraft = AIR_GetFirstFromBase(base); ASSERT_TRUE(nullptr == aircraft); count = AIR_BaseCountAircraft(base); ASSERT_EQ(count, 0); /* cleanup for the following tests */ E_DeleteAllEmployees(nullptr); base->founded = false; }
static void testAircraftHandling (void) { const vec2_t destination = { 10, 10 }; campaign_t *campaign; base_t *base; aircraft_t *aircraft; aircraft_t *newAircraft; aircraft_t *aircraftTemplate; int firstIdx; int initialCount; int count; int newFound; ResetCampaignData(); campaign = GetCampaign(); base = CreateBase("unittestaircraft", destination); CU_ASSERT_PTR_NOT_NULL_FATAL(base); /** @todo we should not assume that initial base has aircraft. It's a campaign parameter */ aircraft = AIR_GetFirstFromBase(base); CU_ASSERT_PTR_NOT_NULL_FATAL(aircraft); /* aircraft should have a template */ aircraftTemplate = aircraft->tpl; CU_ASSERT_PTR_NOT_NULL_FATAL(aircraftTemplate); firstIdx = aircraft->idx; initialCount = AIR_BaseCountAircraft(base); /* test deletion (part 1) */ AIR_DeleteAircraft(aircraft); count = AIR_BaseCountAircraft(base); CU_ASSERT_EQUAL(count, initialCount - 1); /* test addition (part 1) */ newAircraft = AIR_NewAircraft(base, aircraftTemplate); CU_ASSERT_PTR_NOT_NULL_FATAL(newAircraft); count = AIR_BaseCountAircraft(base); CU_ASSERT_EQUAL(count, initialCount); /* new aircraft assigned to the right base */ CU_ASSERT_EQUAL(newAircraft->homebase, base); newFound = 0; AIR_Foreach(aircraft) { /* test deletion (part 2) */ CU_ASSERT_NOT_EQUAL(firstIdx, aircraft->idx); /* for test addition (part 2) */ if (aircraft->idx == newAircraft->idx) newFound++; } /* test addition (part 2) */ CU_ASSERT_EQUAL(newFound, 1); /* check if AIR_Foreach iterates through all aircraft */ AIR_Foreach(aircraft) { AIR_DeleteAircraft(aircraft); } aircraft = AIR_GetFirstFromBase(base); CU_ASSERT_PTR_NULL_FATAL(aircraft); count = AIR_BaseCountAircraft(base); CU_ASSERT_EQUAL(count, 0); /* cleanup for the following tests */ E_DeleteAllEmployees(NULL); base->founded = qfalse; }