diff --git a/.Lib9c.Tests/Action/HitHelperTest.cs b/.Lib9c.Tests/Action/HitHelperTest.cs deleted file mode 100644 index 1b53168ffe..0000000000 --- a/.Lib9c.Tests/Action/HitHelperTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Lib9c.Tests.Action -{ - using System; - using Nekoyume.Battle; - using Xunit; - - public class HitHelperTest - { - [Fact] - public void GetHitStep2() - { - // copy from previous logic - int GetHitStep2Legacy(int attackerHit, int defenderHit) - { - attackerHit = Math.Max(1, attackerHit); - defenderHit = Math.Max(1, defenderHit); - var additionalCorrection = (int)((attackerHit - defenderHit / 3m) / defenderHit * 100); - return Math.Min( - Math.Max(additionalCorrection, HitHelper.GetHitStep2AdditionalCorrectionMin), - HitHelper.GetHitStep2AdditionalCorrectionMax); - } - - for (int i = 0; i < 9; i++) - { - for (int j = 0; j < 9; j++) - { - var legacy = GetHitStep2Legacy(i, j); - var current = HitHelper.GetHitStep2(i, j); - Assert.True(legacy == current, $"{i}, {j}, {legacy}, {current}"); - } - } - } - } -} diff --git a/.Lib9c.Tests/Model/Skill/CombatTest.cs b/.Lib9c.Tests/Model/Skill/CombatTest.cs index 1622761013..fb8f8c05f7 100644 --- a/.Lib9c.Tests/Model/Skill/CombatTest.cs +++ b/.Lib9c.Tests/Model/Skill/CombatTest.cs @@ -75,7 +75,7 @@ public void CalculateDEFAndDamageReduction(int def, int drv, int drr, int enemyA var normalAttack = new NormalAttack(skillRow, 0, 100, default, StatType.NONE); var prevHP = _player.CurrentHP; - normalAttack.Use(_enemy, 1, new List(), false); + normalAttack.Use(_enemy, 1, new List()); var currentHP = _player.CurrentHP; var damage = prevHP - currentHP; @@ -100,41 +100,11 @@ public void CalculateCritDamage(int cdmg, int atk, int expectedDamage) var normalAttack = new NormalAttack(skillRow, 0, 100, default, StatType.NONE); var prevHP = _player.CurrentHP; - normalAttack.Use(_enemy, 1, new List(), false); + normalAttack.Use(_enemy, 1, new List()); var currentHP = _player.CurrentHP; var damage = prevHP - currentHP; Assert.Equal(expectedDamage, damage); } - - [Fact] - public void Thorn() - { - var prevHP = _enemy.CurrentHP; - var skill = _enemy.GiveThornDamage(1); - var currentHP = _enemy.CurrentHP; - // get 1dmg from thorn - Assert.Equal(prevHP - 1, currentHP); - Assert.Equal(prevHP, skill.Character.CurrentHP); - var skillInfo = Assert.Single(skill.SkillInfos); - Assert.Equal(currentHP, skillInfo.Target!.CurrentHP); - } - - [Fact] - public void Bleed() - { - var actionBuffSheet = _tableSheets.ActionBuffSheet; - var row = actionBuffSheet.Values.First(); - var bleed = Assert.IsType(BuffFactory.GetActionBuff(_enemy.Stats, row)); - var dmg = bleed.Power; - var prevHP = _player.CurrentHP; - var skill = bleed.GiveEffect(_player, 1); - var currentHP = _player.CurrentHP; - // get dmg from bleed - Assert.Equal(prevHP - dmg, currentHP); - Assert.Equal(prevHP, skill.Character.CurrentHP); - var skillInfo = Assert.Single(skill.SkillInfos); - Assert.Equal(currentHP, skillInfo.Target!.CurrentHP); - } } } diff --git a/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs b/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs index 42e53cb772..e6a8c843cd 100644 --- a/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs +++ b/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs @@ -26,10 +26,8 @@ public NormalAttackTest(ITestOutputHelper outputHelper) .CreateLogger(); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void Use(bool copyCharacter) + [Fact] + public void Use() { var sheets = TableSheetsImporter.ImportSheets(); var tableSheets = new TableSheets(sheets); @@ -67,8 +65,7 @@ public void Use(bool copyCharacter) StageSimulator.GetWaveRewards( random, tableSheets.StageSheet[1], - tableSheets.MaterialItemSheet), - copyCharacter + tableSheets.MaterialItemSheet) ); var player = new Player(avatarState, simulator); @@ -82,13 +79,13 @@ public void Use(bool copyCharacter) var battleStatusSkill = normalAttack.Use( player, 0, - new List(), - copyCharacter); + new List()); Assert.NotNull(battleStatusSkill); - Assert.Equal(!copyCharacter, battleStatusSkill.Character is null); - var skillInfo = Assert.Single(battleStatusSkill.SkillInfos); - Assert.Equal(enemy.Id, skillInfo.CharacterId); - Assert.Equal(!copyCharacter, skillInfo.Target is null); + Assert.Single(battleStatusSkill.SkillInfos); + + var skillInfo = battleStatusSkill.SkillInfos.FirstOrDefault(); + Assert.NotNull(skillInfo); + Assert.Equal(enemy.Id, skillInfo.Target.Id); } } } diff --git a/Lib9c/Action/HackAndSlash.cs b/Lib9c/Action/HackAndSlash.cs index 926ee68fcf..c25ee7faaf 100644 --- a/Lib9c/Action/HackAndSlash.cs +++ b/Lib9c/Action/HackAndSlash.cs @@ -439,14 +439,8 @@ public IAccountStateDelta Execute( } } - var stageWaveRow = sheets.GetSheet()[StageId]; - var enemySkillSheet = sheets.GetSheet(); - var costumeStatSheet = sheets.GetSheet(); - var stageCleared = !isNotClearedStage; - var starCount = 0; for (var i = 0; i < TotalPlayCount; i++) { - var rewards = StageSimulator.GetWaveRewards(random, stageRow, materialItemSheet); sw.Restart(); // First simulating will use Foods and Random Skills. // Remainder simulating will not use Foods. @@ -459,14 +453,13 @@ public IAccountStateDelta Execute( WorldId, StageId, stageRow, - stageWaveRow, - stageCleared, + sheets.GetSheet()[StageId], + avatarState.worldInformation.IsStageCleared(StageId), StageRewardExpHelper.GetExp(avatarState.level, StageId), simulatorSheets, - enemySkillSheet, - costumeStatSheet, - rewards, - false); + sheets.GetSheet(), + sheets.GetSheet(), + StageSimulator.GetWaveRewards(random, stageRow, materialItemSheet)); sw.Stop(); Log.Verbose("{AddressesHex}HAS Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed); @@ -478,17 +471,13 @@ public IAccountStateDelta Execute( sw.Restart(); if (simulator.Log.IsClear) { - if (!stageCleared) - { - avatarState.worldInformation.ClearStage( - WorldId, - StageId, - blockIndex, - worldSheet, - worldUnlockSheet - ); - stageCleared = true; - } + simulator.Player.worldInformation.ClearStage( + WorldId, + StageId, + blockIndex, + worldSheet, + worldUnlockSheet + ); sw.Stop(); Log.Verbose("{AddressesHex}HAS ClearStage: {Elapsed}", addressesHex, sw.Elapsed); } @@ -515,8 +504,9 @@ public IAccountStateDelta Execute( player.eventMapForBeforeV100310.Clear(); } - starCount += simulator.Log.clearedWaveNumber; avatarState.Update(simulator); + // Update CrystalRandomSkillState.Stars by clearedWaveNumber. (add) + skillState?.Update(simulator.Log.clearedWaveNumber, crystalStageBuffSheet); sw.Stop(); Log.Verbose( @@ -536,8 +526,6 @@ public IAccountStateDelta Execute( Log.Verbose("{AddressesHex}HAS loop Simulate: {Elapsed}, Count: {PlayCount}", addressesHex, sw.Elapsed, TotalPlayCount); - // Update CrystalRandomSkillState.Stars by clearedWaveNumber. (add) - skillState?.Update(starCount, crystalStageBuffSheet); sw.Restart(); avatarState.UpdateQuestRewards(materialItemSheet); avatarState.updatedAt = blockIndex; diff --git a/Lib9c/Battle/AttackCountHelper.cs b/Lib9c/Battle/AttackCountHelper.cs index 7fffe6ff73..89dc520f94 100644 --- a/Lib9c/Battle/AttackCountHelper.cs +++ b/Lib9c/Battle/AttackCountHelper.cs @@ -1,14 +1,68 @@ using System; using System.Collections.Generic; -using System.Diagnostics; namespace Nekoyume.Battle { public static class AttackCountHelper { + public struct Info + { + public decimal DamageMultiplier; + public decimal AdditionalCriticalChance; + } + public const int CountMaxLowerLimit = 2; public const int CountMaxUpperLimit = 5; + /// + /// key: attack count max + /// value: attack count, info + /// + public static readonly IReadOnlyDictionary> CachedInfo = + new Dictionary> + { + { + 1, new Dictionary + { + {1, new Info {DamageMultiplier = 1m, AdditionalCriticalChance = 0m}} + } + }, + { + 2, new Dictionary + { + {1, new Info {DamageMultiplier = 1m, AdditionalCriticalChance = 0m}}, + {2, new Info {DamageMultiplier = 2m, AdditionalCriticalChance = 25m}} + } + }, + { + 3, new Dictionary + { + {1, new Info {DamageMultiplier = 1m, AdditionalCriticalChance = 0m}}, + {2, new Info {DamageMultiplier = 2m, AdditionalCriticalChance = 10m}}, + {3, new Info {DamageMultiplier = 3m, AdditionalCriticalChance = 35m}} + } + }, + { + 4, new Dictionary + { + {1, new Info {DamageMultiplier = 1m, AdditionalCriticalChance = 0m}}, + {2, new Info {DamageMultiplier = 2m, AdditionalCriticalChance = 10m}}, + {3, new Info {DamageMultiplier = 3m, AdditionalCriticalChance = 20m}}, + {4, new Info {DamageMultiplier = 4m, AdditionalCriticalChance = 45m}} + } + }, + { + 5, new Dictionary + { + {1, new Info {DamageMultiplier = 1m, AdditionalCriticalChance = 0m}}, + {2, new Info {DamageMultiplier = 2m, AdditionalCriticalChance = 10m}}, + {3, new Info {DamageMultiplier = 3m, AdditionalCriticalChance = 20m}}, + {4, new Info {DamageMultiplier = 4m, AdditionalCriticalChance = 30m}}, + {5, new Info {DamageMultiplier = 5m, AdditionalCriticalChance = 55m}} + } + } + }; + public static int GetCountMax(int level) { if (level < 11) @@ -22,69 +76,40 @@ public static int GetCountMax(int level) : CountMaxUpperLimit; } - public static int GetDamageMultiplier(int attackCount, int attackCountMax) + public static decimal GetDamageMultiplier(int attackCount, int attackCountMax) { if (attackCount > attackCountMax) throw new ArgumentOutOfRangeException( $"{nameof(attackCount)}: {attackCount} / {nameof(attackCountMax)}: {attackCountMax}"); - if (attackCountMax <= 5) - { - return Math.Max(1, attackCount); - } + var info = GetInfo(attackCount, attackCountMax); + return info.DamageMultiplier; + } - throw new ArgumentOutOfRangeException(); + public static decimal GetAdditionalCriticalChance(int attackCount, int attackCountMax) + { + if (attackCount > attackCountMax) + throw new ArgumentOutOfRangeException( + $"{nameof(attackCount)}: {attackCount} / {nameof(attackCountMax)}: {attackCountMax}"); + + var info = GetInfo(attackCount, attackCountMax); + return info.AdditionalCriticalChance; } - public static int GetAdditionalCriticalChance(int attackCount, int attackCountMax) + private static Info GetInfo(int attackCount, int attackCountMax) { if (attackCount > attackCountMax) throw new ArgumentOutOfRangeException( $"{nameof(attackCount)}: {attackCount} / {nameof(attackCountMax)}: {attackCountMax}"); - switch (attackCount) - { - case 1: - return 0; - case 2: - switch (attackCountMax) - { - case 2: - return 25; - case 3: - case 4: - case 5: - return 10; - } - break; - case 3: - switch (attackCountMax) - { - case 3: - return 35; - case 4: - case 5: - return 20; - } - break; - case 4: - switch (attackCountMax) - { - case 4: - return 45; - case 5: - return 30; - } - break; - case 5: - switch (attackCountMax) - { - case 5: - return 55; - } - break; - } - throw new ArgumentOutOfRangeException(); + if (!CachedInfo.ContainsKey(attackCountMax)) + throw new ArgumentOutOfRangeException($"{nameof(attackCountMax)}: {attackCountMax}"); + + if (!CachedInfo[attackCountMax].ContainsKey(attackCount)) + throw new ArgumentOutOfRangeException( + $"{nameof(attackCountMax)}: {attackCountMax} / {nameof(attackCount)}: {attackCount}"); + + return CachedInfo[attackCountMax][attackCount]; } } } diff --git a/Lib9c/Battle/HitHelper.cs b/Lib9c/Battle/HitHelper.cs index 49cb4932fc..f2d9c2caaa 100644 --- a/Lib9c/Battle/HitHelper.cs +++ b/Lib9c/Battle/HitHelper.cs @@ -64,52 +64,101 @@ public static bool IsHitWithoutLevelCorrection( public static int GetHitStep1(int attackerLevel, int defenderLevel) { + var correction = 0; var diff = attackerLevel - defenderLevel; if (diff <= GetHitStep1LevelDiffMin) { - return GetHitStep1CorrectionMin; + correction = GetHitStep1CorrectionMin; } - - if (diff >= GetHitStep1LevelDiffMax) + else if (diff >= GetHitStep1LevelDiffMax) { - return GetHitStep1CorrectionMax; + correction = GetHitStep1CorrectionMax; } - - return diff switch + else { - -13 => -4, - -12 => -3, - -11 => -2, - -10 => -1, - -9 => 0, - -8 => 1, - -7 => 2, - -6 => 4, - -5 => 6, - -4 => 8, - -3 => 13, - -2 => 20, - -1 => 28, - 0 => 40, - 1 => 41, - 2 => 42, - 3 => 43, - 4 => 44, - 5 => 45, - 6 => 46, - 7 => 47, - 8 => 48, - 9 => 49, - _ => 0 - }; + switch (diff) + { + case -13: + correction = -4; + break; + case -12: + correction = -3; + break; + case -11: + correction = -2; + break; + case -10: + correction = -1; + break; + case -9: + correction = 0; + break; + case -8: + correction = 1; + break; + case -7: + correction = 2; + break; + case -6: + correction = 4; + break; + case -5: + correction = 6; + break; + case -4: + correction = 8; + break; + case -3: + correction = 13; + break; + case -2: + correction = 20; + break; + case -1: + correction = 28; + break; + case 0: + correction = 40; + break; + case 1: + correction = 41; + break; + case 2: + correction = 42; + break; + case 3: + correction = 43; + break; + case 4: + correction = 44; + break; + case 5: + correction = 45; + break; + case 6: + correction = 46; + break; + case 7: + correction = 47; + break; + case 8: + correction = 48; + break; + case 9: + correction = 49; + break; + } + } + + return correction; } public static int GetHitStep2(int attackerHit, int defenderHit) { attackerHit = Math.Max(1, attackerHit); defenderHit = Math.Max(1, defenderHit); - var additionalCorrection = (attackerHit * 10000 - defenderHit * 10000 / 3) / defenderHit / 100; + var additionalCorrection = (int) ((attackerHit - defenderHit / 3m) / defenderHit * 100); return Math.Min(Math.Max(additionalCorrection, GetHitStep2AdditionalCorrectionMin), GetHitStep2AdditionalCorrectionMax); } diff --git a/Lib9c/Battle/ISimulator.cs b/Lib9c/Battle/ISimulator.cs index 00f45d4eef..d68c70b410 100644 --- a/Lib9c/Battle/ISimulator.cs +++ b/Lib9c/Battle/ISimulator.cs @@ -14,6 +14,5 @@ public interface ISimulator IEnumerable Reward { get; } int WaveNumber { get; } int WaveTurn { get; } - bool LogEvent { get; } } } diff --git a/Lib9c/Battle/RaidBoss.cs b/Lib9c/Battle/RaidBoss.cs index ce8b9231dc..3ab518802f 100644 --- a/Lib9c/Battle/RaidBoss.cs +++ b/Lib9c/Battle/RaidBoss.cs @@ -104,8 +104,7 @@ protected override BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - Simulator.LogEvent + ) ); Simulator.Log.Add(usedSkill); @@ -146,17 +145,16 @@ public void Enrage() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - Simulator.LogEvent + ) ); Simulator.Log.Add(usedSkill); foreach (var info in usedSkill.SkillInfos) { - if (!info.IsDead) + if (!info.Target.IsDead) continue; - var target = Targets.FirstOrDefault(i => i.Id == info.CharacterId); + var target = Targets.FirstOrDefault(i => i.Id == info.Target.Id); target?.Die(); } } diff --git a/Lib9c/Battle/Simulator.cs b/Lib9c/Battle/Simulator.cs index 7d43a46bcd..70b4d69c62 100644 --- a/Lib9c/Battle/Simulator.cs +++ b/Lib9c/Battle/Simulator.cs @@ -33,14 +33,14 @@ public abstract class Simulator : ISimulator public int WaveNumber { get; protected set; } public int WaveTurn { get; set; } public abstract IEnumerable Reward { get; } - public bool LogEvent { get; protected set; } - protected Simulator(IRandom random, + protected Simulator( + IRandom random, AvatarState avatarState, List foods, - SimulatorSheetsV1 simulatorSheets, bool logEvent = true) : this(random, new Player(avatarState, simulatorSheets), foods, simulatorSheets) + SimulatorSheetsV1 simulatorSheets + ) : this(random, new Player(avatarState, simulatorSheets), foods, simulatorSheets) { - LogEvent = logEvent; } protected Simulator( diff --git a/Lib9c/Battle/StageSimulator.cs b/Lib9c/Battle/StageSimulator.cs index e01122b6b5..16b43b70b2 100644 --- a/Lib9c/Battle/StageSimulator.cs +++ b/Lib9c/Battle/StageSimulator.cs @@ -13,7 +13,6 @@ using Nekoyume.Model.Buff; using Nekoyume.TableData; using Priority_Queue; -using Skill = Nekoyume.Model.Skill.Skill; namespace Nekoyume.Battle { @@ -33,11 +32,12 @@ public class StageSimulator : Simulator, IStageSimulator private int TurnLimit { get; } public override IEnumerable Reward => _waveRewards; - public StageSimulator(IRandom random, + public StageSimulator( + IRandom random, AvatarState avatarState, List foods, List runeStates, - List skillsOnWaveStart, + List skillsOnWaveStart, int worldId, int stageId, StageSheet.Row stageRow, @@ -47,14 +47,12 @@ public StageSimulator(IRandom random, SimulatorSheets simulatorSheets, EnemySkillSheet enemySkillSheet, CostumeStatSheet costumeStatSheet, - List waveRewards, - bool logEvent = true) + List waveRewards) : base( random, avatarState, foods, - simulatorSheets, - logEvent) + simulatorSheets) { Player.SetCostumeStat(costumeStatSheet); if (runeStates != null) @@ -130,7 +128,8 @@ public Player Simulate() ActionBuffSheet ); - skill.Use(Player, 0, buffs, LogEvent); + var usedSkill = skill.Use(Player, 0, buffs); + Log.Add(usedSkill); } while (true) @@ -143,7 +142,7 @@ public Player Simulate() Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), LogEvent); + Player.GetExp((int)(Exp * 0.3m), true); } } else @@ -170,7 +169,7 @@ public Player Simulate() Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), LogEvent); + Player.GetExp((int)(Exp * 0.3m), true); } } else @@ -193,7 +192,7 @@ public Player Simulate() { if (Exp > 0) { - Player.GetExp(Exp, LogEvent); + Player.GetExp(Exp, true); } break; @@ -201,13 +200,10 @@ public Player Simulate() case 2: { ItemMap = Player.GetRewards(_waveRewards); - if (LogEvent) - { - var dropBox = new DropBox(null, _waveRewards); - Log.Add(dropBox); - var getReward = new GetReward(null, _waveRewards); - Log.Add(getReward); - } + var dropBox = new DropBox(null, _waveRewards); + Log.Add(dropBox); + var getReward = new GetReward(null, _waveRewards); + Log.Add(getReward); break; } default: diff --git a/Lib9c/Battle/StageSimulatorV1.cs b/Lib9c/Battle/StageSimulatorV1.cs index bafcaf03e7..66e386f255 100644 --- a/Lib9c/Battle/StageSimulatorV1.cs +++ b/Lib9c/Battle/StageSimulatorV1.cs @@ -301,7 +301,7 @@ CostumeStatSheet costumeStatSheet { Player.SetCostumeStat(costumeStatSheet); } - + public Player Simulate(int playCount) { Log.worldId = WorldId; @@ -331,7 +331,7 @@ public Player Simulate(int playCount) ActionBuffSheet ); - var usedSkill = skill.Use(Player, 0, buffs, LogEvent); + var usedSkill = skill.Use(Player, 0, buffs); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV2.cs b/Lib9c/Battle/StageSimulatorV2.cs index 08aed9dc75..12845f69ee 100644 --- a/Lib9c/Battle/StageSimulatorV2.cs +++ b/Lib9c/Battle/StageSimulatorV2.cs @@ -122,7 +122,7 @@ public Player Simulate() ActionBuffSheet ); - var usedSkill = skill.Use(Player, 0, buffs, LogEvent); + var usedSkill = skill.Use(Player, 0, buffs); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV3.cs b/Lib9c/Battle/StageSimulatorV3.cs index 5d47a62482..253327ea37 100644 --- a/Lib9c/Battle/StageSimulatorV3.cs +++ b/Lib9c/Battle/StageSimulatorV3.cs @@ -128,7 +128,7 @@ public Player Simulate() ActionBuffSheet ); - var usedSkill = skill.Use(Player, 0, buffs, LogEvent); + var usedSkill = skill.Use(Player, 0, buffs); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/Wave.cs b/Lib9c/Battle/Wave.cs index 99bd2faf12..a938356c14 100644 --- a/Lib9c/Battle/Wave.cs +++ b/Lib9c/Battle/Wave.cs @@ -25,12 +25,9 @@ public void Spawn(ISimulator simulator) enemy.InitAI(); } - if (simulator.LogEvent) - { - var enemies = _enemies.Select(enemy => new Enemy(enemy)).ToList(); - var spawnWave = new SpawnWave(null, simulator.WaveNumber, simulator.WaveTurn, enemies, HasBoss); - simulator.Log.Add(spawnWave); - } + var enemies = _enemies.Select(enemy => new Enemy(enemy)).ToList(); + var spawnWave = new SpawnWave(null, simulator.WaveNumber, simulator.WaveTurn, enemies, HasBoss); + simulator.Log.Add(spawnWave); } [Obsolete("Use Spawn")] diff --git a/Lib9c/Model/BattleStatus/Skill.cs b/Lib9c/Model/BattleStatus/Skill.cs index 48149d5a4d..3c7f3bcf29 100644 --- a/Lib9c/Model/BattleStatus/Skill.cs +++ b/Lib9c/Model/BattleStatus/Skill.cs @@ -12,27 +12,22 @@ public abstract class Skill : EventBase [Serializable] public class SkillInfo { - public readonly CharacterBase? Target; + public readonly CharacterBase Target; public readonly int Effect; public readonly bool Critical; public readonly SkillCategory SkillCategory; public readonly ElementalType ElementalType; public readonly SkillTargetType SkillTargetType; public readonly int WaveTurn; - public readonly int Thorn; - public readonly bool IsDead; - public readonly Guid CharacterId; - + public readonly Model.Buff.Buff? Buff; - public SkillInfo(Guid characterId, bool isDead, int thorn, int effect, bool critical, SkillCategory skillCategory, + public SkillInfo(CharacterBase character, int effect, bool critical, SkillCategory skillCategory, int waveTurn, ElementalType elementalType = ElementalType.Normal, - SkillTargetType targetType = SkillTargetType.Enemy, Model.Buff.Buff? buff = null, CharacterBase? target = null) + SkillTargetType targetType = SkillTargetType.Enemy, Model.Buff.Buff? buff = null) { - CharacterId = characterId; - IsDead = isDead; - Thorn = thorn; + Target = character; Effect = effect; Critical = critical; SkillCategory = skillCategory; @@ -40,7 +35,6 @@ public SkillInfo(Guid characterId, bool isDead, int thorn, int effect, bool crit SkillTargetType = targetType; Buff = buff; WaveTurn = waveTurn; - Target = target; } } @@ -48,7 +42,7 @@ public SkillInfo(Guid characterId, bool isDead, int thorn, int effect, bool crit public readonly IEnumerable SkillInfos; - + public readonly IEnumerable? BuffInfos; protected Skill(int skillId, CharacterBase character, IEnumerable skillInfos, diff --git a/Lib9c/Model/Buff/Bleed.cs b/Lib9c/Model/Buff/Bleed.cs index 800f9bd779..5011703514 100644 --- a/Lib9c/Model/Buff/Bleed.cs +++ b/Lib9c/Model/Buff/Bleed.cs @@ -41,10 +41,9 @@ public override BattleStatus.Skill GiveEffect( var damageInfos = new List { - // Copy new Character with damaged. - new BattleStatus.Skill.SkillInfo(affectedCharacter.Id, affectedCharacter.IsDead, affectedCharacter.Thorn, damage, false, + new BattleStatus.Skill.SkillInfo((CharacterBase)affectedCharacter.Clone(), damage, false, SkillCategory.Debuff, simulatorWaveTurn, RowData.ElementalType, - RowData.TargetType, target: (CharacterBase)affectedCharacter.Clone()) + RowData.TargetType) }; return new Model.BattleStatus.TickDamage( diff --git a/Lib9c/Model/Character/ArenaCharacter.cs b/Lib9c/Model/Character/ArenaCharacter.cs index d487336ea3..2ec210f0dd 100644 --- a/Lib9c/Model/Character/ArenaCharacter.cs +++ b/Lib9c/Model/Character/ArenaCharacter.cs @@ -819,7 +819,7 @@ public bool IsCritical(bool considerAttackCount = true) return CRI >= chance; var additionalCriticalChance = - AttackCountHelper.GetAdditionalCriticalChance(_attackCount, _attackCountMax); + (int) AttackCountHelper.GetAdditionalCriticalChance(_attackCount, _attackCountMax); return CRI + additionalCriticalChance >= chance; } @@ -850,7 +850,7 @@ public int GetDamage(int damage, bool considerAttackCount = true) _attackCount = 1; } - var damageMultiplier = AttackCountHelper.GetDamageMultiplier(_attackCount, _attackCountMax); + var damageMultiplier = (int) AttackCountHelper.GetDamageMultiplier(_attackCount, _attackCountMax); damage *= damageMultiplier; return damage; } diff --git a/Lib9c/Model/Character/CharacterBase.cs b/Lib9c/Model/Character/CharacterBase.cs index e60c085174..b338688b7c 100644 --- a/Lib9c/Model/Character/CharacterBase.cs +++ b/Lib9c/Model/Character/CharacterBase.cs @@ -225,7 +225,7 @@ private void ReduceDurationOfBuffs() pair.Value.RemainedDuration--; } } - + protected virtual void ReduceSkillCooldown() { Skills.ReduceCooldown(); @@ -240,7 +240,6 @@ private void ReduceSkillCooldownV1() protected virtual BattleStatus.Skill UseSkill() { var selectedSkill = Skills.Select(Simulator.Random); - bool log = Simulator.LogEvent; var usedSkill = selectedSkill.Use( this, Simulator.WaveTurn, @@ -251,8 +250,7 @@ protected virtual BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - log + ) ); if (!Simulator.SkillSheet.TryGetValue(selectedSkill.SkillRow.Id, out var sheetSkill)) @@ -261,10 +259,7 @@ protected virtual BattleStatus.Skill UseSkill() } Skills.SetCooldown(selectedSkill.SkillRow.Id, sheetSkill.Cooldown); - if (log) - { - Simulator.Log.Add(usedSkill); - } + Simulator.Log.Add(usedSkill); return usedSkill; } @@ -283,8 +278,7 @@ private BattleStatus.Skill UseSkillV1() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - Simulator.LogEvent + ) ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -307,8 +301,7 @@ private BattleStatus.Skill UseSkillV2() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - Simulator.LogEvent + ) ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -335,10 +328,7 @@ private void RemoveBuffs() return; Stats.SetBuffs(StatBuffs); - if (Simulator.LogEvent) - { - Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); - } + Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); } protected virtual void EndTurn() @@ -420,7 +410,7 @@ public bool IsCritical(bool considerAttackCount = true) return CRI >= chance; var additionalCriticalChance = - AttackCountHelper.GetAdditionalCriticalChance(AttackCount, AttackCountMax); + (int) AttackCountHelper.GetAdditionalCriticalChance(AttackCount, AttackCountMax); return CRI + additionalCriticalChance >= chance; } @@ -453,7 +443,7 @@ public int GetDamage(int damage, bool considerAttackCount = true) AttackCount = 1; } - var damageMultiplier = AttackCountHelper.GetDamageMultiplier(AttackCount, AttackCountMax); + var damageMultiplier = (int) AttackCountHelper.GetDamageMultiplier(AttackCount, AttackCountMax); damage *= damageMultiplier; #if TEST_LOG @@ -475,11 +465,8 @@ public void Die() protected virtual void OnDead() { - if (Simulator.LogEvent) - { - var dead = new Dead((CharacterBase) Clone()); - Simulator.Log.Add(dead); - } + var dead = new Dead((CharacterBase) Clone()); + Simulator.Log.Add(dead); } public void Heal(int heal) @@ -564,14 +551,10 @@ protected virtual void OnPreSkill() protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) { var bleeds = Buffs.Values.OfType().OrderBy(x => x.BuffInfo.Id); - bool log = Simulator.LogEvent; foreach (var bleed in bleeds) { var effect = bleed.GiveEffect(this, Simulator.WaveTurn); - if (log) - { - Simulator.Log.Add(effect); - } + Simulator.Log.Add(effect); } // Apply thorn damage if target has thorn @@ -583,13 +566,10 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) skillInfo.SkillCategory == SkillCategory.DoubleAttack || skillInfo.SkillCategory == SkillCategory.AreaAttack || skillInfo.SkillCategory == SkillCategory.BuffRemovalAttack; - if (isAttackSkill && skillInfo.Thorn > 0) + if (isAttackSkill && skillInfo.Target.Thorn > 0) { - var effect = GiveThornDamage(skillInfo.Thorn); - if (log) - { - Simulator.Log.Add(effect); - } + var effect = GiveThornDamage(skillInfo.Target.Thorn); + Simulator.Log.Add(effect); } } @@ -602,38 +582,31 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) FinishTargetIfKilled(usedSkill); } - internal BattleStatus.Skill GiveThornDamage(int targetThorn) + private BattleStatus.Skill GiveThornDamage(int targetThorn) { - bool log = Simulator.LogEvent; - // Copy not damaged character - var clone = log ? (CharacterBase)Clone() : null; + var clone = (CharacterBase)Clone(); // minimum 1 damage var thornDamage = Math.Max(1, targetThorn - DEF); CurrentHP -= thornDamage; - if (log) + var damageInfos = new List() { - // Copy new damaged character - var damageInfos = new List() - { - new BattleStatus.Skill.SkillInfo( - Id, - IsDead, - thornDamage, - thornDamage, - false, - SkillCategory.TickDamage, - Simulator.WaveTurn, - target: (CharacterBase)Clone()) - }; - var tickDamage = new TickDamage( - default, - clone, - damageInfos, - null); - return tickDamage; - } + new BattleStatus.Skill.SkillInfo( + (CharacterBase)Clone(), + thornDamage, + false, + SkillCategory.TickDamage, + Simulator.WaveTurn, + ElementalType.Normal, + SkillTargetType.Enemy) + }; + + var tickDamage = new TickDamage( + default, + clone, + damageInfos, + null); - return null; + return tickDamage; } private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) @@ -641,7 +614,7 @@ private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) var isFirst = true; foreach (var info in usedSkill.SkillInfos) { - if (!info.IsDead) + if (!info.Target.IsDead) { continue; } @@ -653,7 +626,7 @@ private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) } var target = Targets.FirstOrDefault(i => - i.Id == info.CharacterId); + i.Id == info.Target.Id); switch (target) { case Player player: @@ -682,12 +655,12 @@ private void FinishTargetIfKilled(BattleStatus.Skill usedSkill) var killedTargets = new List(); foreach (var info in usedSkill.SkillInfos) { - if (!info.IsDead) + if (!info.Target.IsDead) { continue; } - var target = Targets.FirstOrDefault(i => i.Id == info.CharacterId); + var target = Targets.FirstOrDefault(i => i.Id == info.Target.Id); if (!killedTargets.Contains(target)) { killedTargets.Add(target); diff --git a/Lib9c/Model/Character/Player.cs b/Lib9c/Model/Character/Player.cs index f66bda838a..44abc2ee4e 100644 --- a/Lib9c/Model/Character/Player.cs +++ b/Lib9c/Model/Character/Player.cs @@ -449,11 +449,8 @@ public CollectionMap GetRewards2(List items) public virtual void Spawn() { InitAI(); - if (Simulator.LogEvent) - { - var spawn = new SpawnPlayer((CharacterBase)Clone()); - Simulator.Log.Add(spawn); - } + var spawn = new SpawnPlayer((CharacterBase)Clone()); + Simulator.Log.Add(spawn); } [Obsolete("Use Spawn")] @@ -515,8 +512,6 @@ protected override BattleStatus.Skill UseSkill() return base.UseSkill(); } - bool log = Simulator.LogEvent; - var usedSkill = selectedSkill.Use( this, Simulator.WaveTurn, @@ -527,16 +522,12 @@ protected override BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ), - log + ) ); var cooldown = RuneSkillCooldownMap[selectedSkill.SkillRow.Id]; RuneSkills.SetCooldown(selectedSkill.SkillRow.Id, cooldown); - if (log) - { - Simulator.Log.Add(usedSkill); - } + Simulator.Log.Add(usedSkill); return usedSkill; } @@ -681,10 +672,7 @@ protected override void EndTurn() Simulator.TurnNumber++; Simulator.WaveTurn++; - if (Simulator.LogEvent) - { - Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); - } + Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); } } } diff --git a/Lib9c/Model/Quest/CollectQuest.cs b/Lib9c/Model/Quest/CollectQuest.cs index 7f0b550a6b..ed00acf407 100644 --- a/Lib9c/Model/Quest/CollectQuest.cs +++ b/Lib9c/Model/Quest/CollectQuest.cs @@ -14,7 +14,7 @@ public class CollectQuest : Quest public readonly int ItemId; - public CollectQuest(CollectQuestSheet.Row data, QuestReward reward) + public CollectQuest(CollectQuestSheet.Row data, QuestReward reward) : base(data, reward) { ItemId = data.ItemId; @@ -54,7 +54,11 @@ public void Update(CollectionMap itemMap) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("itemId", ItemId); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"itemId"] = (Integer)ItemId, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Quest/CombinationEquipmentQuest.cs b/Lib9c/Model/Quest/CombinationEquipmentQuest.cs index 6868333bb0..405840357b 100644 --- a/Lib9c/Model/Quest/CombinationEquipmentQuest.cs +++ b/Lib9c/Model/Quest/CombinationEquipmentQuest.cs @@ -58,9 +58,14 @@ public void Update(int recipeId) public override IValue Serialize() { - return ((Dictionary) base.Serialize()) - .Add("recipe_id", RecipeId.Serialize()) - .Add("stage_id", StageId.Serialize()); + var dict = new Dictionary + { + [(Text) "recipe_id"] = RecipeId.Serialize(), + [(Text) "stage_id"] = StageId.Serialize(), + }; +#pragma warning disable LAA1002 + return new Dictionary(dict.Union((Dictionary) base.Serialize())); +#pragma warning restore LAA1002 } } } diff --git a/Lib9c/Model/Quest/CombinationQuest.cs b/Lib9c/Model/Quest/CombinationQuest.cs index fbe9bbbc78..236e5a8ab5 100644 --- a/Lib9c/Model/Quest/CombinationQuest.cs +++ b/Lib9c/Model/Quest/CombinationQuest.cs @@ -16,7 +16,7 @@ public class CombinationQuest : Quest public override QuestType QuestType => QuestType.Craft; - public CombinationQuest(CombinationQuestSheet.Row data, QuestReward reward) + public CombinationQuest(CombinationQuestSheet.Row data, QuestReward reward) : base(data, reward) { ItemType = data.ItemType; @@ -58,8 +58,13 @@ public void Update(List items) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("itemType", (int) ItemType) - .Add("itemSubType", (int) ItemSubType); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"itemType"] = (Integer)(int)ItemType, + [(Text)"itemSubType"] = (Integer)(int)ItemSubType, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 + } } diff --git a/Lib9c/Model/Quest/GeneralQuest.cs b/Lib9c/Model/Quest/GeneralQuest.cs index f8f26999c3..466b532a9d 100644 --- a/Lib9c/Model/Quest/GeneralQuest.cs +++ b/Lib9c/Model/Quest/GeneralQuest.cs @@ -74,8 +74,12 @@ public void Update(CollectionMap eventMap) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("event", (int) Event); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"event"] = (Integer)(int)Event, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Quest/GoldQuest.cs b/Lib9c/Model/Quest/GoldQuest.cs index 890622a352..8bdba842d4 100644 --- a/Lib9c/Model/Quest/GoldQuest.cs +++ b/Lib9c/Model/Quest/GoldQuest.cs @@ -62,7 +62,12 @@ public void Update(FungibleAssetValue gold) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("type", (int) Type); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"type"] = (Integer)(int)Type, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 + } } diff --git a/Lib9c/Model/Quest/ItemEnhancementQuest.cs b/Lib9c/Model/Quest/ItemEnhancementQuest.cs index b93a56f240..926bc1cb2a 100644 --- a/Lib9c/Model/Quest/ItemEnhancementQuest.cs +++ b/Lib9c/Model/Quest/ItemEnhancementQuest.cs @@ -16,7 +16,7 @@ public class ItemEnhancementQuest : Quest public int Count => _count; public override float Progress => (float) _current / _count; - public ItemEnhancementQuest(ItemEnhancementQuestSheet.Row data, QuestReward reward) + public ItemEnhancementQuest(ItemEnhancementQuestSheet.Row data, QuestReward reward) : base(data, reward) { _count = data.Count; @@ -63,8 +63,13 @@ public void Update(Equipment equipment) protected override string TypeId => "itemEnhancementQuest"; public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("grade", Grade) - .Add("count", _count); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"grade"] = (Integer)Grade, + [(Text)"count"] = (Integer)_count, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 + } } diff --git a/Lib9c/Model/Quest/ItemGradeQuest.cs b/Lib9c/Model/Quest/ItemGradeQuest.cs index 5ad5d7c31a..e123f13b22 100644 --- a/Lib9c/Model/Quest/ItemGradeQuest.cs +++ b/Lib9c/Model/Quest/ItemGradeQuest.cs @@ -14,7 +14,7 @@ public class ItemGradeQuest : Quest { public readonly int Grade; public readonly List ItemIds = new List(); - public ItemGradeQuest(ItemGradeQuestSheet.Row data, QuestReward reward) + public ItemGradeQuest(ItemGradeQuestSheet.Row data, QuestReward reward) : base(data, reward) { Grade = data.Grade; @@ -62,9 +62,13 @@ public void Update(ItemUsable itemUsable) protected override string TypeId => "itemGradeQuest"; public override IValue Serialize() => - ((Dictionary)base.Serialize()) - .Add("grade", Grade.Serialize()) - .Add("itemIds", new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize()))); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"grade"] = Grade.Serialize(), + [(Text)"itemIds"] = new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize())), + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Quest/ItemTypeCollectQuest.cs b/Lib9c/Model/Quest/ItemTypeCollectQuest.cs index ca8a46acbe..64a8ed7d79 100644 --- a/Lib9c/Model/Quest/ItemTypeCollectQuest.cs +++ b/Lib9c/Model/Quest/ItemTypeCollectQuest.cs @@ -15,7 +15,7 @@ public class ItemTypeCollectQuest : Quest public readonly ItemType ItemType; public readonly List ItemIds = new List(); - public ItemTypeCollectQuest(ItemTypeCollectQuestSheet.Row data, QuestReward reward) + public ItemTypeCollectQuest(ItemTypeCollectQuestSheet.Row data, QuestReward reward) : base(data, reward) { ItemType = data.ItemType; @@ -64,9 +64,13 @@ public override string GetProgressText() => protected override string TypeId => "itemTypeCollectQuest"; public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("itemType", ItemType.Serialize()) - .Add("itemIds", new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize()))); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"itemType"] = ItemType.Serialize(), + [(Text)"itemIds"] = new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize())), + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Quest/MonsterQuest.cs b/Lib9c/Model/Quest/MonsterQuest.cs index 60b7818469..b053d2c2e1 100644 --- a/Lib9c/Model/Quest/MonsterQuest.cs +++ b/Lib9c/Model/Quest/MonsterQuest.cs @@ -12,7 +12,7 @@ public class MonsterQuest : Quest { public readonly int MonsterId; - public MonsterQuest(MonsterQuestSheet.Row data, QuestReward reward) + public MonsterQuest(MonsterQuestSheet.Row data, QuestReward reward) : base(data, reward) { MonsterId = data.MonsterId; @@ -54,7 +54,11 @@ public void Update(CollectionMap monsterMap) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("monsterId", MonsterId); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"monsterId"] = (Integer)MonsterId, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Quest/Quest.cs b/Lib9c/Model/Quest/Quest.cs index 2d30d98972..55c378ca02 100644 --- a/Lib9c/Model/Quest/Quest.cs +++ b/Lib9c/Model/Quest/Quest.cs @@ -82,14 +82,16 @@ protected Quest(Dictionary serialized) public abstract string GetProgressText(); public virtual IValue Serialize() => - Dictionary.Empty - .Add("typeId", (Text) TypeId) - .Add("complete", new Bencodex.Types.Boolean(Complete)) - .Add("goal", (Integer) Goal) - .Add("current", (Integer) _current) - .Add("id", (Integer) Id) - .Add("reward", Reward.Serialize()) - .Add("isPaidInAction", new Bencodex.Types.Boolean(IsPaidInAction)); + new Dictionary(new Dictionary + { + [(Text) "typeId"] = (Text) TypeId, + [(Text) "complete"] = new Bencodex.Types.Boolean(Complete), + [(Text) "goal"] = (Integer) Goal, + [(Text) "current"] = (Integer) _current, + [(Text) "id"] = (Integer) Id, + [(Text) "reward"] = Reward.Serialize(), + [(Text) "isPaidInAction"] = new Bencodex.Types.Boolean(IsPaidInAction), + }); public static Quest Deserialize(Dictionary serialized) { diff --git a/Lib9c/Model/Quest/TradeQuest.cs b/Lib9c/Model/Quest/TradeQuest.cs index 206697b9ca..acb5bc6323 100644 --- a/Lib9c/Model/Quest/TradeQuest.cs +++ b/Lib9c/Model/Quest/TradeQuest.cs @@ -14,7 +14,7 @@ public class TradeQuest : Quest public override QuestType QuestType => QuestType.Exchange; public readonly TradeType Type; - public TradeQuest(TradeQuestSheet.Row data, QuestReward reward) + public TradeQuest(TradeQuestSheet.Row data, QuestReward reward) : base(data, reward) { Type = data.Type; @@ -45,7 +45,11 @@ public override string GetProgressText() => protected override string TypeId => "tradeQuest"; public override IValue Serialize() => - ((Dictionary) base.Serialize()) - .Add("type", (int) Type); +#pragma warning disable LAA1002 + new Dictionary(new Dictionary + { + [(Text)"type"] = (Integer)(int)Type, + }.Union((Dictionary)base.Serialize())); +#pragma warning restore LAA1002 } } diff --git a/Lib9c/Model/Skill/AreaAttack.cs b/Lib9c/Model/Skill/AreaAttack.cs index d115d7fcec..c49774e492 100644 --- a/Lib9c/Model/Skill/AreaAttack.cs +++ b/Lib9c/Model/Skill/AreaAttack.cs @@ -17,12 +17,13 @@ public AreaAttack( { } - public override BattleStatus.Skill Use(CharacterBase caster, - int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + public override Model.BattleStatus.Skill Use( + CharacterBase caster, + int simulatorWaveTurn, + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; - var damage = ProcessDamage(caster, simulatorWaveTurn, copyCharacter: copyCharacter); + var clone = (CharacterBase) caster.Clone(); + var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); return new Model.BattleStatus.AreaAttack(SkillRow.Id, clone, damage, buff); diff --git a/Lib9c/Model/Skill/AttackSkill.cs b/Lib9c/Model/Skill/AttackSkill.cs index 6a2370d6ae..b5c392ab28 100644 --- a/Lib9c/Model/Skill/AttackSkill.cs +++ b/Lib9c/Model/Skill/AttackSkill.cs @@ -27,10 +27,9 @@ protected AttackSkill( /// /// /// - /// /// protected IEnumerable ProcessDamage(CharacterBase caster, int simulatorWaveTurn, - bool isNormalAttack = false, bool copyCharacter = true) + bool isNormalAttack = false) { var infos = new List(); var targets = SkillRow.SkillTargetType.GetTarget(caster).ToList(); @@ -87,10 +86,9 @@ protected AttackSkill( target.CurrentHP -= damage; } - var clone = copyCharacter ? (CharacterBase) target.Clone() : null; - infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, damage, isCritical, + infos.Add(new BattleStatus.Skill.SkillInfo((CharacterBase) target.Clone(), damage, isCritical, SkillRow.SkillCategory, simulatorWaveTurn, SkillRow.ElementalType, - SkillRow.SkillTargetType, target: clone)); + SkillRow.SkillTargetType)); } } diff --git a/Lib9c/Model/Skill/BlowAttack.cs b/Lib9c/Model/Skill/BlowAttack.cs index 854380f93d..6d0eb29ba8 100644 --- a/Lib9c/Model/Skill/BlowAttack.cs +++ b/Lib9c/Model/Skill/BlowAttack.cs @@ -17,12 +17,13 @@ public BlowAttack( { } - public override BattleStatus.Skill Use(CharacterBase caster, + public override BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; - var damage = ProcessDamage(caster, simulatorWaveTurn, copyCharacter: copyCharacter); + var clone = (CharacterBase) caster.Clone(); + var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); return new Model.BattleStatus.BlowAttack(SkillRow.Id, clone, damage, buff); diff --git a/Lib9c/Model/Skill/BuffRemovalAttack.cs b/Lib9c/Model/Skill/BuffRemovalAttack.cs index f770ad95fc..be103e777d 100644 --- a/Lib9c/Model/Skill/BuffRemovalAttack.cs +++ b/Lib9c/Model/Skill/BuffRemovalAttack.cs @@ -17,12 +17,13 @@ public BuffRemovalAttack( { } - public override BattleStatus.Skill Use(CharacterBase caster, + public override BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; - var damage = ProcessDamage(caster, simulatorWaveTurn, copyCharacter: copyCharacter); + var clone = (CharacterBase) caster.Clone(); + var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); var targets = SkillRow.SkillTargetType.GetTarget(caster); foreach (var target in targets) diff --git a/Lib9c/Model/Skill/BuffSkill.cs b/Lib9c/Model/Skill/BuffSkill.cs index 674ad3239d..a6d61f8c0d 100644 --- a/Lib9c/Model/Skill/BuffSkill.cs +++ b/Lib9c/Model/Skill/BuffSkill.cs @@ -18,9 +18,9 @@ public BuffSkill( } public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; + var clone = (CharacterBase) caster.Clone(); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); return new BattleStatus.Buff(SkillRow.Id, clone, buff); diff --git a/Lib9c/Model/Skill/DoubleAttack.cs b/Lib9c/Model/Skill/DoubleAttack.cs index cab0ff6439..35f0038128 100644 --- a/Lib9c/Model/Skill/DoubleAttack.cs +++ b/Lib9c/Model/Skill/DoubleAttack.cs @@ -17,12 +17,13 @@ public DoubleAttack( { } - public override BattleStatus.Skill Use(CharacterBase caster, + public override BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; - var damage = ProcessDamage(caster, simulatorWaveTurn, copyCharacter: copyCharacter); + var clone = (CharacterBase) caster.Clone(); + var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); return new Model.BattleStatus.DoubleAttack(SkillRow.Id, clone, damage, buff); diff --git a/Lib9c/Model/Skill/HealSkill.cs b/Lib9c/Model/Skill/HealSkill.cs index 17c87aabe2..f7bbd5cf4b 100644 --- a/Lib9c/Model/Skill/HealSkill.cs +++ b/Lib9c/Model/Skill/HealSkill.cs @@ -17,14 +17,15 @@ public HealSkill( { } - public override BattleStatus.Skill Use(CharacterBase caster, + public override BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; + var clone = (CharacterBase) caster.Clone(); var heal = ProcessHeal(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); - + return new BattleStatus.HealSkill(SkillRow.Id, clone, heal, buff); } @@ -41,8 +42,8 @@ public override BattleStatus.Skill Use(CharacterBase caster, foreach (var target in SkillRow.SkillTargetType.GetTarget(caster)) { target.Heal(healPoint); - infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, healPoint, caster.IsCritical(false), - SkillRow.SkillCategory, simulatorWaveTurn, target: target)); + infos.Add(new BattleStatus.Skill.SkillInfo((CharacterBase)target.Clone(), healPoint, caster.IsCritical(false), + SkillRow.SkillCategory, simulatorWaveTurn)); } return infos; diff --git a/Lib9c/Model/Skill/NormalAttack.cs b/Lib9c/Model/Skill/NormalAttack.cs index e50205ba7d..96facc11c9 100644 --- a/Lib9c/Model/Skill/NormalAttack.cs +++ b/Lib9c/Model/Skill/NormalAttack.cs @@ -17,12 +17,13 @@ public NormalAttack( { } - public override BattleStatus.Skill Use(CharacterBase caster, + public override Model.BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter) + IEnumerable buffs) { - var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; - var damage = ProcessDamage(caster, simulatorWaveTurn, true, copyCharacter); + var clone = (CharacterBase) caster.Clone(); + var damage = ProcessDamage(caster, simulatorWaveTurn, true); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); return new Model.BattleStatus.NormalAttack(SkillRow.Id, clone, damage, buff); diff --git a/Lib9c/Model/Skill/Skill.cs b/Lib9c/Model/Skill/Skill.cs index f75297fd7e..6985aa7e57 100644 --- a/Lib9c/Model/Skill/Skill.cs +++ b/Lib9c/Model/Skill/Skill.cs @@ -36,9 +36,11 @@ protected Skill( ReferencedStatType = referencedStatType; } - public abstract BattleStatus.Skill Use(CharacterBase caster, + public abstract BattleStatus.Skill Use( + CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool copyCharacter); + IEnumerable buffs + ); protected bool Equals(Skill other) { @@ -81,9 +83,9 @@ public override int GetHashCode() foreach (var target in targets.Where(target => target.GetChance(buff.BuffInfo.Chance))) { target.AddBuff(buff); - infos.Add(new Model.BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, 0, false, + infos.Add(new Model.BattleStatus.Skill.SkillInfo((CharacterBase) target.Clone(), 0, false, SkillRow.SkillCategory, simulatorWaveTurn, ElementalType.Normal, SkillRow.SkillTargetType, - buff, target)); + buff)); } } diff --git a/Lib9c/Model/State/RedeemCodeState.cs b/Lib9c/Model/State/RedeemCodeState.cs index 7554b36461..d9b761faa4 100644 --- a/Lib9c/Model/State/RedeemCodeState.cs +++ b/Lib9c/Model/State/RedeemCodeState.cs @@ -79,12 +79,14 @@ public RedeemCodeState(Dictionary rewardMap) } public override IValue Serialize() => - ((Dictionary) base.Serialize()) #pragma warning disable LAA1002 - .Add("map", new Dictionary(_map.Select(kv => new KeyValuePair( - kv.Key, - kv.Value.Serialize() - )))); + new Dictionary(new Dictionary + { + [(Text) "map"] = new Dictionary(_map.Select(kv => new KeyValuePair( + kv.Key, + kv.Value.Serialize() + ))) + }.Union((Dictionary) base.Serialize())); #pragma warning restore LAA1002 public int Redeem(string code, Address userAddress)