Skip to content

Commit

Permalink
Merge pull request #2274 from planetarium/feature/vampire
Browse files Browse the repository at this point in the history
Introduce `Vampiric` : `ActionBuff`
  • Loading branch information
sonohoshi authored Dec 6, 2023
2 parents 76dc527 + 430145f commit 74ff984
Show file tree
Hide file tree
Showing 17 changed files with 2,643 additions and 2,449 deletions.
89 changes: 89 additions & 0 deletions .Lib9c.Tests/Model/PlayerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -570,5 +570,94 @@ public void GiveStun()
Assert.Contains(logList, e => e is RemoveBuffs);
Assert.Contains(logList, e => e is Nekoyume.Model.BattleStatus.NormalAttack);
}

[Theory]
[InlineData(1, 100)]
[InlineData(2, 10)]
[InlineData(1, 1)]
public void Vampiric(int duration, int percent)
{
var defaultAttack = SkillFactory.GetV1(
_tableSheets.SkillSheet.Values.First(r => r.Id == GameConfig.DefaultAttackId),
100,
100
);

var simulator = new StageSimulator(
_random,
_avatarState,
new List<Guid>(),
null,
new List<Nekoyume.Model.Skill.Skill>(),
1,
1,
_tableSheets.StageSheet[1],
_tableSheets.StageWaveSheet[1],
false,
20,
_tableSheets.GetSimulatorSheets(),
_tableSheets.EnemySkillSheet,
_tableSheets.CostumeStatSheet,
StageSimulator.GetWaveRewards(
_random,
_tableSheets.StageSheet[1],
_tableSheets.MaterialItemSheet)
);
var player = simulator.Player;
var enemy = new Enemy(player, _tableSheets.CharacterSheet.Values.First(), 1);
player.Targets.Add(enemy);
simulator.Characters = new SimplePriorityQueue<CharacterBase, decimal>();
simulator.Characters.Enqueue(enemy, 0);
player.InitAI();
player.OverrideSkill(defaultAttack);

var actionBuffSheet = _tableSheets.ActionBuffSheet;
// force add buff 'Vampiric'
// 705000 is ActionBuff id of Vampiric
var vampiric = (Vampiric)BuffFactory.GetCustomActionBuff(
new SkillCustomField { BuffDuration = duration, BuffValue = percent }, actionBuffSheet[705000]);
player.AddBuff(vampiric);
var row = actionBuffSheet.Values.First();
var bleed = BuffFactory.GetActionBuff(enemy.Stats, row);
player.AddBuff(bleed);
player.Tick();
player.Tick();
Assert.NotEmpty(simulator.Log);
var log = simulator.Log;
var logCount = log.Count;
var logList = log.ToList();
for (int i = 0; i < logCount; i++)
{
var currLog = logList[i];
if (currLog is Nekoyume.Model.BattleStatus.NormalAttack)
{
var nextLog = logList[i + 1];
if (currLog.Character.ActionBuffs.Any(actionBuff => actionBuff is Vampiric))
{
Assert.True(nextLog is Tick);
}
else
{
Assert.True(nextLog is TickDamage);
}
}
else if (currLog is Tick healSkill)
{
Assert.Equal(vampiric.RowData.Id, healSkill.SkillId);
var healInfo = healSkill.SkillInfos.First();
var prevAttack = logList.Take(i).OfType<Nekoyume.Model.BattleStatus.NormalAttack>()
.Last();
Assert.Equal(
(int)(prevAttack.SkillInfos.First().Effect * vampiric.BasisPoint / 10000m),
healInfo.Effect);
}
}

Assert.True(logList.Count > 0);
Assert.Contains(logList, e => e is Nekoyume.Model.BattleStatus.NormalAttack);
Assert.Contains(logList, e => e is TickDamage);
Assert.Contains(logList, e => e is RemoveBuffs);
Assert.Contains(logList, e => e is Tick);
}
}
}
2 changes: 1 addition & 1 deletion Lib9c/Model/BattleStatus/Arena/ArenaTick.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public ArenaTick(ArenaCharacter character, IEnumerable<ArenaSkillInfo> skillInfo

public override IEnumerator CoExecute(IArena arena)
{
yield return arena.CoTickDamage(Character, SkillInfos);
yield return arena.CoCustomEvent(Character, this);
}
}
}
2 changes: 1 addition & 1 deletion Lib9c/Model/BattleStatus/Tick.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public Tick(int skillId, CharacterBase character, IEnumerable<SkillInfo> skillIn

public override IEnumerator CoExecute(IStage stage)
{
yield return stage.CoTickDamage(Character, SkillId, SkillInfos);
yield return stage.CoCustomEvent(Character, this);
}
}
}
8 changes: 0 additions & 8 deletions Lib9c/Model/Buff/ActionBuff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,5 @@ protected ActionBuff(ActionBuff value) : base(value)
RowData = value.RowData;
CustomField = value.CustomField;
}

