diff --git a/src/scripts/action/common/ActionSprint3.cpp b/src/scripts/action/common/ActionSprint3.cpp deleted file mode 100644 index fafb974c..00000000 --- a/src/scripts/action/common/ActionSprint3.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include - -class ActionSprint3 : - public Sapphire::ScriptAPI::ActionScript -{ -public: - ActionSprint3() : - Sapphire::ScriptAPI::ActionScript( 3 ) - { - } - - void onExecute( Sapphire::World::Action::Action& action ) override - { - /* - auto sourceChara = action.getSourceChara(); - - if( !sourceChara->isPlayer() ) - return; - - action.getEffectbuilder()->applyStatusEffect( sourceChara, sourceChara, 50, 20000, 30 ); - */ - } -}; - -EXPOSE_SCRIPT( ActionSprint3 ); \ No newline at end of file diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index ea457da9..8d96d36e 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -425,7 +425,7 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( } } - return Math::CalcStats::calcActionDamage( *m_pSource, potency, wepDmg ); + return Math::CalcStats::calcActionDamage( *m_pSource, *this, potency, wepDmg ); } std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing( uint32_t potency ) @@ -448,7 +448,7 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing } } - return Math::CalcStats::calcActionHealing( *m_pSource, potency, wepDmg ); + return Math::CalcStats::calcActionHealing( *m_pSource, *this, potency, wepDmg ); } void Action::Action::buildEffects() @@ -478,7 +478,8 @@ void Action::Action::buildEffects() // we have a valid lut entry if( auto player = getSourceChara()->getAsPlayer() ) { - player->sendDebug( "dpot: {} (dcpot: {}, ddpot: {}), hpot: {}, shpot: {}, ss: {}, ts: {}, gmp: {}, gjob: {}", + player->sendDebug( "type: {}, dpot: {} (dcpot: {}, ddpot: {}), hpot: {}, shpot: {}, ss: {}, ts: {}, gmp: {}, gjob: {}", + m_actionData->attackType, m_lutEntry.damagePotency, m_lutEntry.damageComboPotency, m_lutEntry.damageDirectionalPotency, m_lutEntry.healPotency, m_lutEntry.selfHealPotency, m_lutEntry.selfStatus, m_lutEntry.targetStatus, @@ -828,4 +829,23 @@ bool Action::Action::hasValidLutEntry() const Action::EffectBuilderPtr Action::Action::getEffectbuilder() { return m_effectBuilder; +} + +Data::ActionPtr Action::Action::getActionData() const +{ + return m_actionData; +} + +bool Action::Action::isPhysical() const +{ + return m_actionData->attackType == -1 || + m_actionData->attackType == 1 || + m_actionData->attackType == 2 || + m_actionData->attackType == 3 || + m_actionData->attackType == 4; +} + +bool Action::Action::isMagic() const +{ + return m_actionData->attackType == 5; } \ No newline at end of file diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index 355514b5..8fd055db 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -118,6 +118,11 @@ namespace Sapphire::World::Action */ Entity::CharaPtr getHitChara(); + Data::ActionPtr getActionData() const; + + bool isPhysical() const; + bool isMagic() const; + /*! * @brief Starts the cast. Finishes it immediately if there is no cast time (weaponskills). */ diff --git a/src/world/Action/ActionLut.cpp b/src/world/Action/ActionLut.cpp index bc705ff0..65b4473c 100644 --- a/src/world/Action/ActionLut.cpp +++ b/src/world/Action/ActionLut.cpp @@ -23,5 +23,26 @@ const ActionEntry& ActionLut::getEntry( uint16_t actionId ) assert( it != m_actionLut.end() ); + return it->second; +} + +bool ActionLut::validStatusEffectExists( uint16_t statusId ) +{ + auto it = m_statusEffectTable.find( statusId ); + + if( it == m_statusEffectTable.end() ) + return false; + + const auto& entry = it->second; + + return entry.effectType != 0; +} + +const StatusEffectEntry& ActionLut::getStatusEffectEntry( uint16_t statusId ) +{ + auto it = m_statusEffectTable.find( statusId ); + + assert( it != m_statusEffectTable.end() ); + return it->second; } \ No newline at end of file diff --git a/src/world/Action/ActionLut.h b/src/world/Action/ActionLut.h index 388cf305..e39350ec 100644 --- a/src/world/Action/ActionLut.h +++ b/src/world/Action/ActionLut.h @@ -22,15 +22,32 @@ namespace Sapphire::World::Action uint16_t gainJobResource; }; + const uint32_t EffectTypeInvalid = 0; + const uint32_t EffectTypeDamageMultiplier = 1; + + struct StatusEffectEntry + { + uint32_t effectType; + int32_t effectValue1; + int32_t effectValue2; + int32_t effectValue3; + int32_t effectValue4; + }; + class ActionLut { public: using Lut = std::unordered_map< uint16_t, ActionEntry >; + using StatusEffectTable = std::unordered_map< uint16_t, StatusEffectEntry >; static bool validEntryExists( uint16_t actionId ); static const ActionEntry& getEntry( uint16_t actionId ); + static bool validStatusEffectExists( uint16_t statusId ); + static const StatusEffectEntry& getStatusEffectEntry( uint16_t statusId ); + static Lut m_actionLut; + static StatusEffectTable m_statusEffectTable; }; } diff --git a/src/world/Action/ActionLutData.cpp b/src/world/Action/ActionLutData.cpp index fbfc4caa..edfbb466 100644 --- a/src/world/Action/ActionLutData.cpp +++ b/src/world/Action/ActionLutData.cpp @@ -2078,3 +2078,168 @@ ActionLut::Lut ActionLut::m_actionLut = //Hagakure, 葉隠 { 7495, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, }; + +ActionLut::StatusEffectTable ActionLut::m_statusEffectTable = +{ + //Fight or Flight, ファイト・オア・フライト: damageMultiplier, physical, 25% + { 76, { 1, 1, 25, 0, 0 } }, + //Requiescat, レクイエスカット: damageMultiplier, magic, 50% + { 1368, { 1, 2, 50, 0, 0 } }, + //Storm's Eye, シュトルムブレハ: damageMultiplier, all, 10% + { 90, { 1, 0, 10, 0, 0 } }, + //Darkside, 暗黒: damageMultiplier, all, 10% + { 751, { 1, 0, 10, 0, 0 } }, + //more than 1 effect is found + //Darkside, 暗黒: damageMultiplier, all, 10% + //{ 751, { 1, 0, 10, 0, 0 } }, + //Darkside, 暗黒: damageMultiplier, all, 10% + //{ 751, { 1, 0, 10, 0, 0 } }, + //Darkside, 暗黒: damageMultiplier, all, 10% + //{ 751, { 1, 0, 10, 0, 0 } }, + //No Mercy, ノー・マーシー: damageMultiplier, all, 20% + { 1831, { 1, 0, 20, 0, 0 } }, + //Twin Snakes, 双掌打: damageMultiplier, all, 10% + { 101, { 1, 0, 10, 0, 0 } }, + //more than 1 effect is found + //Twin Snakes, 双掌打: damageMultiplier, all, 10% + //{ 101, { 1, 0, 10, 0, 0 } }, + //Twin Snakes, 双掌打: damageMultiplier, all, 10% + //{ 101, { 1, 0, 10, 0, 0 } }, + //Fists of Fire, 紅蓮の構え: damageMultiplier, all, 10% + { 103, { 1, 0, 10, 0, 0 } }, + //Riddle of Fire, 紅蓮の極意: damageMultiplier, all, 30% + { 1181, { 1, 0, 30, 0, 0 } }, + //more than 1 effect is found + //Riddle of Fire, 紅蓮の極意: damageMultiplier, all, 25% + //{ 1181, { 1, 0, 25, 0, 0 } }, + //Brotherhood, 桃園結義:攻撃: damageMultiplier, physical, 5% + { 1185, { 1, 1, 5, 0, 0 } }, + //Disembowel, ディセムボウル: damageMultiplier, all, 10% + { 1914, { 1, 0, 10, 0, 0 } }, + //Lance Charge, ランスチャージ: damageMultiplier, all, 15% + { 1864, { 1, 0, 15, 0, 0 } }, + //Left Eye, 竜の左眼: damageMultiplier, all, 5% + { 1454, { 1, 0, 5, 0, 0 } }, + //Right Eye, 竜の右眼: damageMultiplier, all, 10% + { 1453, { 1, 0, 10, 0, 0 } }, + //Right Eye, 竜の右眼: damageMultiplier, all, 10% + { 1910, { 1, 0, 10, 0, 0 } }, + //Kassatsu, 活殺自在: damageMultiplier, all, 30% + { 497, { 1, 0, 30, 0, 0 } }, + //Ten Chi Jin, 天地人: damageMultiplier, all, 150% + { 1186, { 1, 0, 150, 0, 0 } }, + //Jinpu, 陣風: damageMultiplier, all, 13% + { 1298, { 1, 0, 13, 0, 0 } }, + //more than 1 effect is found + //Jinpu, 陣風: damageMultiplier, all, 13% + //{ 1298, { 1, 0, 13, 0, 0 } }, + //Jinpu, 陣風: damageMultiplier, all, 13% + //{ 1298, { 1, 0, 13, 0, 0 } }, + //Kaiten, 必殺剣・回天: damageMultiplier, all, 50% + { 1229, { 1, 0, 50, 0, 0 } }, + //Raging Strikes, 猛者の撃: damageMultiplier, all, 10% + { 125, { 1, 0, 10, 0, 0 } }, + //Standard Finish, スタンダードフィニッシュ: damageMultiplier, all, 5% + { 1821, { 1, 0, 5, 0, 0 } }, + //Technical Finish, テクニカルフィニッシュ: damageMultiplier, all, 5% + { 1822, { 1, 0, 5, 0, 0 } }, + //Enochian, エノキアン: damageMultiplier, magic, 15% + { 868, { 1, 2, 15, 0, 0 } }, + //Devotion, エギの加護: damageMultiplier, all, 5% + { 1213, { 1, 0, 5, 0, 0 } }, + //Embolden, エンボルデン: damageMultiplier, magic, 2% + { 1239, { 1, 2, 2, 0, 0 } }, + //Embolden, エンボルデン: damageMultiplier, physical, 2% + { 1297, { 1, 1, 2, 0, 0 } }, + //Manafication, マナフィケーション: damageMultiplier, all, 5% + { 1971, { 1, 0, 5, 0, 0 } }, + //Divination, ディヴィネーション: damageMultiplier, all, 0% + { 1878, { 1, 0, 0, 0, 0 } }, + //The Balance, アーゼマの均衡: damageMultiplier, all, 6% + { 1882, { 1, 0, 6, 0, 0 } }, + //The Arrow, オシュオンの矢: damageMultiplier, all, 6% + { 1884, { 1, 0, 6, 0, 0 } }, + //The Spear, ハルオーネの槍: damageMultiplier, all, 6% + { 1885, { 1, 0, 6, 0, 0 } }, + //The Bole, 世界樹の幹: damageMultiplier, all, 6% + { 1883, { 1, 0, 6, 0, 0 } }, + //The Ewer, サリャクの水瓶: damageMultiplier, all, 6% + { 1886, { 1, 0, 6, 0, 0 } }, + //The Spire, ビエルゴの塔: damageMultiplier, all, 6% + { 1887, { 1, 0, 6, 0, 0 } }, + //Lord of Crowns, クラウンロード: damageMultiplier, all, 8% + { 1876, { 1, 0, 8, 0, 0 } }, + //Lady of Crowns, クラウンレディ: damageMultiplier, all, 8% + { 1877, { 1, 0, 8, 0, 0 } }, + //Boost, 力溜め: damageMultiplier, all, 50% + { 1716, { 1, 0, 50, 0, 0 } }, + //Mighty Guard, マイティガード: damageMultiplier, all, -70% + { 1719, { 1, 0, -70, 0, 0 } }, + //Waxing Nocturne, 狂戦士化: damageMultiplier, all, 50% + { 1718, { 1, 0, 50, 0, 0 } }, + //Reprisal, リプライザル: damageMultiplier, all, -10% + { 1193, { 1, 0, -10, 0, 0 } }, + //more than 1 effect is found + //Reprisal, リプライザル: damageMultiplier, all, -10% + //{ 1193, { 1, 0, -10, 0, 0 } }, + //Boost, 力溜め: damageMultiplier, all, 30% + { 1656, { 1, 0, 30, 0, 0 } }, + //Magic Burst L, ロゴス・マジックバースト: damageMultiplier, magic, 1% + { 1652, { 1, 2, 1, 0, 0 } }, + //Bravery L, ロゴス・ブレイブ: damageMultiplier, all, 10% + { 1646, { 1, 0, 10, 0, 0 } }, + //Double Edge L, ロゴス・ダブルエッジ: damageMultiplier, physical, 15% + { 1653, { 1, 1, 15, 0, 0 } }, + //Wisdom of the Aetherweaver, 術士の記憶: damageMultiplier, magic, 60% + { 1631, { 1, 2, 60, 0, 0 } }, + //Wisdom of the Martialist, 闘士の記憶: damageMultiplier, all, 40% + { 1632, { 1, 0, 40, 0, 0 } }, + //Wisdom of the Skirmisher, 武人の記憶: damageMultiplier, all, 20% + { 1636, { 1, 0, 20, 0, 0 } }, + //Wisdom of the Watcher, 斥候の記憶: damageMultiplier, all, -5% + { 1637, { 1, 0, -5, 0, 0 } }, + //Wisdom of the Templar, 聖騎士の記憶: damageMultiplier, all, -5% + { 1638, { 1, 0, -5, 0, 0 } }, + //Wisdom of the Duelist, 剣豪の記憶: damageMultiplier, magic, 30% + { 1740, { 1, 2, 30, 0, 0 } }, + //more than 1 effect is found + //Wisdom of the Duelist, 剣豪の記憶: damageMultiplier, physical, 40% + //{ 1740, { 1, 1, 40, 0, 0 } }, + //Wisdom of the Elder, 賢者の記憶: damageMultiplier, magic, 35% + { 1739, { 1, 2, 35, 0, 0 } }, + //Wisdom of the Fiendhunter, 弓聖の記憶: damageMultiplier, physical, 25% + { 1741, { 1, 1, 25, 0, 0 } }, + //Infernal Fetters, 炎獄の鎖: damageMultiplier, all, -10% + { 377, { 1, 0, -10, 0, 0 } }, + //Damage Up, ダメージ上昇: damageMultiplier, all, 25% + { 443, { 1, 0, 25, 0, 0 } }, + //more than 1 effect is found + //Damage Up, ダメージ上昇: damageMultiplier, all, 15% + //{ 443, { 1, 0, 15, 0, 0 } }, + //Damage Up, ダメージ上昇: damageMultiplier, all, 25% + //{ 443, { 1, 0, 25, 0, 0 } }, + //Bluefire, 青碧の炎: damageMultiplier, all, -90% + { 591, { 1, 0, -90, 0, 0 } }, + //Minimum, ミニマム: damageMultiplier, all, -50% + { 438, { 1, 0, -50, 0, 0 } }, + //more than 1 effect is found + //Minimum, ミニマム: damageMultiplier, all, -90% + //{ 438, { 1, 0, -90, 0, 0 } }, + //Minimum, ミニマム: damageMultiplier, all, -50% + //{ 438, { 1, 0, -50, 0, 0 } }, + //Minimum, ミニマム: damageMultiplier, all, -50% + //{ 438, { 1, 0, -50, 0, 0 } }, + //Minimum, ミニマム: damageMultiplier, all, -90% + //{ 438, { 1, 0, -90, 0, 0 } }, + //Minimum, ミニマム: damageMultiplier, all, -50% + //{ 438, { 1, 0, -50, 0, 0 } }, + //Damage Down, ダメージ低下: damageMultiplier, all, -10% + { 1016, { 1, 0, -10, 0, 0 } }, + //more than 1 effect is found + //Damage Down, ダメージ低下: damageMultiplier, all, -10% + //{ 1016, { 1, 0, -10, 0, 0 } }, + //Damage Down, ダメージ低下: damageMultiplier, all, -3% + //{ 1016, { 1, 0, -3, 0, 0 } }, + //Damage Down, ダメージ低下: damageMultiplier, all, -3% + //{ 1016, { 1, 0, -3, 0, 0 } }, +}; diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 7544fb9a..55aa7037 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -9,6 +9,10 @@ #include "Inventory/Item.h" +#include "StatusEffect/StatusEffect.h" + +#include "Action/Action.h" + #include "CalcStats.h" #include "Framework.h" @@ -480,7 +484,17 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA factor *= 1.0f + ( ( range100( rng ) - 50.0f ) / 1000.0f ); - // todo: buffs + for( auto const& entry : chara.getStatusEffectMap() ) + { + auto status = entry.second; + auto effectEntry = status->getEffectEntry(); + if( effectEntry.effectType != Sapphire::World::Action::EffectTypeDamageMultiplier ) + continue; + if( effectEntry.effectValue1 == 0 || effectEntry.effectValue1 == 1 ) + { + factor *= 1.0f + ( effectEntry.effectValue2 / 100.0f ); + } + } constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}"; @@ -496,7 +510,7 @@ 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, uint32_t ptc, float wepDmg ) +std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, 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... ⌋ @@ -529,6 +543,20 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActio factor *= 1.0f + ( ( range100( rng ) - 50.0f ) / 1000.0f ); + for( auto const& entry : chara.getStatusEffectMap() ) + { + auto status = entry.second; + auto effectEntry = status->getEffectEntry(); + if( effectEntry.effectType != Sapphire::World::Action::EffectTypeDamageMultiplier ) + continue; + if( effectEntry.effectValue1 == 0 || + ( effectEntry.effectValue1 == 1 && action.isPhysical() ) || + ( effectEntry.effectValue1 == 2 && action.isMagic() ) ) + { + factor *= 1.0f + ( effectEntry.effectValue2 / 100.0f ); + } + } + // todo: buffs constexpr auto format = "dmg: pot: {} ({}) wd: {} ({}) ap: {} det: {} ten: {} = {}"; @@ -545,7 +573,7 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActio return std::pair( factor, hitType ); } -std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionHealing( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg ) +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 ); diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index ce095b53..b50a82f7 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -131,9 +131,9 @@ namespace Sapphire::Math static std::pair< float, Common::ActionHitSeverityType > calcAutoAttackDamage( const Sapphire::Entity::Chara& chara ); - static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg ); + static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, const Sapphire::World::Action::Action& action, uint32_t ptc, float wepDmg ); - static std::pair< float, Common::ActionHitSeverityType > calcActionHealing( const Sapphire::Entity::Chara& chara, uint32_t ptc, float wepDmg ); + 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 ); private: diff --git a/src/world/StatusEffect/StatusEffect.cpp b/src/world/StatusEffect/StatusEffect.cpp index 4dcfd556..41be21f7 100644 --- a/src/world/StatusEffect/StatusEffect.cpp +++ b/src/world/StatusEffect/StatusEffect.cpp @@ -41,6 +41,11 @@ Sapphire::StatusEffect::StatusEffect::StatusEffect( uint32_t id, Entity::CharaPt Util::eraseAll( m_name, '-' ); Util::eraseAll( m_name, '(' ); Util::eraseAll( m_name, ')' ); + + if( Sapphire::World::Action::ActionLut::validStatusEffectExists( id ) ) + m_effectEntry = Sapphire::World::Action::ActionLut::getStatusEffectEntry( id ); + else + m_effectEntry.effectType = Sapphire::World::Action::EffectTypeInvalid; } @@ -153,3 +158,8 @@ const std::string& Sapphire::StatusEffect::StatusEffect::getName() const { return m_name; } + +const Sapphire::World::Action::StatusEffectEntry& Sapphire::StatusEffect::StatusEffect::getEffectEntry() const +{ + return m_effectEntry; +} diff --git a/src/world/StatusEffect/StatusEffect.h b/src/world/StatusEffect/StatusEffect.h index d9f933e1..ae4c7cbd 100644 --- a/src/world/StatusEffect/StatusEffect.h +++ b/src/world/StatusEffect/StatusEffect.h @@ -3,6 +3,8 @@ #include "Forwards.h" +#include "Action/ActionLut.h" + namespace Sapphire { namespace StatusEffect { @@ -47,6 +49,8 @@ public: const std::string& getName() const; + const Sapphire::World::Action::StatusEffectEntry& getEffectEntry() const; + private: uint32_t m_id; Entity::CharaPtr m_sourceActor; @@ -59,7 +63,7 @@ private: std::string m_name; std::pair< uint8_t, uint32_t > m_currTickEffect; FrameworkPtr m_pFw; - + Sapphire::World::Action::StatusEffectEntry m_effectEntry; }; }