1
Fork 0
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:
collett 2020-04-12 19:26:58 +09:00
parent 3c3238ae46
commit 058313e230
8 changed files with 193 additions and 109 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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