/** * @brief Sets aircraftCurrent and updates related cvars and menutexts. * @param[in] aircraft Pointer to given aircraft that should be selected in the menu. */ void AIR_AircraftSelect (aircraft_t* aircraft) { static char aircraftInfo[256]; base_t *base; int id; if (aircraft != NULL) base = aircraft->homebase; else base = NULL; if (!AIR_BaseHasAircraft(base)) { UI_ResetData(TEXT_AIRCRAFT_INFO); return; } assert(aircraft); assert(aircraft->homebase == base); CP_UpdateActorAircraftVar(aircraft, EMPL_SOLDIER); Cvar_SetValue("mn_equipsoldierstate", CL_EquipSoldierState(aircraft)); Cvar_Set("mn_aircraftstatus", AIR_AircraftStatusToName(aircraft)); Cvar_Set("mn_aircraftinbase", AIR_IsAircraftInBase(aircraft) ? "1" : "0"); Cvar_Set("mn_aircraftname", aircraft->name); if (!aircraft->tech) Com_Error(ERR_DROP, "No technology assigned to aircraft '%s'", aircraft->id); Cvar_Set("mn_aircraft_model", aircraft->tech->mdl); Cvar_Set("mn_aircraft_health", va("%3.0f" , aircraft->stats[AIR_STATS_DAMAGE] > 0 ? (double)aircraft->damage * 100 / aircraft->stats[AIR_STATS_DAMAGE] : 0)); /* generate aircraft info text */ Com_sprintf(aircraftInfo, sizeof(aircraftInfo), _("Speed:\t%i km/h\n"), AIR_AircraftMenuStatsValues(aircraft->stats[AIR_STATS_SPEED], AIR_STATS_SPEED)); Q_strcat(aircraftInfo, va(_("Fuel:\t%i/%i\n"), AIR_AircraftMenuStatsValues(aircraft->fuel, AIR_STATS_FUELSIZE), AIR_AircraftMenuStatsValues(aircraft->stats[AIR_STATS_FUELSIZE], AIR_STATS_FUELSIZE)), sizeof(aircraftInfo)); Q_strcat(aircraftInfo, va(_("Operational range:\t%i km\n"), AIR_GetOperationRange(aircraft)), sizeof(aircraftInfo)); Q_strcat(aircraftInfo, va(_("Weapons:\t%i on %i\n"), AIR_GetSlotItems(AC_ITEM_WEAPON, aircraft), aircraft->maxWeapons), sizeof(aircraftInfo)); Q_strcat(aircraftInfo, va(_("Armour:\t%i on 1\n"), AIR_GetSlotItems(AC_ITEM_SHIELD, aircraft)), sizeof(aircraftInfo)); Q_strcat(aircraftInfo, va(_("Electronics:\t%i on %i"), AIR_GetSlotItems(AC_ITEM_ELECTRONICS, aircraft), aircraft->maxElectronics), sizeof(aircraftInfo)); UI_RegisterText(TEXT_AIRCRAFT_INFO, aircraftInfo); /** @todo This shouldn't exists. UI should use the global idx as reference */ /* compute the ID and... */ id = 0; AIR_ForeachFromBase(aircraftInBase, base) { if (aircraft == aircraftInBase) break; id++; } base->aircraftCurrent = aircraft; Cvar_SetValue("mn_aircraft_id", id); /* ...update the GUI */ UI_ExecuteConfunc("aircraft_change %i", id); }
/** * @brief Prints the UFOpaedia description for aircraft * @note Also checks whether the aircraft tech is already researched or collected * @sa BS_MarketAircraftDescription * @sa UP_Article */ void UP_AircraftDescription (const technology_t* tech) { cgi->INV_ItemDescription(nullptr); /* ensure that the buffer is emptied in every case */ upBuffer[0] = '\0'; if (RS_IsResearched_ptr(tech)) { const aircraft_t* aircraft = AIR_GetAircraft(tech->provides); for (int i = 0; i < AIR_STATS_MAX; i++) { switch (i) { case AIR_STATS_SPEED: /* speed may be converted to km/h : multiply by pi / 180 * earth_radius */ Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i km/h\n"), UP_AircraftStatToName(i), AIR_AircraftMenuStatsValues(aircraft->stats[i], i)); break; case AIR_STATS_MAXSPEED: /* speed may be converted to km/h : multiply by pi / 180 * earth_radius */ Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i km/h\n"), UP_AircraftStatToName(i), AIR_AircraftMenuStatsValues(aircraft->stats[i], i)); break; case AIR_STATS_FUELSIZE: Q_strcat(upBuffer, sizeof(upBuffer), _("Operational range:\t%i km\n"), AIR_GetOperationRange(aircraft)); break; case AIR_STATS_ACCURACY: Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i\n"), UP_AircraftStatToName(i), AIR_AircraftMenuStatsValues(aircraft->stats[i], i)); break; default: break; } } const baseCapacities_t cap = AIR_GetCapacityByAircraftWeight(aircraft); const buildingType_t buildingType = B_GetBuildingTypeByCapacity(cap); const building_t* building = B_GetBuildingTemplateByType(buildingType); Q_strcat(upBuffer, sizeof(upBuffer), _("Required Hangar:\t%s\n"), _(building->name)); /* @note: while MAX_ACTIVETEAM limits the number of soldiers on a craft * there is no use to show this in case of an UFO (would be misleading): */ if (!AIR_IsUFO(aircraft)) Q_strcat(upBuffer, sizeof(upBuffer), _("Max. soldiers:\t%i\n"), aircraft->maxTeamSize); } else if (RS_Collected_(tech)) { /** @todo Display crippled info and pre-research text here */ Com_sprintf(upBuffer, sizeof(upBuffer), _("Unknown - need to research this")); } else { Com_sprintf(upBuffer, sizeof(upBuffer), _("Unknown - need to research this")); } cgi->Cvar_Set("mn_upmetadata", "1"); cgi->UI_RegisterText(TEXT_ITEMDESCRIPTION, upBuffer); UP_DisplayTechTree(tech); }
/** * @brief Prints the (UFOpaedia and other) description for aircraft items * @param item The object definition of the item * @sa UP_Article * Not only called from UFOpaedia but also from other places to display * @todo Don't display things like speed for base defence items - a missile * facility isn't getting slower or faster due a special weapon or ammunition */ void UP_AircraftItemDescription (const objDef_t* item) { static char itemText[1024]; const technology_t* tech; /* Set menu text node content to null. */ cgi->INV_ItemDescription(nullptr); *itemText = '\0'; /* no valid item id given */ if (!item) { cgi->Cvar_Set("mn_item", ""); cgi->Cvar_Set("mn_itemname", ""); cgi->Cvar_Set("mn_upmodel_top", ""); cgi->UI_ResetData(TEXT_ITEMDESCRIPTION); return; } tech = RS_GetTechForItem(item); /* select item */ cgi->Cvar_Set("mn_item", "%s", item->id); cgi->Cvar_Set("mn_itemname", "%s", _(item->name)); if (tech->mdl) cgi->Cvar_Set("mn_upmodel_top", "%s", tech->mdl); else cgi->Cvar_Set("mn_upmodel_top", ""); /* set description text */ if (RS_IsResearched_ptr(tech)) { const objDef_t* ammo = nullptr; switch (item->craftitem.type) { case AC_ITEM_WEAPON: Q_strcat(itemText, sizeof(itemText), _("Weight:\t%s\n"), AII_WeightToName(AII_GetItemWeightBySize(item))); break; case AC_ITEM_BASE_MISSILE: case AC_ITEM_BASE_LASER: Q_strcat(itemText, sizeof(itemText), _("Weapon for base defence system\n")); break; case AC_ITEM_AMMO: ammo = item; break; default: break; } /* check ammo of weapons */ if (item->craftitem.type <= AC_ITEM_WEAPON) { for(int i = 0; i < item->numAmmos; i++) if (item->ammos[i]->isVirtual) { ammo = item->ammos[i]; break; } } if (ammo) { /* We display the characteristics of this ammo */ Q_strcat(itemText, sizeof(itemText), _("Ammo:\t%i\n"), ammo->ammo); if (!EQUAL(ammo->craftitem.weaponDamage, 0)) Q_strcat(itemText, sizeof(itemText), _("Damage:\t%i\n"), (int) ammo->craftitem.weaponDamage); Q_strcat(itemText, sizeof(itemText), _("Reloading time:\t%i\n"), (int) ammo->craftitem.weaponDelay); } /* We write the range of the weapon */ if (!EQUAL(item->craftitem.stats[AIR_STATS_WRANGE], 0)) Q_strcat(itemText, sizeof(itemText), "%s:\t%i\n", UP_AircraftStatToName(AIR_STATS_WRANGE), AIR_AircraftMenuStatsValues(item->craftitem.stats[AIR_STATS_WRANGE], AIR_STATS_WRANGE)); /* we scan all stats except weapon range */ for (int i = 0; i < AIR_STATS_MAX; i++) { const char* statsName = UP_AircraftStatToName(i); if (i == AIR_STATS_WRANGE) continue; if (item->craftitem.stats[i] > 2.0f) Q_strcat(itemText, sizeof(itemText), "%s:\t+%i\n", statsName, AIR_AircraftMenuStatsValues(item->craftitem.stats[i], i)); else if (item->craftitem.stats[i] < -2.0f) Q_strcat(itemText, sizeof(itemText), "%s:\t%i\n", statsName, AIR_AircraftMenuStatsValues(item->craftitem.stats[i], i)); else if (item->craftitem.stats[i] > 1.0f) Q_strcat(itemText, sizeof(itemText), _("%s:\t+%i %%\n"), statsName, (int)(item->craftitem.stats[i] * 100) - 100); else if (!EQUAL(item->craftitem.stats[i], 0)) Q_strcat(itemText, sizeof(itemText), _("%s:\t%i %%\n"), statsName, (int)(item->craftitem.stats[i] * 100) - 100); } } else { Q_strcat(itemText, sizeof(itemText), _("Unknown - need to research this")); } cgi->Cvar_Set("mn_upmetadata", "1"); cgi->UI_RegisterText(TEXT_ITEMDESCRIPTION, itemText); }