1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-04 17:57:47 +00:00

Merge pull request #925 from collett8192/Sapphire5.58_action

attackType, minor fixes and merge 5.58 main
This commit is contained in:
Mordred 2023-03-14 23:10:00 +01:00 committed by GitHub
commit 4ceb771a16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 164 additions and 83 deletions

View file

@ -1084,7 +1084,7 @@ namespace Sapphire::Common
{ {
SingleTarget = 1, SingleTarget = 1,
CircularAOE = 2, CircularAOE = 2,
Type3 = 3, // another single target? no idea how to call it ConeAOE = 3,
RectangularAOE = 4, RectangularAOE = 4,
CircularAoEPlaced = 7 CircularAoEPlaced = 7
}; };
@ -1373,6 +1373,12 @@ namespace Sapphire::Common
GetGil = 9, // p1: gil GetGil = 9, // p1: gil
EmptyCoffer = 11, // seems like no param EmptyCoffer = 11, // seems like no param
}; };
enum ItemFlag
{
FlagNone = 0,
FlagHq = 1,
};
} }
#endif #endif

View file

@ -241,7 +241,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
CONNECTION_BOTH ); CONNECTION_BOTH );
prepareStatement( CHARA_ITEMGLOBAL_UP, prepareStatement( CHARA_ITEMGLOBAL_UP,
"UPDATE charaglobalitem SET stack = ?, durability = ?, stain = ? WHERE ItemId = ?;", "UPDATE charaglobalitem SET stack = ?, durability = ?, flags = ?, reservedFlag = ?, stain = ? WHERE ItemId = ?;",
CONNECTION_BOTH ); CONNECTION_BOTH );
prepareStatement( CHARA_ITEMGLOBAL_DELETE, prepareStatement( CHARA_ITEMGLOBAL_DELETE,

View file

@ -573,17 +573,24 @@ void Action::Action::buildEffects()
if( dmg.first > 0 ) 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 ); dmg.first = actor->applyShieldProtection( dmg.first );
if( blocked > 0 ) 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 ) 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 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 ) ); auto reflectDmg = Math::CalcStats::calcDamageReflect( m_pSource, actor, dmg.first, getActionTypeFilterFromAttackType( attackType ) );
if( reflectDmg.first > 0 ) 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 ); auto absorb = Math::CalcStats::calcAbsorbHP( m_pSource, dmg.first );
@ -1124,7 +1131,6 @@ void Action::Action::addDefaultActorFilters()
switch( m_castType ) switch( m_castType )
{ {
case Common::CastType::SingleTarget: case Common::CastType::SingleTarget:
case Common::CastType::Type3:
{ {
auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) ); auto filter = std::make_shared< World::Util::ActorFilterSingleTarget >( static_cast< uint32_t >( m_targetId ) );
@ -1134,6 +1140,7 @@ void Action::Action::addDefaultActorFilters()
} }
case Common::CastType::CircularAOE: case Common::CastType::CircularAOE:
case Common::CastType::ConeAOE:
{ {
auto filter = std::make_shared< World::Util::ActorFilterInRange >( m_pos, m_effectRange ); auto filter = std::make_shared< World::Util::ActorFilterInRange >( m_pos, m_effectRange );
@ -1269,7 +1276,10 @@ bool Action::Action::isWeaponSkill() const
bool Action::Action::isAttackTypePhysical( Common::AttackType attackType ) 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 ) bool Action::Action::isAttackTypeMagical( Common::AttackType attackType )

View file

@ -64,24 +64,24 @@ void EffectBuilder::dodge( Entity::CharaPtr& effectTarget, Entity::CharaPtr& dod
moveToResultList( effectTarget, nextResult ); 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 ); EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs );
nextResult->damage( amount, severity, flag ); nextResult->damage( amount, severity, attackType, flag );
moveToResultList( effectTarget, nextResult ); 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 ); EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs );
nextResult->blockedDamage( amount, rate, flag ); nextResult->blockedDamage( amount, rate, attackType, flag );
moveToResultList( effectTarget, nextResult ); 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 ); EffectResultPtr nextResult = make_EffectResult( damagingTarget, Common::Util::getTimeMs() + resultDelayMs );
nextResult->parriedDamage( amount, rate, flag ); nextResult->parriedDamage( amount, rate, attackType, flag );
moveToResultList( effectTarget, nextResult ); moveToResultList( effectTarget, nextResult );
} }

View file

@ -22,14 +22,14 @@ namespace Sapphire::World::Action
void dodge( Entity::CharaPtr& effectTarget, Entity::CharaPtr& dodgingTarget, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); 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, void damage( Entity::CharaPtr& effectTarget, Entity::CharaPtr& damagingTarget, uint32_t amount, uint8_t attackType,
Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage, Common::ActionHitSeverityType severity = Common::ActionHitSeverityType::NormalDamage,
Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 ); 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 ); 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 ); Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None, uint64_t resultDelayMs = 600 );
void startCombo( Entity::CharaPtr& target, uint16_t actionId ); void startCombo( Entity::CharaPtr& target, uint16_t actionId );

