372 lines
No EOL
16 KiB
C#
372 lines
No EOL
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using WingsAPI.Data.Families;
|
|
using WingsAPI.Packets.Enums.Shells;
|
|
using WingsEmu.DTOs.BCards;
|
|
using WingsEmu.DTOs.Items;
|
|
using WingsEmu.Game._enum;
|
|
using WingsEmu.Game.Buffs;
|
|
using WingsEmu.Game.Characters;
|
|
using WingsEmu.Game.Helpers.Damages;
|
|
using WingsEmu.Game.Items;
|
|
using WingsEmu.Game.Maps;
|
|
using WingsEmu.Game.Monster;
|
|
using WingsEmu.Packets.Enums;
|
|
using WingsEmu.Packets.Enums.Battle;
|
|
using WingsEmu.Packets.Enums.Character;
|
|
|
|
namespace WingsEmu.Game.Battle;
|
|
|
|
public class PlayerBattleEntityDump : IBattleEntityDump
|
|
{
|
|
public PlayerBattleEntityDump(IPlayerEntity playerEntity, SkillInfo skill, bool isDefender, bool isMainTarget)
|
|
{
|
|
bool useSecondWeapon = false;
|
|
GameItemInstance weapon = null;
|
|
var bCardDictionary = new Dictionary<(BCardType type, byte subType), List<BCardDTO>>();
|
|
|
|
if (skill != null) // get all info from attacker calculation
|
|
{
|
|
if (isDefender)
|
|
{
|
|
if (skill.BCardsType.TryGetValue(SkillCastType.BEFORE_ATTACK_ALL_TARGETS, out HashSet<BCardDTO> hashSetBCards))
|
|
{
|
|
foreach (BCardDTO bCard in hashSetBCards)
|
|
{
|
|
if (!bCardDictionary.TryGetValue(((BCardType)bCard.Type, bCard.SubType), out List<BCardDTO> list))
|
|
{
|
|
list = new List<BCardDTO>();
|
|
bCardDictionary[((BCardType)bCard.Type, bCard.SubType)] = list;
|
|
}
|
|
|
|
list.Add(bCard);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (skill.BCardsType.TryGetValue(SkillCastType.BEFORE_ATTACK_SELF, out HashSet<BCardDTO> hashSetBCards))
|
|
{
|
|
foreach (BCardDTO bCard in hashSetBCards)
|
|
{
|
|
if (!bCardDictionary.TryGetValue(((BCardType)bCard.Type, bCard.SubType), out List<BCardDTO> list))
|
|
{
|
|
list = new List<BCardDTO>();
|
|
bCardDictionary[((BCardType)bCard.Type, bCard.SubType)] = list;
|
|
}
|
|
|
|
list.Add(bCard);
|
|
}
|
|
}
|
|
|
|
HashSet<BCardDTO> chargeBCardToRemove = new();
|
|
foreach (BCardDTO bCard in playerEntity.BCardComponent.GetChargeBCards())
|
|
{
|
|
if (!bCardDictionary.TryGetValue(((BCardType)bCard.Type, bCard.SubType), out List<BCardDTO> list))
|
|
{
|
|
list = new List<BCardDTO>();
|
|
bCardDictionary[((BCardType)bCard.Type, bCard.SubType)] = list;
|
|
}
|
|
|
|
list.Add(bCard);
|
|
chargeBCardToRemove.Add(bCard);
|
|
}
|
|
|
|
foreach (BCardDTO bCard in chargeBCardToRemove)
|
|
{
|
|
playerEntity.BCardComponent.RemoveChargeBCard(bCard);
|
|
}
|
|
}
|
|
|
|
if (isMainTarget)
|
|
{
|
|
if (skill.BCardsType.TryGetValue(SkillCastType.BEFORE_ATTACK_ON_MAIN_TARGET, out HashSet<BCardDTO> hashSetBCards))
|
|
{
|
|
foreach (BCardDTO bCard in hashSetBCards)
|
|
{
|
|
if (!bCardDictionary.TryGetValue(((BCardType)bCard.Type, bCard.SubType), out List<BCardDTO> list))
|
|
{
|
|
list = new List<BCardDTO>();
|
|
bCardDictionary[((BCardType)bCard.Type, bCard.SubType)] = list;
|
|
}
|
|
|
|
list.Add(bCard);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (skill.AttackType)
|
|
{
|
|
case AttackType.Melee:
|
|
AttackType = AttackType.Melee;
|
|
switch (playerEntity.Class)
|
|
{
|
|
case ClassType.Archer:
|
|
DamageMinimum = playerEntity.SecondDamageMinimum;
|
|
DamageMaximum = playerEntity.SecondDamageMaximum;
|
|
HitRate = playerEntity.SecondHitRate;
|
|
CriticalChance = playerEntity.SecondHitCriticalChance;
|
|
CriticalDamage = playerEntity.SecondHitCriticalDamage;
|
|
useSecondWeapon = true;
|
|
{
|
|
GameItemInstance inventoryItem = playerEntity.SecondaryWeapon;
|
|
if (inventoryItem != null)
|
|
{
|
|
weapon = inventoryItem;
|
|
}
|
|
}
|
|
|
|
break;
|
|
default:
|
|
{
|
|
GameItemInstance inventoryItem = playerEntity.MainWeapon;
|
|
if (inventoryItem != null)
|
|
{
|
|
weapon = inventoryItem;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case AttackType.Ranged:
|
|
AttackType = AttackType.Ranged;
|
|
switch (playerEntity.Class)
|
|
{
|
|
case ClassType.Adventurer:
|
|
case ClassType.Swordman:
|
|
case ClassType.Magician:
|
|
case ClassType.Wrestler:
|
|
DamageMinimum = playerEntity.SecondDamageMinimum;
|
|
DamageMaximum = playerEntity.SecondDamageMaximum;
|
|
HitRate = playerEntity.SecondHitRate;
|
|
CriticalChance = playerEntity.SecondHitCriticalChance;
|
|
CriticalDamage = playerEntity.SecondHitCriticalDamage;
|
|
weapon = playerEntity.SecondaryWeapon;
|
|
useSecondWeapon = true;
|
|
break;
|
|
case ClassType.Archer:
|
|
weapon = playerEntity.MainWeapon;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case AttackType.Magical:
|
|
AttackType = AttackType.Magical;
|
|
weapon = playerEntity.MainWeapon;
|
|
break;
|
|
|
|
case AttackType.Other:
|
|
weapon = playerEntity.MainWeapon;
|
|
AttackType = playerEntity.Class switch
|
|
{
|
|
ClassType.Wrestler => AttackType.Melee,
|
|
ClassType.Adventurer => AttackType.Melee,
|
|
ClassType.Swordman => AttackType.Melee,
|
|
ClassType.Archer => AttackType.Ranged,
|
|
ClassType.Magician => AttackType.Magical
|
|
};
|
|
|
|
break;
|
|
|
|
case AttackType.Dash:
|
|
AttackType = AttackType.Melee;
|
|
weapon = playerEntity.Class switch
|
|
{
|
|
ClassType.Adventurer => playerEntity.MainWeapon,
|
|
ClassType.Swordman => playerEntity.MainWeapon,
|
|
ClassType.Archer => playerEntity.SecondaryWeapon,
|
|
ClassType.Magician => playerEntity.MainWeapon,
|
|
ClassType.Wrestler => playerEntity.MainWeapon
|
|
};
|
|
|
|
if (playerEntity.Class == ClassType.Archer)
|
|
{
|
|
DamageMinimum = playerEntity.SecondDamageMinimum;
|
|
DamageMaximum = playerEntity.SecondDamageMaximum;
|
|
HitRate = playerEntity.SecondHitRate;
|
|
CriticalChance = playerEntity.SecondHitCriticalChance;
|
|
CriticalDamage = playerEntity.SecondHitCriticalDamage;
|
|
useSecondWeapon = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
weapon = playerEntity.SecondaryWeapon;
|
|
useSecondWeapon = true;
|
|
AttackType = playerEntity.Class switch
|
|
{
|
|
ClassType.Adventurer => AttackType.Melee,
|
|
ClassType.Swordman => AttackType.Melee,
|
|
ClassType.Wrestler => AttackType.Melee,
|
|
ClassType.Archer => AttackType.Ranged,
|
|
ClassType.Magician => AttackType.Magical
|
|
};
|
|
}
|
|
|
|
if (weapon != null)
|
|
{
|
|
AttackUpgrade = weapon.Upgrade;
|
|
WeaponDamageMinimum = weapon.DamageMinimum + weapon.GameItem.DamageMinimum;
|
|
WeaponDamageMaximum = weapon.DamageMaximum + weapon.GameItem.DamageMaximum;
|
|
}
|
|
|
|
GameItemInstance armor = playerEntity.Armor;
|
|
if (armor != null)
|
|
{
|
|
DefenseUpgrade = armor.Upgrade;
|
|
}
|
|
|
|
IReadOnlyList<BCardDTO> bCards = playerEntity.BCardComponent.GetAllBCards();
|
|
foreach (BCardDTO bCard in bCards)
|
|
{
|
|
if (!bCardDictionary.TryGetValue(((BCardType)bCard.Type, bCard.SubType), out List<BCardDTO> list))
|
|
{
|
|
list = new List<BCardDTO>();
|
|
bCardDictionary[((BCardType)bCard.Type, bCard.SubType)] = list;
|
|
}
|
|
|
|
list.Add(bCard);
|
|
}
|
|
|
|
ISet<int> buffsById = playerEntity.BuffComponent.GetAllBuffsId().ToHashSet();
|
|
IReadOnlyList<(int casterLevel, BCardDTO bCard)> buffBCards = playerEntity.BCardComponent.GetBuffBCards();
|
|
var buffs = new Dictionary<(BCardType type, byte subType), List<(int casterLevel, BCardDTO bCard)>>();
|
|
foreach ((int casterLevel, BCardDTO bCard) in buffBCards)
|
|
{
|
|
(BCardType, byte SubType) key = ((BCardType)bCard.Type, bCard.SubType);
|
|
if (!buffs.TryGetValue(key, out List<(int casterLevel, BCardDTO bCard)> list))
|
|
{
|
|
list = new List<(int casterLevel, BCardDTO bCard)>();
|
|
buffs[key] = list;
|
|
}
|
|
|
|
list.Add((casterLevel, bCard));
|
|
}
|
|
|
|
short element = playerEntity.Fairy?.GameItem.Element == (short)ElementType.All ? skill.Element : playerEntity.Element;
|
|
|
|
BuffBCards = buffs;
|
|
MaxHp = playerEntity.MaxHp;
|
|
MaxMp = playerEntity.MaxMp;
|
|
BuffsById = buffsById;
|
|
Type = VisualType.Player;
|
|
Id = playerEntity.Id;
|
|
Morale = playerEntity.Level;
|
|
Level = playerEntity.Level;
|
|
Faction = playerEntity.Faction;
|
|
DamageMinimum = !useSecondWeapon ? playerEntity.DamagesMinimum - WeaponDamageMinimum : DamageMinimum - WeaponDamageMinimum;
|
|
DamageMaximum = !useSecondWeapon ? playerEntity.DamagesMaximum - WeaponDamageMaximum : DamageMaximum - WeaponDamageMaximum;
|
|
CriticalChance = !useSecondWeapon ? playerEntity.HitCriticalChance : CriticalChance;
|
|
CriticalDamage = !useSecondWeapon ? playerEntity.HitCriticalDamage : CriticalDamage;
|
|
ShadowResistance = playerEntity.DarkResistance;
|
|
LightResistance = playerEntity.LightResistance;
|
|
WaterResistance = playerEntity.WaterResistance;
|
|
FireResistance = playerEntity.FireResistance;
|
|
HitRate = !useSecondWeapon ? playerEntity.HitRate : HitRate;
|
|
MeleeDodge = playerEntity.MeleeDodge;
|
|
RangeDodge = playerEntity.RangedDodge;
|
|
Element = (ElementType)element;
|
|
ElementRate = playerEntity.ElementRate + playerEntity.SpecialistElementRate;
|
|
BCards = bCardDictionary;
|
|
ShellOptionsWeapon = playerEntity.GetShellsValues(EquipmentOptionType.WEAPON_SHELL, !useSecondWeapon);
|
|
ShellOptionArmor = playerEntity.GetShellsValues(EquipmentOptionType.ARMOR_SHELL, false);
|
|
RingCellonValues = playerEntity.GetCellonValues(EquipmentType.Ring);
|
|
NecklaceCellonValues = playerEntity.GetCellonValues(EquipmentType.Necklace);
|
|
;
|
|
BraceletCellonValues = playerEntity.GetCellonValues(EquipmentType.Bracelet);
|
|
Morale = playerEntity.Level;
|
|
Position = new Position(playerEntity.PositionX, playerEntity.PositionY);
|
|
MapInstance = playerEntity.MapInstance;
|
|
MonsterRaceType = MonsterRaceType.People;
|
|
MonsterRaceSubType = MonsterSubRace.People.Humanlike;
|
|
MeleeDefense = playerEntity.MeleeDefence;
|
|
RangeDefense = playerEntity.RangedDefence;
|
|
MagicalDefense = playerEntity.MagicDefence;
|
|
FamilyUpgrades = playerEntity.Family?.UpgradeValues ?? new Dictionary<FamilyUpgradeType, short>();
|
|
|
|
double decreaseMagicDamage = 1;
|
|
double damageReduction = 1;
|
|
if (playerEntity.Specialist != null && playerEntity.UseSp)
|
|
{
|
|
IncreaseJajamaruDamage = playerEntity.Specialist.ItemVNum == (short)ItemVnums.JAJAMARU_SP &&
|
|
playerEntity.MateComponent.GetTeamMember(x => x.MateType == MateType.Partner && x.MonsterVNum == (short)MonsterVnum.SAKURA) != null;
|
|
|
|
int elementSl = playerEntity.SpecialistComponent.GetSlElement();
|
|
decreaseMagicDamage = elementSl switch
|
|
{
|
|
>= 20 and <= 49 => 0.95,
|
|
>= 50 and <= 79 => 0.9,
|
|
>= 80 and <= 99 => 0.85,
|
|
>= 100 => 0.8,
|
|
_ => decreaseMagicDamage
|
|
};
|
|
|
|
int slDefense = playerEntity.SpecialistComponent.GetSlDefense();
|
|
damageReduction = slDefense switch
|
|
{
|
|
>= 10 and < 40 => 0.85,
|
|
>= 40 and < 80 => 0.5,
|
|
>= 80 and < 100 => 0.25,
|
|
100 => 0,
|
|
_ => 1
|
|
};
|
|
}
|
|
|
|
DecreaseMagicDamage = decreaseMagicDamage;
|
|
MinimalDamageReduction = damageReduction;
|
|
}
|
|
|
|
public Dictionary<ShellEffectType, int> ShellOptionArmor { get; }
|
|
public Dictionary<ShellEffectType, int> ShellOptionsWeapon { get; }
|
|
public IReadOnlyDictionary<CellonType, int> RingCellonValues { get; }
|
|
public IReadOnlyDictionary<CellonType, int> NecklaceCellonValues { get; }
|
|
public IReadOnlyDictionary<CellonType, int> BraceletCellonValues { get; }
|
|
public double MinimalDamageReduction { get; }
|
|
public bool IncreaseJajamaruDamage { get; }
|
|
public double DecreaseMagicDamage { get; }
|
|
|
|
public IReadOnlyDictionary<(BCardType type, byte subType), List<BCardDTO>> BCards { get; }
|
|
public IReadOnlyDictionary<(BCardType type, byte subType), List<(int casterLevel, BCardDTO bCard)>> BuffBCards { get; }
|
|
public ISet<int> BuffsById { get; }
|
|
public IReadOnlyDictionary<FamilyUpgradeType, short> FamilyUpgrades { get; }
|
|
|
|
public VisualType Type { get; }
|
|
public long Id { get; }
|
|
public IMapInstance MapInstance { get; }
|
|
public MonsterRaceType MonsterRaceType { get; }
|
|
public Enum MonsterRaceSubType { get; }
|
|
public AttackType AttackType { get; }
|
|
public ElementType Element { get; }
|
|
public int ElementRate { get; }
|
|
public int Morale { get; }
|
|
public int Level { get; }
|
|
public FactionType Faction { get; }
|
|
public int DamageMinimum { get; }
|
|
public int DamageMaximum { get; }
|
|
public int AttackUpgrade { get; }
|
|
public int DefenseUpgrade { get; }
|
|
public int HitRate { get; }
|
|
public int MaxHp { get; }
|
|
public int MaxMp { get; }
|
|
public int WeaponDamageMinimum { get; }
|
|
public int WeaponDamageMaximum { get; }
|
|
public int CriticalChance { get; }
|
|
public int CriticalDamage { get; }
|
|
public int FireResistance { get; }
|
|
public int WaterResistance { get; }
|
|
public int LightResistance { get; }
|
|
public int ShadowResistance { get; }
|
|
public int MeleeDefense { get; }
|
|
public int MeleeDodge { get; }
|
|
public int RangeDefense { get; }
|
|
public int RangeDodge { get; }
|
|
public int MagicalDefense { get; }
|
|
public Position Position { get; }
|
|
} |