/** * @brief Remove a defence system from base. * @note 1st argument is the basedefence system type to destroy (sa basedefenceType_t). * @note 2nd argument is the idx of the base in which you want the battery to be destroyed. * @note if the first argument is BASEDEF_RANDOM, the type of the battery to destroy is randomly selected * @note the building must already be removed from ccs.buildings[baseIdx][] */ static void BDEF_RemoveBattery_f (void) { basedefenceType_t basedefType; int baseIdx; base_t* base; if (cgi->Cmd_Argc() < 3) { Com_Printf("Usage: %s <basedefType> <baseIdx>", cgi->Cmd_Argv(0)); return; } else { char type[MAX_VAR]; Q_strncpyz(type, cgi->Cmd_Argv(1), sizeof(type)); if (Q_streq(type, "missile")) basedefType = BASEDEF_MISSILE; else if (Q_streq(type, "laser")) basedefType = BASEDEF_LASER; else if (Q_streq(type, "random")) basedefType = BASEDEF_RANDOM; else return; baseIdx = atoi(cgi->Cmd_Argv(2)); } /* Check that the baseIdx exists */ if (baseIdx < 0 || baseIdx >= B_GetCount()) { Com_Printf("BDEF_RemoveBattery_f: baseIdx %i doesn't exist: there is only %i bases in game.\n", baseIdx, B_GetCount()); return; } base = B_GetFoundedBaseByIDX(baseIdx); if (!base) { Com_Printf("BDEF_RemoveBattery_f: baseIdx %i is not founded.\n", baseIdx); return; } if (basedefType == BASEDEF_RANDOM) { /* Type of base defence to destroy is randomly selected */ if (base->numBatteries <= 0 && base->numLasers <= 0) { Com_Printf("No base defence to destroy\n"); return; } else if (base->numBatteries <= 0) { /* only laser battery is possible */ basedefType = BASEDEF_LASER; } else if (base->numLasers <= 0) { /* only missile battery is possible */ basedefType = BASEDEF_MISSILE; } else { /* both type are possible, choose one randomly */ basedefType = (basedefenceType_t)(rand() % 2 + BASEDEF_MISSILE); } } else { /* Check if the removed building was under construction */ buildingType_t type; int workingNum, max; building_t* building; switch (basedefType) { case BASEDEF_MISSILE: type = B_DEFENCE_MISSILE; max = base->numBatteries; break; case BASEDEF_LASER: type = B_DEFENCE_LASER; max = base->numLasers; break; default: Com_Printf("BDEF_RemoveBattery_f: base defence type %i doesn't exist.\n", basedefType); return; } building = nullptr; workingNum = 0; while ((building = B_GetNextBuildingByType(base, building, type))) if (building->buildingStatus == B_STATUS_WORKING) workingNum++; if (workingNum == max) { /* Removed building was under construction, do nothing */ return; } else if (workingNum != max - 1) { /* Should never happen, we only remove building one by one */ Com_Printf("BDEF_RemoveBattery_f: Error while checking number of batteries (%i instead of %i) in base '%s'.\n", workingNum, max, base->name); return; } /* If we reached this point, that means we are removing a working building: continue */ } BDEF_RemoveBattery(base, basedefType, -1); }
/** * @brief Checks why a button in base menu is disabled, and create a popup to inform player */ static void B_CheckBuildingStatusForMenu_f (void) { int num; const char *buildingID; const building_t *building; const base_t *base = B_GetCurrentSelectedBase(); if (cgi->Cmd_Argc() != 2) { Com_Printf("Usage: %s <buildingID>\n", cgi->Cmd_Argv(0)); return; } buildingID = cgi->Cmd_Argv(1); building = B_GetBuildingTemplate(buildingID); if (!building || !base) return; /* Maybe base is under attack ? */ if (B_IsUnderAttack(base)) { CP_Popup(_("Notice"), _("Base is under attack, you can't access this building !")); return; } if (building->buildingType == B_HANGAR) { /* this is an exception because you must have a small or large hangar to enter aircraft menu */ CP_Popup(_("Notice"), _("You need at least one Hangar (and its dependencies) to use aircraft.")); return; } num = B_GetNumberOfBuildingsInBaseByBuildingType(base, building->buildingType); if (num > 0) { int numUnderConstruction; /* maybe all buildings of this type are under construction ? */ B_CheckBuildingTypeStatus(base, building->buildingType, B_STATUS_UNDER_CONSTRUCTION, &numUnderConstruction); if (numUnderConstruction == num) { int minDay = 99999; building_t *b = NULL; while ((b = B_GetNextBuildingByType(base, b, building->buildingType))) { if (b->buildingStatus == B_STATUS_UNDER_CONSTRUCTION) { const float remaining = B_GetConstructionTimeRemain(b); minDay = std::min(minDay, (int)std::max(0.0f, remaining)); } } CP_Popup(_("Notice"), ngettext("Construction of building will be over in %i day.\nPlease wait to enter.", "Construction of building will be over in %i days.\nPlease wait to enter.", minDay), minDay); return; } if (!B_CheckBuildingDependencesStatus(building)) { const building_t *dependenceBuilding = building->dependsBuilding; assert(building->dependsBuilding); if (B_GetNumberOfBuildingsInBaseByBuildingType(base, dependenceBuilding->buildingType) <= 0) { /* the dependence of the building is not built */ CP_Popup(_("Notice"), _("You need a building %s to make building %s functional."), _(dependenceBuilding->name), _(building->name)); return; } else { /* maybe the dependence of the building is under construction * note that we can't use B_STATUS_UNDER_CONSTRUCTION here, because this value * is not use for every building (for exemple Command Centre) */ building_t *b = NULL; while ((b = B_GetNextBuildingByType(base, b, dependenceBuilding->buildingType))) { if (!B_IsBuildingBuiltUp(b)) { CP_Popup(_("Notice"), _("Building %s is not finished yet, and is needed to use building %s."), _(dependenceBuilding->name), _(building->name)); return; } } /* the dependence is built but doesn't work - must be because of their dependendes */ CP_Popup(_("Notice"), _("Make sure that the dependencies of building %s (%s) are operational, so that building %s may be used."), _(dependenceBuilding->name), _(dependenceBuilding->dependsBuilding->name), _(building->name)); return; } } /* all buildings are OK: employees must be missing */ if (building->buildingType == B_WORKSHOP && E_CountHired(base, EMPL_WORKER) <= 0) { CP_Popup(_("Notice"), _("You need to recruit %s to use building %s."), E_GetEmployeeString(EMPL_WORKER, 2), _(building->name)); return; } else if (building->buildingType == B_LAB && E_CountHired(base, EMPL_SCIENTIST) <= 0) { CP_Popup(_("Notice"), _("You need to recruit %s to use building %s."), E_GetEmployeeString(EMPL_SCIENTIST, 2), _(building->name)); return; } } else { CP_Popup(_("Notice"), _("Build a %s first."), _(building->name)); return; } }