From 366507d69f4d64f05ad190c07323e2d19eec5159 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Thu, 6 Jul 2023 20:22:21 +0900 Subject: [PATCH 1/8] Optimize serialize --- Lib9c/Model/Quest/CollectQuest.cs | 10 +++------- Lib9c/Model/Quest/CombinationEquipmentQuest.cs | 11 +++-------- Lib9c/Model/Quest/CombinationQuest.cs | 13 ++++--------- Lib9c/Model/Quest/GeneralQuest.cs | 8 ++------ Lib9c/Model/Quest/GoldQuest.cs | 9 ++------- Lib9c/Model/Quest/ItemEnhancementQuest.cs | 13 ++++--------- Lib9c/Model/Quest/ItemGradeQuest.cs | 12 ++++-------- Lib9c/Model/Quest/ItemTypeCollectQuest.cs | 12 ++++-------- Lib9c/Model/Quest/MonsterQuest.cs | 10 +++------- Lib9c/Model/Quest/Quest.cs | 18 ++++++++---------- Lib9c/Model/Quest/TradeQuest.cs | 10 +++------- Lib9c/Model/State/RedeemCodeState.cs | 12 +++++------- 12 files changed, 45 insertions(+), 93 deletions(-) diff --git a/Lib9c/Model/Quest/CollectQuest.cs b/Lib9c/Model/Quest/CollectQuest.cs index ed00acf407..7f0b550a6b 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,11 +54,7 @@ public void Update(CollectionMap itemMap) } public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"itemId"] = (Integer)ItemId, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 + ((Dictionary) base.Serialize()) + .Add("itemId", ItemId); } } diff --git a/Lib9c/Model/Quest/CombinationEquipmentQuest.cs b/Lib9c/Model/Quest/CombinationEquipmentQuest.cs index 405840357b..6868333bb0 100644 --- a/Lib9c/Model/Quest/CombinationEquipmentQuest.cs +++ b/Lib9c/Model/Quest/CombinationEquipmentQuest.cs @@ -58,14 +58,9 @@ public void Update(int recipeId) public override IValue 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 + return ((Dictionary) base.Serialize()) + .Add("recipe_id", RecipeId.Serialize()) + .Add("stage_id", StageId.Serialize()); } } } diff --git a/Lib9c/Model/Quest/CombinationQuest.cs b/Lib9c/Model/Quest/CombinationQuest.cs index 236e5a8ab5..fbe9bbbc78 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,13 +58,8 @@ public void Update(List items) } public override IValue Serialize() => -#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 - + ((Dictionary) base.Serialize()) + .Add("itemType", (int) ItemType) + .Add("itemSubType", (int) ItemSubType); } } diff --git a/Lib9c/Model/Quest/GeneralQuest.cs b/Lib9c/Model/Quest/GeneralQuest.cs index 466b532a9d..f8f26999c3 100644 --- a/Lib9c/Model/Quest/GeneralQuest.cs +++ b/Lib9c/Model/Quest/GeneralQuest.cs @@ -74,12 +74,8 @@ public void Update(CollectionMap eventMap) } public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"event"] = (Integer)(int)Event, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 + ((Dictionary) base.Serialize()) + .Add("event", (int) Event); } } diff --git a/Lib9c/Model/Quest/GoldQuest.cs b/Lib9c/Model/Quest/GoldQuest.cs index 8bdba842d4..890622a352 100644 --- a/Lib9c/Model/Quest/GoldQuest.cs +++ b/Lib9c/Model/Quest/GoldQuest.cs @@ -62,12 +62,7 @@ public void Update(FungibleAssetValue gold) } public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"type"] = (Integer)(int)Type, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 - + ((Dictionary) base.Serialize()) + .Add("type", (int) Type); } } diff --git a/Lib9c/Model/Quest/ItemEnhancementQuest.cs b/Lib9c/Model/Quest/ItemEnhancementQuest.cs index 926bc1cb2a..b93a56f240 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,13 +63,8 @@ public void Update(Equipment equipment) protected override string TypeId => "itemEnhancementQuest"; public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"grade"] = (Integer)Grade, - [(Text)"count"] = (Integer)_count, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 - + ((Dictionary) base.Serialize()) + .Add("grade", Grade) + .Add("count", _count); } } diff --git a/Lib9c/Model/Quest/ItemGradeQuest.cs b/Lib9c/Model/Quest/ItemGradeQuest.cs index e123f13b22..5ad5d7c31a 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,13 +62,9 @@ public void Update(ItemUsable itemUsable) protected override string TypeId => "itemGradeQuest"; public override IValue 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 + ((Dictionary)base.Serialize()) + .Add("grade", Grade.Serialize()) + .Add("itemIds", new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize()))); } } diff --git a/Lib9c/Model/Quest/ItemTypeCollectQuest.cs b/Lib9c/Model/Quest/ItemTypeCollectQuest.cs index 64a8ed7d79..ca8a46acbe 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,13 +64,9 @@ public override string GetProgressText() => protected override string TypeId => "itemTypeCollectQuest"; public override IValue 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 + ((Dictionary) base.Serialize()) + .Add("itemType", ItemType.Serialize()) + .Add("itemIds", new List(ItemIds.OrderBy(i => i).Select(i => i.Serialize()))); } } diff --git a/Lib9c/Model/Quest/MonsterQuest.cs b/Lib9c/Model/Quest/MonsterQuest.cs index b053d2c2e1..60b7818469 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,11 +54,7 @@ public void Update(CollectionMap monsterMap) } public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"monsterId"] = (Integer)MonsterId, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 + ((Dictionary) base.Serialize()) + .Add("monsterId", MonsterId); } } diff --git a/Lib9c/Model/Quest/Quest.cs b/Lib9c/Model/Quest/Quest.cs index 55c378ca02..2d30d98972 100644 --- a/Lib9c/Model/Quest/Quest.cs +++ b/Lib9c/Model/Quest/Quest.cs @@ -82,16 +82,14 @@ protected Quest(Dictionary serialized) public abstract string GetProgressText(); public virtual IValue Serialize() => - 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), - }); + 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)); public static Quest Deserialize(Dictionary serialized) { diff --git a/Lib9c/Model/Quest/TradeQuest.cs b/Lib9c/Model/Quest/TradeQuest.cs index acb5bc6323..206697b9ca 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,11 +45,7 @@ public override string GetProgressText() => protected override string TypeId => "tradeQuest"; public override IValue Serialize() => -#pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text)"type"] = (Integer)(int)Type, - }.Union((Dictionary)base.Serialize())); -#pragma warning restore LAA1002 + ((Dictionary) base.Serialize()) + .Add("type", (int) Type); } } diff --git a/Lib9c/Model/State/RedeemCodeState.cs b/Lib9c/Model/State/RedeemCodeState.cs index d9b761faa4..7554b36461 100644 --- a/Lib9c/Model/State/RedeemCodeState.cs +++ b/Lib9c/Model/State/RedeemCodeState.cs @@ -79,14 +79,12 @@ public RedeemCodeState(Dictionary rewardMap) } public override IValue Serialize() => + ((Dictionary) base.Serialize()) #pragma warning disable LAA1002 - new Dictionary(new Dictionary - { - [(Text) "map"] = new Dictionary(_map.Select(kv => new KeyValuePair( - kv.Key, - kv.Value.Serialize() - ))) - }.Union((Dictionary) base.Serialize())); + .Add("map", new Dictionary(_map.Select(kv => new KeyValuePair( + kv.Key, + kv.Value.Serialize() + )))); #pragma warning restore LAA1002 public int Redeem(string code, Address userAddress) From 62cc93d06c214c071f1a99bb4d86c70a0b317a53 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Thu, 6 Jul 2023 20:22:59 +0900 Subject: [PATCH 2/8] Disable log --- Lib9c/Battle/StageSimulator.cs | 22 ++++++++++++---------- Lib9c/Battle/Wave.cs | 6 +++--- Lib9c/Model/Character/CharacterBase.cs | 14 +++++++------- Lib9c/Model/Character/Player.cs | 8 ++++---- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Lib9c/Battle/StageSimulator.cs b/Lib9c/Battle/StageSimulator.cs index 16b43b70b2..ec93e0a26a 100644 --- a/Lib9c/Battle/StageSimulator.cs +++ b/Lib9c/Battle/StageSimulator.cs @@ -99,7 +99,7 @@ public static List GetWaveRewards( return waveRewards; } - public Player Simulate() + public Player Simulate(bool log = false) { Log.worldId = WorldId; Log.stageId = StageId; @@ -128,8 +128,7 @@ public Player Simulate() ActionBuffSheet ); - var usedSkill = skill.Use(Player, 0, buffs); - Log.Add(usedSkill); + skill.Use(Player, 0, buffs); } while (true) @@ -142,7 +141,7 @@ public Player Simulate() Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), true); + Player.GetExp((int)(Exp * 0.3m), log); } } else @@ -169,7 +168,7 @@ public Player Simulate() Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), true); + Player.GetExp((int)(Exp * 0.3m), log); } } else @@ -192,7 +191,7 @@ public Player Simulate() { if (Exp > 0) { - Player.GetExp(Exp, true); + Player.GetExp(Exp, log); } break; @@ -200,10 +199,13 @@ public Player Simulate() case 2: { ItemMap = Player.GetRewards(_waveRewards); - var dropBox = new DropBox(null, _waveRewards); - Log.Add(dropBox); - var getReward = new GetReward(null, _waveRewards); - Log.Add(getReward); + if (log) + { + 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/Wave.cs b/Lib9c/Battle/Wave.cs index a938356c14..615051057b 100644 --- a/Lib9c/Battle/Wave.cs +++ b/Lib9c/Battle/Wave.cs @@ -25,9 +25,9 @@ public void Spawn(ISimulator simulator) enemy.InitAI(); } - 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/Character/CharacterBase.cs b/Lib9c/Model/Character/CharacterBase.cs index b338688b7c..abbf0808c5 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(); @@ -259,7 +259,7 @@ protected virtual BattleStatus.Skill UseSkill() } Skills.SetCooldown(selectedSkill.SkillRow.Id, sheetSkill.Cooldown); - Simulator.Log.Add(usedSkill); + // Simulator.Log.Add(usedSkill); return usedSkill; } @@ -328,7 +328,7 @@ private void RemoveBuffs() return; Stats.SetBuffs(StatBuffs); - Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); + // Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); } protected virtual void EndTurn() @@ -465,8 +465,8 @@ public void Die() protected virtual void OnDead() { - 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) @@ -554,7 +554,7 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) foreach (var bleed in bleeds) { var effect = bleed.GiveEffect(this, Simulator.WaveTurn); - Simulator.Log.Add(effect); + // Simulator.Log.Add(effect); } // Apply thorn damage if target has thorn @@ -569,7 +569,7 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) if (isAttackSkill && skillInfo.Target.Thorn > 0) { var effect = GiveThornDamage(skillInfo.Target.Thorn); - Simulator.Log.Add(effect); + // Simulator.Log.Add(effect); } } diff --git a/Lib9c/Model/Character/Player.cs b/Lib9c/Model/Character/Player.cs index 44abc2ee4e..94eab4af5e 100644 --- a/Lib9c/Model/Character/Player.cs +++ b/Lib9c/Model/Character/Player.cs @@ -449,8 +449,8 @@ public CollectionMap GetRewards2(List items) public virtual void Spawn() { InitAI(); - var spawn = new SpawnPlayer((CharacterBase)Clone()); - Simulator.Log.Add(spawn); + // var spawn = new SpawnPlayer((CharacterBase)Clone()); + // Simulator.Log.Add(spawn); } [Obsolete("Use Spawn")] @@ -527,7 +527,7 @@ protected override BattleStatus.Skill UseSkill() var cooldown = RuneSkillCooldownMap[selectedSkill.SkillRow.Id]; RuneSkills.SetCooldown(selectedSkill.SkillRow.Id, cooldown); - Simulator.Log.Add(usedSkill); + // Simulator.Log.Add(usedSkill); return usedSkill; } @@ -672,7 +672,7 @@ protected override void EndTurn() Simulator.TurnNumber++; Simulator.WaveTurn++; - Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); + // Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); } } } From 0bb4c649cd777545c5aeac2534a0dc0b1899392e Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Thu, 6 Jul 2023 20:27:09 +0900 Subject: [PATCH 3/8] Optimize loop --- Lib9c/Action/HackAndSlash.cs | 39 +++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/Lib9c/Action/HackAndSlash.cs b/Lib9c/Action/HackAndSlash.cs index 58e5dd762e..08e8ed1f6b 100644 --- a/Lib9c/Action/HackAndSlash.cs +++ b/Lib9c/Action/HackAndSlash.cs @@ -439,8 +439,14 @@ 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. @@ -453,13 +459,13 @@ public IAccountStateDelta Execute( WorldId, StageId, stageRow, - sheets.GetSheet()[StageId], - avatarState.worldInformation.IsStageCleared(StageId), + stageWaveRow, + stageCleared, StageRewardExpHelper.GetExp(avatarState.level, StageId), simulatorSheets, - sheets.GetSheet(), - sheets.GetSheet(), - StageSimulator.GetWaveRewards(random, stageRow, materialItemSheet)); + enemySkillSheet, + costumeStatSheet, + rewards); sw.Stop(); Log.Verbose("{AddressesHex}HAS Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed); @@ -471,13 +477,17 @@ public IAccountStateDelta Execute( sw.Restart(); if (simulator.Log.IsClear) { - simulator.Player.worldInformation.ClearStage( - WorldId, - StageId, - blockIndex, - worldSheet, - worldUnlockSheet - ); + if (!stageCleared) + { + avatarState.worldInformation.ClearStage( + WorldId, + StageId, + blockIndex, + worldSheet, + worldUnlockSheet + ); + stageCleared = true; + } sw.Stop(); Log.Verbose("{AddressesHex}HAS ClearStage: {Elapsed}", addressesHex, sw.Elapsed); } @@ -504,9 +514,8 @@ 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( @@ -526,6 +535,8 @@ 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; From c6beb70868dada10a45ed678592a59c55683fb93 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Wed, 12 Jul 2023 16:12:42 +0900 Subject: [PATCH 4/8] Skip clone CharacterBase --- Lib9c/Battle/RaidBoss.cs | 10 +++-- Lib9c/Battle/StageSimulator.cs | 2 +- Lib9c/Battle/StageSimulatorV1.cs | 4 +- Lib9c/Battle/StageSimulatorV2.cs | 2 +- Lib9c/Battle/StageSimulatorV3.cs | 2 +- Lib9c/Model/BattleStatus/Skill.cs | 14 ++++--- Lib9c/Model/Buff/Bleed.cs | 2 +- Lib9c/Model/Character/CharacterBase.cs | 55 ++++++++++++-------------- Lib9c/Model/Character/Player.cs | 3 +- Lib9c/Model/Skill/AreaAttack.cs | 9 ++--- Lib9c/Model/Skill/AttackSkill.cs | 5 ++- Lib9c/Model/Skill/BlowAttack.cs | 7 ++-- Lib9c/Model/Skill/BuffRemovalAttack.cs | 7 ++-- Lib9c/Model/Skill/BuffSkill.cs | 4 +- Lib9c/Model/Skill/DoubleAttack.cs | 7 ++-- Lib9c/Model/Skill/HealSkill.cs | 11 +++--- Lib9c/Model/Skill/NormalAttack.cs | 7 ++-- Lib9c/Model/Skill/Skill.cs | 8 ++-- 18 files changed, 77 insertions(+), 82 deletions(-) diff --git a/Lib9c/Battle/RaidBoss.cs b/Lib9c/Battle/RaidBoss.cs index 3ab518802f..dca8e7657f 100644 --- a/Lib9c/Battle/RaidBoss.cs +++ b/Lib9c/Battle/RaidBoss.cs @@ -104,7 +104,8 @@ protected override BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); Simulator.Log.Add(usedSkill); @@ -145,16 +146,17 @@ public void Enrage() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); Simulator.Log.Add(usedSkill); foreach (var info in usedSkill.SkillInfos) { - if (!info.Target.IsDead) + if (!info.IsDead) continue; - var target = Targets.FirstOrDefault(i => i.Id == info.Target.Id); + var target = Targets.FirstOrDefault(i => i.Id == info.Id); target?.Die(); } } diff --git a/Lib9c/Battle/StageSimulator.cs b/Lib9c/Battle/StageSimulator.cs index ec93e0a26a..6726e10c35 100644 --- a/Lib9c/Battle/StageSimulator.cs +++ b/Lib9c/Battle/StageSimulator.cs @@ -128,7 +128,7 @@ public Player Simulate(bool log = false) ActionBuffSheet ); - skill.Use(Player, 0, buffs); + skill.Use(Player, 0, buffs, log); } while (true) diff --git a/Lib9c/Battle/StageSimulatorV1.cs b/Lib9c/Battle/StageSimulatorV1.cs index 66e386f255..1ad0e2cbc2 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); + var usedSkill = skill.Use(Player, 0, buffs, false); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV2.cs b/Lib9c/Battle/StageSimulatorV2.cs index 12845f69ee..28a2511ff9 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); + var usedSkill = skill.Use(Player, 0, buffs, false); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV3.cs b/Lib9c/Battle/StageSimulatorV3.cs index 253327ea37..98ec1bcfc7 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); + var usedSkill = skill.Use(Player, 0, buffs, false); Log.Add(usedSkill); } diff --git a/Lib9c/Model/BattleStatus/Skill.cs b/Lib9c/Model/BattleStatus/Skill.cs index 3c7f3bcf29..930ce6442e 100644 --- a/Lib9c/Model/BattleStatus/Skill.cs +++ b/Lib9c/Model/BattleStatus/Skill.cs @@ -12,22 +12,26 @@ public abstract class Skill : EventBase [Serializable] public class SkillInfo { - 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 Id; + - public readonly Model.Buff.Buff? Buff; - public SkillInfo(CharacterBase character, int effect, bool critical, SkillCategory skillCategory, + public SkillInfo(Guid id, bool isDead, int thorn, int effect, bool critical, SkillCategory skillCategory, int waveTurn, ElementalType elementalType = ElementalType.Normal, SkillTargetType targetType = SkillTargetType.Enemy, Model.Buff.Buff? buff = null) { - Target = character; + Id = id; + IsDead = isDead; + Thorn = thorn; Effect = effect; Critical = critical; SkillCategory = skillCategory; @@ -42,7 +46,7 @@ public SkillInfo(CharacterBase character, int effect, bool critical, SkillCatego 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 5011703514..3589acec71 100644 --- a/Lib9c/Model/Buff/Bleed.cs +++ b/Lib9c/Model/Buff/Bleed.cs @@ -41,7 +41,7 @@ public override BattleStatus.Skill GiveEffect( var damageInfos = new List { - new BattleStatus.Skill.SkillInfo((CharacterBase)affectedCharacter.Clone(), damage, false, + new BattleStatus.Skill.SkillInfo(affectedCharacter.Id, affectedCharacter.IsDead, affectedCharacter.Thorn, damage, false, SkillCategory.Debuff, simulatorWaveTurn, RowData.ElementalType, RowData.TargetType) }; diff --git a/Lib9c/Model/Character/CharacterBase.cs b/Lib9c/Model/Character/CharacterBase.cs index abbf0808c5..014e946380 100644 --- a/Lib9c/Model/Character/CharacterBase.cs +++ b/Lib9c/Model/Character/CharacterBase.cs @@ -250,7 +250,8 @@ protected virtual BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); if (!Simulator.SkillSheet.TryGetValue(selectedSkill.SkillRow.Id, out var sheetSkill)) @@ -278,7 +279,8 @@ private BattleStatus.Skill UseSkillV1() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -301,7 +303,8 @@ private BattleStatus.Skill UseSkillV2() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -566,9 +569,9 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) skillInfo.SkillCategory == SkillCategory.DoubleAttack || skillInfo.SkillCategory == SkillCategory.AreaAttack || skillInfo.SkillCategory == SkillCategory.BuffRemovalAttack; - if (isAttackSkill && skillInfo.Target.Thorn > 0) + if (isAttackSkill && skillInfo.Thorn > 0) { - var effect = GiveThornDamage(skillInfo.Target.Thorn); + GiveThornDamage(skillInfo.Thorn); // Simulator.Log.Add(effect); } } @@ -582,31 +585,23 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) FinishTargetIfKilled(usedSkill); } - private BattleStatus.Skill GiveThornDamage(int targetThorn) + private void GiveThornDamage(int targetThorn) { - var clone = (CharacterBase)Clone(); + // var clone = (CharacterBase)Clone(); // minimum 1 damage var thornDamage = Math.Max(1, targetThorn - DEF); CurrentHP -= thornDamage; - var damageInfos = new List() - { - 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 tickDamage; + // var damageInfos = new List() + // { + // new BattleStatus.Skill.SkillInfo( + // (CharacterBase)Clone(), + // thornDamage, + // false, + // SkillCategory.TickDamage, + // Simulator.WaveTurn, + // ElementalType.Normal, + // SkillTargetType.Enemy) + // }; } private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) @@ -614,7 +609,7 @@ private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) var isFirst = true; foreach (var info in usedSkill.SkillInfos) { - if (!info.Target.IsDead) + if (!info.IsDead) { continue; } @@ -626,7 +621,7 @@ private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) } var target = Targets.FirstOrDefault(i => - i.Id == info.Target.Id); + i.Id == info.Id); switch (target) { case Player player: @@ -655,12 +650,12 @@ private void FinishTargetIfKilled(BattleStatus.Skill usedSkill) var killedTargets = new List(); foreach (var info in usedSkill.SkillInfos) { - if (!info.Target.IsDead) + if (!info.IsDead) { continue; } - var target = Targets.FirstOrDefault(i => i.Id == info.Target.Id); + var target = Targets.FirstOrDefault(i => i.Id == info.Id); if (!killedTargets.Contains(target)) { killedTargets.Add(target); diff --git a/Lib9c/Model/Character/Player.cs b/Lib9c/Model/Character/Player.cs index 94eab4af5e..6d44793e1f 100644 --- a/Lib9c/Model/Character/Player.cs +++ b/Lib9c/Model/Character/Player.cs @@ -522,7 +522,8 @@ protected override BattleStatus.Skill UseSkill() Simulator.StatBuffSheet, Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet - ) + ), + false ); var cooldown = RuneSkillCooldownMap[selectedSkill.SkillRow.Id]; diff --git a/Lib9c/Model/Skill/AreaAttack.cs b/Lib9c/Model/Skill/AreaAttack.cs index c49774e492..d5009806ac 100644 --- a/Lib9c/Model/Skill/AreaAttack.cs +++ b/Lib9c/Model/Skill/AreaAttack.cs @@ -17,12 +17,11 @@ public AreaAttack( { } - public override Model.BattleStatus.Skill Use( - CharacterBase caster, - int simulatorWaveTurn, - IEnumerable buffs) + public override BattleStatus.Skill Use(CharacterBase caster, + int simulatorWaveTurn, + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/AttackSkill.cs b/Lib9c/Model/Skill/AttackSkill.cs index b5c392ab28..a676c9eabe 100644 --- a/Lib9c/Model/Skill/AttackSkill.cs +++ b/Lib9c/Model/Skill/AttackSkill.cs @@ -29,7 +29,7 @@ protected AttackSkill( /// /// protected IEnumerable ProcessDamage(CharacterBase caster, int simulatorWaveTurn, - bool isNormalAttack = false) + bool isNormalAttack = false, bool b = false) { var infos = new List(); var targets = SkillRow.SkillTargetType.GetTarget(caster).ToList(); @@ -86,7 +86,8 @@ protected AttackSkill( target.CurrentHP -= damage; } - infos.Add(new BattleStatus.Skill.SkillInfo((CharacterBase) target.Clone(), damage, isCritical, + var clone = b ? (CharacterBase) target.Clone() : null; + infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, damage, isCritical, SkillRow.SkillCategory, simulatorWaveTurn, SkillRow.ElementalType, SkillRow.SkillTargetType)); } diff --git a/Lib9c/Model/Skill/BlowAttack.cs b/Lib9c/Model/Skill/BlowAttack.cs index 6d0eb29ba8..fa6b724a02 100644 --- a/Lib9c/Model/Skill/BlowAttack.cs +++ b/Lib9c/Model/Skill/BlowAttack.cs @@ -17,12 +17,11 @@ public BlowAttack( { } - public override BattleStatus.Skill Use( - CharacterBase caster, + public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/BuffRemovalAttack.cs b/Lib9c/Model/Skill/BuffRemovalAttack.cs index be103e777d..fd04ff37bc 100644 --- a/Lib9c/Model/Skill/BuffRemovalAttack.cs +++ b/Lib9c/Model/Skill/BuffRemovalAttack.cs @@ -17,12 +17,11 @@ public BuffRemovalAttack( { } - public override BattleStatus.Skill Use( - CharacterBase caster, + public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); var targets = SkillRow.SkillTargetType.GetTarget(caster); diff --git a/Lib9c/Model/Skill/BuffSkill.cs b/Lib9c/Model/Skill/BuffSkill.cs index a6d61f8c0d..524f9b65d9 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) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; 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 35f0038128..fe75c2b115 100644 --- a/Lib9c/Model/Skill/DoubleAttack.cs +++ b/Lib9c/Model/Skill/DoubleAttack.cs @@ -17,12 +17,11 @@ public DoubleAttack( { } - public override BattleStatus.Skill Use( - CharacterBase caster, + public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/HealSkill.cs b/Lib9c/Model/Skill/HealSkill.cs index f7bbd5cf4b..9bfab1ed7d 100644 --- a/Lib9c/Model/Skill/HealSkill.cs +++ b/Lib9c/Model/Skill/HealSkill.cs @@ -17,15 +17,14 @@ public HealSkill( { } - public override BattleStatus.Skill Use( - CharacterBase caster, + public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var heal = ProcessHeal(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); - + return new BattleStatus.HealSkill(SkillRow.Id, clone, heal, buff); } @@ -42,7 +41,7 @@ public override BattleStatus.Skill Use( foreach (var target in SkillRow.SkillTargetType.GetTarget(caster)) { target.Heal(healPoint); - infos.Add(new BattleStatus.Skill.SkillInfo((CharacterBase)target.Clone(), healPoint, caster.IsCritical(false), + infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, healPoint, caster.IsCritical(false), SkillRow.SkillCategory, simulatorWaveTurn)); } diff --git a/Lib9c/Model/Skill/NormalAttack.cs b/Lib9c/Model/Skill/NormalAttack.cs index 96facc11c9..11329ba690 100644 --- a/Lib9c/Model/Skill/NormalAttack.cs +++ b/Lib9c/Model/Skill/NormalAttack.cs @@ -17,12 +17,11 @@ public NormalAttack( { } - public override Model.BattleStatus.Skill Use( - CharacterBase caster, + public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs) + IEnumerable buffs, bool b) { - var clone = (CharacterBase) caster.Clone(); + var clone = b ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn, true); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/Skill.cs b/Lib9c/Model/Skill/Skill.cs index 6985aa7e57..ce99003587 100644 --- a/Lib9c/Model/Skill/Skill.cs +++ b/Lib9c/Model/Skill/Skill.cs @@ -36,11 +36,9 @@ protected Skill( ReferencedStatType = referencedStatType; } - public abstract BattleStatus.Skill Use( - CharacterBase caster, + public abstract BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs - ); + IEnumerable buffs, bool b); protected bool Equals(Skill other) { @@ -83,7 +81,7 @@ 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((CharacterBase) target.Clone(), 0, false, + infos.Add(new Model.BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, 0, false, SkillRow.SkillCategory, simulatorWaveTurn, ElementalType.Normal, SkillRow.SkillTargetType, buff)); } From f11925f6cf1eb9ed64b20ec73ead6ae3a694cbd0 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Thu, 13 Jul 2023 15:52:19 +0900 Subject: [PATCH 5/8] Improve HitHelper - simplify hitstep1 - remove type casting hitstep2 --- Lib9c/Battle/HitHelper.cs | 113 +++++++++++--------------------------- 1 file changed, 32 insertions(+), 81 deletions(-) diff --git a/Lib9c/Battle/HitHelper.cs b/Lib9c/Battle/HitHelper.cs index f2d9c2caaa..1efbde5a6a 100644 --- a/Lib9c/Battle/HitHelper.cs +++ b/Lib9c/Battle/HitHelper.cs @@ -64,101 +64,52 @@ public static bool IsHitWithoutLevelCorrection( public static int GetHitStep1(int attackerLevel, int defenderLevel) { - var correction = 0; var diff = attackerLevel - defenderLevel; if (diff <= GetHitStep1LevelDiffMin) { - correction = GetHitStep1CorrectionMin; + return GetHitStep1CorrectionMin; } - else if (diff >= GetHitStep1LevelDiffMax) - { - correction = GetHitStep1CorrectionMax; - } - else + + if (diff >= GetHitStep1LevelDiffMax) { - 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 GetHitStep1CorrectionMax; } - return correction; + return diff switch + { + -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 + }; } public static int GetHitStep2(int attackerHit, int defenderHit) { attackerHit = Math.Max(1, attackerHit); defenderHit = Math.Max(1, defenderHit); - var additionalCorrection = (int) ((attackerHit - defenderHit / 3m) / defenderHit * 100); + var additionalCorrection = (attackerHit * 100 - defenderHit * 100 / 3) / defenderHit; return Math.Min(Math.Max(additionalCorrection, GetHitStep2AdditionalCorrectionMin), GetHitStep2AdditionalCorrectionMax); } From cce76925a7162a96897672788a287d1c8e4d9b98 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Thu, 13 Jul 2023 16:53:53 +0900 Subject: [PATCH 6/8] Improve AttackCountHelper - Delete dictionary - Delete type convert --- Lib9c/Battle/AttackCountHelper.cs | 127 ++++++++++-------------- Lib9c/Model/Character/ArenaCharacter.cs | 4 +- Lib9c/Model/Character/CharacterBase.cs | 4 +- 3 files changed, 55 insertions(+), 80 deletions(-) diff --git a/Lib9c/Battle/AttackCountHelper.cs b/Lib9c/Battle/AttackCountHelper.cs index 89dc520f94..7fffe6ff73 100644 --- a/Lib9c/Battle/AttackCountHelper.cs +++ b/Lib9c/Battle/AttackCountHelper.cs @@ -1,68 +1,14 @@ 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) @@ -76,40 +22,69 @@ public static int GetCountMax(int level) : CountMaxUpperLimit; } - public static decimal GetDamageMultiplier(int attackCount, int attackCountMax) + public static int GetDamageMultiplier(int attackCount, int attackCountMax) { if (attackCount > attackCountMax) throw new ArgumentOutOfRangeException( $"{nameof(attackCount)}: {attackCount} / {nameof(attackCountMax)}: {attackCountMax}"); - var info = GetInfo(attackCount, attackCountMax); - return info.DamageMultiplier; - } - - public static decimal GetAdditionalCriticalChance(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.AdditionalCriticalChance; + throw new ArgumentOutOfRangeException(); } - private static Info GetInfo(int attackCount, int attackCountMax) + public static int GetAdditionalCriticalChance(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; + } - 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]; + throw new ArgumentOutOfRangeException(); } } } diff --git a/Lib9c/Model/Character/ArenaCharacter.cs b/Lib9c/Model/Character/ArenaCharacter.cs index 2ec210f0dd..d487336ea3 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 = - (int) AttackCountHelper.GetAdditionalCriticalChance(_attackCount, _attackCountMax); + AttackCountHelper.GetAdditionalCriticalChance(_attackCount, _attackCountMax); return CRI + additionalCriticalChance >= chance; } @@ -850,7 +850,7 @@ public int GetDamage(int damage, bool considerAttackCount = true) _attackCount = 1; } - var damageMultiplier = (int) AttackCountHelper.GetDamageMultiplier(_attackCount, _attackCountMax); + var damageMultiplier = AttackCountHelper.GetDamageMultiplier(_attackCount, _attackCountMax); damage *= damageMultiplier; return damage; } diff --git a/Lib9c/Model/Character/CharacterBase.cs b/Lib9c/Model/Character/CharacterBase.cs index 014e946380..5293ea55f0 100644 --- a/Lib9c/Model/Character/CharacterBase.cs +++ b/Lib9c/Model/Character/CharacterBase.cs @@ -413,7 +413,7 @@ public bool IsCritical(bool considerAttackCount = true) return CRI >= chance; var additionalCriticalChance = - (int) AttackCountHelper.GetAdditionalCriticalChance(AttackCount, AttackCountMax); + AttackCountHelper.GetAdditionalCriticalChance(AttackCount, AttackCountMax); return CRI + additionalCriticalChance >= chance; } @@ -446,7 +446,7 @@ public int GetDamage(int damage, bool considerAttackCount = true) AttackCount = 1; } - var damageMultiplier = (int) AttackCountHelper.GetDamageMultiplier(AttackCount, AttackCountMax); + var damageMultiplier = AttackCountHelper.GetDamageMultiplier(AttackCount, AttackCountMax); damage *= damageMultiplier; #if TEST_LOG From cd81e23c0e88128163b2e681cb8f5bf08206a458 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Fri, 14 Jul 2023 16:37:58 +0900 Subject: [PATCH 7/8] Enable replay log by Simulator.LogEvent --- .Lib9c.Tests/Model/Skill/CombatTest.cs | 34 +++++++- .Lib9c.Tests/Model/Skill/NormalAttackTest.cs | 5 +- Lib9c/Action/HackAndSlash.cs | 3 +- Lib9c/Battle/ISimulator.cs | 1 + Lib9c/Battle/RaidBoss.cs | 6 +- Lib9c/Battle/Simulator.cs | 8 +- Lib9c/Battle/StageSimulator.cs | 24 +++--- Lib9c/Battle/StageSimulatorV1.cs | 2 +- Lib9c/Battle/StageSimulatorV2.cs | 2 +- Lib9c/Battle/StageSimulatorV3.cs | 2 +- Lib9c/Battle/Wave.cs | 9 ++- Lib9c/Model/BattleStatus/Skill.cs | 10 ++- Lib9c/Model/Buff/Bleed.cs | 3 +- Lib9c/Model/Character/CharacterBase.cs | 82 ++++++++++++++------ Lib9c/Model/Character/Player.cs | 21 +++-- Lib9c/Model/Skill/AreaAttack.cs | 4 +- Lib9c/Model/Skill/AttackSkill.cs | 7 +- Lib9c/Model/Skill/BlowAttack.cs | 4 +- Lib9c/Model/Skill/BuffRemovalAttack.cs | 4 +- Lib9c/Model/Skill/BuffSkill.cs | 4 +- Lib9c/Model/Skill/DoubleAttack.cs | 4 +- Lib9c/Model/Skill/HealSkill.cs | 6 +- Lib9c/Model/Skill/NormalAttack.cs | 4 +- Lib9c/Model/Skill/Skill.cs | 4 +- 24 files changed, 169 insertions(+), 84 deletions(-) diff --git a/.Lib9c.Tests/Model/Skill/CombatTest.cs b/.Lib9c.Tests/Model/Skill/CombatTest.cs index fb8f8c05f7..1622761013 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()); + normalAttack.Use(_enemy, 1, new List(), false); var currentHP = _player.CurrentHP; var damage = prevHP - currentHP; @@ -100,11 +100,41 @@ 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()); + normalAttack.Use(_enemy, 1, new List(), false); 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 e6a8c843cd..125bfe47f5 100644 --- a/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs +++ b/.Lib9c.Tests/Model/Skill/NormalAttackTest.cs @@ -79,13 +79,14 @@ public void Use() var battleStatusSkill = normalAttack.Use( player, 0, - new List()); + new List(), + true); Assert.NotNull(battleStatusSkill); Assert.Single(battleStatusSkill.SkillInfos); var skillInfo = battleStatusSkill.SkillInfos.FirstOrDefault(); Assert.NotNull(skillInfo); - Assert.Equal(enemy.Id, skillInfo.Target.Id); + Assert.Equal(enemy.Id, skillInfo.CharacterId); } } } diff --git a/Lib9c/Action/HackAndSlash.cs b/Lib9c/Action/HackAndSlash.cs index 08e8ed1f6b..90563404e2 100644 --- a/Lib9c/Action/HackAndSlash.cs +++ b/Lib9c/Action/HackAndSlash.cs @@ -465,7 +465,8 @@ public IAccountStateDelta Execute( simulatorSheets, enemySkillSheet, costumeStatSheet, - rewards); + rewards, + false); sw.Stop(); Log.Verbose("{AddressesHex}HAS Initialize Simulator: {Elapsed}", addressesHex, sw.Elapsed); diff --git a/Lib9c/Battle/ISimulator.cs b/Lib9c/Battle/ISimulator.cs index d68c70b410..00f45d4eef 100644 --- a/Lib9c/Battle/ISimulator.cs +++ b/Lib9c/Battle/ISimulator.cs @@ -14,5 +14,6 @@ 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 dca8e7657f..ce8b9231dc 100644 --- a/Lib9c/Battle/RaidBoss.cs +++ b/Lib9c/Battle/RaidBoss.cs @@ -105,7 +105,7 @@ protected override BattleStatus.Skill UseSkill() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + Simulator.LogEvent ); Simulator.Log.Add(usedSkill); @@ -147,7 +147,7 @@ public void Enrage() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + Simulator.LogEvent ); Simulator.Log.Add(usedSkill); @@ -156,7 +156,7 @@ public void Enrage() if (!info.IsDead) continue; - var target = Targets.FirstOrDefault(i => i.Id == info.Id); + var target = Targets.FirstOrDefault(i => i.Id == info.CharacterId); target?.Die(); } } diff --git a/Lib9c/Battle/Simulator.cs b/Lib9c/Battle/Simulator.cs index 70b4d69c62..7d43a46bcd 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 - ) : this(random, new Player(avatarState, simulatorSheets), foods, simulatorSheets) + SimulatorSheetsV1 simulatorSheets, bool logEvent = true) : 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 6726e10c35..e01122b6b5 100644 --- a/Lib9c/Battle/StageSimulator.cs +++ b/Lib9c/Battle/StageSimulator.cs @@ -13,6 +13,7 @@ using Nekoyume.Model.Buff; using Nekoyume.TableData; using Priority_Queue; +using Skill = Nekoyume.Model.Skill.Skill; namespace Nekoyume.Battle { @@ -32,12 +33,11 @@ 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,12 +47,14 @@ public StageSimulator( SimulatorSheets simulatorSheets, EnemySkillSheet enemySkillSheet, CostumeStatSheet costumeStatSheet, - List waveRewards) + List waveRewards, + bool logEvent = true) : base( random, avatarState, foods, - simulatorSheets) + simulatorSheets, + logEvent) { Player.SetCostumeStat(costumeStatSheet); if (runeStates != null) @@ -99,7 +101,7 @@ public static List GetWaveRewards( return waveRewards; } - public Player Simulate(bool log = false) + public Player Simulate() { Log.worldId = WorldId; Log.stageId = StageId; @@ -128,7 +130,7 @@ public Player Simulate(bool log = false) ActionBuffSheet ); - skill.Use(Player, 0, buffs, log); + skill.Use(Player, 0, buffs, LogEvent); } while (true) @@ -141,7 +143,7 @@ public Player Simulate(bool log = false) Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), log); + Player.GetExp((int)(Exp * 0.3m), LogEvent); } } else @@ -168,7 +170,7 @@ public Player Simulate(bool log = false) Result = BattleLog.Result.Lose; if (Exp > 0) { - Player.GetExp((int)(Exp * 0.3m), log); + Player.GetExp((int)(Exp * 0.3m), LogEvent); } } else @@ -191,7 +193,7 @@ public Player Simulate(bool log = false) { if (Exp > 0) { - Player.GetExp(Exp, log); + Player.GetExp(Exp, LogEvent); } break; @@ -199,7 +201,7 @@ public Player Simulate(bool log = false) case 2: { ItemMap = Player.GetRewards(_waveRewards); - if (log) + if (LogEvent) { var dropBox = new DropBox(null, _waveRewards); Log.Add(dropBox); diff --git a/Lib9c/Battle/StageSimulatorV1.cs b/Lib9c/Battle/StageSimulatorV1.cs index 1ad0e2cbc2..bafcaf03e7 100644 --- a/Lib9c/Battle/StageSimulatorV1.cs +++ b/Lib9c/Battle/StageSimulatorV1.cs @@ -331,7 +331,7 @@ public Player Simulate(int playCount) ActionBuffSheet ); - var usedSkill = skill.Use(Player, 0, buffs, false); + var usedSkill = skill.Use(Player, 0, buffs, LogEvent); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV2.cs b/Lib9c/Battle/StageSimulatorV2.cs index 28a2511ff9..08aed9dc75 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, false); + var usedSkill = skill.Use(Player, 0, buffs, LogEvent); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/StageSimulatorV3.cs b/Lib9c/Battle/StageSimulatorV3.cs index 98ec1bcfc7..5d47a62482 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, false); + var usedSkill = skill.Use(Player, 0, buffs, LogEvent); Log.Add(usedSkill); } diff --git a/Lib9c/Battle/Wave.cs b/Lib9c/Battle/Wave.cs index 615051057b..99bd2faf12 100644 --- a/Lib9c/Battle/Wave.cs +++ b/Lib9c/Battle/Wave.cs @@ -25,9 +25,12 @@ public void Spawn(ISimulator simulator) enemy.InitAI(); } - // var enemies = _enemies.Select(enemy => new Enemy(enemy)).ToList(); - // var spawnWave = new SpawnWave(null, simulator.WaveNumber, simulator.WaveTurn, enemies, HasBoss); - // simulator.Log.Add(spawnWave); + 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); + } } [Obsolete("Use Spawn")] diff --git a/Lib9c/Model/BattleStatus/Skill.cs b/Lib9c/Model/BattleStatus/Skill.cs index 930ce6442e..48149d5a4d 100644 --- a/Lib9c/Model/BattleStatus/Skill.cs +++ b/Lib9c/Model/BattleStatus/Skill.cs @@ -12,6 +12,7 @@ public abstract class Skill : EventBase [Serializable] public class SkillInfo { + public readonly CharacterBase? Target; public readonly int Effect; public readonly bool Critical; public readonly SkillCategory SkillCategory; @@ -20,16 +21,16 @@ public class SkillInfo public readonly int WaveTurn; public readonly int Thorn; public readonly bool IsDead; - public readonly Guid Id; + public readonly Guid CharacterId; public readonly Model.Buff.Buff? Buff; - public SkillInfo(Guid id, bool isDead, int thorn, int effect, bool critical, SkillCategory skillCategory, + public SkillInfo(Guid characterId, bool isDead, int thorn, int effect, bool critical, SkillCategory skillCategory, int waveTurn, ElementalType elementalType = ElementalType.Normal, - SkillTargetType targetType = SkillTargetType.Enemy, Model.Buff.Buff? buff = null) + SkillTargetType targetType = SkillTargetType.Enemy, Model.Buff.Buff? buff = null, CharacterBase? target = null) { - Id = id; + CharacterId = characterId; IsDead = isDead; Thorn = thorn; Effect = effect; @@ -39,6 +40,7 @@ public SkillInfo(Guid id, bool isDead, int thorn, int effect, bool critical, Ski SkillTargetType = targetType; Buff = buff; WaveTurn = waveTurn; + Target = target; } } diff --git a/Lib9c/Model/Buff/Bleed.cs b/Lib9c/Model/Buff/Bleed.cs index 3589acec71..800f9bd779 100644 --- a/Lib9c/Model/Buff/Bleed.cs +++ b/Lib9c/Model/Buff/Bleed.cs @@ -41,9 +41,10 @@ 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, SkillCategory.Debuff, simulatorWaveTurn, RowData.ElementalType, - RowData.TargetType) + RowData.TargetType, target: (CharacterBase)affectedCharacter.Clone()) }; return new Model.BattleStatus.TickDamage( diff --git a/Lib9c/Model/Character/CharacterBase.cs b/Lib9c/Model/Character/CharacterBase.cs index 5293ea55f0..e60c085174 100644 --- a/Lib9c/Model/Character/CharacterBase.cs +++ b/Lib9c/Model/Character/CharacterBase.cs @@ -240,6 +240,7 @@ 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,7 +252,7 @@ protected virtual BattleStatus.Skill UseSkill() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + log ); if (!Simulator.SkillSheet.TryGetValue(selectedSkill.SkillRow.Id, out var sheetSkill)) @@ -260,7 +261,10 @@ protected virtual BattleStatus.Skill UseSkill() } Skills.SetCooldown(selectedSkill.SkillRow.Id, sheetSkill.Cooldown); - // Simulator.Log.Add(usedSkill); + if (log) + { + Simulator.Log.Add(usedSkill); + } return usedSkill; } @@ -280,7 +284,7 @@ private BattleStatus.Skill UseSkillV1() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + Simulator.LogEvent ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -304,7 +308,7 @@ private BattleStatus.Skill UseSkillV2() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + Simulator.LogEvent ); Skills.SetCooldown(selectedSkill.SkillRow.Id, selectedSkill.SkillRow.Cooldown); @@ -331,7 +335,10 @@ private void RemoveBuffs() return; Stats.SetBuffs(StatBuffs); - // Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); + if (Simulator.LogEvent) + { + Simulator.Log.Add(new RemoveBuffs((CharacterBase) Clone())); + } } protected virtual void EndTurn() @@ -468,8 +475,11 @@ public void Die() protected virtual void OnDead() { - // var dead = new Dead((CharacterBase) Clone()); - // Simulator.Log.Add(dead); + if (Simulator.LogEvent) + { + var dead = new Dead((CharacterBase) Clone()); + Simulator.Log.Add(dead); + } } public void Heal(int heal) @@ -554,10 +564,14 @@ 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); - // Simulator.Log.Add(effect); + if (log) + { + Simulator.Log.Add(effect); + } } // Apply thorn damage if target has thorn @@ -571,8 +585,11 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) skillInfo.SkillCategory == SkillCategory.BuffRemovalAttack; if (isAttackSkill && skillInfo.Thorn > 0) { - GiveThornDamage(skillInfo.Thorn); - // Simulator.Log.Add(effect); + var effect = GiveThornDamage(skillInfo.Thorn); + if (log) + { + Simulator.Log.Add(effect); + } } } @@ -585,23 +602,38 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill) FinishTargetIfKilled(usedSkill); } - private void GiveThornDamage(int targetThorn) + internal BattleStatus.Skill GiveThornDamage(int targetThorn) { - // var clone = (CharacterBase)Clone(); + bool log = Simulator.LogEvent; + // Copy not damaged character + var clone = log ? (CharacterBase)Clone() : null; // minimum 1 damage var thornDamage = Math.Max(1, targetThorn - DEF); CurrentHP -= thornDamage; - // var damageInfos = new List() - // { - // new BattleStatus.Skill.SkillInfo( - // (CharacterBase)Clone(), - // thornDamage, - // false, - // SkillCategory.TickDamage, - // Simulator.WaveTurn, - // ElementalType.Normal, - // SkillTargetType.Enemy) - // }; + if (log) + { + // 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; + } + + return null; } private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) @@ -621,7 +653,7 @@ private void FinishTargetIfKilledForBeforeV100310(BattleStatus.Skill usedSkill) } var target = Targets.FirstOrDefault(i => - i.Id == info.Id); + i.Id == info.CharacterId); switch (target) { case Player player: @@ -655,7 +687,7 @@ private void FinishTargetIfKilled(BattleStatus.Skill usedSkill) continue; } - var target = Targets.FirstOrDefault(i => i.Id == info.Id); + var target = Targets.FirstOrDefault(i => i.Id == info.CharacterId); if (!killedTargets.Contains(target)) { killedTargets.Add(target); diff --git a/Lib9c/Model/Character/Player.cs b/Lib9c/Model/Character/Player.cs index 6d44793e1f..f66bda838a 100644 --- a/Lib9c/Model/Character/Player.cs +++ b/Lib9c/Model/Character/Player.cs @@ -449,8 +449,11 @@ public CollectionMap GetRewards2(List items) public virtual void Spawn() { InitAI(); - // var spawn = new SpawnPlayer((CharacterBase)Clone()); - // Simulator.Log.Add(spawn); + if (Simulator.LogEvent) + { + var spawn = new SpawnPlayer((CharacterBase)Clone()); + Simulator.Log.Add(spawn); + } } [Obsolete("Use Spawn")] @@ -512,6 +515,8 @@ protected override BattleStatus.Skill UseSkill() return base.UseSkill(); } + bool log = Simulator.LogEvent; + var usedSkill = selectedSkill.Use( this, Simulator.WaveTurn, @@ -523,12 +528,15 @@ protected override BattleStatus.Skill UseSkill() Simulator.SkillActionBuffSheet, Simulator.ActionBuffSheet ), - false + log ); var cooldown = RuneSkillCooldownMap[selectedSkill.SkillRow.Id]; RuneSkills.SetCooldown(selectedSkill.SkillRow.Id, cooldown); - // Simulator.Log.Add(usedSkill); + if (log) + { + Simulator.Log.Add(usedSkill); + } return usedSkill; } @@ -673,7 +681,10 @@ protected override void EndTurn() Simulator.TurnNumber++; Simulator.WaveTurn++; - // Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); + if (Simulator.LogEvent) + { + Simulator.Log.Add(new WaveTurnEnd(this, Simulator.TurnNumber, Simulator.WaveTurn)); + } } } } diff --git a/Lib9c/Model/Skill/AreaAttack.cs b/Lib9c/Model/Skill/AreaAttack.cs index d5009806ac..4f23a61eda 100644 --- a/Lib9c/Model/Skill/AreaAttack.cs +++ b/Lib9c/Model/Skill/AreaAttack.cs @@ -19,9 +19,9 @@ public AreaAttack( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/AttackSkill.cs b/Lib9c/Model/Skill/AttackSkill.cs index a676c9eabe..6a2370d6ae 100644 --- a/Lib9c/Model/Skill/AttackSkill.cs +++ b/Lib9c/Model/Skill/AttackSkill.cs @@ -27,9 +27,10 @@ protected AttackSkill( /// /// /// + /// /// protected IEnumerable ProcessDamage(CharacterBase caster, int simulatorWaveTurn, - bool isNormalAttack = false, bool b = false) + bool isNormalAttack = false, bool copyCharacter = true) { var infos = new List(); var targets = SkillRow.SkillTargetType.GetTarget(caster).ToList(); @@ -86,10 +87,10 @@ protected AttackSkill( target.CurrentHP -= damage; } - var clone = b ? (CharacterBase) target.Clone() : null; + var clone = copyCharacter ? (CharacterBase) target.Clone() : null; infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, damage, isCritical, SkillRow.SkillCategory, simulatorWaveTurn, SkillRow.ElementalType, - SkillRow.SkillTargetType)); + SkillRow.SkillTargetType, target: clone)); } } diff --git a/Lib9c/Model/Skill/BlowAttack.cs b/Lib9c/Model/Skill/BlowAttack.cs index fa6b724a02..c4fdae7a40 100644 --- a/Lib9c/Model/Skill/BlowAttack.cs +++ b/Lib9c/Model/Skill/BlowAttack.cs @@ -19,9 +19,9 @@ public BlowAttack( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/BuffRemovalAttack.cs b/Lib9c/Model/Skill/BuffRemovalAttack.cs index fd04ff37bc..bc930314c1 100644 --- a/Lib9c/Model/Skill/BuffRemovalAttack.cs +++ b/Lib9c/Model/Skill/BuffRemovalAttack.cs @@ -19,9 +19,9 @@ public BuffRemovalAttack( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); var targets = SkillRow.SkillTargetType.GetTarget(caster); diff --git a/Lib9c/Model/Skill/BuffSkill.cs b/Lib9c/Model/Skill/BuffSkill.cs index 524f9b65d9..674ad3239d 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 b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; 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 fe75c2b115..3b919354bf 100644 --- a/Lib9c/Model/Skill/DoubleAttack.cs +++ b/Lib9c/Model/Skill/DoubleAttack.cs @@ -19,9 +19,9 @@ public DoubleAttack( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/HealSkill.cs b/Lib9c/Model/Skill/HealSkill.cs index 9bfab1ed7d..17c87aabe2 100644 --- a/Lib9c/Model/Skill/HealSkill.cs +++ b/Lib9c/Model/Skill/HealSkill.cs @@ -19,9 +19,9 @@ public HealSkill( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var heal = ProcessHeal(caster, simulatorWaveTurn); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); @@ -42,7 +42,7 @@ public override BattleStatus.Skill Use(CharacterBase caster, { target.Heal(healPoint); infos.Add(new BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, healPoint, caster.IsCritical(false), - SkillRow.SkillCategory, simulatorWaveTurn)); + SkillRow.SkillCategory, simulatorWaveTurn, target: target)); } return infos; diff --git a/Lib9c/Model/Skill/NormalAttack.cs b/Lib9c/Model/Skill/NormalAttack.cs index 11329ba690..b9e6d26223 100644 --- a/Lib9c/Model/Skill/NormalAttack.cs +++ b/Lib9c/Model/Skill/NormalAttack.cs @@ -19,9 +19,9 @@ public NormalAttack( public override BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b) + IEnumerable buffs, bool copyCharacter) { - var clone = b ? (CharacterBase) caster.Clone() : null; + var clone = copyCharacter ? (CharacterBase) caster.Clone() : null; var damage = ProcessDamage(caster, simulatorWaveTurn, true); var buff = ProcessBuff(caster, simulatorWaveTurn, buffs); diff --git a/Lib9c/Model/Skill/Skill.cs b/Lib9c/Model/Skill/Skill.cs index ce99003587..f75297fd7e 100644 --- a/Lib9c/Model/Skill/Skill.cs +++ b/Lib9c/Model/Skill/Skill.cs @@ -38,7 +38,7 @@ protected Skill( public abstract BattleStatus.Skill Use(CharacterBase caster, int simulatorWaveTurn, - IEnumerable buffs, bool b); + IEnumerable buffs, bool copyCharacter); protected bool Equals(Skill other) { @@ -83,7 +83,7 @@ public override int GetHashCode() target.AddBuff(buff); infos.Add(new Model.BattleStatus.Skill.SkillInfo(target.Id, target.IsDead, target.Thorn, 0, false, SkillRow.SkillCategory, simulatorWaveTurn, ElementalType.Normal, SkillRow.SkillTargetType, - buff)); + buff, target)); } } From 6488222f5a5e3e3c34f725999d0548a5ebf64928 Mon Sep 17 00:00:00 2001 From: Yang Chun Ung Date: Fri, 14 Jul 2023 19:03:17 +0900 Subject: [PATCH 8/8] Fix decimal point case --- .Lib9c.Tests/Action/HitHelperTest.cs | 34 ++++++++++++++++++++++++++++ Lib9c/Battle/HitHelper.cs | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 .Lib9c.Tests/Action/HitHelperTest.cs diff --git a/.Lib9c.Tests/Action/HitHelperTest.cs b/.Lib9c.Tests/Action/HitHelperTest.cs new file mode 100644 index 0000000000..1b53168ffe --- /dev/null +++ b/.Lib9c.Tests/Action/HitHelperTest.cs @@ -0,0 +1,34 @@ +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/Battle/HitHelper.cs b/Lib9c/Battle/HitHelper.cs index 1efbde5a6a..49cb4932fc 100644 --- a/Lib9c/Battle/HitHelper.cs +++ b/Lib9c/Battle/HitHelper.cs @@ -109,7 +109,7 @@ public static int GetHitStep2(int attackerHit, int defenderHit) { attackerHit = Math.Max(1, attackerHit); defenderHit = Math.Max(1, defenderHit); - var additionalCorrection = (attackerHit * 100 - defenderHit * 100 / 3) / defenderHit; + var additionalCorrection = (attackerHit * 10000 - defenderHit * 10000 / 3) / defenderHit / 100; return Math.Min(Math.Max(additionalCorrection, GetHitStep2AdditionalCorrectionMin), GetHitStep2AdditionalCorrectionMax); }