public abstract BattleStatus.Skill GiveEffect(
CharacterBase affectedCharacter,
int simulatorWaveTurn, bool copyCharacter = true);

public abstract BattleStatus.Arena.ArenaSkill GiveEffectForArena(
ArenaCharacter affectedCharacter,
int simulatorWaveTurn);
}
}
4 changes: 2 additions & 2 deletions Lib9c/Model/Buff/Bleed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public override object Clone()
return new Bleed(this);
}

public override BattleStatus.Skill GiveEffect(CharacterBase affectedCharacter,
public BattleStatus.Skill GiveEffect(CharacterBase affectedCharacter,
int simulatorWaveTurn, bool copyCharacter = true)
{
var clone = copyCharacter ? (CharacterBase) affectedCharacter.Clone() : null;
Expand All @@ -53,7 +53,7 @@ public override BattleStatus.Skill GiveEffect(CharacterBase affectedCharacter,
null);
}

public override ArenaSkill GiveEffectForArena(
public ArenaSkill GiveEffectForArena(
ArenaCharacter affectedCharacter,
int simulatorWaveTurn)
{
Expand Down
4 changes: 4 additions & 0 deletions Lib9c/Model/Buff/BuffFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public static ActionBuff GetActionBuff(Stats stat, ActionBuffSheet.Row row)
return new Bleed(row, power);
case ActionBuffType.Stun:
return new Stun(row);
case ActionBuffType.Vampiric:
return new Vampiric(row, 0);
default:
throw new ArgumentOutOfRangeException();
}
Expand All @@ -40,6 +42,8 @@ public static ActionBuff GetCustomActionBuff(SkillCustomField customField, Actio
return new Bleed(customField, row);
case ActionBuffType.Stun:
return new Stun(customField, row);
case ActionBuffType.Vampiric:
return new Vampiric(customField, row);
default:
throw new ArgumentOutOfRangeException();
}
Expand Down
12 changes: 0 additions & 12 deletions Lib9c/Model/Buff/Stun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,5 @@ public override object Clone()
{
return new Stun(this);
}

public override BattleStatus.Skill GiveEffect(CharacterBase affectedCharacter, int simulatorWaveTurn, bool copyCharacter = true)
{
// Do not anything
return null;
}

public override ArenaSkill GiveEffectForArena(ArenaCharacter affectedCharacter, int simulatorWaveTurn)
{
// Do not anything
return null;
}
}
}
81 changes: 81 additions & 0 deletions Lib9c/Model/Buff/Vampiric.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using Nekoyume.Model.BattleStatus.Arena;
using Nekoyume.Model.Skill;
using Nekoyume.TableData;

namespace Nekoyume.Model.Buff
{
[Serializable]
public class Vampiric : ActionBuff
{
public int BasisPoint { get; }

public Vampiric(ActionBuffSheet.Row row, int basisPoint) : base(row)
{
BasisPoint = basisPoint;
}

public Vampiric(SkillCustomField customField, ActionBuffSheet.Row row) : base(customField, row)
{
BasisPoint = customField.BuffValue;
}

protected Vampiric(Vampiric value) : base(value)
{
BasisPoint = value.BasisPoint;
}

public override object Clone()
{
return new Vampiric(this);
}

public BattleStatus.Skill GiveEffect(CharacterBase affectedCharacter, BattleStatus.Skill.SkillInfo skillInfo, int simulatorWaveTurn, bool copyCharacter = true)
{
var target = copyCharacter ? (CharacterBase) affectedCharacter.Clone() : null;
var effect = (int)(skillInfo.Effect * BasisPoint / 10000m);
affectedCharacter.Heal(effect);
// Copy new Character with healed.
var infos = new List<BattleStatus.Skill.SkillInfo>
{
new(affectedCharacter.Id,
affectedCharacter.IsDead,
affectedCharacter.Thorn,
effect,
false,
SkillCategory.Heal,
simulatorWaveTurn,
RowData.ElementalType,
RowData.TargetType,
target: target)
};
return new BattleStatus.Tick(RowData.Id,
target,
infos,
ArraySegment<BattleStatus.Skill.SkillInfo>.Empty);
}

public ArenaSkill GiveEffectForArena(ArenaCharacter affectedCharacter, ArenaSkill.ArenaSkillInfo skillInfo, int simulatorWaveTurn)
{
var clone = (ArenaCharacter)affectedCharacter.Clone();
var effect = (int)(skillInfo.Effect * BasisPoint / 10000m);
affectedCharacter.Heal(effect);
// Copy new Character with healed.
var infos = new List<ArenaSkill.ArenaSkillInfo>
{
new(affectedCharacter,
effect,
false,
SkillCategory.Heal,
simulatorWaveTurn,
RowData.ElementalType,
RowData.TargetType)
};
return new ArenaTick(
clone,
infos,
null);
}
}
}
34 changes: 25 additions & 9 deletions Lib9c/Model/Character/ArenaCharacter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,28 @@ protected virtual bool OnPreSkill()

protected virtual void OnPostSkill(BattleStatus.Arena.ArenaSkill usedSkill)
{
var attackSkills = usedSkill.SkillInfos
.Where(skillInfo => skillInfo.SkillCategory
is SkillCategory.NormalAttack
or SkillCategory.BlowAttack
or SkillCategory.DoubleAttack
or SkillCategory.AreaAttack
or SkillCategory.BuffRemovalAttack)
.ToList();
if (Buffs.Values.OfType<Vampiric>().OrderBy(x => x.BuffInfo.Id) is
{ } vampirics)
{
foreach (var vampiric in vampirics)
{
foreach (var effect in attackSkills
.Select(skillInfo =>
vampiric.GiveEffectForArena(this, skillInfo, _simulator.Turn)))
{
_simulator.Log.Add(effect);
}
}
}

var bleeds = Buffs.Values.OfType<Bleed>().OrderBy(x => x.BuffInfo.Id);
foreach (var bleed in bleeds)
{
Expand All @@ -627,15 +649,9 @@ protected virtual void OnPostSkill(BattleStatus.Arena.ArenaSkill usedSkill)
}

// Apply thorn damage if target has thorn
foreach (var skillInfo in usedSkill.SkillInfos)
{
var isAttackSkill =
skillInfo.SkillCategory == SkillCategory.NormalAttack ||
skillInfo.SkillCategory == SkillCategory.BlowAttack ||
skillInfo.SkillCategory == SkillCategory.DoubleAttack ||
skillInfo.SkillCategory == SkillCategory.AreaAttack ||
skillInfo.SkillCategory == SkillCategory.BuffRemovalAttack;
if (isAttackSkill && skillInfo.Target.Thorn > 0)
foreach (var skillInfo in attackSkills)
{
if (skillInfo.Target.Thorn > 0)
{
var effect = GiveThornDamage(skillInfo.Target.Thorn);
_simulator.Log.Add(effect);
Expand Down
35 changes: 26 additions & 9 deletions Lib9c/Model/Character/CharacterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -577,8 +577,31 @@ protected virtual bool OnPreSkill()

protected virtual void OnPostSkill(BattleStatus.Skill usedSkill)
{
var log = Simulator.LogEvent;
var attackSkills = usedSkill.SkillInfos
.Where(skillInfo => skillInfo.SkillCategory
is SkillCategory.NormalAttack
or SkillCategory.BlowAttack
or SkillCategory.DoubleAttack
or SkillCategory.AreaAttack
or SkillCategory.BuffRemovalAttack)
.ToList();
if (Buffs.Values.OfType<Vampiric>().OrderBy(x => x.BuffInfo.Id) is
{ } vampirics)
{
foreach (var vampiric in vampirics)
{
foreach (var effect in attackSkills
.Select(skillInfo =>
vampiric.GiveEffect(this, skillInfo, Simulator.WaveTurn, log))
.Where(_ => log))
{
Simulator.Log.Add(effect);
}
}
}

var bleeds = Buffs.Values.OfType<Bleed>().OrderBy(x => x.BuffInfo.Id);
bool log = Simulator.LogEvent;
foreach (var bleed in bleeds)
{
var effect = bleed.GiveEffect(this, Simulator.WaveTurn, log);
Expand All @@ -589,15 +612,9 @@ protected virtual void OnPostSkill(BattleStatus.Skill usedSkill)
}

// Apply thorn damage if target has thorn
foreach (var skillInfo in usedSkill.SkillInfos)
foreach (var skillInfo in attackSkills)
{
var isAttackSkill =
skillInfo.SkillCategory == SkillCategory.NormalAttack ||
skillInfo.SkillCategory == SkillCategory.BlowAttack ||
skillInfo.SkillCategory == SkillCategory.DoubleAttack ||
skillInfo.SkillCategory == SkillCategory.AreaAttack ||
skillInfo.SkillCategory == SkillCategory.BuffRemovalAttack;
if (isAttackSkill && skillInfo.Thorn > 0)
if (skillInfo.Thorn > 0)
{
var effect = GiveThornDamage(skillInfo.Thorn);
if (log)
Expand Down
1 change: 1 addition & 0 deletions Lib9c/Model/IArena.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ public interface IArena
IEnumerator CoRemoveBuffs(ArenaCharacter caster);
IEnumerator CoDead(ArenaCharacter caster);
IEnumerator CoTurnEnd(int turnNumber);
IEnumerator CoCustomEvent(ArenaCharacter caster, ArenaEventBase eventBase);
}
}
8 changes: 5 additions & 3 deletions Lib9c/Model/IStage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using Nekoyume.Model.BattleStatus;
using Nekoyume.Model.Item;

namespace Nekoyume.Model
Expand All @@ -19,16 +20,17 @@ public interface IStage
IEnumerator CoHeal(CharacterBase caster, int skillId, IEnumerable<BattleStatus.Skill.SkillInfo> skillInfos, IEnumerable<BattleStatus.Skill.SkillInfo> buffInfos);
IEnumerator CoBuff(CharacterBase caster, int skillId, IEnumerable<BattleStatus.Skill.SkillInfo> skillInfos, IEnumerable<BattleStatus.Skill.SkillInfo> buffInfos);
IEnumerator CoTickDamage(CharacterBase affectedCharacter, int skillId, IEnumerable<BattleStatus.Skill.SkillInfo> skillInfos);

#endregion

IEnumerator CoRemoveBuffs(CharacterBase caster);

IEnumerator CoDropBox(List<ItemBase> items);
IEnumerator CoGetReward(List<ItemBase> rewards);
IEnumerator CoSpawnWave(int waveNumber, int waveTurn, List<Enemy> enemies, bool hasBoss);
IEnumerator CoGetExp(long exp);
IEnumerator CoWaveTurnEnd(int turnNumber, int waveTurn);
IEnumerator CoDead(CharacterBase character);
IEnumerator CoCustomEvent(CharacterBase character, EventBase eventBase);
}
}
Loading

0 comments on commit 74ff984

Please sign in to comment.