mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 14:37:44 +00:00
Merge pull request #747 from hkAlice/slippin-fallin-cant-get-up
[3.0] fall damage implementation;
This commit is contained in:
commit
67d3d28a75
3 changed files with 82 additions and 13 deletions
|
@ -2153,6 +2153,64 @@ Sapphire::Entity::Player::FriendListIDVec& Sapphire::Entity::Player::getBlacklis
|
|||
return m_blacklist;
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool ignoreDamage )
|
||||
{
|
||||
bool isFalling = m_falling;
|
||||
auto initialPos = m_initialFallPos;
|
||||
|
||||
// update internal values - only use scoped values for old state
|
||||
m_falling = state;
|
||||
m_initialFallPos = pos;
|
||||
|
||||
if( ignoreDamage )
|
||||
return;
|
||||
|
||||
// if the player is currently falling and new state is grounded - calc and apply fall dmg
|
||||
if( isFalling && !state )
|
||||
{
|
||||
// calc height difference
|
||||
auto fallHeight = initialPos.y - pos.y;
|
||||
|
||||
// if we've hit the breakpoint in fall damage (min: 10y)
|
||||
if( fallHeight >= 10.f )
|
||||
{
|
||||
// calculate how much damage to deal out (max. 20y : 100%)
|
||||
float deltaMax = std::min( fallHeight, 20.f );
|
||||
|
||||
// get hp percentage starting from 0.1, increasing to 100% at max height
|
||||
float hpPer = std::min( 0.1f + ( deltaMax - 10.f ) / 10.f, 1.f );
|
||||
|
||||
uint32_t damage = getMaxHp() * hpPer;
|
||||
|
||||
// check if player has aggro - if not, player should "live"
|
||||
if( m_actorIdTohateSlotMap.empty() )
|
||||
{
|
||||
// "trick" client into thinking we took more damage than internally passed to takeDamage, if > playerHp
|
||||
uint32_t surviveDamage = damage;
|
||||
|
||||
if( surviveDamage >= getHp() )
|
||||
{
|
||||
surviveDamage = ( getHp() - 1 );
|
||||
}
|
||||
|
||||
takeDamage( surviveDamage );
|
||||
}
|
||||
else
|
||||
{
|
||||
// no mercy on hated players
|
||||
takeDamage( damage );
|
||||
}
|
||||
|
||||
sendToInRangeSet( makeActorControl( getId(), DmgTakenMsg, damage ), true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Sapphire::Entity::Player::isFalling() const
|
||||
{
|
||||
return m_falling;
|
||||
}
|
||||
|
||||
void Sapphire::Entity::Player::setLastPcSearchResult( std::vector< uint32_t > result )
|
||||
{
|
||||
m_lastPcSearch = std::move( result );
|
||||
|
|
|
@ -821,7 +821,9 @@ namespace Sapphire::Entity
|
|||
|
||||
uint64_t m_lastMoveTime{};
|
||||
uint8_t m_lastMoveflag{};
|
||||
bool m_falling;
|
||||
|
||||
void setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool ignoreDamage = false );
|
||||
bool isFalling() const;
|
||||
|
||||
// todo: sort this requestkey pcsearch mess
|
||||
void setLastPcSearchResult( std::vector< uint32_t > result );
|
||||
|
@ -844,6 +846,10 @@ namespace Sapphire::Entity
|
|||
|
||||
uint8_t m_mode{};
|
||||
|
||||
// falling logic
|
||||
bool m_falling;
|
||||
Common::FFXIVARR_POSITION3 m_initialFallPos{};
|
||||
|
||||
bool m_markedForRemoval;
|
||||
|
||||
bool m_directorInitialized;
|
||||
|
|
|
@ -232,13 +232,10 @@ void Sapphire::Network::GameConnection::moveHandler( const Packets::FFXIVARR_PAC
|
|||
if( ( player.getCurrentAction() != nullptr ) && bPosChanged )
|
||||
player.getCurrentAction()->setInterrupted( Common::ActionInterruptType::RegularInterrupt );
|
||||
|
||||
// if no one is in range, don't bother trying to send a position update
|
||||
if( !player.hasInRangeActor() )
|
||||
return;
|
||||
|
||||
auto clientAnimationType = data.flag;
|
||||
auto animationState = data.flag;
|
||||
auto animationType = data.flag2;
|
||||
auto animColType = data.flag2;
|
||||
auto headRotation = data.flag_unshared;
|
||||
uint8_t orgAnimationType = animationType;
|
||||
uint8_t unknownRotation = 0;
|
||||
|
@ -262,34 +259,42 @@ void Sapphire::Network::GameConnection::moveHandler( const Packets::FFXIVARR_PAC
|
|||
}
|
||||
if( animationType & MoveType::Jumping )
|
||||
{
|
||||
if( animationState == MoveState::LeaveCollision )
|
||||
|
||||
if( animColType == MoveState::LeaveCollision )
|
||||
{
|
||||
if( orgAnimationType & clientAnimationType )
|
||||
animationType += 0x10;
|
||||
else
|
||||
animationType += 0x04;
|
||||
}
|
||||
if( animationState == MoveState::StartFalling )
|
||||
player.m_falling = true;
|
||||
if( animationState == MoveState::EnterCollision )
|
||||
|
||||
if( animColType == MoveState::LeaveCollision || animColType == MoveState::StartFalling )
|
||||
{
|
||||
animationType = 2;
|
||||
player.m_falling = false;
|
||||
player.setFalling( true, { data.pos.x, data.pos.y, data.pos.z } );
|
||||
}
|
||||
}
|
||||
|
||||
if( player.m_falling )
|
||||
if( animColType == MoveState::EnterCollision )
|
||||
{
|
||||
animationType = 2;
|
||||
player.setFalling( false, { data.pos.x, data.pos.y, data.pos.z } );
|
||||
}
|
||||
|
||||
if( player.isFalling() )
|
||||
{
|
||||
animationType += 0x10;
|
||||
unknownRotation = 0x7F;
|
||||
}
|
||||
|
||||
|
||||
uint64_t currentTime = Util::getTimeMs();
|
||||
|
||||
player.m_lastMoveTime = currentTime;
|
||||
player.m_lastMoveflag = animationType;
|
||||
|
||||
// if no one is in range, don't bother trying to send a position update
|
||||
if( !player.hasInRangeActor() )
|
||||
return;
|
||||
|
||||
//auto movePacket = std::make_shared< MoveActorPacket >( player, headRotation, animationType, animationState, animationSpeed, unknownRotation );
|
||||
auto movePacket = std::make_shared< MoveActorPacket >( player, headRotation, data.flag, data.flag2, animationSpeed, unknownRotation );
|
||||
player.sendToInRangeSet( movePacket );
|
||||
|
|
Loading…
Add table
Reference in a new issue