public SpellData(string name, IniBin ini) { var enumTranslationService = new EnumTranslationService(); Name = name; Flags = (SpellFlags)(ini["SpellData", "Flags"].Int() ?? 0); TextFlags = ini["SpellData", "TextFlags"].String() ?? ""; var cooldownTime = new Dictionary <int, float>(7); var maxAmmo = new Dictionary <int, int>(7); var ammoUsed = new Dictionary <int, int>(7); var ammoRechargeTime = new Dictionary <int, float>(7); var castRange = new Dictionary <int, float>(7); var channelDuration = new Dictionary <int, float>(7); var castRangeGrowthMax = new Dictionary <int, float>(7); var castRangeGrowthDuration = new Dictionary <int, float>(7); var castRadius = new Dictionary <int, float>(7); var castRadiusSecondary = new Dictionary <int, float>(7); var mana = new Dictionary <int, float>(7); cooldownTime[0] = ini["SpellData", "Cooldown"].Float() ?? 10.0f; maxAmmo[0] = ini["SpellData", "MaxAmmo"].Int() ?? 0; ammoUsed[0] = ini["SpellData", "AmmoUsed"].Int() ?? 1; ammoRechargeTime[0] = ini["SpellData", "AmmoRechargeTime"].Float() ?? 0.0f; channelDuration[0] = ini["SpellData", "ChannelDuration"].Float() ?? 0.0f; castRange[0] = ini["SpellData", "CastRange"].Float() ?? 400.0f; castRangeGrowthMax[0] = ini["SpellData", "CastRangeGrowthMax"].Float() ?? 0.0f; castRangeGrowthDuration[0] = ini["SpellData", "CastRangeGrowthDuration"].Float() ?? 0.0f; castRadius[0] = ini["SpellData", "CastRadius"].Float() ?? 0.0f; castRadiusSecondary[0] = ini["SpellData", "CastRadiusSecondary"].Float() ?? 0.0f; mana[0] = ini["SpellData", "ManaCost1"].Float() ?? 0.0f; for (var i = 1; i < 7; i++) { cooldownTime[i] = ini["SpellData", $"Cooldown{i}"].Float() ?? cooldownTime[0]; maxAmmo[i] = ini["SpellData", $"MaxAmmo{i}"].Int() ?? maxAmmo[0]; ammoUsed[i] = ini["SpellData", $"AmmoUsed{i}"].Int() ?? ammoUsed[0]; ammoRechargeTime[i] = ini["SpellData", $"AmmoRechargeTime{i}"].Float() ?? ammoRechargeTime[0]; channelDuration[i] = ini["SpellData", $"ChannelDuration{i}"].Float() ?? channelDuration[0]; castRange[i] = ini["SpellData", $"CastRange{i}"].Float() ?? castRange[0]; castRangeGrowthMax[i] = ini["SpellData", $"CastRangeGrowthMax{i}"].Float() ?? castRangeGrowthMax[0]; castRangeGrowthDuration[i] = ini["SpellData", $"CastRangeGrowthDuration{i}"].Float() ?? castRangeGrowthDuration[0]; castRadius[i] = ini["SpellData", $"CastRadius{i}"].Float() ?? castRadius[0]; castRadiusSecondary[i] = ini["SpellData", $"CastRadiusSecondary{i}"].Float() ?? castRadiusSecondary[0]; mana[i] = ini["SpellData", $"ManaCost{i}"].Float() ?? mana[0]; } CooldownTime = cooldownTime; MaxAmmo = maxAmmo; AmmoUsed = ammoUsed; AmmoRechargeTime = ammoRechargeTime; ChannelDuration = channelDuration; CastRange = castRange; CastRangeGrowthMax = castRangeGrowthMax; CastRangeGrowthDuration = castRangeGrowthDuration; CastRadius = castRadius; CastRadiusSecondary = castRadiusSecondary; Mana = mana; var totalTime = ini["SpellData", "SpellTotalTime"].Float() ?? 0.0f; var castTime = ini["SpellData", "SpellCastTime"].Float() ?? 0.0f; castTime = Math.Min(castTime, totalTime); if (totalTime > 0.0f && castTime > 0.0f) { SpellTotalTime = totalTime; SpellCastTime = castTime; } else { var delayTotalPercent = ini["SpellData", "DelayTotalTimePercent"].Float() ?? 0.0f; var delayCastPercent = ini["SpellData", "DelayCastOffsetPercent"].Float() ?? 0.0f; SpellTotalTime = (delayTotalPercent + 1.0f) * 2.0f; SpellCastTime = (delayCastPercent + 1.0f) * 0.5f; } OverrideCastTime = ini["SpellData", "OverrideCastTime"].Float() ?? 0.0f; StartCooldown = ini["SpellData", "StartCooldown"].Float() ?? 0.0f; ChargeUpdateInterval = ini["SpellData", "ChargeUpdateInterval"].Float() ?? 0.0f; CancelChargeOnRecastTime = ini["SpellData", "CancelChargeOnRecastTime"].Float() ?? 0.0f; CastConeAngle = ini["SpellData", "CastConeAngle"].Float() ?? 45.0f; CastConeDistance = ini["SpellData", "CastConeDistance"].Float() ?? 400.0f; CastTargetAdditionalUnitsRadius = ini["SpellData", "CastTargetAdditionalUnitsRadius"].Float() ?? 0.0f; CastFrame = ini["SpellData", "CastFrame"].Float() ?? 0.0f; LineWidth = ini["SpellData", "LineWidth"].Float() ?? 0.0f; LineDragLength = ini["SpellData", "LineDragLength"].Float() ?? 0.0f; LookAtPolicy = enumTranslationService.TranslateLookAtPolicy(ini["SpellData", "LookAtPolicy"].StringEnum <LookAtPolicy>() ?? LeagueData.LookAtPolicy.Automatic); SelectionPreference = enumTranslationService.TranslateSelectionPreference(ini["SpellData", "SelectionPreference"].StringEnum <SelectionPreference>() ?? LeagueData.SelectionPreference.None); TargetingType = enumTranslationService.TranslateTargetingType((TargetingType)(ini["SpellData", "TargettingType"].Int() ?? 1)); CastRangeUseBoundingBoxes = ini["SpellData", "CastRangeUseBoundingBoxes"].IntBool() ?? false; AmmoNotAffectedByCDR = ini["SpellData", "AmmoNotAffectedByCDR"].Bool() ?? false; UseAutoattackCastTime = ini["SpellData", "UseAutoattackCastTime"].Bool() ?? false; IgnoreAnimContinueUntilCastFrame = ini["SpellData", "IgnoreAnimContinueUntilCastFrame"].Bool() ?? false; IsToggleSpell = ini["SpellData", "IsToggleSpell"].Bool() ?? false; CanNotBeSuppressed = ini["SpellData", "CanNotBeSuppressed"].Bool() ?? false; CanCastWhileDisabled = ini["SpellData", "CanCastWhileDisabled"].Bool() ?? false; CanOnlyCastWhileDisabled = ini["SpellData", "CanOnlyCastWhileDisabled"].Bool() ?? false; CantCancelWhileWindingUp = ini["SpellData", "CantCancelWhileWindingUp"].Bool() ?? false; CantCancelWhileChanneling = ini["SpellData", "CantCancelWhileChanneling"].Bool() ?? false; CantCastWhileRooted = ini["SpellData", "CantCastWhileRooted"].Bool() ?? false; DoesntBreakChannels = ini["SpellData", "DoesntBreakChannels"].Bool() ?? false; IsDisabledWhileDead = ini["SpellData", "IsDisabledWhileDead"].Bool() ?? true; CanOnlyCastWhileDead = ini["SpellData", "CanOnlyCastWhileDead"].Bool() ?? false; SpellRevealsChampion = ini["SpellData", "SpellRevealsChampion"].IntBool() ?? true; UseChargeChanneling = ini["SpellData", "UseChargeChanneling"].Bool() ?? false; UseChargeTargeting = ini["SpellData", "UseChargeTargeting"].Bool() ?? false; CanMoveWhileChanneling = ini["SpellData", "CanMoveWhileChanneling"].Bool() ?? false; DoNotNeedToFaceTarget = ini["SpellData", "DoNotNeedToFaceTarget"].Bool() ?? false; NoWinddownIfCancelled = ini["SpellData", "NoWinddownIfCancelled"].Bool() ?? false; IgnoreRangeCheck = ini["SpellData", "IgnoreRangeCheck"].Bool() ?? false; ConsideredAsAutoAttack = ini["SpellData", "ConsideredAsAutoAttack"].Bool() ?? false; ApplyAttackDamage = ini["SpellData", "ApplyAttackDamage"].Bool() ?? false; ApplyAttackEffect = ini["SpellData", "ApplyAttackEffect"].Bool() ?? false; AlwaysSnapFacing = ini["SpellData", "AlwaysSnapFacing"].Bool() ?? false; BelongsToAvatar = ini["SpellData", "BelongsToAvatar"].Bool() ?? false; CastType = enumTranslationService.TranslateCastType((LeagueData.CastType)(ini["SpellData", "CastType"].Int() ?? 0)); if (CastType == LeagueSandbox.GameServer.Core.Domain.Enums.CastType.Instant) { CastData = new CastData.Instant(); } else { var gravity = (ini["SpellData", "MissileGravity"].Float() ?? 0.0f) * 100.0f; var targetHeightAugment = ini["SpellData", "MissileTargetHeightAugment"].Float() ?? 100.0f; var speed = ini["SpellData", "MissileSpeed"].Float() ?? 500.0f; var accel = ini["SpellData", "MissileAccel"].Float() ?? 0.0f; var maxSpeed = ini["SpellData", "MissileMaxSpeed"].Float() ?? speed; var minSpeed = ini["SpellData", "MissileMinSpeed"].Float() ?? speed; var fixedTravelTime = ini["SpellData", "MissileFixedTravelTime"].Float() ?? 0.0f; var minTravelTime = ini["SpellData", "MissileMinTravelTime"].Float() ?? 0.0f; var lifetime = ini["SpellData", "MissileLifetime"].Float() ?? 0.0f; var unblockable = ini["SpellData", "MissileUnblockable"].Bool() ?? false; var blockTriggersOnDestroy = ini["SpellData", "MissileBlockTriggersOnDestroy"].Bool() ?? true; var perceptionBubbleRadius = ini["SpellData", "MissilePerceptionBubbleRadius"].Float() ?? 0.0f; var perceptionBubbleRevealsStealth = ini["SpellData", "MissilePerceptionBubbleRevealsStealth"].Bool() ?? false; var updateDistanceInterval = ini["SpellData", "LuaOnMissileUpdateDistanceInterval"].Float() ?? 0.0f; switch (CastType) { case LeagueSandbox.GameServer.Core.Domain.Enums.CastType.Instant: break; case LeagueSandbox.GameServer.Core.Domain.Enums.CastType.Missile: CastData = new CastData.Missile.Normal ( gravity: gravity, targetHeightAugment: targetHeightAugment, speed: speed, accel: accel, maxSpeed: maxSpeed, minSpeed: minSpeed, fixedTravelTime: fixedTravelTime, minTravelTime: minTravelTime, lifetime: lifetime, unblockable: unblockable, blockTriggersOnDestroy: blockTriggersOnDestroy, perceptionBubbleRadius: perceptionBubbleRadius, perceptionBubbleRevealsStealth: perceptionBubbleRevealsStealth, updateDistanceInterval: updateDistanceInterval ); break; case LeagueSandbox.GameServer.Core.Domain.Enums.CastType.ArcMissile: var followsTerrainHeight = ini["SpellData", "LineMissileFollowsTerrainHeight"].Bool() ?? false; var bounces = ini["SpellData", "LineMissileBounces"].Bool() ?? false; var usesAccelerationForBounce = ini["SpellData", "LineMissileUsesAccelerationForBounce"].Bool() ?? false; var trackUnits = ini["SpellData", "LineMissileTrackUnits"].Bool() ?? false; var trackUnitsAndContinues = ini["SpellData", "LineMissileTrackUnitsAndContinues"].Bool() ?? false; var delayDestroyAtEndSeconds = ini["Spelldata", "LineMissileDelayDestroyAtEndSeconds"].Float() ?? 0.0f; var timePulseBetweenCollisionSpellHits = ini["SpellData", "LineMissileTimePulseBetweenCollisionSpellHits"].Float() ?? 0.0f; var endsAtTargetPoint = ini["Spelldata", "LineMissileEndsAtTargetPoint"].Bool() ?? false; CastData = new CastData.Missile.Line ( gravity: gravity, targetHeightAugment: targetHeightAugment, speed: speed, accel: accel, maxSpeed: maxSpeed, minSpeed: minSpeed, fixedTravelTime: fixedTravelTime, minTravelTime: minTravelTime, lifetime: lifetime, unblockable: unblockable, blockTriggersOnDestroy: blockTriggersOnDestroy, perceptionBubbleRadius: perceptionBubbleRadius, perceptionBubbleRevealsStealth: perceptionBubbleRevealsStealth, updateDistanceInterval: updateDistanceInterval, followsTerrainHeight: followsTerrainHeight, bounces: bounces, usesAccelerationForBounce: usesAccelerationForBounce, trackUnits: trackUnits, trackUnitsAndContinues: trackUnitsAndContinues, delayDestroyAtEndSeconds: delayDestroyAtEndSeconds, timePulseBetweenCollisionSpellHits: timePulseBetweenCollisionSpellHits, endsAtTargetPoint: endsAtTargetPoint ); break; case LeagueSandbox.GameServer.Core.Domain.Enums.CastType.ChainMissile: CastData = new CastData.Missile.Chain ( gravity: gravity, targetHeightAugment: targetHeightAugment, speed: speed, accel: accel, maxSpeed: maxSpeed, minSpeed: minSpeed, fixedTravelTime: fixedTravelTime, minTravelTime: minTravelTime, lifetime: lifetime, unblockable: unblockable, blockTriggersOnDestroy: blockTriggersOnDestroy, perceptionBubbleRadius: perceptionBubbleRadius, perceptionBubbleRevealsStealth: perceptionBubbleRevealsStealth, updateDistanceInterval: updateDistanceInterval, bounceRadius: ini["SpellData", "BounceRadius"].Float() ?? 450.0f ); break; case LeagueSandbox.GameServer.Core.Domain.Enums.CastType.CircleMissile: var radialVelocity = ini["SpellData", "CircleMissileRadialVelocity"].Float() ?? 0.0f; var angularVelocity = ini["SpellData", "CircleMissileAngularVelocity"].Float() ?? 0.0f; CastData = new CastData.Missile.Circle ( gravity: gravity, targetHeightAugment: targetHeightAugment, speed: speed, accel: accel, maxSpeed: maxSpeed, minSpeed: minSpeed, fixedTravelTime: fixedTravelTime, minTravelTime: minTravelTime, lifetime: lifetime, unblockable: unblockable, blockTriggersOnDestroy: blockTriggersOnDestroy, perceptionBubbleRadius: perceptionBubbleRadius, perceptionBubbleRevealsStealth: perceptionBubbleRevealsStealth, updateDistanceInterval: updateDistanceInterval, radialVelocity: radialVelocity, angularVelocity: angularVelocity ); break; } } }
public CharData(string name, IniBin ini) { var enumTranslationService = new EnumTranslationService(); Name = name; CharDataFlags flags = 0; if (ini["Data", "IsEpic"].StringBool() ?? false) { flags |= CharDataFlags.Epic; } if (ini["Data", "IsElite"].StringBool() ?? false) { flags |= CharDataFlags.Elite; } if (ini["Data", "DrawPARLikeHealth"].StringBool() ?? false) { flags |= CharDataFlags.DrawPARLikeHealth; } if (ini["Data", "IsMelee"].StringBool() ?? false) { flags |= CharDataFlags.Melee; } if (ini["Data", "NeverRender"].Bool() ?? false) { flags |= CharDataFlags.NeverRender; } if (ini["Data", "ServerOnly"].Bool() ?? false) { flags |= CharDataFlags.ServerOnly; } if (ini["Data", "NoAutoAttack"].Bool() ?? false) { flags |= CharDataFlags.NoAutoAttack; } if (ini["Data", "NoHealthBar"].Bool() ?? false) { flags |= CharDataFlags.NoHealthBar; } if (ini["Data", "ShouldFaceTarget"].Bool() ?? true) { flags |= CharDataFlags.ShouldFaceTarget; } if (ini["Data", "PARDisplayThroughDeath"].Bool() ?? false) { flags |= CharDataFlags.PARDisplayThroughDeath; } if (ini["Data", "AllowPetControl"].Bool() ?? true) { flags |= CharDataFlags.AllowPetControl; } if (ini["Data", "SkipDrawOutline"].Bool() ?? false) { flags |= CharDataFlags.SkipDrawOutline; } if (ini["Data", "UseChampionVisibility"].Bool() ?? false) { flags |= CharDataFlags.UseChampionVisibility; } if (ini["Data", "TriggersOrderAcknowledgementVO"].StringBool() ?? true) { flags |= CharDataFlags.TriggersOrderAcknowledgementVO; } if (ini["Data", "FireworksEnabled"].Bool() ?? false) { flags |= CharDataFlags.HasExpandedVO; } if (ini["Data", "DisableUltReadySounds"].Bool() ?? false) { flags |= CharDataFlags.DisableUltReadySounds; } if (ini["Data", "IsImportantBotTarget"].Bool() ?? false) { flags |= CharDataFlags.IsImportantBotTarget; } if (ini["Data", "DisableGlobalDeathEffect"].Bool() ?? false) { flags |= CharDataFlags.DisableGlobalDeathEffect; } if (ini["Data", "DisableAggroIndicator"].Bool() ?? false) { flags |= CharDataFlags.DisableAggroIndicator; } if (ini["Data", "SequentialAutoAttacks"].Bool() ?? false) { flags |= CharDataFlags.SequentialAutoAttacks; } if (ini["Data", "DisableContinuousTargetFacing"].Bool() ?? false) { flags |= CharDataFlags.DisableContinuousTargetFacing; } if (ini["Data", "Immobile"].Bool() ?? false) { flags |= CharDataFlags.Immobile; } if (ini["Data", "UseRingIconForKillCallout"].Bool() ?? true) { flags |= CharDataFlags.UseRingIconForKillCallout; } Flags = flags; PARType = enumTranslationService.TranslatePrimaryAbilityResourceType(ini["Data", "PARType"].StringEnum <PARType>() ?? LeagueData.PARType.Mana); AssetCategory = ini["Data", "AssetCategory"].String() ?? "character"; MonsterDataTableID = ini["Data", "MonsterDataTableID"].Int() ?? 0; RecordAsWard = ini["Data", "RecordAsWard"].Bool() ?? false; PostAttackMoveDelay = ini["Data", "PostAttackMoveDelay"].Float() ?? 0.0f; ChasingAttackRangePercent = ini["Data", "ChasingAttackRangePercent"].Float() ?? 0.5f; ChampionId = ini["Data", "ChampionId"].Int() ?? 0; BaseSpellEffectiveness = ini["Data", "BaseSpellEffectiveness"].Float() ?? 0.0f; BaseHP = ini["Data", "BaseHP"].Float() ?? 100.0f; BasePAR = ini["Data", "BaseMP"].Float() ?? 100.0f; HPPerLevel = ini["Data", "HPPerLevel"].Float() ?? 0.0f; PARPerLevel = ini["Data", "MPPerLevel"].Float() ?? 0.0f; HPRegenPerLevel = ini["Data", "HPRegenPerLevel"].Float() ?? 0.0f; PARRegenPerLevel = ini["Data", "MPRegenPerLevel"].Float() ?? 0.0f; BaseStaticHPRegen = ini["Data", "BaseStaticHPRegen"].Float() ?? 1.0f; BaseFactorHPRegen = ini["Data", "BaseFactorHPRegen"].Float() ?? 0.0f; BaseStaticPARRegen = ini["Data", "BaseStaticMPRegen"].Float() ?? 1.0f; BaseFactorPARRegen = ini["Data", "BaseFactorMPRegen"].Float() ?? 0.0f; BasePhysicalDamage = ini["Data", "BaseDamage"].Float() ?? 10.0f; PhysicalDamagePerLevel = ini["Data", "DamagePerLevel"].Float() ?? 0.0f; BaseAbilityPower = ini["Data", "BaseAbilityPower"].Float() ?? 0.0f; AbilityPowerIncPerLevel = ini["Data", "AbilityPowerIncPerLevel"].Float() ?? 0.0f; BaseArmor = ini["Data", "Armor"].Float() ?? 1.0f; ArmorPerLevel = ini["Data", "ArmorPerLevel"].Float() ?? 0.0f; BaseSpellBlock = ini["Data", "SpellBlock"].Float() ?? 0.0f; SpellBlockPerLevel = ini["Data", "SpellBlockPerLevel"].Float() ?? 0.0f; BaseDodge = ini["Data", "BaseDodge"].Float() ?? 0.0f; DodgePerLevel = ini["Data", "LevelDodge"].Float() ?? 0.0f; BaseMissChance = ini["Data", "BaseMissChance"].Float() ?? 0.0f; BaseCritChance = ini["Data", "BaseCritChance"].Float() ?? 0.0f; CritChancePerLevel = ini["Data", "CritPerLevel"].Float() ?? 0.0f; CritDamageMultiplier = ini["Data", "CritDamageBonus"].Float() ?? 2.0f; BaseMoveSpeed = ini["Data", "MoveSpeed"].Float() ?? 100.0f; AttackRange = ini["Data", "AttackRange"].Float() ?? 100.0f; AttackAutoInterruptPercent = ini["Data", "AttackAutoInterruptPercent"].Float() ?? 0.2f; AcquisitionRange = ini["Data", "AcquisitionRange"].Float() ?? 750.0f; AttackSpeedPerLevel = (ini["Data", "AttackSpeedPerLevel"].Float() ?? 0.0f) / 100.0f; TowerTargetingPriority = ini["Data", "TowerTargetingPriorityBoost"].Float() ?? 0.0f; DeathTime = ini["Data", "DeathTime"].Float() ?? -1.0f; ExpGivenOnDeath = ini["Data", "ExpGivenOnDeath"].Float() ?? 48.0f; GoldGivenOnDeath = ini["Data", "GoldGivenOnDeath"].Float() ?? 25.0f; GoldRadius = ini["Data", "GoldRadius"].Float() ?? 0.0f; ExperienceRadius = ini["Data", "ExperienceRadius"].Float() ?? 0.0f; DeathEventListeningRadius = ini["Data", "DeathEventListeningRadius"].Float() ?? 1000.0f; LocalGoldSplitWithLastHitter = ini["Data", "LocalGoldSplitWithLastHitter"].Bool() ?? false; LocalGoldGivenOnDeath = ini["Data", "LocalGoldGivenOnDeath"].Float() ?? 0.0f; LocalExpGivenOnDeath = ini["Data", "LocalExpGivenOnDeath"].Float() ?? 0.0f; GlobalGoldGivenOnDeath = ini["Data", "GlobalGoldGivenOnDeath"].Float() ?? 0.0f; GlobalExpGivenOnDeath = ini["Data", "GlobalExpGivenOnDeath"].Float() ?? 0.0f; Significance = ini["Data", "Significance"].Float() ?? 0.0f; PerceptionBubbleRadius = ini["Data", "PerceptionBubbleRadius"].Float() ?? 1350.0f; HitFxScale = ini["Data", "HitFxScale"].Float() ?? 1.0f; OverrideCollisionHeight = ini["Data", "SelectionHeight"].Float() ?? -1.0f; OverrideCollisionRadius = ini["Data", "SelectionRadius"].Float() ?? -1.0f; PathfindingCollisionRadius = ini["Data", "PathfindingCollisionRadius"].Float() ?? -1.0f; GameplayCollisionRadius = ini["Data", "GameplayCollisionRadius"].Float() ?? 65.0f; OccludedUnitSelectableDistance = ini["Data", "OccludedUnitSelectableDistance"].Float() ?? 0.0f; PassiveData = new PassiveData( luaName: ini["Data", "Passive1LuaNam"].String() ?? "", range: ini["Data", "Passive1Range"].Float() ?? 0.0f ); var maxLevels = ini["Data", "MaxLevels"].IntList(5, 5, 5, 3); Spells = new Dictionary <SpellSlot, IBaseSpellData> { { SpellSlot.Q, new BaseSpellData ( name: ini["Data", "Spell1"].String() ?? "", maxLevelOverride: maxLevels[0], upgradeLevels: ini["Data", $"SpellsUpLevels1"].IntList(1, 3, 5, 7, 9, 99) ) }, { SpellSlot.W, new BaseSpellData ( name: ini["Data", "Spell2"].String() ?? "", maxLevelOverride: maxLevels[1], upgradeLevels: ini["Data", $"SpellsUpLevels2"].IntList(1, 3, 5, 7, 9, 99) ) }, { SpellSlot.E, new BaseSpellData ( name: ini["Data", "Spell3"].String() ?? "", maxLevelOverride: maxLevels[2], upgradeLevels: ini["Data", $"SpellsUpLevels3"].IntList(1, 3, 5, 7, 9, 99) ) }, { SpellSlot.R, new BaseSpellData ( name: ini["Data", "Spell4"].String() ?? "", maxLevelOverride: maxLevels[3], upgradeLevels: ini["Data", $"SpellsUpLevels4"].IntList(6, 11, 16, 99, 99, 99) ) }, }; ExtraSpells = Enumerable.Range(1, 16).Select((i) => new KeyValuePair <SpellSlot, string>((SpellSlot)Math.Pow(2, 5 + i), ini["Data", $"ExtraSpell{i}"].String() ?? "")).ToDictionary(x => x.Key, x => x.Value); CriticalAttack = ini["Data", "CriticalAttack"].String() ?? ""; var attacksData = new Dictionary <SpellSlot, IAttackData>(18); AttackData baseAttack; { var attackName = ini["Data", $"{_attackNames[0]}"].String() ?? $"{name}{_attackDefaults[0]}"; var attackProbability = ini["Data", $"{_attackNames[0]}_Probability"].Float() ?? 2.0f; var attackCastTime = ini["Data", "AttackCastTime"].Float() ?? 0.0f; var attackTotalTime = ini["Data", "AttackTotalTime"].Float() ?? 0.0f; if (attackCastTime > 0.0f && attackTotalTime > 0.0f) { baseAttack = new AttackData ( name: attackName, probability: attackProbability, totalTime: attackTotalTime, castTime: attackCastTime ); } else { var delayOffsetPercent = ini["Data", $"AttackDelayOffsetPercent"].Float() ?? 0.0f; var delayCastOffsetPercent = ini["Data", $"AttackDelayCastOffsetPercent"].Float() ?? 0.0f; var delayCastOffsetPercentAttackSpeedRatio = ini["Data", $"AttackDelayCastOffsetPercentAttackSpeedRatio"].Float() ?? 1.0f; baseAttack = new AttackData ( name: attackName, probability: attackProbability, delayOffsetPercent: delayOffsetPercent, delayCastOffsetPercent: delayCastOffsetPercent, delayCastOffsetPercentAttackSpeedRatio: delayCastOffsetPercentAttackSpeedRatio ); } } attacksData.Add(SpellSlot.BaseAttack, baseAttack); for (int i = 1; i < 18; i++) { AttackData attack; var attackName = ini["Data", $"{_attackNames[i]}"].String() ?? $"{name}{_attackDefaults[i]}"; var attackProbability = ini["Data", $"{_attackNames[i]}_Probability"].Float() ?? 2.0f; var attackCastTime = ini["Data", $"{_attackNames[i]}_AttackCastTime"].Float() ?? 0.0f; var attackTotalTime = ini["Data", $"{_attackNames[i]}_AttackTotalTime"].Float() ?? 0.0f; if (attackCastTime > 0.0f && attackTotalTime > 0.0f) { attack = new AttackData ( name: attackName, probability: attackProbability, totalTime: attackTotalTime, castTime: attackCastTime ); } else { var delayOffsetPercent = ini["Data", $"{_attackNames[i]}_AttackDelayOffsetPercent"].Float() ?? baseAttack.DelayOffsetPercent; var delayCastOffsetPercent = ini["Data", $"{_attackNames[i]}_AttackDelayCastOffsetPercent"].Float() ?? baseAttack.DelayCastOffsetPercent; var delayCastOffsetPercentAttackSpeedRatio = ini["Data", $"{_attackNames[i]}_AttackDelayCastOffsetPercentAttackSpeedRatio"].Float() ?? baseAttack.DelayCastOffsetPercentAttackSpeedRatio; attack = new AttackData ( name: attackName, probability: attackProbability, delayOffsetPercent: delayOffsetPercent, delayCastOffsetPercent: delayCastOffsetPercent, delayCastOffsetPercentAttackSpeedRatio: delayCastOffsetPercentAttackSpeedRatio ); } attacksData.Add((SpellSlot)(1L << (22 + i)), attack); } AttacksData = attacksData; }