mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-25 11:07:45 +00:00
inner release, inner chaos, chaotic cyclone
This commit is contained in:
parent
08a0556b36
commit
deebcd76c3
16 changed files with 998 additions and 877 deletions
|
@ -1044,7 +1044,6 @@ namespace Sapphire::Common
|
|||
MPRestore = 11,
|
||||
Haste = 12,
|
||||
InstantCast = 13,
|
||||
NoCostCast = 14,
|
||||
};
|
||||
|
||||
enum class ActionTypeFilter : int32_t
|
||||
|
@ -1069,6 +1068,23 @@ namespace Sapphire::Common
|
|||
AbsorbHP = 2,
|
||||
};
|
||||
|
||||
enum ActionBonusEffect : uint8_t
|
||||
{
|
||||
NoBonus = 0,
|
||||
CritBonus = 1,
|
||||
DHBonus = 2,
|
||||
GainMPPercentage = 4,
|
||||
GainJobResource = 8,
|
||||
SelfHeal = 16,
|
||||
};
|
||||
|
||||
enum ActionBonusEffectRequirement : uint8_t
|
||||
{
|
||||
NoRequirement = 0,
|
||||
RequireCorrectCombo = 1,
|
||||
RequireCorrectPositional = 2,
|
||||
};
|
||||
|
||||
using PlayerStateFlagList = std::vector< PlayerStateFlag >;
|
||||
|
||||
}
|
||||
|
|
35
src/scripts/action/war/ActionChaoticCyclone16463.cpp
Normal file
35
src/scripts/action/war/ActionChaoticCyclone16463.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
using namespace Sapphire::StatusEffect;
|
||||
|
||||
const uint16_t STATUS_ID_NASCENT_CHAOS = 1897;
|
||||
|
||||
class ActionChaoticCyclone16463 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionChaoticCyclone16463() :
|
||||
ScriptAPI::ActionScript( 16463 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
auto effectEntry = action.getSourceChara()->getStatusEffectById( STATUS_ID_NASCENT_CHAOS );
|
||||
if( effectEntry.second )
|
||||
{
|
||||
action.getSourceChara()->removeStatusEffect( effectEntry.first );
|
||||
}
|
||||
else
|
||||
{
|
||||
action.disableGenericHandler();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionChaoticCyclone16463 );
|
|
@ -28,7 +28,7 @@ public:
|
|||
if( pPlayer->getLevel() >= 72 )
|
||||
{
|
||||
auto pEffect = action.createStatusEffect( STATUS_ID_NASCENT_CHAOS, action.getSourceChara(), action.getSourceChara(), 30000, 3000 );
|
||||
action.getEffectbuilder()->applyStatusEffect( action.getSourceChara(), action.getSourceChara(), pEffect );
|
||||
action.getEffectbuilder()->applyStatusEffect( action.getSourceChara(), action.getSourceChara(), pEffect, 0 );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
35
src/scripts/action/war/ActionInnerChaos16465.cpp
Normal file
35
src/scripts/action/war/ActionInnerChaos16465.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
using namespace Sapphire::StatusEffect;
|
||||
|
||||
const uint16_t STATUS_ID_NASCENT_CHAOS = 1897;
|
||||
|
||||
class ActionInnerChaos16465 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionInnerChaos16465() :
|
||||
ScriptAPI::ActionScript( 16465 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
auto effectEntry = action.getSourceChara()->getStatusEffectById( STATUS_ID_NASCENT_CHAOS );
|
||||
if( effectEntry.second )
|
||||
{
|
||||
action.getSourceChara()->removeStatusEffect( effectEntry.first );
|
||||
}
|
||||
else
|
||||
{
|
||||
action.disableGenericHandler();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionInnerChaos16465 );
|
38
src/scripts/action/war/ActionInnerRelease7389.cpp
Normal file
38
src/scripts/action/war/ActionInnerRelease7389.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
using namespace Sapphire::StatusEffect;
|
||||
|
||||
const uint16_t STATUS_ID_INNER_RELEASE = 1177;
|
||||
|
||||
class ActionInnerRelease7389 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionInnerRelease7389() :
|
||||
ScriptAPI::ActionScript( 7389 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
auto pSource = action.getSourceChara();
|
||||
assert( pSource );
|
||||
|
||||
World::Action::StatusEffectEntry effectEntry;
|
||||
effectEntry.effectType = static_cast< uint32_t >( Common::StatusEffectType::CritDHRateBonus );
|
||||
effectEntry.effectValue1 = static_cast< int32_t >( Common::ActionTypeFilter::Physical );
|
||||
effectEntry.effectValue2 = 100;
|
||||
effectEntry.effectValue3 = 100;
|
||||
auto pNewEffect = action.createStatusEffect( STATUS_ID_INNER_RELEASE, action.getSourceChara(), pSource, 10000, 3000 );
|
||||
pNewEffect->replaceEffectEntry( effectEntry );
|
||||
pNewEffect->setParam( 65436 );
|
||||
action.getEffectbuilder()->applyStatusEffect( pSource, action.getSourceChara(), pNewEffect, 0 );
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionInnerRelease7389 );
|
|
@ -1,31 +0,0 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
|
||||
class ActionMaim37 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionMaim37() :
|
||||
ScriptAPI::ActionScript( 37 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
if( !action.isCorrectCombo() )
|
||||
return;
|
||||
|
||||
auto pPlayer = action.getSourceChara()->getAsPlayer();
|
||||
assert( pPlayer );
|
||||
uint8_t ib = pPlayer->gaugeWarGetIb();
|
||||
ib = std::min( 100, ib + 10 );
|
||||
pPlayer->gaugeWarSetIb( ib );
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionMaim37 );
|
|
@ -1,31 +0,0 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
|
||||
class ActionStormsEye45 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionStormsEye45() :
|
||||
ScriptAPI::ActionScript( 45 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
if( !action.isCorrectCombo() )
|
||||
return;
|
||||
|
||||
auto pPlayer = action.getSourceChara()->getAsPlayer();
|
||||
assert( pPlayer );
|
||||
uint8_t ib = pPlayer->gaugeWarGetIb();
|
||||
ib = std::min( 100, ib + 10 );
|
||||
pPlayer->gaugeWarSetIb( ib );
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionStormsEye45 );
|
|
@ -1,31 +0,0 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include <ScriptObject.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Action/Action.h>
|
||||
#include <Math/CalcStats.h>
|
||||
|
||||
using namespace Sapphire;
|
||||
|
||||
class ActionStormsPath42 :
|
||||
public ScriptAPI::ActionScript
|
||||
{
|
||||
public:
|
||||
ActionStormsPath42() :
|
||||
ScriptAPI::ActionScript( 42 )
|
||||
{
|
||||
}
|
||||
|
||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||
{
|
||||
if( !action.isCorrectCombo() )
|
||||
return;
|
||||
|
||||
auto pPlayer = action.getSourceChara()->getAsPlayer();
|
||||
assert( pPlayer );
|
||||
uint8_t ib = pPlayer->gaugeWarGetIb();
|
||||
ib = std::min( 100, ib + 20 );
|
||||
pPlayer->gaugeWarSetIb( ib );
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SCRIPT( ActionStormsPath42 );
|
|
@ -12,6 +12,8 @@
|
|||
#include "Actor/Player.h"
|
||||
#include "Actor/BNpc.h"
|
||||
|
||||
#include "Action/ActionLut.h"
|
||||
|
||||
#include "Territory/Territory.h"
|
||||
|
||||
#include <Network/CommonActorControl.h>
|
||||
|
@ -119,6 +121,18 @@ bool Action::Action::init()
|
|||
m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( m_actionData->primaryCostType );
|
||||
m_primaryCost = m_actionData->primaryCostValue;
|
||||
|
||||
if( m_primaryCostType != Common::ActionPrimaryCostType::None )
|
||||
{
|
||||
for( auto const& entry : m_pSource->getStatusEffectMap() )
|
||||
{
|
||||
if( entry.second->getParam() == 65436 ) // todo: decode this shit and figure out exact percentage to apply to primary cost, this magic number is 0%
|
||||
{
|
||||
setPrimaryCost( Common::ActionPrimaryCostType::None, 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if( !m_actionData->targetArea )
|
||||
{
|
||||
// override pos to target position
|
||||
|
@ -407,12 +421,12 @@ std::pair< uint32_t, Common::ActionHitSeverityType > Action::Action::calcDamage(
|
|||
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 ) );
|
||||
return Math::CalcStats::calcActionDamage( this, *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 )
|
||||
{
|
||||
return Math::CalcStats::calcActionHealing( *m_pSource, static_cast< Common::ActionCategory >( m_actionData->actionCategory ), potency, Math::CalcStats::getWeaponDamage( m_pSource ) );
|
||||
return Math::CalcStats::calcActionHealing( this, *m_pSource, static_cast< Common::ActionCategory >( m_actionData->actionCategory ), potency, Math::CalcStats::getWeaponDamage( m_pSource ) );
|
||||
}
|
||||
|
||||
void Action::Action::buildEffects()
|
||||
|
@ -432,18 +446,18 @@ void Action::Action::buildEffects()
|
|||
}
|
||||
|
||||
// we have a valid lut entry
|
||||
if( auto player = getSourceChara()->getAsPlayer() )
|
||||
auto player = getSourceChara()->getAsPlayer();
|
||||
if( player )
|
||||
{
|
||||
player->sendDebug( "type: {}, dpot: {} (dcpot: {}, ddpot: {}), hpot: {}, shpot: {}, ss: {}, ts: {}, gmp: {}",
|
||||
player->sendDebug( "type: {}, dpot: {} (dcpot: {}, ddpot: {}), hpot: {}, ss: {}, ts: {}, bonus: {}, breq: {}, bdata: {}",
|
||||
m_actionData->attackType,
|
||||
m_lutEntry.damagePotency, m_lutEntry.damageComboPotency, m_lutEntry.damageDirectionalPotency,
|
||||
m_lutEntry.healPotency, m_lutEntry.selfHealPotency,
|
||||
m_lutEntry.selfStatus, m_lutEntry.targetStatus,
|
||||
m_lutEntry.gainMPPercentage );
|
||||
m_lutEntry.healPotency, m_lutEntry.selfStatus, m_lutEntry.targetStatus,
|
||||
m_lutEntry.bonusEffect, m_lutEntry.bonusRequirement, m_lutEntry.bonusDataUInt32 );
|
||||
}
|
||||
|
||||
// when aoe, these effects are in the target whatever is hit first
|
||||
bool shouldRestoreMP = true;
|
||||
bool shouldGainPower = true;
|
||||
bool shouldApplyComboSucceedEffect = true;
|
||||
|
||||
for( auto& actor : m_hitActors )
|
||||
|
@ -499,23 +513,40 @@ void Action::Action::buildEffects()
|
|||
m_effectBuilder->heal( actor, actor, heal.first, heal.second );
|
||||
}
|
||||
|
||||
if( m_lutEntry.selfHealPotency > 0 ) // actions with self heal
|
||||
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::SelfHeal )
|
||||
{
|
||||
if( !isComboAction() || isCorrectCombo() )
|
||||
if( checkActionBonusRequirement() )
|
||||
{
|
||||
auto heal = calcHealing( m_lutEntry.selfHealPotency );
|
||||
auto heal = calcHealing( m_lutEntry.bonusDataUInt16L );
|
||||
heal.first = Math::CalcStats::applyHealingReceiveMultiplier( *m_pSource, heal.first );
|
||||
m_effectBuilder->heal( actor, m_pSource, heal.first, heal.second, Common::ActionEffectResultFlag::EffectOnSource );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_lutEntry.gainMPPercentage > 0 && shouldRestoreMP )
|
||||
if( shouldGainPower )
|
||||
{
|
||||
if( !isComboAction() || isCorrectCombo() )
|
||||
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainMPPercentage )
|
||||
{
|
||||
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.gainMPPercentage / 100, Common::ActionEffectResultFlag::EffectOnSource );
|
||||
shouldRestoreMP = false;
|
||||
if( checkActionBonusRequirement() )
|
||||
m_effectBuilder->restoreMP( actor, m_pSource, m_pSource->getMaxMp() * m_lutEntry.bonusDataUInt16L / 100, Common::ActionEffectResultFlag::EffectOnSource );
|
||||
}
|
||||
|
||||
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobResource )
|
||||
{
|
||||
if( checkActionBonusRequirement() )
|
||||
{
|
||||
switch( static_cast< Common::ClassJob >( m_lutEntry.bonusDataByte3 ) )
|
||||
{
|
||||
case Common::ClassJob::Marauder:
|
||||
case Common::ClassJob::Warrior:
|
||||
{
|
||||
player->gaugeWarSetIb( std::min( 100, player->gaugeWarGetIb() + m_lutEntry.bonusDataByte4 ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
shouldGainPower = false;
|
||||
}
|
||||
|
||||
if( m_lutEntry.targetStatus != 0 )
|
||||
|
@ -831,8 +862,8 @@ Sapphire::Entity::CharaPtr Action::Action::getHitChara()
|
|||
|
||||
bool Action::Action::hasValidLutEntry() const
|
||||
{
|
||||
return m_lutEntry.damagePotency != 0 || m_lutEntry.healPotency != 0 || m_lutEntry.selfHealPotency != 0 || m_lutEntry.selfStatus != 0 ||
|
||||
m_lutEntry.targetStatus != 0 || m_lutEntry.gainMPPercentage != 0;
|
||||
return m_lutEntry.damagePotency != 0 || m_lutEntry.healPotency != 0 || m_lutEntry.selfStatus != 0 ||
|
||||
m_lutEntry.targetStatus != 0 || m_lutEntry.bonusEffect != 0;
|
||||
}
|
||||
|
||||
float Action::Action::getAnimationLock()
|
||||
|
@ -902,6 +933,24 @@ void Action::Action::setPrimaryCost( Common::ActionPrimaryCostType type, uint16_
|
|||
m_primaryCost = cost;
|
||||
}
|
||||
|
||||
bool Action::Action::checkActionBonusRequirement()
|
||||
{
|
||||
if( !m_pSource->isPlayer() )
|
||||
return false;
|
||||
|
||||
if( m_lutEntry.bonusRequirement & Common::ActionBonusEffectRequirement::RequireCorrectCombo )
|
||||
{
|
||||
if( !isCorrectCombo() )
|
||||
return false;
|
||||
}
|
||||
if( m_lutEntry.bonusRequirement & Common::ActionBonusEffectRequirement::RequireCorrectPositional )
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Sapphire::StatusEffect::StatusEffectPtr Action::Action::createStatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, uint32_t duration, uint32_t tickRate )
|
||||
{
|
||||
// workaround to framework access issue in action script
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace Sapphire::World::Action
|
|||
|
||||
void disableGenericHandler();
|
||||
|
||||
bool checkActionBonusRequirement();
|
||||
|
||||
StatusEffect::StatusEffectPtr createStatusEffect( uint32_t id, Entity::CharaPtr sourceActor, Entity::CharaPtr targetActor, uint32_t duration, uint32_t tickRate );
|
||||
|
||||
/*!
|
||||
|
|
|
@ -13,8 +13,8 @@ bool ActionLut::validEntryExists( uint16_t actionId )
|
|||
const auto& entry = it->second;
|
||||
|
||||
// if all of these fields are 0, it's not 'valid' due to parse error or no useful data
|
||||
return entry.damagePotency != 0 || entry.healPotency != 0 || entry.selfHealPotency != 0 || entry.selfStatus != 0 ||
|
||||
entry.targetStatus != 0 || entry.gainMPPercentage != 0;
|
||||
return entry.damagePotency != 0 || entry.healPotency != 0 || entry.selfStatus != 0 ||
|
||||
entry.targetStatus != 0 || entry.bonusEffect != 0;
|
||||
}
|
||||
|
||||
const ActionEntry& ActionLut::getEntry( uint16_t actionId )
|
||||
|
|
|
@ -11,14 +11,30 @@ namespace Sapphire::World::Action
|
|||
uint16_t damageComboPotency;
|
||||
uint16_t damageDirectionalPotency;
|
||||
uint16_t healPotency;
|
||||
uint16_t selfHealPotency;
|
||||
uint16_t selfStatus;
|
||||
uint32_t selfStatusDuration;
|
||||
uint16_t selfStatusParam;
|
||||
uint16_t targetStatus;
|
||||
uint32_t targetStatusDuration;
|
||||
uint16_t targetStatusParam;
|
||||
uint16_t gainMPPercentage;
|
||||
uint8_t bonusEffect;
|
||||
uint8_t bonusRequirement;
|
||||
union
|
||||
{
|
||||
uint32_t bonusDataUInt32;
|
||||
struct
|
||||
{
|
||||
uint16_t bonusDataUInt16L;
|
||||
uint16_t bonusDataUInt16H;
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t bonusDataByte1;
|
||||
uint8_t bonusDataByte2;
|
||||
uint8_t bonusDataByte3;
|
||||
uint8_t bonusDataByte4;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct StatusEffectEntry
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -602,18 +602,44 @@ float CalcStats::calcHealBaseOnPotency( const Sapphire::Entity::Chara& chara, ui
|
|||
return factor;
|
||||
}
|
||||
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( const Sapphire::Entity::Chara& chara, Sapphire::Common::AttackType attackType, uint32_t ptc, float wepDmg )
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionDamage( Sapphire::World::Action::Action* pAction, const Sapphire::Entity::Chara& chara, Sapphire::Common::AttackType attackType, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
auto factor = calcDamageBaseOnPotency( chara, ptc, wepDmg );
|
||||
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalDamage;
|
||||
|
||||
if( criticalHitProbability( chara, Common::CritDHBonusFilter::Damage ) > getRandomNumber0To99() )
|
||||
auto critProb = criticalHitProbability( chara, Common::CritDHBonusFilter::Damage );
|
||||
if( pAction )
|
||||
{
|
||||
auto lutEntry = pAction->getActionEntry();
|
||||
if( lutEntry.bonusEffect & Common::ActionBonusEffect::CritBonus )
|
||||
{
|
||||
if( pAction->checkActionBonusRequirement() )
|
||||
{
|
||||
critProb += lutEntry.bonusDataUInt16L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( critProb > getRandomNumber0To99() )
|
||||
{
|
||||
factor *= criticalHitBonus( chara );
|
||||
hitType = Sapphire::Common::ActionHitSeverityType::CritDamage;
|
||||
}
|
||||
|
||||
if( directHitProbability( chara, Common::CritDHBonusFilter::Damage ) > getRandomNumber0To99() )
|
||||
auto dhProb = directHitProbability( chara, Common::CritDHBonusFilter::Damage );
|
||||
if( pAction )
|
||||
{
|
||||
auto lutEntry = pAction->getActionEntry();
|
||||
if( lutEntry.bonusEffect & Common::ActionBonusEffect::DHBonus )
|
||||
{
|
||||
if( pAction->checkActionBonusRequirement() )
|
||||
{
|
||||
dhProb += lutEntry.bonusDataUInt16L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( dhProb > getRandomNumber0To99() )
|
||||
{
|
||||
factor *= 1.25f;
|
||||
hitType = hitType == Sapphire::Common::ActionHitSeverityType::CritDamage ?
|
||||
|
@ -684,12 +710,25 @@ float CalcStats::applyHealingReceiveMultiplier( const Sapphire::Entity::Chara& c
|
|||
return heal;
|
||||
}
|
||||
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionHealing( const Sapphire::Entity::Chara& chara, Sapphire::Common::ActionCategory actionCategory, uint32_t ptc, float wepDmg )
|
||||
std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActionHealing( Sapphire::World::Action::Action* pAction, const Sapphire::Entity::Chara& chara, Sapphire::Common::ActionCategory actionCategory, uint32_t ptc, float wepDmg )
|
||||
{
|
||||
auto factor = calcHealBaseOnPotency( chara, ptc, wepDmg );
|
||||
Sapphire::Common::ActionHitSeverityType hitType = Sapphire::Common::ActionHitSeverityType::NormalHeal;
|
||||
|
||||
if( criticalHitProbability( chara, Common::CritDHBonusFilter::Heal ) > getRandomNumber0To99() )
|
||||
auto critProb = criticalHitProbability( chara, Common::CritDHBonusFilter::Heal );
|
||||
if( pAction )
|
||||
{
|
||||
auto lutEntry = pAction->getActionEntry();
|
||||
if( lutEntry.bonusEffect & Common::ActionBonusEffect::CritBonus )
|
||||
{
|
||||
if( pAction->checkActionBonusRequirement() )
|
||||
{
|
||||
critProb += lutEntry.bonusDataUInt16L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( critProb > getRandomNumber0To99() )
|
||||
{
|
||||
factor *= criticalHitBonus( chara );
|
||||
hitType = Sapphire::Common::ActionHitSeverityType::CritHeal;
|
||||
|
@ -731,7 +770,7 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcDamag
|
|||
{
|
||||
auto wepDmg = Sapphire::Math::CalcStats::getWeaponDamage( pCharaVictim );
|
||||
// any magical reflect damage exists?
|
||||
auto damage = Sapphire::Math::CalcStats::calcActionDamage( *pCharaVictim, Common::AttackType::Physical, effectEntry.effectValue2, wepDmg );
|
||||
auto damage = Sapphire::Math::CalcStats::calcActionDamage( nullptr, *pCharaVictim, Common::AttackType::Physical, effectEntry.effectValue2, wepDmg );
|
||||
damage.first = Math::CalcStats::applyDamageReceiveMultiplier( *pCharaAttacker, damage.first, Common::AttackType::Physical );
|
||||
|
||||
return damage;
|
||||
|
|
|
@ -134,13 +134,13 @@ namespace Sapphire::Math
|
|||
|
||||
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( World::Action::Action* pAction, const Sapphire::Entity::Chara& chara, Common::AttackType attackType, uint32_t ptc, float wepDmg );
|
||||
|
||||
static float applyDamageReceiveMultiplier( const Sapphire::Entity::Chara& chara, float originalDamage, Common::AttackType attackType );
|
||||
|
||||
static float applyHealingReceiveMultiplier( const Sapphire::Entity::Chara& chara, float originalHeal );
|
||||
|
||||
static std::pair< float, Common::ActionHitSeverityType > calcActionHealing( const Sapphire::Entity::Chara& chara, Sapphire::Common::ActionCategory actionCategory, uint32_t ptc, float wepDmg );
|
||||
static std::pair< float, Common::ActionHitSeverityType > calcActionHealing( World::Action::Action* pAction, const Sapphire::Entity::Chara& chara, Sapphire::Common::ActionCategory actionCategory, uint32_t ptc, float wepDmg );
|
||||
|
||||
static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara );
|
||||
|
||||
|
|
|
@ -297,28 +297,6 @@ void Sapphire::StatusEffect::StatusEffect::onBeforeActionStart( Sapphire::World:
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Common::StatusEffectType::NoCostCast:
|
||||
{
|
||||
// value1: cost type, 0 = all costs, 1 = primary, 2 = secondary
|
||||
// value2-4: affected action ids, or all actions if value2 is 0
|
||||
if( m_effectEntry.effectValue2 != 0 )
|
||||
{
|
||||
if( action->getId() != m_effectEntry.effectValue2 &&
|
||||
action->getId() != m_effectEntry.effectValue3 &&
|
||||
action->getId() != m_effectEntry.effectValue4 )
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_effectEntry.effectValue1 == 0 || m_effectEntry.effectValue1 == 1 )
|
||||
action->setPrimaryCost( Common::ActionPrimaryCostType::None, 0 );
|
||||
|
||||
// secondary cost not implemented yet
|
||||
//if( m_effectEntry.effectValue1 == 0 || m_effectEntry.effectValue1 == 2 )
|
||||
// action->setSecondaryCost();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue