2021-12-05 17:54:36 +00:00
# include "dCommonVars.h"
# include "Entity.h"
# include "CDClientManager.h"
# include "Game.h"
# include "dLogger.h"
# include <PacketUtils.h>
# include <functional>
# include "CDDestructibleComponentTable.h"
# include "CDClientDatabase.h"
# include <sstream>
# include "dServer.h"
# include "GameMessages.h"
# include "EntityManager.h"
# include "dZoneManager.h"
# include "Zone.h"
# include "Spawner.h"
# include "UserManager.h"
# include "dpWorld.h"
# include "Player.h"
//Component includes:
# include "Component.h"
# include "ControllablePhysicsComponent.h"
# include "RenderComponent.h"
2022-05-03 20:05:29 +00:00
# include "RocketLaunchLupComponent.h"
2021-12-05 17:54:36 +00:00
# include "CharacterComponent.h"
# include "DestroyableComponent.h"
# include "BuffComponent.h"
# include "BouncerComponent.h"
# include "InventoryComponent.h"
2022-07-24 18:04:02 +00:00
# include "LevelProgressionComponent.h"
2022-07-24 18:25:10 +00:00
# include "PlayerForcedMovementComponent.h"
2021-12-05 17:54:36 +00:00
# include "ScriptComponent.h"
# include "SkillComponent.h"
# include "SimplePhysicsComponent.h"
# include "SwitchComponent.h"
# include "PhantomPhysicsComponent.h"
# include "RigidbodyPhantomPhysicsComponent.h"
# include "MovingPlatformComponent.h"
# include "MissionComponent.h"
# include "MissionOfferComponent.h"
# include "RebuildComponent.h"
# include "BuildBorderComponent.h"
# include "MovementAIComponent.h"
# include "VendorComponent.h"
# include "RocketLaunchpadControlComponent.h"
# include "PropertyComponent.h"
# include "BaseCombatAIComponent.h"
# include "PropertyManagementComponent.h"
# include "PropertyVendorComponent.h"
# include "ProximityMonitorComponent.h"
# include "PropertyEntranceComponent.h"
# include "ModelComponent.h"
# include "ZCompression.h"
# include "PetComponent.h"
# include "VehiclePhysicsComponent.h"
# include "PossessableComponent.h"
# include "PossessorComponent.h"
# include "ModuleAssemblyComponent.h"
# include "RacingControlComponent.h"
# include "SoundTriggerComponent.h"
# include "ShootingGalleryComponent.h"
# include "RailActivatorComponent.h"
# include "LUPExhibitComponent.h"
Entity : : Entity ( const LWOOBJID & objectID , EntityInfo info , Entity * parentEntity ) {
m_ObjectID = objectID ;
m_TemplateID = info . lot ;
m_ParentEntity = parentEntity ;
m_Character = nullptr ;
m_GMLevel = 0 ;
m_CollectibleID = 0 ;
m_Trigger = nullptr ; //new LUTriggers::Trigger();
m_NetworkID = 0 ;
m_Groups = { } ;
m_OwnerOverride = LWOOBJID_EMPTY ;
m_Timers = { } ;
m_ChildEntities = { } ;
m_ScheduleKiller = nullptr ;
m_TargetsInPhantom = { } ;
m_Components = { } ;
m_DieCallbacks = { } ;
m_PhantomCollisionCallbacks = { } ;
2022-06-16 05:58:38 +00:00
m_IsParentChildDirty = true ;
2021-12-05 17:54:36 +00:00
m_Settings = info . settings ;
m_NetworkSettings = info . networkSettings ;
m_DefaultPosition = info . pos ;
m_DefaultRotation = info . rot ;
m_Scale = info . scale ;
m_Spawner = info . spawner ;
m_SpawnerID = info . spawnerID ;
m_HasSpawnerNodeID = info . hasSpawnerNodeID ;
m_SpawnerNodeID = info . spawnerNodeID ;
if ( info . lot ! = 1 ) m_PlayerIsReadyForUpdates = true ;
}
Entity : : ~ Entity ( ) {
if ( m_Character ) {
m_Character - > SaveXMLToDatabase ( ) ;
}
CancelAllTimers ( ) ;
CancelCallbackTimers ( ) ;
const auto components = m_Components ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
for ( const auto & pair : components ) {
delete pair . second ;
m_Components . erase ( pair . first ) ;
}
2022-07-17 04:39:13 +00:00
for ( auto child : m_ChildEntities ) {
if ( child ) child - > RemoveParent ( ) ;
}
2022-06-17 00:50:33 +00:00
if ( m_ParentEntity ) {
m_ParentEntity - > RemoveChild ( this ) ;
}
2021-12-05 17:54:36 +00:00
}
void Entity : : Initialize ( ) {
/**
* Setup trigger
*/
const auto triggerName = GetVarAsString ( u " trigger_id " ) ;
if ( ! triggerName . empty ( ) ) {
std : : stringstream ss ( triggerName ) ;
std : : vector < std : : string > tokens ;
std : : string token ;
while ( std : : getline ( ss , token , ' : ' ) ) {
tokens . push_back ( token ) ;
}
uint32_t sceneID = std : : stoi ( tokens [ 0 ] ) ;
uint32_t triggerID = std : : stoi ( tokens [ 1 ] ) ;
if ( m_Trigger ! = nullptr ) {
delete m_Trigger ;
m_Trigger = nullptr ;
}
m_Trigger = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetTrigger ( sceneID , triggerID ) ;
if ( m_Trigger = = nullptr ) {
m_Trigger = new LUTriggers : : Trigger ( ) ;
}
}
/**
* Setup groups
*/
const auto groupIDs = GetVarAsString ( u " groupID " ) ;
if ( ! groupIDs . empty ( ) ) {
m_Groups = GeneralUtils : : SplitString ( groupIDs , ' ; ' ) ;
m_Groups . erase ( m_Groups . end ( ) - 1 ) ;
}
/**
* Set ourselves as a child of our parent
*/
if ( m_ParentEntity ! = nullptr ) {
m_ParentEntity - > AddChild ( this ) ;
}
// Get the registry table
CDComponentsRegistryTable * compRegistryTable = CDClientManager : : Instance ( ) - > GetTable < CDComponentsRegistryTable > ( " ComponentsRegistry " ) ;
/**
* Special case for BBB models . They have components not corresponding to the registry .
*/
if ( m_TemplateID = = 14 ) {
const auto simplePhysicsComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SIMPLE_PHYSICS ) ;
SimplePhysicsComponent * comp = new SimplePhysicsComponent ( simplePhysicsComponentID , this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SIMPLE_PHYSICS , comp ) ) ;
2022-07-19 21:51:35 +00:00
ModelComponent * modelcomp = new ModelComponent ( this ) ;
2021-12-05 17:54:36 +00:00
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MODEL , modelcomp ) ) ;
RenderComponent * render = new RenderComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RENDER , render ) ) ;
2022-07-19 21:51:35 +00:00
auto destroyableComponent = new DestroyableComponent ( this ) ;
destroyableComponent - > SetHealth ( 1 ) ;
destroyableComponent - > SetMaxHealth ( 1.0f ) ;
destroyableComponent - > SetFaction ( - 1 , true ) ;
destroyableComponent - > SetIsSmashable ( true ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) ) ;
2021-12-05 17:54:36 +00:00
// We have all our components.
return ;
}
/**
* Go through all the components and check if this entity has them .
*
* Not all components are implemented . Some are represented by a nullptr , as they hold no data .
*/
if ( GetParentUser ( ) ) {
auto missions = new MissionComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MISSION , missions ) ) ;
missions - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
}
uint32_t petComponentId = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PET ) ;
if ( petComponentId > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PET , new PetComponent ( this , petComponentId ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_ZONE_CONTROL ) > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_ZONE_CONTROL , nullptr ) ) ;
}
2022-07-09 03:25:15 +00:00
uint32_t possessableComponentId = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_POSSESSABLE ) ;
if ( possessableComponentId > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_POSSESSABLE , new PossessableComponent ( this , possessableComponentId ) ) ) ;
2021-12-05 17:54:36 +00:00
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_MODULE_ASSEMBLY ) > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MODULE_ASSEMBLY , new ModuleAssemblyComponent ( this ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_RACING_STATS ) > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RACING_STATS , nullptr ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_EXHIBIT , - 1 ) > = 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_EXHIBIT , new LUPExhibitComponent ( this ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_RACING_CONTROL ) > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RACING_CONTROL , new RacingControlComponent ( this ) ) ) ;
}
const auto propertyEntranceComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PROPERTY_ENTRANCE ) ;
if ( propertyEntranceComponentID > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PROPERTY_ENTRANCE ,
new PropertyEntranceComponent ( propertyEntranceComponentID , this ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_CONTROLLABLE_PHYSICS ) > 0 ) {
ControllablePhysicsComponent * controllablePhysics = new ControllablePhysicsComponent ( this ) ;
if ( m_Character ) {
2022-07-25 02:03:22 +00:00
controllablePhysics - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
2021-12-05 17:54:36 +00:00
const auto mapID = Game : : server - > GetZoneID ( ) ;
//If we came from another zone, put us in the starting loc
if ( m_Character - > GetZoneID ( ) ! = Game : : server - > GetZoneID ( ) | | mapID = = 1603 ) { // Exception for Moon Base as you tend to spawn on the roof.
NiPoint3 pos ;
NiQuaternion rot ;
const auto & targetSceneName = m_Character - > GetTargetScene ( ) ;
auto * targetScene = EntityManager : : Instance ( ) - > GetSpawnPointEntity ( targetSceneName ) ;
if ( m_Character - > HasBeenToWorld ( mapID ) & & targetSceneName . empty ( ) ) {
pos = m_Character - > GetRespawnPoint ( mapID ) ;
rot = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetSpawnRot ( ) ;
} else if ( targetScene ! = nullptr ) {
pos = targetScene - > GetPosition ( ) ;
rot = targetScene - > GetRotation ( ) ;
} else {
pos = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetSpawnPos ( ) ;
rot = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetSpawnRot ( ) ;
}
controllablePhysics - > SetPosition ( pos ) ;
controllablePhysics - > SetRotation ( rot ) ;
}
} else {
controllablePhysics - > SetPosition ( m_DefaultPosition ) ;
controllablePhysics - > SetRotation ( m_DefaultRotation ) ;
}
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_CONTROLLABLE_PHYSICS , controllablePhysics ) ) ;
}
// If an entity is marked a phantom, simple physics is made into phantom phyics.
bool markedAsPhantom = GetVar < bool > ( u " markedAsPhantom " ) ;
const auto simplePhysicsComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SIMPLE_PHYSICS ) ;
if ( ! markedAsPhantom & & simplePhysicsComponentID > 0 ) {
SimplePhysicsComponent * comp = new SimplePhysicsComponent ( simplePhysicsComponentID , this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SIMPLE_PHYSICS , comp ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS ) > 0 ) {
RigidbodyPhantomPhysicsComponent * comp = new RigidbodyPhantomPhysicsComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS , comp ) ) ;
}
if ( markedAsPhantom | | compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PHANTOM_PHYSICS ) > 0 ) {
PhantomPhysicsComponent * phantomPhysics = new PhantomPhysicsComponent ( this ) ;
phantomPhysics - > SetPhysicsEffectActive ( false ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PHANTOM_PHYSICS , phantomPhysics ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_VEHICLE_PHYSICS ) > 0 ) {
VehiclePhysicsComponent * vehiclePhysicsComponent = new VehiclePhysicsComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_VEHICLE_PHYSICS , vehiclePhysicsComponent ) ) ;
vehiclePhysicsComponent - > SetPosition ( m_DefaultPosition ) ;
vehiclePhysicsComponent - > SetRotation ( m_DefaultRotation ) ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SOUND_TRIGGER , - 1 ) ! = - 1 ) {
auto * comp = new SoundTriggerComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SOUND_TRIGGER , comp ) ) ;
}
//Also check for the collectible id:
m_CollectibleID = GetVarAs < int32_t > ( u " collectible_id " ) ;
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_BUFF ) > 0 ) {
BuffComponent * comp = new BuffComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_BUFF , comp ) ) ;
}
int collectibleComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_COLLECTIBLE ) ;
if ( collectibleComponentID > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_COLLECTIBLE , nullptr ) ) ;
}
/**
2022-02-05 11:28:17 +00:00
* Multiple components require the destructible component .
2021-12-05 17:54:36 +00:00
*/
int buffComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_BUFF ) ;
int rebuildComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_REBUILD ) ;
int componentID = 0 ;
if ( collectibleComponentID > 0 ) componentID = collectibleComponentID ;
if ( rebuildComponentID > 0 ) componentID = rebuildComponentID ;
if ( buffComponentID > 0 ) componentID = buffComponentID ;
CDDestructibleComponentTable * destCompTable = CDClientManager : : Instance ( ) - > GetTable < CDDestructibleComponentTable > ( " DestructibleComponent " ) ;
std : : vector < CDDestructibleComponent > destCompData = destCompTable - > Query ( [ = ] ( CDDestructibleComponent entry ) { return ( entry . id = = componentID ) ; } ) ;
if ( buffComponentID > 0 | | collectibleComponentID > 0 ) {
DestroyableComponent * comp = new DestroyableComponent ( this ) ;
if ( m_Character ) {
2022-07-25 02:03:22 +00:00
comp - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
2021-12-05 17:54:36 +00:00
} else {
if ( componentID > 0 ) {
std : : vector < CDDestructibleComponent > destCompData = destCompTable - > Query ( [ = ] ( CDDestructibleComponent entry ) { return ( entry . id = = componentID ) ; } ) ;
if ( destCompData . size ( ) > 0 ) {
if ( HasComponent ( COMPONENT_TYPE_RACING_STATS ) ) {
destCompData [ 0 ] . imagination = 60 ;
}
comp - > SetHealth ( destCompData [ 0 ] . life ) ;
comp - > SetImagination ( destCompData [ 0 ] . imagination ) ;
comp - > SetArmor ( destCompData [ 0 ] . armor ) ;
comp - > SetMaxHealth ( destCompData [ 0 ] . life ) ;
comp - > SetMaxImagination ( destCompData [ 0 ] . imagination ) ;
comp - > SetMaxArmor ( destCompData [ 0 ] . armor ) ;
comp - > SetIsSmashable ( destCompData [ 0 ] . isSmashable ) ;
comp - > SetLootMatrixID ( destCompData [ 0 ] . LootMatrixIndex ) ;
// Now get currency information
uint32_t npcMinLevel = destCompData [ 0 ] . level ;
uint32_t currencyIndex = destCompData [ 0 ] . CurrencyIndex ;
CDCurrencyTableTable * currencyTable = CDClientManager : : Instance ( ) - > GetTable < CDCurrencyTableTable > ( " CurrencyTable " ) ;
std : : vector < CDCurrencyTable > currencyValues = currencyTable - > Query ( [ = ] ( CDCurrencyTable entry ) { return ( entry . currencyIndex = = currencyIndex & & entry . npcminlevel = = npcMinLevel ) ; } ) ;
if ( currencyValues . size ( ) > 0 ) {
// Set the coins
comp - > SetMinCoins ( currencyValues [ 0 ] . minvalue ) ;
comp - > SetMaxCoins ( currencyValues [ 0 ] . maxvalue ) ;
}
// extraInfo overrides
comp - > SetIsSmashable ( GetVarAs < int32_t > ( u " is_smashable " ) ! = 0 ) ;
}
} else {
comp - > SetHealth ( 1 ) ;
comp - > SetArmor ( 0 ) ;
comp - > SetMaxHealth ( 1 ) ;
comp - > SetMaxArmor ( 0 ) ;
comp - > SetIsSmashable ( true ) ;
comp - > AddFaction ( - 1 ) ;
comp - > AddFaction ( 6 ) ; //Smashables
// A race car has 60 imagination, other entities defaults to 0.
comp - > SetImagination ( HasComponent ( COMPONENT_TYPE_RACING_STATS ) ? 60 : 0 ) ;
comp - > SetMaxImagination ( HasComponent ( COMPONENT_TYPE_RACING_STATS ) ? 60 : 0 ) ;
}
}
if ( destCompData . size ( ) > 0 ) {
comp - > AddFaction ( destCompData [ 0 ] . faction ) ;
std : : stringstream ss ( destCompData [ 0 ] . factionList ) ;
std : : string token ;
while ( std : : getline ( ss , token , ' , ' ) ) {
if ( std : : stoi ( token ) = = destCompData [ 0 ] . faction ) continue ;
if ( token ! = " " ) {
comp - > AddFaction ( std : : stoi ( token ) ) ;
}
}
}
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_DESTROYABLE , comp ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_CHARACTER ) > 0 | | m_Character ) {
2022-07-24 18:25:10 +00:00
// Character Component always has a possessor, level, and forced movement components
2022-06-29 23:50:24 +00:00
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_POSSESSOR , new PossessorComponent ( this ) ) ) ;
2022-07-24 18:04:02 +00:00
// load in the xml for the level
auto * levelComp = new LevelProgressionComponent ( this ) ;
levelComp - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_LEVEL_PROGRESSION , levelComp ) ) ;
2022-07-24 18:25:10 +00:00
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT , new PlayerForcedMovementComponent ( this ) ) ) ;
2022-07-25 02:03:22 +00:00
CharacterComponent * charComp = new CharacterComponent ( this , m_Character ) ;
charComp - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_CHARACTER , charComp ) ) ;
2021-12-05 17:54:36 +00:00
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_INVENTORY ) > 0 | | m_Character ) {
InventoryComponent * comp = nullptr ;
if ( m_Character ) comp = new InventoryComponent ( this , m_Character - > GetXMLDoc ( ) ) ;
else comp = new InventoryComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_INVENTORY , comp ) ) ;
}
2022-05-03 20:05:29 +00:00
// if this component exists, then we initialize it. it's value is always 0
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_ROCKET_LAUNCH_LUP , - 1 ) ! = - 1 ) {
auto comp = new RocketLaunchLupComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_ROCKET_LAUNCH_LUP , comp ) ) ;
2021-12-05 17:54:36 +00:00
}
/**
* This is a bit of a mess
*/
CDScriptComponentTable * scriptCompTable = CDClientManager : : Instance ( ) - > GetTable < CDScriptComponentTable > ( " ScriptComponent " ) ;
2022-11-27 12:03:30 +00:00
int32_t scriptComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SCRIPT , - 1 ) ;
2021-12-05 17:54:36 +00:00
std : : string scriptName = " " ;
bool client = false ;
if ( scriptComponentID > 0 | | m_Character ) {
std : : string clientScriptName ;
if ( ! m_Character ) {
CDScriptComponent scriptCompData = scriptCompTable - > GetByID ( scriptComponentID ) ;
scriptName = scriptCompData . script_name ;
clientScriptName = scriptCompData . client_script_name ;
} else {
scriptName = " " ;
}
if ( scriptName ! = " " | | ( scriptName = = " " & & m_Character ) ) {
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
} else if ( clientScriptName ! = " " ) {
client = true ;
} else if ( ! m_Character ) {
client = true ;
}
}
std : : string customScriptServer ;
bool hasCustomServerScript = false ;
const auto customScriptServerName = GetVarAsString ( u " custom_script_server " ) ;
const auto customScriptClientName = GetVarAsString ( u " custom_script_client " ) ;
if ( ! customScriptServerName . empty ( ) ) {
customScriptServer = customScriptServerName ;
hasCustomServerScript = true ;
}
if ( ! customScriptClientName . empty ( ) ) {
client = true ;
}
if ( hasCustomServerScript & & scriptName . empty ( ) ) {
scriptName = customScriptServer ;
}
2022-11-27 12:03:30 +00:00
if ( ! scriptName . empty ( ) | | client | | m_Character | | scriptComponentID > = 0 ) {
2021-12-05 17:54:36 +00:00
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SCRIPT , new ScriptComponent ( this , scriptName , true , client & & scriptName . empty ( ) ) ) ) ;
}
// ZoneControl script
if ( m_TemplateID = = 2365 ) {
CDZoneTableTable * zoneTable = CDClientManager : : Instance ( ) - > GetTable < CDZoneTableTable > ( " ZoneTable " ) ;
const auto zoneID = dZoneManager : : Instance ( ) - > GetZoneID ( ) ;
const CDZoneTable * zoneData = zoneTable - > Query ( zoneID . GetMapID ( ) ) ;
if ( zoneData ! = nullptr ) {
int zoneScriptID = zoneData - > scriptID ;
CDScriptComponent zoneScriptData = scriptCompTable - > GetByID ( zoneScriptID ) ;
ScriptComponent * comp = new ScriptComponent ( this , zoneScriptData . script_name , true ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SCRIPT , comp ) ) ;
}
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SKILL , - 1 ) ! = - 1 | | m_Character ) {
SkillComponent * comp = new SkillComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SKILL , comp ) ) ;
}
const auto combatAiId = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_BASE_COMBAT_AI ) ;
if ( combatAiId > 0 ) {
BaseCombatAIComponent * comp = new BaseCombatAIComponent ( this , combatAiId ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_BASE_COMBAT_AI , comp ) ) ;
}
if ( int componentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_REBUILD ) > 0 ) {
RebuildComponent * comp = new RebuildComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_REBUILD , comp ) ) ;
CDRebuildComponentTable * rebCompTable = CDClientManager : : Instance ( ) - > GetTable < CDRebuildComponentTable > ( " RebuildComponent " ) ;
std : : vector < CDRebuildComponent > rebCompData = rebCompTable - > Query ( [ = ] ( CDRebuildComponent entry ) { return ( entry . id = = rebuildComponentID ) ; } ) ;
if ( rebCompData . size ( ) > 0 ) {
comp - > SetResetTime ( rebCompData [ 0 ] . reset_time ) ;
comp - > SetCompleteTime ( rebCompData [ 0 ] . complete_time ) ;
comp - > SetTakeImagination ( rebCompData [ 0 ] . take_imagination ) ;
comp - > SetInterruptible ( rebCompData [ 0 ] . interruptible ) ;
comp - > SetSelfActivator ( rebCompData [ 0 ] . self_activator ) ;
comp - > SetActivityId ( rebCompData [ 0 ] . activityID ) ;
comp - > SetPostImaginationCost ( rebCompData [ 0 ] . post_imagination_cost ) ;
comp - > SetTimeBeforeSmash ( rebCompData [ 0 ] . time_before_smash ) ;
const auto rebuildResetTime = GetVar < float > ( u " rebuild_reset_time " ) ;
if ( rebuildResetTime ! = 0.0f ) {
comp - > SetResetTime ( rebuildResetTime ) ;
if ( m_TemplateID = = 9483 ) // Look away!
{
comp - > SetResetTime ( comp - > GetResetTime ( ) + 25 ) ;
}
}
const auto activityID = GetVar < int32_t > ( u " activityID " ) ;
if ( activityID > 0 ) {
comp - > SetActivityId ( activityID ) ;
}
const auto compTime = GetVar < float > ( u " compTime " ) ;
if ( compTime > 0 ) {
comp - > SetCompleteTime ( compTime ) ;
}
}
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SWITCH , - 1 ) ! = - 1 ) {
SwitchComponent * comp = new SwitchComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SWITCH , comp ) ) ;
}
if ( ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_VENDOR ) > 0 ) ) {
VendorComponent * comp = new VendorComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_VENDOR , comp ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PROPERTY_VENDOR , - 1 ) ! = - 1 ) {
auto * component = new PropertyVendorComponent ( this ) ;
m_Components . insert_or_assign ( COMPONENT_TYPE_PROPERTY_VENDOR , component ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PROPERTY_MANAGEMENT , - 1 ) ! = - 1 ) {
auto * component = new PropertyManagementComponent ( this ) ;
m_Components . insert_or_assign ( COMPONENT_TYPE_PROPERTY_MANAGEMENT , component ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_BOUNCER , - 1 ) ! = - 1 ) { // you have to determine it like this because all bouncers have a componentID of 0
BouncerComponent * comp = new BouncerComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_BOUNCER , comp ) ) ;
}
if ( ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_RENDER ) > 0 & & m_TemplateID ! = 2365 ) | | m_Character ) {
RenderComponent * render = new RenderComponent ( this ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RENDER , render ) ) ;
}
if ( ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_MISSION_OFFER ) > 0 ) | | m_Character ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MISSION_OFFER , new MissionOfferComponent ( this , m_TemplateID ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_BUILD_BORDER , - 1 ) ! = - 1 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_BUILD_BORDER , new BuildBorderComponent ( this ) ) ) ;
}
// Scripted activity component
int scriptedActivityID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SCRIPTED_ACTIVITY ) ;
if ( ( scriptedActivityID > 0 ) ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SCRIPTED_ACTIVITY , new ScriptedActivityComponent ( this , scriptedActivityID ) ) ) ;
}
2022-07-19 21:51:35 +00:00
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_MODEL , - 1 ) ! = - 1 & & ! GetComponent < PetComponent > ( ) ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MODEL , new ModelComponent ( this ) ) ) ;
if ( m_Components . find ( COMPONENT_TYPE_DESTROYABLE ) = = m_Components . end ( ) ) {
auto destroyableComponent = new DestroyableComponent ( this ) ;
destroyableComponent - > SetHealth ( 1 ) ;
destroyableComponent - > SetMaxHealth ( 1.0f ) ;
destroyableComponent - > SetFaction ( - 1 , true ) ;
destroyableComponent - > SetIsSmashable ( true ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) ) ;
}
}
PetComponent * petComponent ;
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_ITEM ) > 0 & & ! TryGetComponent ( COMPONENT_TYPE_PET , petComponent ) & & ! HasComponent ( COMPONENT_TYPE_MODEL ) ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_ITEM , nullptr ) ) ;
}
2021-12-05 17:54:36 +00:00
// Shooting gallery component
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_SHOOTING_GALLERY ) > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_SHOOTING_GALLERY , new ShootingGalleryComponent ( this ) ) ) ;
}
if ( compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PROPERTY , - 1 ) ! = - 1 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PROPERTY , new PropertyComponent ( this ) ) ) ;
}
const int rocketId = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_ROCKET_LAUNCH ) ;
if ( ( rocketId > 0 ) ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_ROCKET_LAUNCH , new RocketLaunchpadControlComponent ( this , rocketId ) ) ) ;
}
const int32_t railComponentID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_RAIL_ACTIVATOR ) ;
if ( railComponentID > 0 ) {
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_RAIL_ACTIVATOR , new RailActivatorComponent ( this , railComponentID ) ) ) ;
}
int movementAIID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_MOVEMENT_AI ) ;
if ( movementAIID > 0 ) {
CDMovementAIComponentTable * moveAITable = CDClientManager : : Instance ( ) - > GetTable < CDMovementAIComponentTable > ( " MovementAIComponent " ) ;
std : : vector < CDMovementAIComponent > moveAIComp = moveAITable - > Query ( [ = ] ( CDMovementAIComponent entry ) { return ( entry . id = = movementAIID ) ; } ) ;
if ( moveAIComp . size ( ) > 0 ) {
MovementAIInfo moveInfo = MovementAIInfo ( ) ;
moveInfo . movementType = moveAIComp [ 0 ] . MovementType ;
moveInfo . wanderChance = moveAIComp [ 0 ] . WanderChance ;
moveInfo . wanderRadius = moveAIComp [ 0 ] . WanderRadius ;
moveInfo . wanderSpeed = moveAIComp [ 0 ] . WanderSpeed ;
moveInfo . wanderDelayMax = moveAIComp [ 0 ] . WanderDelayMax ;
moveInfo . wanderDelayMin = moveAIComp [ 0 ] . WanderDelayMin ;
bool useWanderDB = GetVar < bool > ( u " usewanderdb " ) ;
if ( ! useWanderDB ) {
const auto wanderOverride = GetVarAs < float > ( u " wanderRadius " ) ;
if ( wanderOverride ! = 0.0f ) {
moveInfo . wanderRadius = wanderOverride ;
}
}
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MOVEMENT_AI , new MovementAIComponent ( this , moveInfo ) ) ) ;
}
} else if ( petComponentId > 0 | | combatAiId > 0 & & GetComponent < BaseCombatAIComponent > ( ) - > GetTetherSpeed ( ) > 0 ) {
MovementAIInfo moveInfo = MovementAIInfo ( ) ;
moveInfo . movementType = " " ;
moveInfo . wanderChance = 0 ;
moveInfo . wanderRadius = 16 ;
moveInfo . wanderSpeed = 2.5f ;
moveInfo . wanderDelayMax = 5 ;
moveInfo . wanderDelayMin = 2 ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MOVEMENT_AI , new MovementAIComponent ( this , moveInfo ) ) ) ;
}
2022-11-12 14:44:27 +00:00
std : : string pathName = GetVarAsString ( u " attached_path " ) ;
const Path * path = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetPath ( pathName ) ;
//Check to see if we have an attached path and add the appropiate component to handle it:
if ( path ) {
// if we have a moving platform path, then we need a moving platform component
if ( path - > pathType = = PathType : : MovingPlatform ) {
MovingPlatformComponent * plat = new MovingPlatformComponent ( this , pathName ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_MOVING_PLATFORM , plat ) ) ;
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent < MovementAIComponent > ( ) ;
if ( movementAIcomp ) {
// TODO: set path in existing movementAIComp
} else {
// TODO: create movementAIcomp and set path
}
} */
}
2021-12-05 17:54:36 +00:00
int proximityMonitorID = compRegistryTable - > GetByIDAndType ( m_TemplateID , COMPONENT_TYPE_PROXIMITY_MONITOR ) ;
if ( proximityMonitorID > 0 ) {
CDProximityMonitorComponentTable * proxCompTable = CDClientManager : : Instance ( ) - > GetTable < CDProximityMonitorComponentTable > ( " ProximityMonitorComponent " ) ;
std : : vector < CDProximityMonitorComponent > proxCompData = proxCompTable - > Query ( [ = ] ( CDProximityMonitorComponent entry ) { return ( entry . id = = proximityMonitorID ) ; } ) ;
if ( proxCompData . size ( ) > 0 ) {
std : : vector < std : : string > proximityStr = GeneralUtils : : SplitString ( proxCompData [ 0 ] . Proximities , ' , ' ) ;
ProximityMonitorComponent * comp = new ProximityMonitorComponent ( this , std : : stoi ( proximityStr [ 0 ] ) , std : : stoi ( proximityStr [ 1 ] ) ) ;
m_Components . insert ( std : : make_pair ( COMPONENT_TYPE_PROXIMITY_MONITOR , comp ) ) ;
}
}
// Hacky way to trigger these when the object has had a chance to get constructed
AddCallbackTimer ( 0 , [ this ] ( ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnStartup ( this ) ;
}
} ) ;
if ( ! m_Character & & EntityManager : : Instance ( ) - > GetGhostingEnabled ( ) ) {
// Don't ghost what is likely large scene elements
if ( m_Components . size ( ) = = 2 & & HasComponent ( COMPONENT_TYPE_SIMPLE_PHYSICS ) & & HasComponent ( COMPONENT_TYPE_RENDER ) ) {
goto no_ghosting ;
}
/* Filter for ghosting candidates.
*
* Don ' t ghost moving platforms , until we ' ve got proper syncing for those .
* Don ' t ghost big phantom physics triggers , as putting those to sleep might prevent interactions .
* Don ' t ghost property related objects , as the client expects those to always be loaded .
*/
if (
! EntityManager : : IsExcludedFromGhosting ( GetLOT ( ) ) & &
! HasComponent ( COMPONENT_TYPE_SCRIPTED_ACTIVITY ) & &
! HasComponent ( COMPONENT_TYPE_MOVING_PLATFORM ) & &
! HasComponent ( COMPONENT_TYPE_PHANTOM_PHYSICS ) & &
! HasComponent ( COMPONENT_TYPE_PROPERTY ) & &
! HasComponent ( COMPONENT_TYPE_RACING_CONTROL ) & &
! HasComponent ( COMPONENT_TYPE_VEHICLE_PHYSICS )
)
//if (HasComponent(COMPONENT_TYPE_BASE_COMBAT_AI))
{
m_IsGhostingCandidate = true ;
}
if ( GetLOT ( ) = = 6368 ) {
m_IsGhostingCandidate = true ;
}
// Special case for collectibles in Ninjago
if ( HasComponent ( COMPONENT_TYPE_COLLECTIBLE ) & & Game : : server - > GetZoneID ( ) = = 2000 ) {
m_IsGhostingCandidate = true ;
}
}
no_ghosting :
TriggerEvent ( " OnCreate " ) ;
if ( m_Character ) {
auto * controllablePhysicsComponent = GetComponent < ControllablePhysicsComponent > ( ) ;
2022-07-24 18:04:02 +00:00
auto * levelComponent = GetComponent < LevelProgressionComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-24 18:04:02 +00:00
if ( controllablePhysicsComponent ! = nullptr & & levelComponent - > GetLevel ( ) > = 20 ) {
2021-12-05 17:54:36 +00:00
controllablePhysicsComponent - > SetSpeedMultiplier ( 525.0f / 500.0f ) ;
}
}
}
bool Entity : : operator = = ( const Entity & other ) const {
return other . m_ObjectID = = m_ObjectID ;
}
bool Entity : : operator ! = ( const Entity & other ) const {
return other . m_ObjectID ! = m_ObjectID ;
}
User * Entity : : GetParentUser ( ) const {
if ( ! IsPlayer ( ) ) {
return nullptr ;
}
return static_cast < const Player * > ( this ) - > GetParentUser ( ) ;
}
Component * Entity : : GetComponent ( int32_t componentID ) const {
const auto & index = m_Components . find ( componentID ) ;
if ( index = = m_Components . end ( ) ) {
return nullptr ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return index - > second ;
}
bool Entity : : HasComponent ( const int32_t componentId ) const {
return m_Components . find ( componentId ) ! = m_Components . end ( ) ;
}
void Entity : : AddComponent ( const int32_t componentId , Component * component ) {
if ( HasComponent ( componentId ) ) {
return ;
}
m_Components . insert_or_assign ( componentId , component ) ;
}
std : : vector < ScriptComponent * > Entity : : GetScriptComponents ( ) {
std : : vector < ScriptComponent * > comps ;
for ( std : : pair < int32_t , void * > p : m_Components ) {
if ( p . first = = COMPONENT_TYPE_SCRIPT ) {
comps . push_back ( static_cast < ScriptComponent * > ( p . second ) ) ;
}
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return comps ;
}
void Entity : : SetProximityRadius ( float proxRadius , std : : string name ) {
ProximityMonitorComponent * proxMon = GetComponent < ProximityMonitorComponent > ( ) ;
if ( ! proxMon ) {
proxMon = new ProximityMonitorComponent ( this ) ;
m_Components . insert_or_assign ( COMPONENT_TYPE_PROXIMITY_MONITOR , proxMon ) ;
}
proxMon - > SetProximityRadius ( proxRadius , name ) ;
}
void Entity : : SetProximityRadius ( dpEntity * entity , std : : string name ) {
ProximityMonitorComponent * proxMon = GetComponent < ProximityMonitorComponent > ( ) ;
if ( ! proxMon ) {
proxMon = new ProximityMonitorComponent ( this ) ;
m_Components . insert_or_assign ( COMPONENT_TYPE_PROXIMITY_MONITOR , proxMon ) ;
}
proxMon - > SetProximityRadius ( entity , name ) ;
}
void Entity : : SetGMLevel ( uint8_t value ) {
m_GMLevel = value ;
if ( GetParentUser ( ) ) {
Character * character = GetParentUser ( ) - > GetLastUsedChar ( ) ;
if ( character ) {
character - > SetGMLevel ( value ) ;
}
}
CharacterComponent * character = GetComponent < CharacterComponent > ( ) ;
if ( character ) character - > SetGMLevel ( value ) ;
GameMessages : : SendGMLevelBroadcast ( m_ObjectID , value ) ;
}
void Entity : : WriteBaseReplicaData ( RakNet : : BitStream * outBitStream , eReplicaPacketType packetType ) {
if ( packetType = = PACKET_TYPE_CONSTRUCTION ) {
outBitStream - > Write ( m_ObjectID ) ;
outBitStream - > Write ( m_TemplateID ) ;
if ( IsPlayer ( ) ) {
std : : string name = m_Character ! = nullptr ? m_Character - > GetName ( ) : " Invalid " ;
outBitStream - > Write < uint8_t > ( uint8_t ( name . size ( ) ) ) ;
for ( size_t i = 0 ; i < name . size ( ) ; + + i ) {
outBitStream - > Write < uint16_t > ( name [ i ] ) ;
}
} else {
const auto & name = GetVar < std : : string > ( u " npcName " ) ;
outBitStream - > Write < uint8_t > ( uint8_t ( name . size ( ) ) ) ;
for ( size_t i = 0 ; i < name . size ( ) ; + + i ) {
outBitStream - > Write < uint16_t > ( name [ i ] ) ;
}
}
outBitStream - > Write < uint32_t > ( 0 ) ; //Time since created on server
const auto & syncLDF = GetVar < std : : vector < std : : u16string > > ( u " syncLDF " ) ;
2022-07-19 21:51:35 +00:00
// Only sync for models.
if ( m_Settings . size ( ) > 0 & & ( GetComponent < ModelComponent > ( ) & & ! GetComponent < PetComponent > ( ) ) ) {
2021-12-05 17:54:36 +00:00
outBitStream - > Write1 ( ) ; //ldf data
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
RakNet : : BitStream settingStream ;
settingStream . Write < uint32_t > ( m_Settings . size ( ) ) ;
for ( LDFBaseData * data : m_Settings ) {
if ( data ) {
data - > WriteToPacket ( & settingStream ) ;
}
}
outBitStream - > Write ( settingStream . GetNumberOfBytesUsed ( ) + 1 ) ;
outBitStream - > Write < uint8_t > ( 0 ) ; //no compression used
outBitStream - > Write ( settingStream ) ;
} else if ( ! syncLDF . empty ( ) ) {
std : : vector < LDFBaseData * > ldfData ;
for ( const auto & data : syncLDF ) {
ldfData . push_back ( GetVarData ( data ) ) ;
}
outBitStream - > Write1 ( ) ; //ldf data
RakNet : : BitStream settingStream ;
settingStream . Write < uint32_t > ( ldfData . size ( ) ) ;
for ( LDFBaseData * data : ldfData ) {
if ( data ) {
data - > WriteToPacket ( & settingStream ) ;
}
}
outBitStream - > Write ( settingStream . GetNumberOfBytesUsed ( ) + 1 ) ;
outBitStream - > Write < uint8_t > ( 0 ) ; //no compression used
outBitStream - > Write ( settingStream ) ;
} else {
outBitStream - > Write0 ( ) ; //No ldf data
}
if ( m_Trigger ! = nullptr & & m_Trigger - > events . size ( ) > 0 ) {
outBitStream - > Write1 ( ) ;
} else {
outBitStream - > Write0 ( ) ;
}
if ( m_ParentEntity ! = nullptr | | m_SpawnerID ! = 0 ) {
outBitStream - > Write1 ( ) ;
if ( m_ParentEntity ! = nullptr ) outBitStream - > Write ( GeneralUtils : : SetBit ( m_ParentEntity - > GetObjectID ( ) , OBJECT_BIT_CLIENT ) ) ;
else if ( m_Spawner ! = nullptr & & m_Spawner - > m_Info . isNetwork ) outBitStream - > Write ( m_SpawnerID ) ;
else outBitStream - > Write ( GeneralUtils : : SetBit ( m_SpawnerID , OBJECT_BIT_CLIENT ) ) ;
} else outBitStream - > Write0 ( ) ;
outBitStream - > Write ( m_HasSpawnerNodeID ) ;
if ( m_HasSpawnerNodeID ) outBitStream - > Write ( m_SpawnerNodeID ) ;
//outBitStream->Write0(); //Spawner node id
if ( m_Scale = = 1.0f | | m_Scale = = 0.0f ) outBitStream - > Write0 ( ) ;
else {
outBitStream - > Write1 ( ) ;
outBitStream - > Write ( m_Scale ) ;
}
outBitStream - > Write0 ( ) ; //ObjectWorldState
if ( m_GMLevel ! = 0 ) {
outBitStream - > Write1 ( ) ;
outBitStream - > Write ( m_GMLevel ) ;
} else outBitStream - > Write0 ( ) ; //No GM Level
}
2022-07-28 13:39:57 +00:00
2022-06-16 06:04:03 +00:00
// Only serialize parent / child info should the info be dirty (changed) or if this is the construction of the entity.
2022-06-16 15:38:38 +00:00
outBitStream - > Write ( m_IsParentChildDirty | | packetType = = PACKET_TYPE_CONSTRUCTION ) ;
if ( m_IsParentChildDirty | | packetType = = PACKET_TYPE_CONSTRUCTION ) {
2022-06-16 05:58:38 +00:00
m_IsParentChildDirty = false ;
2021-12-05 17:54:36 +00:00
outBitStream - > Write ( m_ParentEntity ! = nullptr ) ;
if ( m_ParentEntity ) {
outBitStream - > Write ( m_ParentEntity - > GetObjectID ( ) ) ;
outBitStream - > Write0 ( ) ;
}
outBitStream - > Write ( m_ChildEntities . size ( ) > 0 ) ;
if ( m_ChildEntities . size ( ) > 0 ) {
outBitStream - > Write ( ( uint16_t ) m_ChildEntities . size ( ) ) ;
for ( Entity * child : m_ChildEntities ) {
outBitStream - > Write ( ( uint64_t ) child - > GetObjectID ( ) ) ;
}
}
}
}
void Entity : : WriteComponents ( RakNet : : BitStream * outBitStream , eReplicaPacketType packetType ) {
/**
* This has to be done in a specific order .
*/
bool destroyableSerialized = false ;
bool bIsInitialUpdate = false ;
if ( packetType = = PACKET_TYPE_CONSTRUCTION ) bIsInitialUpdate = true ;
unsigned int flags = 0 ;
PossessableComponent * possessableComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_POSSESSABLE , possessableComponent ) ) {
possessableComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
ModuleAssemblyComponent * moduleAssemblyComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_MODULE_ASSEMBLY , moduleAssemblyComponent ) ) {
moduleAssemblyComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
ControllablePhysicsComponent * controllablePhysicsComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_CONTROLLABLE_PHYSICS , controllablePhysicsComponent ) ) {
controllablePhysicsComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
SimplePhysicsComponent * simplePhysicsComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SIMPLE_PHYSICS , simplePhysicsComponent ) ) {
simplePhysicsComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
RigidbodyPhantomPhysicsComponent * rigidbodyPhantomPhysics ;
if ( TryGetComponent ( COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS , rigidbodyPhantomPhysics ) ) {
rigidbodyPhantomPhysics - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
VehiclePhysicsComponent * vehiclePhysicsComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_VEHICLE_PHYSICS , vehiclePhysicsComponent ) ) {
vehiclePhysicsComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
PhantomPhysicsComponent * phantomPhysicsComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_PHANTOM_PHYSICS , phantomPhysicsComponent ) ) {
phantomPhysicsComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
SoundTriggerComponent * soundTriggerComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SOUND_TRIGGER , soundTriggerComponent ) ) {
soundTriggerComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
BuffComponent * buffComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_BUFF , buffComponent ) ) {
buffComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
DestroyableComponent * destroyableComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) ) {
destroyableComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
destroyableSerialized = true ;
}
if ( HasComponent ( COMPONENT_TYPE_COLLECTIBLE ) ) {
DestroyableComponent * destroyableComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) & & ! destroyableSerialized ) {
destroyableComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
destroyableSerialized = true ;
outBitStream - > Write ( m_CollectibleID ) ; // Collectable component
}
PetComponent * petComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_PET , petComponent ) ) {
petComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
CharacterComponent * characterComponent ;
2022-06-29 23:50:24 +00:00
if ( TryGetComponent ( COMPONENT_TYPE_CHARACTER , characterComponent ) ) {
PossessorComponent * possessorComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_POSSESSOR , possessorComponent ) ) {
possessorComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
} else {
// Should never happen, but just to be safe
outBitStream - > Write0 ( ) ;
}
2022-07-24 18:04:02 +00:00
LevelProgressionComponent * levelProgressionComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_LEVEL_PROGRESSION , levelProgressionComponent ) ) {
levelProgressionComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
} else {
// Should never happen, but just to be safe
outBitStream - > Write0 ( ) ;
}
2022-07-24 18:25:10 +00:00
PlayerForcedMovementComponent * playerForcedMovementComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT , playerForcedMovementComponent ) ) {
playerForcedMovementComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
} else {
// Should never happen, but just to be safe
outBitStream - > Write0 ( ) ;
}
2021-12-05 17:54:36 +00:00
characterComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
if ( HasComponent ( COMPONENT_TYPE_ITEM ) ) {
outBitStream - > Write0 ( ) ;
}
InventoryComponent * inventoryComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_INVENTORY , inventoryComponent ) ) {
inventoryComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
ScriptComponent * scriptComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SCRIPT , scriptComponent ) ) {
scriptComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
SkillComponent * skillComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SKILL , skillComponent ) ) {
skillComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
BaseCombatAIComponent * baseCombatAiComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_BASE_COMBAT_AI , baseCombatAiComponent ) ) {
baseCombatAiComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
RebuildComponent * rebuildComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_REBUILD , rebuildComponent ) ) {
DestroyableComponent * destroyableComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) & & ! destroyableSerialized ) {
destroyableComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
destroyableSerialized = true ;
rebuildComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
MovingPlatformComponent * movingPlatformComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_MOVING_PLATFORM , movingPlatformComponent ) ) {
movingPlatformComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
SwitchComponent * switchComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SWITCH , switchComponent ) ) {
switchComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
VendorComponent * vendorComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_VENDOR , vendorComponent ) ) {
vendorComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
BouncerComponent * bouncerComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_BOUNCER , bouncerComponent ) ) {
bouncerComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
ScriptedActivityComponent * scriptedActivityComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SCRIPTED_ACTIVITY , scriptedActivityComponent ) ) {
scriptedActivityComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
ShootingGalleryComponent * shootingGalleryComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_SHOOTING_GALLERY , shootingGalleryComponent ) ) {
shootingGalleryComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
RacingControlComponent * racingControlComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_RACING_CONTROL , racingControlComponent ) ) {
racingControlComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
LUPExhibitComponent * lupExhibitComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_EXHIBIT , lupExhibitComponent ) ) {
lupExhibitComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
ModelComponent * modelComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_MODEL , modelComponent ) ) {
modelComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
RenderComponent * renderComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_RENDER , renderComponent ) ) {
renderComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
}
2022-07-19 21:51:35 +00:00
if ( modelComponent ) {
DestroyableComponent * destroyableComponent ;
if ( TryGetComponent ( COMPONENT_TYPE_DESTROYABLE , destroyableComponent ) & & ! destroyableSerialized ) {
destroyableComponent - > Serialize ( outBitStream , bIsInitialUpdate , flags ) ;
destroyableSerialized = true ;
}
}
2021-12-05 17:54:36 +00:00
if ( HasComponent ( COMPONENT_TYPE_ZONE_CONTROL ) ) {
outBitStream - > Write < uint32_t > ( 0x40000000 ) ;
}
2022-06-29 23:50:24 +00:00
// BBB Component, unused currently
2022-07-19 21:51:35 +00:00
// Need to to write0 so that is serialized correctly
2022-06-29 23:50:24 +00:00
// TODO: Implement BBB Component
outBitStream - > Write0 ( ) ;
2021-12-05 17:54:36 +00:00
}
void Entity : : ResetFlags ( ) {
// Unused
}
void Entity : : UpdateXMLDoc ( tinyxml2 : : XMLDocument * doc ) {
//This function should only ever be called from within Character, meaning doc should always exist when this is called.
//Naturally, we don't include any non-player components in this update function.
for ( const auto & pair : m_Components ) {
if ( pair . second = = nullptr ) continue ;
pair . second - > UpdateXml ( doc ) ;
}
}
void Entity : : Update ( const float deltaTime ) {
2022-07-17 01:21:35 +00:00
uint32_t timerPosition ;
timerPosition = 0 ;
while ( timerPosition < m_Timers . size ( ) ) {
m_Timers [ timerPosition ] - > Update ( deltaTime ) ;
if ( m_Timers [ timerPosition ] - > GetTime ( ) < = 0 ) {
const auto timerName = m_Timers [ timerPosition ] - > GetName ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-17 01:21:35 +00:00
delete m_Timers [ timerPosition ] ;
m_Timers . erase ( m_Timers . begin ( ) + timerPosition ) ;
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnTimerDone ( this , timerName ) ;
}
2022-07-17 01:21:35 +00:00
} else {
timerPosition + + ;
2021-12-05 17:54:36 +00:00
}
}
for ( int i = 0 ; i < m_CallbackTimers . size ( ) ; i + + ) {
m_CallbackTimers [ i ] - > Update ( deltaTime ) ;
if ( m_CallbackTimers [ i ] - > GetTime ( ) < = 0 ) {
m_CallbackTimers [ i ] - > GetCallback ( ) ( ) ;
delete m_CallbackTimers [ i ] ;
m_CallbackTimers . erase ( m_CallbackTimers . begin ( ) + i ) ;
}
}
2022-07-28 13:39:57 +00:00
2022-07-17 01:21:35 +00:00
// Add pending timers to the list of timers so they start next tick.
if ( m_PendingTimers . size ( ) > 0 ) {
for ( auto namedTimer : m_PendingTimers ) {
m_Timers . push_back ( namedTimer ) ;
}
m_PendingTimers . clear ( ) ;
}
2021-12-05 17:54:36 +00:00
if ( IsSleeping ( ) ) {
Sleep ( ) ;
return ;
} else {
Wake ( ) ;
}
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnUpdate ( this ) ;
}
for ( const auto & pair : m_Components ) {
if ( pair . second = = nullptr ) continue ;
pair . second - > Update ( deltaTime ) ;
}
if ( m_ShouldDestroyAfterUpdate ) {
EntityManager : : Instance ( ) - > DestroyEntity ( this - > GetObjectID ( ) ) ;
}
}
void Entity : : OnCollisionProximity ( LWOOBJID otherEntity , const std : : string & proxName , const std : : string & status ) {
Entity * other = EntityManager : : Instance ( ) - > GetEntity ( otherEntity ) ;
if ( ! other ) return ;
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnProximityUpdate ( this , other , proxName , status ) ;
}
RocketLaunchpadControlComponent * rocketComp = GetComponent < RocketLaunchpadControlComponent > ( ) ;
if ( ! rocketComp ) return ;
rocketComp - > OnProximityUpdate ( other , proxName , status ) ;
}
void Entity : : OnCollisionPhantom ( const LWOOBJID otherEntity ) {
auto * other = EntityManager : : Instance ( ) - > GetEntity ( otherEntity ) ;
if ( ! other ) return ;
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnCollisionPhantom ( this , other ) ;
}
for ( const auto & callback : m_PhantomCollisionCallbacks ) {
callback ( other ) ;
}
SwitchComponent * switchComp = GetComponent < SwitchComponent > ( ) ;
if ( switchComp ) {
switchComp - > EntityEnter ( other ) ;
}
TriggerEvent ( " OnEnter " , other ) ;
// POI system
const auto & poi = GetVar < std : : u16string > ( u " POI " ) ;
if ( ! poi . empty ( ) ) {
auto * missionComponent = other - > GetComponent < MissionComponent > ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( missionComponent ! = nullptr ) {
missionComponent - > Progress ( MissionTaskType : : MISSION_TASK_TYPE_LOCATION , 0 , 0 , GeneralUtils : : UTF16ToWTF8 ( poi ) ) ;
}
}
if ( ! other - > GetIsDead ( ) ) {
auto * combat = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( combat ! = nullptr ) {
const auto index = std : : find ( m_TargetsInPhantom . begin ( ) , m_TargetsInPhantom . end ( ) , otherEntity ) ;
if ( index ! = m_TargetsInPhantom . end ( ) ) return ;
const auto valid = combat - > IsEnemy ( otherEntity ) ;
if ( ! valid ) return ;
m_TargetsInPhantom . push_back ( otherEntity ) ;
}
}
}
void Entity : : OnCollisionLeavePhantom ( const LWOOBJID otherEntity ) {
auto * other = EntityManager : : Instance ( ) - > GetEntity ( otherEntity ) ;
if ( ! other ) return ;
TriggerEvent ( " OnLeave " , other ) ;
SwitchComponent * switchComp = GetComponent < SwitchComponent > ( ) ;
if ( switchComp ) {
switchComp - > EntityLeave ( other ) ;
}
const auto index = std : : find ( m_TargetsInPhantom . begin ( ) , m_TargetsInPhantom . end ( ) , otherEntity ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( index = = m_TargetsInPhantom . end ( ) ) return ;
m_TargetsInPhantom . erase ( index ) ;
}
void Entity : : OnFireEventServerSide ( Entity * sender , std : : string args , int32_t param1 , int32_t param2 , int32_t param3 ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnFireEventServerSide ( this , sender , args , param1 , param2 , param3 ) ;
}
}
void Entity : : OnActivityStateChangeRequest ( LWOOBJID senderID , int32_t value1 , int32_t value2 , const std : : u16string & stringValue ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnActivityStateChangeRequest ( this , senderID , value1 , value2 , stringValue ) ;
}
}
void Entity : : OnCinematicUpdate ( Entity * self , Entity * sender , eCinematicEvent event , const std : : u16string & pathName ,
float_t pathTime , float_t totalTime , int32_t waypoint ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnCinematicUpdate ( self , sender , event , pathName , pathTime , totalTime , waypoint ) ;
}
}
void Entity : : NotifyObject ( Entity * sender , const std : : string & name , int32_t param1 , int32_t param2 ) {
GameMessages : : SendNotifyObject ( GetObjectID ( ) , sender - > GetObjectID ( ) , GeneralUtils : : ASCIIToUTF16 ( name ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnNotifyObject ( this , sender , name , param1 , param2 ) ;
}
}
void Entity : : OnEmoteReceived ( const int32_t emote , Entity * target ) {
for ( auto * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnEmoteReceived ( this , emote , target ) ;
}
}
void Entity : : OnUse ( Entity * originator ) {
TriggerEvent ( " OnInteract " ) ;
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnUse ( this , originator ) ;
}
// component base class when
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
for ( const auto & pair : m_Components ) {
if ( pair . second = = nullptr ) continue ;
pair . second - > OnUse ( originator ) ;
}
}
void Entity : : OnHitOrHealResult ( Entity * attacker , int32_t damage ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnHitOrHealResult ( this , attacker , damage ) ;
}
}
void Entity : : OnHit ( Entity * attacker ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnHit ( this , attacker ) ;
}
}
void Entity : : OnZonePropertyEditBegin ( ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyEditBegin ( this ) ;
}
}
void Entity : : OnZonePropertyEditEnd ( ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyEditEnd ( this ) ;
}
}
void Entity : : OnZonePropertyModelEquipped ( ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelEquipped ( this ) ;
}
}
void Entity : : OnZonePropertyModelPlaced ( Entity * player ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelPlaced ( this , player ) ;
}
}
void Entity : : OnZonePropertyModelPickedUp ( Entity * player ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelPickedUp ( this , player ) ;
}
}
void Entity : : OnZonePropertyModelRemoved ( Entity * player ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRemoved ( this , player ) ;
}
}
void Entity : : OnZonePropertyModelRemovedWhileEquipped ( Entity * player ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRemovedWhileEquipped ( this , player ) ;
}
}
void Entity : : OnZonePropertyModelRotated ( Entity * player ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRotated ( this , player ) ;
}
}
void Entity : : OnMessageBoxResponse ( Entity * sender , int32_t button , const std : : u16string & identifier , const std : : u16string & userData ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnMessageBoxResponse ( this , sender , button , identifier , userData ) ;
}
}
void Entity : : OnChoiceBoxResponse ( Entity * sender , int32_t button , const std : : u16string & buttonIdentifier , const std : : u16string & identifier ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnChoiceBoxResponse ( this , sender , button , buttonIdentifier , identifier ) ;
}
}
void Entity : : Smash ( const LWOOBJID source , const eKillType killType , const std : : u16string & deathType ) {
if ( ! m_PlayerIsReadyForUpdates ) return ;
auto * destroyableComponent = GetComponent < DestroyableComponent > ( ) ;
if ( destroyableComponent = = nullptr ) {
Kill ( EntityManager : : Instance ( ) - > GetEntity ( source ) ) ;
return ;
}
2022-09-02 18:49:19 +00:00
auto * possessorComponent = GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent ) {
if ( possessorComponent - > GetPossessable ( ) ! = LWOOBJID_EMPTY ) {
auto * mount = EntityManager : : Instance ( ) - > GetEntity ( possessorComponent - > GetPossessable ( ) ) ;
if ( mount ) possessorComponent - > Dismount ( mount , true ) ;
}
}
2021-12-05 17:54:36 +00:00
destroyableComponent - > Smash ( source , killType , deathType ) ;
}
void Entity : : Kill ( Entity * murderer ) {
if ( ! m_PlayerIsReadyForUpdates ) return ;
for ( const auto & cb : m_DieCallbacks ) {
cb ( ) ;
}
m_DieCallbacks . clear ( ) ;
//OMAI WA MOU, SHINDERIU
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnDie ( this , murderer ) ;
}
if ( m_Spawner ! = nullptr ) {
m_Spawner - > NotifyOfEntityDeath ( m_ObjectID ) ;
}
if ( ! IsPlayer ( ) ) {
EntityManager : : Instance ( ) - > DestroyEntity ( this ) ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
const auto & grpNameQBShowBricks = GetVar < std : : string > ( u " grpNameQBShowBricks " ) ;
if ( ! grpNameQBShowBricks . empty ( ) ) {
auto spawners = dZoneManager : : Instance ( ) - > GetSpawnersByName ( grpNameQBShowBricks ) ;
Spawner * spawner = nullptr ;
if ( ! spawners . empty ( ) ) {
spawner = spawners [ 0 ] ;
} else {
spawners = dZoneManager : : Instance ( ) - > GetSpawnersInGroup ( grpNameQBShowBricks ) ;
if ( ! spawners . empty ( ) ) {
spawner = spawners [ 0 ] ;
}
}
if ( spawner ! = nullptr ) {
spawner - > Spawn ( ) ;
}
}
// Track a player being smashed
auto * characterComponent = GetComponent < CharacterComponent > ( ) ;
if ( characterComponent ! = nullptr ) {
characterComponent - > UpdatePlayerStatistic ( TimesSmashed ) ;
}
// Track a player smashing something else
if ( murderer ! = nullptr ) {
auto * murdererCharacterComponent = murderer - > GetComponent < CharacterComponent > ( ) ;
if ( murdererCharacterComponent ! = nullptr ) {
murdererCharacterComponent - > UpdatePlayerStatistic ( SmashablesSmashed ) ;
}
}
}
void Entity : : AddDieCallback ( const std : : function < void ( ) > & callback ) {
m_DieCallbacks . push_back ( callback ) ;
}
void Entity : : AddCollisionPhantomCallback ( const std : : function < void ( Entity * target ) > & callback ) {
m_PhantomCollisionCallbacks . push_back ( callback ) ;
}
void Entity : : AddRebuildCompleteCallback ( const std : : function < void ( Entity * user ) > & callback ) const {
auto * rebuildComponent = GetComponent < RebuildComponent > ( ) ;
if ( rebuildComponent ! = nullptr ) {
rebuildComponent - > AddRebuildCompleteCallback ( callback ) ;
}
}
bool Entity : : GetIsDead ( ) const {
DestroyableComponent * dest = GetComponent < DestroyableComponent > ( ) ;
if ( dest & & dest - > GetArmor ( ) = = 0 & & dest - > GetHealth ( ) = = 0 ) return true ;
return false ;
}
void Entity : : AddLootItem ( const Loot : : Info & info ) {
if ( ! IsPlayer ( ) ) return ;
auto & droppedLoot = static_cast < Player * > ( this ) - > GetDroppedLoot ( ) ;
droppedLoot . insert ( std : : make_pair ( info . id , info ) ) ;
}
void Entity : : PickupItem ( const LWOOBJID & objectID ) {
if ( ! IsPlayer ( ) ) return ;
InventoryComponent * inv = GetComponent < InventoryComponent > ( ) ;
if ( ! inv ) return ;
CDObjectsTable * objectsTable = CDClientManager : : Instance ( ) - > GetTable < CDObjectsTable > ( " Objects " ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
auto & droppedLoot = static_cast < Player * > ( this ) - > GetDroppedLoot ( ) ;
for ( const auto & p : droppedLoot ) {
if ( p . first = = objectID ) {
auto * characterComponent = GetComponent < CharacterComponent > ( ) ;
if ( characterComponent ! = nullptr ) {
characterComponent - > TrackLOTCollection ( p . second . lot ) ;
}
const CDObjects & object = objectsTable - > GetByID ( p . second . lot ) ;
if ( object . id ! = 0 & & object . type = = " Powerup " ) {
CDObjectSkillsTable * skillsTable = CDClientManager : : Instance ( ) - > GetTable < CDObjectSkillsTable > ( " ObjectSkills " ) ;
std : : vector < CDObjectSkills > skills = skillsTable - > Query ( [ = ] ( CDObjectSkills entry ) { return ( entry . objectTemplate = = p . second . lot ) ; } ) ;
for ( CDObjectSkills skill : skills ) {
CDSkillBehaviorTable * skillBehTable = CDClientManager : : Instance ( ) - > GetTable < CDSkillBehaviorTable > ( " SkillBehavior " ) ;
CDSkillBehavior behaviorData = skillBehTable - > GetSkillByID ( skill . skillID ) ;
SkillComponent : : HandleUnmanaged ( behaviorData . behaviorID , GetObjectID ( ) ) ;
auto * missionComponent = GetComponent < MissionComponent > ( ) ;
if ( missionComponent ! = nullptr ) {
missionComponent - > Progress ( MissionTaskType : : MISSION_TASK_TYPE_POWERUP , skill . skillID ) ;
}
}
} else {
2022-04-24 03:35:34 +00:00
inv - > AddItem ( p . second . lot , p . second . count , eLootSourceType : : LOOT_SOURCE_PICKUP , eInventoryType : : INVALID , { } , LWOOBJID_EMPTY , true , false , LWOOBJID_EMPTY , eInventoryType : : INVALID , 1 ) ;
2021-12-05 17:54:36 +00:00
}
}
}
droppedLoot . erase ( objectID ) ;
}
2021-12-11 16:33:54 +00:00
bool Entity : : CanPickupCoins ( uint64_t count ) {
2021-12-11 13:21:00 +00:00
if ( ! IsPlayer ( ) ) return false ;
2021-12-11 16:33:54 +00:00
auto * player = static_cast < Player * > ( this ) ;
auto droppedCoins = player - > GetDroppedCoins ( ) ;
if ( count > droppedCoins ) {
2021-12-11 13:21:00 +00:00
return false ;
} else {
2021-12-11 16:33:54 +00:00
player - > SetDroppedCoins ( droppedCoins - count ) ;
2021-12-11 13:21:00 +00:00
return true ;
}
}
2021-12-11 13:57:15 +00:00
void Entity : : RegisterCoinDrop ( uint64_t count ) {
2021-12-11 13:21:00 +00:00
if ( ! IsPlayer ( ) ) return ;
2021-12-11 16:33:54 +00:00
auto * player = static_cast < Player * > ( this ) ;
auto droppedCoins = player - > GetDroppedCoins ( ) ;
droppedCoins + = count ;
player - > SetDroppedCoins ( droppedCoins ) ;
2021-12-11 13:21:00 +00:00
}
2021-12-05 17:54:36 +00:00
void Entity : : AddChild ( Entity * child ) {
2022-06-16 05:58:38 +00:00
m_IsParentChildDirty = true ;
2021-12-05 17:54:36 +00:00
m_ChildEntities . push_back ( child ) ;
}
2022-06-17 00:50:33 +00:00
void Entity : : RemoveChild ( Entity * child ) {
if ( ! child ) return ;
2022-07-17 04:39:13 +00:00
uint32_t entityPosition = 0 ;
while ( entityPosition < m_ChildEntities . size ( ) ) {
if ( ! m_ChildEntities [ entityPosition ] | | ( m_ChildEntities [ entityPosition ] ) - > GetObjectID ( ) = = child - > GetObjectID ( ) ) {
2022-06-17 00:50:33 +00:00
m_IsParentChildDirty = true ;
2022-07-17 04:39:13 +00:00
m_ChildEntities . erase ( m_ChildEntities . begin ( ) + entityPosition ) ;
} else {
entityPosition + + ;
2022-06-17 00:50:33 +00:00
}
}
}
2022-07-17 04:39:13 +00:00
void Entity : : RemoveParent ( ) {
this - > m_ParentEntity = nullptr ;
}
2021-12-05 17:54:36 +00:00
void Entity : : AddTimer ( std : : string name , float time ) {
EntityTimer * timer = new EntityTimer ( name , time ) ;
2022-07-17 01:21:35 +00:00
m_PendingTimers . push_back ( timer ) ;
2021-12-05 17:54:36 +00:00
}
void Entity : : AddCallbackTimer ( float time , std : : function < void ( ) > callback ) {
EntityCallbackTimer * timer = new EntityCallbackTimer ( time , callback ) ;
m_CallbackTimers . push_back ( timer ) ;
}
bool Entity : : HasTimer ( const std : : string & name ) {
for ( auto * timer : m_Timers ) {
if ( timer - > GetName ( ) = = name ) {
return true ;
}
}
return false ;
}
void Entity : : CancelCallbackTimers ( ) {
for ( auto * callback : m_CallbackTimers ) {
delete callback ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
m_CallbackTimers . clear ( ) ;
}
void Entity : : ScheduleKillAfterUpdate ( Entity * murderer ) {
//if (m_Info.spawner) m_Info.spawner->ScheduleKill(this);
EntityManager : : Instance ( ) - > ScheduleForKill ( this ) ;
if ( murderer ) m_ScheduleKiller = murderer ;
}
void Entity : : CancelTimer ( const std : : string & name ) {
for ( int i = 0 ; i < m_Timers . size ( ) ; i + + ) {
if ( m_Timers [ i ] - > GetName ( ) = = name ) {
delete m_Timers [ i ] ;
m_Timers . erase ( m_Timers . begin ( ) + i ) ;
return ;
}
}
}
void Entity : : CancelAllTimers ( ) {
/*for (auto timer : m_Timers) {
if ( timer ) delete timer ;
} */
for ( auto * timer : m_Timers ) {
delete timer ;
}
m_Timers . clear ( ) ;
for ( auto * callBackTimer : m_CallbackTimers ) {
delete callBackTimer ;
}
m_CallbackTimers . clear ( ) ;
}
bool Entity : : IsPlayer ( ) const {
2022-04-24 03:35:39 +00:00
return m_TemplateID = = 1 & & GetSystemAddress ( ) ! = UNASSIGNED_SYSTEM_ADDRESS ;
2021-12-05 17:54:36 +00:00
}
void Entity : : TriggerEvent ( std : : string eventID , Entity * optionalTarget ) {
if ( m_Trigger ! = nullptr & & m_Trigger - > enabled ) {
for ( LUTriggers : : Event * triggerEvent : m_Trigger - > events ) {
if ( triggerEvent - > eventID = = eventID ) {
for ( LUTriggers : : Command * cmd : triggerEvent - > commands ) {
HandleTriggerCommand ( cmd - > id , cmd - > target , cmd - > targetName , cmd - > args , optionalTarget ) ;
}
}
}
}
}
// This should probably get it's own triggers class at some point...
void Entity : : HandleTriggerCommand ( std : : string id , std : : string target , std : : string targetName , std : : string args , Entity * optionalTarget ) {
std : : vector < std : : string > argArray ;
// Parse args
std : : stringstream ssData ( args ) ;
std : : string token ;
char deliminator = ' , ' ;
while ( std : : getline ( ssData , token , deliminator ) ) {
std : : string lowerToken ;
for ( char character : token ) {
lowerToken . push_back ( std : : tolower ( character ) ) ; // make lowercase to ensure it works
}
argArray . push_back ( lowerToken ) ;
}
std : : vector < Entity * > targetEntities ;
if ( target = = " self " ) targetEntities . push_back ( this ) ;
if ( target = = " objGroup " ) targetEntities = EntityManager : : Instance ( ) - > GetEntitiesInGroup ( targetName ) ;
if ( optionalTarget ) targetEntities . push_back ( optionalTarget ) ;
if ( targetEntities . size ( ) = = 0 ) return ;
for ( Entity * targetEntity : targetEntities ) {
if ( ! targetEntity ) continue ;
if ( id = = " SetPhysicsVolumeEffect " ) {
PhantomPhysicsComponent * phanPhys = GetComponent < PhantomPhysicsComponent > ( ) ;
if ( ! phanPhys ) return ;
phanPhys - > SetPhysicsEffectActive ( true ) ;
uint32_t effectType = 0 ;
if ( argArray [ 0 ] = = " push " ) effectType = 0 ;
else if ( argArray [ 0 ] = = " attract " ) effectType = 1 ;
else if ( argArray [ 0 ] = = " repulse " ) effectType = 2 ;
else if ( argArray [ 0 ] = = " gravity " ) effectType = 3 ;
else if ( argArray [ 0 ] = = " friction " ) effectType = 4 ;
2021-12-11 10:46:45 +00:00
2021-12-05 17:54:36 +00:00
phanPhys - > SetEffectType ( effectType ) ;
phanPhys - > SetDirectionalMultiplier ( std : : stof ( argArray [ 1 ] ) ) ;
if ( argArray . size ( ) > 4 ) {
NiPoint3 direction = NiPoint3 : : ZERO ;
GeneralUtils : : TryParse < float > ( argArray [ 2 ] , direction . x ) ;
GeneralUtils : : TryParse < float > ( argArray [ 3 ] , direction . y ) ;
GeneralUtils : : TryParse < float > ( argArray [ 4 ] , direction . z ) ;
phanPhys - > SetDirection ( direction ) ;
}
if ( argArray . size ( ) > 5 ) {
phanPhys - > SetMin ( std : : stoi ( argArray [ 6 ] ) ) ;
phanPhys - > SetMax ( std : : stoi ( argArray [ 7 ] ) ) ;
}
2021-12-11 10:46:45 +00:00
if ( target = = " self " ) {
EntityManager : : Instance ( ) - > ConstructEntity ( this ) ;
}
2021-12-05 17:54:36 +00:00
} else if ( id = = " updateMission " ) {
CDMissionTasksTable * missionTasksTable = CDClientManager : : Instance ( ) - > GetTable < CDMissionTasksTable > ( " MissionTasks " ) ;
std : : vector < CDMissionTasks > missionTasks = missionTasksTable - > Query ( [ = ] ( CDMissionTasks entry ) {
std : : string lowerTargetGroup ;
for ( char character : entry . targetGroup ) {
lowerTargetGroup . push_back ( std : : tolower ( character ) ) ; // make lowercase to ensure it works
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return ( lowerTargetGroup = = argArray [ 4 ] ) ;
} ) ;
for ( const CDMissionTasks & task : missionTasks ) {
MissionComponent * missionComponent = targetEntity - > GetComponent < MissionComponent > ( ) ;
if ( ! missionComponent ) continue ;
missionComponent - > ForceProgress ( task . id , task . uid , std : : stoi ( argArray [ 2 ] ) ) ;
}
} else if ( id = = " fireEvent " ) {
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( targetEntity ) ) {
script - > OnFireEventServerSide ( targetEntity , this , args , 0 , 0 , 0 ) ;
}
}
}
}
Entity * Entity : : GetOwner ( ) const {
if ( m_OwnerOverride ! = LWOOBJID_EMPTY ) {
auto * other = EntityManager : : Instance ( ) - > GetEntity ( m_OwnerOverride ) ;
if ( other ! = nullptr ) {
return other - > GetOwner ( ) ;
}
}
return const_cast < Entity * > ( this ) ;
}
const NiPoint3 & Entity : : GetDefaultPosition ( ) const {
return m_DefaultPosition ;
}
const NiQuaternion & Entity : : GetDefaultRotation ( ) const {
return m_DefaultRotation ;
}
float Entity : : GetDefaultScale ( ) const {
return m_Scale ;
}
void Entity : : SetOwnerOverride ( const LWOOBJID value ) {
m_OwnerOverride = value ;
}
bool Entity : : GetIsGhostingCandidate ( ) const {
return m_IsGhostingCandidate ;
}
int8_t Entity : : GetObservers ( ) const {
return m_Observers ;
}
void Entity : : SetObservers ( int8_t value ) {
if ( value < 0 ) {
value = 0 ;
}
m_Observers = value ;
}
void Entity : : Sleep ( ) {
auto * baseCombatAIComponent = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( baseCombatAIComponent ! = nullptr ) {
baseCombatAIComponent - > Sleep ( ) ;
}
}
void Entity : : Wake ( ) {
auto * baseCombatAIComponent = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
if ( baseCombatAIComponent ! = nullptr ) {
baseCombatAIComponent - > Wake ( ) ;
}
}
bool Entity : : IsSleeping ( ) const {
return m_IsGhostingCandidate & & m_Observers = = 0 ;
}
const NiPoint3 & Entity : : GetPosition ( ) const {
if ( ! this ) return NiPoint3 : : ZERO ;
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
if ( controllable ! = nullptr ) {
return controllable - > GetPosition ( ) ;
}
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
if ( phantom ! = nullptr ) {
return phantom - > GetPosition ( ) ;
}
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
if ( simple ! = nullptr ) {
return simple - > GetPosition ( ) ;
}
auto * vehicel = GetComponent < VehiclePhysicsComponent > ( ) ;
if ( vehicel ! = nullptr ) {
return vehicel - > GetPosition ( ) ;
}
return NiPoint3 : : ZERO ;
}
const NiQuaternion & Entity : : GetRotation ( ) const {
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
if ( controllable ! = nullptr ) {
return controllable - > GetRotation ( ) ;
}
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
if ( phantom ! = nullptr ) {
return phantom - > GetRotation ( ) ;
}
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
if ( simple ! = nullptr ) {
return simple - > GetRotation ( ) ;
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
auto * vehicel = GetComponent < VehiclePhysicsComponent > ( ) ;
if ( vehicel ! = nullptr ) {
return vehicel - > GetRotation ( ) ;
}
return NiQuaternion : : IDENTITY ;
}
void Entity : : SetPosition ( NiPoint3 position ) {
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
if ( controllable ! = nullptr ) {
controllable - > SetPosition ( position ) ;
}
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
if ( phantom ! = nullptr ) {
phantom - > SetPosition ( position ) ;
}
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
if ( simple ! = nullptr ) {
simple - > SetPosition ( position ) ;
}
auto * vehicel = GetComponent < VehiclePhysicsComponent > ( ) ;
if ( vehicel ! = nullptr ) {
vehicel - > SetPosition ( position ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( this ) ;
}
void Entity : : SetRotation ( NiQuaternion rotation ) {
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
if ( controllable ! = nullptr ) {
controllable - > SetRotation ( rotation ) ;
}
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
if ( phantom ! = nullptr ) {
phantom - > SetRotation ( rotation ) ;
}
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
if ( simple ! = nullptr ) {
simple - > SetRotation ( rotation ) ;
}
auto * vehicel = GetComponent < VehiclePhysicsComponent > ( ) ;
if ( vehicel ! = nullptr ) {
vehicel - > SetRotation ( rotation ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( this ) ;
}
bool Entity : : GetBoolean ( const std : : u16string & name ) const {
return GetVar < bool > ( name ) ;
}
int32_t Entity : : GetI32 ( const std : : u16string & name ) const {
return GetVar < int32_t > ( name ) ;
}
int64_t Entity : : GetI64 ( const std : : u16string & name ) const {
return GetVar < int64_t > ( name ) ;
}
void Entity : : SetBoolean ( const std : : u16string & name , const bool value ) {
SetVar ( name , value ) ;
}
void Entity : : SetI32 ( const std : : u16string & name , const int32_t value ) {
SetVar ( name , value ) ;
}
void Entity : : SetI64 ( const std : : u16string & name , const int64_t value ) {
SetVar ( name , value ) ;
}
bool Entity : : HasVar ( const std : : u16string & name ) const {
for ( auto * data : m_Settings ) {
if ( data - > GetKey ( ) = = name ) {
return true ;
}
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return false ;
}
uint16_t Entity : : GetNetworkId ( ) const {
return m_NetworkID ;
}
void Entity : : SetNetworkId ( const uint16_t id ) {
m_NetworkID = id ;
}
std : : vector < LWOOBJID > & Entity : : GetTargetsInPhantom ( ) {
std : : vector < LWOOBJID > valid ;
// Clean up invalid targets, like disconnected players
for ( auto i = 0u ; i < m_TargetsInPhantom . size ( ) ; + + i ) {
const auto id = m_TargetsInPhantom . at ( i ) ;
auto * entity = EntityManager : : Instance ( ) - > GetEntity ( id ) ;
if ( entity = = nullptr ) {
continue ;
}
valid . push_back ( id ) ;
}
m_TargetsInPhantom = valid ;
return m_TargetsInPhantom ;
}
void Entity : : SendNetworkVar ( const std : : string & data , const SystemAddress & sysAddr ) {
GameMessages : : SendSetNetworkScriptVar ( this , sysAddr , data ) ;
}
LDFBaseData * Entity : : GetVarData ( const std : : u16string & name ) const {
for ( auto * data : m_Settings ) {
if ( data = = nullptr ) {
continue ;
}
if ( data - > GetKey ( ) ! = name ) {
continue ;
}
return data ;
}
return nullptr ;
}
std : : string Entity : : GetVarAsString ( const std : : u16string & name ) const {
auto * data = GetVarData ( name ) ;
if ( data = = nullptr ) {
return " " ;
}
return data - > GetValueAsString ( ) ;
}
void Entity : : Resurrect ( ) {
if ( IsPlayer ( ) ) {
GameMessages : : SendResurrect ( this ) ;
}
}
void Entity : : AddToGroup ( const std : : string & group ) {
if ( std : : find ( m_Groups . begin ( ) , m_Groups . end ( ) , group ) = = m_Groups . end ( ) ) {
m_Groups . push_back ( group ) ;
}
}
2022-04-13 08:49:55 +00:00
void Entity : : RetroactiveVaultSize ( ) {
auto inventoryComponent = GetComponent < InventoryComponent > ( ) ;
if ( ! inventoryComponent ) return ;
auto itemsVault = inventoryComponent - > GetInventory ( eInventoryType : : VAULT_ITEMS ) ;
auto modelVault = inventoryComponent - > GetInventory ( eInventoryType : : VAULT_MODELS ) ;
if ( itemsVault - > GetSize ( ) = = modelVault - > GetSize ( ) ) return ;
modelVault - > SetSize ( itemsVault - > GetSize ( ) ) ;
}