View file

@ -62,28 +62,31 @@ void EffectResult::dodge( Common::ActionEffectResultFlag flag )
m_type = Common::ActionEffectType::Miss; 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_param0 = static_cast< uint8_t >( severity );
m_param1 = attackType;
m_value = amount; m_value = amount;
m_flag = flag; m_flag = flag;
m_type = Common::ActionEffectType::Damage; 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_value = amount;
m_flag = flag; m_flag = flag;
m_param1 = attackType;
m_param2 = rate; m_param2 = rate;
m_type = Common::ActionEffectType::BlockedDamage; 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_value = amount;
m_flag = flag; m_flag = flag;
m_param1 = attackType;
m_param2 = rate; m_param2 = rate;
m_type = Common::ActionEffectType::ParriedDamage; m_type = Common::ActionEffectType::ParriedDamage;

View file

@ -19,9 +19,9 @@ namespace Sapphire::World::Action
explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs ); explicit EffectResult( Entity::CharaPtr target, uint64_t delayMs );
void dodge( Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None ); void dodge( Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void damage( uint32_t amount, Common::ActionHitSeverityType severity, 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, 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, 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 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 restoreMP( uint32_t amount, Common::ActionEffectResultFlag flag = Common::ActionEffectResultFlag::None );
void startCombo( uint16_t actionId ); void startCombo( uint16_t actionId );

View file

@ -793,6 +793,10 @@ void Sapphire::Entity::Chara::setAgentId( uint32_t agentId )
m_agentId = agentId; m_agentId = agentId;
} }
bool Sapphire::Entity::Chara::canBlock()
{
return false;
}
float Sapphire::Entity::Chara::getRadius() const float Sapphire::Entity::Chara::getRadius() const
{ {

View file

@ -250,6 +250,8 @@ namespace Sapphire::Entity
virtual void autoAttack( CharaPtr pTarget ); virtual void autoAttack( CharaPtr pTarget );
virtual bool canBlock();
virtual void onDeath() {}; virtual void onDeath() {};
virtual void onDamageTaken( Chara& pSource ) {}; virtual void onDamageTaken( Chara& pSource ) {};

View file

@ -2420,6 +2420,16 @@ void Sapphire::Entity::Player::clearBuyBackMap()
m_shopBuyBackMap.clear(); 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() void Sapphire::Entity::Player::gaugeClear()
{ {
std::memset( &m_gauge, 0, sizeof( m_gauge ) ); std::memset( &m_gauge, 0, sizeof( m_gauge ) );

View file

@ -136,7 +136,7 @@ namespace Sapphire::Entity
void checkEvent( uint32_t eventId ); void checkEvent( uint32_t eventId );
bool canBlock() override;
// Events // Events
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
@ -340,7 +340,7 @@ namespace Sapphire::Entity
void equipSoulCrystal( ItemPtr pItem, bool updateClass ); void equipSoulCrystal( ItemPtr pItem, bool updateClass );
/*! unequip a soul crystal, returning to the base class*/ /*! unequip a soul crystal, returning to the base class*/
void unequipSoulCrystal( ItemPtr pItem ); void unequipSoulCrystal();
/*! get player ilvl */ /*! get player ilvl */
uint16_t getItemLevel() const; uint16_t getItemLevel() const;

View file

@ -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 ) void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapphire::ItemPtr& pItem, bool updateClass )
{ {
uint64_t model = pItem->getModelId1(); uint64_t model = pItem ? pItem->getModelId1() : 0;
uint64_t model2 = pItem->getModelId2(); uint64_t model2 = pItem ? pItem->getModelId2() : 0;
uint64_t stain = pItem->getStain(); uint64_t stain = pItem ? pItem->getStain() : 0;
switch( equipSlotId ) switch( equipSlotId )
{ {
@ -172,7 +172,10 @@ void Sapphire::Entity::Player::updateModels( GearSetSlot equipSlotId, const Sapp
break; break;
case SoulCrystal: case SoulCrystal:
equipSoulCrystal( pItem, updateClass ); if( pItem )
equipSoulCrystal( pItem, updateClass );
else
unequipSoulCrystal();
break; break;
case Waist: case Waist:
@ -265,15 +268,12 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite
if( sendUpdate ) if( sendUpdate )
{ {
updateModels( equipSlotId, nullptr, true );
sendModel(); sendModel();
m_itemLevel = calculateEquippedGearItemLevel(); m_itemLevel = calculateEquippedGearItemLevel();
sendItemLevel(); sendItemLevel();
} }
if ( equipSlotId == SoulCrystal )
unequipSoulCrystal( pItem );
auto baseParams = pItem->getBaseParams(); auto baseParams = pItem->getBaseParams();
for( auto i = 0; i < 6; ++i ) 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(); auto& exdData = Common::Service< Sapphire::Data::ExdDataGenerated >::ref();
@ -547,38 +547,6 @@ void Sapphire::Entity::Player::writeInventory( InventoryType type )
db.execute( query ); 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 ) bool Sapphire::Entity::Player::isObtainable( uint32_t catalogId, uint8_t quantity )
{ {
return true; return true;
@ -748,7 +716,19 @@ Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint8_t fromSlotId
auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap();
if( tmpItem == nullptr ) 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; 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(); itemMap[ fromSlotId ].reset();
@ -885,8 +865,28 @@ void Sapphire::Entity::Player::swapItem( uint16_t fromInventoryId, uint8_t fromS
auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot ); auto toItem = m_storageMap[ toInventoryId ]->getItem( toSlot );
auto& itemMap = m_storageMap[ fromInventoryId ]->getItemMap(); 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; 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 // An item is being moved from bag0-3 to equippment, meaning
// the swapped out item will be placed in the matching armory. // the swapped out item will be placed in the matching armory.

View file

@ -650,10 +650,13 @@ void Sapphire::Entity::Player::writeItemDb( Sapphire::ItemPtr pItem ) const
auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref();
uint8_t flags = 0; uint8_t flags = 0;
if( pItem->isHq() )
flags |= Common::ItemFlag::FlagHq;
pItem->setUId( itemMgr.getNextUId() ); 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( getId() ) + ", " +
std::to_string( pItem->getUId() ) + ", " + std::to_string( pItem->getUId() ) + ", " +
std::to_string( pItem->getReservedFlag() ) + ", " +
std::to_string( pItem->getId() ) + ", " + std::to_string( pItem->getId() ) + ", " +
std::to_string( pItem->getStackSize() ) + ", " + std::to_string( pItem->getStackSize() ) + ", " +
std::to_string( flags ) + ");"; 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() bool Sapphire::Entity::Player::loadInventory()
{ {
auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref(); auto& itemMgr = Common::Service< World::Manager::ItemMgr >::ref();

View file

@ -132,15 +132,16 @@ Sapphire::ItemPtr Sapphire::World::Manager::ItemMgr::loadItem( uint64_t uId )
try try
{ {
auto itemInfo = exdData.get< Sapphire::Data::Item >( itemRes->getUInt( 1 ) ); 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, ItemPtr pItem = make_Item( uId,
itemRes->getUInt( 1 ), itemRes->getUInt( 1 ),
isHq ); isHq );
pItem->setStackSize( itemRes->getUInt( 2 ) ); pItem->setStackSize( itemRes->getUInt( 2 ) );
pItem->setStain( itemRes->getUInt16( 13 ) ); pItem->setReservedFlag( itemRes->getUInt( 3 ) );
pItem->setDurability( itemRes->getInt16( 6 ) ); pItem->setDurability( itemRes->getInt16( 6 ) );
pItem->setStain( itemRes->getUInt16( 13 ) );
return pItem; return pItem;
} }

View file

@ -183,14 +183,16 @@ uint32_t CalcStats::calculateMaxHp( PlayerPtr pPlayer )
return result; return result;
} }
float CalcStats::dodgeProbability( const Sapphire::Entity::Chara& chara ) float CalcStats::dodgeProbability( Sapphire::Entity::Chara& chara )
{ {
// dummy value: 5% for players. // dummy value: 5% for players.
return chara.isPlayer() ? 5 : 0; 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 level = chara.getLevel();
auto blockRate = static_cast< float >( chara.getStatValue( Common::BaseParam::BlockRate ) ); auto blockRate = static_cast< float >( chara.getStatValue( Common::BaseParam::BlockRate ) );
auto levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); auto levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] );
@ -205,7 +207,7 @@ float CalcStats::blockProbability( const Chara& chara )
return result; return result;
} }
float CalcStats::parryProbability( const Sapphire::Entity::Chara& chara ) float CalcStats::parryProbability( Sapphire::Entity::Chara& chara )
{ {
// dummy value: 10% for players. // dummy value: 10% for players.
float result = chara.isPlayer() ? 10 : 0; float result = chara.isPlayer() ? 10 : 0;
@ -844,7 +846,7 @@ float CalcStats::calcAbsorbHP( Sapphire::Entity::CharaPtr pChara, float damage )
return result; return result;
} }
bool CalcStats::calcDodge( const Sapphire::Entity::Chara& chara ) bool CalcStats::calcDodge( Sapphire::Entity::Chara& chara )
{ {
if( dodgeProbability( chara ) > getRandomNumber0To100() ) if( dodgeProbability( chara ) > getRandomNumber0To100() )
{ {
@ -853,7 +855,7 @@ bool CalcStats::calcDodge( const Sapphire::Entity::Chara& chara )
return false; 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() ) if( blockProbability( chara ) > getRandomNumber0To100() )
{ {
@ -862,7 +864,7 @@ float CalcStats::calcBlock( const Sapphire::Entity::Chara& chara, float damage )
return 0; 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() ) if( parryProbability( chara ) > getRandomNumber0To100() )
{ {

View file

@ -16,14 +16,14 @@ namespace Sapphire::Math
static uint32_t calculateMaxHp( Sapphire::Entity::PlayerPtr pPlayer ); 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 * @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 * @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 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(); static float getRandomNumber0To100();
private: private: