From 4411f221239786d7b46b4529686fa8a96812fd88 Mon Sep 17 00:00:00 2001 From: collett Date: Sat, 11 Mar 2023 18:44:37 +0900 Subject: [PATCH 1/5] store item hq state in flags field --- src/common/Common.h | 6 ++++ src/common/Database/ZoneDbConnection.cpp | 2 +- src/world/Actor/PlayerInventory.cpp | 32 ----------------- src/world/Actor/PlayerSql.cpp | 45 +++++++++++++++++++++++- src/world/Manager/ItemMgr.cpp | 5 +-- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index c9928c06..e095a77d 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1306,6 +1306,12 @@ namespace Sapphire::Common GetGil = 9, // p1: gil EmptyCoffer = 11, // seems like no param }; + + enum ItemFlag + { + FlagNone = 0, + FlagHq = 1, + }; } #endif diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index 773f8cef..a23a1a72 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -241,7 +241,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements() CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_UP, - "UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;", + "UPDATE charaglobalitem SET stack = ?, durability = ?, flags = ?, reservedFlag = ?, stain = ? WHERE ItemId = ?;", CONNECTION_BOTH ); prepareStatement( CHARA_ITEMGLOBAL_DELETE, diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index cd752de3..af664a1f 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -547,38 +547,6 @@ void Sapphire::Entity::Player::writeInventory( InventoryType type ) db.execute( query ); } -void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const -{ - if( pItem->getUId() == 0 ) - writeItemDb( pItem ); - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); - - // todo: add more fields - stmt->setInt( 1, pItem->getStackSize() ); - stmt->setInt( 2, pItem->getDurability() ); - stmt->setInt( 3, pItem->getStain() ); - - stmt->setInt64( 4, pItem->getUId() ); - - db.directExecute( stmt ); -} - -void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const -{ - if( item->getUId() == 0 ) - return; - - auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); - auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); - - stmt->setInt64( 1, item->getUId() ); - - db.directExecute( stmt ); -} - - bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity ) { return true; diff --git a/src/world/Actor/PlayerSql.cpp b/src/world/Actor/PlayerSql.cpp index bd3fe3d3..4b0bb68b 100644 --- a/src/world/Actor/PlayerSql.cpp +++ b/src/world/Actor/PlayerSql.cpp @@ -650,10 +650,13 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; pItem->setUId( itemMgr.getNextUId() ); - std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, catalogId, stack, flags ) VALUES ( " + + std::string sql = "INSERT INTO charaglobalitem ( CharacterId, itemId, reservedFlag, catalogId, stack, flags ) VALUES ( " + std::to_string( getId() ) + ", " + std::to_string( pItem->getUId() ) + ", " + + std::to_string( pItem->getReservedFlag() ) + ", " + std::to_string( pItem->getId() ) + ", " + std::to_string( pItem->getStackSize() ) + ", " + std::to_string( flags ) + ");"; @@ -661,6 +664,46 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const } } +void Sapphire::Entity::Player::updateItemDb( Sapphire::ItemPtr pItem ) const +{ + if( pItem->getUId() == 0 ) + { + writeItemDb( pItem ); + return; + } + + uint8_t flags = 0; + if( pItem->isHq() ) + flags |= Common::ItemFlag::FlagHq; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_UP ); + + // todo: add more fields + stmt->setInt( 1, pItem->getStackSize() ); + stmt->setInt( 2, pItem->getDurability() ); + stmt->setInt( 3, flags ); + stmt->setInt( 4, pItem->getReservedFlag() ); + stmt->setInt( 5, pItem->getStain() ); + + stmt->setInt64( 6, pItem->getUId() ); + + db.directExecute( stmt ); +} + +void Sapphire::Entity::Player::deleteItemDb( Sapphire::ItemPtr item ) const +{ + if( item->getUId() == 0 ) + return; + + auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); + auto stmt = db.getPreparedStatement( Db::CHARA_ITEMGLOBAL_DELETE ); + + stmt->setInt64( 1, item->getUId() ); + + db.directExecute( stmt ); +} + bool Sapphire::Entity::Player::loadInventory() { auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); diff --git a/src/world/Manager/ItemMgr.cpp b/src/world/Manager/ItemMgr.cpp index c8331dac..01d2b03c 100644 --- a/src/world/Manager/ItemMgr.cpp +++ b/src/world/Manager/ItemMgr.cpp @@ -132,15 +132,16 @@ Sapphire::ItemPtr Sapphire::World::Manager::ItemMgr::loadItem( uint64_t uId ) try { auto itemInfo = exdData.get< Sapphire::Data::Item >( itemRes->getUInt( 1 ) ); - bool isHq = itemRes->getUInt( 3 ) == 1; + bool isHq = itemRes->getUInt( 5 ) & Common::ItemFlag::FlagHq; ItemPtr pItem = make_Item( uId, itemRes->getUInt( 1 ), isHq ); pItem->setStackSize( itemRes->getUInt( 2 ) ); - pItem->setStain( itemRes->getUInt16( 13 ) ); + pItem->setReservedFlag( itemRes->getUInt( 3 ) ); pItem->setDurability( itemRes->getInt16( 6 ) ); + pItem->setStain( itemRes->getUInt16( 13 ) ); return pItem; } From 6576d3314ddec13c53ef326715b6dd56b5f362ec Mon Sep 17 00:00:00 2001 From: collett Date: Mon, 13 Mar 2023 22:32:33 +0900 Subject: [PATCH 2/5] fix CastType 3 --- src/common/Common.h | 2 +- src/world/Action/Action.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index 26dfce34..de697715 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1084,7 +1084,7 @@ namespace Sapphire::Common { SingleTarget = 1, CircularAOE = 2, - Type3 = 3, // another single target? no idea how to call it + ConeAOE = 3, RectangularAOE = 4, CircularAoEPlaced = 7 }; diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index a6e87202..f7815b54 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1124,7 +1124,6 @@ void Action::Action::addDefaultActorFilters() switch( m_castType ) { case Common::CastType::SingleTarget: - case Common::CastType::Type3: { auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) ); @@ -1134,6 +1133,7 @@ void Action::Action::addDefaultActorFilters() } case Common::CastType::CircularAOE: + case Common::CastType::ConeAOE: { auto filter = std::make_shared< World::Util::ActorFilterInRange >( m_pos, m_effectRange ); From df8686f3089fbbc7b0db44a1056829538943ca11 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 15 Mar 2023 02:26:44 +0900 Subject: [PATCH 3/5] only block when a shield is on --- src/world/Actor/Chara.cpp | 4 ++++ src/world/Actor/Chara.h | 2 ++ src/world/Actor/Player.cpp | 10 ++++++++++ src/world/Actor/Player.h | 2 +- src/world/Math/CalcStats.cpp | 14 ++++++++------ src/world/Math/CalcStats.h | 12 ++++++------ 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 61dcac63..45e27b04 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -793,6 +793,10 @@ void Sapphire::Entity::Chara::setAgentId( uint32_t agentId ) m_agentId = agentId; } +bool Sapphire::Entity::Chara::canBlock() +{ + return false; +} float Sapphire::Entity::Chara::getRadius() const { diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index d503da22..1e588118 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -250,6 +250,8 @@ namespace Sapphire::Entity virtual void autoAttack( CharaPtr pTarget ); + virtual bool canBlock(); + virtual void onDeath() {}; virtual void onDamageTaken( Chara& pSource ) {}; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index ccb77f32..59779515 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -2420,6 +2420,16 @@ void Sapphire::Entity::Player::clearBuyBackMap() m_shopBuyBackMap.clear(); } +bool Sapphire::Entity::Player::canBlock() +{ + if( auto item = getEquippedSecondaryWeapon() ) + { + if( item->getCategory() == ItemUICategory::Shield ) + return true; + } + return false; +} + void Sapphire::Entity::Player::gaugeClear() { std::memset( &m_gauge, 0, sizeof( m_gauge ) ); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index ba6c6528..f15e528a 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -136,7 +136,7 @@ namespace Sapphire::Entity void checkEvent( uint32_t eventId ); - + bool canBlock() override; // Events ////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index dbd4ad38..49e47dab 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -183,14 +183,16 @@ uint32_t CalcStats::calculateMaxHp( PlayerPtr pPlayer ) return result; } -float CalcStats::dodgeProbability( const Sapphire::Entity::Chara& chara ) +float CalcStats::dodgeProbability( Sapphire::Entity::Chara& chara ) { // dummy value: 5% for players. return chara.isPlayer() ? 5 : 0; } -float CalcStats::blockProbability( const Chara& chara ) +float CalcStats::blockProbability( Chara& chara ) { + if( !chara.canBlock() ) + return 0; auto level = chara.getLevel(); auto blockRate = static_cast< float >( chara.getStatValue( Common::BaseParam::BlockRate ) ); auto levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); @@ -205,7 +207,7 @@ float CalcStats::blockProbability( const Chara& chara ) return result; } -float CalcStats::parryProbability( const Sapphire::Entity::Chara& chara ) +float CalcStats::parryProbability( Sapphire::Entity::Chara& chara ) { // dummy value: 10% for players. float result = chara.isPlayer() ? 10 : 0; @@ -844,7 +846,7 @@ float CalcStats::calcAbsorbHP( Sapphire::Entity::CharaPtr pChara, float damage ) return result; } -bool CalcStats::calcDodge( const Sapphire::Entity::Chara& chara ) +bool CalcStats::calcDodge( Sapphire::Entity::Chara& chara ) { if( dodgeProbability( chara ) > getRandomNumber0To100() ) { @@ -853,7 +855,7 @@ bool CalcStats::calcDodge( const Sapphire::Entity::Chara& chara ) return false; } -float CalcStats::calcBlock( const Sapphire::Entity::Chara& chara, float damage ) +float CalcStats::calcBlock( Sapphire::Entity::Chara& chara, float damage ) { if( blockProbability( chara ) > getRandomNumber0To100() ) { @@ -862,7 +864,7 @@ float CalcStats::calcBlock( const Sapphire::Entity::Chara& chara, float damage ) return 0; } -float CalcStats::calcParry( const Sapphire::Entity::Chara& chara, float damage ) +float CalcStats::calcParry( Sapphire::Entity::Chara& chara, float damage ) { if( parryProbability( chara ) > getRandomNumber0To100() ) { diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index 92b80648..d9ba5fbc 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -16,14 +16,14 @@ namespace Sapphire::Math static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer ); - static float dodgeProbability( const Sapphire::Entity::Chara& chara ); + static float dodgeProbability( Sapphire::Entity::Chara& chara ); /*! * @brief Calculates the probability of a block happening */ - static float blockProbability( const Sapphire::Entity::Chara& chara ); + static float blockProbability( Sapphire::Entity::Chara& chara ); - static float parryProbability( const Sapphire::Entity::Chara& chara ); + static float parryProbability( Sapphire::Entity::Chara& chara ); /*! * @brief Calculates the probability of a direct hit happening @@ -155,11 +155,11 @@ namespace Sapphire::Math static float calcAbsorbHP( Sapphire::Entity::CharaPtr pChara, float damage ); - static bool calcDodge( const Sapphire::Entity::Chara& chara ); + static bool calcDodge( Sapphire::Entity::Chara& chara ); - static float calcBlock( const Sapphire::Entity::Chara& chara, float damage ); + static float calcBlock( Sapphire::Entity::Chara& chara, float damage ); - static float calcParry( const Sapphire::Entity::Chara& chara, float damage ); + static float calcParry( Sapphire::Entity::Chara& chara, float damage ); static float getRandomNumber0To100(); private: From f0c8f5ef87018223f5617e92785e1bc6dd7888a3 Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 15 Mar 2023 02:35:41 +0900 Subject: [PATCH 4/5] fix model not updating when unequip item, added guards to detect inventory desync and prevent item overwriting. --- src/world/Actor/Player.h | 2 +- src/world/Actor/PlayerInventory.cpp | 52 +++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 62fe1f6b..57a3ca8d 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -340,7 +340,7 @@ namespace Sapphire::Entity void equipSoulCrystal( ItemPtr pItem, bool updateClass ); /*! unequip a soul crystal, returning to the base class*/ - void unequipSoulCrystal( ItemPtr pItem ); + void unequipSoulCrystal(); /*! get player ilvl */ uint16_t getItemLevel() const; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index af664a1f..a2c71292 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -148,9 +148,9 @@ void Sapphire::Entity::Player::equipSoulCrystal( ItemPtr pItem, bool updateJob ) void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapphire::ItemPtr& pItem, bool updateClass ) { - uint64_t model = pItem->getModelId1(); - uint64_t model2 = pItem->getModelId2(); - uint64_t stain = pItem->getStain(); + uint64_t model = pItem ? pItem->getModelId1() : 0; + uint64_t model2 = pItem ? pItem->getModelId2() : 0; + uint64_t stain = pItem ? pItem->getStain() : 0; switch( equipSlotId ) { @@ -172,7 +172,10 @@ void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapp break; case SoulCrystal: - equipSoulCrystal( pItem, updateClass ); + if( pItem ) + equipSoulCrystal( pItem, updateClass ); + else + unequipSoulCrystal(); break; case Waist: @@ -265,15 +268,12 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite if( sendUpdate ) { + updateModels( equipSlotId, nullptr, true ); sendModel(); - m_itemLevel = calculateEquippedGearItemLevel(); sendItemLevel(); } - if ( equipSlotId == SoulCrystal ) - unequipSoulCrystal( pItem ); - auto baseParams = pItem->getBaseParams(); for( auto i = 0; i < 6; ++i ) { @@ -293,7 +293,7 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite } } -void Sapphire::Entity::Player::unequipSoulCrystal( ItemPtr pItem ) +void Sapphire::Entity::Player::unequipSoulCrystal() { auto& exdData = Common::Service< Sapphire::Data::ExdDataGenerated >::ref(); @@ -716,7 +716,19 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); if( tmpItem == nullptr ) + { + sendUrgent( "trying to move EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( auto target = m_storageMap[ toInventoryId ]->getItem( toSlot ) ) + { + sendUrgent( "trying to move item from [container{}, slot{}] to NON-EMPTY [container{}, slot{}], potential client desync, swapItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + swapItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } itemMap[ fromSlotId ].reset(); @@ -853,8 +865,28 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); - if( fromItem == nullptr || toItem == nullptr ) + if( fromItem == nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap TWO EMPTY ITEMS from [container{}, slot{}] to [container{}, slot{}], potential client desync, no action is performed.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); return; + } + + if( fromItem != nullptr && toItem == nullptr ) + { + sendUrgent( "trying to swap item from [container{}, slot{}] to EMPTY [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( fromInventoryId, fromSlotId, toInventoryId, toSlot, sendUpdate ); + return; + } + + if( fromItem == nullptr && toItem != nullptr ) + { + sendUrgent( "trying to swap EMPTY item from [container{}, slot{}] to [container{}, slot{}], potential client desync, moveItem is performed instead.", + fromInventoryId, fromSlotId, toInventoryId, toSlot ); + moveItem( toInventoryId, toSlot, fromInventoryId, fromSlotId, sendUpdate ); // we are moving the non-empty toSlot back to fromSlot. + return; + } // An item is being moved from bag0-3 to equippment, meaning // the swapped out item will be placed in the matching armory. From 2c3b2dfd9b614903070e7f8f49820dd5f5e59b4b Mon Sep 17 00:00:00 2001 From: collett Date: Wed, 15 Mar 2023 06:40:27 +0900 Subject: [PATCH 5/5] add attackType in damage effect --- src/world/Action/Action.cpp | 20 +++++++++++++++----- src/world/Action/EffectBuilder.cpp | 12 ++++++------ src/world/Action/EffectBuilder.h | 8 ++++---- src/world/Action/EffectResult.cpp | 9 ++++++--- src/world/Action/EffectResult.h | 6 +++--- 5 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index f7815b54..898512ec 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -573,17 +573,24 @@ void Action::Action::buildEffects() if( dmg.first > 0 ) { + auto attackTypeEffect = m_actionData->attackType; + if( attackTypeEffect == -1 ) + { + //maybe set it base on job? + attackTypeEffect = 0; + } + dmg.first = actor->applyShieldProtection( dmg.first ); if( blocked > 0 ) - m_effectBuilder->blockedDamage( actor, actor, dmg.first, static_cast< uint16_t >( blocked / originalDamage * 100 ) , dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); + m_effectBuilder->blockedDamage( actor, actor, dmg.first, static_cast< uint16_t >( blocked / originalDamage * 100 ), attackTypeEffect, dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); else if (parried > 0 ) - m_effectBuilder->parriedDamage( actor, actor, dmg.first, static_cast< uint16_t >( parried / originalDamage * 100 ), dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); + m_effectBuilder->parriedDamage( actor, actor, dmg.first, static_cast< uint16_t >( parried / originalDamage * 100 ), attackTypeEffect, dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); else - m_effectBuilder->damage( actor, actor, dmg.first, dmg.second, dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); + m_effectBuilder->damage( actor, actor, dmg.first, attackTypeEffect, dmg.second, dmg.first == 0 ? Common::ActionEffectResultFlag::Absorbed : Common::ActionEffectResultFlag::None, getExecutionDelay() + victimCounter * 100 ); auto reflectDmg = Math::CalcStats::calcDamageReflect( m_pSource, actor, dmg.first, getActionTypeFilterFromAttackType( attackType ) ); if( reflectDmg.first > 0 ) { - m_effectBuilder->damage( actor, m_pSource, reflectDmg.first, reflectDmg.second, Common::ActionEffectResultFlag::Reflected, getExecutionDelay() + victimCounter * 100 ); + m_effectBuilder->damage( actor, m_pSource, reflectDmg.first, attackTypeEffect, reflectDmg.second, Common::ActionEffectResultFlag::Reflected, getExecutionDelay() + victimCounter * 100 ); } auto absorb = Math::CalcStats::calcAbsorbHP( m_pSource, dmg.first ); @@ -1269,7 +1276,10 @@ bool Action::Action::isWeaponSkill() const bool Action::Action::isAttackTypePhysical( Common::AttackType attackType ) { - return attackType == Common::AttackType::Physical; + return attackType == Common::AttackType::Physical || + attackType == Common::AttackType::Slashing || + attackType == Common::AttackType::Piercing || + attackType == Common::AttackType::Blunt; } bool Action::Action::isAttackTypeMagical( Common::AttackType attackType ) diff --git a/src/world/Action/EffectBuilder.cpp b/src/world/Action/EffectBuilder.cpp index e28c3f51..8be1fd62 100644 --- a/src/world/Action/EffectBuilder.cpp +++ b/src/world/Action/EffectBuilder.cpp @@ -64,24 +64,24 @@ void EffectBuilder::dodge( Entity::CharaPtr& effectTarget, Entity::CharaPtr& dod moveToResultList( effectTarget, nextResult ); } -void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) +void EffectBuilder::damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint8_t attackType, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) { EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs ); - nextResult->damage( amount, severity, flag ); + nextResult->damage( amount, severity, attackType, flag ); moveToResultList( effectTarget, nextResult ); } -void EffectBuilder::blockedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) +void EffectBuilder::blockedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) { EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs ); - nextResult->blockedDamage( amount, rate, flag ); + nextResult->blockedDamage( amount, rate, attackType, flag ); moveToResultList( effectTarget, nextResult ); } -void EffectBuilder::parriedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) +void EffectBuilder::parriedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag, uint64_t resultDelayMs ) { EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs ); - nextResult->parriedDamage( amount, rate, flag ); + nextResult->parriedDamage( amount, rate, attackType, flag ); moveToResultList( effectTarget, nextResult ); } diff --git a/src/world/Action/EffectBuilder.h b/src/world/Action/EffectBuilder.h index 46eb3438..b8fbaf16 100644 --- a/src/world/Action/EffectBuilder.h +++ b/src/world/Action/EffectBuilder.h @@ -22,14 +22,14 @@ namespace Sapphire::World::Action void dodge( Entity::CharaPtr& effectTarget, Entity::CharaPtr& dodgingTarget, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); - void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, - Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage, + void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint8_t attackType, + Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); - void blockedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, + void blockedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); - void parriedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, + void parriedDamage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); void startCombo( Entity::CharaPtr& target, uint16_t actionId ); diff --git a/src/world/Action/EffectResult.cpp b/src/world/Action/EffectResult.cpp index 2147633e..2f4688d4 100644 --- a/src/world/Action/EffectResult.cpp +++ b/src/world/Action/EffectResult.cpp @@ -62,28 +62,31 @@ void EffectResult::dodge( Common::ActionEffectResultFlag flag ) m_type = Common::ActionEffectType::Miss; } -void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag ) +void EffectResult::damage( uint32_t amount, Common::ActionHitSeverityType severity, uint8_t attackType, Common::ActionEffectResultFlag flag ) { m_param0 = static_cast< uint8_t >( severity ); + m_param1 = attackType; m_value = amount; m_flag = flag; m_type = Common::ActionEffectType::Damage; } -void EffectResult::blockedDamage( uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag ) +void EffectResult::blockedDamage( uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag ) { m_value = amount; m_flag = flag; + m_param1 = attackType; m_param2 = rate; m_type = Common::ActionEffectType::BlockedDamage; } -void EffectResult::parriedDamage( uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag ) +void EffectResult::parriedDamage( uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag ) { m_value = amount; m_flag = flag; + m_param1 = attackType; m_param2 = rate; m_type = Common::ActionEffectType::ParriedDamage; diff --git a/src/world/Action/EffectResult.h b/src/world/Action/EffectResult.h index 2ab53c69..23862d39 100644 --- a/src/world/Action/EffectResult.h +++ b/src/world/Action/EffectResult.h @@ -19,9 +19,9 @@ namespace Sapphire::World::Action explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs ); void dodge( Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); - void damage( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); - void blockedDamage( uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); - void parriedDamage( uint32_t amount, uint16_t rate, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); + void damage( uint32_t amount, Common::ActionHitSeverityType severity, uint8_t attackType, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); + void blockedDamage( uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); + void parriedDamage( uint32_t amount, uint16_t rate, uint8_t attackType, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); void heal( uint32_t amount, Common::ActionHitSeverityType severity, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); void restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); void startCombo( uint16_t actionId );