int valid_ammo_mode(MECH * mech, int loc, int part, int let) { int w, i; if(!IsAmmo(GetPartType(mech, loc, part)) || !let) return -1; let = toupper(let); w = Ammo2I(GetPartType(mech, loc, part)); if(MechWeapons[w].special & NOSPA) return -1; for(i = 0; ammo_types[i].name; i++) { if(ammo_types[i].name != let) continue; if(ammo_types[i].rtype >= 0 && MechWeapons[w].type != ammo_types[i].rtype) continue; if(ammo_types[i].rspec && !(MechWeapons[w].special & ammo_types[i].rspec)) continue; if(ammo_types[i].ntype >= 0 && MechWeapons[w].type == ammo_types[i].ntype) continue; if(ammo_types[i].nspec && (MechWeapons[w].special & ammo_types[i].nspec)) continue; return ammo_types[i].aflag; } return -1; }
void Ship::Resupply() { Meter* fuel_meter = UniverseObject::GetMeter(METER_FUEL); const Meter* max_fuel_meter = UniverseObject::GetMeter(METER_MAX_FUEL); if (!fuel_meter || !max_fuel_meter) { Logger().errorStream() << "Ship::Resupply couldn't get fuel meters!"; return; } fuel_meter->SetCurrent(max_fuel_meter->Current()); for (ConsumablesMap::iterator it = m_fighters.begin(); it != m_fighters.end(); ++it) { const PartType* part_type = GetPartType(it->first); if (part_type) it->second.second = it->second.first * boost::get<FighterStats>(part_type->Stats()).m_capacity; } for (ConsumablesMap::iterator it = m_missiles.begin(); it != m_missiles.end(); ++it) { const PartType* part_type = GetPartType(it->first); if (part_type) it->second.second = it->second.first * boost::get<LRStats>(part_type->Stats()).m_capacity; } }
std::vector<float> Ship::AllWeaponsDamage() const { std::vector<float> retval; const ShipDesign* design = GetShipDesign(m_design_id); if (!design) return retval; const std::vector<std::string>& parts = design->Parts(); // for each weapon part, get its damage meter value for (std::vector<std::string>::const_iterator part_it = parts.begin(); part_it != parts.end(); ++part_it) { const std::string& part_name = *part_it; const PartType* part = GetPartType(part_name); if (!part) continue; ShipPartClass part_class = part->Class(); // get the attack power for each weapon part float part_attack = 0.0; if (part_class == PC_SHORT_RANGE || part_class == PC_POINT_DEFENSE || part_class == PC_MISSILES) part_attack = this->CurrentPartMeterValue(METER_DAMAGE, part_name); else if (part_class == PC_FIGHTERS) part_attack = this->CurrentPartMeterValue(METER_ANTI_SHIP_DAMAGE, part_name); if (part_attack > 0.0) retval.push_back(part_attack); } return retval; }
void CheckWeaponFailed(MECH * mech, int weapnum, int weaptype, int section, int critical, int *modifier, int *type) { short roll; int l = GetPartBrand(mech, section, critical); int t = GetPartType(mech, section, critical); int i = GetBrandIndex(t), in; *type = FAIL_NONE; if(i < 0) return; if(mudconf.btech_parts) { if(!l) l = 5; if(MechWeapons[Weapon2I(t)].special & PCOMBAT) return; } else return; if(Number(1, 10) < 9) return; if(Number(1, 100) <= brands[(i + l - 1) * 5 / 6].success) return; roll = Number(1, 6); if(roll == 6) roll = Number(1, 6); in = i + roll - 1; if(failures[in].flag & REQ_HEAT) if(!MechWeapons[weaptype].heat) return; if(failures[in].message && strcmp(failures[in].message, "none")) mech_notify(mech, MECHALL, failures[in].message); failures[in].func(mech, weapnum, weaptype, section, critical, roll, modifier, type); }
float Ship::TroopCapacity() const { float retval = 0.0f; // find which troop parts are present in design (one copy of name for each instance of a part, allowing duplicate names to appear) const ShipDesign* design = Design(); if (!design) return retval; const std::vector<std::string>& parts = design->Parts(); for (std::vector<std::string>::const_iterator part_it = parts.begin(); part_it != parts.end(); ++part_it) { const std::string& part_name = *part_it; if (part_name.empty()) continue; const PartType* part_type = GetPartType(part_name); if (!part_type) continue; ShipPartClass part_class = part_type->Class(); if (part_class != PC_TROOPS) continue; // add capacity for all instances of colony parts to accumulator retval += this->CurrentPartMeterValue(METER_CAPACITY, part_name); } return retval; }
void Ship::AddFighters(const std::string& part_name, std::size_t n) { const PartType* part_type = GetPartType(part_name); if (!part_type) return; assert(m_fighters[part_name].second + n <= m_fighters[part_name].first * boost::get<FighterStats>(part_type->Stats()).m_capacity); m_fighters[part_name].second += n; }
int Find_DS_Bay_Number(MECH * ds, int dir) { int bayn = 0; int i, j; for(i = 0; i <= dir; i++) { for(j = 0; j < NUM_CRITICALS; j++) if(GetPartType(ds, dir2loc[i % 6], j) == I2Special(DS_MECHDOOR) || GetPartType(ds, dir2loc[i % 6], j) == I2Special(DS_AERODOOR)) break; if(j != NUM_CRITICALS) { if(i == dir) return bayn; bayn++; } } return -1; }
double ShipDesign::ProductionCost(int empire_id, int location_id) const { if (CHEAP_AND_FAST_SHIP_PRODUCTION) { return 1.0; } else { double cost_accumulator = 0.0; if (const HullType* hull = GetHullType(m_hull)) cost_accumulator += hull->ProductionCost(empire_id, location_id); for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) if (const PartType* part = GetPartType(*it)) cost_accumulator += part->ProductionCost(empire_id, location_id); return std::max(0.0, cost_accumulator); } }
int ShipDesign::ProductionTime(int empire_id, int location_id) const { if (CHEAP_AND_FAST_SHIP_PRODUCTION) { return 1; } else { int time_accumulator = 1; if (const HullType* hull = GetHullType(m_hull)) time_accumulator = std::max(time_accumulator, hull->ProductionTime(empire_id, location_id)); for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) if (const PartType* part = GetPartType(*it)) time_accumulator = std::max(time_accumulator, part->ProductionTime(empire_id, location_id)); return std::max(1, time_accumulator); } }
bool ShipDesign::CanColonize() const { //if (m_colony_capacity > 0.0) // return true; for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) { const std::string& part_name = *it; if (part_name.empty()) continue; if (const PartType* part = GetPartType(part_name)) if (part->Class() == PC_COLONY) return true; } return false; }
static int DS_Bay_Is_Open(MECH * mech, MECH * ds, dbref bayref) { int i, j; for(i = 0; i < NUM_BAYS; i++) if(AeroBay(ds, i) > 0) if(AeroBay(ds, i) == bayref) { j = Find_DS_Bay_Dir(ds, i); for(i = 0; i < NUM_CRITICALS; i++) { if(((is_aero(mech) && GetPartType(ds, dir2loc[j], i) == I2Special(DS_AERODOOR)) || (!is_aero(mech) && GetPartType(ds, dir2loc[j], i) == I2Special(DS_MECHDOOR))) && !PartIsDestroyed(ds, dir2loc[j], i)) return 1; } return 0; } return 0; }
float Ship::FighterCount() const { float retval = 0.0f; for (PartMeterMap::const_iterator it = m_part_meters.begin(); it != m_part_meters.end(); ++it) { //std::map<std::pair<MeterType, std::string>, Meter> if (it->first.first != METER_CAPACITY) continue; const PartType* part_type = GetPartType(it->first.second); if (!part_type || part_type->Class() != PC_FIGHTER_HANGAR) continue; retval += it->second.Current(); } return retval; }
std::vector<std::string> ShipDesign::Weapons() const { std::vector<std::string> retval; retval.reserve(m_parts.size()); for (unsigned int i = 0; i < m_parts.size(); ++i) { const std::string& part_name = m_parts[i]; const PartType* part = GetPartType(part_name); if (!part) continue; ShipPartClass part_class = part->Class(); if (part_class == PC_SHORT_RANGE || part_class == PC_MISSILES || part_class == PC_FIGHTERS || part_class == PC_POINT_DEFENSE) { retval.push_back(part_name); } } return retval; }
bool ShipDesign::ProductionCostTimeLocationInvariant() const { if (CHEAP_AND_FAST_SHIP_PRODUCTION) return true; // as seen in ShipDesign::ProductionCost, the location is passed as the // local candidate in the ScriptingContext // check hull and all parts if (const HullType* hull = GetHullType(m_hull)) if (!hull->ProductionCostTimeLocationInvariant()) return false; for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) if (const PartType* part = GetPartType(*it)) if (!part->ProductionCostTimeLocationInvariant()) return false; // if hull and all parts are invariant, so is whole design return true; }
void CdispenserIGC::Update(Time now) { assert (m_ship); if (m_mountedFraction < 1.0f) { float dt = now - m_ship->GetLastUpdate(); assert (dt >= 0.0f); m_mountedFraction += dt * m_pMission->GetFloatConstant(c_fcidMountRate); if (m_mountedFraction < 1.0f) return; IIgcSite* pigc = GetMission()->GetIgcSite(); pigc->PlayNotificationSound(mountedSound, m_ship); pigc->PostNotificationText(m_ship, false, "%s ready.", GetPartType()->GetName()); m_mountedFraction = 1.0f; } if ((m_timeLoaded < now) && (m_amount > 0)) { static const int c_maskFire[ET_MAX] = { chaffFireIGC, 0, 0, mineFireIGC, 0, 0, 0, 0 }; assert (c_maskFire[ET_ChaffLauncher] == chaffFireIGC); assert (c_maskFire[ET_Dispenser] == mineFireIGC); EquipmentType et = m_expendableType->GetEquipmentType(); if ((m_ship->GetStateM() & c_maskFire[et]) && ((et == ET_ChaffLauncher) || (m_ship->GetRipcordModel() == NULL))) { m_timeLoaded = now + m_expendableType->GetLoadTime(); m_pMission->GetIgcSite()->FireExpendable(m_ship, this, now); } } }
void CombatShip::LaunchFighters() { // Note that this just launches the fighters that can be launched on this // turn. There is currently no code that accounts for turns(!), so we're // only launching part of the fighters here and not providing for the // launches of the rest. for (FighterMap::iterator it = m_unlaunched_fighters.begin(); it != m_unlaunched_fighters.end(); ++it) { const PartType* part = GetPartType(it->first); assert(part && part->Class() == PC_FIGHTERS); std::vector<CombatFighterPtr>& fighters_vec = it->second.second; std::size_t num_fighters = fighters_vec.size(); double launch_rate = GetShip()->GetPartMeter(METER_LAUNCH_RATE, part->Name())->Current(); std::size_t launch_size = std::min<std::size_t>(num_fighters, launch_rate * it->second.first); std::size_t formation_size = std::min(CombatFighter::FORMATION_SIZE, launch_size); std::size_t num_formations = launch_size / formation_size; std::size_t final_formation_size = launch_size % formation_size; if (final_formation_size) ++num_formations; else final_formation_size = formation_size; for (std::size_t j = 0; j < num_formations; ++j) { std::size_t size = j == num_formations - 1 ? final_formation_size : formation_size; std::set<CombatFighterFormationPtr>::iterator formation_it = m_launched_formations.insert( m_pathing_engine->CreateFighterFormation( shared_from_this(), fighters_vec.end() - size, fighters_vec.end())).first; fighters_vec.resize(fighters_vec.size() - size); m_pathing_engine->AddFighterFormation(*formation_it); } GetShip()->RemoveFighters(it->first, launch_size); } }
int tech_parsegun(MECH * mech, char *buffer, int *loc, int *pos, int *brand) { char *args[3]; int l, argc, t, c = 0, pi, pb; argc = mech_parseattributes(buffer, args, 3); if(argc < 1 || argc > (2 + (brand != NULL))) return -1; if(argc == (2 + (brand != NULL)) || (brand && argc == 2 && atoi(args[1]))) { if((*loc = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0])) < 0) return -1; l = atoi(args[1]); if(l <= 0 || l > CritsInLoc(mech, *loc)) return -4; *pos = l - 1; } else { /* Check if it's a number */ if(args[0][0] < '0' || args[0][0] > '9') return -1; l = atoi(args[0]); if(l < 0) return -1; if((t = FindWeaponNumberOnMech(mech, l, loc, pos)) == -1) return -1; } t = GetPartType(mech, *loc, *pos); if(brand != NULL && argc > 1 && !atoi(args[argc - 1])) { if(!find_matching_long_part(args[argc - 1], &c, &pi, &pb)) return -2; if(pi != t) return -3; *brand = pb; } else if(brand != NULL) *brand = GetPartBrand(mech, *loc, *pos); return 0; }
bool Ship::HasTag(const std::string& name) const { const ShipDesign* design = GetShipDesign(m_design_id); if (design) { // check hull for tag const HullType* hull = ::GetHullType(design->Hull()); if (hull && hull->Tags().count(name)) return true; // check parts for tag const std::vector<std::string>& parts = design->Parts(); for (std::vector<std::string>::const_iterator part_it = parts.begin(); part_it != parts.end(); ++part_it) { const PartType* part = GetPartType(*part_it); if (part && part->Tags().count(name)) return true; } } // check species for tag const Species* species = GetSpecies(SpeciesName()); if (species && species->Tags().count(name)) return true; return false; }
static int check_for_scrappage(MECH * mech, int loc) { int a, b; int ret = 1; if (SectIsDestroyed(mech, loc)) return 1; if (SomeoneScrappingLoc(mech, loc)) { DAMAGE2(DETACH, loc); return 1; } for (a = 0; a < NUM_CRITICALS; a++) { if (!(b = GetPartType(mech, loc, a))) continue; if (PartIsBroken(mech, loc, a)) continue; if (IsCrap(b)) continue; if (IsAmmo(b) && GetPartData(mech, loc, a)) { DAMAGE3(UNLOAD, loc, a); if (ret && !SomeoneRepairing(mech, loc, a)) ret = 0; continue; } DAMAGE3(IsWeapon(b) ? SCRAPG : SCRAPP, loc, a); if (ret && !SomeoneScrappingPart(mech, loc, a)) ret = 0; if (IsWeapon(b)) a += GetWeaponCrits(mech, Weapon2I(b)) - 1; } if (ret && !Invalid_Scrap_Path(mech, loc)) DAMAGE2(DETACH, loc); return 0; }
std::set<std::string> Ship::Tags() const { std::set<std::string> retval; const ShipDesign* design = GetShipDesign(m_design_id); if (!design) return retval; const HullType* hull = ::GetHullType(design->Hull()); if (!hull) return retval; retval.insert(hull->Tags().begin(), hull->Tags().end()); const std::vector<std::string>& parts = design->Parts(); if (parts.empty()) return retval; for (std::vector<std::string>::const_iterator part_it = parts.begin(); part_it != parts.end(); ++part_it) { if (const PartType* part = GetPartType(*part_it)) { retval.insert(part->Tags().begin(), part->Tags().end()); } } return retval; }
void ShipDesign::BuildStatCaches() { const HullType* hull = GetHullType(m_hull); if (!hull) { Logger().errorStream() << "ShipDesign::BuildStatCaches couldn't get hull with name " << m_hull; return; } m_producible = hull->Producible(); m_detection = hull->Detection(); m_colony_capacity = hull->ColonyCapacity(); m_troop_capacity = hull->TroopCapacity(); m_stealth = hull->Stealth(); m_fuel = hull->Fuel(); m_shields = hull->Shields(); m_structure = hull->Structure(); m_battle_speed = hull->BattleSpeed(); m_starlane_speed = hull->StarlaneSpeed(); for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) { if (it->empty()) continue; const PartType* part = GetPartType(*it); if (!part) { Logger().errorStream() << "ShipDesign::BuildStatCaches couldn't get part with name " << *it; continue; } if (!part->Producible()) m_producible = false; switch (part->Class()) { case PC_SHORT_RANGE: { const DirectFireStats& stats = boost::get<DirectFireStats>(part->Stats()); m_SR_weapons.insert(std::make_pair(stats.m_range, part)); m_is_armed = true; m_min_SR_range = std::min(m_min_SR_range, stats.m_range); m_max_SR_range = std::max(m_max_SR_range, stats.m_range); m_min_weapon_range = std::min(m_min_weapon_range, stats.m_range); m_max_weapon_range = std::max(m_max_weapon_range, stats.m_range); m_min_non_PD_weapon_range = std::min(m_min_non_PD_weapon_range, stats.m_range); m_max_non_PD_weapon_range = std::max(m_max_non_PD_weapon_range, stats.m_range); break; } case PC_MISSILES: { const LRStats& stats = boost::get<LRStats>(part->Stats()); m_LR_weapons.insert(std::make_pair(stats.m_range, part)); m_is_armed = true; m_min_LR_range = std::min(m_min_LR_range, stats.m_range); m_max_LR_range = std::max(m_max_LR_range, stats.m_range); m_min_weapon_range = std::min(m_min_weapon_range, stats.m_range); m_max_weapon_range = std::max(m_max_weapon_range, stats.m_range); m_min_non_PD_weapon_range = std::min(m_min_non_PD_weapon_range, stats.m_range); m_max_non_PD_weapon_range = std::max(m_max_non_PD_weapon_range, stats.m_range); break; } case PC_FIGHTERS: m_F_weapons.push_back(part); m_is_armed = true; break; case PC_POINT_DEFENSE: { const DirectFireStats& stats = boost::get<DirectFireStats>(part->Stats()); m_PD_weapons.insert(std::make_pair(stats.m_range, part)); m_is_armed = true; m_min_PD_range = std::min(m_min_PD_range, stats.m_range); m_max_PD_range = std::max(m_max_PD_range, stats.m_range); m_min_weapon_range = std::min(m_min_weapon_range, stats.m_range); m_max_weapon_range = std::max(m_max_weapon_range, stats.m_range); break; } case PC_COLONY: m_colony_capacity += boost::get<float>(part->Stats()); break; case PC_TROOPS: m_troop_capacity += boost::get<float>(part->Stats()); break; case PC_STEALTH: m_stealth += boost::get<float>(part->Stats()); break; case PC_BATTLE_SPEED: m_battle_speed += boost::get<float>(part->Stats()); break; case PC_STARLANE_SPEED: m_starlane_speed += boost::get<float>(part->Stats()); break; case PC_SHIELD: m_shields += boost::get<float>(part->Stats()); break; case PC_FUEL: m_fuel += boost::get<float>(part->Stats()); break; case PC_ARMOUR: m_structure += boost::get<float>(part->Stats()); break; case PC_DETECTION: m_detection += boost::get<float>(part->Stats()); break; default: break; } } if (m_SR_weapons.empty()) m_min_SR_range = 0.0; if (m_LR_weapons.empty()) m_min_LR_range = 0.0; if (m_PD_weapons.empty()) m_min_PD_range = 0.0; if (!m_min_SR_range && !m_min_LR_range && !m_min_PD_range) m_min_weapon_range = 0.0; if (!m_min_LR_range && !m_min_PD_range) m_min_non_PD_weapon_range = 0.0; }
bool ShipDesign::ProductionLocation(int empire_id, int location_id) const { const UniverseObject* location = GetUniverseObject(location_id); if (!location) return false; // currently ships can only be built at planets, and by species that are // not planetbound const Planet* planet = universe_object_cast<const Planet*>(location); if (!planet) return false; const std::string& species_name = planet->SpeciesName(); if (species_name.empty()) return false; const Species* species = GetSpecies(species_name); if (!species) return false; if (!species->CanProduceShips()) return false; // also, species that can't colonize can't produce colony ships if (this->CanColonize() && !species->CanColonize()) return false; Empire* empire = Empires().Lookup(empire_id); if (!empire) { Logger().debugStream() << "ShipDesign::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } // get a source object, which is owned by the empire with the passed-in // empire id. this is used in conditions to reference which empire is // doing the producing. Ideally this will be the capital, but any object // owned by the empire will work. const UniverseObject* source = SourceForEmpire(empire_id); // if this empire doesn't own ANYTHING, then how is it producing anyway? if (!source) return false; // apply hull location conditions to potential location const HullType* hull = GetHull(); if (!hull) { Logger().errorStream() << "ShipDesign::ProductionLocation ShipDesign couldn't get its own hull with name " << m_hull; return false; } if (!hull->Location()->Eval(ScriptingContext(source), location)) return false; // apply external and internal parts' location conditions to potential location for (std::vector<std::string>::const_iterator part_it = m_parts.begin(); part_it != m_parts.end(); ++part_it) { std::string part_name = *part_it; if (part_name.empty()) continue; // empty slots don't limit build location const PartType* part = GetPartType(part_name); if (!part) { Logger().errorStream() << "ShipDesign::ProductionLocation ShipDesign couldn't get part with name " << part_name; return false; } if (!part->Location()->Eval(ScriptingContext(source), location)) return false; } // location matched all hull and part conditions, so is a valid build location return true; }
Ship::Ship(int empire_id, int design_id, const std::string& species_name, int produced_by_empire_id/* = ALL_EMPIRES*/) : m_design_id(design_id), m_fleet_id(INVALID_OBJECT_ID), m_ordered_scrapped(false), m_ordered_colonize_planet_id(INVALID_OBJECT_ID), m_ordered_invade_planet_id(INVALID_OBJECT_ID), m_ordered_bombard_planet_id(INVALID_OBJECT_ID), m_last_turn_active_in_combat(INVALID_GAME_TURN), m_species_name(species_name), m_produced_by_empire_id(produced_by_empire_id) { if (!GetShipDesign(design_id)) throw std::invalid_argument("Attempted to construct a Ship with an invalid design id"); if (!m_species_name.empty() && !GetSpecies(m_species_name)) Logger().debugStream() << "Ship created with invalid species name: " << m_species_name; SetOwner(empire_id); UniverseObject::Init(); AddMeter(METER_FUEL); AddMeter(METER_MAX_FUEL); AddMeter(METER_SHIELD); AddMeter(METER_MAX_SHIELD); AddMeter(METER_DETECTION); AddMeter(METER_STRUCTURE); AddMeter(METER_MAX_STRUCTURE); AddMeter(METER_BATTLE_SPEED); AddMeter(METER_STARLANE_SPEED); const std::vector<std::string>& part_names = Design()->Parts(); for (std::size_t i = 0; i < part_names.size(); ++i) { if (part_names[i] != "") { const PartType* part = GetPartType(part_names[i]); if (!part) { Logger().errorStream() << "Ship::Ship couldn't get part with name " << part_names[i]; continue; } switch (part->Class()) { case PC_SHORT_RANGE: case PC_POINT_DEFENSE: { m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ROF, part->Name())]; m_part_meters[std::make_pair(METER_RANGE, part->Name())]; break; } case PC_MISSILES: { std::pair<std::size_t, std::size_t>& part_missiles = m_missiles[part_names[i]]; ++part_missiles.first; part_missiles.second += boost::get<LRStats>(part->Stats()).m_capacity; m_part_meters[std::make_pair(METER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ROF, part->Name())]; m_part_meters[std::make_pair(METER_RANGE, part->Name())]; m_part_meters[std::make_pair(METER_SPEED, part->Name())]; m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; m_part_meters[std::make_pair(METER_STRUCTURE, part->Name())]; m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } case PC_FIGHTERS: { std::pair<std::size_t, std::size_t>& part_fighters = m_fighters[part_names[i]]; ++part_fighters.first; part_fighters.second += boost::get<FighterStats>(part->Stats()).m_capacity; m_part_meters[std::make_pair(METER_ANTI_SHIP_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_ANTI_FIGHTER_DAMAGE, part->Name())]; m_part_meters[std::make_pair(METER_LAUNCH_RATE, part->Name())]; m_part_meters[std::make_pair(METER_FIGHTER_WEAPON_RANGE,part->Name())]; m_part_meters[std::make_pair(METER_SPEED, part->Name())]; m_part_meters[std::make_pair(METER_STEALTH, part->Name())]; m_part_meters[std::make_pair(METER_STRUCTURE, part->Name())]; m_part_meters[std::make_pair(METER_DETECTION, part->Name())]; m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } default: break; } } } }
void ShipDesign::BuildStatCaches() { const HullType* hull = GetHullType(m_hull); if (!hull) { ErrorLogger() << "ShipDesign::BuildStatCaches couldn't get hull with name " << m_hull; return; } m_producible = hull->Producible(); m_detection = hull->Detection(); m_colony_capacity = hull->ColonyCapacity(); m_troop_capacity = hull->TroopCapacity(); m_stealth = hull->Stealth(); m_fuel = hull->Fuel(); m_shields = hull->Shields(); m_structure = hull->Structure(); m_speed = hull->Speed(); for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) { if (it->empty()) continue; const PartType* part = GetPartType(*it); if (!part) { ErrorLogger() << "ShipDesign::BuildStatCaches couldn't get part with name " << *it; continue; } if (!part->Producible()) m_producible = false; switch (part->Class()) { case PC_SHORT_RANGE: case PC_MISSILES: case PC_FIGHTERS: case PC_POINT_DEFENSE: { m_is_armed = true; break; } case PC_COLONY: m_colony_capacity += part->Capacity(); break; case PC_TROOPS: m_troop_capacity += part->Capacity(); break; case PC_STEALTH: m_stealth += part->Capacity(); break; case PC_SPEED: m_speed += part->Capacity(); break; case PC_SHIELD: m_shields += part->Capacity(); break; case PC_FUEL: m_fuel += part->Capacity(); break; case PC_ARMOUR: m_structure += part->Capacity(); break; case PC_DETECTION: m_detection += part->Capacity(); break; case PC_BOMBARD: m_can_bombard = true; break; case PC_RESEARCH: m_research_generation += part->Capacity(); break; case PC_INDUSTRY: m_industry_generation += part->Capacity(); break; case PC_TRADE: m_trade_generation += part->Capacity(); break; case PC_PRODICTION_LOCATION: m_is_production_location = true; break; default: break; } } }
static int check_for_damage(MECH * mech, int loc) { int a, b, c, d; if (SectIsDestroyed(mech, loc)) { if (MechType(mech) != CLASS_BSUIT) DAMAGE2(REATTACH, loc); else DAMAGE2(REPLACESUIT, loc); return 0; } /* * Added by Kipsta * 8/4/99 */ if (SectIsFlooded(mech, loc)) { DAMAGE2(RESEAL, loc); return 0; } if ((a = GetSectInt(mech, loc)) != (b = GetSectOInt(mech, loc))) DAMAGE3(FIXINTERNAL, loc, (b - a)); else { if ((a = GetSectArmor(mech, loc)) != (b = GetSectOArmor(mech, loc))) DAMAGE3(FIXARMOR, loc, (b - a)); if ((a = GetSectRArmor(mech, loc)) != (b = GetSectORArmor(mech, loc))) DAMAGE3(FIXARMOR_R, loc, (b - a)); } for (a = 0; a < NUM_CRITICALS; a++) { if (!(b = GetPartType(mech, loc, a))) continue; if (IsAmmo(b) && !PartIsDestroyed(mech, loc, a) && (c = GetPartData(mech, loc, a)) != (d = FullAmmo(mech, loc, a))) DAMAGE3(RELOAD, loc, a); if (!PartIsNonfunctional(mech, loc, a) && !PartTempNuke(mech, loc, a) && !PartIsDamaged(mech, loc, a)) continue; if (IsCrap(b)) continue; /* Destroyed / tempnuke'd part. Either case, it works for us :) */ if (PartIsDamaged(mech, loc, a)) { if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_EN_FOCUS) DAMAGE3(ENHCRIT_FOCUS, loc, a); else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_EN_CRYSTAL) DAMAGE3(ENHCRIT_CRYSTAL, loc, a); else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_BALL_BARREL) DAMAGE3(ENHCRIT_BARREL, loc, a); else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_BALL_AMMO) DAMAGE3(ENHCRIT_AMMOB, loc, a); else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_MSL_RANGING) DAMAGE3(ENHCRIT_RANGING, loc, a); else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_MSL_AMMO) DAMAGE3(ENHCRIT_AMMOM, loc, a); else DAMAGE3(ENHCRIT_MISC, loc, a); } else if (IsWeapon(b) && GetWeaponCrits(mech, Weapon2I(b)) > 4 && !PartIsDestroyed(mech, loc, a + 1)) DAMAGE3(REPAIRP_T, loc, a); else DAMAGE3(IsWeapon(b) ? REPAIRG : REPAIRP, loc, a); if (IsWeapon(b)) a += GetWeaponCrits(mech, Weapon2I(b)) - 1; } return 1; }
void CombatShip::Init(const OpenSteer::Vec3& position_, const OpenSteer::Vec3& direction) { m_proximity_token = m_pathing_engine->GetProximityDB().Insert(this, SHIP_FLAG, EmpireFlag(m_empire_id)); SimpleVehicle::reset(); SimpleVehicle::setMaxForce(3.0); SimpleVehicle::setMaxSpeed(GetShip()->Design()->BattleSpeed()); // TODO: setMass() SimpleVehicle::regenerateOrthonormalBasis(direction, OpenSteer::Vec3(0, 0, 1)); SimpleVehicle::setPosition(position_); SimpleVehicle::setSpeed(0); m_proximity_token->UpdatePosition(position()); m_mission_queue.push_front(ShipMission(ShipMission::NONE)); const Ship::ConsumablesMap& fighters = GetShip()->Fighters(); for (Ship::ConsumablesMap::const_iterator it = fighters.begin(); it != fighters.end(); ++it) { const PartType* part = GetPartType(it->first); assert(part && part->Class() == PC_FIGHTERS); std::size_t num_fighters = it->second.second; m_unlaunched_fighters[it->first].first = it->second.first; std::vector<CombatFighterPtr>& fighter_vec = m_unlaunched_fighters[it->first].second; fighter_vec.resize(num_fighters); for (std::size_t i = 0; i < num_fighters; ++i) { fighter_vec[i].reset( new CombatFighter(shared_from_this(), *part, m_empire_id, *m_pathing_engine)); fighter_vec[i]->SetWeakPtr(fighter_vec[i]); } } m_missiles = GetShip()->Missiles(); float PD_minus_non_PD = 0.0f; const std::vector<std::string>& part_names = GetShip()->Design()->Parts(); for (std::size_t i = 0; i < part_names.size(); ++i) { if (part_names[i].empty()) continue; const PartType* part = GetPartType(part_names[i]); assert(part); if (part->Class() == PC_POINT_DEFENSE) { const std::string& part_name = part->Name(); float damage = GetShip()->GetPartMeter(METER_DAMAGE, part_name)->Current(); m_raw_PD_strength += damage * GetShip()->GetPartMeter(METER_ROF, part_name)->Current() * GetShip()->GetPartMeter(METER_RANGE, part_name)->Current(); PD_minus_non_PD += damage; } else if (part->Class() == PC_SHORT_RANGE) { const std::string& part_name = part->Name(); float damage = GetShip()->GetPartMeter(METER_DAMAGE, part_name)->Current(); m_raw_SR_strength += damage * GetShip()->GetPartMeter(METER_ROF, part_name)->Current() * GetShip()->GetPartMeter(METER_RANGE, part_name)->Current(); PD_minus_non_PD -= damage; } else if (part->Class() == PC_MISSILES) { const std::string& part_name = part->Name(); float damage = GetShip()->GetPartMeter(METER_DAMAGE, part_name)->Current(); m_raw_LR_strength += damage * GetShip()->GetPartMeter(METER_ROF, part_name)->Current() * GetShip()->GetPartMeter(METER_RANGE, part_name)->Current(); PD_minus_non_PD -= damage; } } m_is_PD_ship = 0.0f < PD_minus_non_PD; }
void CafterburnerIGC::IncrementalUpdate(Time lastUpdate, Time now, bool bUseFuel) { assert (m_ship); assert (now >= lastUpdate); { #ifdef WIN float dt = now - lastUpdate; #else float dt = Seconds(now - lastUpdate).count(); #endif if (m_mountedFraction < 1.0f) { if (bUseFuel) m_mountedFraction += dt * m_pMission->GetFloatConstant(c_fcidMountRate); if (m_mountedFraction >= 1.0f) { IIgcSite* pigc = GetMission()->GetIgcSite(); pigc->PlayNotificationSound(mountedSound, m_ship); pigc->PostNotificationText(m_ship, false, "%s ready.", GetPartType()->GetName()); m_mountedFraction = 1.0f; } else return; } { float fuel = m_ship->GetFuel(); bool bActivated = (m_ship->GetStateM() & afterburnerButtonIGC) && (fuel != 0.0f || m_typeData->fuelConsumption == 0.0f); //Spunky - #271 if (bActivated) Activate(); if (m_fActive) { if (bActivated) { m_power += dt * m_typeData->onRate; if (m_power > 1.0f) m_power = 1.0f; } else { m_power -= dt * m_typeData->offRate; if (m_power <= 0.0f) Deactivate(); } if ((m_power != 0.0f) && bUseFuel) { float fuelUsed = m_power * m_typeData->fuelConsumption * m_typeData->maxThrust * dt; if (fuelUsed < fuel) m_ship->SetFuel(fuel - fuelUsed); else if (fuel != 0.0f) { //Out of gas m_ship->SetFuel(0.0f); Deactivate(); } } } } } }
Ship::Ship(int empire_id, int design_id, const std::string& species_name, int produced_by_empire_id/* = ALL_EMPIRES*/) : UniverseObject(), m_design_id(design_id), m_fleet_id(INVALID_OBJECT_ID), m_ordered_scrapped(false), m_ordered_colonize_planet_id(INVALID_OBJECT_ID), m_ordered_invade_planet_id(INVALID_OBJECT_ID), m_ordered_bombard_planet_id(INVALID_OBJECT_ID), m_last_turn_active_in_combat(INVALID_GAME_TURN), m_species_name(species_name), m_produced_by_empire_id(produced_by_empire_id), m_arrived_on_turn(CurrentTurn()) { if (!GetShipDesign(design_id)) throw std::invalid_argument("Attempted to construct a Ship with an invalid design id"); if (!m_species_name.empty() && !GetSpecies(m_species_name)) DebugLogger() << "Ship created with invalid species name: " << m_species_name; SetOwner(empire_id); UniverseObject::Init(); AddMeter(METER_FUEL); AddMeter(METER_MAX_FUEL); AddMeter(METER_SHIELD); AddMeter(METER_MAX_SHIELD); AddMeter(METER_DETECTION); AddMeter(METER_STRUCTURE); AddMeter(METER_MAX_STRUCTURE); AddMeter(METER_SPEED); AddMeter(METER_TARGET_INDUSTRY); AddMeter(METER_INDUSTRY); AddMeter(METER_TARGET_RESEARCH); AddMeter(METER_RESEARCH); AddMeter(METER_TARGET_TRADE); AddMeter(METER_TRADE); const std::vector<std::string>& part_names = Design()->Parts(); for (std::size_t i = 0; i < part_names.size(); ++i) { if (part_names[i] != "") { const PartType* part = GetPartType(part_names[i]); if (!part) { ErrorLogger() << "Ship::Ship couldn't get part with name " << part_names[i]; continue; } switch (part->Class()) { case PC_COLONY: case PC_TROOPS: { m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; break; } case PC_DIRECT_WEAPON: // capacity is damage, secondary stat is shots per attack case PC_FIGHTER_HANGAR: { // capacity is how many fighters contained, secondary stat is damage per fighter attack m_part_meters[std::make_pair(METER_SECONDARY_STAT, part->Name())]; m_part_meters[std::make_pair(METER_MAX_SECONDARY_STAT, part->Name())]; // intentionally no break here } case PC_FIGHTER_BAY: { // capacity is how many fighters launched per combat round m_part_meters[std::make_pair(METER_CAPACITY, part->Name())]; m_part_meters[std::make_pair(METER_MAX_CAPACITY, part->Name())]; break; } default: break; } } } }
int FindAmmoType(MECH * mech, int loc, int part) { int t = GetPartType(mech, loc, part); int m = GetPartAmmoMode(mech, loc, part); int base = -1; if(!IsAmmo(t)) return t; t = Ammo2I(t); if(strstr(MechWeapons[t].name, "StreakSRM")) base = SSRM_AMMO; else if(strstr(MechWeapons[t].name, "StreakLRM")) base = SLRM_AMMO; else if(strstr(MechWeapons[t].name, "ELRM")) base = ELRM_AMMO; else if(strstr(MechWeapons[t].name, "LR_DFM")) base = LR_DFM_AMMO; else if(strstr(MechWeapons[t].name, "SR_DFM")) base = SR_DFM_AMMO; else if(strstr(MechWeapons[t].name, "LRM")) base = LRM_AMMO; else if(strstr(MechWeapons[t].name, "SRM")) base = SRM_AMMO; else if(strstr(MechWeapons[t].name, "MRM")) base = MRM_AMMO; if(!(m & AMMO_MODES)) { if(base < 0) return I2Ammo(t); else return Cargo(base); } if(m & LBX_MODE) { if(strstr(MechWeapons[t].name, "LB20")) base = LBX20_AMMO; else if(strstr(MechWeapons[t].name, "LB10")) base = LBX10_AMMO; else if(strstr(MechWeapons[t].name, "LB5")) base = LBX5_AMMO; else if(strstr(MechWeapons[t].name, "LB2")) base = LBX2_AMMO; if(base < 0) return I2Ammo(t); return Cargo(base); } if(m & AC_MODES) { if(m & AC_AP_MODE) { if(strstr(MechWeapons[t].name, "AC/2")) base = AC2_AP_AMMO; if(strstr(MechWeapons[t].name, "AC/5")) base = AC5_AP_AMMO; if(strstr(MechWeapons[t].name, "AC/10")) base = AC10_AP_AMMO; if(strstr(MechWeapons[t].name, "AC/20")) base = AC20_AP_AMMO; if(strstr(MechWeapons[t].name, "LightAC/2")) base = LAC2_AP_AMMO; if(strstr(MechWeapons[t].name, "LightAC/5")) base = LAC5_AP_AMMO; } if(m & AC_FLECHETTE_MODE) { if(strstr(MechWeapons[t].name, "AC/2")) base = AC2_FLECHETTE_AMMO; if(strstr(MechWeapons[t].name, "AC/5")) base = AC5_FLECHETTE_AMMO; if(strstr(MechWeapons[t].name, "AC/10")) base = AC10_FLECHETTE_AMMO; if(strstr(MechWeapons[t].name, "AC/20")) base = AC20_FLECHETTE_AMMO; if(strstr(MechWeapons[t].name, "LightAC/2")) base = LAC2_FLECHETTE_AMMO; if(strstr(MechWeapons[t].name, "LightAC/5")) base = LAC5_FLECHETTE_AMMO; } if(m & AC_INCENDIARY_MODE) { if(strstr(MechWeapons[t].name, "AC/2")) base = AC2_INCENDIARY_AMMO; if(strstr(MechWeapons[t].name, "AC/5")) base = AC5_INCENDIARY_AMMO; if(strstr(MechWeapons[t].name, "AC/10")) base = AC10_INCENDIARY_AMMO; if(strstr(MechWeapons[t].name, "AC/20")) base = AC20_INCENDIARY_AMMO; if(strstr(MechWeapons[t].name, "LightAC/2")) base = LAC2_INCENDIARY_AMMO; if(strstr(MechWeapons[t].name, "LightAC/5")) base = LAC5_INCENDIARY_AMMO; } if(m & AC_PRECISION_MODE) { if(strstr(MechWeapons[t].name, "AC/2")) base = AC2_PRECISION_AMMO; if(strstr(MechWeapons[t].name, "AC/5")) base = AC5_PRECISION_AMMO; if(strstr(MechWeapons[t].name, "AC/10")) base = AC10_PRECISION_AMMO; if(strstr(MechWeapons[t].name, "AC/20")) base = AC20_PRECISION_AMMO; if(strstr(MechWeapons[t].name, "LightAC/2")) base = LAC2_PRECISION_AMMO; if(strstr(MechWeapons[t].name, "LightAC/5")) base = LAC5_PRECISION_AMMO; } if(m & AC_CASELESS_MODE) { if(strstr(MechWeapons[t].name, "AC/2")) base = AC2_CASELESS_AMMO; if(strstr(MechWeapons[t].name, "AC/5")) base = AC5_CASELESS_AMMO; if(strstr(MechWeapons[t].name, "AC/10")) base = AC10_CASELESS_AMMO; if(strstr(MechWeapons[t].name, "AC/20")) base = AC20_CASELESS_AMMO; if(strstr(MechWeapons[t].name, "LightAC/2")) base = LAC2_CASELESS_AMMO; if(strstr(MechWeapons[t].name, "LightAC/5")) base = LAC5_CASELESS_AMMO; } if(base < 0) return I2Ammo(t); return Cargo(base); } if(m & INARC_EXPLO_MODE) return Cargo(INARC_EXPLO_AMMO); else if(m & INARC_HAYWIRE_MODE) return Cargo(INARC_HAYWIRE_AMMO); else if(m & INARC_ECM_MODE) return Cargo(INARC_ECM_AMMO); else if(m & INARC_NEMESIS_MODE) return Cargo(INARC_NEMESIS_AMMO); if(base < 0) return I2Ammo(t); if(m & NARC_MODE) return Cargo(base) + NARC_LRM_AMMO - LRM_AMMO; if(m & ARTEMIS_MODE) return Cargo(base) + ARTEMIS_LRM_AMMO - LRM_AMMO; if(m & SWARM_MODE) return Cargo(base) + SWARM_LRM_AMMO - LRM_AMMO; if(m & SWARM1_MODE) return Cargo(base) + SWARM1_LRM_AMMO - LRM_AMMO; if(m & INFERNO_MODE) return Cargo(base) + INFERNO_SRM_AMMO - SRM_AMMO; if(m & STINGER_MODE) return Cargo(base) + AMMO_LRM_STINGER - LRM_AMMO; if(m & SGUIDED_MODE) return Cargo(base) + AMMO_LRM_SGUIDED - LRM_AMMO; return Cargo(base); }