1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-25 19:17:45 +00:00

status effect: damage multiplier

This commit is contained in:
collett 2020-01-09 19:37:50 +09:00
parent 8247a04d3a
commit da17eecac5
10 changed files with 279 additions and 36 deletions

View file

@ -1,27 +0,0 @@
#include <ScriptObject.h>
#include <Actor/Player.h>
#include <Action/Action.h>
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 );

View file

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

View file

@ -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).
*/

View file

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

View file

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

View file

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

View file

@ -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 );

View file

@ -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:

View file

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

View file

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