server-master/srcs/WingsAPI.Game/Battle/PlayerBattleEntityDump.cs
2026-02-10 18:21:30 +01:00

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; }
}