1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-27 11:57:45 +00:00

Create lut entry for auto attacks so we won't have three different places that do damage.

of course more dumb mistake fixes.
This commit is contained in:
collett 2020-01-12 17:46:18 +09:00
parent e08643f380
commit 64a1c4033b
8 changed files with 61 additions and 52 deletions

View file

@ -50,7 +50,8 @@ Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId, uint16_t seq
m_targetId( 0 ), m_targetId( 0 ),
m_startTime( 0 ), m_startTime( 0 ),
m_interruptType( Common::ActionInterruptType::None ), m_interruptType( Common::ActionInterruptType::None ),
m_sequence( sequence ) m_sequence( sequence ),
m_isAutoAttack( false )
{ {
} }
@ -288,7 +289,8 @@ void Action::Action::start()
// todo: m_recastTimeMs needs to be adjusted for player sks/sps // todo: m_recastTimeMs needs to be adjusted for player sks/sps
auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(), auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(),
m_recastTimeMs / 10 ); m_recastTimeMs / 10 );
player->queuePacket( actionStartPkt ); if( player )
player->queuePacket( actionStartPkt );
auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
@ -406,7 +408,10 @@ void Action::Action::execute()
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( uint32_t potency ) std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage( uint32_t potency )
{ {
return Math::CalcStats::calcActionDamage( *m_pSource, static_cast< Common::AttackType >( m_actionData->attackType ), potency, Math::CalcStats::getWeaponDamage( m_pSource ) ); if( m_isAutoAttack )
return Math::CalcStats::calcAutoAttackDamage( *m_pSource, potency );
else
return Math::CalcStats::calcActionDamage( *m_pSource, static_cast< Common::AttackType >( m_actionData->attackType ), potency, Math::CalcStats::getWeaponDamage( m_pSource ) );
} }
std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing( uint32_t potency ) std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcHealing( uint32_t potency )
@ -472,7 +477,7 @@ void Action::Action::buildEffects()
if( reflectDmg.first > 0 ) if( reflectDmg.first > 0 )
{ {
m_effectBuilder->damage( actor, m_pSource, dmg.first, dmg.second, Common::ActionEffectResultFlag::Reflected ); m_effectBuilder->damage( actor, m_pSource, reflectDmg.first, reflectDmg.second, Common::ActionEffectResultFlag::Reflected );
} }
if( isCorrectCombo() && shouldApplyComboSucceedEffect ) if( isCorrectCombo() && shouldApplyComboSucceedEffect )
@ -813,6 +818,11 @@ Data::ActionPtr Action::Action::getActionData() const
return m_actionData; return m_actionData;
} }
void Action::Action::setAutoAttack()
{
m_isAutoAttack = true;
}
bool Action::Action::isPhysical() const bool Action::Action::isPhysical() const
{ {
return isAttackTypePhysical( static_cast< Common::AttackType >( m_actionData->attackType ) ); return isAttackTypePhysical( static_cast< Common::AttackType >( m_actionData->attackType ) );

View file

@ -52,6 +52,8 @@ namespace Sapphire::World::Action
bool isComboAction() const; bool isComboAction() const;
void setAutoAttack();
/*! /*!
* @brief Checks if a chara has enough resources available to cast the action (tp/mp/etc) * @brief Checks if a chara has enough resources available to cast the action (tp/mp/etc)
* @return true if they have the required resources * @return true if they have the required resources
@ -188,6 +190,7 @@ namespace Sapphire::World::Action
bool m_canTargetFriendly; bool m_canTargetFriendly;
bool m_canTargetHostile; bool m_canTargetHostile;
bool m_canTargetDead; bool m_canTargetDead;
bool m_isAutoAttack;
Common::ActionInterruptType m_interruptType; Common::ActionInterruptType m_interruptType;

View file

@ -2816,6 +2816,14 @@ ActionLut::Lut ActionLut::m_actionLut =
//Hagakure, 葉隠 //Hagakure, 葉隠
{ 7495, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, { 7495, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//attack, 攻撃
//has damage: potency 110, combo potency 0, directional potency 0
{ 7, { 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Shot, ショット
//has damage: potency 110, combo potency 0, directional potency 0
{ 8, { 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
}; };
ActionLut::StatusEffectTable ActionLut::m_statusEffectTable = ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =

View file

@ -94,8 +94,8 @@ void EffectBuilder::applyStatusEffect( Entity::CharaPtr& target, Entity::CharaPt
void EffectBuilder::buildAndSendPackets() void EffectBuilder::buildAndSendPackets()
{ {
auto targetCount = m_resolvedEffects.size(); auto targetCount = m_resolvedEffects.size();
Logger::debug( "EffectBuilder result: " ); //Logger::debug( "EffectBuilder result: " );
Logger::debug( "Targets afflicted: {}", targetCount ); //Logger::debug( "Targets afflicted: {}", targetCount );
auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence(); auto globalSequence = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();
@ -184,7 +184,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_
assert( !resultList->empty() ); assert( !resultList->empty() );
auto firstResult = resultList->data()[ 0 ]; auto firstResult = resultList->data()[ 0 ];
pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId(); pEffectTargetId[ targetIndex ] = firstResult->getTarget()->getId();
Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] ); //Logger::debug( " - id: {}", pEffectTargetId[ targetIndex ] );
for( auto i = 0; i < resultList->size(); i++ ) for( auto i = 0; i < resultList->size(); i++ )
{ {
@ -213,7 +213,7 @@ std::shared_ptr< FFXIVPacketBase > EffectBuilder::buildNextEffectPacket( uint32_
auto resultList = m_resolvedEffects.begin()->second; auto resultList = m_resolvedEffects.begin()->second;
assert( !resultList->empty() ); assert( !resultList->empty() );
auto firstResult = resultList->data()[ 0 ]; auto firstResult = resultList->data()[ 0 ];
Logger::debug( " - id: {}", firstResult->getTarget()->getId() ); //Logger::debug( " - id: {}", firstResult->getTarget()->getId() );
auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence(); auto seq = m_sourceChara->getCurrentTerritory()->getNextEffectSequence();

View file

@ -680,10 +680,7 @@ void Sapphire::Entity::BNpc::setFlag( uint32_t flag )
} }
/*! /*!
Autoattack prototype implementation TODO: this only solves attacks from melee classes.
TODO: move the check if the autoAttack can be performed to the callee
also rename autoAttack to autoAttack as that is more elaborate
On top of that, this only solves attacks from melee classes.
Will have to be extended for ranged attacks. Will have to be extended for ranged attacks.
\param ActorPtr the autoAttack is performed on \param ActorPtr the autoAttack is performed on
@ -698,18 +695,20 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget )
pTarget->onActionHostile( getAsChara() ); pTarget->onActionHostile( getAsChara() );
m_lastAttack = tick; m_lastAttack = tick;
auto pSource = getAsChara(); auto exdData = m_pFw->get< Data::ExdDataGenerated >();
auto damage = Math::CalcStats::calcAutoAttackDamage( *this ); assert( exdData );
damage.first = Math::CalcStats::applyDamageReceiveMultiplier( *pTarget, damage.first, Common::AttackType::Physical ); auto actionData = exdData->get< Data::Action >( 7 );
auto reflectDmg = Math::CalcStats::calcDamageReflect( pSource, pTarget, damage.first, Common::ActionTypeFilter::Physical ); assert( actionData );
auto action = World::Action::make_Action( getAsChara(), 7, 0, actionData, m_pFw );
World::Action::EffectBuilder effectBuilder( pSource, 7, 0 ); action->setTargetId( pTarget->getId() );
effectBuilder.damage( pTarget, pTarget, damage.first, damage.second ); action->setPos( getPos() );
if( reflectDmg.first > 0 ) action->setAutoAttack();
if( action->init() )
{ {
effectBuilder.damage( pTarget, pSource, reflectDmg.first, reflectDmg.second, Common::ActionEffectResultFlag::Reflected ); action->start();
} }
effectBuilder.buildAndSendPackets();
} }
} }

View file

@ -1565,32 +1565,31 @@ uint32_t Sapphire::Entity::Player::getPersistentEmote() const
void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget )
{ {
auto mainWeap = getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
pTarget->onActionHostile( getAsChara() ); pTarget->onActionHostile( getAsChara() );
auto exdData = m_pFw->get< Data::ExdDataGenerated >();
auto pSource = getAsChara(); assert( exdData );
auto damage = Math::CalcStats::calcAutoAttackDamage( *this ); World::Action::ActionPtr action;
damage.first = Math::CalcStats::applyDamageReceiveMultiplier( *pTarget, damage.first, Common::AttackType::Physical );
auto reflectDmg = Math::CalcStats::calcDamageReflect( pSource, pTarget, damage.first, Common::ActionTypeFilter::Physical );
World::Action::EffectBuilderPtr effectBuilder = nullptr;
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer ) if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
{ {
effectBuilder = World::Action::make_EffectBuilder( pSource, 8, 0 ); auto actionData = exdData->get< Data::Action >( 8 );
assert( actionData );
action = World::Action::make_Action( getAsChara(), 8, 0, actionData, m_pFw );
} }
else else
{ {
effectBuilder = World::Action::make_EffectBuilder( pSource, 7, 0 ); auto actionData = exdData->get< Data::Action >( 7 );
assert( actionData );
action = World::Action::make_Action( getAsChara(), 7, 0, actionData, m_pFw );
} }
effectBuilder->damage( pTarget, pTarget, damage.first, damage.second ); action->setTargetId( pTarget->getId() );
if( reflectDmg.first > 0 ) action->setPos( getPos() );
action->setAutoAttack();
if( action->init() )
{ {
effectBuilder->damage( pTarget, pSource, reflectDmg.first, reflectDmg.second, Common::ActionEffectResultFlag::Reflected ); action->start();
} }
effectBuilder->buildAndSendPackets();
} }

View file

@ -252,15 +252,8 @@ float CalcStats::potency( uint16_t potency )
return potency / 100.f; return potency / 100.f;
} }
float CalcStats::autoAttackPotency( const Sapphire::Entity::Chara& chara ) float CalcStats::autoAttackPotency( const Sapphire::Entity::Chara& chara, uint32_t aaPotency )
{ {
uint32_t aaPotency = AUTO_ATTACK_POTENCY;
if( chara.getRole() == Common::Role::RangedPhysical )
{
aaPotency = RANGED_AUTO_ATTACK_POTENCY;
}
float autoAttackDelay = 2.5f; float autoAttackDelay = 2.5f;
// fetch actual auto attack delay if its a player // fetch actual auto attack delay if its a player
if( chara.isPlayer() ) if( chara.isPlayer() )
@ -495,12 +488,12 @@ float CalcStats::healingMagicPotency( const Sapphire::Entity::Chara& chara )
return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::HealingMagicPotency ) - 292.f ) / 264.f + 100.f ) / 100.f; return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::HealingMagicPotency ) - 292.f ) / 264.f + 100.f ) / 100.f;
} }
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara ) std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoAttackDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc )
{ {
// D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ × // D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ ×
// f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋ // f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋
auto pot = autoAttackPotency( chara ); auto pot = autoAttackPotency( chara, ptc );
auto aa = autoAttack( chara ); auto aa = autoAttack( chara );
auto ap = getPrimaryAttackPower( chara ); auto ap = getPrimaryAttackPower( chara );
auto det = determination( chara ); auto det = determination( chara );

View file

@ -11,9 +11,6 @@ namespace Sapphire::Math
class CalcStats class CalcStats
{ {
public: public:
static const uint32_t AUTO_ATTACK_POTENCY = 110;
static const uint32_t RANGED_AUTO_ATTACK_POTENCY = 100;
static float calculateBaseStat( const Entity::Chara& chara ); static float calculateBaseStat( const Entity::Chara& chara );
static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer, FrameworkPtr pFw ); static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer, FrameworkPtr pFw );
@ -40,7 +37,7 @@ namespace Sapphire::Math
*/ */
static float potency( uint16_t potency ); static float potency( uint16_t potency );
static float autoAttackPotency( const Sapphire::Entity::Chara& chara ); static float autoAttackPotency( const Sapphire::Entity::Chara& chara, uint32_t aaPotency );
/*! /*!
* @brief Weapon damage is the contribution the weapon's damage rating * @brief Weapon damage is the contribution the weapon's damage rating
@ -135,7 +132,7 @@ namespace Sapphire::Math
static float calcHealBaseOnPotency( 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 > calcAutoAttackDamage( const Sapphire::Entity::Chara& chara, uint32_t ptc );
static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, Common::AttackType attackType, uint32_t ptc, float wepDmg ); static std::pair< float, Common::ActionHitSeverityType > calcActionDamage( const Sapphire::Entity::Chara& chara, Common::AttackType attackType, uint32_t ptc, float wepDmg );