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

implement drk blood and darkside, some war fixes as well

This commit is contained in:
collett 2020-03-15 18:59:07 +09:00
parent 21fffcd353
commit b6068046ac
7 changed files with 196 additions and 60 deletions

View file

@ -583,7 +583,7 @@ namespace Sapphire::Common
TacticsPoints = 5,
StatusEffect = 10,
WARGauge = 22,
// DRKGauge = 25,
DRKGauge = 25,
// AetherflowStack = 30,
// Status = 32,
PLDGauge = 41,
@ -1079,6 +1079,7 @@ namespace Sapphire::Common
GainJobResource = 8,
SelfHeal = 16,
DamageFallOff = 32,
GainJobTimer = 64,
};
enum ActionBonusEffectRequirement : uint8_t
@ -1185,9 +1186,9 @@ namespace Sapphire::Common
struct
{
uint8_t blood;
uint16_t darksideTimeRemaining;
uint16_t darksideTimer;
uint8_t darkArts;
uint16_t shadowTimeRemaining;
uint16_t shadowTimer;
} drk;
struct
{

View file

@ -1,38 +0,0 @@
#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 pEffect = Sapphire::StatusEffect::make_StatusEffect( STATUS_ID_INNER_RELEASE, action.getSourceChara(), pSource, 10000, 3000 );
pEffect->replaceEffectEntry( effectEntry );
pEffect->setParam( 65436 );
action.getEffectbuilder()->applyStatusEffect( pSource, action.getSourceChara(), pEffect, 0 );
}
};
EXPOSE_SCRIPT( ActionInnerRelease7389 );

View file

@ -125,7 +125,30 @@ bool Action::Action::init()
{
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 );
/*
Since the client is displaying correctly without additional data, there should be a "primary primary cost type" defined for each class.
In the case of 65436, on whm, mp cost is removed, on drk, blood cost is removed but mp cost remains.
*/
auto affectedPrimaryCost = Common::ActionPrimaryCostType::MagicPoints;
switch( m_pSource->getClass() )
{
case Common::ClassJob::Marauder:
case Common::ClassJob::Warrior:
{
affectedPrimaryCost = Common::ActionPrimaryCostType::WARGauge;
break;
}
case Common::ClassJob::Darkknight:
{
affectedPrimaryCost = Common::ActionPrimaryCostType::DRKGauge;
break;
}
}
if( m_primaryCostType == affectedPrimaryCost )
{
setPrimaryCost( Common::ActionPrimaryCostType::None, 0 );
}
break;
}
}
@ -612,6 +635,26 @@ void Action::Action::buildEffects()
player->gaugeWarSetIb( std::min( 100, player->gaugeWarGetIb() + m_lutEntry.bonusDataByte4 ) );
break;
}
case Common::ClassJob::Darkknight:
{
player->gaugeDrkSetBlood( std::min( 100, player->gaugeDrkGetBlood() + m_lutEntry.bonusDataByte4 ) );
break;
}
}
}
}
if( m_lutEntry.bonusEffect & Common::ActionBonusEffect::GainJobTimer )
{
if( checkActionBonusRequirement() )
{
switch( static_cast< Common::ClassJob >( m_lutEntry.bonusDataByte3 ) )
{
case Common::ClassJob::Darkknight:
{
player->gaugeDrkSetDarkSideTimer( std::min( 60000, player->gaugeDrkGetDarkSideTimer() + m_lutEntry.bonusDataUInt16L ), true );
break;
}
}
}
}
@ -862,6 +905,23 @@ bool Action::Action::primaryCostCheck( bool subtractCosts )
return false;
}
case Common::ActionPrimaryCostType::DRKGauge:
{
auto pPlayer = m_pSource->getAsPlayer();
if( pPlayer )
{
auto blood = pPlayer->gaugeDrkGetBlood();
if( blood >= m_primaryCost )
{
if( subtractCosts )
pPlayer->gaugeDrkSetBlood( blood - m_primaryCost );
return true;
}
}
return false;
}
// free casts, likely just pure ogcds
case Common::ActionPrimaryCostType::None:
{

View file

@ -225,12 +225,12 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 7387, { 450, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Shake It Off, シェイクオフ
//applies to targets: Shake It Off, シェイクオフ, duration 0, param 0
{ 7388, { 0, 0, 0, 0, 0, 0, 0, 1457, 0, 0, 0, 0, 0 } },
//applies to targets: Shake It Off, シェイクオフ, duration 15000, param 0
{ 7388, { 0, 0, 0, 0, 0, 0, 0, 1457, 15000, 0, 0, 0, 0 } },
//Inner Release, 原初の解放
//comment: status removed need script
{ 7389, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//applies to self: Inner Release, 原初の解放, duration 10000, param 65436
{ 7389, { 0, 0, 0, 0, 1177, 10000, 65436, 0, 0, 0, 0, 0, 0 } },
//Chaotic Cyclone, カオティックサイクロン
//has damage: potency 400, combo potency 0, directional potency 0
@ -271,13 +271,14 @@ ActionLut::Lut ActionLut::m_actionLut =
//Souleater, ソウルイーター
//has damage: potency 100, combo potency 400, directional potency 0
//has heal: potency 300
{ 3632, { 100, 400, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//has bonus effect: 24, 169869612
//bonus effect requirement: RequireCorrectCombo
{ 3632, { 100, 400, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 169869612 } },
//Flood of Darkness, 暗黒の波動
//has damage: potency 250, combo potency 0, directional potency 0
//applies to self: Darkside, 暗黒, duration 30000, param 0
{ 16466, { 250, 0, 0, 0, 751, 30000, 0, 0, 0, 0, 0, 0, 0 } },
//has bonus effect: GainJobTimer, 2127152
{ 16466, { 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 2127152 } },
//Blood Weapon, ブラッドウェポン
//applies to self: Blood Weapon, ブラッドウェポン, duration 10000, param 0
@ -289,8 +290,8 @@ ActionLut::Lut ActionLut::m_actionLut =
//Edge of Darkness, 暗黒の剣
//has damage: potency 350, combo potency 0, directional potency 0
//applies to self: Darkside, 暗黒, duration 30000, param 0
{ 16467, { 350, 0, 0, 0, 751, 30000, 0, 0, 0, 0, 0, 0, 0 } },
//has bonus effect: GainJobTimer, 2127152
{ 16467, { 350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 2127152 } },
//Dark Mind, ダークマインド
//applies to targets: Dark Mind, ダークマインド, duration 10000, param 0
@ -328,8 +329,8 @@ ActionLut::Lut ActionLut::m_actionLut =
{ 7391, { 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Delirium, ブラッドデリリアム
//applies to self: Delirium, ブラッドデリリアム, duration 10000, param 0
{ 7390, { 0, 0, 0, 0, 1972, 10000, 0, 0, 0, 0, 0, 0, 0 } },
//applies to self: Delirium, ブラッドデリリアム, duration 10000, param 65436
{ 7390, { 0, 0, 0, 0, 1972, 10000, 65436, 0, 0, 0, 0, 0, 0 } },
//The Blackest Night, ブラックナイト
//applies to self: Blackest Night, ブラックナイト, duration 0, param 0
@ -343,8 +344,8 @@ ActionLut::Lut ActionLut::m_actionLut =
//Edge of Shadow, 漆黒の剣
//has damage: potency 500, combo potency 0, directional potency 0
//applies to self: Darkside, 暗黒, duration 30000, param 0
{ 16470, { 500, 0, 0, 0, 751, 30000, 0, 0, 0, 0, 0, 0, 0 } },
//has bonus effect: GainJobTimer, 2127152
{ 16470, { 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 2127152 } },
//Dark Missionary, ダークミッショナリー
//applies to targets: Dark Missionary, ダークミッショナリー, duration 15000, param 0
@ -2834,6 +2835,11 @@ ActionLut::Lut ActionLut::m_actionLut =
//has damage: potency 100, combo potency 0, directional potency 0
{ 8, { 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
//Flood of Shadow, 漆黒の波動
//has damage: potency 300, combo potency 0, directional potency 0
//has bonus effect: GainJobTimer, 2127152
{ 16469, { 300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 2127152 } },
};
ActionLut::StatusEffectTable ActionLut::m_statusEffectTable =

View file

@ -1192,7 +1192,25 @@ void Sapphire::Entity::Player::update( uint64_t tickCount )
gaugeWhmSetLilyTimer( 0 );
}
}
};
break;
}
case Common::ClassJob::Darkknight:
{
auto dsTimer = gaugeDrkGetDarkSideTimer();
if( dsTimer > interval )
dsTimer -= interval;
else
dsTimer = 0;
gaugeDrkSetDarkSideTimer( dsTimer );
auto shadowTimer = gaugeDrkGetShadowTimer();
if( shadowTimer > interval )
shadowTimer -= interval;
else
shadowTimer = 0;
gaugeDrkSetShadowTimer( shadowTimer );
break;
}
}
Chara::update( tickCount );
@ -2310,4 +2328,57 @@ void Sapphire::Entity::Player::gaugeWhmSetLilyTimer( uint16_t value, bool sendPa
uint16_t Sapphire::Entity::Player::gaugeWhmGetLilyTimer()
{
return m_gauge.whm.lilyTimer;
}
void Sapphire::Entity::Player::gaugeDrkSetBlood( uint8_t value )
{
assert( value >= 0 && value <= 100 );
auto oldValue = gaugeDrkGetBlood();
m_gauge.drk.blood = value;
if( oldValue != value )
sendActorGauge();
}
uint8_t Sapphire::Entity::Player::gaugeDrkGetBlood()
{
return m_gauge.drk.blood;
}
void Sapphire::Entity::Player::gaugeDrkSetDarkArts( bool value )
{
auto oldValue = gaugeDrkGetDarkArts();
m_gauge.drk.darkArts = value ? 1 : 0;
if( oldValue != value )
sendActorGauge();
}
bool Sapphire::Entity::Player::gaugeDrkGetDarkArts()
{
return m_gauge.drk.darkArts > 0;
}
void Sapphire::Entity::Player::gaugeDrkSetDarkSideTimer( uint16_t value, bool sendPacket )
{
assert( value >= 0 && value <= 60000 );
m_gauge.drk.darksideTimer = value;
if( sendPacket )
sendActorGauge();
}
uint16_t Sapphire::Entity::Player::gaugeDrkGetDarkSideTimer()
{
return m_gauge.drk.darksideTimer;
}
void Sapphire::Entity::Player::gaugeDrkSetShadowTimer( uint16_t value, bool sendPacket )
{
assert( value >= 0 && value <= 60000 );
m_gauge.drk.shadowTimer = value;
if( sendPacket )
sendActorGauge();
}
uint16_t Sapphire::Entity::Player::gaugeDrkGetShadowTimer()
{
return m_gauge.drk.shadowTimer;
}

View file

@ -988,6 +988,15 @@ namespace Sapphire::Entity
void gaugeWhmSetLilyTimer( uint16_t value, bool sendPacket = false );
uint16_t gaugeWhmGetLilyTimer();
void gaugeDrkSetBlood( uint8_t value );
uint8_t gaugeDrkGetBlood();
void gaugeDrkSetDarkArts( bool value );
bool gaugeDrkGetDarkArts();
void gaugeDrkSetDarkSideTimer( uint16_t value, bool sendPacket = false );
uint16_t gaugeDrkGetDarkSideTimer();
void gaugeDrkSetShadowTimer( uint16_t value, bool sendPacket = false );
uint16_t gaugeDrkGetShadowTimer();
//////////////////////////////////////////////////////////////////////////////////////////////////////
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );

View file

@ -584,10 +584,21 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcAutoA
}
}
constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}";
if( auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer() )
if( chara.isPlayer() )
{
auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer();
switch( player->getClass() )
{
case Common::ClassJob::Darkknight:
{
if( player->gaugeDrkGetDarkSideTimer() > 0 )
{
factor *= 1.1f;
}
break;
}
}
constexpr auto format = "auto attack: pot: {} aa: {} ap: {} det: {} ten: {} = {}";
player->sendDebug( format, pot, aa, ap, det, ten, factor );
}
@ -706,6 +717,22 @@ std::pair< float, Sapphire::Common::ActionHitSeverityType > CalcStats::calcActio
}
}
if( chara.isPlayer() )
{
auto player = const_cast< Entity::Chara& >( chara ).getAsPlayer();
switch( player->getClass() )
{
case Common::ClassJob::Darkknight:
{
if( player->gaugeDrkGetDarkSideTimer() > 0 )
{
factor *= 1.1f;
}
break;
}
}
}
return std::pair( factor, hitType );
}