mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-27 11:57:45 +00:00
status effect: dots & hots
This commit is contained in:
parent
384404bb33
commit
77a6904220
7 changed files with 331 additions and 82 deletions
|
@ -406,49 +406,12 @@ void Action::Action::execute()
|
|||
|
||||
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( uint32_t potency )
|
||||
{
|
||||
// todo: what do for npcs?
|
||||
auto wepDmg = 1.f;
|
||||
|
||||
if( auto player = m_pSource->getAsPlayer() )
|
||||
{
|
||||
auto item = player->getEquippedWeapon();
|
||||
assert( item );
|
||||
|
||||
auto role = player->getRole();
|
||||
if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
|
||||
{
|
||||
wepDmg = item->getMagicalDmg();
|
||||
}
|
||||
else
|
||||
{
|
||||
wepDmg = item->getPhysicalDmg();
|
||||
}
|
||||
}
|
||||
|
||||
return Math::CalcStats::calcActionDamage( *m_pSource, *this, potency, wepDmg );
|
||||
return Math::CalcStats::calcActionDamage( *m_pSource, *this, potency, Math::CalcStats::getWeaponDamage( *m_pSource ) );
|
||||
}
|
||||
|
||||
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing( uint32_t potency )
|
||||
{
|
||||
auto wepDmg = 1.f;
|
||||
|
||||
if( auto player = m_pSource->getAsPlayer() )
|
||||
{
|
||||
auto item = player->getEquippedWeapon();
|
||||
assert( item );
|
||||
|
||||
auto role = player->getRole();
|
||||
if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
|
||||
{
|
||||
wepDmg = item->getMagicalDmg();
|
||||
}
|
||||
else
|
||||
{
|
||||
wepDmg = item->getPhysicalDmg();
|
||||
}
|
||||
}
|
||||
|
||||
return Math::CalcStats::calcActionHealing( *m_pSource, *this, potency, wepDmg );
|
||||
return Math::CalcStats::calcActionHealing( *m_pSource, *this, potency, Math::CalcStats::getWeaponDamage( *m_pSource ) );
|
||||
}
|
||||
|
||||
void Action::Action::buildEffects()
|
||||
|
@ -512,6 +475,7 @@ void Action::Action::buildEffects()
|
|||
if( m_lutEntry.selfHealPotency > 0 ) // actions with self heal
|
||||
{
|
||||
auto heal = calcHealing( m_lutEntry.selfHealPotency );
|
||||
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *m_pSource, heal.first, 0 );
|
||||
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource );
|
||||
}
|
||||
|
||||
|
@ -530,6 +494,7 @@ void Action::Action::buildEffects()
|
|||
else if( m_lutEntry.healPotency > 0 )
|
||||
{
|
||||
auto heal = calcHealing( m_lutEntry.healPotency );
|
||||
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *actor, heal.first, 0 );
|
||||
m_effectBuilder->heal( actor, actor, heal.first, heal.second );
|
||||
|
||||
if( m_lutEntry.gainMPPercentage > 0 && shouldRestoreMP )
|
||||
|
|
|
@ -2088,6 +2088,10 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//more than 1 effect is found
|
||||
//Sentinel, センチネル: EffectTypeDamageReceiveMultiplier, all, -30%
|
||||
//{ 74, { 2, 0, -30, 0, 0 } },
|
||||
//Circle of Scorn, サークル・オブ・ドゥーム: EffectTypeDot, physical, potency 35
|
||||
{ 248, { 4, 1, 35, 0, 0 } },
|
||||
//Goring Blade, ゴアブレード: EffectTypeDot, physical, potency 85
|
||||
{ 725, { 4, 1, 85, 0, 0 } },
|
||||
//Requiescat, レクイエスカット: EffectTypeDamageMultiplier, magic, 50%
|
||||
{ 1368, { 1, 2, 50, 0, 0 } },
|
||||
//Vulnerability Down, 被ダメージ低下: EffectTypeDamageReceiveMultiplier, all, -30%
|
||||
|
@ -2129,6 +2133,12 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//more than 1 effect is found
|
||||
//Nebula, ネビュラ: EffectTypeDamageReceiveMultiplier, all, -30%
|
||||
//{ 1834, { 2, 0, -30, 0, 0 } },
|
||||
//Aurora, オーロラ: EffectTypeHot, potency 200
|
||||
{ 1835, { 3, 0, 200, 0, 0 } },
|
||||
//Sonic Break, ソニックブレイク: EffectTypeDot, unknown, potency 90
|
||||
{ 1837, { 4, 0, 90, 0, 0 } },
|
||||
//Bow Shock, バウショック: EffectTypeDot, unknown, potency 90
|
||||
{ 1838, { 4, 0, 90, 0, 0 } },
|
||||
//Heart of Light, ハート・オブ・ライト: EffectTypeDamageReceiveMultiplier, all, -10%
|
||||
{ 1839, { 2, 0, -10, 0, 0 } },
|
||||
//Heart of Stone, ハート・オブ・ストーン: EffectTypeDamageReceiveMultiplier, all, -7%
|
||||
|
@ -2142,6 +2152,11 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//{ 101, { 1, 0, 10, 0, 0 } },
|
||||
//Twin Snakes, 双掌打: EffectTypeDamageMultiplier, all, 10%
|
||||
//{ 101, { 1, 0, 10, 0, 0 } },
|
||||
//Demolish, 破砕拳: EffectTypeDot, physical, potency 65
|
||||
{ 246, { 4, 1, 65, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Demolish, 破砕拳: EffectTypeDot, physical, potency 65
|
||||
//{ 246, { 4, 1, 65, 0, 0 } },
|
||||
//Fists of Fire, 紅蓮の構え: EffectTypeDamageMultiplier, all, 10%
|
||||
{ 103, { 1, 0, 10, 0, 0 } },
|
||||
//Earth's Reply, 金剛の決意: EffectTypeDamageReceiveMultiplier, all, -10%
|
||||
|
@ -2157,6 +2172,8 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
{ 1914, { 1, 0, 10, 0, 0 } },
|
||||
//Lance Charge, ランスチャージ: EffectTypeDamageMultiplier, all, 15%
|
||||
{ 1864, { 1, 0, 15, 0, 0 } },
|
||||
//Chaos Thrust, 桜華狂咲: EffectTypeDot, physical, potency 45
|
||||
{ 118, { 4, 1, 45, 0, 0 } },
|
||||
//Left Eye, 竜の左眼: EffectTypeDamageMultiplier, all, 5%
|
||||
{ 1454, { 1, 0, 5, 0, 0 } },
|
||||
//Right Eye, 竜の右眼: EffectTypeDamageMultiplier, all, 10%
|
||||
|
@ -2168,6 +2185,13 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//more than 1 effect is found
|
||||
//Vulnerability Up, 被ダメージ上昇: EffectTypeDamageReceiveMultiplier, all, 5%
|
||||
//{ 638, { 2, 0, 5, 0, 0 } },
|
||||
//Shadow Fang, 影牙: EffectTypeDot, physical, potency 50
|
||||
{ 508, { 4, 1, 50, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Shadow Fang, 影牙: EffectTypeDot, physical, potency 70
|
||||
//{ 508, { 4, 1, 70, 0, 0 } },
|
||||
//Shadow Fang, 影牙: EffectTypeDot, physical, potency 90
|
||||
//{ 508, { 4, 1, 90, 0, 0 } },
|
||||
//Kassatsu, 活殺自在: EffectTypeDamageMultiplier, all, 30%
|
||||
{ 497, { 1, 0, 30, 0, 0 } },
|
||||
//Ten Chi Jin, 天地人: EffectTypeDamageMultiplier, all, 150%
|
||||
|
@ -2181,32 +2205,200 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//{ 1298, { 1, 0, 13, 0, 0 } },
|
||||
//Kaiten, 必殺剣・回天: EffectTypeDamageMultiplier, all, 50%
|
||||
{ 1229, { 1, 0, 50, 0, 0 } },
|
||||
//Higanbana, 彼岸花: EffectTypeDot, physical, potency 35
|
||||
{ 1228, { 4, 1, 35, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Higanbana, 彼岸花: EffectTypeDot, physical, potency 52
|
||||
//{ 1228, { 4, 1, 52, 0, 0 } },
|
||||
//Higanbana, 彼岸花: EffectTypeDot, physical, potency 40
|
||||
//{ 1228, { 4, 1, 40, 0, 0 } },
|
||||
//Higanbana, 彼岸花: EffectTypeDot, physical, potency 60
|
||||
//{ 1228, { 4, 1, 60, 0, 0 } },
|
||||
//Raging Strikes, 猛者の撃: EffectTypeDamageMultiplier, all, 10%
|
||||
{ 125, { 1, 0, 10, 0, 0 } },
|
||||
//Venomous Bite, ベノムバイト: EffectTypeDot, physical, potency 40
|
||||
{ 124, { 4, 1, 40, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Venomous Bite, ベノムバイト: EffectTypeDot, physical, potency 30
|
||||
//{ 124, { 4, 1, 30, 0, 0 } },
|
||||
//Windbite, ウィンドバイト: EffectTypeDot, physical, potency 50
|
||||
{ 129, { 4, 1, 50, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Windbite, ウィンドバイト: EffectTypeDot, physical, potency 50
|
||||
//{ 129, { 4, 1, 50, 0, 0 } },
|
||||
//Windbite, ウィンドバイト: EffectTypeDot, physical, potency 40
|
||||
//{ 129, { 4, 1, 40, 0, 0 } },
|
||||
//Windbite, ウィンドバイト: EffectTypeDot, physical, potency 40
|
||||
//{ 129, { 4, 1, 40, 0, 0 } },
|
||||
//Caustic Bite, コースティックバイト: EffectTypeDot, physical, potency 50
|
||||
{ 1200, { 4, 1, 50, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Caustic Bite, コースティックバイト: EffectTypeDot, physical, potency 50
|
||||
//{ 1200, { 4, 1, 50, 0, 0 } },
|
||||
//Caustic Bite, コースティックバイト: EffectTypeDot, physical, potency 40
|
||||
//{ 1200, { 4, 1, 40, 0, 0 } },
|
||||
//Caustic Bite, コースティックバイト: EffectTypeDot, physical, potency 40
|
||||
//{ 1200, { 4, 1, 40, 0, 0 } },
|
||||
//Troubadour, トルバドゥール: EffectTypeDamageReceiveMultiplier, all, -10%
|
||||
{ 1934, { 2, 0, -10, 0, 0 } },
|
||||
//Stormbite, ストームバイト: EffectTypeDot, physical, potency 60
|
||||
{ 1201, { 4, 1, 60, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Stormbite, ストームバイト: EffectTypeDot, physical, potency 50
|
||||
//{ 1201, { 4, 1, 50, 0, 0 } },
|
||||
//Tactician, タクティシャン: EffectTypeDamageReceiveMultiplier, all, -10%
|
||||
{ 1951, { 2, 0, -10, 0, 0 } },
|
||||
//Bioblaster, バイオブラスト: EffectTypeDot, physical, potency 60
|
||||
{ 1866, { 4, 1, 60, 0, 0 } },
|
||||
//Standard Finish, スタンダードフィニッシュ: EffectTypeDamageMultiplier, all, 5%
|
||||
{ 1821, { 1, 0, 5, 0, 0 } },
|
||||
//Shield Samba, 守りのサンバ: EffectTypeDamageReceiveMultiplier, all, -10%
|
||||
{ 1826, { 2, 0, -10, 0, 0 } },
|
||||
//Technical Finish, テクニカルフィニッシュ: EffectTypeDamageMultiplier, all, 5%
|
||||
{ 1822, { 1, 0, 5, 0, 0 } },
|
||||
//Thunder, サンダー: EffectTypeDot, magic, potency 40
|
||||
{ 161, { 4, 2, 40, 0, 0 } },
|
||||
//Thunder II, サンダラ: EffectTypeDot, magic, potency 30
|
||||
{ 162, { 4, 2, 30, 0, 0 } },
|
||||
//Thunder III, サンダガ: EffectTypeDot, magic, potency 40
|
||||
{ 163, { 4, 2, 40, 0, 0 } },
|
||||
//Enochian, エノキアン: EffectTypeDamageMultiplier, magic, 15%
|
||||
{ 868, { 1, 2, 15, 0, 0 } },
|
||||
//Thunder IV, サンダジャ: EffectTypeDot, magic, potency 30
|
||||
{ 1210, { 4, 2, 30, 0, 0 } },
|
||||
//Bio, バイオ: EffectTypeDot, magic, potency 20
|
||||
{ 179, { 4, 2, 20, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Bio, バイオ: EffectTypeDot, magic, potency 20
|
||||
//{ 179, { 4, 2, 20, 0, 0 } },
|
||||
//Bio, バイオ: EffectTypeDot, magic, potency 20
|
||||
//{ 179, { 4, 2, 20, 0, 0 } },
|
||||
//Bio, バイオ: EffectTypeDot, magic, potency 20
|
||||
//{ 179, { 4, 2, 20, 0, 0 } },
|
||||
//Miasma, ミアズマ: EffectTypeDot, magic, potency 20
|
||||
{ 180, { 4, 2, 20, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Miasma, ミアズマ: EffectTypeDot, magic, potency 20
|
||||
//{ 180, { 4, 2, 20, 0, 0 } },
|
||||
//Miasma, ミアズマ: EffectTypeDot, magic, potency 20
|
||||
//{ 180, { 4, 2, 20, 0, 0 } },
|
||||
//Bio II, バイオラ: EffectTypeDot, magic, potency 30
|
||||
{ 189, { 4, 2, 30, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Bio II, バイオラ: EffectTypeDot, magic, potency 30
|
||||
//{ 189, { 4, 2, 30, 0, 0 } },
|
||||
//Bio II, バイオラ: EffectTypeDot, magic, potency 30
|
||||
//{ 189, { 4, 2, 30, 0, 0 } },
|
||||
//Bio II, バイオラ: EffectTypeDot, magic, potency 30
|
||||
//{ 189, { 4, 2, 30, 0, 0 } },
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 40
|
||||
{ 1214, { 4, 2, 40, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 40
|
||||
//{ 1214, { 4, 2, 40, 0, 0 } },
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 40
|
||||
//{ 1214, { 4, 2, 40, 0, 0 } },
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1214, { 4, 2, 50, 0, 0 } },
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1214, { 4, 2, 50, 0, 0 } },
|
||||
//Bio III, バイオガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1214, { 4, 2, 50, 0, 0 } },
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 40
|
||||
{ 1215, { 4, 2, 40, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 40
|
||||
//{ 1215, { 4, 2, 40, 0, 0 } },
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 40
|
||||
//{ 1215, { 4, 2, 40, 0, 0 } },
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1215, { 4, 2, 50, 0, 0 } },
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1215, { 4, 2, 50, 0, 0 } },
|
||||
//Miasma III, ミアズガ: EffectTypeDot, magic, potency 50
|
||||
//{ 1215, { 4, 2, 50, 0, 0 } },
|
||||
//Devotion, エギの加護: EffectTypeDamageMultiplier, all, 5%
|
||||
{ 1213, { 1, 0, 5, 0, 0 } },
|
||||
//Everlasting Flight, 不死鳥の翼: EffectTypeHot, potency 100
|
||||
{ 1868, { 3, 0, 100, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Everlasting Flight, 不死鳥の翼: EffectTypeHot, potency 100
|
||||
//{ 1868, { 3, 0, 100, 0, 0 } },
|
||||
//Inferno, 地獄の火炎: EffectTypeDot, magic, potency 20
|
||||
{ 314, { 4, 2, 20, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Inferno, 地獄の火炎: EffectTypeDot, magic, potency 20
|
||||
//{ 314, { 4, 2, 20, 0, 0 } },
|
||||
//Embolden, エンボルデン: EffectTypeDamageMultiplier, magic, 2%
|
||||
{ 1239, { 1, 2, 2, 0, 0 } },
|
||||
//Embolden, エンボルデン: EffectTypeDamageMultiplier, physical, 2%
|
||||
{ 1297, { 1, 1, 2, 0, 0 } },
|
||||
//Manafication, マナフィケーション: EffectTypeDamageMultiplier, all, 5%
|
||||
{ 1971, { 1, 0, 5, 0, 0 } },
|
||||
//Aero, エアロ: EffectTypeDot, magic, potency 30
|
||||
{ 143, { 4, 2, 30, 0, 0 } },
|
||||
//Aero II, エアロラ: EffectTypeDot, magic, potency 60
|
||||
{ 144, { 4, 2, 60, 0, 0 } },
|
||||
//Medica II, メディカラ: EffectTypeHot, potency 100
|
||||
{ 150, { 3, 0, 100, 0, 0 } },
|
||||
//Regen, リジェネ: EffectTypeHot, potency 200
|
||||
{ 158, { 3, 0, 200, 0, 0 } },
|
||||
//Confession, インドゥルゲンティア: EffectTypeHot, potency 200
|
||||
{ 1219, { 3, 0, 200, 0, 0 } },
|
||||
//Dia, ディア: EffectTypeDot, magic, potency 60
|
||||
{ 1871, { 4, 2, 60, 0, 0 } },
|
||||
//Temperance, テンパランス:効果: EffectTypeDamageReceiveMultiplier, all, 10%
|
||||
{ 1873, { 2, 0, 10, 0, 0 } },
|
||||
//Biolysis, 蠱毒法: EffectTypeDot, magic, potency 60
|
||||
{ 1895, { 4, 2, 60, 0, 0 } },
|
||||
//Whispering Dawn, 光の囁き: EffectTypeHot, potency 120
|
||||
{ 315, { 3, 0, 120, 0, 0 } },
|
||||
//Angel's Whisper, 光輝の囁き: EffectTypeHot, potency 120
|
||||
{ 1874, { 3, 0, 120, 0, 0 } },
|
||||
//Combust, コンバス: EffectTypeDot, magic, potency 30
|
||||
{ 838, { 4, 2, 30, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Combust, コンバス: EffectTypeDot, magic, potency 40
|
||||
//{ 838, { 4, 2, 40, 0, 0 } },
|
||||
//Aspected Benefic, アスペクト・ベネフィク: EffectTypeHot, potency 200
|
||||
{ 835, { 3, 0, 200, 0, 0 } },
|
||||
//Aspected Helios, アスペクト・ヘリオス: EffectTypeHot, potency 100
|
||||
{ 836, { 3, 0, 100, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Aspected Helios, アスペクト・ヘリオス: EffectTypeHot, potency 100
|
||||
//{ 836, { 3, 0, 100, 0, 0 } },
|
||||
//Horoscope Helios, ホロスコープ・ヘリオス: EffectTypeHot, potency 100
|
||||
{ 1891, { 3, 0, 100, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Horoscope Helios, ホロスコープ・ヘリオス: EffectTypeHot, potency 100
|
||||
//{ 1891, { 3, 0, 100, 0, 0 } },
|
||||
//Combust II, コンバラ: EffectTypeDot, magic, potency 35
|
||||
{ 843, { 4, 2, 35, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Combust II, コンバラ: EffectTypeDot, magic, potency 50
|
||||
//{ 843, { 4, 2, 50, 0, 0 } },
|
||||
//Divination, ディヴィネーション: EffectTypeDamageMultiplier, all, 0%
|
||||
{ 1878, { 1, 0, 0, 0, 0 } },
|
||||
//Wheel of Fortune, 運命の輪: EffectTypeHot, potency 50
|
||||
{ 956, { 3, 0, 50, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Wheel of Fortune, 運命の輪: EffectTypeHot, potency 50
|
||||
//{ 956, { 3, 0, 50, 0, 0 } },
|
||||
//Diurnal Opposition, 星天対抗[日]: EffectTypeHot, potency 60
|
||||
{ 1879, { 3, 0, 60, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Diurnal Opposition, 星天対抗[日]: EffectTypeHot, potency 100
|
||||
//{ 1879, { 3, 0, 100, 0, 0 } },
|
||||
//Combust III, コンバガ: EffectTypeDot, magic, potency 45
|
||||
{ 1881, { 4, 2, 45, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Combust III, コンバガ: EffectTypeDot, magic, potency 60
|
||||
//{ 1881, { 4, 2, 60, 0, 0 } },
|
||||
//Diurnal Intersection, 星天交差[日]: EffectTypeHot, potency 80
|
||||
{ 1888, { 3, 0, 80, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
//Diurnal Intersection, 星天交差[日]: EffectTypeHot, potency 150
|
||||
//{ 1888, { 3, 0, 150, 0, 0 } },
|
||||
//The Balance, アーゼマの均衡: EffectTypeDamageMultiplier, all, 6%
|
||||
{ 1882, { 1, 0, 6, 0, 0 } },
|
||||
//The Arrow, オシュオンの矢: EffectTypeDamageMultiplier, all, 6%
|
||||
|
@ -2234,8 +2426,12 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//more than 1 effect is found
|
||||
//Mighty Guard, マイティガード: EffectTypeDamageMultiplier, all, -70%
|
||||
//{ 1719, { 1, 0, -70, 0, 0 } },
|
||||
//Bleeding, ペイン: EffectTypeDot, magic, potency 25
|
||||
{ 1714, { 4, 2, 25, 0, 0 } },
|
||||
//Waxing Nocturne, 狂戦士化: EffectTypeDamageMultiplier, all, 50%
|
||||
{ 1718, { 1, 0, 50, 0, 0 } },
|
||||
//Windburn, 裂傷: EffectTypeDot, magic, potency 20
|
||||
{ 1723, { 4, 2, 20, 0, 0 } },
|
||||
//Diamondback, 超硬化: EffectTypeDamageReceiveMultiplier, all, -90%
|
||||
{ 1722, { 2, 0, -90, 0, 0 } },
|
||||
//Reprisal, リプライザル: EffectTypeDamageMultiplier, all, -10%
|
||||
|
@ -2243,6 +2439,10 @@ ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =
|
|||
//more than 1 effect is found
|
||||
//Reprisal, リプライザル: EffectTypeDamageMultiplier, all, -10%
|
||||
//{ 1193, { 1, 0, -10, 0, 0 } },
|
||||
//Choco Beak, チョコビーク: EffectTypeDot, physical, potency 20
|
||||
{ 236, { 4, 1, 20, 0, 0 } },
|
||||
//Choco Regen, チョコリジェネ: EffectTypeHot, potency 25
|
||||
{ 237, { 3, 0, 25, 0, 0 } },
|
||||
//Vulnerability Up, 被ダメージ上昇: EffectTypeDamageReceiveMultiplier, all, 5%
|
||||
{ 1208, { 2, 0, 5, 0, 0 } },
|
||||
//more than 1 effect is found
|
||||
|
|
|
@ -738,14 +738,14 @@ void Sapphire::Entity::Chara::updateStatusEffects()
|
|||
{
|
||||
takeDamage( thisTickDmg );
|
||||
sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0,
|
||||
static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
|
||||
static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ), true );
|
||||
}
|
||||
|
||||
if( thisTickHeal != 0 )
|
||||
{
|
||||
heal( thisTickDmg );
|
||||
heal( thisTickHeal );
|
||||
sendToInRangeSet( makeActorControl( getId(), HPFloatingText, 0,
|
||||
static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
|
||||
static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ), true );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -332,6 +332,29 @@ float CalcStats::healingMagicPower( const Sapphire::Entity::Chara& chara )
|
|||
return calcAttackPower( chara, chara.getStatValue( Common::BaseParam::HealingMagicPotency ) );
|
||||
}
|
||||
|
||||
float CalcStats::getWeaponDamage( Sapphire::Entity::Chara& chara )
|
||||
{
|
||||
auto wepDmg = chara.getLevel();
|
||||
|
||||
if( auto player = chara.getAsPlayer() )
|
||||
{
|
||||
auto item = player->getEquippedWeapon();
|
||||
assert( item );
|
||||
|
||||
auto role = player->getRole();
|
||||
if( role == Common::Role::RangedMagical || role == Common::Role::Healer )
|
||||
{
|
||||
wepDmg = item->getMagicalDmg();
|
||||
}
|
||||
else
|
||||
{
|
||||
wepDmg = item->getPhysicalDmg();
|
||||
}
|
||||
}
|
||||
|
||||
return wepDmg;
|
||||
}
|
||||
|
||||
float CalcStats::determination( const Sapphire::Entity::Chara& chara )
|
||||
{
|
||||
auto level = chara.getLevel();
|
||||
|
@ -510,10 +533,10 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
|
|||
return std::pair( factor, hitType );
|
||||
}
|
||||
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg )
|
||||
float CalcStats::calcDamageBaseOnPotency( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
// D = ⌊ f(pot) × f(wd) × f(ap) × f(det) × f(tnc) × traits ⌋
|
||||
// × f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ buff_1 ⌋ × buff_1 ⌋ × buff... ⌋
|
||||
// × f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ buff_1 ⌋ × buff_1 ⌋ × buff... ⌋
|
||||
|
||||
auto pot = potency( static_cast< uint16_t >( ptc ) );
|
||||
auto wd = weaponDamage( chara, wepDmg );
|
||||
|
@ -525,6 +548,40 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActio
|
|||
ten = tenacity( chara );
|
||||
|
||||
auto factor = std::floor( pot * wd * ap * det * ten );
|
||||
|
||||
constexpr auto format = "dmg: pot: {} ({}) wd: {} ({}) ap: {} det: {} ten: {} = {}";
|
||||
|
||||
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
||||
{
|
||||
player->sendDebug( format, pot, ptc, wd, wepDmg, ap, det, ten, factor );
|
||||
}
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
float CalcStats::calcHealBaseOnPotency( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
// reused damage formula just for testing
|
||||
auto pot = potency( static_cast< uint16_t >( ptc ) );
|
||||
auto wd = weaponDamage( chara, wepDmg );
|
||||
auto ap = getPrimaryAttackPower( chara );
|
||||
auto det = determination( chara );
|
||||
|
||||
auto factor = std::floor( pot * wd * ap * det );
|
||||
|
||||
constexpr auto format = "heal: pot: {} ({}) wd: {} ({}) ap: {} det: {} = {}";
|
||||
|
||||
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
||||
{
|
||||
player->sendDebug( format, pot, ptc, wd, wepDmg, ap, det, factor );
|
||||
}
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
auto factor =calcDamageBaseOnPotency( chara, ptc, wepDmg );
|
||||
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
||||
|
||||
if( criticalHitProbability( chara ) > range100( rng ) )
|
||||
|
@ -557,19 +614,6 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActio
|
|||
}
|
||||
}
|
||||
|
||||
// todo: buffs
|
||||
|
||||
constexpr auto format = "dmg: pot: {} ({}) wd: {} ({}) ap: {} det: {} ten: {} = {}";
|
||||
|
||||
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
|
||||
{
|
||||
player->sendDebug( format, pot, ptc, wd, wepDmg, ap, det, ten, factor );
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug( format, pot, ptc, wd, wepDmg, ap, det, ten, factor );
|
||||
}
|
||||
|
||||
return std::pair( factor, hitType );
|
||||
}
|
||||
|
||||
|
@ -592,10 +636,15 @@ float CalcStats::applyDamageReceiveMultiplier( const Sapphire::Entity::Chara& ch
|
|||
return damage;
|
||||
}
|
||||
|
||||
float CalcStats::applyHealingReceiveMultiplier( const Sapphire::Entity::Chara& chara, float originalHeal, int8_t healType )
|
||||
{
|
||||
// todo
|
||||
return originalHeal;
|
||||
}
|
||||
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionHealing( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
// lol just for testing
|
||||
auto factor = std::floor( ptc * ( wepDmg / 10.0f ) + ptc );
|
||||
auto factor = calcHealBaseOnPotency( chara, ptc, wepDmg );
|
||||
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalHeal;
|
||||
|
||||
if( criticalHitProbability( chara ) > range100( rng ) )
|
||||
|
|
|
@ -64,6 +64,8 @@ namespace Sapphire::Math
|
|||
|
||||
static float healingMagicPower( const Sapphire::Entity::Chara& chara );
|
||||
|
||||
static float getWeaponDamage( Sapphire::Entity::Chara& chara );
|
||||
|
||||
/*!
|
||||
* @brief Calculates determinations contribution to damage and healing output.
|
||||
*
|
||||
|
@ -129,15 +131,25 @@ namespace Sapphire::Math
|
|||
|
||||
////////////////////////////////////////////
|
||||
|
||||
static float calcDamageBaseOnPotency( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg );
|
||||
|
||||
static float calcHealBaseOnPotency( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg );
|
||||
|
||||
static std::pair< float, Common::ActionHitSeverityType > calcAutoAttackDamage( const Sapphire::Entity::Chara& chara );
|
||||
|
||||
static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg );
|
||||
|
||||
static float applyDamageReceiveMultiplier( const Sapphire::Entity::Chara& chara, float originalDamage, int8_t attackType );
|
||||
|
||||
static float applyHealingReceiveMultiplier( const Sapphire::Entity::Chara& chara, float originalHeal, int8_t healType );
|
||||
|
||||
static std::pair< float, Common::ActionHitSeverityType > calcActionHealing( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg );
|
||||
|
||||
static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara );
|
||||
|
||||
static std::random_device dev;
|
||||
static std::mt19937 rng;
|
||||
static std::uniform_int_distribution< std::mt19937::result_type > range100;
|
||||
private:
|
||||
|
||||
/*!
|
||||
|
@ -146,10 +158,6 @@ namespace Sapphire::Math
|
|||
* @param attackPower The magic/physical attack power value.
|
||||
*/
|
||||
static float calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower );
|
||||
|
||||
static std::random_device dev;
|
||||
static std::mt19937 rng;
|
||||
static std::uniform_int_distribution< std::mt19937::result_type > range100;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "Script/ScriptMgr.h"
|
||||
|
||||
#include "Math/CalcStats.h"
|
||||
|
||||
#include "StatusEffect.h"
|
||||
#include "Framework.h"
|
||||
|
||||
|
@ -26,7 +28,8 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt
|
|||
m_startTime( 0 ),
|
||||
m_tickRate( tickRate ),
|
||||
m_lastTick( 0 ),
|
||||
m_pFw( pFw )
|
||||
m_pFw( pFw ),
|
||||
m_cachedHotOrDotValue( 0 )
|
||||
{
|
||||
auto pExdData = m_pFw->get< Data::ExdDataGenerated >();
|
||||
auto entry = pExdData->get< Sapphire::Data::Status >( id );
|
||||
|
@ -61,7 +64,30 @@ void Sapphire::StatusEffect::StatusEffect::registerTickEffect( uint8_t type, uin
|
|||
std::pair< uint8_t, uint32_t > Sapphire::StatusEffect::StatusEffect::getTickEffect()
|
||||
{
|
||||
auto thisTick = m_currTickEffect;
|
||||
m_currTickEffect = std::make_pair( 0, 0 );
|
||||
if( m_effectEntry.effectType == Sapphire::World::Action::EffectTypeDot )
|
||||
{
|
||||
auto value = m_cachedHotOrDotValue;
|
||||
if( m_cachedSourceCrit > Sapphire::Math::CalcStats::range100( Sapphire::Math::CalcStats::rng ) )
|
||||
{
|
||||
value *= m_cachedSourceCritBonus;
|
||||
}
|
||||
value *= 1.0f + ( ( Sapphire::Math::CalcStats::range100( Sapphire::Math::CalcStats::rng ) - 50.0f ) / 1000.0f );
|
||||
m_currTickEffect = std::make_pair( 1, value );
|
||||
}
|
||||
else if( m_effectEntry.effectType == Sapphire::World::Action::EffectTypeHot )
|
||||
{
|
||||
auto value = m_cachedHotOrDotValue;
|
||||
if( m_cachedSourceCrit > Sapphire::Math::CalcStats::range100( Sapphire::Math::CalcStats::rng ) )
|
||||
{
|
||||
value *= m_cachedSourceCritBonus;
|
||||
}
|
||||
value *= 1.0f + ( ( Sapphire::Math::CalcStats::range100( Sapphire::Math::CalcStats::rng ) - 50.0f ) / 1000.0f );
|
||||
m_currTickEffect = std::make_pair( 2, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currTickEffect = std::make_pair( 0, 0 );
|
||||
}
|
||||
return thisTick;
|
||||
}
|
||||
|
||||
|
@ -92,23 +118,21 @@ void Sapphire::StatusEffect::StatusEffect::applyStatus()
|
|||
m_startTime = Util::getTimeMs();
|
||||
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
||||
|
||||
// this is only right when an action is being used by the player
|
||||
// else you probably need to use an actorcontrol
|
||||
|
||||
//GamePacketNew< FFXIVIpcEffect > effectPacket( m_sourceActor->getId() );
|
||||
//effectPacket.data().targetId = m_sourceActor->getId();
|
||||
//effectPacket.data().actionAnimationId = 3;
|
||||
//effectPacket.data().unknown_3 = 1;
|
||||
//effectPacket.data().actionTextId = 3;
|
||||
//effectPacket.data().unknown_5 = 1;
|
||||
//effectPacket.data().unknown_6 = 321;
|
||||
//effectPacket.data().rotation = ( uint16_t ) ( 0x8000 * ( ( m_sourceActor->getPos().getR() + 3.1415926 ) ) / 3.1415926 );
|
||||
//effectPacket.data().effectTargetId = m_sourceActor->getId();
|
||||
//effectPacket.data().effects[4].unknown_1 = 17;
|
||||
//effectPacket.data().effects[4].bonusPercent = 30;
|
||||
//effectPacket.data().effects[4].param1 = m_id;
|
||||
//effectPacket.data().effects[4].unknown_5 = 0x80;
|
||||
//m_sourceActor->sendToInRangeSet( effectPacket, true );
|
||||
if( m_effectEntry.effectType == Sapphire::World::Action::EffectTypeDot )
|
||||
{
|
||||
auto wepDmg = Sapphire::Math::CalcStats::getWeaponDamage( *m_sourceActor );
|
||||
auto damage = Sapphire::Math::CalcStats::calcDamageBaseOnPotency( *m_sourceActor, m_effectEntry.effectValue2, wepDmg );
|
||||
m_cachedHotOrDotValue = Sapphire::Math::CalcStats::applyDamageReceiveMultiplier( *m_targetActor, damage,
|
||||
m_effectEntry.effectValue1 == 1 ? -1 : ( m_effectEntry.effectValue1 == 2 ? 5 : -128 ) );
|
||||
}
|
||||
else if( m_effectEntry.effectType == Sapphire::World::Action::EffectTypeHot )
|
||||
{
|
||||
auto wepDmg = Sapphire::Math::CalcStats::getWeaponDamage( *m_sourceActor );
|
||||
auto heal = Sapphire::Math::CalcStats::calcHealBaseOnPotency( *m_sourceActor, m_effectEntry.effectValue2, wepDmg );
|
||||
m_cachedHotOrDotValue = Sapphire::Math::CalcStats::applyHealingReceiveMultiplier( *m_targetActor, heal, m_effectEntry.effectValue1 );
|
||||
}
|
||||
m_cachedSourceCrit = Sapphire::Math::CalcStats::criticalHitProbability( *m_sourceActor );
|
||||
m_cachedSourceCritBonus = Sapphire::Math::CalcStats::criticalHitBonus( *m_sourceActor );
|
||||
|
||||
pScriptMgr->onStatusReceive( m_targetActor, m_id );
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ private:
|
|||
std::pair< uint8_t, uint32_t > m_currTickEffect;
|
||||
FrameworkPtr m_pFw;
|
||||
Sapphire::World::Action::StatusEffectEntry m_effectEntry;
|
||||
uint32_t m_cachedHotOrDotValue;
|
||||
float m_cachedSourceCrit;
|
||||
float m_cachedSourceCritBonus;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue