From: <geo...@us...> - 2013-07-17 20:52:44
|
Revision: 6240 http://sourceforge.net/p/freeorion/code/6240 Author: geoffthemedio Date: 2013-07-17 20:52:39 +0000 (Wed, 17 Jul 2013) Log Message: ----------- -Modified FleetWnd to display meter-derived ship attack, rather than design stats. -Modified combat to use meter-derived ship part attack strengths, rather than design stats. -Modified meter-only effectsgroup execution functions to include ship part meters. -Added some getters to SetShipPartMeter effect to facilitate the previous change. -Modified SetShipPartMeter to only set meters once, not once per each copy of a part that is present. -Collectively, these changes mean effects can modify ship attack power and this will be taken into account in the UI and in combat, and effects won't be applied repeatedly when they shouldn't. Modified Paths: -------------- trunk/FreeOrion/UI/FleetWnd.cpp trunk/FreeOrion/combat/CombatSystem.cpp trunk/FreeOrion/universe/Effect.cpp trunk/FreeOrion/universe/Effect.h Modified: trunk/FreeOrion/UI/FleetWnd.cpp =================================================================== --- trunk/FreeOrion/UI/FleetWnd.cpp 2013-07-17 08:47:25 UTC (rev 6239) +++ trunk/FreeOrion/UI/FleetWnd.cpp 2013-07-17 20:52:39 UTC (rev 6240) @@ -735,7 +735,9 @@ // update stat icon values and browse wnds - for (std::vector<std::pair<std::string, StatisticIcon*> >::const_iterator it = m_stat_icons.begin(); it != m_stat_icons.end(); ++it) { + for (std::vector<std::pair<std::string, StatisticIcon*> >::const_iterator it = m_stat_icons.begin(); + it != m_stat_icons.end(); ++it) + { //std::cout << "setting ship stat " << it->first << " to value: " << StatValue(it->first) << std::endl; it->second->SetValue(StatValue(it->first)); @@ -759,12 +761,8 @@ double ShipDataPanel::StatValue(const std::string& stat_name) const { if (const Ship* ship = GetShip(m_ship_id)) { - if (stat_name == DAMAGE_STAT_STRING) { - if (const ShipDesign* design = ship->Design()) - return design->Attack(); - else - return 0.0; - } + if (stat_name == DAMAGE_STAT_STRING) + return ship->TotalWeaponsDamage(); MeterType meter_type = MeterTypeFromStatString(stat_name); //std::cout << "got meter type " << boost::lexical_cast<std::string>(meter_type) << " from stat_name " << stat_name << std::endl; @@ -1292,7 +1290,7 @@ if (const Ship* ship = GetShip(ship_id)) { if (const ShipDesign* design = ship->Design()) { ship_count++; - damage_tally += design->Attack(); + damage_tally += ship->TotalWeaponsDamage(); structure_tally += ship->CurrentMeterValue(METER_STRUCTURE); shield_tally += ship->CurrentMeterValue(METER_SHIELD); fuels.push_back(ship->CurrentMeterValue(METER_FUEL)); @@ -2426,12 +2424,12 @@ if (const Ship* ship = GetShip(ship_id)) { if (const ShipDesign* design = ship->Design()) { ship_count++; - damage_tally += design->Attack(); + damage_tally += ship->TotalWeaponsDamage(); structure_tally += ship->CurrentMeterValue(METER_STRUCTURE); shield_tally += ship->CurrentMeterValue(METER_SHIELD); } } - } + } } for (std::vector<std::pair<std::string, StatisticIcon*> >::const_iterator it = @@ -2508,6 +2506,9 @@ // skip fleets in wrong system if (fleet->SystemID() != m_system_id) continue; + // skip empty fleets + //if (fleet->Empty()) + // continue; // skip known destroyed and stale info objects if (this_client_known_destroyed_objects.find(fleet_id) != this_client_known_destroyed_objects.end() || @@ -2667,7 +2668,6 @@ return; // verify that fleet is consistent - const GG::Pt row_size = m_fleets_lb->ListRowSize(); FleetRow* row = new FleetRow(fleet_id, GG::X1, row_size.y); m_fleets_lb->Insert(row); Modified: trunk/FreeOrion/combat/CombatSystem.cpp =================================================================== --- trunk/FreeOrion/combat/CombatSystem.cpp 2013-07-17 08:47:25 UTC (rev 6239) +++ trunk/FreeOrion/combat/CombatSystem.cpp 2013-07-17 20:52:39 UTC (rev 6240) @@ -463,14 +463,14 @@ } struct PartAttackInfo { - PartAttackInfo(ShipPartClass c, const std::string& s, double a) : - part_class(c), - part_type_name(s), - part_attack(a) + PartAttackInfo(ShipPartClass part_class_, const std::string& part_name_, float part_attack_) : + part_class(part_class_), + part_type_name(part_name_), + part_attack(part_attack_) {} ShipPartClass part_class; std::string part_type_name; - double part_attack; + float part_attack; }; std::vector<PartAttackInfo> ShipWeaponsStrengths(const Ship* ship) { @@ -481,23 +481,27 @@ if (!design) return retval; const std::vector<std::string>& parts = design->Parts(); - // check if each part is a weapon - for (std::vector<std::string>::const_iterator it = parts.begin(); it != parts.end(); ++it) { - const PartType* part = GetPartType(*it); + + // 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(); - double part_attack = 0.0; - // TODO: base this off meter values, not part stats - if (part->Class() == PC_SHORT_RANGE || part->Class() == PC_POINT_DEFENSE) - part_attack = boost::get<DirectFireStats>(part->Stats()).m_damage; - else if (part->Class() == PC_MISSILES) - part_attack = boost::get<LRStats>(part->Stats()).m_damage; - else if (part->Class() == PC_FIGHTERS) - part_attack = boost::get<FighterStats>(part->Stats()).m_anti_ship_damage; - if (part_attack == 0.0) - continue; - retval.push_back(PartAttackInfo(part->Class(), *it, part_attack)); + // 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 = ship->CurrentPartMeterValue(METER_DAMAGE, part_name); + else if (part_class == PC_FIGHTERS) + part_attack = ship->CurrentPartMeterValue(METER_ANTI_SHIP_DAMAGE, part_name); + + if (part_attack > 0.0) + retval.push_back(PartAttackInfo(part_class, part_name, part_attack)); } return retval; } Modified: trunk/FreeOrion/universe/Effect.cpp =================================================================== --- trunk/FreeOrion/universe/Effect.cpp 2013-07-17 08:47:25 UTC (rev 6239) +++ trunk/FreeOrion/universe/Effect.cpp 2013-07-17 20:52:39 UTC (rev 6240) @@ -329,16 +329,26 @@ effect_it != m_effects.end(); ++effect_it) { const EffectBase* effect = *effect_it; - const SetMeter* meter_effect = dynamic_cast<const SetMeter*>(effect); + MeterType meter_type = INVALID_METER_TYPE; + const Meter* meter = 0; - // for non-meter effects, can do default batch execute - if (!meter_effect) { + // for meter effects, need to separately call effect's Execute for each + // target and do meter accounting before and after. + const SetMeter* set_meter_effect = 0; + const SetShipPartMeter* set_ship_part_meter_effect = 0; + + if (set_meter_effect = dynamic_cast<const SetMeter*>(effect)) { + meter_type = set_meter_effect->GetMeterType(); + + } else if (set_ship_part_meter_effect = dynamic_cast<const SetShipPartMeter*>(effect)) { + meter_type = set_ship_part_meter_effect->GetMeterType(); + + } else { + // for non-meter effects, can do default batch execute effect->Execute(source_context, targets); continue; } - // for meter effects, need to separately call effect's Execute for each - // target and do meter accounting before and after. // accounting info for this effect on this meter, starting with // non-target-dependent info @@ -348,23 +358,39 @@ info.custom_label = targets_and_cause.effect_cause.custom_label; info.source_id = source_id; - MeterType meter_type = meter_effect->GetMeterType(); + // process each target separately to do effect accounting for (TargetSet::const_iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { UniverseObject* target = *target_it; - // record pre-effect meter values - const Meter* meter = target->GetMeter(meter_type); + // get Meter for this effect and target + const Meter* meter = 0; + + if (set_meter_effect) { + meter = target->GetMeter(meter_type); + + } else if (set_ship_part_meter_effect) { + if (target->ObjectType() != OBJ_SHIP) + continue; // only ships have ship part meters + const Ship* ship = universe_object_cast<const Ship*>(target); + if (!ship) + continue; + meter = ship->GetPartMeter(meter_type, set_ship_part_meter_effect->GetPartName()); + } + if (!meter) continue; // some objects might match target conditions, but not actually have the relevant meter + + // record pre-effect meter values... + // accounting info for this effect on this meter of this target info.running_meter_total = meter->Current(); // actually execute effect to modify meter - meter_effect->Execute(ScriptingContext(source, target)); + effect->Execute(ScriptingContext(source, target)); // update for meter change and new total info.meter_change = meter->Current() - info.running_meter_total; @@ -388,16 +414,29 @@ effect_it != m_effects.end(); ++effect_it) { const EffectBase* effect = *effect_it; - const SetMeter* meter_effect = dynamic_cast<const SetMeter*>(effect); - if (!meter_effect) - continue; + MeterType meter_type = INVALID_METER_TYPE; + const Meter* meter = 0; - MeterType meter_type = meter_effect->GetMeterType(); - const Meter* meter = target->GetMeter(meter_type); + // only process SetMeter and SetShipPartMeter effects in this function + + if (const SetMeter* meter_effect = dynamic_cast<const SetMeter*>(effect)) { + meter_type = meter_effect->GetMeterType(); + meter = target->GetMeter(meter_type); + + } else if (const SetShipPartMeter* meter_effect = dynamic_cast<const SetShipPartMeter*>(effect)) { + meter_type = meter_effect->GetMeterType(); + if (target->ObjectType() != OBJ_SHIP) + continue; + const Ship* ship = universe_object_cast<const Ship*>(target); + if (!ship) + continue; + meter = ship->GetPartMeter(meter_type, meter_effect->GetPartName()); + } + if (!meter) continue; - meter_effect->Execute(ScriptingContext(source, target)); + effect->Execute(ScriptingContext(source, target)); } } } @@ -409,7 +448,8 @@ for (TargetSet::const_iterator target_it = targets.begin(); target_it != targets.end(); ++target_it) { UniverseObject* target = *target_it; - //Logger().debugStream() << "effectsgroup source: " << source->Name() << " target " << (*it)->Name(); + // only process SetEmpireMeter effects in this function + for (std::vector<EffectBase*>::const_iterator effect_it = m_effects.begin(); effect_it != m_effects.end(); ++effect_it) { @@ -437,12 +477,25 @@ effect_it != m_effects.end(); ++effect_it) { const EffectBase* effect = *effect_it; - const SetMeter* meter_effect = dynamic_cast<const SetMeter*>(effect); - if (!meter_effect) - continue; + MeterType meter_type = INVALID_METER_TYPE; + const Meter* meter = 0; - MeterType meter_type = meter_effect->GetMeterType(); - const Meter* meter = target->GetMeter(meter_type); + // only process SetMeter and SetShipPartMeter effects in this function + + if (const SetMeter* meter_effect = dynamic_cast<const SetMeter*>(effect)) { + meter_type = meter_effect->GetMeterType(); + meter = target->GetMeter(meter_type); + + } else if (const SetShipPartMeter* meter_effect = dynamic_cast<const SetShipPartMeter*>(effect)) { + meter_type = meter_effect->GetMeterType(); + if (target->ObjectType() != OBJ_SHIP) + continue; + const Ship* ship = universe_object_cast<const Ship*>(target); + if (!ship) + continue; + meter = ship->GetPartMeter(meter_type, meter_effect->GetPartName()); + } + if (!meter) continue; @@ -761,10 +814,15 @@ return; } - // loop through all parts in the ship design, applying effect to each if appropriate + // loop through all part meters in the ship design, applying effect to each if part is appropriate const std::vector<std::string>& design_parts = ship->Design()->Parts(); - for (std::size_t i = 0; i < design_parts.size(); ++i) { - const std::string& target_part_name = design_parts[i]; + std::set<std::string> unique_design_parts; + std::copy(design_parts.begin(), design_parts.end(), std::inserter(unique_design_parts, unique_design_parts.begin())); + + for (std::set<std::string>::const_iterator it = unique_design_parts.begin(); + it != unique_design_parts.end(); ++it) + { + const std::string& target_part_name = *it; if (target_part_name.empty()) continue; // slots in a design may be empty... this isn't an error Modified: trunk/FreeOrion/universe/Effect.h =================================================================== --- trunk/FreeOrion/universe/Effect.h 2013-07-17 08:47:25 UTC (rev 6239) +++ trunk/FreeOrion/universe/Effect.h 2013-07-17 20:52:39 UTC (rev 6240) @@ -101,13 +101,16 @@ void Execute(int source_id, const TargetSet& targets) const; void Execute(int source_id, const TargetsAndCause& targets_and_cause, AccountingMap& accounting_map) const; + /** execute all SetMeter effects in group. This is useful for doing meter * estimate updates and effect accounting, for which executing non-meter * effects is neither needed nor useful. */ void ExecuteSetMeter(int source_id, const TargetSet& targets) const; void ExecuteSetMeter(int source_id, const TargetsAndCause& targets_and_cause, AccountingMap& accounting_map) const; + void ExecuteSetEmpireMeter(int source_id, const TargetSet& targets) const; + /** execute all appearance modifying effects in group. */ void ExecuteAppearanceModifications(int source_id, const TargetSet& targets) const; @@ -216,6 +219,9 @@ virtual void Execute(const ScriptingContext& context) const; virtual std::string Description() const; virtual std::string Dump() const; + const std::string& GetPartName() const {return m_part_name;} + ShipSlotType GetShipSlotType() const {return m_slot_type;} + MeterType GetMeterType() const {return m_meter;}; private: ShipPartClass m_part_class; |