mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-28 12:17:46 +00:00
Merge actor_rewrite
This commit is contained in:
commit
76ccca75a9
393 changed files with 18858 additions and 3472 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -113,4 +113,8 @@ src/common/Version\.cpp
|
|||
.mtime_cache
|
||||
|
||||
# generated script loader files
|
||||
src/servers/sapphire_zone/Script/Scripts/*/ScriptLoader.cpp
|
||||
src/servers/sapphire_zone/Script/Scripts/*/ScriptLoader.cpp
|
||||
|
||||
# cotire generated files/folders
|
||||
cotire/
|
||||
*_cotire.cmake
|
|
@ -31,6 +31,7 @@ set(LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/libraries")
|
|||
include( "cmake/boost.cmake" )
|
||||
include( "cmake/mysql.cmake" )
|
||||
include( "cmake/compiler.cmake" )
|
||||
include( "cmake/cotire.cmake" )
|
||||
|
||||
##############################
|
||||
# Git #
|
||||
|
@ -68,3 +69,4 @@ add_subdirectory("src/tools/exd_struct_gen")
|
|||
add_subdirectory("src/tools/exd_struct_test")
|
||||
add_subdirectory("src/tools/quest_parser")
|
||||
#add_subdirectory("src/tools/pcb_reader")
|
||||
#add_subdirectory("src/tools/event_object_parser")
|
||||
|
|
|
@ -33,10 +33,10 @@ switch( commandId )
|
|||
case 0x01: // Toggle sheathe
|
||||
{
|
||||
if ( param11 == 1 )
|
||||
pPlayer->setStance( Entity::Actor::Stance::Active );
|
||||
pPlayer->setStance( Entity::Chara::Stance::Active );
|
||||
else
|
||||
{
|
||||
pPlayer->setStance( Entity::Actor::Stance::Passive );
|
||||
pPlayer->setStance( Entity::Chara::Stance::Passive );
|
||||
pPlayer->setAutoattack( false );
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ if(UNIX)
|
|||
endif()
|
||||
else()
|
||||
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
|
||||
message(STATUS "Using boost in /libraries/external")
|
||||
set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
|
||||
set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME}/lib32-msvc-14.0)
|
||||
set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
|
||||
set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME}/lib32-msvc-14.0)
|
||||
else()
|
||||
find_package(Boost ${SAPPHIRE_BOOST_VER} COMPONENTS system)
|
||||
if(Boost_FOUND)
|
||||
|
|
|
@ -21,6 +21,10 @@ else()
|
|||
# incremental linking
|
||||
message(STATUS "Enabling Incremental Linking..")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /INCREMENTAL")
|
||||
|
||||
# enable building with multiple processes
|
||||
message(STATUS "Enabling Build with Multiple Processes..")
|
||||
add_definitions(/MP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
4055
cmake/cotire.cmake
Normal file
4055
cmake/cotire.cmake
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,8 +14,9 @@
|
|||
namespace Core {
|
||||
namespace Common {
|
||||
|
||||
// 99 is the last spawn id that seems to spawn any actor
|
||||
const uint8_t MAX_DISPLAYED_ACTORS = 99;
|
||||
// 99 is the last spawn id that seems to spawn any actor
|
||||
const uint8_t MAX_DISPLAYED_ACTORS = 99;
|
||||
const uint8_t MAX_DISPLAYED_EOBJS = 40;
|
||||
|
||||
const int32_t INVALID_GAME_OBJECT_ID = 0xE0000000;
|
||||
|
||||
|
@ -403,70 +404,21 @@ namespace Core {
|
|||
Gathering,
|
||||
Fishing,
|
||||
|
||||
BeingRaised,
|
||||
BetweenAreas,
|
||||
Stealthed,
|
||||
InnRoom,
|
||||
Jumping,
|
||||
AutoRun,
|
||||
Occupied6,
|
||||
BetweenAreas1,
|
||||
SystemError,
|
||||
LoggingOut,
|
||||
enum PlayerStateFlag : uint8_t
|
||||
{
|
||||
HideUILockChar = 0, // as the name suggests, hides the ui and logs the char...
|
||||
InCombat = 1, // in Combat, locks gearchange/return/teleport
|
||||
Casting = 2,
|
||||
InNpcEvent = 7, // when talking to an npc, locks ui giving "occupied" message
|
||||
|
||||
InvalidLocation,
|
||||
WaitingForDuty,
|
||||
BoundByDuty1,
|
||||
Mounting,
|
||||
WatchingCutscene,
|
||||
WaitingForDutyFinder,
|
||||
CreatingCharacter,
|
||||
Jumping1,
|
||||
PvpDisplay,
|
||||
StatusAfflication2,
|
||||
InNpcEvent1 = 10, // Sent together with InNpcEvent, when waiting for input? just a guess...
|
||||
|
||||
Mounting1,
|
||||
CarryingItem,
|
||||
UsingPartyFinder,
|
||||
HousingFunctions,
|
||||
Transformed,
|
||||
FreeTrail,
|
||||
BeingMoved,
|
||||
Mounting2,
|
||||
StatusAffliction3,
|
||||
StatusAffliction4,
|
||||
BetweenAreas = 24,
|
||||
BoundByDuty = 28,
|
||||
WatchingCutscene = 50, // this is actually just a dummy, this id is different
|
||||
|
||||
RegisteringRaceOrMatch,
|
||||
WaitingForRaceOrMatch,
|
||||
WaitingForTripleTriadMatch,
|
||||
InFlight,
|
||||
WatchingCutscene1,
|
||||
DeepDungeon,
|
||||
Swimming,
|
||||
Diving,
|
||||
RegisteringTripleTriad,
|
||||
WaitingTripleTriad,
|
||||
InCrossWorldParty
|
||||
|
||||
};
|
||||
|
||||
enum struct FateStatus : uint8_t
|
||||
{
|
||||
Active = 2,
|
||||
Inactive = 4,
|
||||
Preparing = 7,
|
||||
Completed = 8,
|
||||
};
|
||||
|
||||
enum ActorControlType : uint16_t
|
||||
{
|
||||
ToggleWeapon = 0x01,
|
||||
SetStatus = 0x02,
|
||||
CastStart = 0x03,
|
||||
ToggleAggro = 0x04,
|
||||
ClassJobChange = 0x05,
|
||||
DefeatMsg = 0x06,
|
||||
GainExpMsg = 0x07,
|
||||
};
|
||||
|
||||
LevelUpEffect = 0x0A,
|
||||
|
||||
|
@ -778,13 +730,7 @@ namespace Core {
|
|||
FreeCompany = 5,
|
||||
};
|
||||
|
||||
enum SocialListType : uint8_t
|
||||
{
|
||||
PartyList = 0x02,
|
||||
FriendList = 0x0b,
|
||||
SearchList = 0x0e,
|
||||
};
|
||||
|
||||
typedef std::vector< PlayerStateFlag > PlayerStateFlagList;
|
||||
|
||||
// todo: rename SocialRequestAction and SocialRequestResponse cause they seem ambiguous
|
||||
enum class SocialRequestAction : uint8_t
|
||||
|
|
|
@ -463,6 +463,7 @@ namespace Common {
|
|||
//Weather.exd
|
||||
enum class Weather : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
ClearSkies = 1,
|
||||
FairSkies = 2,
|
||||
Clouds = 3,
|
||||
|
|
|
@ -172,6 +172,7 @@ Core::Data::Aetheryte::Aetheryte( uint32_t row_id, Core::Data::ExdDataGenerated*
|
|||
placeName = exdData->getField< uint16_t >( row, 8 );
|
||||
aethernetName = exdData->getField< uint16_t >( row, 9 );
|
||||
territory = exdData->getField< uint16_t >( row, 10 );
|
||||
levelId = exdData->getField< uint32_t >( row, 11 );
|
||||
isAetheryte = exdData->getField< bool >( row, 15 );
|
||||
aethernetGroup = exdData->getField< uint8_t >( row, 16 );
|
||||
map = exdData->getField< uint16_t >( row, 19 );
|
||||
|
|
|
@ -496,6 +496,7 @@ struct Aetheryte
|
|||
uint16_t placeName;
|
||||
uint16_t aethernetName;
|
||||
uint16_t territory;
|
||||
uint32_t levelId;
|
||||
bool isAetheryte;
|
||||
uint8_t aethernetGroup;
|
||||
uint16_t map;
|
||||
|
|
|
@ -72,8 +72,8 @@ namespace Packets {
|
|||
|
||||
Playtime = 0x00DF, // updated 4.2
|
||||
CFRegistered = 0x00B8, // updated 4.1
|
||||
|
||||
|
||||
SocialRequestResponse = 0x00BB, // updated 4.1
|
||||
CancelAllianceForming = 0x00C6, // updated 4.2
|
||||
Chat = 0x00E1, // updated 4.2
|
||||
SocialRequestResponse = 0x00E5, // updated 4.1
|
||||
SocialRequestReceive = 0x00E6, // updated 4.2
|
||||
|
@ -104,15 +104,18 @@ namespace Packets {
|
|||
NpcSpawn = 0x015D, // updated 4.2
|
||||
ActorMove = 0x015E, // updated 4.2
|
||||
ActorSetPos = 0x0160, // updated 4.2
|
||||
|
||||
ActorCast = 0x0162, // updated 4.2
|
||||
|
||||
HateList = 0x0165, // updated 4.2
|
||||
|
||||
ObjectSpawn = 0x0167, // updated 4.2
|
||||
ObjectDespawn = 0x0168, // updated 4.2
|
||||
UpdateClassInfo = 0x0169, // updated 4.2
|
||||
|
||||
InitUI = 0x016B, // updated 4.2
|
||||
|
||||
ActorOwner = 0x016D, // updated 4.2 ?
|
||||
|
||||
PlayerStats = 0x016C, // updated 4.2
|
||||
ActorOwner = 0x016D, // updated 4.2 ?
|
||||
PlayerStateFlags = 0x016E, // updated 4.2
|
||||
PlayerClassInfo = 0x016F, // updated 4.2
|
||||
ModelEquip = 0x0170, // updated 4.2
|
||||
|
@ -127,6 +130,7 @@ namespace Packets {
|
|||
UpdateInventorySlot = 0x0181, // updated 4.2
|
||||
|
||||
EventPlay = 0x018E, // updated 4.2
|
||||
DirectorPlayScene = 0x0192, // updated 4.2
|
||||
|
||||
EventStart = 0x0198, // updated 4.2
|
||||
EventFinish = 0x0199, // updated 4.2
|
||||
|
@ -209,6 +213,8 @@ namespace Packets {
|
|||
|
||||
FcInfoReqHandler = 0x011A, // updated 4.2
|
||||
|
||||
|
||||
ReqJoinNoviceNetwork = 0x0129, // updated 4.2
|
||||
ReqCountdownInitiate = 0x012C, // updated 4.2
|
||||
ReqCountdownCancel = 0x012D, // updated 4.2
|
||||
|
||||
|
@ -230,8 +236,8 @@ namespace Packets {
|
|||
OutOfRangeEventHandler = 0x014B, // updated 4.2
|
||||
EnterTeriEventHandler = 0x014C, // updated 4.2
|
||||
|
||||
ReturnEventHandler = 0x0151, // updated 4.2 ?
|
||||
TradeReturnEventHandler = 0x0152, // updated 4.2 ?
|
||||
ReturnEventHandler = 0x0151, // updated 4.2
|
||||
TradeReturnEventHandler = 0x0152, // updated 4.2
|
||||
|
||||
|
||||
LinkshellEventHandler = 0x0144, // updated 4.1 ??
|
||||
|
|
|
@ -233,7 +233,7 @@ struct FFXIVIpcLinkshellList : FFXIVIpcBasePacket<LinkshellList>
|
|||
struct FFXIVIpcStatusEffectList : FFXIVIpcBasePacket<StatusEffectList>
|
||||
{
|
||||
uint8_t classId;
|
||||
uint8_t classId1;
|
||||
uint8_t level1;
|
||||
uint16_t level;
|
||||
uint32_t current_hp;
|
||||
uint32_t max_hp;
|
||||
|
@ -427,7 +427,7 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket<PlayerSpawn>
|
|||
uint8_t spawnIndex;
|
||||
uint8_t state;
|
||||
uint8_t persistantEmote;
|
||||
uint8_t type;
|
||||
uint8_t modelType; // modelType -> eventSystemDefine
|
||||
uint8_t subtype;
|
||||
uint8_t voice;
|
||||
uint16_t u25c;
|
||||
|
@ -459,8 +459,7 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket<PlayerSpawn>
|
|||
*/
|
||||
struct FFXIVIpcNpcSpawn : FFXIVIpcBasePacket<NpcSpawn>
|
||||
{
|
||||
uint16_t title;
|
||||
uint16_t u1b;
|
||||
uint32_t gimmickId; // needs to be existing in the map, mob will snap to it
|
||||
uint8_t u2b;
|
||||
uint8_t u2ab;
|
||||
uint8_t gmRank;
|
||||
|
@ -503,7 +502,7 @@ struct FFXIVIpcNpcSpawn : FFXIVIpcBasePacket<NpcSpawn>
|
|||
uint8_t spawnIndex;
|
||||
uint8_t state;
|
||||
uint8_t persistantEmote;
|
||||
uint8_t type;
|
||||
uint8_t modelType;
|
||||
uint8_t subtype;
|
||||
uint8_t voice;
|
||||
uint16_t u25c;
|
||||
|
@ -611,7 +610,7 @@ struct FFXIVIpcHateList : FFXIVIpcBasePacket<HateList>
|
|||
struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket<UpdateClassInfo>
|
||||
{
|
||||
uint8_t classId;
|
||||
uint8_t classId1;
|
||||
uint8_t level1;
|
||||
uint16_t level;
|
||||
uint32_t nextLevelIndex;
|
||||
uint32_t currentExp;
|
||||
|
@ -674,7 +673,7 @@ struct FFXIVIpcInitUI : FFXIVIpcBasePacket<InitUI>
|
|||
uint8_t namedayDay;
|
||||
uint8_t cityState;
|
||||
uint8_t homepoint;
|
||||
uint8_t unknown26;
|
||||
uint8_t unknown26; // 2 if "warrior of light"
|
||||
uint8_t petHotBar;
|
||||
uint8_t companionRank;
|
||||
uint8_t companionStars;
|
||||
|
@ -871,10 +870,8 @@ struct FFXIVIpcActorOwner : FFXIVIpcBasePacket<ActorOwner>
|
|||
*/
|
||||
struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket<PlayerStateFlags>
|
||||
{
|
||||
uint8_t flags[7];
|
||||
uint8_t padding1[3];
|
||||
uint32_t padding2;
|
||||
uint16_t padding;
|
||||
uint8_t flags[12];
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1047,7 +1044,7 @@ struct FFXIVIpcEventStart : FFXIVIpcBasePacket<EventStart>
|
|||
/* 000D */ uint8_t param2;
|
||||
/* 000E */ uint16_t padding;
|
||||
/* 0010 */ uint32_t param3;
|
||||
/* 0014 */ uint32_t padding1;
|
||||
/* 0014 */ uint32_t contentId;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1069,6 +1066,24 @@ struct FFXIVIpcEventPlay : FFXIVIpcBasePacket<EventPlay>
|
|||
uint8_t unknown[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* Structural representation of the packet sent by the server
|
||||
* to play an event
|
||||
*/
|
||||
struct FFXIVIpcDirectorPlayScene : FFXIVIpcBasePacket<DirectorPlayScene>
|
||||
{
|
||||
uint64_t actorId;
|
||||
uint32_t eventId;
|
||||
uint16_t scene;
|
||||
uint16_t padding;
|
||||
uint32_t flags;
|
||||
uint32_t param3;
|
||||
uint8_t param4;
|
||||
uint8_t padding1[3];
|
||||
uint32_t param5;
|
||||
uint8_t unknown[0x40];
|
||||
};
|
||||
|
||||
/**
|
||||
* Structural representation of the packet sent by the server
|
||||
* to finish an event
|
||||
|
@ -1363,24 +1378,33 @@ struct FFXIVIpcMSQTrackerComplete : FFXIVIpcBasePacket<MSQTrackerComplete>
|
|||
|
||||
struct FFXIVIpcObjectSpawn : FFXIVIpcBasePacket<ObjectSpawn>
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t spawnIndex;
|
||||
uint8_t objKind;
|
||||
uint8_t unknown2;
|
||||
uint8_t state;
|
||||
uint8_t unknown3;
|
||||
uint32_t objId;
|
||||
uint32_t actorId;
|
||||
uint32_t levelId;
|
||||
uint32_t unknown10;
|
||||
uint32_t someActorId14;
|
||||
uint32_t hierachyId;
|
||||
uint32_t unknown1C;
|
||||
uint32_t unknown20;
|
||||
uint32_t unknown24;
|
||||
uint32_t unknown28;
|
||||
uint32_t unknown2c;
|
||||
uint32_t gimmickId;
|
||||
float scale;
|
||||
int16_t unknown20a;
|
||||
uint16_t rotation;
|
||||
int16_t unknown24a;
|
||||
int16_t unknown24b;
|
||||
uint16_t unknown28a;
|
||||
int16_t unknown28c;
|
||||
uint32_t unknown2C;
|
||||
Common::FFXIVARR_POSITION3 position;
|
||||
int16_t rotation;
|
||||
int16_t unknown;
|
||||
int16_t unknown3C;
|
||||
int16_t unknown3E;
|
||||
};
|
||||
|
||||
struct FFXIVIpcObjectDespawn : FFXIVIpcBasePacket<ObjectDespawn>
|
||||
{
|
||||
uint8_t spawnIndex;
|
||||
uint8_t padding[7];
|
||||
};
|
||||
|
||||
|
||||
|
|
109
src/common/Util/SpawnIndexAllocator.h
Normal file
109
src/common/Util/SpawnIndexAllocator.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
#ifndef SAPPHIRE_SPAWNINDEXALLOCATOR_H
|
||||
#define SAPPHIRE_SPAWNINDEXALLOCATOR_H
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Util
|
||||
{
|
||||
template< typename T, typename ActorIdType = uint32_t >
|
||||
class SpawnIndexAllocator
|
||||
{
|
||||
public:
|
||||
static_assert( std::is_same< T, uint8_t >::value || std::is_same< T, uint16_t >::value ||
|
||||
std::is_same< T, uint32_t >::value || std::is_same< T, uint64_t >::value,
|
||||
"T must be uint8_t, uint16_t, uint32_t, uint64_t" );
|
||||
|
||||
SpawnIndexAllocator() :
|
||||
m_maxSlotId( 0 ),
|
||||
m_reserveFirstSlot( false )
|
||||
{ }
|
||||
|
||||
void init( T maxSlotId, bool reserveFirstSlot = false )
|
||||
{
|
||||
m_maxSlotId = maxSlotId;
|
||||
m_reserveFirstSlot = reserveFirstSlot;
|
||||
|
||||
setupQueue();
|
||||
|
||||
// todo: reserve max slot id in map to prevent any runtime reshashing
|
||||
}
|
||||
|
||||
T freeUsedSpawnIndex( ActorIdType actorId )
|
||||
{
|
||||
auto it = m_actorIdToAllocatedMap.find( actorId );
|
||||
if( it == m_actorIdToAllocatedMap.end() )
|
||||
return 0;
|
||||
|
||||
auto index = it->second;
|
||||
m_availableIds.push( index );
|
||||
m_actorIdToAllocatedMap.erase( it );
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
T getNextFreeSpawnIndex( ActorIdType actorId )
|
||||
{
|
||||
assert( m_maxSlotId != 0 );
|
||||
|
||||
if( m_availableIds.empty() )
|
||||
return getAllocFailId();
|
||||
|
||||
auto nextId = m_availableIds.front();
|
||||
m_availableIds.pop();
|
||||
|
||||
m_actorIdToAllocatedMap[actorId] = nextId;
|
||||
|
||||
return nextId;
|
||||
}
|
||||
|
||||
void freeAllSpawnIndexes()
|
||||
{
|
||||
setupQueue();
|
||||
|
||||
m_actorIdToAllocatedMap.clear();
|
||||
}
|
||||
|
||||
bool isSpawnIndexValid( T spawnIndex )
|
||||
{
|
||||
return spawnIndex != getAllocFailId();
|
||||
}
|
||||
|
||||
constexpr T getAllocFailId()
|
||||
{
|
||||
return static_cast< T >( -1 );
|
||||
}
|
||||
|
||||
protected:
|
||||
void setupQueue()
|
||||
{
|
||||
assert( m_maxSlotId != 0 );
|
||||
|
||||
while( !m_availableIds.empty() )
|
||||
m_availableIds.pop();
|
||||
|
||||
uint32_t start = 0;
|
||||
|
||||
// slot 0 is reserved when used for spawning actors/players otherwise the local player actor spawnIndex
|
||||
// will be used by another actor and despawn the local player
|
||||
if( m_reserveFirstSlot )
|
||||
start = 1;
|
||||
|
||||
for( uint32_t i = start; i < m_maxSlotId; i++ )
|
||||
m_availableIds.push( i );
|
||||
}
|
||||
|
||||
std::queue< T > m_availableIds;
|
||||
std::unordered_map< ActorIdType, T > m_actorIdToAllocatedMap;
|
||||
|
||||
T m_maxSlotId;
|
||||
bool m_reserveFirstSlot;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //SAPPHIRE_SPAWNINDEXALLOCATOR_H
|
|
@ -34,11 +34,11 @@ namespace Core
|
|||
|
||||
namespace Entity
|
||||
{
|
||||
class Actor;
|
||||
class Chara;
|
||||
class Player;
|
||||
class BattleNpc;
|
||||
|
||||
typedef boost::shared_ptr<Actor> ActorPtr;
|
||||
typedef boost::shared_ptr<Chara> ActorPtr;
|
||||
typedef boost::shared_ptr<Player> PlayerPtr;
|
||||
typedef boost::shared_ptr<BattleNpc> BattleNpcPtr;
|
||||
}
|
||||
|
@ -91,10 +91,10 @@ namespace Core
|
|||
|
||||
namespace Scripting
|
||||
{
|
||||
typedef std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t ) > EventReturnCallback;
|
||||
using EventReturnCallback = std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t ) >;
|
||||
}
|
||||
|
||||
typedef std::function< void( Entity::Player&, uint32_t, uint64_t ) > ActionCallback;
|
||||
using ActionCallback = std::function< void( Entity::Player&, uint32_t, uint64_t ) >;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -148,13 +148,13 @@ namespace Core {
|
|||
{
|
||||
|
||||
std::vector< uint8_t > customize( 26 );
|
||||
std::vector< uint8_t > howTo( 32 );
|
||||
std::vector< uint8_t > aetherytes( 12 );
|
||||
std::vector< uint8_t > discovery( 411 );
|
||||
std::vector< uint8_t > howTo( 33 );
|
||||
std::vector< uint8_t > aetherytes( 16 );
|
||||
std::vector< uint8_t > discovery( 421 );
|
||||
std::vector< uint8_t > questComplete( 396 );
|
||||
std::vector< uint8_t > unlocks( 64 );
|
||||
std::vector< uint8_t > mountGuide( 13 );
|
||||
std::vector< uint8_t > orchestrion( 38 );
|
||||
std::vector< uint8_t > mountGuide( 15 );
|
||||
std::vector< uint8_t > orchestrion( 40 );
|
||||
std::vector< uint8_t > modelEquip( 40 );
|
||||
std::vector< uint8_t > questTracking8( 10 );
|
||||
std::vector< int16_t > questTracking = { -1, -1, -1, -1, -1 };
|
||||
|
|
|
@ -22,7 +22,7 @@ Core::Common::HandleActionType Core::Action::Action::getHandleActionType() const
|
|||
return m_handleActionType;
|
||||
}
|
||||
|
||||
Core::Entity::ActorPtr Core::Action::Action::getTargetActor() const
|
||||
Core::Entity::CharaPtr Core::Action::Action::getTargetChara() const
|
||||
{
|
||||
return m_pTarget;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ void Core::Action::Action::setCastTime( uint32_t castTime )
|
|||
m_castTime = castTime;
|
||||
}
|
||||
|
||||
Core::Entity::ActorPtr Core::Action::Action::getActionSource() const
|
||||
Core::Entity::CharaPtr Core::Action::Action::getActionSource() const
|
||||
{
|
||||
return m_pSource;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Action {
|
|||
|
||||
Common::HandleActionType getHandleActionType() const;
|
||||
|
||||
Entity::ActorPtr getTargetActor() const;
|
||||
Entity::CharaPtr getTargetChara() const;
|
||||
|
||||
bool isInterrupted() const;
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace Action {
|
|||
|
||||
void setCastTime( uint32_t castTime );
|
||||
|
||||
Entity::ActorPtr getActionSource() const;
|
||||
Entity::CharaPtr getActionSource() const;
|
||||
|
||||
virtual void onStart() {};
|
||||
virtual void onFinish() {};
|
||||
|
@ -48,8 +48,8 @@ namespace Action {
|
|||
uint64_t m_startTime;
|
||||
uint32_t m_castTime;
|
||||
|
||||
Entity::ActorPtr m_pSource;
|
||||
Entity::ActorPtr m_pTarget;
|
||||
Entity::CharaPtr m_pSource;
|
||||
Entity::CharaPtr m_pTarget;
|
||||
|
||||
bool m_bInterrupt;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ Core::Action::ActionCast::ActionCast()
|
|||
m_handleActionType = Common::HandleActionType::Event;
|
||||
}
|
||||
|
||||
Core::Action::ActionCast::ActionCast( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint16_t actionId )
|
||||
Core::Action::ActionCast::ActionCast( Entity::CharaPtr pActor, Entity::CharaPtr pTarget, uint16_t actionId )
|
||||
{
|
||||
m_startTime = 0;
|
||||
m_id = actionId;
|
||||
|
@ -84,7 +84,7 @@ void Core::Action::ActionCast::onInterrupt()
|
|||
if( !m_pSource )
|
||||
return;
|
||||
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
//m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting );
|
||||
|
||||
auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt,
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Action {
|
|||
ActionCast();
|
||||
~ActionCast();
|
||||
|
||||
ActionCast( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint16_t actionId );
|
||||
ActionCast( Entity::CharaPtr pActor, Entity::CharaPtr pTarget, uint16_t actionId );
|
||||
|
||||
void onStart() override;
|
||||
void onFinish() override;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include <common/Util/Util.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
|
||||
#include <common/Exd/ExdDataGenerated.h>
|
||||
|
||||
#include "ActionCollision.h"
|
||||
#include "Actor/Actor.h"
|
||||
#include "Actor/Chara.h"
|
||||
#include "Actor/Player.h"
|
||||
|
||||
#include <cmath>
|
||||
|
@ -31,7 +34,7 @@ bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter
|
|||
case TargetFilter::Allies:
|
||||
{
|
||||
// todo: implement ally NPCs
|
||||
actorApplicable = !actor.isBattleNpc();
|
||||
// actorApplicable = !chara.isBattleNpc();
|
||||
break;
|
||||
}
|
||||
case TargetFilter::Party:
|
||||
|
@ -42,12 +45,12 @@ bool ActionCollision::isActorApplicable( Actor& actor, TargetFilter targetFilter
|
|||
}
|
||||
case TargetFilter::Enemies:
|
||||
{
|
||||
actorApplicable = actor.isBattleNpc();
|
||||
//actorApplicable = chara.isBattleNpc();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ( actorApplicable && actor.isAlive() );
|
||||
return ( actorApplicable && actor.getAsChara()->isAlive() );
|
||||
}
|
||||
|
||||
std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXIVARR_POSITION3 aoePosition,
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
#define _ACTIONCOLLISION_H
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <common/Exd/ExdDataGenerated.h>
|
||||
|
||||
#include "Actor/Actor.h"
|
||||
#include "Action.h"
|
||||
|
||||
|
||||
namespace Core {
|
||||
namespace Data
|
||||
{
|
||||
struct Action;
|
||||
}
|
||||
namespace Entity {
|
||||
|
||||
enum class TargetFilter
|
||||
|
|
|
@ -25,7 +25,7 @@ Core::Action::ActionMount::ActionMount()
|
|||
m_handleActionType = HandleActionType::Event;
|
||||
}
|
||||
|
||||
Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, uint16_t mountId )
|
||||
Core::Action::ActionMount::ActionMount( Entity::CharaPtr pActor, uint16_t mountId )
|
||||
{
|
||||
m_startTime = 0;
|
||||
m_id = mountId;
|
||||
|
@ -79,7 +79,7 @@ void Core::Action::ActionMount::onFinish()
|
|||
effectPacket.data().unknown_62 = 13;
|
||||
effectPacket.data().actionTextId = 4;
|
||||
effectPacket.data().numEffects = 1;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( pPlayer->getRotation() );
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( pPlayer->getRot() );
|
||||
effectPacket.data().effectTarget = INVALID_GAME_OBJECT_ID;
|
||||
effectPacket.data().effects[0].effectType = ActionEffectType::Mount;
|
||||
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage;
|
||||
|
@ -95,7 +95,7 @@ void Core::Action::ActionMount::onInterrupt()
|
|||
if( !m_pSource )
|
||||
return;
|
||||
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
//m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting );
|
||||
|
||||
auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt,
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Action {
|
|||
ActionMount();
|
||||
~ActionMount();
|
||||
|
||||
ActionMount( Entity::ActorPtr pActor, uint16_t mountId );
|
||||
ActionMount( Entity::CharaPtr pActor, uint16_t mountId );
|
||||
|
||||
void onStart() override;
|
||||
void onFinish() override;
|
||||
|
|
|
@ -22,7 +22,7 @@ Core::Action::ActionTeleport::ActionTeleport()
|
|||
m_handleActionType = HandleActionType::Event;
|
||||
}
|
||||
|
||||
Core::Action::ActionTeleport::ActionTeleport( Entity::ActorPtr pActor, uint16_t targetZone, uint16_t cost )
|
||||
Core::Action::ActionTeleport::ActionTeleport( Entity::CharaPtr pActor, uint16_t targetZone, uint16_t cost )
|
||||
{
|
||||
m_startTime = 0;
|
||||
m_id = 5;
|
||||
|
@ -89,7 +89,7 @@ void Core::Action::ActionTeleport::onFinish()
|
|||
effectPacket.data().actionTextId = 5;
|
||||
effectPacket.data().unknown_5 = 1;
|
||||
effectPacket.data().numEffects = 1;
|
||||
effectPacket.data().rotation = static_cast< uint16_t >( 0x8000 * ( ( pPlayer->getRotation() + 3.1415926 ) ) / 3.1415926 );
|
||||
effectPacket.data().rotation = static_cast< uint16_t >( 0x8000 * ( ( pPlayer->getRot() + 3.1415926 ) ) / 3.1415926 );
|
||||
effectPacket.data().effectTarget = pPlayer->getId();
|
||||
pPlayer->sendToInRangeSet( effectPacket, true );
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Action {
|
|||
ActionTeleport();
|
||||
~ActionTeleport();
|
||||
|
||||
ActionTeleport( Entity::ActorPtr pActor, uint16_t action, uint16_t cost );
|
||||
ActionTeleport( Entity::CharaPtr pActor, uint16_t action, uint16_t cost );
|
||||
|
||||
void onStart() override;
|
||||
void onFinish() override;
|
||||
|
|
|
@ -23,7 +23,7 @@ Core::Action::EventAction::EventAction()
|
|||
m_handleActionType = HandleActionType::Event;
|
||||
}
|
||||
|
||||
Core::Action::EventAction::EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
|
||||
Core::Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action,
|
||||
ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional )
|
||||
{
|
||||
m_additional = additional;
|
||||
|
@ -55,7 +55,8 @@ void Core::Action::EventAction::onStart()
|
|||
if( m_pSource->isPlayer() )
|
||||
{
|
||||
m_pSource->sendToInRangeSet( control, true );
|
||||
m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Occupied2 );
|
||||
if( m_pSource->getAsPlayer()->hasStateFlag( PlayerStateFlag::InNpcEvent ) )
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::InNpcEvent );
|
||||
}
|
||||
else
|
||||
m_pSource->sendToInRangeSet( control );
|
||||
|
@ -84,7 +85,7 @@ void Core::Action::EventAction::onFinish()
|
|||
|
||||
if( m_pSource->isPlayer() )
|
||||
{
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied2 );
|
||||
//m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied2 );
|
||||
m_pSource->sendToInRangeSet( control, true );
|
||||
}
|
||||
else
|
||||
|
@ -112,8 +113,8 @@ void Core::Action::EventAction::onInterrupt()
|
|||
{
|
||||
auto control1 = ActorControlPacket143( m_pSource->getId(), ActorControlType::FreeEventPos, m_eventId );
|
||||
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat );
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
//m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::NoCombat );
|
||||
//m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 );
|
||||
m_pSource->sendToInRangeSet( control );
|
||||
m_pSource->sendToInRangeSet( control1 );
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Action {
|
|||
EventAction();
|
||||
~EventAction();
|
||||
|
||||
EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
|
||||
EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action,
|
||||
ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional );
|
||||
|
||||
void onStart() override;
|
||||
|
|
|
@ -24,7 +24,7 @@ Core::Action::EventItemAction::EventItemAction()
|
|||
m_handleActionType = HandleActionType::Event;
|
||||
}
|
||||
|
||||
Core::Action::EventItemAction::EventItemAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
|
||||
Core::Action::EventItemAction::EventItemAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action,
|
||||
ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional )
|
||||
{
|
||||
m_additional = additional;
|
||||
|
@ -75,7 +75,7 @@ void Core::Action::EventItemAction::onFinish()
|
|||
effectPacket.data().actionTextId = m_id;
|
||||
effectPacket.data().unknown_5 = 2;
|
||||
effectPacket.data().numEffects = 1;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( m_pSource->getRotation() );
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( m_pSource->getRot() );
|
||||
effectPacket.data().effectTarget = static_cast< uint32_t >( m_additional );
|
||||
|
||||
m_pSource->getAsPlayer()->unsetStateFlag( Common::PlayerStateFlag::Casting );
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Action {
|
|||
EventItemAction();
|
||||
~EventItemAction();
|
||||
|
||||
EventItemAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
|
||||
EventItemAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action,
|
||||
ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional );
|
||||
|
||||
void onStart() override;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,10 @@
|
|||
#ifndef _ACTOR_H_
|
||||
#define _ACTOR_H_
|
||||
#ifndef _GAME_OBJECT_H_
|
||||
#define _GAME_OBJECT_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "GameObject.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
@ -14,284 +13,127 @@ namespace Core {
|
|||
namespace Entity {
|
||||
|
||||
/*!
|
||||
\class Actor
|
||||
\brief Base class for all actors
|
||||
\class GameObject
|
||||
\brief Base class for all actor/objects
|
||||
|
||||
*/
|
||||
class Actor : public GameObject
|
||||
{
|
||||
public:
|
||||
enum Stance : uint8_t
|
||||
class Actor : public boost::enable_shared_from_this< Actor >
|
||||
{
|
||||
Passive = 0,
|
||||
Active = 1,
|
||||
public:
|
||||
enum ObjKind : uint8_t
|
||||
{
|
||||
None = 0x00,
|
||||
Player = 0x01,
|
||||
BattleNpc = 0x02,
|
||||
EventNpc = 0x03,
|
||||
Treasure = 0x04,
|
||||
Aetheryte = 0x05,
|
||||
GatheringPoint = 0x06,
|
||||
EventObj = 0x07,
|
||||
Mount = 0x08,
|
||||
Companion = 0x09, // this probably actually means minion
|
||||
Retainer = 0x0A,
|
||||
Area = 0x0B,
|
||||
Housing = 0x0C,
|
||||
Cutscene = 0x0D,
|
||||
CardStand = 0x0E,
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
/*! Position of the object */
|
||||
Common::FFXIVARR_POSITION3 m_pos;
|
||||
/*! Rotation of the object */
|
||||
float m_rot;
|
||||
/*! Id of the actor */
|
||||
uint32_t m_id;
|
||||
/*! Type of the actor */
|
||||
ObjKind m_objKind;
|
||||
/*! Id of the zone the actor currently is in */
|
||||
uint32_t m_zoneId;
|
||||
/*! Ptr to the ZoneObj the actor belongs to */
|
||||
ZonePtr m_pCurrentZone;
|
||||
|
||||
/*! list of various actors in range */
|
||||
std::set< ActorPtr > m_inRangeActor;
|
||||
std::set< PlayerPtr > m_inRangePlayers;
|
||||
|
||||
/*! Parent cell in the zone */
|
||||
Core::Cell* m_pCell;
|
||||
|
||||
public:
|
||||
explicit Actor( ObjKind type );
|
||||
virtual ~Actor() {};
|
||||
|
||||
virtual void spawn( PlayerPtr pTarget ) {}
|
||||
virtual void despawn( PlayerPtr pTarget ) {}
|
||||
|
||||
uint32_t getId() const;
|
||||
void setId( uint32_t id );
|
||||
|
||||
ObjKind getObjKind() const;
|
||||
|
||||
Common::FFXIVARR_POSITION3& getPos();
|
||||
void setPos( const Common::FFXIVARR_POSITION3& pos );
|
||||
void setPos( float x, float y, float z );
|
||||
|
||||
float getRot() const;
|
||||
void setRot( float rot );
|
||||
|
||||
bool isChara() const;
|
||||
bool isPlayer() const;
|
||||
bool isEventNpc() const;
|
||||
bool isBattleNpc() const;
|
||||
bool isRetainer() const;
|
||||
bool isCompanion() const;
|
||||
bool isEventObj() const;
|
||||
bool isHousingEventObj() const;
|
||||
bool isAetheryte() const;
|
||||
|
||||
///// IN RANGE LOGIC ///////////////////////////////
|
||||
virtual void onRemoveInRangeActor( Actor& pActor ) {}
|
||||
|
||||
// check if another actor is in the actors in range set
|
||||
bool isInRangeSet( ActorPtr pActor ) const;
|
||||
|
||||
ActorPtr getClosestActor();
|
||||
|
||||
void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false );
|
||||
|
||||
// add an actor to in range set
|
||||
void addInRangeActor( ActorPtr pActor );
|
||||
|
||||
// remove an actor from the in range set
|
||||
void removeInRangeActor( Actor& actor );
|
||||
|
||||
// return true if there is at least one actor in the in range set
|
||||
bool hasInRangeActor() const;
|
||||
|
||||
void removeFromInRange();
|
||||
|
||||
// clear the whole in range set, this does no cleanup
|
||||
virtual void clearInRangeSet();
|
||||
|
||||
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
CharaPtr getAsChara();
|
||||
PlayerPtr getAsPlayer();
|
||||
EventObjectPtr getAsEventObj();
|
||||
|
||||
ZonePtr getCurrentZone() const;
|
||||
void setCurrentZone( ZonePtr currZone );
|
||||
|
||||
InstanceContentPtr getCurrentInstance() const;
|
||||
|
||||
// get the current cell of a region the actor is in
|
||||
Cell* getCellPtr();
|
||||
// set the current cell
|
||||
void setCell( Cell* pCell );
|
||||
|
||||
};
|
||||
|
||||
enum DisplayFlags : uint16_t
|
||||
{
|
||||
ActiveStance = 0x001,
|
||||
Invisible = 0x020,
|
||||
HideHead = 0x040,
|
||||
HideWeapon = 0x080,
|
||||
Faded = 0x100,
|
||||
Visor = 0x800,
|
||||
};
|
||||
|
||||
enum struct ActorStatus : uint8_t
|
||||
{
|
||||
Idle = 0x01,
|
||||
Dead = 0x02,
|
||||
Sitting = 0x03,
|
||||
Mounted = 0x04,
|
||||
Crafting = 0x05,
|
||||
Gathering = 0x06,
|
||||
Melding = 0x07,
|
||||
SMachine = 0x08
|
||||
};
|
||||
|
||||
struct ActorStats
|
||||
{
|
||||
uint32_t max_mp = 0;
|
||||
uint32_t max_hp = 0;
|
||||
|
||||
uint32_t str = 0;
|
||||
uint32_t dex = 0;
|
||||
uint32_t vit = 0;
|
||||
uint32_t inte = 0;
|
||||
uint32_t mnd = 0;
|
||||
uint32_t pie = 0;
|
||||
|
||||
uint32_t tenacity = 0;
|
||||
uint32_t attack = 0;
|
||||
uint32_t defense = 0;
|
||||
uint32_t accuracy = 0;
|
||||
uint32_t spellSpeed = 0;
|
||||
uint32_t magicDefense = 0;
|
||||
uint32_t critHitRate = 0;
|
||||
uint32_t resistSlash = 0;
|
||||
uint32_t resistPierce = 0;
|
||||
uint32_t resistBlunt = 0;
|
||||
uint32_t attackPotMagic = 0;
|
||||
uint32_t healingPotMagic = 0;
|
||||
uint32_t determination = 0;
|
||||
uint32_t skillSpeed = 0;
|
||||
|
||||
uint32_t resistSlow = 0;
|
||||
uint32_t resistSilence = 0;
|
||||
uint32_t resistBlind = 0;
|
||||
uint32_t resistPoison = 0;
|
||||
uint32_t resistStun = 0;
|
||||
uint32_t resistSleep = 0;
|
||||
uint32_t resistBind = 0;
|
||||
uint32_t resistHeavy = 0;
|
||||
|
||||
uint32_t resistFire = 0;
|
||||
uint32_t resistIce = 0;
|
||||
uint32_t resistWind = 0;
|
||||
uint32_t resistEarth = 0;
|
||||
uint32_t resistLightning = 0;
|
||||
uint32_t resistWater = 0;
|
||||
|
||||
} m_baseStats;
|
||||
|
||||
protected:
|
||||
char m_name[34];
|
||||
/*! Id of the zone the actor currently is in */
|
||||
uint32_t m_zoneId;
|
||||
/*! Ptr to the ZoneObj the actor belongs to */
|
||||
ZonePtr m_pCurrentZone;
|
||||
/*! Last tick time for the actor ( in ms ) */
|
||||
uint64_t m_lastTickTime;
|
||||
/*! Last time the actor performed an autoAttack ( in ms ) */
|
||||
uint64_t m_lastAttack;
|
||||
/*! Last time the actor was updated ( in ms ) */
|
||||
uint64_t m_lastUpdate;
|
||||
/*! Current stance of the actor */
|
||||
Stance m_currentStance;
|
||||
/*! Current staus of the actor */
|
||||
ActorStatus m_status;
|
||||
/*! Max HP of the actor ( based on job / class ) */
|
||||
uint32_t m_maxHp;
|
||||
/*! Max MP of the actor ( based on job / class ) */
|
||||
uint32_t m_maxMp;
|
||||
/*! Current HP of the actor */
|
||||
uint32_t m_hp;
|
||||
/*! Current MP of the actor */
|
||||
uint32_t m_mp;
|
||||
/*! Current TP of the actor */
|
||||
uint16_t m_tp;
|
||||
/*! Current GP of the actor */
|
||||
uint16_t m_gp;
|
||||
/*! Additional look info of the actor */
|
||||
uint8_t m_customize[26];
|
||||
/*! Current class of the actor */
|
||||
Common::ClassJob m_class;
|
||||
/*! Id of the currently selected target actor */
|
||||
uint64_t m_targetId;
|
||||
/*! Ptr to a queued action */
|
||||
Action::ActionPtr m_pCurrentAction;
|
||||
/*! Invincibility type */
|
||||
Common::InvincibilityType m_invincibilityType;
|
||||
|
||||
/*! Status effects */
|
||||
const uint8_t MAX_STATUS_EFFECTS = 30;
|
||||
std::queue< uint8_t > m_statusEffectFreeSlotQueue;
|
||||
std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList;
|
||||
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||
|
||||
std::set< ActorPtr > m_inRangeActors;
|
||||
std::set< PlayerPtr > m_inRangePlayers;
|
||||
|
||||
public:
|
||||
Actor( ObjKind type );
|
||||
|
||||
virtual ~Actor() override;
|
||||
|
||||
virtual void calculateStats() {};
|
||||
|
||||
/// Status effect functions
|
||||
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect );
|
||||
void removeStatusEffect( uint8_t effectSlotId );
|
||||
void removeSingleStatusEffectById( uint32_t id );
|
||||
void updateStatusEffects();
|
||||
|
||||
bool hasStatusEffect( uint32_t id );
|
||||
|
||||
int8_t getStatusEffectFreeSlot();
|
||||
void statusEffectFreeSlot( uint8_t slotId );
|
||||
|
||||
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getStatusEffectMap() const;
|
||||
|
||||
void sendStatusEffectUpdate();
|
||||
// add a status effect by id
|
||||
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
||||
|
||||
// add a status effect by id if it doesn't exist
|
||||
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param = 0 );
|
||||
|
||||
// remove a status effect by id
|
||||
void removeSingleStatusEffectFromId( uint32_t id );
|
||||
/// End Status Effect Functions
|
||||
|
||||
void setPosition( const Common::FFXIVARR_POSITION3& pos );
|
||||
void setPosition( float x, float y, float z );
|
||||
|
||||
void setRotation( float rot );
|
||||
|
||||
float getRotation() const;
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
std::set< ActorPtr > getInRangeActors( bool includeSelf = false );
|
||||
|
||||
bool face( const Common::FFXIVARR_POSITION3& p );
|
||||
|
||||
Stance getStance() const;
|
||||
|
||||
void setStance( Stance stance );
|
||||
|
||||
ActorStats getStats() const;
|
||||
|
||||
uint32_t getHp() const;
|
||||
uint32_t getMp() const;
|
||||
uint16_t getTp() const;
|
||||
uint16_t getGp() const;
|
||||
|
||||
Common::InvincibilityType getInvincibilityType() const;
|
||||
|
||||
Common::ClassJob getClass() const;
|
||||
|
||||
uint8_t getClassAsInt() const;
|
||||
|
||||
void setClass( Common::ClassJob classJob );
|
||||
|
||||
void setTargetId( uint64_t targetId );
|
||||
|
||||
uint64_t getTargetId() const;
|
||||
|
||||
bool isAlive() const;
|
||||
|
||||
virtual uint32_t getMaxHp() const;
|
||||
virtual uint32_t getMaxMp() const;
|
||||
|
||||
void resetHp();
|
||||
void resetMp();
|
||||
|
||||
void setHp( uint32_t hp );
|
||||
void setMp( uint32_t mp );
|
||||
void setGp( uint32_t gp );
|
||||
|
||||
void setInvincibilityType( Common::InvincibilityType type );
|
||||
|
||||
void die();
|
||||
|
||||
ActorStatus getStatus() const;
|
||||
|
||||
void setStatus( ActorStatus status );
|
||||
|
||||
void handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, uint64_t param2, Entity::Actor& target );
|
||||
|
||||
virtual void autoAttack( ActorPtr pTarget );
|
||||
|
||||
virtual void onRemoveInRangeActor( Actor& pActor ) {}
|
||||
|
||||
virtual void onDeath() {};
|
||||
virtual void onDamageTaken( Actor& pSource ) {};
|
||||
virtual void onActionHostile( Actor& source ) {};
|
||||
virtual void onActionFriendly( Actor& pSource ) {};
|
||||
virtual void onTick() {};
|
||||
|
||||
virtual void changeTarget( uint64_t targetId );
|
||||
virtual uint8_t getLevel() const;
|
||||
virtual void sendStatusUpdate( bool toSelf = true );
|
||||
virtual void takeDamage( uint32_t damage );
|
||||
virtual void heal( uint32_t amount );
|
||||
virtual bool checkAction();
|
||||
virtual void update( int64_t currTime ) {};
|
||||
|
||||
Action::ActionPtr getCurrentAction() const;
|
||||
|
||||
void setCurrentAction( Action::ActionPtr pAction );
|
||||
|
||||
///// IN RANGE LOGIC /////
|
||||
|
||||
// check if another actor is in the actors in range set
|
||||
bool isInRangeSet( ActorPtr pActor ) const;
|
||||
|
||||
ActorPtr getClosestActor();
|
||||
|
||||
void sendToInRangeSet( Network::Packets::GamePacketPtr pPacket, bool bToSelf = false );
|
||||
|
||||
// add an actor to in range set
|
||||
void addInRangeActor( ActorPtr pActor );
|
||||
|
||||
// remove an actor from the in range set
|
||||
void removeInRangeActor( Actor& pActor );
|
||||
|
||||
// return true if there is at least one actor in the in range set
|
||||
bool hasInRangeActor() const;
|
||||
|
||||
void checkInRangeActors();
|
||||
|
||||
void removeFromInRange();
|
||||
|
||||
// clear the whole in range set, this does no cleanup
|
||||
virtual void clearInRangeSet();
|
||||
|
||||
ZonePtr getCurrentZone() const;
|
||||
|
||||
void setCurrentZone( ZonePtr currZone );
|
||||
|
||||
// get the current cell of a region the actor is in
|
||||
Cell* getCell() const;
|
||||
|
||||
// set the current cell
|
||||
void setCell( Cell* pCell );
|
||||
|
||||
Core::Cell* m_pCell;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,569 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
|
||||
#include <common/Logging/Logger.h>
|
||||
#include <common/Exd/ExdDataGenerated.h>
|
||||
#include <common/Util/Util.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
|
||||
#include "Network/PacketWrappers/MoveActorPacket.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||
|
||||
#include "Player.h"
|
||||
#include "BattleNpc.h"
|
||||
#include "Framework.h"
|
||||
|
||||
using namespace Core::Common;
|
||||
using namespace Core::Network::Packets;
|
||||
using namespace Core::Network::Packets::Server;
|
||||
|
||||
extern Core::Framework g_framework;
|
||||
|
||||
uint32_t Core::Entity::BattleNpc::m_nextID = 1149241694;
|
||||
|
||||
Core::Entity::BattleNpc::BattleNpc() :
|
||||
Actor( ObjKind::BattleNpc )
|
||||
{
|
||||
m_id = 0;
|
||||
m_status = ActorStatus::Idle;
|
||||
}
|
||||
|
||||
Core::Entity::BattleNpc::~BattleNpc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Core::Entity::BattleNpc::BattleNpc( uint16_t modelId, uint16_t nameid, const Common::FFXIVARR_POSITION3& spawnPos,
|
||||
uint16_t bnpcBaseId, uint32_t type, uint8_t level, uint8_t behaviour,
|
||||
uint32_t mobType ) :
|
||||
Actor( ObjKind::BattleNpc )
|
||||
{
|
||||
BattleNpc::m_nextID++;
|
||||
m_id = BattleNpc::m_nextID;
|
||||
//strcpy( m_name, pBNpc->m_name.c_str() );
|
||||
|
||||
m_pos = spawnPos;
|
||||
m_posOrigin = spawnPos;
|
||||
|
||||
m_mode = MODE_IDLE;
|
||||
m_targetId = static_cast< uint64_t >( INVALID_GAME_OBJECT_ID );
|
||||
|
||||
m_maxHp = 150;
|
||||
m_maxMp = 100;
|
||||
|
||||
m_baseStats.max_hp = m_maxHp;
|
||||
m_baseStats.max_mp = m_maxMp;
|
||||
|
||||
m_hp = m_maxHp;
|
||||
m_mp = m_maxMp;
|
||||
|
||||
m_currentStance = Stance::Passive;
|
||||
|
||||
m_class = ClassJob::Gladiator;
|
||||
m_level = level > uint8_t{0} ? level : uint8_t{70};
|
||||
|
||||
m_modelId = modelId;
|
||||
m_nameId = nameid;
|
||||
|
||||
m_behavior = behaviour;
|
||||
|
||||
m_bnpcBaseId = bnpcBaseId;
|
||||
|
||||
m_status = ActorStatus::Idle;
|
||||
|
||||
m_pOwner = nullptr;
|
||||
|
||||
m_mobType = mobType;
|
||||
|
||||
m_invincibilityType = InvincibilityType::InvincibilityNone;
|
||||
|
||||
//m_type = static_cast< Common::ObjKind >( type );
|
||||
|
||||
}
|
||||
|
||||
// spawn this player for pTarget
|
||||
void Core::Entity::BattleNpc::spawn( PlayerPtr pTarget )
|
||||
{
|
||||
//GamePacketNew< FFXIVIpcActorSpawn > spawnPacket( getId(), pTarget->getId() );
|
||||
|
||||
//spawnPacket.data().unknown_0 = 0;
|
||||
//spawnPacket.data().ownerId = m_pOwner == nullptr ? INVALID_GAME_OBJECT_ID : m_pOwner->getId();
|
||||
//spawnPacket.data().targetId = INVALID_GAME_OBJECT_ID & 0xFFFFFFFF;
|
||||
//spawnPacket.data().hPCurr = m_hp;
|
||||
//spawnPacket.data().hPMax = m_baseStats.max_hp;
|
||||
//spawnPacket.data().level = m_level;
|
||||
////spawnPacket.data().tPCurr = 1000;
|
||||
//spawnPacket.data().model = m_modelId;
|
||||
//spawnPacket.data().bnpcBaseId = m_bnpcBaseId;
|
||||
//spawnPacket.data().nameId = m_nameId;
|
||||
//spawnPacket.data().spawnIndex = pTarget->getSpawnIdForActorId( getId() );
|
||||
//g_framework.getLogger().info(std::to_string(spawnPacket.data().spawnIndex) + " " + std::to_string(getId()));
|
||||
//spawnPacket.data().status = static_cast< uint8_t >( m_status );
|
||||
//spawnPacket.data().mobAgressive = m_behavior;
|
||||
//spawnPacket.data().type = static_cast< uint8_t >( m_type );
|
||||
//spawnPacket.data().mobTypeIcon = m_mobType;
|
||||
//spawnPacket.data().unknown_33 = 5;
|
||||
//spawnPacket.data().typeFlags = 4;
|
||||
//spawnPacket.data().pos.x = m_pos.x;
|
||||
//spawnPacket.data().pos.y = m_pos.y;
|
||||
//spawnPacket.data().pos.z = m_pos.z;
|
||||
//spawnPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
||||
////spawnPacket.data().unknown_B0[11] = 1;
|
||||
////spawnPacket.data().unknown_B0[12] = 4;
|
||||
////spawnPacket.data().unknown_B0[14] = 20;
|
||||
|
||||
//pTarget->queuePacket( spawnPacket );
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcNpcSpawn > spawnPacket( getId(), pTarget->getId() );
|
||||
|
||||
|
||||
spawnPacket.data().pos.x = m_pos.x;
|
||||
spawnPacket.data().pos.y = m_pos.y;
|
||||
spawnPacket.data().pos.z = m_pos.z;
|
||||
|
||||
spawnPacket.data().targetId = INVALID_GAME_OBJECT_ID & 0xFFFFFFFF;
|
||||
spawnPacket.data().hPCurr = m_hp;
|
||||
spawnPacket.data().hPMax = m_baseStats.max_hp;
|
||||
spawnPacket.data().level = m_level;
|
||||
|
||||
spawnPacket.data().subtype = 5;
|
||||
spawnPacket.data().enemyType = 4;
|
||||
|
||||
spawnPacket.data().modelChara = m_modelId;
|
||||
spawnPacket.data().bNPCBase = m_bnpcBaseId;
|
||||
spawnPacket.data().bNPCName = m_nameId;
|
||||
spawnPacket.data().spawnIndex = pTarget->getSpawnIdForActorId( getId() );
|
||||
|
||||
spawnPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
||||
|
||||
spawnPacket.data().type = static_cast< uint8_t >( m_objKind );
|
||||
|
||||
spawnPacket.data().state = static_cast< uint8_t >( m_status );
|
||||
|
||||
pTarget->queuePacket( spawnPacket );
|
||||
}
|
||||
|
||||
// despawn
|
||||
void Core::Entity::BattleNpc::despawn( PlayerPtr pPlayer )
|
||||
{
|
||||
pPlayer->freePlayerSpawnId( getId() );
|
||||
|
||||
ActorControlPacket143 controlPacket( m_id, DespawnZoneScreenMsg, 0x04, getId(), 0x01 );
|
||||
pPlayer->queuePacket( controlPacket );
|
||||
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::BattleNpc::getLevel() const
|
||||
{
|
||||
return m_level;
|
||||
}
|
||||
|
||||
Core::Entity::StateMode Core::Entity::BattleNpc::getMode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::setMode( StateMode mode )
|
||||
{
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::BattleNpc::getbehavior() const
|
||||
{
|
||||
return m_behavior;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::hateListAdd( Actor& actor, int32_t hateAmount )
|
||||
{
|
||||
auto hateEntry = new HateListEntry();
|
||||
hateEntry->m_hateAmount = hateAmount;
|
||||
hateEntry->m_pActor = actor.getAsActor();
|
||||
|
||||
m_hateList.insert( hateEntry );
|
||||
}
|
||||
|
||||
Core::Entity::ActorPtr Core::Entity::BattleNpc::hateListGetHighest()
|
||||
{
|
||||
|
||||
auto it = m_hateList.begin();
|
||||
uint32_t maxHate = 0;
|
||||
HateListEntry* entry = nullptr;
|
||||
for( ; it != m_hateList.end(); ++it )
|
||||
{
|
||||
if( ( *it )->m_hateAmount > maxHate )
|
||||
{
|
||||
maxHate = ( *it )->m_hateAmount;
|
||||
entry = *it;
|
||||
}
|
||||
}
|
||||
|
||||
if( entry && maxHate != 0 )
|
||||
return entry->m_pActor;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::setOwner( PlayerPtr pPlayer )
|
||||
{
|
||||
m_pOwner = pPlayer;
|
||||
|
||||
if( pPlayer != nullptr )
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcActorOwner > setOwnerPacket( getId(), pPlayer->getId() );
|
||||
setOwnerPacket.data().type = 0x01;
|
||||
setOwnerPacket.data().actorId = pPlayer->getId();
|
||||
sendToInRangeSet( setOwnerPacket );
|
||||
}
|
||||
else
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcActorOwner > setOwnerPacket(getId(), INVALID_GAME_OBJECT_ID );
|
||||
setOwnerPacket.data().type = 0x01;
|
||||
setOwnerPacket.data().actorId = INVALID_GAME_OBJECT_ID;
|
||||
sendToInRangeSet( setOwnerPacket );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::sendPositionUpdate()
|
||||
{
|
||||
MoveActorPacket movePacket( *this, 0x3A, 0x00, 0, 0x5A );
|
||||
sendToInRangeSet( movePacket );
|
||||
}
|
||||
|
||||
bool Core::Entity::BattleNpc::moveTo( Common::FFXIVARR_POSITION3& pos )
|
||||
{
|
||||
|
||||
if( Math::Util::distance( getPos().x, getPos().y, getPos().z,
|
||||
pos.x, pos.y, pos.z ) <= 4 )
|
||||
// reached destination
|
||||
return true;
|
||||
|
||||
float rot = Math::Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z );
|
||||
float newRot = PI - rot + ( PI / 2 );
|
||||
|
||||
face( pos );
|
||||
float angle = Math::Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ) + PI;
|
||||
|
||||
float x = static_cast< float >( cosf( angle ) * 1.1f );
|
||||
float y = ( getPos().y + pos.y ) * 0.5f; // fake value while there is no collision
|
||||
float z = static_cast< float >( sinf( angle ) * 1.1f );
|
||||
|
||||
Common::FFXIVARR_POSITION3 newPos{};
|
||||
|
||||
newPos.x = getPos().x + x;
|
||||
newPos.y = y;
|
||||
newPos.z = getPos().z + z;
|
||||
|
||||
setPosition( newPos );
|
||||
|
||||
Common::FFXIVARR_POSITION3 tmpPos{};
|
||||
tmpPos.x = getPos().x + x;
|
||||
tmpPos.y = y;
|
||||
tmpPos.z = getPos().z + z;
|
||||
|
||||
setPosition( tmpPos );
|
||||
setRotation(newRot);
|
||||
|
||||
sendPositionUpdate();
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::aggro( Actor& actor )
|
||||
{
|
||||
|
||||
m_lastAttack = Util::getTimeMs();
|
||||
hateListUpdate( actor, 1 );
|
||||
|
||||
changeTarget( actor.getId() );
|
||||
setStance( Stance::Active );
|
||||
m_mode = MODE_COMBAT;
|
||||
|
||||
if( actor.isPlayer() )
|
||||
{
|
||||
PlayerPtr tmpPlayer = actor.getAsPlayer();
|
||||
tmpPlayer->queuePacket( ActorControlPacket142( getId(), 0, 1, 1 ) );
|
||||
tmpPlayer->onMobAggro( getAsBattleNpc() );
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::deaggro( Actor& actor )
|
||||
{
|
||||
if( !hateListHasActor( actor ) )
|
||||
hateListRemove( actor );
|
||||
|
||||
if( actor.isPlayer() )
|
||||
{
|
||||
PlayerPtr tmpPlayer = actor.getAsPlayer();
|
||||
tmpPlayer->onMobDeaggro( getAsBattleNpc() );
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::hateListClear()
|
||||
{
|
||||
auto it = m_hateList.begin();
|
||||
for( ; it != m_hateList.end(); ++it )
|
||||
{
|
||||
if( isInRangeSet( ( *it )->m_pActor ) )
|
||||
deaggro( *( *it )->m_pActor );
|
||||
HateListEntry* tmpListEntry = ( *it );
|
||||
delete tmpListEntry;
|
||||
}
|
||||
m_hateList.clear();
|
||||
}
|
||||
|
||||
|
||||
void Core::Entity::BattleNpc::hateListRemove( Actor& actor )
|
||||
{
|
||||
auto it = m_hateList.begin();
|
||||
for( ; it != m_hateList.end(); ++it )
|
||||
{
|
||||
if( ( *it )->m_pActor->getId() == actor.getId() )
|
||||
{
|
||||
HateListEntry* pEntry = *it;
|
||||
m_hateList.erase( it );
|
||||
delete pEntry;
|
||||
if( actor.isPlayer() )
|
||||
{
|
||||
PlayerPtr tmpPlayer = actor.getAsPlayer();
|
||||
tmpPlayer->onMobDeaggro( getAsBattleNpc() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::Entity::BattleNpc::hateListHasActor( Actor& actor )
|
||||
{
|
||||
auto it = m_hateList.begin();
|
||||
for( ; it != m_hateList.end(); ++it )
|
||||
{
|
||||
if( ( *it )->m_pActor->getId() == actor.getId() )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::resetPos()
|
||||
{
|
||||
m_pos = m_posOrigin;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::BattleNpc::getNameId() const
|
||||
{
|
||||
return m_nameId;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::hateListUpdate( Actor& actor, int32_t hateAmount )
|
||||
{
|
||||
|
||||
auto it = m_hateList.begin();
|
||||
for( ; it != m_hateList.end(); ++it )
|
||||
{
|
||||
if( ( *it )->m_pActor->getId() == actor.getId() )
|
||||
{
|
||||
( *it )->m_hateAmount += hateAmount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto hateEntry = new HateListEntry();
|
||||
hateEntry->m_hateAmount = hateAmount;
|
||||
hateEntry->m_pActor = actor.getAsActor();
|
||||
m_hateList.insert( hateEntry );
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::onDeath()
|
||||
{
|
||||
//LuaManager->onMobDeath( this );
|
||||
|
||||
setTimeOfDeath( static_cast< uint32_t >( time( nullptr ) ) );
|
||||
setTargetId( INVALID_GAME_OBJECT_ID );
|
||||
m_currentStance = Stance::Passive;
|
||||
m_mode = MODE_IDLE;
|
||||
m_hp = 0;
|
||||
setOwner( nullptr );
|
||||
|
||||
// todo: fully ghetto retarded exp reward pls fix
|
||||
{
|
||||
uint32_t minHate = -1;
|
||||
uint32_t maxHate = 0;
|
||||
uint32_t totalHate = 0;
|
||||
for( auto& pHateEntry : m_hateList )
|
||||
{
|
||||
if( pHateEntry->m_pActor->isPlayer() )
|
||||
{
|
||||
if( pHateEntry->m_hateAmount < minHate )
|
||||
minHate = pHateEntry->m_hateAmount;
|
||||
else if( pHateEntry->m_hateAmount > maxHate )
|
||||
maxHate = pHateEntry->m_hateAmount;
|
||||
}
|
||||
totalHate += pHateEntry->m_hateAmount;
|
||||
}
|
||||
|
||||
//uint32_t plsBeHatedThisMuchAtLeast = totalHate / ( maxHate + 2 ) / clamp( m_hateList.size(), 1.0f, 1.5f );
|
||||
|
||||
for( auto& pHateEntry : m_hateList )
|
||||
{
|
||||
// todo: this is pure retarded
|
||||
// todo: check for companion
|
||||
if( pHateEntry->m_pActor->isPlayer() ) // && pHateEntry->m_hateAmount >= plsBeHatedThisMuchAtLeast )
|
||||
{
|
||||
uint8_t level = pHateEntry->m_pActor->getLevel();
|
||||
auto levelDiff = static_cast< int32_t >( this->m_level ) - level;
|
||||
auto cappedLevelDiff = Math::Util::clamp( levelDiff, 1, 6 );
|
||||
|
||||
auto expNeeded = g_framework.getExdDataGen().get< Core::Data::ParamGrow >( m_level + cappedLevelDiff - 1 )->expToNext;
|
||||
int32_t exp = 0;
|
||||
|
||||
// todo: arbitrary numbers pulled out of my ass
|
||||
if( m_level <= 14 )
|
||||
exp = ( expNeeded / ( 100 - levelDiff) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 9 ) ) + 1 ) );
|
||||
else if( m_level <= 24 )
|
||||
exp = ( expNeeded / ( 150 - levelDiff) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 8 ) ) + 1 ) );
|
||||
else if( m_level <= 34 )
|
||||
exp = ( expNeeded / ( 350 - levelDiff ) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 7 ) ) + 1 ) );
|
||||
else if( m_level <= 44 )
|
||||
exp = ( expNeeded / ( 550 - levelDiff ) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 6 ) ) + 1 ) );
|
||||
else if( m_level <= 50 )
|
||||
exp = ( expNeeded / ( 750 - levelDiff ) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 5 ) ) + 1 ) );
|
||||
else
|
||||
exp = ( expNeeded / ( 1200 - levelDiff ) ) + cappedLevelDiff + ( cappedLevelDiff * ( ( rand() % ( cappedLevelDiff * 4 ) ) + 1 ) );
|
||||
|
||||
|
||||
// todo: this is actually retarded, we need real rand()
|
||||
srand( static_cast< uint32_t > ( time( nullptr ) ) );
|
||||
|
||||
auto pPlayer = pHateEntry->m_pActor->getAsPlayer();
|
||||
pPlayer->gainExp( exp );
|
||||
pPlayer->onMobKill( m_nameId );
|
||||
}
|
||||
}
|
||||
}
|
||||
hateListClear();
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::onActionHostile( Actor& source )
|
||||
{
|
||||
|
||||
if( hateListGetHighest() == nullptr )
|
||||
aggro( source );
|
||||
|
||||
if( getClaimer() == nullptr )
|
||||
setOwner( source.getAsPlayer() );
|
||||
}
|
||||
|
||||
Core::Entity::ActorPtr Core::Entity::BattleNpc::getClaimer() const
|
||||
{
|
||||
return m_pOwner;
|
||||
}
|
||||
|
||||
|
||||
// HACK: this is highly experimental code, will have to be changed eventually
|
||||
// since there are different types of mobs... (stationary, moving...) likely to be
|
||||
// handled by scripts entirely.
|
||||
void Core::Entity::BattleNpc::update( int64_t currTime )
|
||||
{
|
||||
|
||||
if( !isAlive() )
|
||||
{
|
||||
m_status = ActorStatus::Idle;
|
||||
m_mode = MODE_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatusEffects();
|
||||
float distance = Math::Util::distance( m_pos.x, m_pos.y, m_pos.z,
|
||||
m_posOrigin.x, m_posOrigin.y, m_posOrigin.z );
|
||||
|
||||
if( ( distance > 70 ) && m_mode != MODE_RETREAT )
|
||||
{
|
||||
changeTarget( INVALID_GAME_OBJECT_ID );
|
||||
m_mode = MODE_RETREAT;
|
||||
hateListClear();
|
||||
setOwner( nullptr );
|
||||
}
|
||||
|
||||
switch( m_mode )
|
||||
{
|
||||
|
||||
case MODE_RETREAT:
|
||||
{
|
||||
if( moveTo( m_posOrigin ) )
|
||||
m_mode = MODE_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_IDLE:
|
||||
{
|
||||
ActorPtr pClosestActor = getClosestActor();
|
||||
|
||||
if( pClosestActor && pClosestActor->isAlive() )
|
||||
{
|
||||
distance = Math::Util::distance( getPos().x, getPos().y, getPos().z,
|
||||
pClosestActor->getPos().x,
|
||||
pClosestActor->getPos().y,
|
||||
pClosestActor->getPos().z );
|
||||
|
||||
//if( distance < 8 && getbehavior() == 2 )
|
||||
// aggro( pClosestActor );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_COMBAT:
|
||||
{
|
||||
ActorPtr pClosestActor = hateListGetHighest();
|
||||
|
||||
if( pClosestActor != nullptr && !pClosestActor->isAlive() )
|
||||
{
|
||||
hateListRemove( *pClosestActor );
|
||||
pClosestActor = hateListGetHighest();
|
||||
}
|
||||
|
||||
if( pClosestActor != nullptr )
|
||||
{
|
||||
distance = Math::Util::distance( getPos().x, getPos().y, getPos().z,
|
||||
pClosestActor->getPos().x,
|
||||
pClosestActor->getPos().y,
|
||||
pClosestActor->getPos().z );
|
||||
|
||||
if( distance > 4 )
|
||||
moveTo( pClosestActor->getPos() );
|
||||
else
|
||||
{
|
||||
if( face( pClosestActor->getPos() ) )
|
||||
sendPositionUpdate();
|
||||
// in combat range. ATTACK!
|
||||
autoAttack( pClosestActor );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
changeTarget( INVALID_GAME_OBJECT_ID );
|
||||
setStance( Stance::Passive );
|
||||
setOwner( nullptr );
|
||||
m_mode = MODE_RETREAT;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::BattleNpc::getTimeOfDeath() const
|
||||
{
|
||||
return m_timeOfDeath;
|
||||
}
|
||||
|
||||
void Core::Entity::BattleNpc::setTimeOfDeath( uint32_t tod )
|
||||
{
|
||||
m_timeOfDeath = tod;
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
#ifndef _BATTLENPC_H
|
||||
#define _BATTLENPC_H
|
||||
|
||||
#include "Actor.h"
|
||||
|
||||
namespace Core {
|
||||
namespace Entity {
|
||||
|
||||
enum StateMode
|
||||
{
|
||||
MODE_COMBAT,
|
||||
MODE_RETREAT,
|
||||
MODE_IDLE,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t m_hateAmount;
|
||||
ActorPtr m_pActor;
|
||||
} HateListEntry;
|
||||
|
||||
// class for Mobs inheriting from Actor
|
||||
class BattleNpc : public Actor
|
||||
{
|
||||
public:
|
||||
BattleNpc();
|
||||
virtual ~BattleNpc() override;
|
||||
|
||||
BattleNpc( uint16_t modelId, uint16_t nameid, const Common::FFXIVARR_POSITION3& spawnPos, uint16_t bnpcBaseId = 0,
|
||||
uint32_t type = 2, uint8_t level = 0, uint8_t behaviour = 1, uint32_t mobType = 0 );
|
||||
|
||||
//BattleNpc( uint32_t modelId,
|
||||
// uint32_t nameId,
|
||||
// uint32_t bnpcBaseId,
|
||||
// uint32_t level,
|
||||
// const Common::FFXIVARR_POSITION3& spawnPos,
|
||||
// uint32_t type = 2, uint32_t behaviour = 1, uint32_t mobType = 0 );
|
||||
|
||||
void initStatusEffectContainer();
|
||||
|
||||
// send spawn packets to pTarget
|
||||
void spawn( PlayerPtr pTarget ) override;
|
||||
|
||||
// send despawn packets to pTarget
|
||||
void despawn( PlayerPtr pTarget ) override;
|
||||
|
||||
uint8_t getLevel() const override;
|
||||
|
||||
StateMode getMode() const;
|
||||
|
||||
void setMode( StateMode mode );
|
||||
|
||||
uint8_t getbehavior() const;
|
||||
|
||||
void hateListAdd( Actor& actor, int32_t hateAmount );
|
||||
|
||||
void hateListUpdate( Actor& actor, int32_t hateAmount );
|
||||
void hateListRemove( Actor& actor );
|
||||
|
||||
bool hateListHasActor( Actor& actor );
|
||||
|
||||
void resetPos();
|
||||
|
||||
uint32_t getNameId() const;
|
||||
|
||||
void hateListClear();
|
||||
|
||||
ActorPtr hateListGetHighest();
|
||||
|
||||
void aggro( Actor& actor );
|
||||
|
||||
void deaggro( Actor& actor );
|
||||
|
||||
void setOwner( PlayerPtr pPlayer );
|
||||
|
||||
void onDeath() override;
|
||||
|
||||
void onActionHostile( Actor& source ) override;
|
||||
|
||||
ActorPtr getClaimer() const;
|
||||
|
||||
void sendPositionUpdate();
|
||||
|
||||
// return true if it reached the position
|
||||
bool moveTo( Common::FFXIVARR_POSITION3& pos );
|
||||
|
||||
void update( int64_t currTime ) override;
|
||||
|
||||
uint32_t getTimeOfDeath() const;
|
||||
|
||||
void setTimeOfDeath( uint32_t tod );
|
||||
|
||||
private:
|
||||
|
||||
static uint32_t m_nextID;
|
||||
StateMode m_mode;
|
||||
Common::FFXIVARR_POSITION3 m_posOrigin;
|
||||
uint8_t m_level;
|
||||
uint16_t m_modelId;
|
||||
uint16_t m_nameId;
|
||||
uint16_t m_bnpcBaseId;
|
||||
uint8_t m_behavior;
|
||||
uint32_t m_unk1;
|
||||
uint32_t m_unk2;
|
||||
std::set< HateListEntry* > m_hateList;
|
||||
ActorPtr m_pOwner;
|
||||
uint32_t m_timeOfDeath;
|
||||
uint32_t m_mobType;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||
#include "BattleNpcTemplate.h"
|
||||
|
||||
Core::Entity::BattleNpcTemplate::BattleNpcTemplate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Core::Entity::BattleNpcTemplate::BattleNpcTemplate( std::string templateName, uint32_t bnpcBaseId,
|
||||
uint32_t bnpcNameId, uint32_t modelId, std::string aiName ) :
|
||||
m_templateName( templateName ),
|
||||
m_bnpcBaseId( bnpcBaseId ),
|
||||
m_bnpcNameId( bnpcNameId ),
|
||||
m_modelId( modelId ),
|
||||
m_aiName( aiName )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Core::Entity::BattleNpcTemplate::~BattleNpcTemplate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::BattleNpcTemplate::getBnpcBaseId() const
|
||||
{
|
||||
return m_bnpcBaseId;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::BattleNpcTemplate::getBnpcNameId() const
|
||||
{
|
||||
return m_bnpcNameId;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::BattleNpcTemplate::getModelId() const
|
||||
{
|
||||
return m_modelId;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#ifndef _BATTLENPCTEMPLATE_H
|
||||
#define _BATTLENPCTEMPLATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace Core {
|
||||
namespace Entity {
|
||||
|
||||
/**
|
||||
* \brief BattleNpcTemplate - Class which defines a template specific BNpcs can be created from
|
||||
*/
|
||||
class BattleNpcTemplate
|
||||
{
|
||||
public:
|
||||
BattleNpcTemplate();
|
||||
BattleNpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName );
|
||||
|
||||
~BattleNpcTemplate();
|
||||
|
||||
uint32_t getBnpcBaseId() const;
|
||||
uint32_t getBnpcNameId() const;
|
||||
uint32_t getModelId() const;
|
||||
|
||||
private:
|
||||
std::string m_templateName;
|
||||
std::string m_aiName;
|
||||
uint32_t m_bnpcBaseId = 0;
|
||||
uint32_t m_bnpcNameId = 0;
|
||||
uint32_t m_modelId = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
763
src/servers/sapphire_zone/Actor/Chara.cpp
Normal file
763
src/servers/sapphire_zone/Actor/Chara.cpp
Normal file
|
@ -0,0 +1,763 @@
|
|||
#include <common/Util/Util.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
#include <common/Network/PacketContainer.h>
|
||||
#include <common/Exd/ExdDataGenerated.h>
|
||||
#include <common/Network/GamePacket.h>
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "Action/Action.h"
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
#include "Network/GameConnection.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
||||
#include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
|
||||
|
||||
#include "StatusEffect/StatusEffect.h"
|
||||
#include "Action/ActionCollision.h"
|
||||
#include "ServerZone.h"
|
||||
#include "Session.h"
|
||||
#include "Math/CalcBattle.h"
|
||||
#include "Chara.h"
|
||||
#include "Player.h"
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
#include "Framework.h"
|
||||
|
||||
extern Core::Framework g_framework;
|
||||
|
||||
using namespace Core::Common;
|
||||
using namespace Core::Network::Packets;
|
||||
using namespace Core::Network::Packets::Server;
|
||||
|
||||
Core::Entity::Chara::Chara( ObjKind type ) :
|
||||
Actor( type )
|
||||
{
|
||||
// initialize the free slot queue
|
||||
for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ )
|
||||
{
|
||||
m_statusEffectFreeSlotQueue.push( i );
|
||||
}
|
||||
}
|
||||
|
||||
Core::Entity::Chara::~Chara()
|
||||
{
|
||||
}
|
||||
|
||||
/*! \return the actors name */
|
||||
std::string Core::Entity::Chara::getName() const
|
||||
{
|
||||
return std::string( m_name );
|
||||
}
|
||||
|
||||
|
||||
/*! \return current stance of the actors */
|
||||
Core::Entity::Chara::Stance Core::Entity::Chara::getStance() const
|
||||
{
|
||||
return m_currentStance;
|
||||
}
|
||||
|
||||
/*! \return actor stats */
|
||||
Core::Entity::Chara::ActorStats Core::Entity::Chara::getStats() const
|
||||
{
|
||||
return m_baseStats;
|
||||
}
|
||||
|
||||
/*! \return current HP */
|
||||
uint32_t Core::Entity::Chara::getHp() const
|
||||
{
|
||||
return m_hp;
|
||||
}
|
||||
|
||||
/*! \return current MP */
|
||||
uint32_t Core::Entity::Chara::getMp() const
|
||||
{
|
||||
return m_mp;
|
||||
}
|
||||
|
||||
/*! \return current TP */
|
||||
uint16_t Core::Entity::Chara::getTp() const
|
||||
{
|
||||
return m_tp;
|
||||
}
|
||||
|
||||
/*! \return current GP */
|
||||
uint16_t Core::Entity::Chara::getGp() const
|
||||
{
|
||||
return m_gp;
|
||||
}
|
||||
|
||||
/*! \return current invincibility type */
|
||||
InvincibilityType Core::Entity::Chara::getInvincibilityType() const
|
||||
{
|
||||
return m_invincibilityType;
|
||||
}
|
||||
|
||||
/*! \return current class or job */
|
||||
Core::Common::ClassJob Core::Entity::Chara::getClass() const
|
||||
{
|
||||
return m_class;
|
||||
}
|
||||
|
||||
/*! \return current class or job as int32_t ( this feels pointless ) */
|
||||
uint8_t Core::Entity::Chara::getClassAsInt() const
|
||||
{
|
||||
return static_cast< uint8_t >( m_class );
|
||||
}
|
||||
|
||||
/*! \param ClassJob to set */
|
||||
void Core::Entity::Chara::setClass( Common::ClassJob classJob )
|
||||
{
|
||||
m_class = classJob;
|
||||
}
|
||||
|
||||
/*! \param Id of the target to set */
|
||||
void Core::Entity::Chara::setTargetId( uint64_t targetId )
|
||||
{
|
||||
m_targetId = targetId;
|
||||
}
|
||||
|
||||
/*! \return Id of the current target */
|
||||
uint64_t Core::Entity::Chara::getTargetId() const
|
||||
{
|
||||
return m_targetId;
|
||||
}
|
||||
|
||||
/*! \return True if the actor is alive */
|
||||
bool Core::Entity::Chara::isAlive() const
|
||||
{
|
||||
return ( m_hp > 0 );
|
||||
}
|
||||
|
||||
/*! \return max hp for the actor */
|
||||
uint32_t Core::Entity::Chara::getMaxHp() const
|
||||
{
|
||||
return m_baseStats.max_hp;
|
||||
}
|
||||
|
||||
/*! \return max mp for the actor */
|
||||
uint32_t Core::Entity::Chara::getMaxMp() const
|
||||
{
|
||||
return m_baseStats.max_mp;
|
||||
}
|
||||
|
||||
/*! \return reset hp to current max hp */
|
||||
void Core::Entity::Chara::resetHp()
|
||||
{
|
||||
m_hp = getMaxHp();
|
||||
sendStatusUpdate( true );
|
||||
}
|
||||
|
||||
/*! \return reset mp to current max mp */
|
||||
void Core::Entity::Chara::resetMp()
|
||||
{
|
||||
m_mp = getMaxMp();
|
||||
sendStatusUpdate( true );
|
||||
}
|
||||
|
||||
/*! \param hp amount to set ( caps to maxHp ) */
|
||||
void Core::Entity::Chara::setHp( uint32_t hp )
|
||||
{
|
||||
m_hp = hp < getMaxHp() ? hp : getMaxHp();
|
||||
sendStatusUpdate( true );
|
||||
}
|
||||
|
||||
/*! \param mp amount to set ( caps to maxMp ) */
|
||||
void Core::Entity::Chara::setMp( uint32_t mp )
|
||||
{
|
||||
m_mp = mp < getMaxMp() ? mp : getMaxMp();
|
||||
sendStatusUpdate( true );
|
||||
}
|
||||
|
||||
/*! \param gp amount to set*/
|
||||
void Core::Entity::Chara::setGp( uint32_t gp )
|
||||
{
|
||||
m_gp = gp;
|
||||
sendStatusUpdate( true );
|
||||
}
|
||||
|
||||
/*! \param type invincibility type to set */
|
||||
void Core::Entity::Chara::setInvincibilityType( Common::InvincibilityType type )
|
||||
{
|
||||
m_invincibilityType = type;
|
||||
}
|
||||
|
||||
/*! \return current status of the actor */
|
||||
Core::Entity::Chara::ActorStatus Core::Entity::Chara::getStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
/*! \param status to set */
|
||||
void Core::Entity::Chara::setStatus( ActorStatus status )
|
||||
{
|
||||
m_status = status;
|
||||
}
|
||||
|
||||
/*!
|
||||
Performs necessary steps to mark an actor dead.
|
||||
Sets hp/mp/tp, sets status, plays animation and fires onDeath event
|
||||
*/
|
||||
void Core::Entity::Chara::die()
|
||||
{
|
||||
m_status = ActorStatus::Dead;
|
||||
m_hp = 0;
|
||||
m_mp = 0;
|
||||
m_tp = 0;
|
||||
|
||||
// fire onDeath event
|
||||
onDeath();
|
||||
|
||||
// if the actor is a player, the update needs to be send to himself too
|
||||
bool selfNeedsUpdate = isPlayer();
|
||||
|
||||
sendToInRangeSet( ActorControlPacket142( m_id, SetStatus, static_cast< uint8_t >( ActorStatus::Dead ) ), selfNeedsUpdate );
|
||||
|
||||
// TODO: not all actor show the death animation when they die, some quest npcs might just despawn
|
||||
// although that might be handled by setting the HP to 1 and doing some script magic
|
||||
sendToInRangeSet( ActorControlPacket142( m_id, DeathAnimation, 0, 0, 0, 0x20 ), selfNeedsUpdate );
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Calculates and sets the rotation to look towards a specified
|
||||
position
|
||||
|
||||
\param Position to look towards
|
||||
*/
|
||||
bool Core::Entity::Chara::face( const Common::FFXIVARR_POSITION3& p )
|
||||
{
|
||||
float oldRot = getRot();
|
||||
float rot = Math::Util::calcAngFrom( getPos().x, getPos().z, p.x, p.z );
|
||||
float newRot = PI - rot + ( PI / 2 );
|
||||
|
||||
m_pCell = nullptr;
|
||||
|
||||
setRot( newRot );
|
||||
|
||||
return oldRot != newRot ? true : false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set and propagate the actor stance to in range players
|
||||
( not the actor himself )
|
||||
|
||||
\param stance to set
|
||||
*/
|
||||
void Core::Entity::Chara::setStance( Stance stance )
|
||||
{
|
||||
m_currentStance = stance;
|
||||
|
||||
sendToInRangeSet( ActorControlPacket142( m_id, ToggleAggro, stance, 1 ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Check if an action is queued for execution, if so update it
|
||||
and if fully performed, clean up again.
|
||||
|
||||
\return true if a queued action has been updated
|
||||
*/
|
||||
bool Core::Entity::Chara::checkAction()
|
||||
{
|
||||
|
||||
if( m_pCurrentAction == nullptr )
|
||||
return false;
|
||||
|
||||
if( m_pCurrentAction->update() )
|
||||
m_pCurrentAction.reset();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Change the current target and propagate to in range players
|
||||
|
||||
\param target actor id
|
||||
*/
|
||||
void Core::Entity::Chara::changeTarget( uint64_t targetId )
|
||||
{
|
||||
setTargetId( targetId );
|
||||
sendToInRangeSet( ActorControlPacket144( m_id, SetTarget, 0, 0, 0, 0, targetId ) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Dummy function \return 0
|
||||
*/
|
||||
uint8_t Core::Entity::Chara::getLevel() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Let an actor take damage and perform necessary steps
|
||||
according to resulting hp, propagates new hp value to players
|
||||
in range
|
||||
TODO: eventually this needs to distinguish between physical and
|
||||
magical dmg and take status effects into account
|
||||
|
||||
\param amount of damage to be taken
|
||||
*/
|
||||
void Core::Entity::Chara::takeDamage( uint32_t damage )
|
||||
{
|
||||
if( damage >= m_hp )
|
||||
{
|
||||
switch( m_invincibilityType ) {
|
||||
case InvincibilityNone:
|
||||
setHp( 0 );
|
||||
die();
|
||||
break;
|
||||
case InvincibilityRefill:
|
||||
resetHp();
|
||||
break;
|
||||
case InvincibilityStayAlive:
|
||||
setHp( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_hp -= damage;
|
||||
|
||||
sendStatusUpdate( false );
|
||||
}
|
||||
|
||||
/*!
|
||||
Let an actor get healed and perform necessary steps
|
||||
according to resulting hp, propagates new hp value to players
|
||||
in range
|
||||
|
||||
\param amount of hp to be healed
|
||||
*/
|
||||
void Core::Entity::Chara::heal( uint32_t amount )
|
||||
{
|
||||
if( ( m_hp + amount ) > getMaxHp() )
|
||||
{
|
||||
m_hp = getMaxHp();
|
||||
}
|
||||
else
|
||||
m_hp += amount;
|
||||
|
||||
sendStatusUpdate( false );
|
||||
}
|
||||
|
||||
/*!
|
||||
Send an HpMpTp update to players in range ( and potentially to self )
|
||||
TODO: poor naming, should be changed. Status is not HP. Also should be virtual
|
||||
so players can have their own version and we can abolish the param.
|
||||
|
||||
\param true if the update should also be sent to the actor ( player ) himself
|
||||
*/
|
||||
void Core::Entity::Chara::sendStatusUpdate( bool toSelf )
|
||||
{
|
||||
UpdateHpMpTpPacket updateHpPacket( *this );
|
||||
sendToInRangeSet( updateHpPacket );
|
||||
}
|
||||
|
||||
/*! \return ActionPtr of the currently registered action, or nullptr */
|
||||
Core::Action::ActionPtr Core::Entity::Chara::getCurrentAction() const
|
||||
{
|
||||
return m_pCurrentAction;
|
||||
}
|
||||
|
||||
/*! \param ActionPtr of the action to be registered */
|
||||
void Core::Entity::Chara::setCurrentAction( Core::Action::ActionPtr pAction )
|
||||
{
|
||||
m_pCurrentAction = pAction;
|
||||
}
|
||||
|
||||
/*!
|
||||
Autoattack prototype implementation
|
||||
TODO: move the check if the autoAttack can be performed to the callee
|
||||
also rename autoAttack to autoAttack as that is more elaborate
|
||||
On top of that, this only solves attacks from melee classes.
|
||||
Will have to be extended for ranged attacks.
|
||||
|
||||
\param ActorPtr the autoAttack is performed on
|
||||
*/
|
||||
void Core::Entity::Chara::autoAttack( CharaPtr pTarget )
|
||||
{
|
||||
|
||||
uint64_t tick = Util::getTimeMs();
|
||||
|
||||
if( ( tick - m_lastAttack ) > 2500 )
|
||||
{
|
||||
pTarget->onActionHostile( *this );
|
||||
m_lastAttack = tick;
|
||||
srand( static_cast< uint32_t >( tick ) );
|
||||
|
||||
uint16_t damage = static_cast< uint16_t >( 10 + rand() % 12 );
|
||||
uint32_t variation = static_cast< uint32_t >( 0 + rand() % 4 );
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() );
|
||||
effectPacket.data().targetId = pTarget->getId();
|
||||
effectPacket.data().actionAnimationId = 0x366;
|
||||
effectPacket.data().unknown_2 = variation;
|
||||
// effectPacket.data().unknown_3 = 1;
|
||||
effectPacket.data().actionTextId = 0x366;
|
||||
effectPacket.data().numEffects = 1;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRot() );
|
||||
effectPacket.data().effectTarget = pTarget->getId();
|
||||
effectPacket.data().effects[0].value = damage;
|
||||
effectPacket.data().effects[0].effectType = ActionEffectType::Damage;
|
||||
effectPacket.data().effects[0].hitSeverity = static_cast< ActionHitSeverityType >( variation );
|
||||
effectPacket.data().effects[0].unknown_3 = 7;
|
||||
|
||||
sendToInRangeSet( effectPacket );
|
||||
|
||||
if( isPlayer() )
|
||||
getAsPlayer()->queuePacket( effectPacket );
|
||||
|
||||
pTarget->takeDamage( damage );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
ChaiScript Skill Handler.
|
||||
|
||||
\param GamePacketPtr to send
|
||||
\param bool should be send to self?
|
||||
*/
|
||||
void Core::Entity::Chara::handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1,
|
||||
uint64_t param2, Entity::Chara& target )
|
||||
{
|
||||
|
||||
if( isPlayer() )
|
||||
{
|
||||
getAsPlayer()->sendDebug( std::to_string( target.getId() ) );
|
||||
getAsPlayer()->sendDebug( "Handle script skill type: " + std::to_string( type ) );
|
||||
}
|
||||
|
||||
auto actionInfoPtr = g_framework.getExdDataGen().get< Core::Data::Action >( actionId );
|
||||
|
||||
// Todo: Effect packet generator. 90% of this is basically setting params and it's basically unreadable.
|
||||
// Prepare packet. This is seemingly common for all packets in the action handler.
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() );
|
||||
effectPacket.data().targetId = target.getId();
|
||||
effectPacket.data().actionAnimationId = actionId;
|
||||
effectPacket.data().unknown_62 = 1; // Affects displaying action name next to number in floating text
|
||||
effectPacket.data().unknown_2 = 1; // This seems to have an effect on the "double-cast finish" animation
|
||||
effectPacket.data().actionTextId = actionId;
|
||||
effectPacket.data().numEffects = 1;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRot() );
|
||||
effectPacket.data().effectTarget = target.getId();
|
||||
|
||||
// Todo: for each actor, calculate how much damage the calculated value should deal to them - 2-step damage calc. we only have 1-step
|
||||
switch( type )
|
||||
{
|
||||
|
||||
case ActionEffectType::Damage:
|
||||
{
|
||||
effectPacket.data().effects[0].value = static_cast< uint16_t >( param1 );
|
||||
effectPacket.data().effects[0].effectType = ActionEffectType::Damage;
|
||||
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalDamage;
|
||||
effectPacket.data().effects[0].unknown_3 = 7;
|
||||
|
||||
if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 )
|
||||
{
|
||||
// If action on this specific target is valid...
|
||||
if ( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Enemies ) )
|
||||
break;
|
||||
|
||||
sendToInRangeSet( effectPacket, true );
|
||||
|
||||
if ( target.isAlive() )
|
||||
target.onActionHostile( *this );
|
||||
|
||||
target.takeDamage( static_cast< uint32_t >( param1 ) );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors( true ),
|
||||
actionInfoPtr, TargetFilter::Enemies );
|
||||
|
||||
for( const auto& pHitActor : actorsCollided )
|
||||
{
|
||||
effectPacket.data().targetId = pHitActor->getId();
|
||||
effectPacket.data().effectTarget = pHitActor->getId();
|
||||
|
||||
// todo: send to range of what? ourselves? when mob script hits this is going to be lacking
|
||||
sendToInRangeSet( effectPacket, true );
|
||||
|
||||
|
||||
if( pHitActor->getAsChara()->isAlive() )
|
||||
pHitActor->getAsChara()->onActionHostile( *this );
|
||||
|
||||
pHitActor->getAsChara()->takeDamage( static_cast< uint32_t >( param1 ) );
|
||||
|
||||
// Debug
|
||||
if ( isPlayer() )
|
||||
{
|
||||
if ( pHitActor->isPlayer() )
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) +
|
||||
" (" + pHitActor->getAsChara()->getName() + ")" );
|
||||
else
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionEffectType::Heal:
|
||||
{
|
||||
uint32_t calculatedHeal = Math::CalcBattle::calculateHealValue( getAsPlayer(), static_cast< uint32_t >( param1 ) );
|
||||
|
||||
effectPacket.data().effects[0].value = calculatedHeal;
|
||||
effectPacket.data().effects[0].effectType = ActionEffectType::Heal;
|
||||
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal;
|
||||
|
||||
if( actionInfoPtr->castType == 1 && actionInfoPtr->effectRange != 0 || actionInfoPtr->castType != 1 )
|
||||
{
|
||||
if( isPlayer() && !ActionCollision::isActorApplicable( target, TargetFilter::Allies ) )
|
||||
break;
|
||||
|
||||
sendToInRangeSet( effectPacket, true );
|
||||
target.heal( calculatedHeal );
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: get proper packets: the following was just kind of thrown together from what we know.
|
||||
// atm buggy (packets look "delayed" from client)
|
||||
|
||||
auto actorsCollided = ActionCollision::getActorsHitFromAction( target.getPos(), getInRangeActors(true),
|
||||
actionInfoPtr, TargetFilter::Allies );
|
||||
|
||||
for( auto pHitActor : actorsCollided )
|
||||
{
|
||||
effectPacket.data().targetId = target.getId();
|
||||
effectPacket.data().effectTarget = pHitActor->getId();
|
||||
|
||||
sendToInRangeSet( effectPacket, true );
|
||||
pHitActor->getAsChara()->heal( calculatedHeal );
|
||||
|
||||
// Debug
|
||||
if( isPlayer() )
|
||||
{
|
||||
if( pHitActor->isPlayer() )
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) +
|
||||
" (" + pHitActor->getAsChara()->getName() + ")" );
|
||||
else
|
||||
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \param StatusEffectPtr to be applied to the actor */
|
||||
void Core::Entity::Chara::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
|
||||
{
|
||||
int8_t nextSlot = getStatusEffectFreeSlot();
|
||||
// if there is no slot left, do not add the effect
|
||||
if( nextSlot == -1 )
|
||||
return;
|
||||
|
||||
pEffect->applyStatus();
|
||||
m_statusEffectMap[nextSlot] = pEffect;
|
||||
|
||||
ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( getId() );
|
||||
statusEffectAdd.data().actor_id = pEffect->getTargetActorId();
|
||||
statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId();
|
||||
statusEffectAdd.data().current_hp = getHp();
|
||||
statusEffectAdd.data().current_mp = getMp();
|
||||
statusEffectAdd.data().current_tp = getTp();
|
||||
statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000;
|
||||
statusEffectAdd.data().effect_id = pEffect->getId();
|
||||
statusEffectAdd.data().effect_index = nextSlot;
|
||||
statusEffectAdd.data().max_hp = getMaxHp();
|
||||
statusEffectAdd.data().max_mp = getMaxMp();
|
||||
statusEffectAdd.data().max_something = 1;
|
||||
//statusEffectAdd.data().unknown2 = 28;
|
||||
statusEffectAdd.data().param = pEffect->getParam();
|
||||
|
||||
sendToInRangeSet( statusEffectAdd, isPlayer() );
|
||||
}
|
||||
|
||||
/*! \param StatusEffectPtr to be applied to the actor */
|
||||
void Core::Entity::Chara::addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param )
|
||||
{
|
||||
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 );
|
||||
effect->setParam( param );
|
||||
addStatusEffect( effect );
|
||||
}
|
||||
|
||||
/*! \param StatusEffectPtr to be applied to the actor */
|
||||
void Core::Entity::Chara::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param )
|
||||
{
|
||||
if( hasStatusEffect( id ) )
|
||||
return;
|
||||
|
||||
auto effect = StatusEffect::make_StatusEffect( id, source.getAsChara(), getAsChara(), duration, 3000 );
|
||||
effect->setParam( param );
|
||||
addStatusEffect( effect );
|
||||
|
||||
}
|
||||
|
||||
int8_t Core::Entity::Chara::getStatusEffectFreeSlot()
|
||||
{
|
||||
int8_t freeEffectSlot = -1;
|
||||
|
||||
if( m_statusEffectFreeSlotQueue.empty() )
|
||||
return freeEffectSlot;
|
||||
|
||||
freeEffectSlot = m_statusEffectFreeSlotQueue.front();
|
||||
m_statusEffectFreeSlotQueue.pop();
|
||||
|
||||
return freeEffectSlot;
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::statusEffectFreeSlot( uint8_t slotId )
|
||||
{
|
||||
m_statusEffectFreeSlotQueue.push( slotId );
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::removeSingleStatusEffectById( uint32_t id )
|
||||
{
|
||||
for( auto effectIt : m_statusEffectMap )
|
||||
{
|
||||
if( effectIt.second->getId() == id )
|
||||
{
|
||||
removeStatusEffect( effectIt.first );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::removeStatusEffect( uint8_t effectSlotId )
|
||||
{
|
||||
auto pEffectIt = m_statusEffectMap.find( effectSlotId );
|
||||
if( pEffectIt == m_statusEffectMap.end() )
|
||||
return;
|
||||
|
||||
statusEffectFreeSlot( effectSlotId );
|
||||
|
||||
auto pEffect = pEffectIt->second;
|
||||
pEffect->removeStatus();
|
||||
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), StatusEffectLose, pEffect->getId() ), isPlayer() );
|
||||
|
||||
m_statusEffectMap.erase( effectSlotId );
|
||||
|
||||
sendStatusEffectUpdate();
|
||||
}
|
||||
|
||||
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::Entity::Chara::getStatusEffectMap() const
|
||||
{
|
||||
return m_statusEffectMap;
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::sendStatusEffectUpdate()
|
||||
{
|
||||
uint64_t currentTimeMs = Util::getTimeMs();
|
||||
|
||||
ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( getId() );
|
||||
|
||||
statusEffectList.data().classId = static_cast< uint8_t >( getClass() );
|
||||
statusEffectList.data().level = getLevel();
|
||||
statusEffectList.data().level1 = getLevel();
|
||||
statusEffectList.data().current_hp = getHp();
|
||||
statusEffectList.data().current_mp = getMp();
|
||||
statusEffectList.data().currentTp = getTp();
|
||||
statusEffectList.data().max_hp = getMaxHp();
|
||||
statusEffectList.data().max_mp = getMaxMp();
|
||||
uint8_t slot = 0;
|
||||
for( auto effectIt : m_statusEffectMap )
|
||||
{
|
||||
float timeLeft = static_cast< float >( effectIt.second->getDuration() -
|
||||
( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000;
|
||||
statusEffectList.data().effect[slot].duration = timeLeft;
|
||||
statusEffectList.data().effect[slot].effect_id = effectIt.second->getId();
|
||||
statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId();
|
||||
slot++;
|
||||
}
|
||||
|
||||
sendToInRangeSet( statusEffectList, isPlayer() );
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::Chara::updateStatusEffects()
|
||||
{
|
||||
uint64_t currentTimeMs = Util::getTimeMs();
|
||||
|
||||
uint32_t thisTickDmg = 0;
|
||||
uint32_t thisTickHeal = 0;
|
||||
|
||||
for( auto effectIt : m_statusEffectMap )
|
||||
{
|
||||
uint8_t effectIndex = effectIt.first;
|
||||
auto effect = effectIt.second;
|
||||
|
||||
uint64_t lastTick = effect->getLastTickMs();
|
||||
uint64_t startTime = effect->getStartTimeMs();
|
||||
uint32_t duration = effect->getDuration();
|
||||
uint32_t tickRate = effect->getTickRate();
|
||||
|
||||
if( ( currentTimeMs - startTime ) > duration )
|
||||
{
|
||||
// remove status effect
|
||||
removeStatusEffect( effectIndex );
|
||||
// break because removing invalidates iterators
|
||||
break;
|
||||
}
|
||||
|
||||
if( ( currentTimeMs - lastTick ) > tickRate )
|
||||
{
|
||||
effect->setLastTick( currentTimeMs );
|
||||
effect->onTick();
|
||||
|
||||
auto thisEffect = effect->getTickEffect();
|
||||
|
||||
switch( thisEffect.first )
|
||||
{
|
||||
|
||||
case 1:
|
||||
{
|
||||
thisTickDmg += thisEffect.second;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
thisTickHeal += thisEffect.second;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( thisTickDmg != 0 )
|
||||
{
|
||||
takeDamage( thisTickDmg );
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
|
||||
}
|
||||
|
||||
if( thisTickHeal != 0 )
|
||||
{
|
||||
heal( thisTickDmg );
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::Entity::Chara::hasStatusEffect( uint32_t id )
|
||||
{
|
||||
if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Chara::ModelType Chara::getModelType() const
|
||||
{
|
||||
return m_modelType;
|
||||
}
|
256
src/servers/sapphire_zone/Actor/Chara.h
Normal file
256
src/servers/sapphire_zone/Actor/Chara.h
Normal file
|
@ -0,0 +1,256 @@
|
|||
#ifndef _ACTOR_H_
|
||||
#define _ACTOR_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "Forwards.h"
|
||||
#include "Actor.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
namespace Core {
|
||||
namespace Entity {
|
||||
|
||||
/*!
|
||||
\class Chara
|
||||
\brief Base class for all animate actors
|
||||
|
||||
*/
|
||||
class Chara : public Actor
|
||||
{
|
||||
public:
|
||||
enum Stance : uint8_t
|
||||
{
|
||||
Passive = 0,
|
||||
Active = 1,
|
||||
};
|
||||
|
||||
enum DisplayFlags : uint16_t
|
||||
{
|
||||
ActiveStance = 0x001,
|
||||
Invisible = 0x020,
|
||||
HideHead = 0x040,
|
||||
HideWeapon = 0x080,
|
||||
Faded = 0x100,
|
||||
Visor = 0x800,
|
||||
};
|
||||
|
||||
enum struct ActorStatus : uint8_t
|
||||
{
|
||||
Idle = 0x01,
|
||||
Dead = 0x02,
|
||||
Sitting = 0x03,
|
||||
Mounted = 0x04,
|
||||
Crafting = 0x05,
|
||||
Gathering = 0x06,
|
||||
Melding = 0x07,
|
||||
SMachine = 0x08
|
||||
};
|
||||
|
||||
/*! ModelType as found in eventsystemdefine.exd */
|
||||
enum ModelType : uint8_t
|
||||
{
|
||||
Human = 1,
|
||||
DemiHuman = 2,
|
||||
Monster = 3,
|
||||
SharedGroup = 4,
|
||||
Parts = 5
|
||||
};
|
||||
|
||||
struct ActorStats
|
||||
{
|
||||
uint32_t max_mp = 0;
|
||||
uint32_t max_hp = 0;
|
||||
|
||||
uint32_t str = 0;
|
||||
uint32_t dex = 0;
|
||||
uint32_t vit = 0;
|
||||
uint32_t inte = 0;
|
||||
uint32_t mnd = 0;
|
||||
uint32_t pie = 0;
|
||||
|
||||
uint32_t tenacity = 0;
|
||||
uint32_t attack = 0;
|
||||
uint32_t defense = 0;
|
||||
uint32_t accuracy = 0;
|
||||
uint32_t spellSpeed = 0;
|
||||
uint32_t magicDefense = 0;
|
||||
uint32_t critHitRate = 0;
|
||||
uint32_t resistSlash = 0;
|
||||
uint32_t resistPierce = 0;
|
||||
uint32_t resistBlunt = 0;
|
||||
uint32_t attackPotMagic = 0;
|
||||
uint32_t healingPotMagic = 0;
|
||||
uint32_t determination = 0;
|
||||
uint32_t skillSpeed = 0;
|
||||
|
||||
uint32_t resistSlow = 0;
|
||||
uint32_t resistSilence = 0;
|
||||
uint32_t resistBlind = 0;
|
||||
uint32_t resistPoison = 0;
|
||||
uint32_t resistStun = 0;
|
||||
uint32_t resistSleep = 0;
|
||||
uint32_t resistBind = 0;
|
||||
uint32_t resistHeavy = 0;
|
||||
|
||||
uint32_t resistFire = 0;
|
||||
uint32_t resistIce = 0;
|
||||
uint32_t resistWind = 0;
|
||||
uint32_t resistEarth = 0;
|
||||
uint32_t resistLightning = 0;
|
||||
uint32_t resistWater = 0;
|
||||
|
||||
} m_baseStats;
|
||||
|
||||
protected:
|
||||
char m_name[34];
|
||||
/*! Last tick time for the actor ( in ms ) */
|
||||
uint64_t m_lastTickTime;
|
||||
/*! Last time the actor performed an autoAttack ( in ms ) */
|
||||
uint64_t m_lastAttack;
|
||||
/*! Last time the actor was updated ( in ms ) */
|
||||
uint64_t m_lastUpdate;
|
||||
/*! Current stance of the actor */
|
||||
Stance m_currentStance;
|
||||
/*! Current staus of the actor */
|
||||
ActorStatus m_status;
|
||||
/*! Max HP of the actor ( based on job / class ) */
|
||||
uint32_t m_maxHp;
|
||||
/*! Max MP of the actor ( based on job / class ) */
|
||||
uint32_t m_maxMp;
|
||||
/*! Current HP of the actor */
|
||||
uint32_t m_hp;
|
||||
/*! Current MP of the actor */
|
||||
uint32_t m_mp;
|
||||
/*! Current TP of the actor */
|
||||
uint16_t m_tp;
|
||||
/*! Current GP of the actor */
|
||||
uint16_t m_gp;
|
||||
/*! Additional look info of the actor */
|
||||
uint8_t m_customize[26];
|
||||
/*! Current class of the actor */
|
||||
Common::ClassJob m_class;
|
||||
/*! Id of the currently selected target actor */
|
||||
uint64_t m_targetId;
|
||||
/*! Ptr to a queued action */
|
||||
Action::ActionPtr m_pCurrentAction;
|
||||
/*! Invincibility type */
|
||||
Common::InvincibilityType m_invincibilityType;
|
||||
/*! Type of model to use, humanoid for actors that use look data */
|
||||
ModelType m_modelType;
|
||||
|
||||
/*! Status effects */
|
||||
const uint8_t MAX_STATUS_EFFECTS = 30;
|
||||
std::queue< uint8_t > m_statusEffectFreeSlotQueue;
|
||||
std::vector< std::pair< uint8_t, uint32_t> > m_statusEffectList;
|
||||
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||
|
||||
public:
|
||||
Chara( ObjKind type );
|
||||
|
||||
virtual ~Chara() override;
|
||||
|
||||
virtual void calculateStats() {};
|
||||
|
||||
/// Status effect functions
|
||||
void addStatusEffect( StatusEffect::StatusEffectPtr pEffect );
|
||||
void removeStatusEffect( uint8_t effectSlotId );
|
||||
void removeSingleStatusEffectById( uint32_t id );
|
||||
void updateStatusEffects();
|
||||
|
||||
bool hasStatusEffect( uint32_t id );
|
||||
|
||||
int8_t getStatusEffectFreeSlot();
|
||||
void statusEffectFreeSlot( uint8_t slotId );
|
||||
|
||||
std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > getStatusEffectMap() const;
|
||||
|
||||
void sendStatusEffectUpdate();
|
||||
// add a status effect by id
|
||||
void addStatusEffectById( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
|
||||
|
||||
// add a status effect by id if it doesn't exist
|
||||
void addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Chara& source, uint16_t param = 0 );
|
||||
|
||||
// remove a status effect by id
|
||||
void removeSingleStatusEffectFromId( uint32_t id );
|
||||
/// End Status Effect Functions
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
bool face( const Common::FFXIVARR_POSITION3& p );
|
||||
|
||||
Stance getStance() const;
|
||||
|
||||
void setStance( Stance stance );
|
||||
|
||||
ActorStats getStats() const;
|
||||
|
||||
uint32_t getHp() const;
|
||||
uint32_t getMp() const;
|
||||
uint16_t getTp() const;
|
||||
uint16_t getGp() const;
|
||||
|
||||
Common::InvincibilityType getInvincibilityType() const;
|
||||
|
||||
Common::ClassJob getClass() const;
|
||||
|
||||
ModelType getModelType() const;
|
||||
|
||||
uint8_t getClassAsInt() const;
|
||||
|
||||
void setClass( Common::ClassJob classJob );
|
||||
|
||||
void setTargetId( uint64_t targetId );
|
||||
|
||||
uint64_t getTargetId() const;
|
||||
|
||||
bool isAlive() const;
|
||||
|
||||
virtual uint32_t getMaxHp() const;
|
||||
virtual uint32_t getMaxMp() const;
|
||||
|
||||
void resetHp();
|
||||
void resetMp();
|
||||
|
||||
void setHp( uint32_t hp );
|
||||
void setMp( uint32_t mp );
|
||||
void setGp( uint32_t gp );
|
||||
|
||||
void setInvincibilityType( Common::InvincibilityType type );
|
||||
|
||||
void die();
|
||||
|
||||
ActorStatus getStatus() const;
|
||||
|
||||
void setStatus( ActorStatus status );
|
||||
|
||||
void handleScriptSkill( uint32_t type, uint16_t actionId, uint64_t param1, uint64_t param2, Entity::Chara& target );
|
||||
|
||||
virtual void autoAttack( CharaPtr pTarget );
|
||||
|
||||
virtual void onDeath() {};
|
||||
virtual void onDamageTaken( Chara& pSource ) {};
|
||||
virtual void onActionHostile( Chara& source ) {};
|
||||
virtual void onActionFriendly( Chara& pSource ) {};
|
||||
virtual void onTick() {};
|
||||
|
||||
virtual void changeTarget( uint64_t targetId );
|
||||
virtual uint8_t getLevel() const;
|
||||
virtual void sendStatusUpdate( bool toSelf = true );
|
||||
virtual void takeDamage( uint32_t damage );
|
||||
virtual void heal( uint32_t amount );
|
||||
virtual bool checkAction();
|
||||
virtual void update( int64_t currTime ) {};
|
||||
|
||||
Action::ActionPtr getCurrentAction() const;
|
||||
|
||||
void setCurrentAction( Action::ActionPtr pAction );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
|
||||
#include <common/Logging/Logger.h>
|
||||
#include <common/Util/Util.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
|
||||
#include "Network/PacketWrappers/MoveActorPacket.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||
|
||||
#include "Player.h"
|
||||
#include "EventNpc.h"
|
||||
#include "Framework.h"
|
||||
|
||||
using namespace Core::Common;
|
||||
using namespace Core::Network::Packets;
|
||||
using namespace Core::Network::Packets::Server;
|
||||
|
||||
extern Core::Framework g_framework;
|
||||
|
||||
uint32_t Core::Entity::EventNpc::m_nextID = 1249241694;
|
||||
|
||||
Core::Entity::EventNpc::EventNpc() :
|
||||
Actor( ObjKind::EventNpc )
|
||||
{
|
||||
m_id = 0;
|
||||
m_status = ActorStatus::Idle;
|
||||
}
|
||||
|
||||
Core::Entity::EventNpc::~EventNpc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Core::Entity::EventNpc::EventNpc( uint32_t enpcId, const Common::FFXIVARR_POSITION3& spawnPos, float rotation ) :
|
||||
Actor( ObjKind::EventNpc )
|
||||
{
|
||||
EventNpc::m_nextID++;
|
||||
m_id = EventNpc::m_nextID;
|
||||
|
||||
m_pos = spawnPos;
|
||||
m_posOrigin = spawnPos;
|
||||
|
||||
m_targetId = static_cast< uint64_t >( INVALID_GAME_OBJECT_ID );
|
||||
|
||||
m_maxHp = 150;
|
||||
m_maxMp = 100;
|
||||
|
||||
m_baseStats.max_hp = m_maxHp;
|
||||
m_baseStats.max_mp = m_maxMp;
|
||||
|
||||
m_hp = m_maxHp;
|
||||
m_mp = m_maxMp;
|
||||
|
||||
m_currentStance = Stance::Passive;
|
||||
|
||||
m_eNpcId = enpcId;
|
||||
|
||||
m_status = ActorStatus::Idle;
|
||||
|
||||
m_invincibilityType = InvincibilityType::InvincibilityNone;
|
||||
m_rot = rotation;
|
||||
|
||||
}
|
||||
|
||||
// spawn this player for pTarget
|
||||
/*! TODO: Retail additionally sends Look+Models for EventNpcs even though it is not needed,
|
||||
add when the new exd reader is implemented(also counts for BNPCs) */
|
||||
void Core::Entity::EventNpc::spawn( PlayerPtr pTarget )
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcNpcSpawn > spawnPacket( getId(), pTarget->getId() );
|
||||
|
||||
|
||||
spawnPacket.data().pos.x = m_pos.x;
|
||||
spawnPacket.data().pos.y = m_pos.y;
|
||||
spawnPacket.data().pos.z = m_pos.z;
|
||||
|
||||
spawnPacket.data().targetId = pTarget->getId();
|
||||
spawnPacket.data().hPCurr = 1;
|
||||
spawnPacket.data().hPMax = 1;
|
||||
|
||||
spawnPacket.data().bNPCBase = m_eNpcId;
|
||||
spawnPacket.data().bNPCName = m_eNpcId;
|
||||
spawnPacket.data().spawnIndex = pTarget->getSpawnIdForActorId( getId() );
|
||||
|
||||
spawnPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
||||
|
||||
spawnPacket.data().type = static_cast< uint8_t >( m_objKind );
|
||||
|
||||
pTarget->queuePacket( spawnPacket );
|
||||
}
|
||||
|
||||
// despawn
|
||||
void Core::Entity::EventNpc::despawn( PlayerPtr pTarget )
|
||||
{
|
||||
pTarget->freePlayerSpawnId( getId() );
|
||||
|
||||
ActorControlPacket143 controlPacket( m_id, DespawnZoneScreenMsg, 0x04, getId(), 0x01 );
|
||||
pTarget->queuePacket( controlPacket );
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::EventNpc::getLevel() const
|
||||
{
|
||||
return m_level;
|
||||
}
|
||||
|
||||
void Core::Entity::EventNpc::resetPos()
|
||||
{
|
||||
m_pos = m_posOrigin;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::EventNpc::getEnpcId() const
|
||||
{
|
||||
return m_eNpcId;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#ifndef _EVENTNPC_H
|
||||
#define _EVENTNPC_H
|
||||
|
||||
#include "Actor.h"
|
||||
|
||||
namespace Core {
|
||||
namespace Entity {
|
||||
|
||||
// class for Mobs inheriting from Actor
|
||||
class EventNpc : public Actor
|
||||
{
|
||||
public:
|
||||
EventNpc();
|
||||
virtual ~EventNpc() override;
|
||||
|
||||
EventNpc( uint32_t enpcId, const Common::FFXIVARR_POSITION3& spawnPos, float rotation );
|
||||
|
||||
// send spawn packets to pTarget
|
||||
void spawn( PlayerPtr pTarget ) override;
|
||||
|
||||
// send despawn packets to pTarget
|
||||
void despawn( PlayerPtr pTarget ) override;
|
||||
|
||||
uint8_t getLevel() const override;
|
||||
|
||||
void resetPos();
|
||||
|
||||
uint32_t getEnpcId() const;
|
||||
|
||||
private:
|
||||
|
||||
static uint32_t m_nextID;
|
||||
Common::FFXIVARR_POSITION3 m_posOrigin;
|
||||
uint8_t m_level;
|
||||
uint32_t m_eNpcId;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
132
src/servers/sapphire_zone/Actor/EventObject.cpp
Normal file
132
src/servers/sapphire_zone/Actor/EventObject.cpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
#include "EventObject.h"
|
||||
|
||||
#include "Zone/InstanceContent.h"
|
||||
#include "Actor/Player.h"
|
||||
|
||||
#include <common/Logging/Logger.h>
|
||||
#include <common/Network/GamePacket.h>
|
||||
#include <common/Network/GamePacketNew.h>
|
||||
#include <common/Network/CommonNetwork.h>
|
||||
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
#include <common/Network/PacketContainer.h>
|
||||
#include <common/Util/UtilMath.h>
|
||||
|
||||
using namespace Core::Common;
|
||||
using namespace Core::Network::Packets;
|
||||
using namespace Core::Network::Packets::Server;
|
||||
|
||||
extern Core::Logger g_log;
|
||||
|
||||
|
||||
Core::Entity::EventObject::EventObject( uint32_t actorId, uint32_t objectId, uint32_t gimmickId,
|
||||
uint8_t initialState, Common::FFXIVARR_POSITION3 pos,
|
||||
float rotation, const std::string& givenName ) :
|
||||
Core::Entity::Actor( ObjKind::EventObj ),
|
||||
m_gimmickId( gimmickId ),
|
||||
m_state( initialState ),
|
||||
m_objectId( objectId ),
|
||||
m_name( givenName )
|
||||
{
|
||||
m_id = actorId;
|
||||
m_pos.x = pos.x;
|
||||
m_pos.y = pos.y;
|
||||
m_pos.z = pos.z;
|
||||
m_rot = rotation;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::EventObject::getGimmickId() const
|
||||
{
|
||||
return m_gimmickId;
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::EventObject::getObjectId() const
|
||||
{
|
||||
return m_objectId;
|
||||
}
|
||||
|
||||
float Core::Entity::EventObject::getScale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::setScale( float scale )
|
||||
{
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
Core::Entity::EventObject::OnTalkEventHandler Core::Entity::EventObject::getOnTalkHandler() const
|
||||
{
|
||||
return m_onTalkEventHandler;
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::setOnTalkHandler( Core::Entity::EventObject::OnTalkEventHandler handler )
|
||||
{
|
||||
m_onTalkEventHandler = handler;
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::setGimmickId( uint32_t gimmickId )
|
||||
{
|
||||
m_gimmickId = gimmickId;
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::EventObject::getState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::setState( uint8_t state )
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
for( const auto& player : m_inRangePlayers )
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcActorControl142 > eobjUpdatePacket( getId(), player->getId() );
|
||||
eobjUpdatePacket.data().category = Common::ActorControlType::DirectorEObjMod;
|
||||
eobjUpdatePacket.data().param1 = state;
|
||||
|
||||
player->queuePacket( eobjUpdatePacket );
|
||||
}
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::setParentInstance( Core::InstanceContentPtr instance )
|
||||
{
|
||||
m_parentInstance = instance;
|
||||
}
|
||||
|
||||
Core::InstanceContentPtr Core::Entity::EventObject::getParentInstance() const
|
||||
{
|
||||
return m_parentInstance;
|
||||
}
|
||||
|
||||
void Core::Entity::EventObject::spawn( Core::Entity::PlayerPtr pTarget )
|
||||
{
|
||||
auto spawnIndex = pTarget->getNextObjSpawnIndexForActorId( getId( ) );
|
||||
if( !pTarget->isObjSpawnIndexValid( spawnIndex ) )
|
||||
return;
|
||||
|
||||
g_log.debug( "Spawning EObj: id:" + std::to_string( getId() ) + " name:" + getName() );
|
||||
ZoneChannelPacket< FFXIVIpcObjectSpawn > eobjStatePacket( getId(), pTarget->getId() );
|
||||
eobjStatePacket.data().spawnIndex = spawnIndex;
|
||||
eobjStatePacket.data().objKind = getObjKind();
|
||||
eobjStatePacket.data().state = getState();
|
||||
eobjStatePacket.data().objId = getObjectId();
|
||||
eobjStatePacket.data().gimmickId = getGimmickId();
|
||||
eobjStatePacket.data().position = getPos();
|
||||
eobjStatePacket.data().scale = getScale();
|
||||
eobjStatePacket.data().actorId = getId();
|
||||
eobjStatePacket.data().rotation = Math::Util::floatToUInt16Rot( getRot() );
|
||||
pTarget->queuePacket( eobjStatePacket );
|
||||
}
|
||||
|
||||
|
||||
void Core::Entity::EventObject::despawn( Core::Entity::PlayerPtr pTarget )
|
||||
{
|
||||
g_log.debug( "despawn eobj: " + std::to_string( getId() ) );
|
||||
|
||||
pTarget->freeObjSpawnIndexForActorId( getId( ) );
|
||||
}
|
||||
|
||||
const std::string& Core::Entity::EventObject::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
52
src/servers/sapphire_zone/Actor/EventObject.h
Normal file
52
src/servers/sapphire_zone/Actor/EventObject.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef SAPPHIRE_INSTANCEOBJECT_H
|
||||
#define SAPPHIRE_INSTANCEOBJECT_H
|
||||
|
||||
#include "Actor.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Entity
|
||||
{
|
||||
class EventObject : public Actor
|
||||
{
|
||||
public:
|
||||
EventObject( uint32_t actorId, uint32_t objectId, uint32_t gimmickId, uint8_t initialState, Common::FFXIVARR_POSITION3 pos,
|
||||
float rotation, const std::string& givenName = "none" );
|
||||
|
||||
using OnTalkEventHandler = std::function< void( Entity::Player&, Entity::EventObjectPtr, InstanceContentPtr, uint64_t ) >;
|
||||
|
||||
uint32_t getGimmickId() const;
|
||||
void setGimmickId( uint32_t gimmickId );
|
||||
|
||||
uint8_t getState() const;
|
||||
void setState( uint8_t state );
|
||||
|
||||
float getScale() const;
|
||||
void setScale( float scale );
|
||||
|
||||
void setOnTalkHandler( OnTalkEventHandler handler );
|
||||
OnTalkEventHandler getOnTalkHandler() const;
|
||||
|
||||
uint32_t getObjectId() const;
|
||||
|
||||
const std::string& getName() const;
|
||||
|
||||
InstanceContentPtr getParentInstance() const;
|
||||
void setParentInstance( InstanceContentPtr instance );
|
||||
|
||||
void spawn( PlayerPtr pTarget ) override;
|
||||
void despawn( PlayerPtr pTarget ) override;
|
||||
|
||||
protected:
|
||||
uint32_t m_gimmickId;
|
||||
uint32_t m_objectId;
|
||||
uint8_t m_state;
|
||||
float m_scale;
|
||||
std::string m_name;
|
||||
InstanceContentPtr m_parentInstance;
|
||||
OnTalkEventHandler m_onTalkEventHandler;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SAPPHIRE_INSTANCEOBJECT_H
|
|
@ -1,94 +0,0 @@
|
|||
#include "GameObject.h"
|
||||
|
||||
#include "Player.h"
|
||||
#include "Actor.h"
|
||||
#include "BattleNpc.h"
|
||||
#include "EventNpc.h"
|
||||
|
||||
Core::Entity::GameObject::GameObject( ObjKind type ) :
|
||||
m_objKind( type )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::GameObject::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
Core::Entity::GameObject::ObjKind Core::Entity::GameObject::getObjKind() const
|
||||
{
|
||||
return m_objKind;
|
||||
}
|
||||
|
||||
Core::Common::FFXIVARR_POSITION3& Core::Entity::GameObject::getPos()
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void Core::Entity::GameObject::setPos( float x, float y, float z )
|
||||
{
|
||||
m_pos.x = x;
|
||||
m_pos.y = y;
|
||||
m_pos.z = z;
|
||||
}
|
||||
|
||||
void Core::Entity::GameObject::setPos( const Core::Common::FFXIVARR_POSITION3& pos )
|
||||
{
|
||||
m_pos = pos;
|
||||
}
|
||||
|
||||
float Core::Entity::GameObject::getRot() const
|
||||
{
|
||||
return m_rot;
|
||||
}
|
||||
|
||||
void Core::Entity::GameObject::setRot( float rot )
|
||||
{
|
||||
m_rot = rot;
|
||||
}
|
||||
|
||||
bool Core::Entity::GameObject::isPlayer() const
|
||||
{
|
||||
return m_objKind == ObjKind::Player;
|
||||
}
|
||||
|
||||
bool Core::Entity::GameObject::isBattleNpc() const
|
||||
{
|
||||
return m_objKind == ObjKind::BattleNpc;
|
||||
}
|
||||
|
||||
bool Core::Entity::GameObject::isEventNpc() const
|
||||
{
|
||||
return m_objKind == ObjKind::EventNpc;
|
||||
}
|
||||
|
||||
/*! \return pointer to this instance as ActorPtr */
|
||||
Core::Entity::ActorPtr Core::Entity::GameObject::getAsActor()
|
||||
{
|
||||
return boost::dynamic_pointer_cast< Entity::Actor, Entity::GameObject >( shared_from_this() );
|
||||
}
|
||||
|
||||
/*! \return pointer to this instance as PlayerPtr */
|
||||
Core::Entity::PlayerPtr Core::Entity::GameObject::getAsPlayer()
|
||||
{
|
||||
if( !isPlayer() )
|
||||
return nullptr;
|
||||
return boost::dynamic_pointer_cast< Entity::Player, Entity::GameObject >( shared_from_this() );
|
||||
}
|
||||
|
||||
/*! \return pointer to this instance as BattleNpcPtr */
|
||||
Core::Entity::BattleNpcPtr Core::Entity::GameObject::getAsBattleNpc()
|
||||
{
|
||||
if( !isBattleNpc() )
|
||||
return nullptr;
|
||||
return boost::dynamic_pointer_cast< Entity::BattleNpc, Entity::GameObject >( shared_from_this() );
|
||||
}
|
||||
|
||||
/*! \return pointer to this instance as EventNpcPtr */
|
||||
Core::Entity::EventNpcPtr Core::Entity::GameObject::getAsEventNpc()
|
||||
{
|
||||
if( !isEventNpc() )
|
||||
return nullptr;
|
||||
return boost::dynamic_pointer_cast< Entity::EventNpc, Entity::GameObject >( shared_from_this() );
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
#ifndef _GAME_OBJECT_H_
|
||||
#define _GAME_OBJECT_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
#include "Forwards.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
namespace Core {
|
||||
namespace Entity {
|
||||
|
||||
/*!
|
||||
\class GameObject
|
||||
\brief Base class for all actor/objects
|
||||
|
||||
*/
|
||||
class GameObject : public boost::enable_shared_from_this< GameObject >
|
||||
{
|
||||
public:
|
||||
enum ObjKind : uint8_t
|
||||
{
|
||||
None = 0x00,
|
||||
Player = 0x01,
|
||||
BattleNpc = 0x02,
|
||||
EventNpc = 0x03,
|
||||
Treasure = 0x04,
|
||||
Aetheryte = 0x05,
|
||||
GatheringPoint = 0x06,
|
||||
EventObj = 0x07,
|
||||
Mount = 0x08,
|
||||
Companion = 0x09,
|
||||
Retainer = 0x0A,
|
||||
Area = 0x0B,
|
||||
Housing = 0x0C,
|
||||
Cutscene = 0x0D,
|
||||
CardStand = 0x0E,
|
||||
};
|
||||
|
||||
protected:
|
||||
/*! Position of the object */
|
||||
Common::FFXIVARR_POSITION3 m_pos;
|
||||
/*! Rotation of the object */
|
||||
float m_rot;
|
||||
/*! Id of the actor */
|
||||
uint32_t m_id;
|
||||
/*! Type of the actor */
|
||||
ObjKind m_objKind;
|
||||
|
||||
public:
|
||||
explicit GameObject( ObjKind type );
|
||||
virtual ~GameObject() {};
|
||||
|
||||
virtual void spawn( PlayerPtr pTarget ) {}
|
||||
virtual void despawn( PlayerPtr pTarget ) {}
|
||||
|
||||
uint32_t getId() const;
|
||||
|
||||
ObjKind getObjKind() const;
|
||||
|
||||
Common::FFXIVARR_POSITION3& getPos();
|
||||
void setPos( const Common::FFXIVARR_POSITION3& pos );
|
||||
void setPos( float x, float y, float z );
|
||||
|
||||
float getRot() const;
|
||||
void setRot( float rot );
|
||||
|
||||
bool isPlayer() const;
|
||||
bool isBattleNpc() const;
|
||||
bool isEventNpc() const;
|
||||
|
||||
ActorPtr getAsActor();
|
||||
PlayerPtr getAsPlayer();
|
||||
BattleNpcPtr getAsBattleNpc();
|
||||
EventNpcPtr getAsEventNpc();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||
#include "InstanceObject.h"
|
||||
#include "Zone/InstanceContent.h"
|
||||
|
||||
Core::Entity::InstanceObject::InstanceObject( uint32_t objectId, uint32_t mapLinkId ) :
|
||||
Core::Entity::GameObject( ObjKind::EventObj ),
|
||||
m_mapLinkId( mapLinkId ),
|
||||
m_state( 0 )
|
||||
{
|
||||
m_id = objectId;
|
||||
}
|
||||
|
||||
Core::Entity::InstanceObject::InstanceObject( uint32_t objectId, uint32_t mapLinkId, Common::FFXIVARR_POSITION3 pos ) :
|
||||
InstanceObject( objectId, mapLinkId )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t Core::Entity::InstanceObject::getHierachyId() const
|
||||
{
|
||||
return m_mapLinkId;
|
||||
}
|
||||
|
||||
void Core::Entity::InstanceObject::setHierachyId( uint32_t hierachyId )
|
||||
{
|
||||
m_mapLinkId = hierachyId;
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::InstanceObject::getState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void Core::Entity::InstanceObject::setState( uint8_t state )
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
//m_parentInstance->updateInstanceObj( InstanceObjectPtr( this ) );
|
||||
}
|
||||
|
||||
void Core::Entity::InstanceObject::setParentInstance( Core::InstanceContentPtr instance )
|
||||
{
|
||||
m_parentInstance = instance;
|
||||
}
|
||||
|
||||
Core::InstanceContentPtr Core::Entity::InstanceObject::getParentInstance() const
|
||||
{
|
||||
return m_parentInstance;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef SAPPHIRE_INSTANCEOBJECT_H
|
||||
#define SAPPHIRE_INSTANCEOBJECT_H
|
||||
|
||||
#include "GameObject.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Entity
|
||||
{
|
||||
class InstanceObject : public GameObject
|
||||
{
|
||||
public:
|
||||
InstanceObject( uint32_t objectId, uint32_t mapLinkId );
|
||||
InstanceObject( uint32_t objectId, uint32_t mapLinkId, Common::FFXIVARR_POSITION3 pos );
|
||||
|
||||
uint32_t getHierachyId() const;
|
||||
void setHierachyId( uint32_t hierachyId );
|
||||
|
||||
uint8_t getState() const;
|
||||
void setState( uint8_t state );
|
||||
|
||||
InstanceContentPtr getParentInstance() const;
|
||||
void setParentInstance( InstanceContentPtr instance );
|
||||
|
||||
protected:
|
||||
uint32_t m_mapLinkId;
|
||||
uint8_t m_state;
|
||||
InstanceContentPtr m_parentInstance;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SAPPHIRE_INSTANCEOBJECT_H
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include "Session.h"
|
||||
#include "Player.h"
|
||||
#include "BattleNpc.h"
|
||||
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
#include "Zone/Zone.h"
|
||||
|
@ -20,6 +19,7 @@
|
|||
#include "Network/GameConnection.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket142.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket143.h"
|
||||
#include "Network/PacketWrappers/ActorControlPacket144.h"
|
||||
#include "Network/PacketWrappers/InitUIPacket.h"
|
||||
#include "Network/PacketWrappers/ServerNoticePacket.h"
|
||||
#include "Network/PacketWrappers/ChatPacket.h"
|
||||
|
@ -40,6 +40,7 @@
|
|||
#include "Event/EventHandler.h"
|
||||
|
||||
#include "Action/Action.h"
|
||||
#include "Action/ActionTeleport.h"
|
||||
#include "Action/EventAction.h"
|
||||
#include "Action/EventItemAction.h"
|
||||
|
||||
|
@ -57,7 +58,7 @@ using namespace Core::Network::Packets::Server;
|
|||
|
||||
// player constructor
|
||||
Core::Entity::Player::Player() :
|
||||
Actor( ObjKind::Player ),
|
||||
Chara( ObjKind::Player ),
|
||||
m_lastWrite( 0 ),
|
||||
m_lastPing( 0 ),
|
||||
m_bIsLogin( false ),
|
||||
|
@ -75,7 +76,8 @@ Core::Entity::Player::Player() :
|
|||
m_bAutoattack( false ),
|
||||
m_markedForRemoval( false ),
|
||||
m_mount( 0 ),
|
||||
m_directorInitialized( false )
|
||||
m_directorInitialized( false ),
|
||||
m_onEnterEventDone( false )
|
||||
{
|
||||
m_id = 0;
|
||||
m_currentStance = Stance::Passive;
|
||||
|
@ -83,6 +85,7 @@ Core::Entity::Player::Player() :
|
|||
m_queuedZoneing = nullptr;
|
||||
m_status = ActorStatus::Idle;
|
||||
m_invincibilityType = InvincibilityType::InvincibilityNone;
|
||||
m_modelType = ModelType::Human;
|
||||
|
||||
memset( m_questTracking, 0, sizeof( m_questTracking ) );
|
||||
memset( m_name, 0, sizeof( m_name ) );
|
||||
|
@ -90,12 +93,22 @@ Core::Entity::Player::Player() :
|
|||
memset( m_searchMessage, 0, sizeof( m_searchMessage ) );
|
||||
memset( m_classArray, 0, sizeof( m_classArray ) );
|
||||
memset( m_expArray, 0, sizeof( m_expArray ) );
|
||||
|
||||
m_objSpawnIndexAllocator.init( MAX_DISPLAYED_EOBJS );
|
||||
m_actorSpawnIndexAllocator.init( MAX_DISPLAYED_ACTORS, true );
|
||||
}
|
||||
|
||||
Core::Entity::Player::~Player()
|
||||
{
|
||||
}
|
||||
|
||||
void Core::Entity::Player::injectPacket( std::string path )
|
||||
{
|
||||
auto session = g_framework.getServerZone().getSession( getId() );
|
||||
if( session )
|
||||
session->getZoneConnection()->injectPacket( path, *this );
|
||||
}
|
||||
|
||||
// TODO: add a proper calculation based on race / job / level / gear
|
||||
uint32_t Core::Entity::Player::getMaxHp()
|
||||
{
|
||||
|
@ -181,7 +194,7 @@ Core::Common::OnlineStatus Core::Entity::Player::getOnlineStatus()
|
|||
if( m_onlineStatus & rpMask )
|
||||
status = OnlineStatus::Roleplaying;
|
||||
|
||||
if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) || hasStateFlag( PlayerStateFlag::WatchingCutscene1 ) )
|
||||
if( hasStateFlag( PlayerStateFlag::WatchingCutscene ) )
|
||||
status = OnlineStatus::ViewingCutscene;
|
||||
|
||||
// TODO: add all the logic for returning the proper online status, there probably is a better way for this alltogether
|
||||
|
@ -252,7 +265,7 @@ void Core::Entity::Player::calculateStats()
|
|||
}
|
||||
|
||||
|
||||
void Core::Entity::Player::setAutoattack(bool mode)
|
||||
void Core::Entity::Player::setAutoattack( bool mode )
|
||||
{
|
||||
m_bAutoattack = mode;
|
||||
m_lastAttack = Util::getTimeMs();
|
||||
|
@ -307,8 +320,7 @@ void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type )
|
|||
}
|
||||
|
||||
setStateFlag( PlayerStateFlag::BetweenAreas );
|
||||
|
||||
auto z_pos = g_framework.getTerritoryMgr().getTerritoryPosition( data->territory );
|
||||
auto targetPos = g_framework.getTerritoryMgr().getTerritoryPosition( data->levelId );
|
||||
|
||||
Common::FFXIVARR_POSITION3 pos;
|
||||
pos.x = 0;
|
||||
|
@ -316,10 +328,10 @@ void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type )
|
|||
pos.z = 0;
|
||||
float rot = 0;
|
||||
|
||||
if( z_pos != nullptr )
|
||||
if( targetPos != nullptr )
|
||||
{
|
||||
pos = z_pos->getTargetPosition();
|
||||
rot = z_pos->getTargetRotation();
|
||||
pos = targetPos->getTargetPosition();
|
||||
rot = targetPos->getTargetRotation();
|
||||
}
|
||||
|
||||
sendDebug( "Teleport: " + g_framework.getExdDataGen().get< Core::Data::PlaceName >( data->placeName )->name + " " +
|
||||
|
@ -365,6 +377,7 @@ void Core::Entity::Player::returnToHomepoint()
|
|||
|
||||
void Core::Entity::Player::setZone( uint32_t zoneId )
|
||||
{
|
||||
m_onEnterEventDone = false;
|
||||
if( !g_framework.getTerritoryMgr().movePlayer( zoneId, getAsPlayer() ) )
|
||||
{
|
||||
// todo: this will require proper handling, for now just return the player to their previous area
|
||||
|
@ -381,6 +394,7 @@ void Core::Entity::Player::setZone( uint32_t zoneId )
|
|||
|
||||
bool Core::Entity::Player::setInstance( uint32_t instanceContentId )
|
||||
{
|
||||
m_onEnterEventDone = false;
|
||||
auto instance = g_framework.getTerritoryMgr().getInstanceZonePtr( instanceContentId );
|
||||
if( !instance )
|
||||
return false;
|
||||
|
@ -390,6 +404,7 @@ bool Core::Entity::Player::setInstance( uint32_t instanceContentId )
|
|||
|
||||
bool Core::Entity::Player::setInstance( ZonePtr instance )
|
||||
{
|
||||
m_onEnterEventDone = false;
|
||||
if( !instance )
|
||||
return false;
|
||||
|
||||
|
@ -440,43 +455,27 @@ uint8_t Core::Entity::Player::getGender() const
|
|||
|
||||
void Core::Entity::Player::initSpawnIdQueue()
|
||||
{
|
||||
while( !m_freeSpawnIdQueue.empty() )
|
||||
{
|
||||
m_freeSpawnIdQueue.pop();
|
||||
}
|
||||
|
||||
for( int32_t i = 1; i < MAX_DISPLAYED_ACTORS; i++ )
|
||||
{
|
||||
m_freeSpawnIdQueue.push( i );
|
||||
}
|
||||
m_actorSpawnIndexAllocator.freeAllSpawnIndexes();
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::Player::getSpawnIdForActorId( uint32_t actorId )
|
||||
{
|
||||
if( m_freeSpawnIdQueue.empty() )
|
||||
return 0;
|
||||
|
||||
uint8_t spawnId = m_freeSpawnIdQueue.front();
|
||||
m_freeSpawnIdQueue.pop();
|
||||
m_playerIdToSpawnIdMap[actorId] = spawnId;
|
||||
return spawnId;
|
||||
return m_actorSpawnIndexAllocator.getNextFreeSpawnIndex( actorId );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::assignSpawnIdToPlayerId( uint32_t actorId, uint8_t spawnId )
|
||||
bool Core::Entity::Player::isActorSpawnIdValid( uint8_t spawnIndex )
|
||||
{
|
||||
m_playerIdToSpawnIdMap[actorId] = spawnId;
|
||||
return m_actorSpawnIndexAllocator.isSpawnIndexValid( spawnIndex );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::registerAetheryte( uint8_t aetheryteId )
|
||||
{
|
||||
|
||||
uint16_t index;
|
||||
uint8_t value;
|
||||
Util::valueToFlagByteIndexValue( aetheryteId, value, index );
|
||||
|
||||
m_aetheryte[index] |= value;
|
||||
queuePacket( ActorControlPacket143( getId(), LearnTeleport, aetheryteId, 1 ) );
|
||||
|
||||
}
|
||||
|
||||
bool Core::Entity::Player::isAetheryteRegistered( uint8_t aetheryteId ) const
|
||||
|
@ -639,7 +638,7 @@ void Core::Entity::Player::gainLevel()
|
|||
|
||||
ZoneChannelPacket< FFXIVIpcStatusEffectList > effectListPacket( getId() );
|
||||
effectListPacket.data().classId = static_cast< uint8_t > ( getClass() );
|
||||
effectListPacket.data().classId1 = static_cast< uint8_t > ( getClass() );
|
||||
effectListPacket.data().level1 = getLevel();
|
||||
effectListPacket.data().level = getLevel();
|
||||
effectListPacket.data().current_hp = getMaxHp();
|
||||
effectListPacket.data().current_mp = getMaxMp();
|
||||
|
@ -654,23 +653,12 @@ void Core::Entity::Player::gainLevel()
|
|||
|
||||
ZoneChannelPacket< FFXIVIpcUpdateClassInfo > classInfoPacket( getId() );
|
||||
classInfoPacket.data().classId = static_cast< uint8_t > ( getClass() );
|
||||
classInfoPacket.data().classId1 = static_cast< uint8_t > ( getClass() );
|
||||
classInfoPacket.data().level1 = getLevel();
|
||||
classInfoPacket.data().level = getLevel();
|
||||
classInfoPacket.data().nextLevelIndex = getLevel();
|
||||
classInfoPacket.data().currentExp = getExp();
|
||||
queuePacket( classInfoPacket );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::Player::unlock()
|
||||
{
|
||||
queuePacket( PlayerStateFlagsPacket( *getAsPlayer(), PlayerStateFlagList{} ) );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::sendStatusUpdate( bool toSelf )
|
||||
|
@ -831,6 +819,8 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget )
|
|||
{
|
||||
auto pPlayer = pTarget;
|
||||
|
||||
g_framework.getLogger().debug( "despawning " + getName() + " for " + pTarget->getName() );
|
||||
|
||||
pPlayer->freePlayerSpawnId( getId() );
|
||||
|
||||
pPlayer->queuePacket( ActorControlPacket143( getId(), DespawnZoneScreenMsg, 0x04, getId(), 0x01 ) );
|
||||
|
@ -839,7 +829,7 @@ void Core::Entity::Player::despawn( Entity::PlayerPtr pTarget )
|
|||
Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId )
|
||||
{
|
||||
ActorPtr targetActor;
|
||||
auto inRange = getInRangeActors( true );
|
||||
auto inRange = getInRangeActors(true);
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
if( actor->getId() == targetId )
|
||||
|
@ -989,7 +979,7 @@ void Core::Entity::Player::update( int64_t currTime )
|
|||
setActorPosPacket.data().y = targetPos.y;
|
||||
setActorPosPacket.data().z = targetPos.z;
|
||||
sendToInRangeSet( setActorPosPacket, true );
|
||||
setPosition( targetPos );
|
||||
setPos( targetPos );
|
||||
}
|
||||
m_queuedZoneing.reset();
|
||||
return;
|
||||
|
@ -1007,14 +997,14 @@ void Core::Entity::Player::update( int64_t currTime )
|
|||
|
||||
if( !checkAction() )
|
||||
{
|
||||
if( m_targetId && m_currentStance == Entity::Actor::Stance::Active && isAutoattackOn() )
|
||||
if( m_targetId && m_currentStance == Entity::Chara::Stance::Active && isAutoattackOn() )
|
||||
{
|
||||
auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand );
|
||||
|
||||
// @TODO i dislike this, iterating over all in range actors when you already know the id of the actor you need...
|
||||
for( auto actor : m_inRangeActors )
|
||||
for( auto actor : m_inRangeActor )
|
||||
{
|
||||
if( actor->getId() == m_targetId && actor->isAlive() && mainWeap )
|
||||
if( actor->getId() == m_targetId && actor->getAsChara()->isAlive() && mainWeap )
|
||||
{
|
||||
// default autoattack range
|
||||
// TODO make this dependant on bnpc size
|
||||
|
@ -1034,7 +1024,7 @@ void Core::Entity::Player::update( int64_t currTime )
|
|||
if( ( currTime - m_lastAttack ) > mainWeap->getDelay() )
|
||||
{
|
||||
m_lastAttack = currTime;
|
||||
autoAttack( actor );
|
||||
autoAttack( actor->getAsChara() );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1059,9 +1049,7 @@ void Core::Entity::Player::onMobKill( uint16_t nameId )
|
|||
|
||||
void Core::Entity::Player::freePlayerSpawnId( uint32_t actorId )
|
||||
{
|
||||
uint8_t spawnId = m_playerIdToSpawnIdMap[actorId];
|
||||
m_playerIdToSpawnIdMap.erase( actorId );
|
||||
m_freeSpawnIdQueue.push( spawnId );
|
||||
auto spawnId = m_actorSpawnIndexAllocator.freeUsedSpawnIndex( actorId );
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcActorFreeSpawn > freeActorSpawnPacket( getId() );
|
||||
freeActorSpawnPacket.data().actorId = actorId;
|
||||
|
@ -1206,7 +1194,7 @@ void Core::Entity::Player::performZoning( uint16_t zoneId, const Common::FFXIVAR
|
|||
m_pos = pos;
|
||||
m_zoneId = zoneId;
|
||||
m_bMarkedForZoning = true;
|
||||
setRotation( rotation );
|
||||
setRot( rotation );
|
||||
setZone( zoneId );
|
||||
}
|
||||
|
||||
|
@ -1273,64 +1261,6 @@ void Core::Entity::Player::updateHowtosSeen( uint32_t howToId )
|
|||
m_howTo[index] |= value;
|
||||
}
|
||||
|
||||
|
||||
void Core::Entity::Player::onMobAggro( BattleNpcPtr pBNpc )
|
||||
{
|
||||
hateListAdd( pBNpc );
|
||||
|
||||
queuePacket( ActorControlPacket142( getId(), ToggleAggro, 1 ) );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::onMobDeaggro( BattleNpcPtr pBNpc )
|
||||
{
|
||||
hateListRemove( pBNpc );
|
||||
|
||||
if( m_actorIdTohateSlotMap.empty() )
|
||||
queuePacket( ActorControlPacket142( getId(), ToggleAggro ) );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::hateListAdd( BattleNpcPtr pBNpc )
|
||||
|
||||
{
|
||||
if( m_freeHateSlotQueue.empty() )
|
||||
return;
|
||||
uint8_t hateId = m_freeHateSlotQueue.front();
|
||||
m_freeHateSlotQueue.pop();
|
||||
m_actorIdTohateSlotMap[pBNpc->getId()] = hateId;
|
||||
sendHateList();
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::Player::hateListRemove( BattleNpcPtr pBNpc )
|
||||
{
|
||||
|
||||
auto it = m_actorIdTohateSlotMap.begin();
|
||||
for( ; it != m_actorIdTohateSlotMap.end(); ++it )
|
||||
{
|
||||
if( it->first == pBNpc->getId() )
|
||||
{
|
||||
uint8_t hateSlot = it->second;
|
||||
m_freeHateSlotQueue.push( hateSlot );
|
||||
m_actorIdTohateSlotMap.erase( it );
|
||||
sendHateList();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::Entity::Player::hateListHasMob( BattleNpcPtr pBNpc )
|
||||
{
|
||||
|
||||
auto it = m_actorIdTohateSlotMap.begin();
|
||||
for( ; it != m_actorIdTohateSlotMap.end(); ++it )
|
||||
{
|
||||
if( it->first == pBNpc->getId() )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::initHateSlotQueue()
|
||||
{
|
||||
m_freeHateSlotQueue = std::queue< uint8_t >();
|
||||
|
@ -1366,6 +1296,11 @@ uint8_t* Core::Entity::Player::getTitleList()
|
|||
return m_titleList;
|
||||
}
|
||||
|
||||
const uint8_t* Core::Entity::Player::getTitleList() const
|
||||
{
|
||||
return m_titleList;
|
||||
}
|
||||
|
||||
uint16_t Core::Entity::Player::getTitle() const
|
||||
{
|
||||
return m_activeTitle;
|
||||
|
@ -1410,7 +1345,7 @@ uint8_t Core::Entity::Player::getEquipDisplayFlags() const
|
|||
void Core::Entity::Player::mount( uint32_t id )
|
||||
{
|
||||
m_mount = id;
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Mounted )), true );
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Chara::ActorStatus::Mounted )), true );
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), 0x39e, 12 ), true ); //?
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcMount > mountPacket( getId() );
|
||||
|
@ -1421,7 +1356,7 @@ void Core::Entity::Player::mount( uint32_t id )
|
|||
void Core::Entity::Player::dismount()
|
||||
{
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus,
|
||||
static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle )), true );
|
||||
static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle )), true );
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), ActorControlType::Dismount, 1 ), true );
|
||||
m_mount = 0;
|
||||
}
|
||||
|
@ -1431,7 +1366,7 @@ uint8_t Core::Entity::Player::getCurrentMount() const
|
|||
return m_mount;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
||||
void Core::Entity::Player::autoAttack( CharaPtr pTarget )
|
||||
{
|
||||
|
||||
auto mainWeap = m_pInventory->getItemAt( Inventory::GearSet0,
|
||||
|
@ -1444,11 +1379,9 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
|||
uint32_t damage = static_cast< uint32_t >( mainWeap->getAutoAttackDmg() );
|
||||
uint32_t variation = 0 + rand() % 3;
|
||||
|
||||
if( getClass() == ClassJob::Machinist ||
|
||||
getClass() == ClassJob::Bard ||
|
||||
getClass() == ClassJob::Archer )
|
||||
if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer )
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket(getId());
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() );
|
||||
effectPacket.data().targetId = pTarget->getId();
|
||||
effectPacket.data().actionAnimationId = 8;
|
||||
// effectPacket.data().unknown_2 = variation;
|
||||
|
@ -1456,7 +1389,7 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
|||
effectPacket.data().unknown_61 = 1;
|
||||
effectPacket.data().unknown_62 = 1;
|
||||
effectPacket.data().actionTextId = 8;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation());
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRot() );
|
||||
effectPacket.data().effectTargetId = pTarget->getId();
|
||||
effectPacket.data().effectTarget = pTarget->getId();
|
||||
effectPacket.data().effects[0].value = damage;
|
||||
|
@ -1469,7 +1402,7 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
|||
else
|
||||
{
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket(getId());
|
||||
ZoneChannelPacket< FFXIVIpcEffect > effectPacket( getId() );
|
||||
effectPacket.data().targetId = pTarget->getId();
|
||||
effectPacket.data().actionAnimationId = 7;
|
||||
// effectPacket.data().unknown_2 = variation;
|
||||
|
@ -1477,7 +1410,7 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
|||
effectPacket.data().unknown_61 = 1;
|
||||
effectPacket.data().unknown_62 = 1;
|
||||
effectPacket.data().actionTextId = 7;
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot(getRotation());
|
||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRot() );
|
||||
effectPacket.data().effectTarget = pTarget->getId();
|
||||
effectPacket.data().effects[0].value = damage;
|
||||
effectPacket.data().effects[0].effectType = Common::ActionEffectType::Damage;
|
||||
|
@ -1550,18 +1483,20 @@ void Core::Entity::Player::setEorzeaTimeOffset( uint64_t timestamp )
|
|||
queuePacket( packet );
|
||||
}
|
||||
|
||||
void Player::setTerritoryId( uint32_t territoryId )
|
||||
void Core::Entity::Player::setTerritoryId( uint32_t territoryId )
|
||||
{
|
||||
m_zoneId = territoryId;
|
||||
}
|
||||
|
||||
uint32_t Player::getTerritoryId() const
|
||||
uint32_t Core::Entity::Player::getTerritoryId() const
|
||||
{
|
||||
return m_zoneId;
|
||||
}
|
||||
|
||||
void Player::sendZonePackets()
|
||||
void Core::Entity::Player::sendZonePackets()
|
||||
{
|
||||
getCurrentZone()->onBeforePlayerZoneIn( *this );
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcInit > initPacket( getId() );
|
||||
initPacket.data().charId = getId();
|
||||
queuePacket( initPacket );
|
||||
|
@ -1570,7 +1505,7 @@ void Player::sendZonePackets()
|
|||
|
||||
if( isLogin() )
|
||||
{
|
||||
queuePacket(ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) );
|
||||
queuePacket( ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) );
|
||||
}
|
||||
|
||||
// set flags, will be reset automatically by zoning ( only on client side though )
|
||||
|
@ -1627,17 +1562,135 @@ void Player::sendZonePackets()
|
|||
if( getLastPing() == 0 )
|
||||
sendQuestInfo();
|
||||
|
||||
getCurrentZone()->onEnterTerritory( *this );
|
||||
getCurrentZone()->onPlayerZoneIn( *this );
|
||||
|
||||
m_bMarkedForZoning = false;
|
||||
}
|
||||
|
||||
void Player::setDirectorInitialized( bool isInitialized )
|
||||
void Core::Entity::Player::setDirectorInitialized( bool isInitialized )
|
||||
{
|
||||
m_directorInitialized = isInitialized;
|
||||
}
|
||||
|
||||
bool Player::isDirectorInitialized() const
|
||||
bool Core::Entity::Player::isDirectorInitialized() const
|
||||
{
|
||||
return m_directorInitialized;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::sendTitleList()
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcPlayerTitleList > titleListPacket( getId() );
|
||||
memcpy( titleListPacket.data().titleList, getTitleList(), sizeof( titleListPacket.data().titleList ) );
|
||||
|
||||
queuePacket( titleListPacket );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::finishZoning()
|
||||
{
|
||||
switch( getZoningType() )
|
||||
{
|
||||
case ZoneingType::None:
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01 ), true );
|
||||
break;
|
||||
|
||||
case ZoneingType::Teleport:
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0, 0, 110 ), true );
|
||||
break;
|
||||
|
||||
case ZoneingType::Return:
|
||||
case ZoneingType::ReturnDead:
|
||||
{
|
||||
if( getStatus() == Entity::Chara::ActorStatus::Dead )
|
||||
{
|
||||
resetHp();
|
||||
resetMp();
|
||||
setStatus( Entity::Chara::ActorStatus::Idle );
|
||||
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x01, 0, 111 ), true );
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), SetStatus,
|
||||
static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle ) ), true );
|
||||
}
|
||||
else
|
||||
sendToInRangeSet( ActorControlPacket143( getId(), ZoneIn, 0x01, 0x00, 0, 111 ), true );
|
||||
}
|
||||
break;
|
||||
|
||||
case ZoneingType::FadeIn:
|
||||
break;
|
||||
}
|
||||
|
||||
setZoningType( Common::ZoneingType::None );
|
||||
unsetStateFlag( PlayerStateFlag::BetweenAreas );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::emote( uint32_t emoteId, uint64_t targetId )
|
||||
{
|
||||
sendToInRangeSet( ActorControlPacket144( getId(), ActorControlType::Emote, emoteId, 0, 0, 0, targetId ) );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::teleportQuery( uint16_t aetheryteId )
|
||||
{
|
||||
// TODO: only register this action if enough gil is in possession
|
||||
auto& exdDataGen = g_framework.getExdDataGen();
|
||||
auto targetAetheryte = exdDataGen.get< Core::Data::Aetheryte >( aetheryteId );
|
||||
|
||||
if( targetAetheryte )
|
||||
{
|
||||
auto fromAetheryte = exdDataGen.get< Core::Data::Aetheryte >(
|
||||
exdDataGen.get< Core::Data::TerritoryType >( getZoneId() )->aetheryte );
|
||||
|
||||
// calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets
|
||||
auto cost = static_cast< uint16_t > ( ( sqrt( pow( fromAetheryte->aetherstreamX - targetAetheryte->aetherstreamX, 2 ) +
|
||||
pow( fromAetheryte->aetherstreamY - targetAetheryte->aetherstreamY, 2 ) ) / 2 ) + 100 );
|
||||
|
||||
// cap at 999 gil
|
||||
cost = cost > uint16_t{999} ? uint16_t{999} : cost;
|
||||
|
||||
bool insufficientGil = getCurrency( Inventory::CurrencyType::Gil ) < cost;
|
||||
// TODO: figure out what param1 really does
|
||||
queuePacket( ActorControlPacket143( getId(), TeleportStart, insufficientGil ? 2 : 0, aetheryteId ) );
|
||||
|
||||
if( !insufficientGil )
|
||||
{
|
||||
Action::ActionPtr pActionTeleport;
|
||||
pActionTeleport = Action::make_ActionTeleport( getAsPlayer(), aetheryteId, cost );
|
||||
setCurrentAction( pActionTeleport );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Core::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actorId )
|
||||
{
|
||||
return m_objSpawnIndexAllocator.getNextFreeSpawnIndex( actorId );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::resetObjSpawnIndex()
|
||||
{
|
||||
m_objSpawnIndexAllocator.freeAllSpawnIndexes();
|
||||
}
|
||||
|
||||
void Core::Entity::Player::freeObjSpawnIndexForActorId( uint32_t actorId )
|
||||
{
|
||||
auto spawnId = m_objSpawnIndexAllocator.freeUsedSpawnIndex( actorId );
|
||||
|
||||
ZoneChannelPacket< FFXIVIpcObjectDespawn > freeObjectSpawnPacket( getId() );
|
||||
freeObjectSpawnPacket.data().spawnIndex = spawnId;
|
||||
queuePacket( freeObjectSpawnPacket );
|
||||
}
|
||||
|
||||
bool Core::Entity::Player::isObjSpawnIndexValid( uint8_t index )
|
||||
{
|
||||
return m_objSpawnIndexAllocator.isSpawnIndexValid( index );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::setOnEnterEventDone( bool isDone )
|
||||
{
|
||||
m_onEnterEventDone = isDone;
|
||||
}
|
||||
|
||||
bool Core::Entity::Player::isOnEnterEventDone() const
|
||||
{
|
||||
return m_onEnterEventDone;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
|
||||
#include <sapphire_zone/Social/FriendList.h>
|
||||
#include <common/Common.h>
|
||||
#include <common/Util/SpawnIndexAllocator.h>
|
||||
|
||||
#include "Actor.h"
|
||||
#include "Chara.h"
|
||||
#include "Inventory/Inventory.h"
|
||||
#include "Event/EventHandler.h"
|
||||
#include <map>
|
||||
|
@ -37,7 +38,7 @@ struct QueuedZoning
|
|||
* Inheriting from Actor
|
||||
*
|
||||
*/
|
||||
class Player : public Actor
|
||||
class Player : public Chara
|
||||
{
|
||||
public:
|
||||
/*! Contructor */
|
||||
|
@ -46,7 +47,9 @@ public:
|
|||
/*! Destructor */
|
||||
~Player();
|
||||
|
||||
void autoAttack( ActorPtr pTarget ) override;
|
||||
void autoAttack( CharaPtr pTarget ) override;
|
||||
|
||||
void injectPacket( std::string path );
|
||||
|
||||
// EventHandlers
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -55,9 +58,12 @@ public:
|
|||
/*! start an event item action */
|
||||
void eventItemActionStart( uint32_t eventId, uint32_t action, ActionCallback finishCallback, ActionCallback interruptCallback, uint64_t additional );
|
||||
/*! start/register a normal event */
|
||||
void eventStart( uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventParam, uint8_t eventParam1, uint32_t eventParam2 );
|
||||
void eventStart( uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventParam, uint8_t eventParam1, uint32_t eventParam2, uint32_t contentId = 0 );
|
||||
/*! play a subevent */
|
||||
void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, uint32_t eventParam3 );
|
||||
|
||||
void directorPlayScene( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2, uint32_t eventParam3 );
|
||||
|
||||
/*! play a subevent */
|
||||
void eventPlay( uint32_t eventId, uint32_t scene, uint32_t flags,
|
||||
uint32_t eventParam2, uint32_t eventParam3, Event::EventHandler::SceneReturnCallback eventReturnCallback );
|
||||
|
@ -347,16 +353,21 @@ public:
|
|||
uint64_t getOnlineStatusMask() 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 */
|
||||
void teleportQuery( uint16_t aetheryteId );
|
||||
/*! prepares zoning / fades out the screen */
|
||||
void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 );
|
||||
/*! get player's title list (available titles) */
|
||||
uint8_t* getTitleList();
|
||||
const uint8_t* getTitleList() const;
|
||||
/*! get player's active title */
|
||||
uint16_t getTitle() const;
|
||||
/*! add title to player title list */
|
||||
void addTitle( uint16_t titleId );
|
||||
/*! change player's active title */
|
||||
void setTitle( uint16_t titleId );
|
||||
/*! send the players title list */
|
||||
void sendTitleList();
|
||||
/*! change gear param state */
|
||||
void setEquipDisplayFlags( uint8_t state );
|
||||
/*! get gear param state */
|
||||
|
@ -423,10 +434,10 @@ public:
|
|||
void initSpawnIdQueue();
|
||||
/*! get the spawn id mapped to a specific actorId */
|
||||
uint8_t getSpawnIdForActorId( uint32_t actorId );
|
||||
/*! assigns the given spawnId to the actor */
|
||||
void assignSpawnIdToPlayerId( uint32_t actorId, uint8_t spawnId );
|
||||
/*! frees the spawnId assigned to the given actor */
|
||||
void freePlayerSpawnId( uint32_t actorId );
|
||||
/*! checks if the given spawn id is valid */
|
||||
bool isActorSpawnIdValid( uint8_t spawnId );
|
||||
/*! send spawn packets to pTarget */
|
||||
void spawn( PlayerPtr pTarget ) override;
|
||||
/*! send despawn packets to pTarget */
|
||||
|
@ -444,8 +455,6 @@ public:
|
|||
bool hasStateFlag( Common::PlayerStateFlag flag ) const;
|
||||
/* reset a specified flag */
|
||||
void unsetStateFlag( Common::PlayerStateFlag flag );
|
||||
/* helper function, send an empty state flag update */
|
||||
void unlock();
|
||||
|
||||
// Player Session Handling
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -494,6 +503,10 @@ public:
|
|||
/*! return true if the player is marked for zoning */
|
||||
bool isMarkedForZoning() const;
|
||||
|
||||
void emote( uint32_t emoteId, uint64_t targetId );
|
||||
|
||||
void finishZoning();
|
||||
|
||||
void sendZonePackets();
|
||||
|
||||
Common::ZoneingType getZoningType() const;
|
||||
|
@ -513,14 +526,7 @@ public:
|
|||
|
||||
// Player Battle Handling
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void onMobAggro( BattleNpcPtr pBNpc );
|
||||
void onMobDeaggro( BattleNpcPtr pBNpc );
|
||||
|
||||
void initHateSlotQueue();
|
||||
void hateListAdd( BattleNpcPtr pBNpc );
|
||||
void hateListRemove( BattleNpcPtr pBNpc );
|
||||
|
||||
bool hateListHasMob( BattleNpcPtr pBNpc );
|
||||
|
||||
void sendHateList();
|
||||
|
||||
|
@ -566,6 +572,18 @@ public:
|
|||
void setMarkedForRemoval();
|
||||
bool isMarkedForRemoval() const;
|
||||
|
||||
void setOnEnterEventDone( bool isDone );
|
||||
bool isOnEnterEventDone() const;
|
||||
|
||||
/*! gets the next available obj count */
|
||||
uint8_t getNextObjSpawnIndexForActorId( uint32_t actorId );
|
||||
/*! resets the players obj count */
|
||||
void resetObjSpawnIndex();
|
||||
/*! frees an obj count to be used by another eobj */
|
||||
void freeObjSpawnIndexForActorId( uint32_t actorId );
|
||||
/*! checks if a spawn index is valid */
|
||||
bool isObjSpawnIndexValid( uint8_t index );
|
||||
|
||||
private:
|
||||
uint32_t m_lastWrite;
|
||||
uint32_t m_lastPing;
|
||||
|
@ -580,6 +598,8 @@ private:
|
|||
|
||||
bool m_directorInitialized;
|
||||
|
||||
bool m_onEnterEventDone;
|
||||
|
||||
private:
|
||||
|
||||
Common::FFXIVARR_POSITION3 m_prevPos;
|
||||
|
@ -636,8 +656,6 @@ private:
|
|||
|
||||
std::map< uint32_t, Event::EventHandlerPtr > m_eventHandlerMap;
|
||||
|
||||
std::map< uint32_t, uint8_t > m_playerIdToSpawnIdMap; // maps player to spawn id
|
||||
std::queue< uint8_t > m_freeSpawnIdQueue; // queue with spawn ids free to be assigned
|
||||
std::queue< uint8_t > m_freeHateSlotQueue; // queue with "hate slots" free to be assigned
|
||||
std::map< uint32_t, uint8_t > m_actorIdTohateSlotMap;
|
||||
|
||||
|
@ -646,7 +664,7 @@ private:
|
|||
boost::shared_ptr< Common::QuestActive > m_activeQuests[30];
|
||||
int16_t m_questTracking[5];
|
||||
|
||||
uint8_t m_stateFlags[7];
|
||||
uint8_t m_stateFlags[12];
|
||||
uint8_t m_gmRank;
|
||||
uint16_t zoneId;
|
||||
|
||||
|
@ -680,6 +698,9 @@ private:
|
|||
uint32_t m_cfPenaltyUntil; // unix time
|
||||
|
||||
uint8_t m_mount;
|
||||
|
||||
Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator;
|
||||
Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Network/PacketWrappers/EventStartPacket.h"
|
||||
#include "Network/PacketWrappers/EventPlayPacket.h"
|
||||
#include "Network/PacketWrappers/EventFinishPacket.h"
|
||||
#include "Network/PacketWrappers/DirectorPlayScenePacket.h"
|
||||
|
||||
#include "Action/EventAction.h"
|
||||
#include "Action/EventItemAction.h"
|
||||
|
@ -74,18 +75,39 @@ void Core::Entity::Player::checkEvent( uint32_t eventId )
|
|||
}
|
||||
|
||||
|
||||
void Core::Entity::Player::directorPlayScene( uint32_t eventId, uint32_t scene, uint32_t flags, uint32_t eventParam2,
|
||||
uint32_t eventParam3 )
|
||||
{
|
||||
if( flags & 0x02 )
|
||||
setStateFlag( PlayerStateFlag::WatchingCutscene );
|
||||
|
||||
auto pEvent = getEvent( eventId );
|
||||
if( !pEvent )
|
||||
{
|
||||
g_framework.getLogger().error( "Could not find event " + std::to_string( eventId ) + ", event has not been started!" );
|
||||
return;
|
||||
}
|
||||
|
||||
pEvent->setPlayedScene( true );
|
||||
pEvent->setEventReturnCallback( nullptr );
|
||||
DirectorPlayScenePacket eventPlay( getId(), getId(), pEvent->getId(),
|
||||
scene, flags, eventParam2, eventParam3 );
|
||||
|
||||
queuePacket( eventPlay );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::eventStart( uint64_t actorId, uint32_t eventId,
|
||||
Event::EventHandler::EventType eventType, uint8_t eventParam1,
|
||||
uint32_t eventParam2 )
|
||||
uint32_t eventParam2, uint32_t contentId )
|
||||
{
|
||||
|
||||
auto newEvent = Event::make_EventHandler( this, actorId, eventId, eventType, eventParam2 );
|
||||
|
||||
addEvent( newEvent );
|
||||
|
||||
setStateFlag( PlayerStateFlag::Occupied2 );
|
||||
setStateFlag( PlayerStateFlag::InNpcEvent );
|
||||
|
||||
EventStartPacket eventStart( getId(), actorId, eventId, eventType, eventParam1, eventParam2 );
|
||||
EventStartPacket eventStart( getId(), actorId, eventId, eventType, eventParam1, eventParam2, contentId );
|
||||
|
||||
queuePacket( eventStart );
|
||||
|
||||
|
@ -217,7 +239,7 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer )
|
|||
removeEvent( pEvent->getId() );
|
||||
|
||||
if( freePlayer == 1 )
|
||||
unsetStateFlag( PlayerStateFlag::Occupied2 );
|
||||
unsetStateFlag( PlayerStateFlag::InNpcEvent );
|
||||
}
|
||||
|
||||
void Core::Entity::Player::eventActionStart( uint32_t eventId,
|
||||
|
@ -226,7 +248,7 @@ void Core::Entity::Player::eventActionStart( uint32_t eventId,
|
|||
ActionCallback interruptCallback,
|
||||
uint64_t additional )
|
||||
{
|
||||
auto pEventAction = Action::make_EventAction( getAsActor(), eventId, action,
|
||||
auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action,
|
||||
finishCallback, interruptCallback, additional );
|
||||
|
||||
setCurrentAction( pEventAction );
|
||||
|
@ -256,7 +278,7 @@ void Core::Entity::Player::eventItemActionStart( uint32_t eventId,
|
|||
ActionCallback interruptCallback,
|
||||
uint64_t additional )
|
||||
{
|
||||
Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsActor(), eventId, action,
|
||||
Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsChara(), eventId, action,
|
||||
finishCallback, interruptCallback, additional );
|
||||
|
||||
setCurrentAction( pEventItemAction );
|
||||
|
@ -289,7 +311,6 @@ void Core::Entity::Player::onDeath()
|
|||
|
||||
}
|
||||
|
||||
|
||||
// TODO: slightly ugly here and way too static. Needs too be done properly
|
||||
void Core::Entity::Player::onTick()
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession )
|
|||
m_pos.x = res->getFloat( "PosX" );
|
||||
m_pos.y = res->getFloat( "PosY" );
|
||||
m_pos.z = res->getFloat( "PosZ" );
|
||||
setRotation( res->getFloat( "PosR" ) );
|
||||
setRot( res->getFloat( "PosR" ) );
|
||||
|
||||
m_prevPos.x = res->getFloat( "OPosX" );
|
||||
m_prevPos.y = res->getFloat( "OPosY" );
|
||||
|
@ -79,7 +79,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession )
|
|||
m_pos.x = m_prevPos.x;
|
||||
m_pos.y = m_prevPos.y;
|
||||
m_pos.z = m_prevPos.z;
|
||||
setRotation( m_prevRot );
|
||||
setRot( m_prevRot );
|
||||
pCurrZone = g_framework.getTerritoryMgr().getZoneByTerriId( zoneId );
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession )
|
|||
m_pos.x = 0.0f;
|
||||
m_pos.y = 0.0f;
|
||||
m_pos.z = 0.0f;
|
||||
setRotation( 0.0f );
|
||||
setRot( 0.0f );
|
||||
}
|
||||
|
||||
// Stats
|
||||
|
@ -230,9 +230,6 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession )
|
|||
|
||||
initSpawnIdQueue();
|
||||
|
||||
if( !m_playerIdToSpawnIdMap.empty() )
|
||||
m_playerIdToSpawnIdMap.clear();
|
||||
|
||||
if( !g_framework.getTerritoryMgr().movePlayer( pCurrZone, getAsPlayer() ) )
|
||||
return false;
|
||||
|
||||
|
@ -307,7 +304,10 @@ bool Core::Entity::Player::loadSearchInfo()
|
|||
|
||||
m_searchSelectClass = res->getUInt8( 1 );
|
||||
m_searchSelectRegion = res->getUInt8( 2 );
|
||||
sprintf( m_searchMessage, res->getString( 3 ).c_str() );
|
||||
|
||||
// todo: internally use an std::string instead of a char[]
|
||||
auto searchMessage = res->getString( 3 );
|
||||
std::copy( searchMessage.begin(), searchMessage.end(), m_searchMessage );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ void Core::Entity::Player::updateSql()
|
|||
stmt->setDouble( 20, m_pos.x );
|
||||
stmt->setDouble( 21, m_pos.y );
|
||||
stmt->setDouble( 22, m_pos.z );
|
||||
stmt->setDouble( 23, getRotation() );
|
||||
stmt->setDouble( 23, getRot() );
|
||||
|
||||
stmt->setInt( 24, m_prevZoneType ); // OTerritoryType
|
||||
stmt->setInt( 25, m_prevZoneId ); // OTerritoryId
|
||||
|
|
|
@ -70,3 +70,4 @@ else()
|
|||
endif()
|
||||
|
||||
target_link_libraries( sapphire_zone ${Boost_LIBRARIES} )
|
||||
cotire( sapphire_zone )
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <common/Common.h>
|
||||
|
||||
#include "Actor/Player.h"
|
||||
#include "Forwards.h"
|
||||
|
||||
namespace Core {
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "Script/NativeScriptMgr.h"
|
||||
|
||||
#include "Actor/Player.h"
|
||||
#include "Actor/BattleNpc.h"
|
||||
#include "Actor/EventNpc.h"
|
||||
#include "Actor/EventObject.h"
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/InstanceContent.h"
|
||||
|
@ -54,7 +53,6 @@ Core::DebugCommandHandler::DebugCommandHandler()
|
|||
registerCommand( "replay", &DebugCommandHandler::replay, "Replays a saved capture folder.", 1 );
|
||||
registerCommand( "nudge", &DebugCommandHandler::nudge, "Nudges you forward/up/down.", 1 );
|
||||
registerCommand( "info", &DebugCommandHandler::serverInfo, "Show server info.", 0 );
|
||||
registerCommand( "unlock", &DebugCommandHandler::unlockCharacter, "Unlock character.", 1 );
|
||||
registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 );
|
||||
registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 );
|
||||
registerCommand( "instance", &DebugCommandHandler::instance, "Instance utilities", 1 );
|
||||
|
@ -173,13 +171,13 @@ void Core::DebugCommandHandler::set( char * data, Entity::Player& player, boost:
|
|||
}
|
||||
|
||||
if( subCommand == "pos" )
|
||||
player.setPosition( static_cast< float >( posX ),
|
||||
static_cast< float >( posY ),
|
||||
static_cast< float >( posZ ) );
|
||||
player.setPos( static_cast< float >( posX ),
|
||||
static_cast< float >( posY ),
|
||||
static_cast< float >( posZ ) );
|
||||
else
|
||||
player.setPosition( player.getPos().x + static_cast< float >( posX ),
|
||||
player.getPos().y + static_cast< float >( posY ),
|
||||
player.getPos().z + static_cast< float >( posZ ) );
|
||||
player.setPos( player.getPos().x + static_cast< float >( posX ),
|
||||
player.getPos().y + static_cast< float >( posY ),
|
||||
player.getPos().z + static_cast< float >( posZ ) );
|
||||
|
||||
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorSetPos >
|
||||
setActorPosPacket( player.getId() );
|
||||
|
@ -302,6 +300,14 @@ void Core::DebugCommandHandler::set( char * data, Entity::Player& player, boost:
|
|||
|
||||
player.sendDebug( "MSQ Guide updated " );
|
||||
}
|
||||
else if( subCommand == "weatheroverride" || subCommand == "wo" )
|
||||
{
|
||||
uint32_t weatherId;
|
||||
|
||||
sscanf( params.c_str(), "%d", &weatherId );
|
||||
|
||||
player.getCurrentZone()->setWeatherOverride( static_cast< Common::Weather >( weatherId ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendUrgent( subCommand + " is not a valid SET command." );
|
||||
|
@ -354,43 +360,6 @@ void Core::DebugCommandHandler::add( char * data, Entity::Player& player, boost:
|
|||
player.addTitle( titleId );
|
||||
player.sendNotice( "Added title (ID: " + std::to_string( titleId ) + ")" );
|
||||
}
|
||||
else if( subCommand == "spawn" )
|
||||
{
|
||||
int32_t model, name;
|
||||
|
||||
sscanf( params.c_str(), "%d %d", &model, &name );
|
||||
|
||||
auto pBNpc = Entity::make_BattleNpc( model, name, player.getPos() );
|
||||
|
||||
auto pZone = player.getCurrentZone();
|
||||
pBNpc->setCurrentZone( pZone );
|
||||
pZone->pushActor( pBNpc );
|
||||
|
||||
}
|
||||
else if( subCommand == "sspawn" )
|
||||
{
|
||||
int32_t model, name, count, distCoefficient, i;
|
||||
|
||||
sscanf( params.c_str(), "%d %d %d %d", &model, &name, &count, &distCoefficient );
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
Common::FFXIVARR_POSITION3 posC = player.getPos();
|
||||
std::mt19937 gen( rand() * 1000 );
|
||||
std::uniform_int_distribution< int > dis( distCoefficient * -1, distCoefficient );
|
||||
|
||||
posC.x += dis( gen );
|
||||
posC.z += dis( gen );
|
||||
|
||||
Entity::BattleNpcPtr pBNpc( new Entity::BattleNpc( model, name, posC ) );
|
||||
|
||||
auto pZone = player.getCurrentZone();
|
||||
pBNpc->setCurrentZone( pZone );
|
||||
pZone->pushActor( pBNpc );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if( subCommand == "op" )
|
||||
{
|
||||
// temporary research packet
|
||||
|
@ -399,33 +368,6 @@ void Core::DebugCommandHandler::add( char * data, Entity::Player& player, boost:
|
|||
auto pPe = Network::Packets::make_GamePacket( opcode, 0x30, player.getId(), player.getId() );
|
||||
player.queuePacket( pPe );
|
||||
}
|
||||
else if( subCommand == "eventnpc-self" )
|
||||
{
|
||||
int32_t id;
|
||||
|
||||
sscanf( params.c_str(), "%d", &id );
|
||||
|
||||
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcNpcSpawn > spawnPacket( player.getId() );
|
||||
spawnPacket.data().type = 3;
|
||||
spawnPacket.data().pos = player.getPos();
|
||||
spawnPacket.data().rotation = player.getRotation();
|
||||
spawnPacket.data().bNPCBase = id;
|
||||
spawnPacket.data().bNPCName = id;
|
||||
spawnPacket.data().targetId = player.getId();
|
||||
player.queuePacket( spawnPacket );
|
||||
}
|
||||
else if( subCommand == "eventnpc" )
|
||||
{
|
||||
int32_t id;
|
||||
|
||||
sscanf( params.c_str(), "%d", &id );
|
||||
|
||||
auto pENpc = Entity::make_EventNpc( id, player.getPos(), player.getRotation() );
|
||||
|
||||
auto pZone = player.getCurrentZone();
|
||||
pENpc->setCurrentZone( pZone );
|
||||
pZone->pushActor( pENpc );
|
||||
}
|
||||
else if( subCommand == "actrl" )
|
||||
{
|
||||
|
||||
|
@ -507,7 +449,7 @@ void Core::DebugCommandHandler::get( char * data, Entity::Player& player, boost:
|
|||
std::to_string( player.getPos().x ) + "\n" +
|
||||
std::to_string( player.getPos().y ) + "\n" +
|
||||
std::to_string( player.getPos().z ) + "\n" +
|
||||
std::to_string( player.getRotation() ) + "\nMapId: " +
|
||||
std::to_string( player.getRot() ) + "\nMapId: " +
|
||||
std::to_string( map_id ) + "\nZoneID: " +
|
||||
std::to_string(player.getCurrentZone()->getTerritoryId() ) + "\n" );
|
||||
}
|
||||
|
@ -612,7 +554,7 @@ void Core::DebugCommandHandler::nudge( char * data, Entity::Player& player, boos
|
|||
}
|
||||
else
|
||||
{
|
||||
float angle = player.getRotation() + ( PI / 2 );
|
||||
float angle = player.getRot() + ( PI / 2 );
|
||||
pos.x -= offset * cos( angle );
|
||||
pos.z += offset * sin( angle );
|
||||
player.sendNotice( "nudge: Placing forward " + std::to_string( offset ) + " yalms" );
|
||||
|
@ -624,23 +566,18 @@ void Core::DebugCommandHandler::nudge( char * data, Entity::Player& player, boos
|
|||
setActorPosPacket.data().x = player.getPos().x;
|
||||
setActorPosPacket.data().y = player.getPos().y;
|
||||
setActorPosPacket.data().z = player.getPos().z;
|
||||
setActorPosPacket.data().r16 = Math::Util::floatToUInt16Rot( player.getRotation() );
|
||||
setActorPosPacket.data().r16 = Math::Util::floatToUInt16Rot( player.getRot() );
|
||||
player.queuePacket( setActorPosPacket );
|
||||
}
|
||||
}
|
||||
|
||||
void Core::DebugCommandHandler::serverInfo( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
|
||||
{
|
||||
player.sendDebug( "SapphireServer " + Version::VERSION + "\nRev: " + Version::GIT_HASH );
|
||||
player.sendDebug( "SapphireZone " + Version::VERSION + "\nRev: " + Version::GIT_HASH );
|
||||
player.sendDebug( "Compiled: " __DATE__ " " __TIME__ );
|
||||
player.sendDebug( "Sessions: " + std::to_string( g_framework.getServerZone().getSessionCount() ) );
|
||||
}
|
||||
|
||||
void Core::DebugCommandHandler::unlockCharacter( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
|
||||
{
|
||||
player.unlock();
|
||||
}
|
||||
|
||||
void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boost::shared_ptr< DebugCommand > command )
|
||||
{
|
||||
std::string subCommand;
|
||||
|
@ -776,51 +713,58 @@ void Core::DebugCommandHandler::instance( char* data, Entity::Player &player, bo
|
|||
}
|
||||
else if( subCommand == "set" )
|
||||
{
|
||||
uint32_t instanceId;
|
||||
uint32_t index;
|
||||
uint32_t value;
|
||||
sscanf( params.c_str(), "%d %d %d", &instanceId, &index, &value );
|
||||
sscanf( params.c_str(), "%d %d", &index, &value );
|
||||
|
||||
auto pInstance = g_framework.getTerritoryMgr().getInstanceZonePtr( instanceId );
|
||||
if( !pInstance )
|
||||
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() );
|
||||
if( !instance )
|
||||
return;
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( pInstance );
|
||||
|
||||
instance->setVar( static_cast< uint8_t >( index ), static_cast< uint8_t >( value ) );
|
||||
}
|
||||
else if( subCommand == "objupdate" )
|
||||
{
|
||||
uint32_t objId;
|
||||
|
||||
sscanf( params.c_str(), "%d", &objId );
|
||||
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
auto obj = instance->getInstanceObject( objId );
|
||||
if( !obj )
|
||||
return;
|
||||
|
||||
instance->updateInstanceObj( obj );
|
||||
}
|
||||
else if( subCommand == "objstate" )
|
||||
{
|
||||
uint32_t objId;
|
||||
char objName[128];
|
||||
uint8_t state;
|
||||
|
||||
sscanf( params.c_str(), "%d %hhu", &objId, &state );
|
||||
sscanf( params.c_str(), "%s %hhu", objName, &state );
|
||||
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
auto obj = instance->getInstanceObject( objId );
|
||||
auto obj = instance->getEObjByName( objName );
|
||||
if( !obj )
|
||||
return;
|
||||
|
||||
obj->setState( state );
|
||||
}
|
||||
else if( subCommand == "seq" )
|
||||
{
|
||||
uint8_t seq;
|
||||
|
||||
sscanf( params.c_str(), "%hhu", &seq );
|
||||
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
instance->setSequence( seq );
|
||||
}
|
||||
else if( subCommand == "branch" )
|
||||
{
|
||||
uint8_t branch;
|
||||
|
||||
sscanf( params.c_str(), "%hhu", &branch );
|
||||
|
||||
auto instance = boost::dynamic_pointer_cast< InstanceContent >( player.getCurrentZone() );
|
||||
if( !instance )
|
||||
return;
|
||||
|
||||
instance->setBranch( branch );
|
||||
}
|
||||
else if( subCommand == "festival" )
|
||||
{
|
||||
uint32_t festivalId;
|
||||
|
|
|
@ -168,3 +168,13 @@ void Core::Event::Director::setDirectorUI8JH( uint8_t value )
|
|||
{
|
||||
m_unionData.ui8lh.UI8JH = value;
|
||||
}
|
||||
|
||||
void Core::Event::Director::setDirectorBranch( uint8_t value )
|
||||
{
|
||||
m_branch = value;
|
||||
}
|
||||
|
||||
void Core::Event::Director::setDirectorSequence( uint8_t value )
|
||||
{
|
||||
m_sequence = value;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@ public:
|
|||
void setDirectorUI8JL( uint8_t value );
|
||||
void setDirectorUI8JH( uint8_t value );
|
||||
|
||||
void setDirectorSequence( uint8_t value );
|
||||
void setDirectorBranch( uint8_t value );
|
||||
|
||||
private:
|
||||
/*! Id of the content of the director */
|
||||
uint16_t m_contentId;
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace Core {
|
|||
SpecialShop = 0x001B,
|
||||
BahamutGuide = 0x001C,
|
||||
FcTalk = 0x001F,
|
||||
ICDirector = 0x8003,
|
||||
};
|
||||
|
||||
using SceneReturnCallback = std::function< void( Entity::Player&, uint32_t, uint16_t, uint16_t, uint16_t ) > ;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include <common/Common.h>
|
||||
#include <common/Exd/ExdDataGenerated.h>
|
||||
|
||||
#include "Framework.h"
|
||||
#include "EventHelper.h"
|
||||
#include "EventHandler.h"
|
||||
|
||||
#include <boost/range/algorithm/remove_if.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
extern Core::Framework g_framework;
|
||||
|
||||
|
||||
using namespace Core::Common;
|
||||
|
||||
std::string Core::Event::getEventName( uint32_t eventId )
|
||||
|
@ -54,6 +55,15 @@ std::string Core::Event::getEventName( uint32_t eventId )
|
|||
return "Aetheryte";
|
||||
return "Aethernet";
|
||||
}
|
||||
case Event::EventHandler::EventHandlerType::ICDirector:
|
||||
{
|
||||
auto contentInfo = g_framework.getExdDataGen().get< Core::Data::InstanceContent >( eventId & 0xFFFF );
|
||||
std::string name = contentInfo->name;
|
||||
|
||||
name.erase( boost::remove_if( name, boost::is_any_of( "★_ '()[]-\x1a\x1\x2\x1f\x1\x3.:" ) ), name.end() );
|
||||
name[0] = toupper( name[0] );
|
||||
return name;
|
||||
}
|
||||
|
||||
case Event::EventHandler::EventHandlerType::Warp:
|
||||
{
|
||||
|
|
|
@ -34,13 +34,10 @@ namespace Core
|
|||
|
||||
namespace Entity
|
||||
{
|
||||
TYPE_FORWARD( GameObject );
|
||||
TYPE_FORWARD( Actor );
|
||||
TYPE_FORWARD( Chara );
|
||||
TYPE_FORWARD( Player );
|
||||
TYPE_FORWARD( BattleNpc );
|
||||
TYPE_FORWARD( EventNpc );
|
||||
TYPE_FORWARD( BattleNpcTemplate );
|
||||
TYPE_FORWARD( InstanceObject );
|
||||
TYPE_FORWARD( EventObject );
|
||||
}
|
||||
|
||||
namespace Event
|
||||
|
|
|
@ -720,7 +720,7 @@ bool Core::Inventory::load()
|
|||
while( bagRes->next() )
|
||||
{
|
||||
uint16_t storageId = bagRes->getUInt16( 1 );
|
||||
for( uint32_t i = 1; i <= 25; i++ )
|
||||
for( uint32_t i = 1; i <= 35; i++ )
|
||||
{
|
||||
uint64_t uItemId = bagRes->getUInt64( i + 1 );
|
||||
if( uItemId == 0 )
|
||||
|
@ -890,7 +890,7 @@ uint8_t Core::Inventory::getFreeSlotsInBags()
|
|||
uint8_t slots = 0;
|
||||
for( uint8_t container : { 0, 1, 2, 3 } )
|
||||
{
|
||||
slots += 25 - m_inventoryMap[container]->getEntryCount();
|
||||
slots += 34 - m_inventoryMap[container]->getEntryCount();
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ extern Core::Framework g_framework;
|
|||
|
||||
Core::ItemContainer::ItemContainer( uint16_t locationId ) :
|
||||
m_id( locationId ),
|
||||
m_size( 25 )
|
||||
m_size( 35 )
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#include <common/Exd/ExdDataGenerated.h>
|
||||
#include <common/Common.h>
|
||||
|
||||
#include "Actor/Actor.h"
|
||||
#include "Actor/Chara.h"
|
||||
|
||||
#include "Actor/Player.h"
|
||||
|
||||
#include "CalcBattle.h"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define _CALCBATTLE_H
|
||||
|
||||
#include <common/Common.h>
|
||||
#include "Actor/Actor.h"
|
||||
#include "Forwards.h"
|
||||
|
||||
using namespace Core::Entity;
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#include <common/Exd/ExdDataGenerated.h>
|
||||
#include <common/Common.h>
|
||||
|
||||
#include "Actor/Actor.h"
|
||||
#include "Actor/Chara.h"
|
||||
|
||||
#include "Actor/Player.h"
|
||||
|
||||
#include "CalcStats.h"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define _CALCSTATS_H
|
||||
|
||||
#include <common/Common.h>
|
||||
#include "Actor/Actor.h"
|
||||
#include "Forwards.h"
|
||||
|
||||
using namespace Core::Entity;
|
||||
|
||||
|
|
|
@ -45,6 +45,65 @@ using namespace Core::Common;
|
|||
using namespace Core::Network::Packets;
|
||||
using namespace Core::Network::Packets::Server;
|
||||
|
||||
enum ClientTrigger
|
||||
{
|
||||
ToggleSeathe = 0x01,
|
||||
ToggleAutoAttack = 0x02,
|
||||
ChangeTarget = 0x03,
|
||||
|
||||
Dismount = 0x65,
|
||||
|
||||
RemoveStatusEffect = 0x68,
|
||||
CastCancel = 0x69,
|
||||
|
||||
Return = 0xC8, // return dead / accept raise
|
||||
FinishZoning = 0xC9,
|
||||
Teleport = 0xCA,
|
||||
|
||||
MarkPlayer = 0x12D, // Mark player, visible to party only
|
||||
SetTitle = 0x12E,
|
||||
TitleList = 0x12F,
|
||||
|
||||
UpdatedSeenHowTos = 0x133,
|
||||
AllotAttribute = 0x135,
|
||||
|
||||
ClearWaymarks = 0x13A,
|
||||
|
||||
HuntingLogDetails = 0x194,
|
||||
|
||||
Timers = 0x1AB,
|
||||
|
||||
DyeItem = 0x1B5,
|
||||
|
||||
RequestChocoboInventory = 0x1C4,
|
||||
|
||||
Emote = 0x1F4,
|
||||
PersistantEmoteCancel = 0x1F7,
|
||||
PoseChange = 0x1F9,
|
||||
PoseReapply = 0x1FA,
|
||||
PoseCancel = 0x1FB,
|
||||
|
||||
AchievementCrit = 0x202,
|
||||
AchievementComp = 0x203,
|
||||
AchievementCatChat = 0x206,
|
||||
|
||||
|
||||
DirectorInitFinish = 0x321,
|
||||
|
||||
SomeDirectorEvent = 0x328, // unsure what exactly triggers it, starts director when returning to instance though
|
||||
|
||||
EnterTerritoryEventFinished = 0x330,
|
||||
|
||||
AchievementCritReq = 0x3E8,
|
||||
AchievementList = 0x3E9,
|
||||
|
||||
CompanionAction = 0x6A4,
|
||||
CompanionSetBarding = 0x6A5,
|
||||
CompanionActionUnlock = 0x6A6,
|
||||
|
||||
OpenPerformInstrumentUI = 0x71C,
|
||||
};
|
||||
|
||||
void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& inPacket,
|
||||
Entity::Player& player )
|
||||
{
|
||||
|
@ -67,13 +126,13 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
|||
|
||||
switch( commandId )
|
||||
{
|
||||
case 0x01: // Toggle sheathe
|
||||
case ClientTrigger::ToggleSeathe: // Toggle sheathe
|
||||
{
|
||||
if ( param11 == 1 )
|
||||
player.setStance( Entity::Actor::Stance::Active );
|
||||
player.setStance( Entity::Chara::Stance::Active );
|
||||
else
|
||||
{
|
||||
player.setStance( Entity::Actor::Stance::Passive );
|
||||
player.setStance( Entity::Chara::Stance::Passive );
|
||||
player.setAutoattack( false );
|
||||
}
|
||||
|
||||
|
@ -81,12 +140,12 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
|||
|
||||
break;
|
||||
}
|
||||
case 0x02: // Toggle auto-attack
|
||||
case ClientTrigger::ToggleAutoAttack: // Toggle auto-attack
|
||||
{
|
||||
if ( param11 == 1 )
|
||||
{
|
||||
player.setAutoattack( true );
|
||||
player.setStance( Entity::Actor::Stance::Active );
|
||||
player.setStance( Entity::Chara::Stance::Active );
|
||||
}
|
||||
else
|
||||
player.setAutoattack( false );
|
||||
|
@ -95,58 +154,75 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
|||
|
||||
break;
|
||||
}
|
||||
case 0x03: // Change target
|
||||
case ClientTrigger::ChangeTarget: // Change target
|
||||
{
|
||||
|
||||
uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 );
|
||||
player.changeTarget( targetId );
|
||||
break;
|
||||
}
|
||||
case 0x65:
|
||||
case ClientTrigger::Dismount:
|
||||
{
|
||||
player.dismount();
|
||||
break;
|
||||
}
|
||||
case 0x68: // Remove status (clicking it off)
|
||||
case ClientTrigger::RemoveStatusEffect: // Remove status (clicking it off)
|
||||
{
|
||||
// todo: check if status can be removed by client from exd
|
||||
player.removeSingleStatusEffectById( static_cast< uint32_t >( param1 ) );
|
||||
break;
|
||||
}
|
||||
case 0x69: // Cancel cast
|
||||
case ClientTrigger::CastCancel: // Cancel cast
|
||||
{
|
||||
if( player.getCurrentAction() )
|
||||
player.getCurrentAction()->setInterrupted();
|
||||
break;
|
||||
}
|
||||
case 0x12E: // Set player title
|
||||
case ClientTrigger::MarkPlayer: // Mark player
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::SetTitle: // Set player title
|
||||
{
|
||||
player.setTitle( static_cast< uint16_t >( param1 ) );
|
||||
break;
|
||||
}
|
||||
case 0x12F: // Get title list
|
||||
case ClientTrigger::TitleList: // Get title list
|
||||
{
|
||||
ZoneChannelPacket< FFXIVIpcPlayerTitleList > titleListPacket( player.getId() );
|
||||
memcpy( titleListPacket.data().titleList, player.getTitleList(), sizeof( titleListPacket.data().titleList ) );
|
||||
|
||||
player.queuePacket( titleListPacket );
|
||||
player.sendTitleList();
|
||||
break;
|
||||
}
|
||||
case 0x133: // Update howtos seen
|
||||
case ClientTrigger::UpdatedSeenHowTos: // Update howtos seen
|
||||
{
|
||||
uint32_t howToId = static_cast< uint32_t >( param1 );
|
||||
uint32_t howToId = param11;
|
||||
player.updateHowtosSeen( howToId );
|
||||
break;
|
||||
}
|
||||
case 0x1F4: // emote
|
||||
case ClientTrigger::Emote: // emote
|
||||
{
|
||||
uint64_t targetId = player.getTargetId();
|
||||
uint32_t emoteId = inPacket.getValAt< uint32_t >( 0x24 );
|
||||
|
||||
player.sendToInRangeSet( ActorControlPacket144( player.getId(), Emote, emoteId, 0, 0, 0, targetId ) );
|
||||
player.emote( emoteId, targetId );
|
||||
break;
|
||||
}
|
||||
case 0xC8: // return dead
|
||||
case ClientTrigger::PersistantEmoteCancel: // cancel persistant emote
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::PoseChange: // change pose
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::PoseReapply: // reapply pose
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::PoseCancel: // cancel pose
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::Return: // return dead / accept raise
|
||||
{
|
||||
switch ( static_cast < ResurrectType >( param1 ) )
|
||||
{
|
||||
|
@ -162,80 +238,37 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
|||
}
|
||||
|
||||
}
|
||||
case 0xC9: // Finish zoning
|
||||
case ClientTrigger::FinishZoning: // Finish zoning
|
||||
{
|
||||
switch( player.getZoningType() )
|
||||
{
|
||||
case ZoneingType::None:
|
||||
player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01 ), true );
|
||||
break;
|
||||
case ZoneingType::Teleport:
|
||||
player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0, 0, 110 ), true );
|
||||
break;
|
||||
case ZoneingType::Return:
|
||||
case ZoneingType::ReturnDead:
|
||||
{
|
||||
if( player.getStatus() == Entity::Actor::ActorStatus::Dead )
|
||||
{
|
||||
player.resetHp();
|
||||
player.resetMp();
|
||||
player.setStatus( Entity::Actor::ActorStatus::Idle );
|
||||
|
||||
player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x01, 0, 111 ), true );
|
||||
player.sendToInRangeSet( ActorControlPacket142( player.getId(), SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true );
|
||||
}
|
||||
else
|
||||
player.sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x00, 0, 111 ), true );
|
||||
}
|
||||
break;
|
||||
case ZoneingType::FadeIn:
|
||||
break;
|
||||
}
|
||||
|
||||
player.setZoningType( Common::ZoneingType::None );
|
||||
|
||||
player.unsetStateFlag( PlayerStateFlag::BetweenAreas );
|
||||
player.unsetStateFlag( PlayerStateFlag::BetweenAreas1 );
|
||||
player.finishZoning();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xCA: // Teleport
|
||||
case ClientTrigger::Teleport: // Teleport
|
||||
{
|
||||
// TODO: only register this action if enough gil is in possession
|
||||
auto targetAetheryte = g_framework.getExdDataGen().get< Core::Data::Aetheryte >( param11 );
|
||||
|
||||
if( targetAetheryte )
|
||||
{
|
||||
auto fromAetheryte = g_framework.getExdDataGen().get< Core::Data::Aetheryte >( g_framework.getExdDataGen().get< Core::Data::TerritoryType >( player.getZoneId() )->aetheryte );
|
||||
|
||||
// calculate cost - does not apply for favorite points or homepoints neither checks for aether tickets
|
||||
auto cost = static_cast< uint16_t >( ( sqrt( pow( fromAetheryte->aetherstreamX - targetAetheryte->aetherstreamX, 2 ) +
|
||||
pow( fromAetheryte->aetherstreamY - targetAetheryte->aetherstreamY, 2 ) ) / 2 ) + 100 );
|
||||
|
||||
// cap at 999 gil
|
||||
cost = cost > uint16_t{999} ? uint16_t{999} : cost;
|
||||
|
||||
bool insufficientGil = player.getCurrency( Inventory::CurrencyType::Gil ) < cost;
|
||||
// todo: figure out what param1 really does
|
||||
player.queuePacket( ActorControlPacket143( player.getId(), TeleportStart, insufficientGil ? 2 : 0, param11 ) );
|
||||
|
||||
if( !insufficientGil )
|
||||
{
|
||||
auto pActionTeleport = Action::make_ActionTeleport( player.getAsPlayer(), param11, cost );
|
||||
player.setCurrentAction( pActionTeleport );
|
||||
}
|
||||
}
|
||||
player.teleportQuery( param11 );
|
||||
break;
|
||||
}
|
||||
case 0x1B5: // Dye item
|
||||
case ClientTrigger::DyeItem: // Dye item
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 0x321: // Director init finish
|
||||
case ClientTrigger::DirectorInitFinish: // Director init finish
|
||||
{
|
||||
player.getCurrentZone()->onInitDirector( player );
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::SomeDirectorEvent: // Director init finish
|
||||
{
|
||||
player.getCurrentZone()->onSomeDirectorEvent( player );
|
||||
break;
|
||||
}
|
||||
case ClientTrigger::EnterTerritoryEventFinished:// this may still be something else. I think i have seen it elsewhere
|
||||
{
|
||||
player.setOnEnterEventDone( true );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
g_framework.getLogger().debug( "[" + std::to_string( m_pSession->getId() ) + "] Unhandled action: " +
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include "Actor/Player.h"
|
||||
|
||||
#include "Event/EventHelper.h"
|
||||
|
||||
#include "Zone/InstanceContent.h"
|
||||
|
||||
#include "Session.h"
|
||||
#include "Forwards.h"
|
||||
#include "Framework.h"
|
||||
|
@ -40,7 +43,7 @@ void Core::Network::GameConnection::eventHandlerTalk( const Packets::GamePacket&
|
|||
std::string eventName = "onTalk";
|
||||
std::string objName = Event::getEventName( eventId );
|
||||
|
||||
player.sendDebug( "Actor: " +
|
||||
player.sendDebug( "Chara: " +
|
||||
std::to_string( actorId ) + " -> " +
|
||||
std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) +
|
||||
" \neventId: " +
|
||||
|
@ -52,8 +55,13 @@ void Core::Network::GameConnection::eventHandlerTalk( const Packets::GamePacket&
|
|||
player.sendDebug( "Calling: " + objName + "." + eventName );
|
||||
player.eventStart( actorId, eventId, Event::EventHandler::Talk, 0, 0 );
|
||||
|
||||
if( !g_framework.getScriptMgr().onTalk( player, actorId, eventId ) &&
|
||||
eventType == Event::EventHandler::EventHandlerType::Quest )
|
||||
|
||||
if( auto instance = player.getCurrentInstance() )
|
||||
{
|
||||
instance->onTalk( player, eventId, actorId );
|
||||
}
|
||||
else if( !g_framework.getScriptMgr().onTalk( player, actorId, eventId ) &&
|
||||
eventType == Event::EventHandler::EventHandlerType::Quest )
|
||||
{
|
||||
auto questInfo = g_framework.getExdDataGen().get< Core::Data::Quest >( eventId );
|
||||
if( questInfo )
|
||||
|
@ -75,7 +83,7 @@ void Core::Network::GameConnection::eventHandlerEmote( const Packets::GamePacket
|
|||
std::string eventName = "onEmote";
|
||||
std::string objName = Event::getEventName( eventId );
|
||||
|
||||
player.sendDebug( "Actor: " +
|
||||
player.sendDebug( "Chara: " +
|
||||
std::to_string( actorId ) + " -> " +
|
||||
std::to_string( Event::mapEventActorToRealActor( static_cast< uint32_t >( actorId ) ) ) +
|
||||
" \neventId: " +
|
||||
|
@ -155,9 +163,22 @@ void Core::Network::GameConnection::eventHandlerEnterTerritory( const Packets::G
|
|||
|
||||
player.sendDebug( "Calling: " + objName + "." + eventName + " - " + std::to_string( eventId ) );
|
||||
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() );
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId(), 0 );
|
||||
|
||||
g_framework.getScriptMgr().onEnterTerritory( player, eventId, param1, param2 );
|
||||
if( auto instance = player.getCurrentInstance() )
|
||||
{
|
||||
// param2 of eventStart
|
||||
// 0 = default state?
|
||||
// 1 = restore state?
|
||||
// (^ Mordred: Nope, i don't think thats it )
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId(), instance->getDirectorId() & 0xFFFF );
|
||||
instance->onEnterTerritory( player, eventId, param1, param2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
player.eventStart( player.getId(), eventId, Event::EventHandler::EnterTerritory, 0, player.getZoneId() );
|
||||
g_framework.getScriptMgr().onEnterTerritory( player, eventId, param1, param2 );
|
||||
}
|
||||
|
||||
player.checkEvent( eventId );
|
||||
}
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
#include <common/Logging/Logger.h>
|
||||
#include <common/Network/PacketContainer.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include "Network/GameConnection.h"
|
||||
|
||||
#include "Session.h"
|
||||
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/ZonePosition.h"
|
||||
|
@ -141,7 +148,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
player.sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetPlayer->getInRangeActors();
|
||||
for ( auto actor : inRange )
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
targetPlayer->spawn( actor->getAsPlayer() );
|
||||
|
@ -154,7 +161,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
player.sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetPlayer->getInRangeActors();
|
||||
for ( auto actor : inRange )
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
targetPlayer->spawn( actor->getAsPlayer() );
|
||||
|
@ -167,7 +174,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
player.sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
|
||||
targetPlayer->spawn( targetPlayer );
|
||||
auto inRange = targetActor->getInRangeActors();
|
||||
for ( auto actor : inRange )
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
targetPlayer->despawn( actor->getAsPlayer() );
|
||||
targetPlayer->spawn( actor->getAsPlayer() );
|
||||
|
@ -182,18 +189,17 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Weather:
|
||||
{
|
||||
targetPlayer->getCurrentZone()->setWeatherOverride( param1 );
|
||||
targetPlayer->getCurrentZone()->setWeatherOverride( static_cast< Common::Weather >( param1 ) );
|
||||
player.sendNotice( "Weather in Zone \"" + targetPlayer->getCurrentZone()->getName() + "\" of " +
|
||||
targetPlayer->getName() + " set in range." );
|
||||
break;
|
||||
}
|
||||
case GmCommand::Call:
|
||||
{
|
||||
if ( targetPlayer->getZoneId() != player.getZoneId() )
|
||||
if( targetPlayer->getZoneId() != player.getZoneId() )
|
||||
targetPlayer->setZone( player.getZoneId() );
|
||||
|
||||
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z,
|
||||
player.getRotation() );
|
||||
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, player.getRot() );
|
||||
player.sendNotice( "Calling " + targetPlayer->getName() );
|
||||
break;
|
||||
}
|
||||
|
@ -218,7 +224,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Kill:
|
||||
{
|
||||
targetActor->takeDamage( 9999999 );
|
||||
targetActor->getAsChara()->takeDamage( 9999999 );
|
||||
player.sendNotice( "Killed " + std::to_string( targetActor->getId() ) );
|
||||
break;
|
||||
}
|
||||
|
@ -268,10 +274,10 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Inv:
|
||||
{
|
||||
if ( targetActor->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill )
|
||||
targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityNone );
|
||||
if( targetActor->getAsChara()->getInvincibilityType() == Common::InvincibilityType::InvincibilityRefill )
|
||||
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityNone );
|
||||
else
|
||||
targetActor->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill );
|
||||
targetActor->getAsChara()->setInvincibilityType( Common::InvincibilityType::InvincibilityRefill );
|
||||
|
||||
player.sendNotice( "Invincibility for " + targetPlayer->getName() +
|
||||
" was switched." );
|
||||
|
@ -279,11 +285,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Orchestrion:
|
||||
{
|
||||
if ( param1 == 1 )
|
||||
if( param1 == 1 )
|
||||
{
|
||||
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 );
|
||||
|
||||
player.sendNotice( "All Songs for " + targetPlayer->getName() +
|
||||
|
@ -326,7 +332,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
{
|
||||
uint32_t gil = targetPlayer->getCurrency( 1 );
|
||||
|
||||
if ( gil < param1 )
|
||||
if( gil < param1 )
|
||||
{
|
||||
player.sendUrgent( "Player does not have enough Gil(" + std::to_string( gil ) + ")" );
|
||||
}
|
||||
|
@ -381,11 +387,11 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::Aetheryte:
|
||||
{
|
||||
if ( param1 == 0 )
|
||||
if( param1 == 0 )
|
||||
{
|
||||
if ( param2 == 0 )
|
||||
if( param2 == 0 )
|
||||
{
|
||||
for ( uint8_t i = 0; i < 255; i++ )
|
||||
for( uint8_t i = 0; i < 255; i++ )
|
||||
targetActor->getAsPlayer()->registerAetheryte( i );
|
||||
|
||||
player.sendNotice( "All Aetherytes for " + targetPlayer->getName() +
|
||||
|
@ -421,7 +427,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
player.sendUrgent( "No zone instance found for " + std::to_string( param1 ) );
|
||||
break;
|
||||
}
|
||||
targetPlayer->setPosition( targetPlayer->getPos() );
|
||||
targetPlayer->setPos( targetPlayer->getPos() );
|
||||
targetPlayer->performZoning( param1, targetPlayer->getPos(), 0 );
|
||||
player.sendNotice( targetPlayer->getName() + " was warped to zone " + std::to_string( param1 ) + " (" + pZone->getName() + ")" );
|
||||
}
|
||||
|
@ -429,23 +435,23 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
}
|
||||
case GmCommand::TeriInfo:
|
||||
{
|
||||
auto pCurrentZone = player.getCurrentZone();
|
||||
player.sendNotice( "ZoneId: " + std::to_string( player.getZoneId() ) + "\nName: " +
|
||||
player.getCurrentZone()->getName() + "\nInternalName: " +
|
||||
player.getCurrentZone()->getInternalName() + "\nPopCount: " +
|
||||
std::to_string( player.getCurrentZone()->getPopCount() ) +
|
||||
"\nCurrentWeather:" + std::to_string( player.getCurrentZone()->getCurrentWeather() ) +
|
||||
"\nNextWeather:" + std::to_string( player.getCurrentZone()->getNextWeather() ) );
|
||||
pCurrentZone->getName() + "\nInternalName: " +
|
||||
pCurrentZone->getInternalName() + "\nPopCount: " +
|
||||
std::to_string( pCurrentZone->getPopCount() ) +
|
||||
"\nCurrentWeather:" + std::to_string( static_cast< uint8_t >( pCurrentZone->getCurrentWeather() ) ) +
|
||||
"\nNextWeather:" + std::to_string( static_cast< uint8_t >( pCurrentZone->getNextWeather() ) ) );
|
||||
break;
|
||||
}
|
||||
case GmCommand::Jump:
|
||||
{
|
||||
|
||||
auto inRange = player.getInRangeActors();
|
||||
for( auto actor : inRange )
|
||||
{
|
||||
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
|
||||
targetActor->getRotation() );
|
||||
}
|
||||
|
||||
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
|
||||
targetActor->getRot() );
|
||||
|
||||
player.sendNotice( "Jumping to " + targetPlayer->getName() + " in range." );
|
||||
break;
|
||||
}
|
||||
|
@ -468,7 +474,7 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac
|
|||
g_framework.getLogger().debug( player.getName() + " used GM2 commandId: " + std::to_string( commandId ) + ", params: " + param1 );
|
||||
|
||||
auto targetSession = g_framework.getServerZone().getSession( param1 );
|
||||
Core::Entity::ActorPtr targetActor;
|
||||
Core::Entity::CharaPtr targetActor;
|
||||
|
||||
if( targetSession != nullptr )
|
||||
{
|
||||
|
@ -498,11 +504,11 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac
|
|||
{
|
||||
targetPlayer->resetHp();
|
||||
targetPlayer->resetMp();
|
||||
targetPlayer->setStatus( Entity::Actor::ActorStatus::Idle );
|
||||
targetPlayer->setStatus( Entity::Chara::ActorStatus::Idle );
|
||||
|
||||
targetPlayer->sendToInRangeSet( ActorControlPacket143( player.getId(), ZoneIn, 0x01, 0x01, 0, 113 ), true );
|
||||
targetPlayer->sendToInRangeSet( ActorControlPacket142( player.getId(), SetStatus,
|
||||
static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true );
|
||||
static_cast< uint8_t >( Entity::Chara::ActorStatus::Idle ) ), true );
|
||||
player.sendNotice( "Raised " + targetPlayer->getName() );
|
||||
break;
|
||||
}
|
||||
|
@ -513,17 +519,16 @@ void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPac
|
|||
player.setZone( targetPlayer->getZoneId() );
|
||||
}
|
||||
player.changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
|
||||
targetActor->getRotation() );
|
||||
targetActor->getRot() );
|
||||
player.sendNotice( "Jumping to " + targetPlayer->getName() );
|
||||
break;
|
||||
}
|
||||
case GmCommand::Call:
|
||||
{
|
||||
if ( targetPlayer->getZoneId() != player.getZoneId() )
|
||||
if( targetPlayer->getZoneId() != player.getZoneId() )
|
||||
targetPlayer->setZone( player.getZoneId() );
|
||||
|
||||
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z,
|
||||
player.getRotation() );
|
||||
targetPlayer->changePosition( player.getPos().x, player.getPos().y, player.getPos().z, player.getRot() );
|
||||
player.sendNotice( "Calling " + targetPlayer->getName() );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include <common/Network/PacketContainer.h>
|
||||
#include <common/Network/PacketDef/Chat/ServerChatDef.h>
|
||||
#include <common/Database/DatabaseDef.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <unordered_map>
|
||||
#include "Network/GameConnection.h"
|
||||
|
||||
#include "Zone/TerritoryMgr.h"
|
||||
|
@ -181,13 +182,13 @@ void Core::Network::GameConnection::updatePositionHandler( const Packets::GamePa
|
|||
( player.getPos().y != inPacket.getValAt< float >( 0x30 ) ) ||
|
||||
( player.getPos().z != inPacket.getValAt< float >( 0x34 ) ) )
|
||||
bPosChanged = true;
|
||||
if( !bPosChanged && player.getRotation() == inPacket.getValAt< float >( 0x20 ) )
|
||||
if( !bPosChanged && player.getRot() == inPacket.getValAt< float >( 0x20 ) )
|
||||
return;
|
||||
|
||||
player.setRotation( inPacket.getValAt< float >( 0x20 ) );
|
||||
player.setPosition( inPacket.getValAt< float >( 0x2c ),
|
||||
inPacket.getValAt< float >( 0x30 ),
|
||||
inPacket.getValAt< float >( 0x34 ) );
|
||||
player.setRot( inPacket.getValAt< float >( 0x20 ) );
|
||||
player.setPos( inPacket.getValAt< float >( 0x2c ),
|
||||
inPacket.getValAt< float >( 0x30 ),
|
||||
inPacket.getValAt< float >( 0x34 ) );
|
||||
|
||||
if( ( player.getCurrentAction() != nullptr ) && bPosChanged )
|
||||
player.getCurrentAction()->setInterrupted();
|
||||
|
@ -793,16 +794,14 @@ void Core::Network::GameConnection::tellHandler( const Packets::GamePacket& inPa
|
|||
|
||||
auto pTargetPlayer = pSession->getPlayer();
|
||||
|
||||
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) ||
|
||||
pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas1 ) )
|
||||
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BetweenAreas ) )
|
||||
{
|
||||
// send error for player between areas
|
||||
// TODO: implement me
|
||||
return;
|
||||
}
|
||||
|
||||
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) ||
|
||||
pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty1 ) )
|
||||
if( pTargetPlayer->hasStateFlag( PlayerStateFlag::BoundByDuty ) )
|
||||
{
|
||||
// send error for player bound by duty
|
||||
// TODO: implement me
|
||||
|
|
|
@ -80,11 +80,11 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP
|
|||
|
||||
if( !player.actionHasCastTime( action ) )
|
||||
{
|
||||
g_framework.getScriptMgr().onCastFinish( player, targetActor, action );
|
||||
g_framework.getScriptMgr().onCastFinish( player, targetActor->getAsChara(), action );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto pActionCast = Action::make_ActionCast( player.getAsPlayer(), targetActor, action );
|
||||
auto pActionCast = Action::make_ActionCast( player.getAsPlayer(), targetActor->getAsChara(), action );
|
||||
player.setCurrentAction( pActionCast );
|
||||
player.sendDebug( "setCurrentAction()" );
|
||||
player.getCurrentAction()->onStart();
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _DIRECTORPLAYSCENE_H
|
||||
#define _DIRECTORPLAYSCENE_H
|
||||
|
||||
#include <common/Network/GamePacketNew.h>
|
||||
#include "Forwards.h"
|
||||
|
||||
namespace Core {
|
||||
namespace Network {
|
||||
namespace Packets {
|
||||
namespace Server {
|
||||
|
||||
/**
|
||||
* @brief The packet sent to play an event.
|
||||
*/
|
||||
class DirectorPlayScenePacket : public ZoneChannelPacket< FFXIVIpcDirectorPlayScene >
|
||||
{
|
||||
public:
|
||||
DirectorPlayScenePacket( uint32_t playerId,
|
||||
uint64_t actorId,
|
||||
uint32_t eventId,
|
||||
uint16_t scene,
|
||||
uint32_t flags,
|
||||
uint8_t param3,
|
||||
uint32_t param4 = 0,
|
||||
uint32_t param5 = 0 ) :
|
||||
ZoneChannelPacket< FFXIVIpcDirectorPlayScene >( playerId, playerId )
|
||||
{
|
||||
initialize( actorId, eventId, scene, flags, param3, param4, param5 );
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize( uint64_t actorId,
|
||||
uint32_t eventId,
|
||||
uint16_t scene,
|
||||
uint32_t flags,
|
||||
uint8_t param3,
|
||||
uint32_t param4,
|
||||
uint32_t param5 )
|
||||
{
|
||||
m_data.actorId = actorId;
|
||||
m_data.eventId = eventId;
|
||||
m_data.scene = scene;
|
||||
m_data.flags = flags;
|
||||
m_data.param3 = param3;
|
||||
m_data.param4 = param4;
|
||||
m_data.param5 = param5;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*_EVENTPLAY_H*/
|
|
@ -20,10 +20,11 @@ public:
|
|||
uint32_t eventId,
|
||||
uint8_t param1 = 0,
|
||||
uint8_t param2 = 0,
|
||||
uint32_t param3 = 0 ) :
|
||||
uint32_t param3 = 0,
|
||||
uint32_t contentId = 0 ) :
|
||||
ZoneChannelPacket< FFXIVIpcEventStart >( playerId, playerId )
|
||||
{
|
||||
initialize( actorId, eventId, param1, param2, param3 );
|
||||
initialize( actorId, eventId, param1, param2, param3, contentId );
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -31,13 +32,15 @@ private:
|
|||
uint32_t eventId,
|
||||
uint8_t param1,
|
||||
uint8_t param2,
|
||||
uint32_t param3 )
|
||||
uint32_t param3,
|
||||
uint32_t contentId )
|
||||
{
|
||||
m_data.actorId = actorId;
|
||||
m_data.eventId = eventId;
|
||||
m_data.param1 = param1;
|
||||
m_data.param2 = param2;
|
||||
m_data.param3 = param3;
|
||||
m_data.contentId = contentId;
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -21,17 +21,17 @@ class MoveActorPacket :
|
|||
public ZoneChannelPacket< FFXIVIpcActorMove >
|
||||
{
|
||||
public:
|
||||
MoveActorPacket( Entity::Actor& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) :
|
||||
MoveActorPacket( Entity::Chara& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 ) :
|
||||
ZoneChannelPacket< FFXIVIpcActorMove >( actor.getId(), actor.getId() )
|
||||
{
|
||||
initialize( actor, unk1, unk2, unk3, unk4 );
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize( Entity::Actor& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 )
|
||||
void initialize( Entity::Chara& actor, uint8_t unk1, uint8_t unk2, uint8_t unk3, uint16_t unk4 )
|
||||
{
|
||||
|
||||
m_data.rotation = Math::Util::floatToUInt8Rot( actor.getRotation() );
|
||||
m_data.rotation = Math::Util::floatToUInt8Rot( actor.getRot() );
|
||||
m_data.unknown_1 = unk1;
|
||||
m_data.unknown_2 = unk2;
|
||||
m_data.unknown_3 = unk3;
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace Server {
|
|||
m_data.pos.x = player.getPos().x;
|
||||
m_data.pos.y = player.getPos().y;
|
||||
m_data.pos.z = player.getPos().z;
|
||||
m_data.rotation = Math::Util::floatToUInt16Rot( player.getRotation() );
|
||||
m_data.rotation = Math::Util::floatToUInt16Rot( player.getRot() );
|
||||
|
||||
|
||||
m_data.title = player.getTitle();
|
||||
|
@ -76,7 +76,7 @@ namespace Server {
|
|||
//m_data.u23 = 0x04;
|
||||
//m_data.u24 = 256;
|
||||
m_data.state = static_cast< uint8_t >( player.getStatus() );
|
||||
m_data.type = 1;
|
||||
m_data.modelType = player.getModelType();
|
||||
if( target.getId() == player.getId() )
|
||||
{
|
||||
m_data.spawnIndex = 0x00;
|
||||
|
@ -84,28 +84,31 @@ namespace Server {
|
|||
else
|
||||
{
|
||||
m_data.spawnIndex = target.getSpawnIdForActorId( player.getId() );
|
||||
|
||||
if( !target.isActorSpawnIdValid( m_data.spawnIndex ) )
|
||||
return;
|
||||
}
|
||||
// 0x20 == spawn hidden to be displayed by the spawneffect control
|
||||
m_data.displayFlags = player.getStance();
|
||||
|
||||
if( player.getZoningType() != Common::ZoneingType::None )
|
||||
{
|
||||
m_data.displayFlags |= Entity::Actor::DisplayFlags::Invisible;
|
||||
m_data.displayFlags |= Entity::Chara::DisplayFlags::Invisible;
|
||||
}
|
||||
|
||||
if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideHead )
|
||||
{
|
||||
m_data.displayFlags |= Entity::Actor::DisplayFlags::HideHead;
|
||||
m_data.displayFlags |= Entity::Chara::DisplayFlags::HideHead;
|
||||
}
|
||||
|
||||
if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideWeapon )
|
||||
{
|
||||
m_data.displayFlags |= Entity::Actor::DisplayFlags::HideWeapon;
|
||||
m_data.displayFlags |= Entity::Chara::DisplayFlags::HideWeapon;
|
||||
}
|
||||
|
||||
if( player.getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::Visor )
|
||||
{
|
||||
m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor;
|
||||
m_data.displayFlags |= Entity::Chara::DisplayFlags::Visor;
|
||||
}
|
||||
|
||||
m_data.currentMount = player.getCurrentMount();
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
PlayerStateFlagsPacket( Entity::Player& player, std::vector< Common::PlayerStateFlag > flags ) :
|
||||
ZoneChannelPacket< FFXIVIpcPlayerStateFlags >( player.getId(), player.getId() )
|
||||
{
|
||||
uint8_t newFlags[7];
|
||||
memset( newFlags, 0, 7 );
|
||||
uint8_t newFlags[12];
|
||||
memset( newFlags, 0, 12 );
|
||||
|
||||
for( auto& flag : flags )
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ public:
|
|||
private:
|
||||
void initialize( const uint8_t* flags )
|
||||
{
|
||||
memcpy( m_data.flags, flags, 7 );
|
||||
memcpy( m_data.flags, flags, 12 );
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define _UPDATEHPMPTP_H
|
||||
|
||||
#include <common/Network/GamePacketNew.h>
|
||||
#include <Actor/Actor.h>
|
||||
#include <Actor/Chara.h>
|
||||
#include "Forwards.h"
|
||||
|
||||
namespace Core {
|
||||
|
@ -17,14 +17,14 @@ class UpdateHpMpTpPacket :
|
|||
public ZoneChannelPacket< FFXIVIpcUpdateHpMpTp >
|
||||
{
|
||||
public:
|
||||
UpdateHpMpTpPacket( Entity::Actor& actor ) :
|
||||
UpdateHpMpTpPacket( Entity::Chara& actor ) :
|
||||
ZoneChannelPacket< FFXIVIpcUpdateHpMpTp >( actor.getId(), actor.getId() )
|
||||
{
|
||||
initialize( actor );
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize( Entity::Actor& actor )
|
||||
void initialize( Entity::Chara& actor )
|
||||
{
|
||||
m_data.hp = actor.getHp();
|
||||
m_data.mp = actor.getMp();
|
||||
|
|
|
@ -4,11 +4,7 @@
|
|||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
|
||||
#include <Actor/Actor.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <StatusEffect/StatusEffect.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
#include "Forwards.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT __declspec( dllexport )
|
||||
|
@ -53,14 +49,14 @@ public:
|
|||
ScriptObject( effectId, typeid( StatusEffectScript ).hash_code() )
|
||||
{ }
|
||||
|
||||
virtual void onTick( Entity::Actor& actor ) { }
|
||||
virtual void onApply( Entity::Actor& actor ) { }
|
||||
virtual void onRemove( Entity::Actor& actor ) { }
|
||||
virtual void onExpire( Entity::Actor& actor ) { }
|
||||
virtual void onPlayerCollision( Entity::Actor& actor, Entity::Actor& actorHit ) { }
|
||||
virtual void onPlayerFinishCast( Entity::Actor& actor ) { }
|
||||
virtual void onPlayerDamaged( Entity::Actor& actor ) { }
|
||||
virtual void onPlayerDeath( Entity::Actor& actor ) { }
|
||||
virtual void onTick( Entity::Chara& actor ) { }
|
||||
virtual void onApply( Entity::Chara& actor ) { }
|
||||
virtual void onRemove( Entity::Chara& actor ) { }
|
||||
virtual void onExpire( Entity::Chara& actor ) { }
|
||||
virtual void onPlayerCollision( Entity::Chara& actor, Entity::Chara& actorHit ) { }
|
||||
virtual void onPlayerFinishCast( Entity::Chara& actor ) { }
|
||||
virtual void onPlayerDamaged( Entity::Chara& actor ) { }
|
||||
virtual void onPlayerDeath( Entity::Chara& actor ) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -71,9 +67,9 @@ public:
|
|||
ScriptObject( abilityId, typeid( ActionScript ).hash_code() )
|
||||
{ }
|
||||
|
||||
virtual void onStart( Entity::Actor& sourceActor, Entity::Actor& targetActor ) { }
|
||||
virtual void onCastFinish( Entity::Player& player, Entity::Actor& targetActor ) { }
|
||||
virtual void onInterrupt( Entity::Actor& sourceActor/*, Core::Entity::Actor targetActor*/ ) { }
|
||||
virtual void onStart( Entity::Chara& sourceActor, Entity::Chara& targetActor ) { }
|
||||
virtual void onCastFinish( Entity::Player& player, Entity::Chara& targetActor ) { }
|
||||
virtual void onInterrupt( Entity::Chara& sourceActor/*, Core::Entity::Chara targetActor*/ ) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,7 +83,7 @@ public:
|
|||
virtual void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) { }
|
||||
virtual void onNpcKill( uint32_t npcId, Entity::Player& player ) { }
|
||||
virtual void onEmote( uint64_t actorId, uint32_t eventId, uint32_t emoteId, Entity::Player& player ) { }
|
||||
virtual void onEnterZone( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { }
|
||||
virtual void onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { }
|
||||
virtual void onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) { }
|
||||
virtual void onOutsideRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z ) { }
|
||||
virtual void onEventItem( Entity::Player& player, uint32_t eventItemId, uint32_t eventId, uint32_t castTime, uint64_t targetId ) { }
|
||||
|
@ -117,11 +113,12 @@ class InstanceContentScript : public ScriptObject
|
|||
{
|
||||
public:
|
||||
explicit InstanceContentScript( uint32_t instanceContentId ) :
|
||||
ScriptObject( instanceContentId, typeid( InstanceContentScript ).hash_code() )
|
||||
ScriptObject( uint32_t{ 0x8003 } << 16 | instanceContentId, typeid( InstanceContentScript ).hash_code() )
|
||||
{ }
|
||||
|
||||
virtual void onInit( InstanceContent& instance ) { }
|
||||
virtual void onUpdate( InstanceContent& instance, uint32_t currTime ) { }
|
||||
virtual void onInit( InstanceContentPtr instance ) { }
|
||||
virtual void onUpdate( InstanceContentPtr instance, uint32_t currTime ) { }
|
||||
virtual void onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "NativeScriptMgr.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <common/Crypt/md5.h>
|
||||
|
||||
namespace Core {
|
||||
namespace Scripting {
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <common/Crypt/md5.h>
|
||||
|
||||
#include "ScriptLoader.h"
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <winbase.h>
|
||||
typedef HMODULE ModuleHandle;
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
|
|
@ -9,10 +9,9 @@
|
|||
#include <common/Config/XMLConfig.h>
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
#include "Zone/InstanceContent.h"
|
||||
#include "Actor/Player.h"
|
||||
#include "Actor/BattleNpc.h"
|
||||
|
||||
#include "ServerZone.h"
|
||||
#include "Event/EventHandler.h"
|
||||
#include "Event/EventHelper.h"
|
||||
|
||||
|
@ -142,12 +141,6 @@ void Core::Scripting::ScriptMgr::onPlayerFirstEnterWorld( Entity::Player& player
|
|||
// }
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId,
|
||||
uint32_t bnpcNameId, uint32_t modelId, std::string aiName )
|
||||
{
|
||||
return g_framework.getServerZone().registerBnpcTemplate( templateName, bnpcBaseId, bnpcNameId, modelId, aiName );
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId )
|
||||
{
|
||||
|
||||
|
@ -176,7 +169,7 @@ bool Core::Scripting::ScriptMgr::onEnterTerritory( Entity::Player& player, uint3
|
|||
auto script = m_nativeScriptMgr->getScript< EventScript >( eventId );
|
||||
if( !script )
|
||||
return false;
|
||||
script->onEnterZone( player, eventId, param1, param2 );
|
||||
script->onEnterTerritory( player, eventId, param1, param2 );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -278,7 +271,7 @@ bool Core::Scripting::ScriptMgr::onMobKill( Entity::Player& player, uint16_t nam
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onCastFinish( Entity::Player& player, Entity::ActorPtr pTarget, uint32_t actionId )
|
||||
bool Core::Scripting::ScriptMgr::onCastFinish( Entity::Player& player, Entity::CharaPtr pTarget, uint32_t actionId )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< ActionScript >( actionId );
|
||||
|
||||
|
@ -287,7 +280,7 @@ bool Core::Scripting::ScriptMgr::onCastFinish( Entity::Player& player, Entity::A
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId )
|
||||
bool Core::Scripting::ScriptMgr::onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< StatusEffectScript >( effectId );
|
||||
|
||||
|
@ -303,30 +296,30 @@ bool Core::Scripting::ScriptMgr::onStatusReceive( Entity::ActorPtr pActor, uint3
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect )
|
||||
bool Core::Scripting::ScriptMgr::onStatusTick( Entity::CharaPtr pChara, Core::StatusEffect::StatusEffect& effect )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< StatusEffectScript >( effect.getId() );
|
||||
if( script )
|
||||
{
|
||||
if( pActor->isPlayer() )
|
||||
pActor->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) );
|
||||
if( pChara->isPlayer() )
|
||||
pChara->getAsPlayer()->sendDebug( "Calling status tick for statusid: " + std::to_string( effect.getId() ) );
|
||||
|
||||
script->onTick( *pActor );
|
||||
script->onTick( *pChara );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId )
|
||||
bool Core::Scripting::ScriptMgr::onStatusTimeOut( Entity::CharaPtr pChara, uint32_t effectId )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< StatusEffectScript >( effectId );
|
||||
if( script )
|
||||
{
|
||||
if( pActor->isPlayer() )
|
||||
pActor->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) );
|
||||
if( pChara->isPlayer() )
|
||||
pChara->getAsPlayer()->sendDebug( "Calling status timeout for statusid: " + std::to_string( effectId ) );
|
||||
|
||||
script->onExpire( *pActor );
|
||||
script->onExpire( *pChara );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -345,9 +338,9 @@ bool Core::Scripting::ScriptMgr::onZoneInit( ZonePtr pZone )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onInstanceInit( InstanceContent& instance )
|
||||
bool Core::Scripting::ScriptMgr::onInstanceInit( InstanceContentPtr instance )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< InstanceContentScript >( instance.getInstanceContentId() );
|
||||
auto script = m_nativeScriptMgr->getScript< InstanceContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onInit( instance );
|
||||
|
@ -357,9 +350,10 @@ bool Core::Scripting::ScriptMgr::onInstanceInit( InstanceContent& instance )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onInstanceUpdate( InstanceContent& instance, uint32_t currTime )
|
||||
bool Core::Scripting::ScriptMgr::onInstanceUpdate( InstanceContentPtr instance, uint32_t currTime )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< InstanceContentScript >( instance.getInstanceContentId() );
|
||||
auto script = m_nativeScriptMgr->getScript< InstanceContentScript >( instance->getDirectorId() );
|
||||
|
||||
if( script )
|
||||
{
|
||||
script->onUpdate( instance, currTime );
|
||||
|
@ -369,6 +363,18 @@ bool Core::Scripting::ScriptMgr::onInstanceUpdate( InstanceContent& instance, ui
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Core::Scripting::ScriptMgr::onInstanceEnterTerritory( InstanceContentPtr instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 )
|
||||
{
|
||||
auto script = m_nativeScriptMgr->getScript< InstanceContentScript >( instance->getDirectorId() );
|
||||
if( script )
|
||||
{
|
||||
script->onEnterTerritory( player, eventId, param1, param2 );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Scripting::NativeScriptMgr& Core::Scripting::ScriptMgr::getNativeScriptHandler()
|
||||
{
|
||||
return *m_nativeScriptMgr;
|
||||
|
|
|
@ -37,8 +37,6 @@ namespace Core
|
|||
|
||||
void onPlayerFirstEnterWorld( Entity::Player& player );
|
||||
|
||||
static bool registerBnpcTemplate( std::string templateName, uint32_t bnpcBaseId, uint32_t bnpcNameId, uint32_t modelId, std::string aiName );
|
||||
|
||||
bool onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId );
|
||||
bool onEnterTerritory( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 );
|
||||
bool onWithinRange( Entity::Player& player, uint32_t eventId, uint32_t param1, float x, float y, float z );
|
||||
|
@ -48,19 +46,20 @@ namespace Core
|
|||
|
||||
bool onMobKill( Entity::Player& player, uint16_t nameId );
|
||||
|
||||
bool onCastFinish( Entity::Player& pPlayer, Entity::ActorPtr pTarget, uint32_t actionId );
|
||||
bool onCastFinish( Entity::Player& pPlayer, Entity::CharaPtr pTarget, uint32_t actionId );
|
||||
|
||||
bool onStatusReceive( Entity::ActorPtr pActor, uint32_t effectId );
|
||||
bool onStatusTick( Entity::ActorPtr pActor, Core::StatusEffect::StatusEffect& effect );
|
||||
bool onStatusTimeOut( Entity::ActorPtr pActor, uint32_t effectId );
|
||||
bool onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId );
|
||||
bool onStatusTick( Entity::CharaPtr pActor, Core::StatusEffect::StatusEffect& effect );
|
||||
bool onStatusTimeOut( Entity::CharaPtr pActor, uint32_t effectId );
|
||||
|
||||
bool onZoneInit( ZonePtr pZone );
|
||||
|
||||
bool onEventHandlerReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param1, uint16_t param2, uint16_t param3 );
|
||||
bool onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId );
|
||||
|
||||
bool onInstanceInit( InstanceContent& instance );
|
||||
bool onInstanceUpdate( InstanceContent& instance, uint32_t currTime );
|
||||
bool onInstanceInit( InstanceContentPtr instance );
|
||||
bool onInstanceUpdate( InstanceContentPtr instance, uint32_t currTime );
|
||||
bool onInstanceEnterTerritory( InstanceContentPtr instance, Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 );
|
||||
|
||||
void loadDir( const std::string& dirname, std::set<std::string> &files, const std::string& ext );
|
||||
|
||||
|
|
|
@ -39,8 +39,13 @@ foreach(_scriptDir ${children})
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
add_library("script_${_name}" MODULE "${SCRIPT_BUILD_FILES}" "${SCRIPT_INCLUDE_FILES}" "${_scriptDir}/ScriptLoader.cpp")
|
||||
add_library("script_${_name}" MODULE ${SCRIPT_BUILD_FILES} "${SCRIPT_INCLUDE_FILES}" "${_scriptDir}/ScriptLoader.cpp")
|
||||
target_link_libraries("script_${_name}" sapphire_zone)
|
||||
cotire("script_${_name}")
|
||||
|
||||
if(MSVC)
|
||||
target_link_libraries("script_${_name}" ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set_target_properties("script_${_name}" PROPERTIES
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#ifndef SAPPHIRE_SCRIPTOBJECT_H
|
||||
#define SAPPHIRE_SCRIPTOBJECT_H
|
||||
|
||||
#include <Script/NativeScriptApi.h>
|
||||
#include <Forwards.h>
|
||||
#include <Actor/Actor.h>
|
||||
#include <Actor/Player.h>
|
||||
#include <Event/EventHelper.h>
|
||||
#include <Script/NativeScriptApi.h>
|
||||
|
||||
enum EventFlags
|
||||
{
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
class ActionSprint3 : public ActionScript
|
||||
{
|
||||
|
@ -6,7 +8,7 @@ public:
|
|||
ActionSprint3() : ActionScript( 3 )
|
||||
{}
|
||||
|
||||
void onCastFinish( Core::Entity::Player& player, Core::Entity::Actor& targetActor ) override
|
||||
void onCastFinish( Core::Entity::Player& player, Core::Entity::Chara& targetActor ) override
|
||||
{
|
||||
player.addStatusEffectByIdIfNotExist( 50, 20000, player, 30 );
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
#define ACTION_ATTUNE 0x13
|
||||
|
||||
|
@ -39,7 +41,6 @@ public:
|
|||
|
||||
}, 0 );
|
||||
|
||||
player.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
|
||||
#define ACTION_ATTUNE 0x13
|
||||
#define ACTION_TELEPORT 0x4
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
class CmnDefCutSceneReplay : public EventScript
|
||||
{
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
class CmnDefInnBed : public EventScript
|
||||
{
|
||||
|
@ -49,7 +51,7 @@ public:
|
|||
Scene00000( player );
|
||||
}
|
||||
|
||||
void onEnterZone( Entity::Player& player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
Scene00100( player );
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
#define ACTION_CREATE 2
|
||||
#define ACTION_RENAME 3
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <Script/NativeScriptApi.h>
|
||||
#include "../ScriptObject.h"
|
||||
#include <Actor/Player.h>
|
||||
|
||||
class HouFurOrchestrion : public EventScript
|
||||
{
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors101110 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors101110() : InstanceContentScript( 60011 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6527847, 4, { -300.000000f, 0.000026f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959_1", 2000608, 6544382, 4, { 301.149902f, -0.045413f, 285.247589f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors110 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors110() : InstanceContentScript( 60001 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2002872, 6324883, 4, { -300.000000f, -0.000010f, -220.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors111120 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors111120() : InstanceContentScript( 60012 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6535115, 4, { -300.000000f, 0.000026f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors1120 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors1120() : InstanceContentScript( 60002 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6353850, 4, { -300.000000f, 0.000026f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors121130 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors121130() : InstanceContentScript( 60013 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6535115, 4, { -300.000000f, 0.000026f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors131140 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors131140() : InstanceContentScript( 60014 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6535683, 4, { -300.000000f, -0.000205f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors141150 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors141150() : InstanceContentScript( 60015 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6535683, 4, { -300.000000f, -0.000205f, -237.000000f }, 1.000000f, 0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors151160 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors151160() : InstanceContentScript( 60016 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6534547, 4, { -301.179504f, 0.130118f, -301.014709f }, 1.000000f, -0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors161170 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors161170() : InstanceContentScript( 60017 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6534547, 4, { -301.179504f, 0.130118f, -301.014709f }, 1.000000f, -0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors171180 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors171180() : InstanceContentScript( 60018 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6534547, 4, { -301.179504f, 0.130118f, -301.014709f }, 1.000000f, -0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
#include <ScriptObject.h>
|
||||
#include <Zone/InstanceContent.h>
|
||||
|
||||
class ThePalaceoftheDeadFloors181190 : public InstanceContentScript
|
||||
{
|
||||
public:
|
||||
ThePalaceoftheDeadFloors181190() : InstanceContentScript( 60019 )
|
||||
{ }
|
||||
|
||||
void onInit( InstanceContentPtr instance ) override
|
||||
{
|
||||
instance->registerEObj( "sgvf_w_lvd_b0959", 2000608, 6534547, 4, { -301.179504f, 0.130118f, -301.014709f }, 1.000000f, -0.000000f );
|
||||
// States -> vf_bextwall_on vf_bextwall_on2off vf_bextwall_off
|
||||
|
||||
}
|
||||
|
||||
void onUpdate( InstanceContentPtr instance, uint32_t currTime ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onEnterTerritory( Entity::Player &player, uint32_t eventId, uint16_t param1, uint16_t param2 ) override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue