diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h index 10a34cd0..a9c5905f 100644 --- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h @@ -368,8 +368,8 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket uint32_t u20; uint32_t ownerId; uint32_t u22; - uint32_t hPCurr; uint32_t hPMax; + uint32_t hPCurr; uint32_t displayFlags; uint16_t fateID; uint16_t mPCurr; diff --git a/src/servers/Server_Zone/Action/ActionCast.cpp b/src/servers/Server_Zone/Action/ActionCast.cpp index df132950..a28125c7 100644 --- a/src/servers/Server_Zone/Action/ActionCast.cpp +++ b/src/servers/Server_Zone/Action/ActionCast.cpp @@ -92,7 +92,11 @@ void Core::Action::ActionCast::onInterrupt() m_pSource->getAsPlayer()->sendStateFlags(); auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, - 0x219, 1, m_id, 1 ); + 0x219, 1, m_id, 0 ); + + // Note: When cast interrupt from taking too much damage, set the last value to 1. This enables the cast interrupt effect. Example: + // auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 ); + m_pSource->sendToInRangeSet( control, true ); } diff --git a/src/servers/Server_Zone/Actor/Actor.cpp b/src/servers/Server_Zone/Actor/Actor.cpp index 977cdd6e..33f20c6b 100644 --- a/src/servers/Server_Zone/Actor/Actor.cpp +++ b/src/servers/Server_Zone/Actor/Actor.cpp @@ -696,9 +696,13 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint32_t actionId, u if ( isPlayer() && !ActionCollision::isActorApplicable( pTarget.shared_from_this(), TargetFilter::Enemies ) ) break; - pTarget.takeDamage( static_cast< uint32_t >( param1 ) ); - pTarget.onActionHostile( shared_from_this() ); sendToInRangeSet( effectPacket, true ); + + pTarget.takeDamage( static_cast< uint32_t >( param1 ) ); + + if ( pTarget.isAlive() ) + pTarget.onActionHostile( shared_from_this() ); + } else { @@ -711,8 +715,11 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint32_t actionId, u effectPacket.data().effectTarget = pHitActor->getId(); sendToInRangeSet( effectPacket, true ); // todo: send to range of what? ourselves? when mob script hits this is going to be lacking + pHitActor->takeDamage( static_cast< uint32_t >( param1 ) ); - pHitActor->onActionHostile( shared_from_this() ); + + if( pHitActor->isAlive() ) + pHitActor->onActionHostile( shared_from_this() ); // Debug if ( isPlayer() ) diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 54b7270e..cd4b0c68 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -1415,6 +1415,12 @@ void Core::Entity::Player::setIsLogin( bool bIsLogin ) m_bIsLogin = bIsLogin; } +void Core::Entity::Player::setTitle( uint16_t titleId ) +{ + m_title = titleId; + sendToInRangeSet( ActorControlPacket142( getId(), SetTitle, titleId ), true ); +} + void Core::Entity::Player::autoAttack( ActorPtr pTarget ) { diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index 1001251a..f64c1d75 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -328,6 +328,8 @@ public: void teleport( uint16_t aetheryteId, uint8_t type = 1 ); /*! prepares zoning / fades out the screen */ void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 ); + /*! change player's title */ + void setTitle( uint16_t titleId ); void calculateStats() override; void sendStats(); @@ -565,7 +567,8 @@ private: uint8_t status; } m_retainerInfo[8]; - uint8_t m_titleList[32]; + uint16_t m_title; + uint16_t m_titleList[32]; uint8_t m_achievement[16]; uint8_t m_howTo[33]; uint8_t m_homePoint; diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp index a9669cef..acfbad2c 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp @@ -257,6 +257,13 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye pPlayer->sendModel(); pPlayer->sendDebug( "Model updated" ); } + else if ( subCommand == "title" ) + { + uint32_t titleId; + sscanf( params.c_str(), "%d", &titleId ); + + pPlayer->setTitle( titleId ); + } else { pPlayer->sendUrgent( subCommand + " is not a valid SET command." ); diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index 01f2e024..09d76e94 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -114,7 +114,7 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } case 0x69: // Cancel cast { - if( pPlayer->checkAction() ) + if( pPlayer->getCurrentAction() != nullptr ) pPlayer->getCurrentAction()->setInterrupted(); break; } diff --git a/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h b/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h index 5bd39a09..c4be1206 100644 --- a/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h @@ -70,7 +70,7 @@ namespace Server { //m_data.u23 = 0x04; //m_data.u24 = 256; - m_data.state = 1; + m_data.state = static_cast< uint8_t >( pPlayer->getStatus() ); m_data.type = 1; if( pTarget == pPlayer ) {