diff --git a/src/scripts/instances/questbattles/ChasingShadows.cpp b/src/scripts/instances/questbattles/ChasingShadows.cpp index f2e08715..194f9729 100644 --- a/src/scripts/instances/questbattles/ChasingShadows.cpp +++ b/src/scripts/instances/questbattles/ChasingShadows.cpp @@ -30,7 +30,9 @@ private: enum vars { SET_1_SPAWNED, - SET_2_SPAWNED + SET_2_SPAWNED, + SET_3_SPAWNED, + SUCCESS_CALLED, }; public: @@ -45,18 +47,37 @@ public: void onInit( QuestBattle& instance ) override { instance.registerEObj( "unknown_0", 2005192, 5760474, 4, { -51.493111f, 0.309087f, 71.436897f }, 1.000000f, -0.000006f ); - } void onUpdate( QuestBattle& instance, uint64_t tickCount ) override { auto pair1Spawnd = instance.getCustomVar( SET_1_SPAWNED ); + auto pair2Spawnd = instance.getCustomVar( SET_2_SPAWNED ); + auto pair3Spawnd = instance.getCustomVar( SET_3_SPAWNED ); + auto successCalled = instance.getCustomVar( SUCCESS_CALLED ); auto boss = instance.getActiveBNpcByLevelId( INIT_POP_BOSS ); - if( !boss ) + auto ida = instance.getActiveBNpcByLevelId( INIT_P_POP_IDA ); + auto papa = instance.getActiveBNpcByLevelId( INIT_P_POP_PAPARIMO ); + auto pPlayer = instance.getPlayerPtr(); + + if( pPlayer && !pPlayer->isAlive() ) + { + instance.fail(); + return; + } + + if( instance.getCountEnemyBNpc() == 0 && successCalled == 0 ) + { + instance.setCustomVar( SUCCESS_CALLED, 1 ); + instance.success(); + return; + } + + if( !boss || !ida || !papa ) return; - if( pair1Spawnd == 0 && boss->getHpPercent() <= 90 ) + if( pair1Spawnd == 0 && boss->getHpPercent() <= 75 ) { instance.setCustomVar( SET_1_SPAWNED, 1 ); auto a2 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_B_03, 10, 0, 1440, 938, @@ -66,10 +87,66 @@ public: a2->setFlag( Entity::NoDeaggro ); a3->setFlag( Entity::NoDeaggro ); - auto pPlayer = instance.getPlayerPtr(); - a2->hateListAdd( pPlayer, 1 ); + a2->hateListAdd( ida, 10000 ); + a3->hateListAdd( ida, 10000 ); + a2->hateListAdd( papa, 10000 ); + a3->hateListAdd( papa, 10000 ); - a3->hateListAdd( pPlayer, 1 ); + + auto a4 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_01, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + auto a5 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_02, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + a4->setFlag( Entity::NoDeaggro ); + a5->setFlag( Entity::NoDeaggro ); + + auto pPlayer = instance.getPlayerPtr(); + a4->hateListAdd( pPlayer, 1 ); + a5->hateListAdd( pPlayer, 1 ); + } + + if( pair2Spawnd == 0 && boss->getHpPercent() <= 50 ) + { + instance.setCustomVar( SET_2_SPAWNED, 1 ); + auto a2 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_B_05, 10, 0, 1440, 938, + instance.getDirectorId(), Common::BNpcType::Enemy ); + auto a3 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_B_06, 10, 0, 1440, 938, + instance.getDirectorId(), Common::BNpcType::Enemy ); + a2->setFlag( Entity::NoDeaggro ); + a3->setFlag( Entity::NoDeaggro ); + + a2->hateListAdd( ida, 10000 ); + a3->hateListAdd( ida, 10000 ); + a2->hateListAdd( papa, 10000 ); + a3->hateListAdd( papa, 10000 ); + + auto a4 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_03, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + auto a5 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_04, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + a4->setFlag( Entity::NoDeaggro ); + a5->setFlag( Entity::NoDeaggro ); + + auto pPlayer = instance.getPlayerPtr(); + a4->hateListAdd( pPlayer, 1 ); + a5->hateListAdd( pPlayer, 1 ); + + } + + if( pair3Spawnd == 0 && boss->getHpPercent() <= 25 ) + { + instance.setCustomVar( SET_3_SPAWNED, 1 ); + + auto a4 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_05, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + auto a5 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_A_06, 5, 0, 300, 937, + instance.getDirectorId(), Common::BNpcType::Enemy ); + a4->setFlag( Entity::NoDeaggro ); + a5->setFlag( Entity::NoDeaggro ); + + auto pPlayer = instance.getPlayerPtr(); + a4->hateListAdd( pPlayer, 1 ); + a5->hateListAdd( pPlayer, 1 ); } } diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index b970927d..93f96f25 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -36,6 +36,7 @@ #include #include #include +#include using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; @@ -392,7 +393,10 @@ bool Sapphire::Entity::BNpc::hateListHasActor( Sapphire::Entity::CharaPtr pChara void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::CharaPtr pChara ) { - m_lastAttack = Util::getTimeMs(); + auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); + auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 50, 600 ).next() ); + + m_lastAttack = Util::getTimeMs() + variation; hateListUpdate( pChara, 1 ); changeTarget( pChara->getId() ); @@ -721,3 +725,33 @@ void Sapphire::Entity::BNpc::setFlag( uint32_t flag ) { m_flags |= flag; } + +void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) +{ + + uint64_t tick = Util::getTimeMs(); + + // todo: this needs to use the auto attack delay for the equipped weapon + if( ( tick - m_lastAttack ) > 2500 ) + { + pTarget->onActionHostile( getAsChara() ); + m_lastAttack = tick; + srand( static_cast< uint32_t >( tick ) ); + + auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); + auto damage = static_cast< uint16_t >( pRNGMgr->getRandGenerator< float >( m_level, m_level + m_level * 1.5f ).next() ); + + auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 ); + effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); + Common::EffectEntry effectEntry{}; + effectEntry.value = damage; + effectEntry.effectType = ActionEffectType::Damage; + effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage; + effectPacket->addEffect( effectEntry ); + + sendToInRangeSet( effectPacket ); + + pTarget->takeDamage( damage ); + + } +} \ No newline at end of file diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index d688dfdc..f9709745 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -102,6 +102,8 @@ namespace Sapphire::Entity void onDeath() override; + void autoAttack( CharaPtr pTarget ) override; + uint32_t getTimeOfDeath() const; void setTimeOfDeath( uint32_t timeOfDeath ); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 2aad1b9c..de231a2b 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -14,6 +14,7 @@ #include "Manager/HousingMgr.h" #include "Manager/TerritoryMgr.h" +#include "Manager/RNGMgr.h" #include "Territory/Zone.h" #include "Territory/ZonePosition.h" @@ -1554,8 +1555,11 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) //uint64_t tick = Util::getTimeMs(); //srand(static_cast< uint32_t >(tick)); - uint32_t damage = static_cast< uint32_t >( mainWeap->getAutoAttackDmg() ); - uint32_t variation = 0 + rand() % 3; + auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); + auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 0, 3 ).next() ); + + auto damage = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( static_cast< uint32_t > ( getLevel() * 1.5f ), + getLevel() + static_cast< uint32_t >( mainWeap->getAutoAttackDmg() * 2 ) ).next() ); if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer ) { @@ -1566,6 +1570,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) entry.value = damage; entry.effectType = Common::ActionEffectType::Damage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; + entry.param = variation; effectPacket->addEffect( entry ); diff --git a/src/world/Territory/QuestBattle.cpp b/src/world/Territory/QuestBattle.cpp index 9160fbfc..ef23f08e 100644 --- a/src/world/Territory/QuestBattle.cpp +++ b/src/world/Territory/QuestBattle.cpp @@ -348,7 +348,7 @@ void Sapphire::QuestBattle::clearDirector( Entity::Player& player ) void Sapphire::QuestBattle::success() { - + //m_state = DutyFinished; m_pPlayer->eventStart( m_pPlayer->getId(), getDirectorId(), Event::EventHandler::GameProgress, 1, 0 ); m_pPlayer->playScene( getDirectorId(), 60001, 0x40000, [ & ]( Entity::Player& player, const Event::SceneResult& result ) @@ -382,7 +382,7 @@ uint32_t Sapphire::QuestBattle::getCountEnemyBNpc() uint32_t count = 0; for( auto bnpcIt : m_bNpcMap ) { - if( bnpcIt.second->getEnemyType() == 4 ) + if( bnpcIt.second->getEnemyType() == 4 && bnpcIt.second->isAlive() ) count++; } return count;