private void AddTo(ref Dictionary <RESIST,Dictionary <bool,Dictionary <int,List <float> > > > ResistBonuses,RESIST Resist,bool Hot,int StackGroup,float Value,uint Count) { if (!ResistBonuses.ContainsKey(Resist)) { ResistBonuses.Add(Resist,new Dictionary <bool,Dictionary <int,List <float> > >()); } if (!ResistBonuses[Resist].ContainsKey(Hot)) { ResistBonuses[Resist].Add(Hot,new Dictionary <int,List <float> >()); } if (!ResistBonuses[Resist][Hot].ContainsKey(StackGroup)) { ResistBonuses[Resist][Hot].Add(StackGroup,new List <float>()); } for (uint i = 0; i < Count; ++i) { ResistBonuses[Resist][Hot][StackGroup].Add(Value); } }
GetLayerTank(float BaseHP,float LayerMultiplier,float ResistEM,float ResistThermal,float ResistKinetic,float ResistExplosive,bool isPolarized,LAYER Layer,IReadOnlyCollection <Tuple <ModuleDescription,uint> > Modules,float ShipOverheatingBonus) { float FlatHPBonus = 0.0f; float HPMultiplier = LayerMultiplier; // resist => cold/hot => stacking_group => list of resist bonuses Dictionary <RESIST,Dictionary <bool,Dictionary <int,List <float> > > > ResistBonuses = new Dictionary <RESIST,Dictionary <bool,Dictionary <int,List <float> > > >(); float SubsystemOverheatingBonus = 0.0f; foreach (Tuple <ModuleDescription,uint> ModuleAndCount in Modules) { uint Count = ModuleAndCount.Item2; if (ModuleAndCount.Item1.m_Effects.ContainsKey(Layer)) { if (ModuleAndCount.Item1.m_Effects[Layer].ContainsKey(EFFECT.OVERHEATING)) { if (ModuleAndCount.Item1.m_Effects[Layer][EFFECT.OVERHEATING].ContainsKey(ACTIVE.PASSIVE)) { // Only subsystems (passive modules) can be with overheating bonus. // Not active and not assault DCs. Debug.Assert(Count == 1); Debug.Assert(SubsystemOverheatingBonus <= 0.0f); SubsystemOverheatingBonus = ModuleAndCount.Item1.m_Effects[Layer][EFFECT.OVERHEATING][ACTIVE.PASSIVE].Item1; Debug.Assert(SubsystemOverheatingBonus > 0.0f); } } } } foreach (Tuple <ModuleDescription,uint> ModuleAndCount in Modules) { uint Count = ModuleAndCount.Item2; if (ModuleAndCount.Item1.m_Effects.ContainsKey(Layer)) { foreach (EFFECT Effect in ModuleAndCount.Item1.m_Effects[Layer].Keys) { foreach (ACTIVE Active in ModuleAndCount.Item1.m_Effects[Layer][Effect].Keys) { Tuple <float,int> EffectParams = ModuleAndCount.Item1.m_Effects[Layer][Effect][Active]; switch (Effect) { case EFFECT.ADD: Debug.Assert(Active == ACTIVE.PASSIVE); // all flat shield/armor/hull bonuses belong to passive modules Debug.Assert(EffectParams.Item2 == 1); // all flat shield/armor/hull bonuses have stacking group 1 FlatHPBonus += (EffectParams.Item1 * Count); break; case EFFECT.MULTIPLY: Debug.Assert(Active == ACTIVE.PASSIVE); // all multiplicative shield/armor/hull bonuses belong to passive modules Debug.Assert(EffectParams.Item2 == 1); // all multiplicative shield/armor/hull bonuses have stacking group 1 HPMultiplier *= (float)Math.Pow(EffectParams.Item1,Count); break; case EFFECT.EM: case EFFECT.THERMAL: case EFFECT.KINETIC: case EFFECT.EXPLOSIVE: if (!isPolarized) { RESIST Resist = EffectToResist(Effect); switch (Active) { case ACTIVE.PASSIVE: // passive effect AddTo(ref ResistBonuses,Resist,false,EffectParams.Item2,EffectParams.Item1,Count); AddTo(ref ResistBonuses,Resist,true,EffectParams.Item2,EffectParams.Item1,Count); break; case ACTIVE.ACTIVE: // active effect if (!PassiveTank) { AddTo(ref ResistBonuses,Resist,false,EffectParams.Item2,EffectParams.Item1,Count); float OverloadBonus = ModuleAndCount.Item1.m_OverloadBonus; if (OverloadBonus > 0.01f) { float OverloadedResist = EffectParams.Item1 * (1.0f + OverloadBonus * (1.0f + ShipOverheatingBonus + SubsystemOverheatingBonus)); AddTo(ref ResistBonuses,Resist,true,EffectParams.Item2,OverloadedResist,Count); } else { AddTo(ref ResistBonuses,Resist,true,EffectParams.Item2,EffectParams.Item1,Count); } } break; case ACTIVE.ASSAULT_PASSIVE: // bonus from passive ADC if (PassiveTank || !AssaultDCEnabled) { AddTo(ref ResistBonuses,Resist,false,EffectParams.Item2,EffectParams.Item1,Count); AddTo(ref ResistBonuses,Resist,true,EffectParams.Item2,EffectParams.Item1,Count); } break; case ACTIVE.ASSAULT_ACTIVE: // bonus from active ADC if (!PassiveTank && AssaultDCEnabled) { AddTo(ref ResistBonuses,Resist,false,EffectParams.Item2,EffectParams.Item1,Count); AddTo(ref ResistBonuses,Resist,true,EffectParams.Item2,EffectParams.Item1,Count); } break; } } break; } } } } } float LayerHP = (BaseHP + FlatHPBonus) * HPMultiplier; LayerHP *= 1.25f; // Shield Management / Hull Upgrades / Mechanics Dictionary <RESIST,float> ResistsCold = new Dictionary <RESIST,float>(); Dictionary <RESIST,float> ResistsHot = new Dictionary <RESIST,float>(); if (!isPolarized) { Dictionary <RESIST,Dictionary <bool,float> > Resonances = new Dictionary <RESIST,Dictionary <bool,float> >(); Resonances[RESIST.EM] = new Dictionary <bool,float>(); Resonances[RESIST.THERMAL] = new Dictionary <bool,float>(); Resonances[RESIST.KINETIC] = new Dictionary <bool,float>(); Resonances[RESIST.EXPLOSIVE] = new Dictionary <bool,float>(); foreach (RESIST Resist in ResistBonuses.Keys) { foreach (bool Hot in ResistBonuses[Resist].Keys) { float ResonanceCombined = 1.0f; foreach (int StackGroup in ResistBonuses[Resist][Hot].Keys) { List <float> ResistsGroup = ResistBonuses[Resist][Hot][StackGroup]; ResistsGroup.Sort( delegate(float a,float b) { if (a < b) { return(1); } if (a > b) { return(-1); } return(0); } ); float Resonance = 1.0f; for (int i = 0; i < ResistsGroup.Count; ++i) { float pc = PenaltyCoeff(i); Resonance *= (1.0f - ResistsGroup[i] * pc); } ResonanceCombined *= Resonance; } Resonances[Resist][Hot] = ResonanceCombined; } } ResistsCold[RESIST.EM] = 1.0f - (1.0f - ResistEM) * GetResonance(Resonances,RESIST.EM,false); ResistsCold[RESIST.THERMAL] = 1.0f - (1.0f - ResistThermal) * GetResonance(Resonances,RESIST.THERMAL,false); ResistsCold[RESIST.KINETIC] = 1.0f - (1.0f - ResistKinetic) * GetResonance(Resonances,RESIST.KINETIC,false); ResistsCold[RESIST.EXPLOSIVE] = 1.0f - (1.0f - ResistExplosive) * GetResonance(Resonances,RESIST.EXPLOSIVE,false); ResistsHot[RESIST.EM] = 1.0f - (1.0f - ResistEM) * GetResonance(Resonances,RESIST.EM,true); ResistsHot[RESIST.THERMAL] = 1.0f - (1.0f - ResistThermal) * GetResonance(Resonances,RESIST.THERMAL,true); ResistsHot[RESIST.KINETIC] = 1.0f - (1.0f - ResistKinetic) * GetResonance(Resonances,RESIST.KINETIC,true); ResistsHot[RESIST.EXPLOSIVE] = 1.0f - (1.0f - ResistExplosive) * GetResonance(Resonances,RESIST.EXPLOSIVE,true); } else { ResistsCold[RESIST.EM] = 0.0f; ResistsCold[RESIST.THERMAL] = 0.0f; ResistsCold[RESIST.KINETIC] = 0.0f; ResistsCold[RESIST.EXPLOSIVE] = 0.0f; ResistsHot[RESIST.EM] = 0.0f; ResistsHot[RESIST.THERMAL] = 0.0f; ResistsHot[RESIST.KINETIC] = 0.0f; ResistsHot[RESIST.EXPLOSIVE] = 0.0f; } return(new Tuple <float,Dictionary <RESIST,float>,Dictionary <RESIST,float> >(LayerHP,ResistsCold,ResistsHot)); }
float GetResonance(IReadOnlyDictionary <RESIST,Dictionary <bool,float> > Resonances,RESIST Resist,bool Hot) { if (Resonances.ContainsKey(Resist)) { if (Resonances[Resist].ContainsKey(Hot)) { return(Resonances[Resist][Hot]); } } return(1.0f); }