mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 08:27:46 +00:00
Merge branch 'master' of https://github.com/SapphireMordred/Sapphire
This commit is contained in:
commit
19d84b5eb3
40 changed files with 1123 additions and 295 deletions
|
@ -587,7 +587,7 @@ namespace Sapphire::Common
|
||||||
WaterCluster = 0x12
|
WaterCluster = 0x12
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct ZoneingType : uint8_t
|
enum struct ZoningType : uint8_t
|
||||||
{
|
{
|
||||||
None = 1,
|
None = 1,
|
||||||
Teleport = 2,
|
Teleport = 2,
|
||||||
|
|
|
@ -548,6 +548,7 @@ namespace Sapphire::Network::ActorControl
|
||||||
REQUEST_SALVAGE_SUCCESS_RATE = 0x1B2,
|
REQUEST_SALVAGE_SUCCESS_RATE = 0x1B2,
|
||||||
MOBHUNT_RECEIPT_ORDER = 0x1B3,
|
MOBHUNT_RECEIPT_ORDER = 0x1B3,
|
||||||
MOBHUNT_BREAK_ORDER = 0x1B4,
|
MOBHUNT_BREAK_ORDER = 0x1B4,
|
||||||
|
DYE_ITEM = 0x1B5,
|
||||||
EMOTE = 0x1F4,
|
EMOTE = 0x1F4,
|
||||||
EMOTE_WITH_WARP = 0x1F5,
|
EMOTE_WITH_WARP = 0x1F5,
|
||||||
EMOTE_CANCEL = 0x1F6,
|
EMOTE_CANCEL = 0x1F6,
|
||||||
|
|
|
@ -1145,6 +1145,12 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
ZoneProtoDownNormalItem item;
|
ZoneProtoDownNormalItem item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcUpdateItem : FFXIVIpcBasePacket< UpdateItem >
|
||||||
|
{
|
||||||
|
uint32_t contextId;
|
||||||
|
ZoneProtoDownNormalItem item;
|
||||||
|
};
|
||||||
|
|
||||||
struct FFXIVIpcItemSize : FFXIVIpcBasePacket< ItemSize >
|
struct FFXIVIpcItemSize : FFXIVIpcBasePacket< ItemSize >
|
||||||
{
|
{
|
||||||
uint32_t contextId;
|
uint32_t contextId;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <ScriptObject.h>
|
#include <ScriptObject.h>
|
||||||
#include <Actor/Player.h>
|
#include <Actor/Player.h>
|
||||||
#include <Action/Action.h>
|
#include <Action/Action.h>
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
#include <Service.h>
|
||||||
|
|
||||||
class ActionReturn6 :
|
class ActionReturn6 :
|
||||||
public Sapphire::ScriptAPI::ActionScript
|
public Sapphire::ScriptAPI::ActionScript
|
||||||
|
@ -17,7 +19,9 @@ public:
|
||||||
if( !action.getSourceChara()->isPlayer() )
|
if( !action.getSourceChara()->isPlayer() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
action.getSourceChara()->getAsPlayer()->teleport( action.getSourceChara()->getAsPlayer()->getHomepoint(), 3 );
|
auto pPlayer = action.getSourceChara()->getAsPlayer();
|
||||||
|
|
||||||
|
warpMgr().requestPlayerTeleport( *pPlayer, pPlayer->getHomepoint(), 3 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,26 +16,27 @@ public:
|
||||||
|
|
||||||
void onExecute( Sapphire::World::Action::Action& action ) override
|
void onExecute( Sapphire::World::Action::Action& action ) override
|
||||||
{
|
{
|
||||||
auto player = action.getSourceChara()->getAsPlayer();
|
auto pPlayer = action.getSourceChara()->getAsPlayer();
|
||||||
|
|
||||||
if( !player )
|
if( !pPlayer )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto teleportQuery = player->getTeleportQuery();
|
auto teleportQuery = pPlayer->getTeleportQuery();
|
||||||
|
|
||||||
if( player->getCurrency( Common::CurrencyType::Gil ) < teleportQuery.cost ||
|
if( pPlayer->getCurrency( Common::CurrencyType::Gil ) < teleportQuery.cost ||
|
||||||
teleportQuery.targetAetheryte == 0 )
|
teleportQuery.targetAetheryte == 0 )
|
||||||
{
|
{
|
||||||
action.interrupt();
|
action.interrupt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player->removeCurrency( Common::CurrencyType::Gil, teleportQuery.cost );
|
pPlayer->removeCurrency( Common::CurrencyType::Gil, teleportQuery.cost );
|
||||||
|
|
||||||
player->setZoningType( Common::ZoneingType::Teleport );
|
pPlayer->setZoningType( Common::ZoningType::Teleport );
|
||||||
player->teleport( teleportQuery.targetAetheryte );
|
|
||||||
|
|
||||||
player->clearTeleportQuery();
|
warpMgr().requestPlayerTeleport( *pPlayer, teleportQuery.targetAetheryte, 1 );
|
||||||
|
|
||||||
|
pPlayer->clearTeleportQuery();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
auto destination = result.getResult( 0 );
|
auto destination = result.getResult( 0 );
|
||||||
if( result.numOfResults == 1 && destination != 0 )
|
if( result.numOfResults == 1 && destination != 0 )
|
||||||
{
|
{
|
||||||
player.teleport( destination, 2 );
|
warpMgr().requestPlayerTeleport( player, destination, 2 );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ public:
|
||||||
auto data = result.getResult( 1 );
|
auto data = result.getResult( 1 );
|
||||||
if( cmd == 4 && data != 0 )
|
if( cmd == 4 && data != 0 )
|
||||||
{
|
{
|
||||||
player.teleport( data, 2 );
|
warpMgr().requestPlayerTeleport( player, data, 2 );
|
||||||
}
|
}
|
||||||
else if( cmd == 2 ) // register favored destination
|
else if( cmd == 2 ) // register favored destination
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,8 +101,8 @@ private:
|
||||||
|
|
||||||
void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
void Scene00001Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
||||||
{
|
{
|
||||||
player.setGc( OrderOfTwinAdder );
|
playerMgr().onSetGc( player, OrderOfTwinAdder );
|
||||||
player.setGcRankAt( OrderOfTwinAdder, 1 );
|
playerMgr().onSetGcRank( player, OrderOfTwinAdder, 1 );
|
||||||
Scene00002( quest, player );
|
Scene00002( quest, player );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
218
src/scripts/quest/subquest/goldsaucer/SubGsc001.cpp
Normal file
218
src/scripts/quest/subquest/goldsaucer/SubGsc001.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
// FFXIVTheMovie.ParserV3.10
|
||||||
|
// param used:
|
||||||
|
//ACTOR1 = dummy1
|
||||||
|
//SCENE_2 = dummy1
|
||||||
|
//SCENE_5 = ELYENORA
|
||||||
|
#include <Actor/Player.h>
|
||||||
|
#include <ScriptObject.h>
|
||||||
|
#include <Service.h>
|
||||||
|
#include "Manager/TerritoryMgr.h"
|
||||||
|
#include "Manager/EventMgr.h"
|
||||||
|
#include "Territory/Territory.h"
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
|
||||||
|
class SubGsc001 : public Sapphire::ScriptAPI::QuestScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SubGsc001() : Sapphire::ScriptAPI::QuestScript( 65970 ){};
|
||||||
|
~SubGsc001() = default;
|
||||||
|
|
||||||
|
//SEQ_0, 2 entries
|
||||||
|
//SEQ_255, 3 entries
|
||||||
|
|
||||||
|
//ACTOR0 = 1011565
|
||||||
|
//ACTOR1 = 1011566
|
||||||
|
//ACTOR2 = 1004433
|
||||||
|
//BGM0 = 250
|
||||||
|
//ITEM0 = 2001555
|
||||||
|
//NCUT0 = 769
|
||||||
|
//NCUT1 = 770
|
||||||
|
//POPRANGE0 = 5654039
|
||||||
|
//SCREENIMAGE0 = 272
|
||||||
|
|
||||||
|
static constexpr auto EVENT_ON_TALK = 0;
|
||||||
|
static constexpr auto EVENT_ON_EMOTE = 1;
|
||||||
|
static constexpr auto EVENT_ON_BNPC_KILL = 2;
|
||||||
|
static constexpr auto EVENT_ON_WITHIN_RANGE = 3;
|
||||||
|
static constexpr auto EVENT_ON_ENTER_TERRITORY = 4;
|
||||||
|
static constexpr auto EVENT_ON_EVENT_ITEM = 5;
|
||||||
|
static constexpr auto EVENT_ON_EOBJ_HIT = 6;
|
||||||
|
static constexpr auto EVENT_ON_SAY = 7;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onProgress( World::Quest& quest, Entity::Player& player, uint32_t type, uint64_t param1, uint32_t param2, uint32_t param3 )
|
||||||
|
{
|
||||||
|
switch( quest.getSeq() )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if( param1 == 1011565 ) // ACTOR0 = TRADER00434
|
||||||
|
{
|
||||||
|
if( quest.getUI8AL() != 1 )
|
||||||
|
{
|
||||||
|
Scene00000( quest, player ); // Scene00000: Normal(QuestOffer), id=unknown
|
||||||
|
// +Callback Scene00001: Normal(Talk, QuestAccept, TargetCanMove), id=TRADER00434
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( param1 == 1011566 ) // ACTOR1 = dummy1
|
||||||
|
{
|
||||||
|
Scene00002( quest, player ); // Scene00002: Empty(None), id=dummy1
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//seq 255 event item ITEM0 = UI8BH max stack 1
|
||||||
|
case 255:
|
||||||
|
{
|
||||||
|
if( param1 == 1004433 ) // ACTOR2 = ELYENORA
|
||||||
|
{
|
||||||
|
Scene00003( quest, player ); // Scene00003: NpcTrade(Talk, TargetCanMove), id=unknown
|
||||||
|
// +Callback Scene00004: Normal(Talk, YesNo, TargetCanMove, CanCancel), id=ELYENORA
|
||||||
|
// +Callback Scene00005: Normal(CutScene, FadeIn, QuestReward, QuestComplete, AutoFadeIn), id=ELYENORA
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( param1 == 1011565 ) // ACTOR0 = TRADER00434
|
||||||
|
{
|
||||||
|
Scene00006( quest, player ); // Scene00006: Normal(Talk, TargetCanMove), id=TRADER00434
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( param1 == 1011566 ) // ACTOR1 = unknown
|
||||||
|
{
|
||||||
|
Scene00007( quest, player ); // Scene00007: Empty(None), id=unknown
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
playerMgr().sendUrgent( player, "Sequence {} not defined.", quest.getSeq() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_TALK, actorId, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEmote( World::Quest& quest, uint64_t actorId, uint32_t emoteId, Sapphire::Entity::Player& player ) override
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "emote: {}", emoteId );
|
||||||
|
onProgress( quest, player, EVENT_ON_EMOTE, actorId, 0, emoteId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWithinRange( World::Quest& quest, Sapphire::Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_WITHIN_RANGE, static_cast< uint64_t >( param1 ), 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEnterTerritory( World::Quest& quest, Sapphire::Entity::Player& player, uint16_t param1, uint16_t param2 ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_ENTER_TERRITORY, static_cast< uint64_t >( param1 ), static_cast< uint32_t >( param2 ), 0 );
|
||||||
|
}
|
||||||
|
void onEventItem( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_EVENT_ITEM, actorId, 0, 0 );
|
||||||
|
}
|
||||||
|
void onEObjHit( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId, uint32_t actionId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_EOBJ_HIT, actorId, actionId, 0 );
|
||||||
|
}
|
||||||
|
void onSay( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId, uint32_t sayId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_SAY, actorId, sayId, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkProgressSeq0( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 255 );
|
||||||
|
quest.setUI8BH( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00000( World::Quest& quest, Entity::Player& player ) //SEQ_0: ACTOR0, UI8AL = 1, Flag8(1)=True
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00000: Normal(QuestOffer), id=unknown" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.numOfResults > 0 && result.getResult( 0 ) == 1 )
|
||||||
|
{
|
||||||
|
Scene00001( quest, player );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 0, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
void Scene00001( World::Quest& quest, Entity::Player& player ) //SEQ_0: ACTOR0, UI8AL = 1, Flag8(1)=True
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00001: Normal(Talk, QuestAccept, TargetCanMove), id=TRADER00434" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq0( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00002( World::Quest& quest, Entity::Player& player ) //SEQ_0: ACTOR1, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00002: Empty(None), id=dummy1" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00003( World::Quest& quest, Entity::Player& player ) //SEQ_255: ACTOR2, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00003: NpcTrade(Talk, TargetCanMove), id=unknown" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.numOfResults > 0 && result.getResult( 0 ) == 1 )
|
||||||
|
{
|
||||||
|
Scene00004( quest, player );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
void Scene00004( World::Quest& quest, Entity::Player& player ) //SEQ_255: ACTOR2, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00004: Normal(Talk, YesNo, TargetCanMove, CanCancel), id=ELYENORA" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.errorCode == 0 || ( result.numOfResults > 0 && result.getResult( 0 ) == 1 ) )
|
||||||
|
{
|
||||||
|
Scene00005( quest, player );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 4, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
void Scene00005( World::Quest& quest, Entity::Player& player ) //SEQ_255: ACTOR2, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00005: Normal(CutScene, FadeIn, QuestReward, QuestComplete, AutoFadeIn), id=ELYENORA" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.numOfResults > 0 && result.getResult( 0 ) == 1 )
|
||||||
|
{
|
||||||
|
player.finishQuest( getId(), result.getResult( 1 ) );
|
||||||
|
eventMgr().eventFinish( player, result.eventId, 1 );
|
||||||
|
warpMgr().requestMoveTerritory( player, Common::WarpType::WARP_TYPE_NORMAL, teriMgr().getZoneByTerritoryTypeId( 144 )->getGuId(), { -34.5, 0.64, 100 }, -1.58 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 5, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00006( World::Quest& quest, Entity::Player& player ) //SEQ_255: ACTOR0, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00006: Normal(Talk, TargetCanMove), id=TRADER00434" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 6, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00007( World::Quest& quest, Entity::Player& player ) //SEQ_255: ACTOR1, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc001:65970 calling Scene00007: Empty(None), id=unknown" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPOSE_SCRIPT( SubGsc001 );
|
296
src/scripts/quest/subquest/goldsaucer/SubGsc002.cpp
Normal file
296
src/scripts/quest/subquest/goldsaucer/SubGsc002.cpp
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
// FFXIVTheMovie.ParserV3.10
|
||||||
|
#include <Actor/Player.h>
|
||||||
|
#include <ScriptObject.h>
|
||||||
|
#include <Service.h>
|
||||||
|
#include "Manager/TerritoryMgr.h"
|
||||||
|
#include "Manager/EventMgr.h"
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
|
||||||
|
class SubGsc002 : public Sapphire::ScriptAPI::QuestScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SubGsc002() : Sapphire::ScriptAPI::QuestScript( 65971 ){};
|
||||||
|
~SubGsc002() = default;
|
||||||
|
|
||||||
|
//SEQ_0, 1 entries
|
||||||
|
//SEQ_1, 2 entries
|
||||||
|
//SEQ_2, 1 entries
|
||||||
|
//SEQ_3, 1 entries
|
||||||
|
//SEQ_4, 1 entries
|
||||||
|
//SEQ_5, 1 entries
|
||||||
|
//SEQ_6, 1 entries
|
||||||
|
//SEQ_255, 1 entries
|
||||||
|
|
||||||
|
//ACTOR0 = 1011022
|
||||||
|
//ACTOR1 = 1010448
|
||||||
|
//ACTOR2 = 1011038
|
||||||
|
//ACTOR3 = 1010478
|
||||||
|
//ACTOR4 = 1011080
|
||||||
|
//ACTOR5 = 1011079
|
||||||
|
//ACTOR6 = 1011084
|
||||||
|
//BGM0 = 250
|
||||||
|
//LOCACTIONTIMELINE001 = 1072
|
||||||
|
//LOCCHECKQUEST001 = 66996
|
||||||
|
//LOCCHECKQUEST002 = 65625
|
||||||
|
//LOCCHECKQUEST003 = 65964
|
||||||
|
//LOCENPC001 = 1011586
|
||||||
|
//LOCLEVELENPC001 = 5581118
|
||||||
|
//LOCLEVELENPC002 = 5581208
|
||||||
|
//LOCLEVELENPC003 = 5584143
|
||||||
|
//LOCLEVELENPC004 = 5653245
|
||||||
|
//LOCLEVELENPC005 = 5581064
|
||||||
|
|
||||||
|
static constexpr auto EVENT_ON_TALK = 0;
|
||||||
|
static constexpr auto EVENT_ON_EMOTE = 1;
|
||||||
|
static constexpr auto EVENT_ON_BNPC_KILL = 2;
|
||||||
|
static constexpr auto EVENT_ON_WITHIN_RANGE = 3;
|
||||||
|
static constexpr auto EVENT_ON_ENTER_TERRITORY = 4;
|
||||||
|
static constexpr auto EVENT_ON_EVENT_ITEM = 5;
|
||||||
|
static constexpr auto EVENT_ON_EOBJ_HIT = 6;
|
||||||
|
static constexpr auto EVENT_ON_SAY = 7;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onProgress( World::Quest& quest, Entity::Player& player, uint32_t type, uint64_t param1, uint32_t param2, uint32_t param3 )
|
||||||
|
{
|
||||||
|
switch( quest.getSeq() )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00000( quest, player ); // Scene00000: Normal(QuestOffer, TargetCanMove), id=unknown
|
||||||
|
// +Callback Scene00001: Normal(Talk, QuestAccept, TargetCanMove), id=RECEPTIONIDT00434
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if( param1 == 1010448 ) // ACTOR1 = INFORMATION00435
|
||||||
|
{
|
||||||
|
if( quest.getUI8AL() != 1 )
|
||||||
|
{
|
||||||
|
Scene00002( quest, player ); // Scene00002: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=INFORMATION00435
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( param1 == 1011022 ) // ACTOR0 = RECEPTIONIDT00434
|
||||||
|
{
|
||||||
|
Scene00003( quest, player ); // Scene00003: Normal(Talk, TargetCanMove), id=RECEPTIONIDT00434
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00004( quest, player ); // Scene00004: Normal(Talk, TargetCanMove), id=EXCHANGE00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00005( quest, player ); // Scene00005: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=CARDSHOP00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00006( quest, player ); // Scene00006: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=GATENPCA00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00007( quest, player ); // Scene00007: Normal(Talk, FadeIn, TargetCanMove), id=BUNNY00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00008( quest, player ); // Scene00008: Normal(Talk, FadeIn, TargetCanMove), id=GATENPCB00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 255:
|
||||||
|
{
|
||||||
|
if( type != EVENT_ON_BNPC_KILL ) Scene00009( quest, player ); // Scene00009: Normal(Talk, FadeIn, QuestReward, QuestComplete, TargetCanMove), id=INFORMATION00435
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
playerMgr().sendUrgent( player, "Sequence {} not defined.", quest.getSeq() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void onTalk( World::Quest& quest, Entity::Player& player, uint64_t actorId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_TALK, actorId, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEmote( World::Quest& quest, uint64_t actorId, uint32_t emoteId, Sapphire::Entity::Player& player ) override
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "emote: {}", emoteId );
|
||||||
|
onProgress( quest, player, EVENT_ON_EMOTE, actorId, 0, emoteId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWithinRange( World::Quest& quest, Sapphire::Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_WITHIN_RANGE, static_cast< uint64_t >( param1 ), 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEnterTerritory( World::Quest& quest, Sapphire::Entity::Player& player, uint16_t param1, uint16_t param2 ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_ENTER_TERRITORY, static_cast< uint64_t >( param1 ), static_cast< uint32_t >( param2 ), 0 );
|
||||||
|
}
|
||||||
|
void onEventItem( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_EVENT_ITEM, actorId, 0, 0 );
|
||||||
|
}
|
||||||
|
void onEObjHit( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId, uint32_t actionId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_EOBJ_HIT, actorId, actionId, 0 );
|
||||||
|
}
|
||||||
|
void onSay( World::Quest& quest, Sapphire::Entity::Player& player, uint64_t actorId, uint32_t sayId ) override
|
||||||
|
{
|
||||||
|
onProgress( quest, player, EVENT_ON_SAY, actorId, sayId, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkProgressSeq0( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 1 );
|
||||||
|
}
|
||||||
|
void checkProgressSeq1( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
if( quest.getUI8AL() == 1 )
|
||||||
|
{
|
||||||
|
quest.setUI8AL( 0 );
|
||||||
|
quest.setBitFlag8( 1, false );
|
||||||
|
quest.setSeq( 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void checkProgressSeq2( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 3 );
|
||||||
|
}
|
||||||
|
void checkProgressSeq3( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 4 );
|
||||||
|
}
|
||||||
|
void checkProgressSeq4( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 5 );
|
||||||
|
}
|
||||||
|
void checkProgressSeq5( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 6 );
|
||||||
|
}
|
||||||
|
void checkProgressSeq6( World::Quest& quest, Entity::Player& player )
|
||||||
|
{
|
||||||
|
quest.setSeq( 255 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00000( World::Quest& quest, Entity::Player& player ) //SEQ_0: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00000: Normal(QuestOffer, TargetCanMove), id=unknown" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.numOfResults > 0 && result.getResult( 0 ) == 1 )
|
||||||
|
{
|
||||||
|
Scene00001( quest, player );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 0, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
void Scene00001( World::Quest& quest, Entity::Player& player ) //SEQ_0: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00001: Normal(Talk, QuestAccept, TargetCanMove), id=RECEPTIONIDT00434" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq0( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 1, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00002( World::Quest& quest, Entity::Player& player ) //SEQ_1: ACTOR1, UI8AL = 1, Flag8(1)=True(Todo:0)
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00002: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=INFORMATION00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
quest.setUI8AL( 1 );
|
||||||
|
quest.setBitFlag8( 1, true );
|
||||||
|
eventMgr().sendEventNotice( player, getId(), 0, 0, 0, 0 );
|
||||||
|
checkProgressSeq1( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 2, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00003( World::Quest& quest, Entity::Player& player ) //SEQ_1: ACTOR0, <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00003: Normal(Talk, TargetCanMove), id=RECEPTIONIDT00434" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 3, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00004( World::Quest& quest, Entity::Player& player ) //SEQ_2: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00004: Normal(Talk, TargetCanMove), id=EXCHANGE00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq2( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 4, HIDE_HOTBAR, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00005( World::Quest& quest, Entity::Player& player ) //SEQ_3: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00005: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=CARDSHOP00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq3( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 5, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00006( World::Quest& quest, Entity::Player& player ) //SEQ_4: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00006: Normal(Talk, FadeIn, TargetCanMove, ENpcBind), id=GATENPCA00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq4( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 6, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00007( World::Quest& quest, Entity::Player& player ) //SEQ_5: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00007: Normal(Talk, FadeIn, TargetCanMove), id=BUNNY00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq5( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 7, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00008( World::Quest& quest, Entity::Player& player ) //SEQ_6: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00008: Normal(Talk, FadeIn, TargetCanMove), id=GATENPCB00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
checkProgressSeq6( quest, player );
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 8, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene00009( World::Quest& quest, Entity::Player& player ) //SEQ_255: , <No Var>, <No Flag>
|
||||||
|
{
|
||||||
|
playerMgr().sendDebug( player, "SubGsc002:65971 calling Scene00009: Normal(Talk, FadeIn, QuestReward, QuestComplete, TargetCanMove), id=INFORMATION00435" );
|
||||||
|
auto callback = [ & ]( World::Quest& quest, Entity::Player& player , const Event::SceneResult& result )
|
||||||
|
{
|
||||||
|
if( result.numOfResults > 0 && result.getResult( 0 ) == 1 )
|
||||||
|
{
|
||||||
|
player.finishQuest( getId(), result.getResult( 1 ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventMgr().playQuestScene( player, getId(), 9, FADE_OUT | CONDITION_CUTSCENE | HIDE_UI, callback );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPOSE_SCRIPT( SubGsc002 );
|
|
@ -396,7 +396,7 @@ private:
|
||||||
{
|
{
|
||||||
eventMgr().sendEventNotice( player, getId(), 3, 0 );
|
eventMgr().sendEventNotice( player, getId(), 3, 0 );
|
||||||
quest.setSeq( Seq5 );
|
quest.setSeq( Seq5 );
|
||||||
player.setMount( Mount0 );
|
playerMgr().onMountUpdate( player, Mount0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -490,7 +490,7 @@ private:
|
||||||
|
|
||||||
void Scene00017Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
void Scene00017Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
||||||
{
|
{
|
||||||
player.setMount( Mount0 );
|
playerMgr().onMountUpdate( player, Mount0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -562,7 +562,7 @@ private:
|
||||||
|
|
||||||
void Scene00023Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
void Scene00023Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
||||||
{
|
{
|
||||||
player.setMount( Mount0 );
|
playerMgr().onMountUpdate( player, Mount0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -611,7 +611,7 @@ private:
|
||||||
{
|
{
|
||||||
eventMgr().sendEventNotice( player, getId(), 6, 0 );
|
eventMgr().sendEventNotice( player, getId(), 6, 0 );
|
||||||
quest.setSeq( Seq8 );
|
quest.setSeq( Seq8 );
|
||||||
player.setMount( 0 );
|
playerMgr().onMountUpdate( player, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +646,7 @@ private:
|
||||||
|
|
||||||
void Scene00030Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
void Scene00030Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result )
|
||||||
{
|
{
|
||||||
player.setMount( Mount0 );
|
playerMgr().onMountUpdate( player, Mount0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -320,7 +320,7 @@ void Action::Action::start()
|
||||||
|
|
||||||
if( player )
|
if( player )
|
||||||
{
|
{
|
||||||
player->setStateFlag( PlayerStateFlag::Casting );
|
Service< World::Manager::PlayerMgr >::ref().onSendStateFlags( *player, PlayerStateFlag::Casting );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,14 +368,14 @@ void Action::Action::interrupt()
|
||||||
// things that aren't players don't care about cooldowns and state flags
|
// things that aren't players don't care about cooldowns and state flags
|
||||||
if( m_pSource->isPlayer() )
|
if( m_pSource->isPlayer() )
|
||||||
{
|
{
|
||||||
auto player = m_pSource->getAsPlayer();
|
auto pPlayer = m_pSource->getAsPlayer();
|
||||||
|
|
||||||
// todo: reset cooldown for actual player
|
// todo: reset cooldown for actual player
|
||||||
|
|
||||||
// reset state flag
|
// reset state flag
|
||||||
//player->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
//player->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||||
player->setLastActionTick( 0 );
|
pPlayer->setLastActionTick( 0 );
|
||||||
player->unsetStateFlag( PlayerStateFlag::Casting );
|
Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( *pPlayer, PlayerStateFlag::Casting );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( hasCastTime() )
|
if( hasCastTime() )
|
||||||
|
@ -424,10 +424,10 @@ void Action::Action::execute()
|
||||||
0x219, m_id, m_id, m_id, m_id );
|
0x219, m_id, m_id, m_id, m_id );
|
||||||
m_pSource->sendToInRangeSet( control, true );*/
|
m_pSource->sendToInRangeSet( control, true );*/
|
||||||
|
|
||||||
if( auto player = m_pSource->getAsPlayer() )
|
if( auto pPlayer = m_pSource->getAsPlayer(); pPlayer )
|
||||||
{
|
{
|
||||||
player->setLastActionTick( 0 );
|
pPlayer->setLastActionTick( 0 );
|
||||||
player->unsetStateFlag( PlayerStateFlag::Casting );
|
Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( *pPlayer, PlayerStateFlag::Casting );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include <Util/Util.h>
|
#include <Util/Util.h>
|
||||||
|
|
||||||
|
#include <Service.h>
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
|
||||||
#include "Actor/Chara.h"
|
#include "Actor/Chara.h"
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
|
|
||||||
|
@ -133,7 +136,7 @@ void EffectResult::execute()
|
||||||
case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT:
|
case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT:
|
||||||
{
|
{
|
||||||
auto pPlayer = m_target->getAsPlayer();
|
auto pPlayer = m_target->getAsPlayer();
|
||||||
pPlayer->setMount( m_value );
|
Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( *pPlayer, m_value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
#include <Exd/Structs.h>
|
#include <Exd/Structs.h>
|
||||||
#include <Network/CommonActorControl.h>
|
#include <Network/CommonActorControl.h>
|
||||||
|
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
#include <Manager/EventMgr.h>
|
||||||
|
|
||||||
#include "Network/PacketWrappers/ActorControlPacket.h"
|
#include <Network/PacketWrappers/ActorControlPacket.h>
|
||||||
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
||||||
|
#include <Network/CommonActorControl.h>
|
||||||
|
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
|
|
||||||
|
@ -14,7 +17,6 @@
|
||||||
#include "WorldServer.h"
|
#include "WorldServer.h"
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "Network/GameConnection.h"
|
#include "Network/GameConnection.h"
|
||||||
#include "Manager/EventMgr.h"
|
|
||||||
|
|
||||||
#include "EventAction.h"
|
#include "EventAction.h"
|
||||||
|
|
||||||
|
@ -54,9 +56,11 @@ void Action::EventAction::start()
|
||||||
|
|
||||||
if( m_pSource->isPlayer() )
|
if( m_pSource->isPlayer() )
|
||||||
{
|
{
|
||||||
|
auto pPlayer = m_pSource->getAsPlayer();
|
||||||
|
|
||||||
m_pSource->sendToInRangeSet( control, true );
|
m_pSource->sendToInRangeSet( control, true );
|
||||||
if( m_pSource->getAsPlayer()->hasStateFlag( PlayerStateFlag::InNpcEvent ) )
|
if( pPlayer->hasStateFlag( PlayerStateFlag::InNpcEvent ) )
|
||||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::InNpcEvent );
|
Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( *pPlayer, PlayerStateFlag::InNpcEvent );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_pSource->sendToInRangeSet( control );
|
m_pSource->sendToInRangeSet( control );
|
||||||
|
|
70
src/world/Action/ItemManipulationAction.cpp
Normal file
70
src/world/Action/ItemManipulationAction.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "ItemManipulationAction.h"
|
||||||
|
|
||||||
|
#include <Exd/ExdData.h>
|
||||||
|
|
||||||
|
#include "Script/ScriptMgr.h"
|
||||||
|
|
||||||
|
#include "Actor/Player.h"
|
||||||
|
#include "Actor/BNpc.h"
|
||||||
|
|
||||||
|
#include <Logging/Logger.h>
|
||||||
|
|
||||||
|
#include <Service.h>
|
||||||
|
#include "WorldServer.h"
|
||||||
|
|
||||||
|
using namespace Sapphire;
|
||||||
|
using namespace Sapphire::World::Action;
|
||||||
|
using namespace Sapphire::Network::Packets::WorldPackets::Server;
|
||||||
|
|
||||||
|
ItemManipulationAction::ItemManipulationAction( Entity::CharaPtr source, uint32_t actionId, uint16_t sequence,
|
||||||
|
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint32_t delayTime ) :
|
||||||
|
m_delayTimeMs( delayTime )
|
||||||
|
{
|
||||||
|
m_id = actionId;
|
||||||
|
m_pSource = std::move( source );
|
||||||
|
m_actionData = std::move( actionData );
|
||||||
|
m_sequence = sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemManipulationAction::start()
|
||||||
|
{
|
||||||
|
assert( m_pSource );
|
||||||
|
m_startTime = Common::Util::getTimeMs();
|
||||||
|
|
||||||
|
onStart();
|
||||||
|
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemManipulationAction::execute()
|
||||||
|
{
|
||||||
|
assert( m_pSource );
|
||||||
|
|
||||||
|
m_effectBuilder->buildAndSendPackets( m_hitActors );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemManipulationAction::onFinish()
|
||||||
|
{
|
||||||
|
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||||
|
|
||||||
|
// send execute event to action script
|
||||||
|
scriptMgr.onExecute( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemManipulationAction::update()
|
||||||
|
{
|
||||||
|
// action has not been started yet
|
||||||
|
if( m_startTime == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64_t tickCount = Common::Util::getTimeMs();
|
||||||
|
uint32_t delayTime = m_delayTimeMs;
|
||||||
|
|
||||||
|
if( std::difftime( static_cast< time_t >( tickCount ), static_cast< time_t >( m_startTime ) ) > delayTime )
|
||||||
|
{
|
||||||
|
onFinish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
26
src/world/Action/ItemManipulationAction.h
Normal file
26
src/world/Action/ItemManipulationAction.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
#include <Exd/Structs.h>
|
||||||
|
|
||||||
|
namespace Sapphire::World::Action
|
||||||
|
{
|
||||||
|
class ItemManipulationAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemManipulationAction( Entity::CharaPtr source, uint32_t actionId, uint16_t sequence,
|
||||||
|
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint32_t delayTime );
|
||||||
|
virtual ~ItemManipulationAction() = default;
|
||||||
|
|
||||||
|
void start() override;
|
||||||
|
|
||||||
|
void execute() override;
|
||||||
|
|
||||||
|
bool update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onFinish();
|
||||||
|
|
||||||
|
uint32_t m_delayTimeMs{};
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,17 +2,19 @@
|
||||||
|
|
||||||
#include <Exd/ExdData.h>
|
#include <Exd/ExdData.h>
|
||||||
|
|
||||||
#include "Actor/Player.h"
|
#include <Actor/Player.h>
|
||||||
|
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
|
||||||
|
#include <Network/GameConnection.h>
|
||||||
#include <Network/CommonActorControl.h>
|
#include <Network/CommonActorControl.h>
|
||||||
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
||||||
|
|
||||||
#include <Service.h>
|
#include <Service.h>
|
||||||
#include <Util/UtilMath.h>
|
#include <Util/UtilMath.h>
|
||||||
|
|
||||||
#include "WorldServer.h"
|
#include "WorldServer.h"
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "Network/GameConnection.h"
|
|
||||||
|
|
||||||
using namespace Sapphire;
|
using namespace Sapphire;
|
||||||
using namespace Sapphire::Network::Packets;
|
using namespace Sapphire::Network::Packets;
|
||||||
|
@ -59,20 +61,19 @@ void MountAction::start()
|
||||||
|
|
||||||
m_pSource->sendToInRangeSet( castPacket, true );
|
m_pSource->sendToInRangeSet( castPacket, true );
|
||||||
|
|
||||||
player->setStateFlag( Common::PlayerStateFlag::Casting );
|
Common::Service< World::Manager::PlayerMgr >::ref().onSetStateFlag( *player, Common::PlayerStateFlag::Casting );
|
||||||
|
|
||||||
auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(), m_recastTimeMs / 10 );
|
auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(), m_recastTimeMs / 10 );
|
||||||
|
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
server.queueForPlayer( m_pSource->getAsPlayer()->getCharacterId(), actionStartPkt );
|
server.queueForPlayer( m_pSource->getAsPlayer()->getCharacterId(), actionStartPkt );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MountAction::execute()
|
void MountAction::execute()
|
||||||
{
|
{
|
||||||
assert( m_pSource );
|
assert( m_pSource );
|
||||||
|
|
||||||
m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting );
|
Common::Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( *m_pSource->getAsPlayer(), Common::PlayerStateFlag::Casting );
|
||||||
m_effectBuilder->mount( m_pSource, m_mountId );
|
m_effectBuilder->mount( m_pSource, m_mountId );
|
||||||
m_effectBuilder->buildAndSendPackets( { m_pSource } );
|
m_effectBuilder->buildAndSendPackets( { m_pSource } );
|
||||||
}
|
}
|
|
@ -27,8 +27,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
using ActorStatsArray = std::array< uint32_t, STAT_ARRAY_SIZE >;
|
using ActorStatsArray = std::array< uint32_t, STAT_ARRAY_SIZE >;
|
||||||
|
|
||||||
ActorStatsArray m_baseStats;
|
ActorStatsArray m_baseStats{ 0 };
|
||||||
ActorStatsArray m_bonusStats;
|
ActorStatsArray m_bonusStats{ 0 };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char m_name[34];
|
char m_name[34];
|
||||||
|
|
|
@ -71,7 +71,7 @@ Player::Player() :
|
||||||
m_lastActionTick( 0 ),
|
m_lastActionTick( 0 ),
|
||||||
m_bInCombat( false ),
|
m_bInCombat( false ),
|
||||||
m_bLoadingComplete( false ),
|
m_bLoadingComplete( false ),
|
||||||
m_zoningType( Common::ZoneingType::None ),
|
m_zoningType( Common::ZoningType::None ),
|
||||||
m_bAutoattack( false ),
|
m_bAutoattack( false ),
|
||||||
m_markedForRemoval( false ),
|
m_markedForRemoval( false ),
|
||||||
m_mount( 0 ),
|
m_mount( 0 ),
|
||||||
|
@ -318,6 +318,8 @@ void Player::removeOnlineStatus( const std::vector< Common::OnlineStatus >& stat
|
||||||
|
|
||||||
void Player::calculateStats()
|
void Player::calculateStats()
|
||||||
{
|
{
|
||||||
|
calculateBonusStats();
|
||||||
|
|
||||||
uint8_t tribe = getLookAt( Common::CharaLook::Tribe );
|
uint8_t tribe = getLookAt( Common::CharaLook::Tribe );
|
||||||
uint8_t level = getLevel();
|
uint8_t level = getLevel();
|
||||||
auto job = static_cast< uint8_t >( getClass() );
|
auto job = static_cast< uint8_t >( getClass() );
|
||||||
|
@ -404,72 +406,6 @@ void Player::sendStats()
|
||||||
Service< World::Manager::PlayerMgr >::ref().onSendStats( *this );
|
Service< World::Manager::PlayerMgr >::ref().onSendStats( *this );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::teleport( uint16_t aetheryteId, uint8_t type )
|
|
||||||
{
|
|
||||||
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
||||||
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
|
||||||
auto& warpMgr = Common::Service< WarpMgr >::ref();
|
|
||||||
|
|
||||||
auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId );
|
|
||||||
|
|
||||||
if( !aetherData )
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& data = aetherData->data();
|
|
||||||
|
|
||||||
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
|
||||||
auto pop = instanceObjectCache.getPopRangeInfo( data.PopRange[ 0 ] );
|
|
||||||
|
|
||||||
Common::FFXIVARR_POSITION3 pos{ 0.f, 0.f, 0.f };
|
|
||||||
|
|
||||||
float rot = 0.f;
|
|
||||||
|
|
||||||
if( pop )
|
|
||||||
{
|
|
||||||
PlayerMgr::sendDebug( *this, "Teleport: popRange {0} found!", data.PopRange[ 0 ] );
|
|
||||||
pos = pop->m_pos;
|
|
||||||
rot = pop->m_rotation;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PlayerMgr::sendDebug( *this, "Teleport: popRange {0} not found in {1}!", data.PopRange[ 0 ], data.TerritoryType );
|
|
||||||
}
|
|
||||||
|
|
||||||
auto townPlace = exdData.getRow< Excel::PlaceName >( data.TelepoName );
|
|
||||||
auto aetherytePlace = exdData.getRow< Excel::PlaceName >( data.TransferName );
|
|
||||||
|
|
||||||
PlayerMgr::sendDebug( *this, "Teleport: {0} - {1} ({2})",
|
|
||||||
townPlace->getString( townPlace->data().Text.SGL ),
|
|
||||||
aetherytePlace->getString( aetherytePlace->data().Text.SGL ),
|
|
||||||
data.TerritoryType );
|
|
||||||
|
|
||||||
// if it is a teleport in the same zone, we want to do warp instead of moveTerri
|
|
||||||
bool sameTerritory = getTerritoryTypeId() == data.TerritoryType;
|
|
||||||
|
|
||||||
WarpType warpType = WarpType::WARP_TYPE_NORMAL;
|
|
||||||
// TODO: this should be simplified and a type created in server_common/common.h.
|
|
||||||
if( type == 1 || type == 2 ) // teleport
|
|
||||||
{
|
|
||||||
warpType = WarpType::WARP_TYPE_TELEPO;
|
|
||||||
setZoningType( Common::ZoneingType::Teleport );
|
|
||||||
}
|
|
||||||
else if( type == 3 ) // return
|
|
||||||
{
|
|
||||||
warpType = WarpType::WARP_TYPE_HOME_POINT;
|
|
||||||
setZoningType( Common::ZoneingType::Return );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( sameTerritory )
|
|
||||||
warpMgr.requestWarp( *this, warpType, pos, rot );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto pTeri = teriMgr.getZoneByTerritoryTypeId( data.TerritoryType );
|
|
||||||
if( !pTeri )
|
|
||||||
return;
|
|
||||||
warpMgr.requestMoveTerritory( *this, warpType, pTeri->getGuId(), pos, rot );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::forceZoneing( uint32_t zoneId )
|
void Player::forceZoneing( uint32_t zoneId )
|
||||||
{
|
{
|
||||||
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
||||||
|
@ -671,8 +607,6 @@ void Player::learnSong( uint8_t songId, uint32_t itemId )
|
||||||
Util::valueToFlagByteIndexValue( songId, value, index );
|
Util::valueToFlagByteIndexValue( songId, value, index );
|
||||||
|
|
||||||
m_orchestrion[ index ] |= value;
|
m_orchestrion[ index ] |= value;
|
||||||
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onUnlockOrchestrion( *this, songId, itemId );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::hasReward( Common::UnlockEntry unlockId ) const
|
bool Player::hasReward( Common::UnlockEntry unlockId ) const
|
||||||
|
@ -736,6 +670,7 @@ void Player::levelUp()
|
||||||
|
|
||||||
void Player::sendStatusUpdate()
|
void Player::sendStatusUpdate()
|
||||||
{
|
{
|
||||||
|
// todo: overrides are funky
|
||||||
Service< World::Manager::PlayerMgr >::ref().onPlayerHpMpTpChanged( *this );
|
Service< World::Manager::PlayerMgr >::ref().onPlayerHpMpTpChanged( *this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,15 +862,11 @@ void Player::setVoiceId( uint8_t voiceId )
|
||||||
void Player::setGc( uint8_t gc )
|
void Player::setGc( uint8_t gc )
|
||||||
{
|
{
|
||||||
m_gc = gc;
|
m_gc = gc;
|
||||||
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onGcUpdate( *this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setGcRankAt( uint8_t index, uint8_t rank )
|
void Player::setGcRankAt( uint8_t index, uint8_t rank )
|
||||||
{
|
{
|
||||||
m_gcRank[ index ] = rank;
|
m_gcRank[ index ] = rank;
|
||||||
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onGcUpdate( *this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Player::StateFlags& Player::getStateFlags() const
|
const Player::StateFlags& Player::getStateFlags() const
|
||||||
|
@ -956,7 +887,6 @@ bool Player::hasStateFlag( Common::PlayerStateFlag flag ) const
|
||||||
|
|
||||||
void Player::setStateFlag( Common::PlayerStateFlag flag )
|
void Player::setStateFlag( Common::PlayerStateFlag flag )
|
||||||
{
|
{
|
||||||
auto prevOnlineStatus = getOnlineStatus();
|
|
||||||
auto iFlag = static_cast< int32_t >( flag );
|
auto iFlag = static_cast< int32_t >( flag );
|
||||||
|
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
|
@ -964,22 +894,6 @@ void Player::setStateFlag( Common::PlayerStateFlag flag )
|
||||||
Util::valueToFlagByteIndexValue( iFlag, value, index );
|
Util::valueToFlagByteIndexValue( iFlag, value, index );
|
||||||
|
|
||||||
m_stateFlags[ index ] |= value;
|
m_stateFlags[ index ] |= value;
|
||||||
|
|
||||||
auto newOnlineStatus = getOnlineStatus();
|
|
||||||
sendStateFlags( prevOnlineStatus != newOnlineStatus );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::setStateFlags( std::vector< Common::PlayerStateFlag > flags )
|
|
||||||
{
|
|
||||||
for( const auto& flag : flags )
|
|
||||||
{
|
|
||||||
setStateFlag( flag );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::sendStateFlags( bool updateInRange )
|
|
||||||
{
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onSendStateFlags( *this, updateInRange );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::unsetStateFlag( Common::PlayerStateFlag flag )
|
void Player::unsetStateFlag( Common::PlayerStateFlag flag )
|
||||||
|
@ -987,8 +901,6 @@ void Player::unsetStateFlag( Common::PlayerStateFlag flag )
|
||||||
if( !hasStateFlag( flag ) )
|
if( !hasStateFlag( flag ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto prevOnlineStatus = getOnlineStatus();
|
|
||||||
|
|
||||||
auto iFlag = static_cast< int32_t >( flag );
|
auto iFlag = static_cast< int32_t >( flag );
|
||||||
|
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
|
@ -996,60 +908,21 @@ void Player::unsetStateFlag( Common::PlayerStateFlag flag )
|
||||||
Util::valueToFlagByteIndexValue( iFlag, value, index );
|
Util::valueToFlagByteIndexValue( iFlag, value, index );
|
||||||
|
|
||||||
m_stateFlags[ index ] ^= value;
|
m_stateFlags[ index ] ^= value;
|
||||||
|
|
||||||
auto newOnlineStatus = getOnlineStatus();
|
|
||||||
sendStateFlags( prevOnlineStatus != newOnlineStatus );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::update( uint64_t tickCount )
|
void Player::update( uint64_t tickCount )
|
||||||
{
|
{
|
||||||
if( m_hp <= 0 && m_status != ActorStatus::Dead )
|
// todo: better way to handle this override chara update
|
||||||
{
|
Service< World::Manager::PlayerMgr >::ref().onUpdate( *this, tickCount );
|
||||||
die();
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onDeath( *this );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !isAlive() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_lastUpdate = tickCount;
|
|
||||||
|
|
||||||
if( !checkAction() )
|
|
||||||
{
|
|
||||||
if( m_targetId && m_currentStance == Common::Stance::Active && isAutoattackOn() )
|
|
||||||
{
|
|
||||||
auto mainWeap = getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
|
|
||||||
|
|
||||||
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need...
|
|
||||||
for( const auto& actor : m_inRangeActor )
|
|
||||||
{
|
|
||||||
if( actor->getId() == m_targetId && actor->getAsChara()->isAlive() && mainWeap )
|
|
||||||
{
|
|
||||||
auto chara = actor->getAsChara();
|
|
||||||
|
|
||||||
// default autoattack range
|
|
||||||
float range = 3.f + chara->getRadius() + getRadius() * 0.5f;
|
|
||||||
|
|
||||||
// default autoattack range for ranged classes
|
|
||||||
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
|
|
||||||
range = 25.f + chara->getRadius() + getRadius() * 0.5f;
|
|
||||||
|
|
||||||
if( Util::distance( getPos(), actor->getPos() ) <= range )
|
|
||||||
{
|
|
||||||
if( ( tickCount - m_lastAttack ) > mainWeap->getDelay() )
|
|
||||||
{
|
|
||||||
m_lastAttack = tickCount;
|
|
||||||
autoAttack( actor->getAsChara() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Chara::update( tickCount );
|
Chara::update( tickCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Player::getLastAttack() const
|
||||||
|
{
|
||||||
|
return m_lastAttack;
|
||||||
|
}
|
||||||
|
|
||||||
void Player::setLastAttack( uint64_t tickCount )
|
void Player::setLastAttack( uint64_t tickCount )
|
||||||
{
|
{
|
||||||
m_lastAttack = tickCount;
|
m_lastAttack = tickCount;
|
||||||
|
@ -1113,6 +986,11 @@ const Player::OrchestrionList& Player::getOrchestrionBitmask() const
|
||||||
return m_orchestrion;
|
return m_orchestrion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::setOrchestrionBitmask( const Player::OrchestrionList& orchestrion )
|
||||||
|
{
|
||||||
|
m_orchestrion = orchestrion;
|
||||||
|
}
|
||||||
|
|
||||||
void Player::unlockMount( uint32_t mountId )
|
void Player::unlockMount( uint32_t mountId )
|
||||||
{
|
{
|
||||||
auto& exdData = Common::Service< Data::ExdData >::ref();
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
||||||
|
@ -1190,12 +1068,12 @@ void Player::setLoadingComplete( bool bComplete )
|
||||||
m_bLoadingComplete = bComplete;
|
m_bLoadingComplete = bComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneingType Player::getZoningType() const
|
ZoningType Player::getZoningType() const
|
||||||
{
|
{
|
||||||
return m_zoningType;
|
return m_zoningType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setZoningType( Common::ZoneingType zoneingType )
|
void Player::setZoningType( Common::ZoningType zoneingType )
|
||||||
{
|
{
|
||||||
m_zoningType = zoneingType;
|
m_zoningType = zoneingType;
|
||||||
}
|
}
|
||||||
|
@ -1374,21 +1252,11 @@ uint8_t Player::getEquipDisplayFlags() const
|
||||||
void Player::setMount( uint32_t mountId )
|
void Player::setMount( uint32_t mountId )
|
||||||
{
|
{
|
||||||
m_mount = mountId;
|
m_mount = mountId;
|
||||||
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onMountUpdate( *this, m_mount );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setCompanion( uint8_t id )
|
void Player::setCompanion( uint8_t id )
|
||||||
{
|
{
|
||||||
auto& exdData = Common::Service< Data::ExdData >::ref();
|
|
||||||
|
|
||||||
auto companion = exdData.getRow< Excel::Companion >( id );
|
|
||||||
if( !id )
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_companionId = id;
|
m_companionId = id;
|
||||||
|
|
||||||
Service< World::Manager::PlayerMgr >::ref().onCompanionUpdate( *this, m_companionId );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Player::getCurrentCompanion() const
|
uint8_t Player::getCurrentCompanion() const
|
||||||
|
@ -1618,20 +1486,27 @@ void Player::dyeItemFromDyeingInfo()
|
||||||
uint32_t dyeBagContainer = m_dyeingInfo.dyeBagContainer;
|
uint32_t dyeBagContainer = m_dyeingInfo.dyeBagContainer;
|
||||||
uint32_t dyeBagSlot = m_dyeingInfo.dyeBagSlot;
|
uint32_t dyeBagSlot = m_dyeingInfo.dyeBagSlot;
|
||||||
|
|
||||||
sendStateFlags(); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..?
|
Service< World::Manager::PlayerMgr >::ref().onSendStateFlags( *this, true ); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..?
|
||||||
|
|
||||||
auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot );
|
auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot );
|
||||||
auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot );
|
auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot );
|
||||||
|
|
||||||
if( !itemToDye || !dyeToUse )
|
if( !itemToDye || !dyeToUse )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t stainColorID = dyeToUse->getAdditionalData();
|
if( !removeItem( dyeToUse->getId() ) )
|
||||||
itemToDye->setStain( stainColorID );
|
return;
|
||||||
|
|
||||||
// TODO: subtract/remove dye used
|
uint32_t stainColorID = dyeToUse->getAdditionalData();
|
||||||
|
bool shouldDye = stainColorID != 0;
|
||||||
|
bool invalidateGearSet = stainColorID != itemToDye->getStain();
|
||||||
|
itemToDye->setStain( stainColorID );
|
||||||
|
|
||||||
insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye );
|
insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye );
|
||||||
writeItem( itemToDye );
|
writeItem( itemToDye );
|
||||||
|
|
||||||
|
auto dyePkt = makeActorControlSelf( getId(), DyeMsg, itemToDye->getId(), shouldDye, invalidateGearSet );
|
||||||
|
queuePacket( dyePkt );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::resetObjSpawnIndex()
|
void Player::resetObjSpawnIndex()
|
||||||
|
@ -1931,7 +1806,7 @@ void Player::setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool
|
||||||
// if we've hit the breakpoint in fall damage (min: 10y)
|
// if we've hit the breakpoint in fall damage (min: 10y)
|
||||||
if( fallHeight >= 10.f )
|
if( fallHeight >= 10.f )
|
||||||
{
|
{
|
||||||
// calculate how much damage to deal out (max. 20y : 100%)
|
// calculate how much damage to deal out (max. 30y : 100%)
|
||||||
float deltaMax = std::min( fallHeight, 30.f );
|
float deltaMax = std::min( fallHeight, 30.f );
|
||||||
|
|
||||||
// get hp percentage starting from 0.1, increasing to 100% at max height
|
// get hp percentage starting from 0.1, increasing to 100% at max height
|
||||||
|
|
|
@ -83,6 +83,10 @@ namespace Sapphire::Entity
|
||||||
/*! Event called on every session iteration */
|
/*! Event called on every session iteration */
|
||||||
void update( uint64_t tickCount ) override;
|
void update( uint64_t tickCount ) override;
|
||||||
|
|
||||||
|
/*! get last attack tick for player */
|
||||||
|
uint64_t getLastAttack() const;
|
||||||
|
|
||||||
|
/*! set last attack tick for player */
|
||||||
void setLastAttack( uint64_t tickCount );
|
void setLastAttack( uint64_t tickCount );
|
||||||
|
|
||||||
// Quest
|
// Quest
|
||||||
|
@ -343,9 +347,6 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
uint64_t getFullOnlineStatusMask() const;
|
uint64_t getFullOnlineStatusMask() const;
|
||||||
|
|
||||||
/*! perform a teleport of a specified type ( teleport,return,aethernet ) */
|
|
||||||
void teleport( uint16_t aetheryteId, uint8_t type = 1 );
|
|
||||||
|
|
||||||
/*! query teleport of a specified type */
|
/*! query teleport of a specified type */
|
||||||
void teleportQuery( uint16_t aetheryteId );
|
void teleportQuery( uint16_t aetheryteId );
|
||||||
|
|
||||||
|
@ -418,7 +419,7 @@ namespace Sapphire::Entity
|
||||||
/*! check if aetheryte is already registered */
|
/*! check if aetheryte is already registered */
|
||||||
bool isAetheryteRegistered( uint8_t aetheryteId ) const;
|
bool isAetheryteRegistered( uint8_t aetheryteId ) const;
|
||||||
|
|
||||||
/*! return a const pointer to the aetheryte unlock bitmask array */
|
/*! return aetheryte mask */
|
||||||
uint8_t getAetheryteMaskAt( uint8_t index ) const;
|
uint8_t getAetheryteMaskAt( uint8_t index ) const;
|
||||||
|
|
||||||
/*! return a pointer to the aetheryte unlock bitmask array */
|
/*! return a pointer to the aetheryte unlock bitmask array */
|
||||||
|
@ -433,13 +434,13 @@ namespace Sapphire::Entity
|
||||||
/*! discover subarea subid fo map map_id, also send udpate packet */
|
/*! discover subarea subid fo map map_id, also send udpate packet */
|
||||||
void discover( int16_t map_id, int16_t sub_id );
|
void discover( int16_t map_id, int16_t sub_id );
|
||||||
|
|
||||||
/*! return a pointer to the discovery bitmask array */
|
/*! return a reference to the discovery bitmask array */
|
||||||
Discovery& getDiscoveryBitmask();
|
Discovery& getDiscoveryBitmask();
|
||||||
|
|
||||||
/*! helper/debug function to reset all discovered areas */
|
/*! helper/debug function to reset all discovered areas */
|
||||||
void resetDiscovery();
|
void resetDiscovery();
|
||||||
|
|
||||||
/*! get a pointer to the howto bitmask array */
|
/*! get a reference to the howto bitmask array */
|
||||||
HowToList& getHowToArray();
|
HowToList& getHowToArray();
|
||||||
|
|
||||||
/*! update bitmask for how-to's seen */
|
/*! update bitmask for how-to's seen */
|
||||||
|
@ -454,22 +455,25 @@ namespace Sapphire::Entity
|
||||||
/*! check if an action is already unlocked in the bitmask. */
|
/*! check if an action is already unlocked in the bitmask. */
|
||||||
bool hasReward( Common::UnlockEntry unlockId ) const;
|
bool hasReward( Common::UnlockEntry unlockId ) const;
|
||||||
|
|
||||||
/*! return a const pointer to the unlock bitmask array */
|
/*! return a const reference to the unlock bitmask array */
|
||||||
const UnlockList& getUnlockBitmask() const;
|
const UnlockList& getUnlockBitmask() const;
|
||||||
|
|
||||||
/*! return a const pointer to the orchestrion bitmask array */
|
/*! return a const reference to the orchestrion bitmask array */
|
||||||
const OrchestrionList& getOrchestrionBitmask() const;
|
const OrchestrionList& getOrchestrionBitmask() const;
|
||||||
|
|
||||||
|
/*! set orchestrion bitmask array */
|
||||||
|
void setOrchestrionBitmask( const OrchestrionList& orchestrion );
|
||||||
|
|
||||||
/*! unlock a mount */
|
/*! unlock a mount */
|
||||||
void unlockMount( uint32_t mountId );
|
void unlockMount( uint32_t mountId );
|
||||||
|
|
||||||
/*! unlock a companion */
|
/*! unlock a companion */
|
||||||
void unlockCompanion( uint32_t companionId );
|
void unlockCompanion( uint32_t companionId );
|
||||||
|
|
||||||
/*! return a const pointer to the minion guide bitmask array */
|
/*! return a reference to the minion guide bitmask array */
|
||||||
MinionList& getMinionGuideBitmask();
|
MinionList& getMinionGuideBitmask();
|
||||||
|
|
||||||
/*! return a const pointer to the setMount guide bitmask array */
|
/*! return a reference to the setMount guide bitmask array */
|
||||||
MountList& getMountGuideBitmask();
|
MountList& getMountGuideBitmask();
|
||||||
|
|
||||||
bool checkAction() override;
|
bool checkAction() override;
|
||||||
|
@ -567,9 +571,6 @@ namespace Sapphire::Entity
|
||||||
/*! send current models ( equipment ) */
|
/*! send current models ( equipment ) */
|
||||||
void sendModel();
|
void sendModel();
|
||||||
|
|
||||||
/*! send active state flags */
|
|
||||||
void sendStateFlags( bool updateInRange = true );
|
|
||||||
|
|
||||||
/*! send status update */
|
/*! send status update */
|
||||||
void sendStatusUpdate() override;
|
void sendStatusUpdate() override;
|
||||||
|
|
||||||
|
@ -582,9 +583,9 @@ namespace Sapphire::Entity
|
||||||
/*! set the loading complete bool */
|
/*! set the loading complete bool */
|
||||||
void setLoadingComplete( bool bComplete );
|
void setLoadingComplete( bool bComplete );
|
||||||
|
|
||||||
Common::ZoneingType getZoningType() const;
|
Common::ZoningType getZoningType() const;
|
||||||
|
|
||||||
void setZoningType( Common::ZoneingType zoneingType );
|
void setZoningType( Common::ZoningType zoneingType );
|
||||||
|
|
||||||
void setSearchInfo( uint8_t selectRegion, uint8_t selectClass, const char* searchMessage );
|
void setSearchInfo( uint8_t selectRegion, uint8_t selectClass, const char* searchMessage );
|
||||||
|
|
||||||
|
@ -722,6 +723,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
|
ItemPtr addItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false, bool slient = false, bool canMerge = true );
|
||||||
|
|
||||||
|
bool removeItem( uint32_t catalogId, uint32_t quantity = 1, bool isHq = false );
|
||||||
|
|
||||||
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
void moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
||||||
|
|
||||||
void swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
void swapItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot );
|
||||||
|
@ -740,6 +743,10 @@ namespace Sapphire::Entity
|
||||||
/*! calculate and return player ilvl based off equipped gear */
|
/*! calculate and return player ilvl based off equipped gear */
|
||||||
uint16_t calculateEquippedGearItemLevel();
|
uint16_t calculateEquippedGearItemLevel();
|
||||||
|
|
||||||
|
|
||||||
|
/*! calculate bonus stats from gear */
|
||||||
|
void calculateBonusStats();
|
||||||
|
|
||||||
ItemPtr getEquippedWeapon();
|
ItemPtr getEquippedWeapon();
|
||||||
|
|
||||||
/*! return the current amount of currency of type */
|
/*! return the current amount of currency of type */
|
||||||
|
@ -919,7 +926,7 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
bool m_bIsConnected;
|
bool m_bIsConnected;
|
||||||
|
|
||||||
Common::ZoneingType m_zoningType;
|
Common::ZoningType m_zoningType;
|
||||||
|
|
||||||
bool m_bNewAdventurer{};
|
bool m_bNewAdventurer{};
|
||||||
uint64_t m_onlineStatus;
|
uint64_t m_onlineStatus;
|
||||||
|
|
|
@ -224,16 +224,6 @@ void Sapphire::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, Item&
|
||||||
|
|
||||||
updateModels( equipSlotId, item );
|
updateModels( equipSlotId, item );
|
||||||
|
|
||||||
auto baseParams = item.getBaseParams();
|
|
||||||
for( auto i = 0; i < 6; ++i )
|
|
||||||
{
|
|
||||||
if( baseParams[ i ].baseParam != static_cast< uint8_t >( Common::BaseParam::None ) )
|
|
||||||
m_bonusStats[ baseParams[ i ].baseParam ] += baseParams[ i ].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Defense ) ] += item.getDefense();
|
|
||||||
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::MagicDefense ) ] += item.getDefenseMag();
|
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
if( sendUpdate )
|
if( sendUpdate )
|
||||||
{
|
{
|
||||||
|
@ -254,16 +244,6 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite
|
||||||
if ( equipSlotId == SoulCrystal )
|
if ( equipSlotId == SoulCrystal )
|
||||||
unequipSoulCrystal();
|
unequipSoulCrystal();
|
||||||
|
|
||||||
auto baseParams = item.getBaseParams();
|
|
||||||
for( auto i = 0; i < 6; ++i )
|
|
||||||
{
|
|
||||||
if( baseParams[ i ].baseParam != static_cast< uint8_t >( Common::BaseParam::None ) )
|
|
||||||
m_bonusStats[ baseParams[ i ].baseParam ] -= baseParams[ i ].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Defense ) ] -= item.getDefense();
|
|
||||||
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::MagicDefense ) ] -= item.getDefenseMag();
|
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
|
|
||||||
if( sendUpdate )
|
if( sendUpdate )
|
||||||
|
@ -720,6 +700,54 @@ Sapphire::ItemPtr Sapphire::Entity::Player::addItem( uint32_t catalogId, uint32_
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sapphire::Entity::Player::removeItem( uint32_t catalogId, uint32_t quantity, bool isHq )
|
||||||
|
{
|
||||||
|
std::vector< uint16_t > bags = { Bag0, Bag1, Bag2, Bag3 };
|
||||||
|
|
||||||
|
for( auto bag : bags )
|
||||||
|
{
|
||||||
|
auto storage = m_storageMap[ bag ];
|
||||||
|
|
||||||
|
for( uint16_t slot = 0; slot < storage->getMaxSize(); slot++ )
|
||||||
|
{
|
||||||
|
if( quantity == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto item = storage->getItem( slot );
|
||||||
|
|
||||||
|
// remove any matching items
|
||||||
|
if( item && item->getId() == catalogId )
|
||||||
|
{
|
||||||
|
uint32_t count = item->getStackSize();
|
||||||
|
uint32_t maxStack = item->getMaxStackSize();
|
||||||
|
|
||||||
|
// check slot is same quality
|
||||||
|
if( item->isHq() != isHq )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// update stack
|
||||||
|
int32_t newStackSize = count - quantity;
|
||||||
|
if( newStackSize <= 0 )
|
||||||
|
{
|
||||||
|
quantity = std::abs( newStackSize );
|
||||||
|
discardItem( bag, slot );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
quantity = 0;
|
||||||
|
item->setStackSize( newStackSize );
|
||||||
|
|
||||||
|
insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( bag ), slot, item );
|
||||||
|
|
||||||
|
writeItem( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return quantity == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot )
|
Sapphire::Entity::Player::moveItem( uint16_t fromInventoryId, uint16_t fromSlotId, uint16_t toInventoryId, uint16_t toSlot )
|
||||||
{
|
{
|
||||||
|
@ -951,6 +979,38 @@ uint16_t Sapphire::Entity::Player::calculateEquippedGearItemLevel()
|
||||||
return ilvl;
|
return ilvl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::Entity::Player::calculateBonusStats()
|
||||||
|
{
|
||||||
|
m_bonusStats.fill( 0 );
|
||||||
|
|
||||||
|
auto gearSetMap = m_storageMap[ GearSet0 ]->getItemMap();
|
||||||
|
|
||||||
|
auto it = gearSetMap.begin();
|
||||||
|
|
||||||
|
while( it != gearSetMap.end() )
|
||||||
|
{
|
||||||
|
auto pItem = it->second;
|
||||||
|
|
||||||
|
if( pItem && pItem->getCategory() != Common::ItemUICategory::SoulCrystal )
|
||||||
|
{
|
||||||
|
auto baseParams = pItem->getBaseParams();
|
||||||
|
for( auto i = 0; i < 6; ++i )
|
||||||
|
{
|
||||||
|
auto itemBaseParam = baseParams[ i ].baseParam;
|
||||||
|
auto itemBaseVal = baseParams[ i ].value;
|
||||||
|
if( itemBaseParam != static_cast< uint8_t >( Common::BaseParam::None ) )
|
||||||
|
m_bonusStats[ itemBaseParam ] += itemBaseVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Defense ) ] += pItem->getDefense();
|
||||||
|
m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::MagicDefense ) ] += pItem->getDefenseMag();
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedWeapon()
|
Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedWeapon()
|
||||||
{
|
{
|
||||||
return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand );
|
return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand );
|
||||||
|
|
|
@ -87,6 +87,7 @@ TYPE_FORWARD( EventAction );
|
||||||
TYPE_FORWARD( ItemAction );
|
TYPE_FORWARD( ItemAction );
|
||||||
TYPE_FORWARD( EventItemAction );
|
TYPE_FORWARD( EventItemAction );
|
||||||
TYPE_FORWARD( MountAction );
|
TYPE_FORWARD( MountAction );
|
||||||
|
TYPE_FORWARD( ItemManipulationAction );
|
||||||
TYPE_FORWARD( EffectBuilder );
|
TYPE_FORWARD( EffectBuilder );
|
||||||
TYPE_FORWARD( EffectResult );
|
TYPE_FORWARD( EffectResult );
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace Sapphire::World::Manager
|
||||||
if( !pAchv )
|
if( !pAchv )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto achvExdData = pAchv->data();
|
auto& achvExdData = pAchv->data();
|
||||||
|
|
||||||
if( achvExdData.ConditionArg[ 1 ] <= static_cast< int32_t >( achvData.progressData[ dataKey.u32 ] ) )
|
if( achvExdData.ConditionArg[ 1 ] <= static_cast< int32_t >( achvData.progressData[ dataKey.u32 ] ) )
|
||||||
unlockAchievement( player, achvId );
|
unlockAchievement( player, achvId );
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Action/ItemAction.h"
|
#include "Action/ItemAction.h"
|
||||||
#include "Action/EventItemAction.h"
|
#include "Action/EventItemAction.h"
|
||||||
#include "Action/MountAction.h"
|
#include "Action/MountAction.h"
|
||||||
|
#include "Action/ItemManipulationAction.h"
|
||||||
#include "Script/ScriptMgr.h"
|
#include "Script/ScriptMgr.h"
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
|
|
||||||
|
@ -45,6 +46,19 @@ void ActionMgr::handlePlacedPlayerAction( Entity::Player& player, uint32_t actio
|
||||||
bootstrapAction( player, action, actionData );
|
bootstrapAction( player, action, actionData );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActionMgr::handleItemManipulationAction( Entity::Player& player, uint32_t actionId,
|
||||||
|
Excel::ExcelStructPtr< Excel::Action > actionData, uint16_t sequence )
|
||||||
|
{
|
||||||
|
auto action = Action::make_ItemManipulationAction( player.getAsPlayer(), actionId, sequence, actionData, 2500 ); // todo: maybe the delay can be retrieved from data
|
||||||
|
|
||||||
|
player.setCurrentAction( action );
|
||||||
|
|
||||||
|
if( !action->init() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
action->start();
|
||||||
|
}
|
||||||
|
|
||||||
void ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
|
void ActionMgr::handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
|
||||||
Excel::ExcelStructPtr< Excel::Action > actionData, uint64_t targetId, uint16_t sequence )
|
Excel::ExcelStructPtr< Excel::Action > actionData, uint64_t targetId, uint16_t sequence )
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,9 @@ namespace Sapphire::World::Manager
|
||||||
|
|
||||||
bool cacheActionLut();
|
bool cacheActionLut();
|
||||||
|
|
||||||
|
void handleItemManipulationAction( Entity::Player& player, uint32_t actionId,
|
||||||
|
Excel::ExcelStructPtr< Excel::Action > actionData, uint16_t sequence );
|
||||||
|
|
||||||
void handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
|
void handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId,
|
||||||
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t sequence );
|
std::shared_ptr< Excel::ExcelStruct< Excel::Action > > actionData, uint64_t targetId, uint16_t sequence );
|
||||||
void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId,
|
void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId,
|
||||||
|
|
|
@ -217,7 +217,7 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr<
|
||||||
int32_t aetheryteId;
|
int32_t aetheryteId;
|
||||||
sscanf( params.c_str(), "%i", &aetheryteId );
|
sscanf( params.c_str(), "%i", &aetheryteId );
|
||||||
|
|
||||||
player.teleport( static_cast< uint16_t >( aetheryteId ) );
|
Common::Service< WarpMgr >::ref().requestPlayerTeleport( player, static_cast< uint16_t >( aetheryteId ), 1 );
|
||||||
}
|
}
|
||||||
else if( ( subCommand == "discovery" ) && ( !params.empty() ) )
|
else if( ( subCommand == "discovery" ) && ( !params.empty() ) )
|
||||||
{
|
{
|
||||||
|
@ -269,8 +269,8 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr<
|
||||||
int32_t id;
|
int32_t id;
|
||||||
sscanf( params.c_str(), "%d", &id );
|
sscanf( params.c_str(), "%d", &id );
|
||||||
|
|
||||||
player.setMount( 0 );
|
Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, 0 );
|
||||||
player.setMount( static_cast< uint32_t >( id ));
|
Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, id );
|
||||||
}
|
}
|
||||||
else if( subCommand == "weatheroverride" || subCommand == "wo" )
|
else if( subCommand == "weatheroverride" || subCommand == "wo" )
|
||||||
{
|
{
|
||||||
|
|
|
@ -555,12 +555,12 @@ void EventMgr::eventFinish( Sapphire::Entity::Player& player, uint32_t eventId,
|
||||||
}
|
}
|
||||||
|
|
||||||
if( player.hasStateFlag( Common::PlayerStateFlag::WatchingCutscene ) )
|
if( player.hasStateFlag( Common::PlayerStateFlag::WatchingCutscene ) )
|
||||||
player.unsetStateFlag( Common::PlayerStateFlag::WatchingCutscene );
|
Common::Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( player, Common::PlayerStateFlag::WatchingCutscene );
|
||||||
|
|
||||||
player.removeEvent( pEvent->getId() );
|
player.removeEvent( pEvent->getId() );
|
||||||
|
|
||||||
if( freePlayer == 1 )
|
if( freePlayer == 1 )
|
||||||
player.unsetStateFlag( Common::PlayerStateFlag::InNpcEvent );
|
Common::Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( player, Common::PlayerStateFlag::InNpcEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventType, uint8_t eventParam1,
|
void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventType, uint8_t eventParam1,
|
||||||
|
@ -571,7 +571,7 @@ void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t ev
|
||||||
newEvent->setEventFinishCallback( std::move( callback ) );
|
newEvent->setEventFinishCallback( std::move( callback ) );
|
||||||
player.addEvent( newEvent );
|
player.addEvent( newEvent );
|
||||||
|
|
||||||
player.setStateFlag( Common::PlayerStateFlag::InNpcEvent );
|
Common::Service< World::Manager::PlayerMgr >::ref().onSetStateFlag( player, Common::PlayerStateFlag::InNpcEvent );
|
||||||
|
|
||||||
server.queueForPlayer( player.getCharacterId(), std::make_shared< EventStartPacket >( player.getId(), actorId,
|
server.queueForPlayer( player.getCharacterId(), std::make_shared< EventStartPacket >( player.getId(), actorId,
|
||||||
eventId, eventType, eventParam1, eventParam2 ) );
|
eventId, eventType, eventParam1, eventParam2 ) );
|
||||||
|
@ -836,7 +836,7 @@ Sapphire::Event::EventHandlerPtr EventMgr::bootstrapSceneEvent( Entity::Player&
|
||||||
}
|
}
|
||||||
|
|
||||||
if( flags & CONDITION_CUTSCENE )
|
if( flags & CONDITION_CUTSCENE )
|
||||||
player.setStateFlag( Common::PlayerStateFlag::WatchingCutscene );
|
Common::Service< World::Manager::PlayerMgr >::ref().onSetStateFlag( player, Common::PlayerStateFlag::WatchingCutscene );
|
||||||
|
|
||||||
return pEvent;
|
return pEvent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
#include <Manager/HousingMgr.h>
|
#include <Manager/HousingMgr.h>
|
||||||
#include <Manager/FreeCompanyMgr.h>
|
#include <Manager/FreeCompanyMgr.h>
|
||||||
|
|
||||||
#include "Script/ScriptMgr.h"
|
#include <Script/ScriptMgr.h>
|
||||||
#include "WorldServer.h"
|
#include <WorldServer.h>
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
|
|
||||||
#include <Network/PacketContainer.h>
|
#include <Network/PacketContainer.h>
|
||||||
|
@ -23,19 +23,23 @@
|
||||||
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
||||||
#include <Network/PacketWrappers/ActorControlPacket.h>
|
#include <Network/PacketWrappers/ActorControlPacket.h>
|
||||||
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
||||||
#include "Network/PacketWrappers/ActorControlTargetPacket.h"
|
#include <Network/PacketWrappers/ActorControlTargetPacket.h>
|
||||||
#include "Network/PacketWrappers/InitZonePacket.h"
|
#include <Network/PacketWrappers/InitZonePacket.h>
|
||||||
#include <Network/PacketWrappers/ModelEquipPacket.h>
|
#include <Network/PacketWrappers/ModelEquipPacket.h>
|
||||||
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
#include <Network/PacketWrappers/PlayerSetupPacket.h>
|
||||||
#include <Network/PacketWrappers/PlayerStateFlagsPacket.h>
|
#include <Network/PacketWrappers/PlayerStateFlagsPacket.h>
|
||||||
#include <Network/PacketWrappers/UpdateHpMpTpPacket.h>
|
#include <Network/PacketWrappers/UpdateHpMpTpPacket.h>
|
||||||
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
#include <Network/PacketWrappers/ServerNoticePacket.h>
|
||||||
#include "Network/PacketWrappers/ChatPacket.h"
|
#include <Network/PacketWrappers/ChatPacket.h>
|
||||||
#include "Network/PacketWrappers/HudParamPacket.h"
|
#include <Network/PacketWrappers/HudParamPacket.h>
|
||||||
|
|
||||||
#include <Actor/Player.h>
|
#include <Actor/Player.h>
|
||||||
#include <Actor/BNpc.h>
|
#include <Actor/BNpc.h>
|
||||||
|
|
||||||
|
#include <Inventory/Item.h>
|
||||||
|
|
||||||
|
#include <Util/UtilMath.h>
|
||||||
|
|
||||||
using namespace Sapphire;
|
using namespace Sapphire;
|
||||||
using namespace Sapphire::World::Manager;
|
using namespace Sapphire::World::Manager;
|
||||||
using namespace Sapphire::Network::Packets;
|
using namespace Sapphire::Network::Packets;
|
||||||
|
@ -163,7 +167,11 @@ void PlayerMgr::onPlayerStatusUpdate( Entity::Player& player )
|
||||||
|
|
||||||
void PlayerMgr::onPlayerHpMpTpChanged( Entity::Player& player )
|
void PlayerMgr::onPlayerHpMpTpChanged( Entity::Player& player )
|
||||||
{
|
{
|
||||||
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
|
|
||||||
player.sendToInRangeSet( std::make_shared< UpdateHpMpTpPacket >( player ), true );
|
player.sendToInRangeSet( std::make_shared< UpdateHpMpTpPacket >( player ), true );
|
||||||
|
auto hudParamPacket = makeHudParam( player );
|
||||||
|
server.queueForPlayer( player.getCharacterId(), hudParamPacket );
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::onPlayerItemLevelUpdate( Entity::Player& player )
|
void PlayerMgr::onPlayerItemLevelUpdate( Entity::Player& player )
|
||||||
|
@ -213,6 +221,8 @@ void PlayerMgr::onGainExp( Entity::Player& player, uint32_t exp )
|
||||||
|
|
||||||
void PlayerMgr::onUnlockOrchestrion( Entity::Player& player, uint8_t songId, uint32_t itemId )
|
void PlayerMgr::onUnlockOrchestrion( Entity::Player& player, uint8_t songId, uint32_t itemId )
|
||||||
{
|
{
|
||||||
|
player.learnSong( songId, itemId );
|
||||||
|
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) );
|
server.queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) );
|
||||||
}
|
}
|
||||||
|
@ -225,21 +235,47 @@ void PlayerMgr::onChangeGear( Entity::Player& player )
|
||||||
void PlayerMgr::onGcUpdate( Entity::Player& player )
|
void PlayerMgr::onGcUpdate( Entity::Player& player )
|
||||||
{
|
{
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
|
|
||||||
auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() );
|
auto gcAffPacket = makeZonePacket< FFXIVIpcGrandCompany >( player.getId() );
|
||||||
gcAffPacket->data().ActiveCompanyId = player.getGc();
|
gcAffPacket->data().ActiveCompanyId = player.getGc();
|
||||||
gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ];
|
gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ];
|
||||||
gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ];
|
gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ];
|
||||||
gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ];
|
gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ];
|
||||||
|
|
||||||
server.queueForPlayer( player.getCharacterId(), gcAffPacket );
|
server.queueForPlayer( player.getCharacterId(), gcAffPacket );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::onSetGc( Entity::Player& player, uint8_t gc )
|
||||||
|
{
|
||||||
|
player.setGc( gc );
|
||||||
|
|
||||||
|
onGcUpdate( player );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::onSetGcRank( Entity::Player& player, uint8_t gc, uint8_t rank )
|
||||||
|
{
|
||||||
|
player.setGcRankAt( gc, rank );
|
||||||
|
|
||||||
|
onGcUpdate( player );
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId )
|
void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId )
|
||||||
{
|
{
|
||||||
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
||||||
|
|
||||||
|
auto companion = exdData.getRow< Excel::Companion >( companionId );
|
||||||
|
if( !companion )
|
||||||
|
return;
|
||||||
|
|
||||||
|
player.setCompanion( companionId );
|
||||||
|
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::ToggleCompanion, companionId ), true );
|
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::ToggleCompanion, companionId ), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId )
|
void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId )
|
||||||
{
|
{
|
||||||
|
Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, mountId );
|
||||||
|
|
||||||
if( mountId != 0 )
|
if( mountId != 0 )
|
||||||
{
|
{
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus,
|
player.sendToInRangeSet( makeActorControl( player.getId(), ActorControlType::SetStatus,
|
||||||
|
@ -310,13 +346,13 @@ void PlayerMgr::onHateListChanged( Entity::Player& player )
|
||||||
server.queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } );
|
server.queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } );
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::onChangeClass( Entity::Player &player )
|
void PlayerMgr::onChangeClass( Entity::Player& player )
|
||||||
{
|
{
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), ClassJobChange, 0x04 ), true );
|
player.sendToInRangeSet( makeActorControl( player.getId(), ClassJobChange, 0x04 ), true );
|
||||||
player.sendStatusUpdate();
|
onPlayerHpMpTpChanged( player );
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::onLogin( Entity::Player &player )
|
void PlayerMgr::onLogin( Entity::Player& player )
|
||||||
{
|
{
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
auto& server = Common::Service< World::WorldServer >::ref();
|
||||||
|
|
||||||
|
@ -330,7 +366,7 @@ void PlayerMgr::onLogin( Entity::Player &player )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::onDeath( Entity::Player &player )
|
void PlayerMgr::onDeath( Entity::Player& player )
|
||||||
{
|
{
|
||||||
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref();
|
||||||
scriptMgr.onPlayerDeath( player );
|
scriptMgr.onPlayerDeath( player );
|
||||||
|
@ -425,6 +461,73 @@ void PlayerMgr::onZone( Sapphire::Entity::Player& player )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::onUpdate( Entity::Player& player, uint64_t tickCount )
|
||||||
|
{
|
||||||
|
if( player.getHp() <= 0 && player.getStatus() != Common::ActorStatus::Dead )
|
||||||
|
{
|
||||||
|
player.die();
|
||||||
|
onDeath( player );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !player.isAlive() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !player.checkAction() )
|
||||||
|
{
|
||||||
|
if( player.getTargetId() && player.getStance() == Common::Stance::Active && player.isAutoattackOn() )
|
||||||
|
{
|
||||||
|
auto mainWeap = player.getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
|
||||||
|
|
||||||
|
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need...
|
||||||
|
for( const auto& actor : player.getInRangeActors() )
|
||||||
|
{
|
||||||
|
if( actor->getId() == player.getTargetId() && actor->getAsChara()->isAlive() && mainWeap )
|
||||||
|
{
|
||||||
|
auto chara = actor->getAsChara();
|
||||||
|
|
||||||
|
// default autoattack range
|
||||||
|
float range = 3.f + chara->getRadius() + player.getRadius() * 0.5f;
|
||||||
|
|
||||||
|
// default autoattack range for ranged classes
|
||||||
|
auto classJob = player.getClass();
|
||||||
|
|
||||||
|
if( classJob == Common::ClassJob::Machinist || classJob == Common::ClassJob::Bard || classJob == Common::ClassJob::Archer )
|
||||||
|
range = 25.f + chara->getRadius() + player.getRadius() * 0.5f;
|
||||||
|
|
||||||
|
if( Common::Util::distance( player.getPos(), actor->getPos() ) <= range )
|
||||||
|
{
|
||||||
|
if( ( tickCount - player.getLastAttack() ) > mainWeap->getDelay() )
|
||||||
|
{
|
||||||
|
player.setLastAttack( tickCount );
|
||||||
|
player.autoAttack( actor->getAsChara() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::onSetStateFlag( Sapphire::Entity::Player& player, Common::PlayerStateFlag flag )
|
||||||
|
{
|
||||||
|
auto prevOnlineStatus = player.getOnlineStatus();
|
||||||
|
|
||||||
|
player.setStateFlag( flag );
|
||||||
|
|
||||||
|
auto newOnlineStatus = player.getOnlineStatus();
|
||||||
|
onSendStateFlags( player, prevOnlineStatus != newOnlineStatus );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::onUnsetStateFlag( Sapphire::Entity::Player& player, Common::PlayerStateFlag flag )
|
||||||
|
{
|
||||||
|
auto prevOnlineStatus = player.getOnlineStatus();
|
||||||
|
|
||||||
|
player.unsetStateFlag( flag );
|
||||||
|
|
||||||
|
auto newOnlineStatus = player.getOnlineStatus();
|
||||||
|
onSendStateFlags( player, prevOnlineStatus != newOnlineStatus );
|
||||||
|
}
|
||||||
|
|
||||||
////////// Helper ///////////
|
////////// Helper ///////////
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ class PlayerMgr
|
||||||
|
|
||||||
void onGcUpdate( Sapphire::Entity::Player& player );
|
void onGcUpdate( Sapphire::Entity::Player& player );
|
||||||
|
|
||||||
|
void onSetGc( Sapphire::Entity::Player& player, uint8_t gc );
|
||||||
|
|
||||||
|
void onSetGcRank( Sapphire::Entity::Player& player, uint8_t gc, uint8_t rank );
|
||||||
|
|
||||||
void onCompanionUpdate( Entity::Player& player, uint8_t companionId );
|
void onCompanionUpdate( Entity::Player& player, uint8_t companionId );
|
||||||
|
|
||||||
void onMountUpdate( Sapphire::Entity::Player& player, uint32_t mountId );
|
void onMountUpdate( Sapphire::Entity::Player& player, uint32_t mountId );
|
||||||
|
@ -58,6 +62,12 @@ class PlayerMgr
|
||||||
|
|
||||||
void onZone( Sapphire::Entity::Player& player );
|
void onZone( Sapphire::Entity::Player& player );
|
||||||
|
|
||||||
|
void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount );
|
||||||
|
|
||||||
|
void onSetStateFlag( Sapphire::Entity::Player& player, Common::PlayerStateFlag flag );
|
||||||
|
|
||||||
|
void onUnsetStateFlag( Sapphire::Entity::Player& player, Common::PlayerStateFlag flag );
|
||||||
|
|
||||||
//////////// Helpers
|
//////////// Helpers
|
||||||
|
|
||||||
static void sendServerNotice( Sapphire::Entity::Player& player, const std::string& message );
|
static void sendServerNotice( Sapphire::Entity::Player& player, const std::string& message );
|
||||||
|
|
|
@ -6,14 +6,20 @@
|
||||||
|
|
||||||
#include <WorldServer.h>
|
#include <WorldServer.h>
|
||||||
#include <Logging/Logger.h>
|
#include <Logging/Logger.h>
|
||||||
|
#include <Exd/ExdData.h>
|
||||||
|
|
||||||
#include "Task/MoveTerritoryTask.h"
|
#include "Task/MoveTerritoryTask.h"
|
||||||
#include "Task/WarpTask.h"
|
#include "Task/WarpTask.h"
|
||||||
|
|
||||||
#include <Network/CommonActorControl.h>
|
#include <Network/CommonActorControl.h>
|
||||||
|
#include <Network/PacketWrappers/ActorControlSelfPacket.h>
|
||||||
|
#include <Network/PacketWrappers/ActorControlPacket.h>
|
||||||
|
|
||||||
|
#include <Manager/PlayerMgr.h>
|
||||||
|
|
||||||
#include "Territory/Territory.h"
|
#include "Territory/Territory.h"
|
||||||
#include "Network/PacketWrappers/ActorControlSelfPacket.h"
|
|
||||||
#include "Network/PacketWrappers/ActorControlPacket.h"
|
|
||||||
#include "Actor/Player.h"
|
#include "Actor/Player.h"
|
||||||
|
#include <Territory/InstanceObjectCache.h>
|
||||||
|
|
||||||
using namespace Sapphire::World::Manager;
|
using namespace Sapphire::World::Manager;
|
||||||
using namespace Sapphire::World;
|
using namespace Sapphire::World;
|
||||||
|
@ -42,7 +48,7 @@ void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType war
|
||||||
|
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, pTeri->getTerritoryTypeId() ), true );
|
player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, pTeri->getTerritoryTypeId() ), true );
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) );
|
player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) );
|
||||||
player.setStateFlag( PlayerStateFlag::BetweenAreas );
|
Common::Service< PlayerMgr >::ref().onSetStateFlag( player, PlayerStateFlag::BetweenAreas );
|
||||||
|
|
||||||
auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() );
|
auto moveTerritoryPacket = makeZonePacket< FFXIVIpcMoveTerritory >( player.getId() );
|
||||||
moveTerritoryPacket->data().index = -1;
|
moveTerritoryPacket->data().index = -1;
|
||||||
|
@ -61,13 +67,28 @@ void WarpMgr::requestMoveTerritory( Entity::Player& player, Common::WarpType war
|
||||||
taskMgr.queueTask( makeMoveTerritoryTask( player, warpType, targetTerritoryId, targetPos, targetRot, 2000 ) );
|
taskMgr.queueTask( makeMoveTerritoryTask( player, warpType, targetTerritoryId, targetPos, targetRot, 2000 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot )
|
||||||
|
{
|
||||||
|
m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot };
|
||||||
|
|
||||||
|
player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, 0, player.getTerritoryTypeId(), 1 ), true );
|
||||||
|
player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) );
|
||||||
|
|
||||||
|
auto& taskMgr = Common::Service< TaskMgr >::ref();
|
||||||
|
taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) );
|
||||||
|
}
|
||||||
|
|
||||||
void WarpMgr::finishWarp( Entity::Player& player )
|
void WarpMgr::finishWarp( Entity::Player& player )
|
||||||
{
|
{
|
||||||
|
auto& playerMgr = Common::Service< PlayerMgr >::ref();
|
||||||
|
|
||||||
WarpType warpType = WarpType::WARP_TYPE_NORMAL;
|
WarpType warpType = WarpType::WARP_TYPE_NORMAL;
|
||||||
auto it = m_entityIdToWarpInfoMap.find( player.getId() );
|
auto it = m_entityIdToWarpInfoMap.find( player.getId() );
|
||||||
if( it != m_entityIdToWarpInfoMap.end() )
|
if( it != m_entityIdToWarpInfoMap.end() )
|
||||||
warpType = it->second.m_warpType;
|
warpType = it->second.m_warpType;
|
||||||
|
|
||||||
|
uint32_t vfxType = 0; // seems to only be used for raise animation?
|
||||||
|
|
||||||
switch( warpType )
|
switch( warpType )
|
||||||
{
|
{
|
||||||
case WarpType::WARP_TYPE_REISE:
|
case WarpType::WARP_TYPE_REISE:
|
||||||
|
@ -78,34 +99,93 @@ void WarpMgr::finishWarp( Entity::Player& player )
|
||||||
player.resetHp();
|
player.resetHp();
|
||||||
player.resetMp();
|
player.resetMp();
|
||||||
player.setStatus( Common::ActorStatus::Idle );
|
player.setStatus( Common::ActorStatus::Idle );
|
||||||
|
vfxType = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto zoneInPacket = makeActorControlSelf( player.getId(), Appear, warpType, 0, 0, 0 );
|
auto zoneInPacket = makeActorControlSelf( player.getId(), Appear, warpType, vfxType, 0, 0 );
|
||||||
auto SetStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
auto setStatusPacket = makeActorControl( player.getId(), SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) );
|
||||||
|
player.setZoningType( Common::ZoningType::None );
|
||||||
player.setZoningType( Common::ZoneingType::None );
|
|
||||||
|
|
||||||
if( !player.getGmInvis() )
|
if( !player.getGmInvis() )
|
||||||
player.sendToInRangeSet( zoneInPacket );
|
player.sendToInRangeSet( zoneInPacket );
|
||||||
|
|
||||||
player.sendToInRangeSet( SetStatusPacket, true );
|
player.sendToInRangeSet( setStatusPacket, true );
|
||||||
|
|
||||||
auto& server = Common::Service< WorldServer >::ref();
|
auto& server = Common::Service< WorldServer >::ref();
|
||||||
server.queueForPlayer( player.getCharacterId(), zoneInPacket );
|
server.queueForPlayer( player.getCharacterId(), zoneInPacket );
|
||||||
|
|
||||||
player.unsetStateFlag( PlayerStateFlag::BetweenAreas );
|
playerMgr.onUnsetStateFlag( player, PlayerStateFlag::BetweenAreas );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WarpMgr::requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot )
|
void WarpMgr::requestPlayerTeleport( Entity::Player& player, uint16_t aetheryteId, uint8_t teleportType )
|
||||||
{
|
{
|
||||||
m_entityIdToWarpInfoMap[ player.getId() ] = { 0, warpType, targetPos, targetRot };
|
auto& exdData = Common::Service< Data::ExdData >::ref();
|
||||||
|
auto& teriMgr = Common::Service< TerritoryMgr >::ref();
|
||||||
|
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), WarpStart, warpType, 1, 0, player.getTerritoryTypeId(), 1 ), true );
|
auto aetherData = exdData.getRow< Excel::Aetheryte >( aetheryteId );
|
||||||
player.sendToInRangeSet( makeActorControl( player.getId(), ActorDespawnEffect, warpType ) );
|
|
||||||
|
|
||||||
auto& taskMgr = Common::Service< TaskMgr >::ref();
|
if( !aetherData )
|
||||||
taskMgr.queueTask( makeWarpTask( player, warpType, targetPos, targetRot, 1000 ) );
|
return;
|
||||||
|
|
||||||
|
const auto& data = aetherData->data();
|
||||||
|
|
||||||
|
auto& instanceObjectCache = Common::Service< InstanceObjectCache >::ref();
|
||||||
|
auto pop = instanceObjectCache.getPopRangeInfo( data.PopRange[ 0 ] );
|
||||||
|
|
||||||
|
Common::FFXIVARR_POSITION3 pos{ 0.f, 0.f, 0.f };
|
||||||
|
|
||||||
|
float rot = 0.f;
|
||||||
|
|
||||||
|
if( pop )
|
||||||
|
{
|
||||||
|
PlayerMgr::sendDebug( player, "Teleport: popRange {0} found!", data.PopRange[ 0 ] );
|
||||||
|
pos = pop->m_pos;
|
||||||
|
rot = pop->m_rotation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlayerMgr::sendDebug( player, "Teleport: popRange {0} not found in {1}!", data.PopRange[ 0 ], data.TerritoryType );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto townPlace = exdData.getRow< Excel::PlaceName >( data.TelepoName );
|
||||||
|
auto aetherytePlace = exdData.getRow< Excel::PlaceName >( data.TransferName );
|
||||||
|
|
||||||
|
PlayerMgr::sendDebug( player, "Teleport: {0} - {1} ({2})",
|
||||||
|
townPlace->getString( townPlace->data().Text.SGL ),
|
||||||
|
aetherytePlace->getString( aetherytePlace->data().Text.SGL ),
|
||||||
|
data.TerritoryType );
|
||||||
|
|
||||||
|
// if it is a teleport in the same zone, we want to do warp instead of moveTerri
|
||||||
|
bool sameTerritory = player.getTerritoryTypeId() == data.TerritoryType;
|
||||||
|
|
||||||
|
WarpType warpType = WarpType::WARP_TYPE_NORMAL;
|
||||||
|
// TODO: should teleport type be a separate enum?
|
||||||
|
if( teleportType == 1 || teleportType == 2 ) // teleport
|
||||||
|
{
|
||||||
|
warpType = WarpType::WARP_TYPE_TELEPO;
|
||||||
|
player.setZoningType( Common::ZoningType::Teleport );
|
||||||
|
}
|
||||||
|
else if( teleportType == 3 ) // return
|
||||||
|
{
|
||||||
|
warpType = WarpType::WARP_TYPE_HOME_POINT;
|
||||||
|
player.setZoningType( Common::ZoningType::Return );
|
||||||
|
}
|
||||||
|
else if( teleportType == 4 ) // return
|
||||||
|
{
|
||||||
|
warpType = WarpType::WARP_TYPE_REISE;
|
||||||
|
player.setZoningType( Common::ZoningType::ReturnDead );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sameTerritory )
|
||||||
|
requestWarp( player, warpType, pos, rot );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto pTeri = teriMgr.getZoneByTerritoryTypeId( data.TerritoryType );
|
||||||
|
if( !pTeri )
|
||||||
|
return;
|
||||||
|
|
||||||
|
requestMoveTerritory( player, warpType, pTeri->getGuId(), pos, rot );
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -21,10 +21,40 @@ namespace Sapphire::World::Manager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WarpMgr() = default;
|
WarpMgr() = default;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// request to move a player to specified territorytype and position, with given WarpType
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="player"></param>
|
||||||
|
/// <param name="warpType"></param>
|
||||||
|
/// <param name="targetTerritoryId"></param>
|
||||||
|
/// <param name="targetPos"></param>
|
||||||
|
/// <param name="targetRot"></param>
|
||||||
void requestMoveTerritory( Entity::Player& player, Common::WarpType warpType, uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot );
|
void requestMoveTerritory( Entity::Player& player, Common::WarpType warpType, uint32_t targetTerritoryId, Common::FFXIVARR_POSITION3 targetPos, float targetRot );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// handle player state pre-warp and tells client to warp player
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="player"></param>
|
||||||
|
/// <param name="warpType"></param>
|
||||||
|
/// <param name="targetPos"></param>
|
||||||
|
/// <param name="targetRot"></param>
|
||||||
void requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot );
|
void requestWarp( Entity::Player& player, Common::WarpType warpType, Common::FFXIVARR_POSITION3 targetPos, float targetRot );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// handle player state post-warp after client is done loading
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="player"></param>
|
||||||
void finishWarp( Entity::Player& player );
|
void finishWarp( Entity::Player& player );
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// teleport a player to specified aetheryte and teleport type (teleport, return, etc)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="player"></param>
|
||||||
|
/// <param name="aetheryteId"></param>
|
||||||
|
/// <param name="teleportType"></param>
|
||||||
|
void requestPlayerTeleport( Entity::Player& player, uint16_t aetheryteId, uint8_t teleportType );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map< uint32_t, WarpInfo > m_entityIdToWarpInfoMap;
|
std::unordered_map< uint32_t, WarpInfo > m_entityIdToWarpInfoMap;
|
||||||
|
|
||||||
|
|
|
@ -139,15 +139,16 @@ uint32_t CalcStats::calculateMaxHp( Player& player )
|
||||||
|
|
||||||
auto vitMod = player.getBonusStat( Common::BaseParam::Vitality );
|
auto vitMod = player.getBonusStat( Common::BaseParam::Vitality );
|
||||||
float baseStat = calculateBaseStat( player );
|
float baseStat = calculateBaseStat( player );
|
||||||
uint16_t vitStat = static_cast< uint16_t >( player.getStatValue( Common::BaseParam::Vitality ) ) + static_cast< uint16_t >( vitMod );
|
auto baseParamVit = player.getStatValue( Common::BaseParam::Vitality );
|
||||||
|
auto vitStat = player.getStatValue( Common::BaseParam::Vitality ) + vitMod;
|
||||||
uint16_t hpMod = paramGrowthInfo->data().ParamBase;
|
uint16_t hpMod = paramGrowthInfo->data().ParamBase;
|
||||||
uint16_t jobModHp = classInfo->data().Hp;
|
uint16_t jobModHp = classInfo->data().Hp;
|
||||||
float approxBaseHp = 0.0f; // Read above
|
float approxBaseHp = 0.0f; // Read above
|
||||||
|
|
||||||
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
|
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
|
||||||
|
|
||||||
uint16_t result = static_cast< uint16_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
|
auto result = static_cast< uint32_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
|
||||||
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );
|
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +177,7 @@ uint32_t CalcStats::calculateMaxHp( Chara& chara )
|
||||||
|
|
||||||
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
|
approxBaseHp = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::HP ] );
|
||||||
|
|
||||||
uint16_t result = static_cast< uint16_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
|
auto result = static_cast< uint32_t >( floor( jobModHp * ( approxBaseHp / 100.0f ) ) +
|
||||||
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );
|
floor( hpMod / 100.0f * ( vitStat - baseStat ) ) );
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -47,7 +47,12 @@ void Sapphire::Network::GameConnection::actionRequest( const Packets::FFXIVARR_P
|
||||||
if( !action )
|
if( !action )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
actionMgr.handleTargetedPlayerAction( player, actionId, action, targetId, sequence );
|
auto category = static_cast< Common::ActionCategory >( action->data().Category );
|
||||||
|
|
||||||
|
if( category == Common::ActionCategory::ItemManipulation )
|
||||||
|
actionMgr.handleItemManipulationAction( player, actionId, action, sequence );
|
||||||
|
else
|
||||||
|
actionMgr.handleTargetedPlayerAction( player, actionId, action, targetId, sequence );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -327,14 +327,14 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
|
||||||
if( param2 == 0 )
|
if( param2 == 0 )
|
||||||
{
|
{
|
||||||
for( uint8_t i = 0; i < 255; i++ )
|
for( uint8_t i = 0; i < 255; i++ )
|
||||||
targetActor->getAsPlayer()->learnSong( i, 0 );
|
Service< World::Manager::PlayerMgr >::ref().onUnlockOrchestrion( *targetPlayer, i, 0 );
|
||||||
|
|
||||||
PlayerMgr::sendServerNotice( player, "All Songs for {0} were turned on.", targetPlayer->getName());
|
PlayerMgr::sendServerNotice( player, "All Songs for {0} were turned on.", targetPlayer->getName() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
targetActor->getAsPlayer()->learnSong( static_cast< uint8_t >( param2 ), 0 );
|
Service< World::Manager::PlayerMgr >::ref().onUnlockOrchestrion( *targetPlayer, static_cast< uint8_t >( param2 ), 0 );
|
||||||
PlayerMgr::sendServerNotice( player, "Song {0} for {1} was turned on.", param2, targetPlayer->getName());
|
PlayerMgr::sendServerNotice( player, "Song {0} for {1} was turned on.", param2, targetPlayer->getName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetPlayer->setGc( static_cast< uint8_t >( param1 ) );
|
Service< World::Manager::PlayerMgr >::ref().onSetGc( player, static_cast< uint8_t >( param1 ) );
|
||||||
|
|
||||||
// if we're changing them to a GC, check if they have a rank and if not, set it to the lowest rank
|
// if we're changing them to a GC, check if they have a rank and if not, set it to the lowest rank
|
||||||
if( param1 > 0 )
|
if( param1 > 0 )
|
||||||
|
@ -442,7 +442,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetPlayer->setGcRankAt( static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) );
|
Service< World::Manager::PlayerMgr >::ref().onSetGcRank( player, static_cast< uint8_t >( gcId ), static_cast< uint8_t >( param1 ) );
|
||||||
PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
|
PlayerMgr::sendServerNotice( player, "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
|
||||||
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
|
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
|
||||||
break;
|
break;
|
||||||
|
@ -533,7 +533,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
|
||||||
}
|
}
|
||||||
if( doTeleport )
|
if( doTeleport )
|
||||||
{
|
{
|
||||||
player.teleport( teleport );
|
warpMgr.requestPlayerTeleport( player, teleport, 1 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@ void Sapphire::Network::GameConnection::itemOperation( const Packets::FFXIVARR_P
|
||||||
const auto packet = ZoneChannelPacket< FFXIVIpcClientInventoryItemOperation >( inPacket );
|
const auto packet = ZoneChannelPacket< FFXIVIpcClientInventoryItemOperation >( inPacket );
|
||||||
|
|
||||||
const auto operationType = packet.data().OperationType;
|
const auto operationType = packet.data().OperationType;
|
||||||
const auto splitCount = packet.data().SrcStack;
|
const auto splitCount = packet.data().DstStack;
|
||||||
|
|
||||||
const auto fromSlot = packet.data().SrcContainerIndex;
|
const auto fromSlot = packet.data().SrcContainerIndex;
|
||||||
const auto fromContainer = packet.data().SrcStorageId;
|
const auto fromContainer = packet.data().SrcStorageId;
|
||||||
|
|
|
@ -182,6 +182,8 @@ const char* packetCommandToString( uint16_t commandId )
|
||||||
return "MOBHUNT_RECEIPT_ORDER";
|
return "MOBHUNT_RECEIPT_ORDER";
|
||||||
case MOBHUNT_BREAK_ORDER:
|
case MOBHUNT_BREAK_ORDER:
|
||||||
return "MOBHUNT_BREAK_ORDER";
|
return "MOBHUNT_BREAK_ORDER";
|
||||||
|
case DYE_ITEM:
|
||||||
|
return "DYE_ITEM";
|
||||||
case EMOTE:
|
case EMOTE:
|
||||||
return "EMOTE";
|
return "EMOTE";
|
||||||
case EMOTE_WITH_WARP:
|
case EMOTE_WITH_WARP:
|
||||||
|
@ -458,17 +460,17 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
|
||||||
}
|
}
|
||||||
case PacketCommand::CANCEL_MOUNT:
|
case PacketCommand::CANCEL_MOUNT:
|
||||||
{
|
{
|
||||||
player.setMount( 0 );
|
Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketCommand::COMPANION:
|
case PacketCommand::COMPANION:
|
||||||
{
|
{
|
||||||
player.setCompanion( static_cast< uint8_t >( param1 ) );
|
Common::Service< World::Manager::PlayerMgr >::ref().onCompanionUpdate( player, static_cast< uint8_t >( param1 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketCommand::COMPANION_CANCEL:
|
case PacketCommand::COMPANION_CANCEL:
|
||||||
{
|
{
|
||||||
player.setCompanion( 0 );
|
Common::Service< World::Manager::PlayerMgr >::ref().onCompanionUpdate( player, 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketCommand::REQUEST_STATUS_RESET: // Remove status (clicking it off)
|
case PacketCommand::REQUEST_STATUS_RESET: // Remove status (clicking it off)
|
||||||
|
@ -583,14 +585,15 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
|
||||||
}
|
}
|
||||||
case PacketCommand::REVIVE: // return dead / accept raise
|
case PacketCommand::REVIVE: // return dead / accept raise
|
||||||
{
|
{
|
||||||
|
auto& warpMgr = Service< WarpMgr >::ref();
|
||||||
switch( static_cast < ResurrectType >( param1 ) )
|
switch( static_cast < ResurrectType >( param1 ) )
|
||||||
{
|
{
|
||||||
case ResurrectType::RaiseSpell:
|
case ResurrectType::RaiseSpell:
|
||||||
// todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
|
// todo: handle raise case (set position to raiser, apply weakness status, set hp/mp/tp as well as packet)
|
||||||
player.teleport( player.getHomepoint(), 3 );
|
warpMgr.requestPlayerTeleport( player, player.getHomepoint(), 5 );
|
||||||
break;
|
break;
|
||||||
case ResurrectType::Return:
|
case ResurrectType::Return:
|
||||||
player.teleport( player.getHomepoint(), 3 );
|
warpMgr.requestPlayerTeleport( player, player.getHomepoint(), 4 );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -623,7 +626,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
|
||||||
player.teleportQuery( static_cast< uint16_t >( param11 ) );
|
player.teleportQuery( static_cast< uint16_t >( param11 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* case PacketCommand::DyeItem: // Dye item
|
case PacketCommand::DYE_ITEM: // Dye item
|
||||||
{
|
{
|
||||||
// param11 = item to dye container
|
// param11 = item to dye container
|
||||||
// param12 = item to dye slot
|
// param12 = item to dye slot
|
||||||
|
@ -631,7 +634,7 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_
|
||||||
// param4 = dye bag slot
|
// param4 = dye bag slot
|
||||||
player.setDyeingInfo( param11, param12, param2, param4 );
|
player.setDyeingInfo( param11, param12, param2, param4 );
|
||||||
break;
|
break;
|
||||||
}*/
|
}
|
||||||
case PacketCommand::DIRECTOR_INIT_RETURN: // Director init finish
|
case PacketCommand::DIRECTOR_INIT_RETURN: // Director init finish
|
||||||
{
|
{
|
||||||
pZone->onInitDirector( player );
|
pZone->onInitDirector( player );
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Ping response packet.
|
* @brief HUD stats packet.
|
||||||
*/
|
*/
|
||||||
class HudParamPacket : public ZoneChannelPacket< FFXIVIpcHudParam >
|
class HudParamPacket : public ZoneChannelPacket< FFXIVIpcHudParam >
|
||||||
{
|
{
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
m_data.ActiveType = player.getStance();
|
m_data.ActiveType = player.getStance();
|
||||||
m_data.Flag = 0;
|
m_data.Flag = 0;
|
||||||
|
|
||||||
if( player.getZoningType() != Common::ZoneingType::None || player.getGmInvis() )
|
if( player.getZoningType() != Common::ZoningType::None || player.getGmInvis() )
|
||||||
{
|
{
|
||||||
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Invisible );
|
m_data.Flag |= static_cast< uint16_t >( Common::DisplayFlags::Invisible );
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,17 +11,17 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
/**
|
/**
|
||||||
* @brief The update inventory-slot packet.
|
* @brief The update inventory-slot packet.
|
||||||
*/
|
*/
|
||||||
class UpdateInventorySlotPacket : public ZoneChannelPacket< FFXIVIpcNormalItem >
|
class UpdateInventorySlotPacket : public ZoneChannelPacket< FFXIVIpcUpdateItem >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UpdateInventorySlotPacket( uint32_t playerId, uint16_t slot, uint16_t storageId, const Item& item, uint32_t contextId ) :
|
UpdateInventorySlotPacket( uint32_t playerId, uint16_t slot, uint16_t storageId, const Item& item, uint32_t contextId ) :
|
||||||
ZoneChannelPacket< FFXIVIpcNormalItem >( playerId, playerId )
|
ZoneChannelPacket< FFXIVIpcUpdateItem >( playerId, playerId )
|
||||||
{
|
{
|
||||||
initialize( slot, storageId, item, contextId );
|
initialize( slot, storageId, item, contextId );
|
||||||
};
|
};
|
||||||
|
|
||||||
UpdateInventorySlotPacket( uint32_t playerId, uint16_t slot, uint16_t storageId, uint32_t contextId ) :
|
UpdateInventorySlotPacket( uint32_t playerId, uint16_t slot, uint16_t storageId, uint32_t contextId ) :
|
||||||
ZoneChannelPacket< FFXIVIpcNormalItem >( playerId, playerId )
|
ZoneChannelPacket< FFXIVIpcUpdateItem >( playerId, playerId )
|
||||||
{
|
{
|
||||||
initialize( slot, storageId, contextId );
|
initialize( slot, storageId, contextId );
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
m_data.item.flags = static_cast< uint8_t >( item.isHq() ? 1 : 0 );
|
m_data.item.flags = static_cast< uint8_t >( item.isHq() ? 1 : 0 );
|
||||||
m_data.item.refine = item.getSpiritbond();
|
m_data.item.refine = item.getSpiritbond();
|
||||||
m_data.item.stain = static_cast< uint8_t >( item.getStain() );
|
m_data.item.stain = static_cast< uint8_t >( item.getStain() );
|
||||||
|
m_data.item.durability = item.getDurability();
|
||||||
m_data.item.signatureId = 0;
|
m_data.item.signatureId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,11 @@ namespace Sapphire::ScriptAPI
|
||||||
virtual void onExecute( Sapphire::World::Action::Action& action );
|
virtual void onExecute( Sapphire::World::Action::Action& action );
|
||||||
|
|
||||||
virtual void onInterrupt( Sapphire::World::Action::Action& action );
|
virtual void onInterrupt( Sapphire::World::Action::Action& action );
|
||||||
|
|
||||||
|
World::Manager::WarpMgr& warpMgr()
|
||||||
|
{
|
||||||
|
return Common::Service< World::Manager::WarpMgr >::ref();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -99,7 +99,7 @@ void Sapphire::InstanceContent::onPlayerZoneIn( Entity::Player& player )
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark player as "bound by duty"
|
// mark player as "bound by duty"
|
||||||
player.setStateFlag( PlayerStateFlag::BoundByDuty );
|
Common::Service< World::Manager::PlayerMgr >::ref().onSetStateFlag( player, PlayerStateFlag::BoundByDuty );
|
||||||
|
|
||||||
sendDirectorInit( player );
|
sendDirectorInit( player );
|
||||||
}
|
}
|
||||||
|
@ -614,7 +614,7 @@ void Sapphire::InstanceContent::clearDirector( Entity::Player& player )
|
||||||
|
|
||||||
player.setDirectorInitialized( false );
|
player.setDirectorInitialized( false );
|
||||||
// remove "bound by duty" state
|
// remove "bound by duty" state
|
||||||
player.unsetStateFlag( PlayerStateFlag::BoundByDuty );
|
Service< World::Manager::PlayerMgr >::ref().onUnsetStateFlag( player, PlayerStateFlag::BoundByDuty );
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Sapphire::InstanceContent::getExpireValue()
|
uint32_t Sapphire::InstanceContent::getExpireValue()
|
||||||
|
|
Loading…
Add table
Reference in a new issue