mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-25 19:17:45 +00:00
more sam stuff
This commit is contained in:
parent
3c3238ae46
commit
058313e230
8 changed files with 193 additions and 109 deletions
|
@ -587,10 +587,12 @@ namespace Sapphire::Common
|
|||
// AetherflowStack = 30,
|
||||
// Status = 32,
|
||||
SAMKenki = 39,
|
||||
SAMSen = 40,
|
||||
PLDGauge = 41,
|
||||
GNBAmmo = 55,
|
||||
WHMBloodLily = 56,
|
||||
WHMLily = 57,
|
||||
SAMMeditation = 63,
|
||||
// RDMGaugeBoth = 74,
|
||||
//// RDMGaugeBlack = 75, // not right?
|
||||
// DRGGauge3Eyes = 76,
|
||||
|
@ -1258,7 +1260,7 @@ namespace Sapphire::Common
|
|||
uint8_t unused2;
|
||||
uint8_t kenki;
|
||||
uint8_t meditationStacks;
|
||||
SamSen senFlag;
|
||||
SamSen sen;
|
||||
} sam;
|
||||
struct
|
||||
{
|
||||
|
|
|
@ -85,6 +85,7 @@ bool Action::Action::init()
|
|||
if( actionCategory == Common::ActionCategory::Spell || actionCategory == Common::ActionCategory::Weaponskill )
|
||||
{
|
||||
m_castTimeMs = static_cast< uint32_t >( m_castTimeMs * ( m_pSource->getStatValue( Common::BaseParam::Haste ) / 100.0f ) );
|
||||
m_recastTimeMs = static_cast< uint32_t >( m_recastTimeMs * ( m_pSource->getStatValue( Common::BaseParam::Haste ) / 100.0f ) );
|
||||
}
|
||||
|
||||
m_cooldownGroup = m_actionData->cooldownGroup;
|
||||
|
@ -478,6 +479,11 @@ void Action::Action::buildEffects()
|
|||
|
||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||
|
||||
for( const auto& statusIt : m_pSource->getStatusEffectMap() )
|
||||
{
|
||||
statusIt.second->onActionExecute( this );
|
||||
}
|
||||
|
||||
scriptMgr.onExecute( *this );
|
||||
|
||||
if( isInterrupted() )
|
||||
|
@ -999,6 +1005,28 @@ bool Action::Action::primaryCostCheck( bool subtractCosts )
|
|||
return false;
|
||||
}
|
||||
|
||||
case Common::ActionPrimaryCostType::SAMSen:
|
||||
{
|
||||
auto pPlayer = m_pSource->getAsPlayer();
|
||||
if( pPlayer )
|
||||
{
|
||||
// trust the client and assume the action is correct, you can cheat this by performing one sen midare :)
|
||||
if( pPlayer->gaugeSamHasAnySen() )
|
||||
{
|
||||
if( subtractCosts )
|
||||
pPlayer->gaugeSamSetSen( Common::SamSen::None );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
case Common::ActionPrimaryCostType::SAMMeditation:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// free casts, likely just pure ogcds
|
||||
case Common::ActionPrimaryCostType::None:
|
||||
{
|
||||
|
|
|
@ -666,7 +666,7 @@ void Sapphire::Entity::Chara::sendStatusEffectUpdate()
|
|||
sendToInRangeSet( statusEffectList, true );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Chara::sendEffectResultToUpdateShieldValue()
|
||||
void Sapphire::Entity::Chara::sendShieldUpdate()
|
||||
{
|
||||
auto pPacket = makeZonePacket< FFXIVIpcEffectResult >( getId() );
|
||||
|
||||
|
@ -730,7 +730,7 @@ std::pair< uint8_t, Sapphire::StatusEffect::StatusEffectPtr > Sapphire::Entity::
|
|||
{
|
||||
for( auto effectIt : m_statusEffectMap )
|
||||
{
|
||||
if( effectIt.second->getId() == id )
|
||||
if( effectIt.second->getId() == id && !effectIt.second->isMarkedToRemove() )
|
||||
{
|
||||
return std::make_pair( effectIt.first, effectIt.second );
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ float Sapphire::Entity::Chara::applyShieldProtection( float damage )
|
|||
}
|
||||
|
||||
if( shieldChanged )
|
||||
sendEffectResultToUpdateShieldValue();
|
||||
sendShieldUpdate();
|
||||
|
||||
return remainingDamage;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace Sapphire::Entity
|
|||
|
||||
void sendStatusEffectUpdate();
|
||||
|
||||
void sendEffectResultToUpdateShieldValue();
|
||||
void sendShieldUpdate();
|
||||
|
||||
/*! return a const pointer to the look array */
|
||||
const uint8_t* getLookArray() const;
|
||||
|
|
|
@ -2462,3 +2462,38 @@ uint8_t Sapphire::Entity::Player::gaugeSamGetKenki()
|
|||
{
|
||||
return m_gauge.sam.kenki;
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::gaugeSamSetSen( Sapphire::Common::SamSen type, bool value )
|
||||
{
|
||||
auto sen = static_cast< uint8_t >( type );
|
||||
auto current = static_cast< uint8_t >( gaugeSamGetSenRaw() );
|
||||
if( value )
|
||||
current |= sen;
|
||||
else
|
||||
current &= ~sen;
|
||||
gaugeSamSetSen( static_cast< Sapphire::Common::SamSen >( current ) );
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::gaugeSamSetSen( Sapphire::Common::SamSen value )
|
||||
{
|
||||
assert( value >= 0 && value <= 7 );
|
||||
auto oldValue = gaugeSamGetSenRaw();
|
||||
m_gauge.sam.sen = value;
|
||||
if( oldValue != value )
|
||||
sendActorGauge();
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::gaugeSamGetSen( Sapphire::Common::SamSen type )
|
||||
{
|
||||
return ( static_cast< uint8_t >( m_gauge.sam.sen ) & static_cast< uint8_t >( type ) ) > 0;
|
||||
}
|
||||
|
||||
Sapphire::Common::SamSen Sapphire::Entity::Player::gaugeSamGetSenRaw()
|
||||
{
|
||||
return m_gauge.sam.sen;
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::gaugeSamHasAnySen()
|
||||
{
|
||||
return static_cast< uint8_t >( m_gauge.sam.sen ) > 0;
|
||||
}
|
||||
|
|
|
@ -1008,6 +1008,11 @@ namespace Sapphire::Entity
|
|||
|
||||
void gaugeSamSetKenki( uint8_t value );
|
||||
uint8_t gaugeSamGetKenki();
|
||||
void gaugeSamSetSen( Common::SamSen type, bool value );
|
||||
void gaugeSamSetSen( Common::SamSen value );
|
||||
bool gaugeSamGetSen( Common::SamSen type );
|
||||
Common::SamSen gaugeSamGetSenRaw();
|
||||
bool gaugeSamHasAnySen();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -294,116 +294,35 @@ void Sapphire::StatusEffect::StatusEffect::replaceEffectEntry( Sapphire::World::
|
|||
void Sapphire::StatusEffect::StatusEffect::onBeforeActionStart( Sapphire::World::Action::Action* action )
|
||||
{
|
||||
// todo: add script function for this if needed
|
||||
//auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
|
||||
//pScriptMgr->onBeforeActionStart( m_targetActor, *this );
|
||||
|
||||
auto checkAction1 = []( Sapphire::World::Action::Action* action, Sapphire::World::Action::StatusEffectEntry& effectEntry )
|
||||
{
|
||||
// value1: remaining uses if >= 0
|
||||
// value2-4: affected action ids if value2 > 0, otherwise value3 is actionCategory filter (4 bytes for 4 categories)
|
||||
if( effectEntry.effectValue1 == 0 )
|
||||
return false;
|
||||
|
||||
if( effectEntry.effectValue2 != 0 )
|
||||
{
|
||||
if( action->getId() != effectEntry.effectValue2 &&
|
||||
action->getId() != effectEntry.effectValue3 &&
|
||||
action->getId() != effectEntry.effectValue4 )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( effectEntry.effectValue3 != 0 )
|
||||
{
|
||||
auto ac = action->getActionData()->actionCategory;
|
||||
uint8_t f1 = static_cast< uint8_t >( effectEntry.effectValue3 );
|
||||
uint8_t f2 = static_cast< uint8_t >( effectEntry.effectValue3 >> 8 );
|
||||
uint8_t f3 = static_cast< uint8_t >( effectEntry.effectValue3 >> 16 );
|
||||
uint8_t f4 = static_cast< uint8_t >( effectEntry.effectValue3 >> 24 );
|
||||
bool passed = false;
|
||||
if( f1 != 0 && ac == f1 )
|
||||
passed = true;
|
||||
else if ( f2 != 0 && ac == f2 )
|
||||
passed = true;
|
||||
else if ( f3 != 0 && ac == f3 )
|
||||
passed = true;
|
||||
else if ( f4 != 0 && ac == f4 )
|
||||
passed = true;
|
||||
if( !passed )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
switch( static_cast< Common::StatusEffectType >( m_effectEntry.effectType ) )
|
||||
{
|
||||
case Common::StatusEffectType::InstantCast:
|
||||
{
|
||||
if( action->hasCastTime() && checkAction1( action, m_effectEntry ) )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 > 0 )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 == getStacks() )
|
||||
{
|
||||
// if stacks equal to remaining uses, assume it is synced
|
||||
setStacks( getStacks() - 1 );
|
||||
m_targetActor->sendStatusEffectUpdate();
|
||||
}
|
||||
m_effectEntry.effectValue1--;
|
||||
if( m_effectEntry.effectValue1 == 0 )
|
||||
{
|
||||
markToRemove();
|
||||
}
|
||||
action->setCastTime( 0 );
|
||||
}
|
||||
}
|
||||
if( action->hasCastTime() && checkActionBoostType1( action ) )
|
||||
action->setCastTime( 0 );
|
||||
break;
|
||||
}
|
||||
case Common::StatusEffectType::AlwaysCombo:
|
||||
{
|
||||
if( checkAction1( action, m_effectEntry ) )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 > 0 )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 == getStacks() )
|
||||
{
|
||||
// if stacks equal to remaining uses, assume it is synced
|
||||
setStacks( getStacks() - 1 );
|
||||
m_targetActor->sendStatusEffectUpdate();
|
||||
}
|
||||
m_effectEntry.effectValue1--;
|
||||
if( m_effectEntry.effectValue1 == 0 )
|
||||
{
|
||||
markToRemove();
|
||||
}
|
||||
action->setAlwaysCombo();
|
||||
}
|
||||
}
|
||||
if( checkActionBoostType1( action ) )
|
||||
action->setAlwaysCombo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sapphire::StatusEffect::StatusEffect::onActionExecute( Sapphire::World::Action::Action* action )
|
||||
{
|
||||
// todo: add script function for this if needed
|
||||
switch( static_cast< Common::StatusEffectType >( m_effectEntry.effectType ) )
|
||||
{
|
||||
case Common::StatusEffectType::PotencyMultiplier:
|
||||
{
|
||||
if( checkAction1( action, m_effectEntry ) )
|
||||
if( checkActionBoostType1( action ) )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 > 0 )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 == getStacks() )
|
||||
{
|
||||
// if stacks equal to remaining uses, assume it is synced
|
||||
setStacks( getStacks() - 1 );
|
||||
m_targetActor->sendStatusEffectUpdate();
|
||||
}
|
||||
m_effectEntry.effectValue1--;
|
||||
if( m_effectEntry.effectValue1 == 0 )
|
||||
{
|
||||
markToRemove();
|
||||
}
|
||||
action->getActionEntry().damagePotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
action->getActionEntry().damageComboPotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
action->getActionEntry().damageDirectionalPotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
}
|
||||
action->getActionEntry().damagePotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
action->getActionEntry().damageComboPotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
action->getActionEntry().damageDirectionalPotency *= 1.0 + ( m_effectEntry.effectValue4 / 100.0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -442,18 +361,108 @@ bool Sapphire::StatusEffect::StatusEffect::onActionHitTarget( World::Action::Act
|
|||
{
|
||||
if( victimCounter == 1 && action->isGCD() )
|
||||
{
|
||||
if( m_effectEntry.effectValue2 != 0 )
|
||||
if( checkActionBoostType2( action ) )
|
||||
{
|
||||
if( action->getId() != m_effectEntry.effectValue2 &&
|
||||
action->getId() != m_effectEntry.effectValue3 &&
|
||||
action->getId() != m_effectEntry.effectValue4 )
|
||||
break;
|
||||
float restored = 0.01f * m_targetActor->getMaxMp() * m_effectEntry.effectValue1;
|
||||
action->getEffectbuilder()->restoreMP( victim, m_targetActor, static_cast< uint32_t >( restored ), Sapphire::Common::ActionEffectResultFlag::EffectOnSource );
|
||||
}
|
||||
float restored = 0.01f * m_targetActor->getMaxMp() * m_effectEntry.effectValue1;
|
||||
action->getEffectbuilder()->restoreMP( victim, m_targetActor, static_cast< uint32_t >( restored ), Sapphire::Common::ActionEffectResultFlag::EffectOnSource );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sapphire::StatusEffect::StatusEffect::checkActionBoostType1( World::Action::Action* action )
|
||||
{
|
||||
// value1: remaining uses if >= 0, infinite uses if < 0 and can be custom data
|
||||
// value2-4: affected action ids if value2 > 0,
|
||||
// otherwise value3 is actionCategory filter (4 bytes for 4 categories) and value4 is custom data
|
||||
if( m_effectEntry.effectValue1 == 0 )
|
||||
return false;
|
||||
|
||||
if( m_effectEntry.effectValue2 != 0 )
|
||||
{
|
||||
if( action->getId() != m_effectEntry.effectValue2 &&
|
||||
action->getId() != m_effectEntry.effectValue3 &&
|
||||
action->getId() != m_effectEntry.effectValue4 )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_effectEntry.effectValue3 != 0 )
|
||||
{
|
||||
auto ac = action->getActionData()->actionCategory;
|
||||
uint8_t f1 = static_cast< uint8_t >( m_effectEntry.effectValue3 );
|
||||
uint8_t f2 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 8 );
|
||||
uint8_t f3 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 16 );
|
||||
uint8_t f4 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 24 );
|
||||
bool passed = false;
|
||||
if( f1 != 0 && ac == f1 )
|
||||
passed = true;
|
||||
else if ( f2 != 0 && ac == f2 )
|
||||
passed = true;
|
||||
else if ( f3 != 0 && ac == f3 )
|
||||
passed = true;
|
||||
else if ( f4 != 0 && ac == f4 )
|
||||
passed = true;
|
||||
if( !passed )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_effectEntry.effectValue1 > 0 )
|
||||
{
|
||||
if( m_effectEntry.effectValue1 == getStacks() )
|
||||
{
|
||||
// if stacks equal to remaining uses, assume it is synced
|
||||
setStacks( getStacks() - 1 );
|
||||
m_targetActor->sendStatusEffectUpdate();
|
||||
}
|
||||
m_effectEntry.effectValue1--;
|
||||
if( m_effectEntry.effectValue1 == 0 )
|
||||
{
|
||||
markToRemove();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sapphire::StatusEffect::StatusEffect::checkActionBoostType2( World::Action::Action* action )
|
||||
{
|
||||
// value1: custom data
|
||||
// value2-4: affected action ids if value2 > 0,
|
||||
// otherwise value3 is actionCategory filter (4 bytes for 4 categories) and value4 is custom data
|
||||
if( m_effectEntry.effectValue2 != 0 )
|
||||
{
|
||||
if( action->getId() != m_effectEntry.effectValue2 &&
|
||||
action->getId() != m_effectEntry.effectValue3 &&
|
||||
action->getId() != m_effectEntry.effectValue4 )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_effectEntry.effectValue3 != 0 )
|
||||
{
|
||||
auto ac = action->getActionData()->actionCategory;
|
||||
uint8_t f1 = static_cast< uint8_t >( m_effectEntry.effectValue3 );
|
||||
uint8_t f2 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 8 );
|
||||
uint8_t f3 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 16 );
|
||||
uint8_t f4 = static_cast< uint8_t >( m_effectEntry.effectValue3 >> 24 );
|
||||
bool passed = false;
|
||||
if( f1 != 0 && ac == f1 )
|
||||
passed = true;
|
||||
else if ( f2 != 0 && ac == f2 )
|
||||
passed = true;
|
||||
else if ( f3 != 0 && ac == f3 )
|
||||
passed = true;
|
||||
else if ( f4 != 0 && ac == f4 )
|
||||
passed = true;
|
||||
if( !passed )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -21,6 +21,8 @@ public:
|
|||
|
||||
void onBeforeActionStart( World::Action::Action* action );
|
||||
|
||||
void onActionExecute( World::Action::Action* action );
|
||||
|
||||
bool onActionHitTarget( World::Action::Action* action, Entity::CharaPtr victim, int victimCounter );
|
||||
|
||||
void applyStatus();
|
||||
|
@ -69,6 +71,9 @@ public:
|
|||
void refresh( Sapphire::World::Action::StatusEffectEntry newEntry );
|
||||
|
||||
private:
|
||||
bool checkActionBoostType1( Sapphire::World::Action::Action* action ); // see cpp for more info
|
||||
bool checkActionBoostType2( Sapphire::World::Action::Action* action ); // see cpp for more info
|
||||
|
||||
uint32_t m_id;
|
||||
Entity::CharaPtr m_sourceActor;
|
||||
Entity::CharaPtr m_targetActor;
|
||||
|
|
Loading…
Add table
Reference in a new issue