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"
2023-01-07 05:17:05 +00:00
# include "LUTriggers.h"
# include "User.h"
# include "EntityTimer.h"
# include "EntityCallbackTimer.h"
# include "Loot.h"
2023-01-22 23:38:47 +00:00
# include "eMissionTaskType.h"
2023-02-10 08:29:53 +00:00
# include "eTriggerEventType.h"
2023-04-25 18:17:40 +00:00
# include "eObjectBits.h"
2021-12-05 17:54:36 +00:00
//Component includes:
# include "Component.h"
# include "ControllablePhysicsComponent.h"
# include "RenderComponent.h"
2023-06-08 15:29:17 +00:00
# include "MultiZoneEntranceComponent.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"
2023-06-09 22:12:57 +00:00
# include "QuickBuildComponent.h"
2021-12-05 17:54:36 +00:00
# include "BuildBorderComponent.h"
# include "MovementAIComponent.h"
# include "VendorComponent.h"
# include "RocketLaunchpadControlComponent.h"
# include "PropertyComponent.h"
2023-06-10 11:46:48 +00:00
# include "CollectibleComponent.h"
2021-12-05 17:54:36 +00:00
# include "BaseCombatAIComponent.h"
# include "PropertyManagementComponent.h"
# include "PropertyVendorComponent.h"
# include "ProximityMonitorComponent.h"
# include "PropertyEntranceComponent.h"
2023-06-08 15:29:17 +00:00
# include "ModelBehaviorComponent.h"
2021-12-05 17:54:36 +00:00
# include "ZCompression.h"
# include "PetComponent.h"
2023-06-08 15:29:17 +00:00
# include "HavokVehiclePhysicsComponent.h"
2021-12-05 17:54:36 +00:00
# include "PossessableComponent.h"
# include "PossessorComponent.h"
# include "ModuleAssemblyComponent.h"
# include "RacingControlComponent.h"
# include "SoundTriggerComponent.h"
# include "ShootingGalleryComponent.h"
# include "RailActivatorComponent.h"
# include "LUPExhibitComponent.h"
2023-02-10 08:29:53 +00:00
# include "TriggerComponent.h"
2023-03-24 23:16:45 +00:00
# include "eGameMasterLevel.h"
2023-03-04 07:16:37 +00:00
# include "eReplicaComponentType.h"
2023-05-02 22:39:21 +00:00
# include "eReplicaPacketType.h"
2023-06-09 11:05:04 +00:00
# include "RacingStatsComponent.h"
# include "MinigameControlComponent.h"
2023-06-10 11:46:48 +00:00
# include "ItemComponent.h"
2021-12-05 17:54:36 +00:00
2023-03-17 14:36:21 +00:00
// Table includes
# include "CDComponentsRegistryTable.h"
# include "CDCurrencyTableTable.h"
# include "CDMovementAIComponentTable.h"
# include "CDProximityMonitorComponentTable.h"
# include "CDRebuildComponentTable.h"
# include "CDObjectSkillsTable.h"
# include "CDObjectsTable.h"
# include "CDScriptComponentTable.h"
# include "CDSkillBehaviorTable.h"
# include "CDZoneTableTable.h"
2023-06-10 06:02:28 +00:00
const std : : vector < ComponentWhitelist > Entity : : m_ComponentWhitelists = {
{ // Unknown use case
eReplicaComponentType : : CONTROLLABLE_PHYSICS ,
eReplicaComponentType : : SIMPLE_PHYSICS ,
eReplicaComponentType : : RENDER
} ,
{ // Used for BBB
eReplicaComponentType : : RENDER ,
eReplicaComponentType : : DESTROYABLE ,
eReplicaComponentType : : ITEM ,
eReplicaComponentType : : BLUEPRINT ,
eReplicaComponentType : : MODEL_BEHAVIOR ,
eReplicaComponentType : : CONTROLLABLE_PHYSICS ,
eReplicaComponentType : : SIMPLE_PHYSICS ,
eReplicaComponentType : : SPAWN
} ,
{ // Unknown use case
eReplicaComponentType : : RENDER ,
eReplicaComponentType : : ITEM ,
eReplicaComponentType : : BLUEPRINT ,
} ,
{ // Used for Pets
eReplicaComponentType : : PET ,
eReplicaComponentType : : SKILL ,
eReplicaComponentType : : DESTROYABLE ,
eReplicaComponentType : : RENDER ,
eReplicaComponentType : : CONTROLLABLE_PHYSICS
} ,
{ // Unknown use case
eReplicaComponentType : : CONTROLLABLE_PHYSICS ,
eReplicaComponentType : : SIMPLE_PHYSICS ,
eReplicaComponentType : : RENDER ,
} ,
} ;
2021-12-05 17:54:36 +00:00
Entity : : Entity ( const LWOOBJID & objectID , EntityInfo info , Entity * parentEntity ) {
m_ObjectID = objectID ;
m_TemplateID = info . lot ;
m_ParentEntity = parentEntity ;
m_Character = nullptr ;
2023-03-24 23:16:45 +00:00
m_GMLevel = eGameMasterLevel : : CIVILIAN ;
2021-12-05 17:54:36 +00:00
m_NetworkID = 0 ;
2023-06-09 08:04:42 +00:00
m_Observers = 0 ;
2021-12-05 17:54:36 +00:00
m_OwnerOverride = LWOOBJID_EMPTY ;
2023-06-09 09:46:01 +00:00
m_Groups . clear ( ) ;
m_Timers . clear ( ) ;
m_ChildEntities . clear ( ) ;
m_TargetsInPhantom . clear ( ) ;
m_DieCallbacks . clear ( ) ;
m_PhantomCollisionCallbacks . clear ( ) ;
2021-12-05 17:54:36 +00:00
m_ScheduleKiller = nullptr ;
2022-06-16 05:58:38 +00:00
m_IsParentChildDirty = true ;
2023-06-09 08:04:42 +00:00
m_IsGhostingCandidate = false ;
m_PlayerIsReadyForUpdates = false ;
m_ShouldDestroyAfterUpdate = false ;
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 ;
2022-07-28 13:39:57 +00:00
m_HasSpawnerNodeID = info . hasSpawnerNodeID ;
m_SpawnerNodeID = info . spawnerNodeID ;
2021-12-05 17:54:36 +00:00
if ( info . lot ! = 1 ) m_PlayerIsReadyForUpdates = true ;
}
Entity : : ~ Entity ( ) {
2023-06-07 03:48:30 +00:00
if ( m_Character ) m_Character - > SaveXMLToDatabase ( ) ;
2021-12-05 17:54:36 +00:00
CancelAllTimers ( ) ;
CancelCallbackTimers ( ) ;
2023-06-07 03:48:30 +00:00
for ( auto child : m_ChildEntities ) if ( child ) child - > RemoveParent ( ) ;
2022-07-17 04:39:13 +00:00
2023-06-07 03:48:30 +00:00
if ( m_ParentEntity ) m_ParentEntity - > RemoveChild ( this ) ;
2021-12-05 17:54:36 +00:00
}
2023-06-10 11:46:48 +00:00
void Entity : : ApplyComponentWhitelist ( TemplateComponents & components ) const {
2023-06-10 06:02:28 +00:00
const auto whitelistIndex = GetVar < int32_t > ( u " componentWhitelist " ) ;
if ( whitelistIndex < 0 | | whitelistIndex > = m_ComponentWhitelists . size ( ) ) return ;
2023-06-10 07:03:07 +00:00
const auto & whitelist = m_ComponentWhitelists . at ( whitelistIndex ) ;
2023-06-10 07:14:20 +00:00
const auto endRange = std : : remove_if ( components . begin ( ) , components . end ( ) , [ & whitelist ] ( const auto & componentCandidate ) {
return std : : find ( whitelist . begin ( ) , whitelist . end ( ) , componentCandidate . first ) = = whitelist . end ( ) ;
2023-06-10 11:46:48 +00:00
} ) ;
2023-06-10 07:03:07 +00:00
components . erase ( endRange , components . end ( ) ) ;
2023-06-10 06:02:28 +00:00
}
2023-06-10 11:46:48 +00:00
void Entity : : ApplyComponentBlacklist ( TemplateComponents & components ) const {
bool hasPetComponent = std : : find_if ( components . begin ( ) , components . end ( ) , [ ] ( const auto & componentCandidate ) {
return componentCandidate . first = = eReplicaComponentType : : PET ;
2023-06-10 12:10:00 +00:00
} ) ! = components . end ( ) ;
if ( hasPetComponent ) {
auto toRemove = std : : remove_if ( components . begin ( ) , components . end ( ) , [ ] ( const auto & componentCandidate ) {
return componentCandidate . first = = eReplicaComponentType : : MODEL_BEHAVIOR | | componentCandidate . first = = eReplicaComponentType : : ITEM ;
} ) ;
components . erase ( toRemove , components . end ( ) ) ;
}
2023-06-10 11:46:48 +00:00
}
void Entity : : ApplyComponentConfig ( TemplateComponents & components ) const {
if ( GetVar < bool > ( u " markedAsPhantom " ) ) {
auto toRemove = std : : remove_if ( components . begin ( ) , components . end ( ) , [ ] ( const auto & componentCandidate ) {
return componentCandidate . first = = eReplicaComponentType : : SIMPLE_PHYSICS | |
componentCandidate . first = = eReplicaComponentType : : PHANTOM_PHYSICS ; // Just make sure we dont have phantom physics already
} ) ;
components . erase ( toRemove , components . end ( ) ) ;
components . emplace_back ( eReplicaComponentType : : PHANTOM_PHYSICS , 0U ) ;
}
}
2023-06-12 08:29:43 +00:00
void Entity : : AddPathComponent ( TemplateComponents & components ) const {
const Path * path = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetPath ( GetVarAsString ( u " attached_path " ) ) ;
//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 ) {
bool hasMovingPlatform = std : : count_if ( components . begin ( ) , components . end ( ) , [ ] ( const auto & componentCandidate ) {
return componentCandidate . first = = eReplicaComponentType : : MOVING_PLATFORM ;
} ) > 0 ;
if ( ! hasMovingPlatform ) components . emplace_back ( eReplicaComponentType : : MOVING_PLATFORM , 0U ) ;
} else if ( path - > pathType = = PathType : : Movement ) {
bool hasMovementAi = std : : count_if ( components . begin ( ) , components . end ( ) , [ ] ( const auto & componentCandidate ) {
return componentCandidate . first = = eReplicaComponentType : : MOVEMENT_AI ;
} ) > 0 ;
if ( ! hasMovementAi ) {
components . emplace_back ( eReplicaComponentType : : MOVEMENT_AI , 0U ) ;
}
} else {
Game : : logger - > Log ( " Entity " , " Unsupported path type %i provided for lot %i. " , path - > pathType , GetLOT ( ) ) ;
}
}
}
2022-07-28 13:39:57 +00:00
void Entity : : Initialize ( ) {
2023-06-09 11:05:04 +00:00
// A few edge cases to tackle first
const auto triggerInfo = GetVarAsString ( u " trigger_id " ) ;
if ( ! triggerInfo . empty ( ) ) AddComponent < TriggerComponent > ( triggerInfo ) ;
const auto groupIDs = GetVarAsString ( u " groupID " ) ;
if ( ! groupIDs . empty ( ) ) {
m_Groups = GeneralUtils : : SplitString ( groupIDs , ' ; ' ) ;
if ( m_Groups . back ( ) . empty ( ) ) m_Groups . erase ( m_Groups . end ( ) - 1 ) ;
}
if ( m_ParentEntity ) m_ParentEntity - > AddChild ( this ) ;
2023-06-07 03:48:30 +00:00
auto * componentsRegistry = CDClientManager : : Instance ( ) . GetTable < CDComponentsRegistryTable > ( ) ;
2023-06-10 07:14:20 +00:00
TemplateComponents components = componentsRegistry - > GetTemplateComponents ( m_TemplateID ) ;
ApplyComponentWhitelist ( components ) ;
2023-06-10 11:46:48 +00:00
ApplyComponentBlacklist ( components ) ;
2023-06-12 08:29:43 +00:00
AddPathComponent ( components ) ;
2023-06-11 11:37:53 +00:00
// Brick-by-Brick models use custom physics depending on _something_ but the client uses 4246 as the simple
// physics component id and 4247 for phantom physics. We'll just use the simple physics component for now
// since we dont know what the phantom physics are for at the moment.
2023-06-12 08:29:43 +00:00
if ( GetLOT ( ) = = LOT_MODEL_IN_WORLD ) components . emplace_back ( eReplicaComponentType : : SIMPLE_PHYSICS , 4246U ) ;
2023-06-07 03:48:30 +00:00
for ( const auto & [ componentTemplate , componentId ] : components ) {
switch ( componentTemplate ) {
case eReplicaComponentType : : CONTROLLABLE_PHYSICS :
2023-06-07 07:23:50 +00:00
AddComponent < ControllablePhysicsComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : RENDER :
2023-06-09 11:05:04 +00:00
AddComponent < RenderComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : SIMPLE_PHYSICS :
2023-06-10 11:46:48 +00:00
AddComponent < SimplePhysicsComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : CHARACTER :
2023-06-09 11:05:04 +00:00
AddComponent < CharacterComponent > ( m_Character ) ;
AddComponent < MissionComponent > ( ) ;
2023-06-10 11:46:48 +00:00
AddComponent < PossessorComponent > ( ) ;
AddComponent < LevelProgressionComponent > ( ) ;
AddComponent < PlayerForcedMovementComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 10:06:18 +00:00
case eReplicaComponentType : : SCRIPT : {
2023-06-12 11:13:06 +00:00
std : : string script ;
2023-06-12 08:29:43 +00:00
if ( m_TemplateID = = LOT_ZONE_CONTROL ) {
2023-06-12 11:13:06 +00:00
script = ScriptComponent : : GetZoneScriptName ( componentId ) ;
} else {
script = ScriptComponent : : GetScriptName ( this , componentId ) ;
2023-06-11 10:06:18 +00:00
}
2023-06-12 11:13:06 +00:00
AddComponent < ScriptComponent > ( script ) ; // Technically this should check for if the script name is empty and not create a component if it is.
2023-06-11 10:06:18 +00:00
break ;
}
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : BOUNCER :
2023-06-09 11:05:04 +00:00
AddComponent < BouncerComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 12:10:00 +00:00
case eReplicaComponentType : : DESTROYABLE :
2023-06-12 08:29:43 +00:00
if ( ! HasComponent ( eReplicaComponentType : : DESTROYABLE ) ) AddComponent < DestroyableComponent > ( componentId ) ;
2023-06-10 12:10:00 +00:00
break ;
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : SKILL :
2023-06-09 11:05:04 +00:00
AddComponent < SkillComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : ITEM :
2023-06-10 11:46:48 +00:00
AddComponent < ItemComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : VENDOR :
2023-06-09 11:05:04 +00:00
AddComponent < VendorComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : INVENTORY :
2023-06-10 11:46:48 +00:00
AddComponent < InventoryComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : SHOOTING_GALLERY :
2023-06-09 11:05:04 +00:00
AddComponent < ShootingGalleryComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : RIGID_BODY_PHANTOM_PHYSICS :
2023-06-10 11:46:48 +00:00
AddComponent < RigidbodyPhantomPhysicsComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : COLLECTIBLE :
2023-06-10 11:46:48 +00:00
AddComponent < CollectibleComponent > ( ) ;
2023-06-12 08:29:43 +00:00
if ( ! HasComponent ( eReplicaComponentType : : DESTROYABLE ) ) AddComponent < DestroyableComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : MOVING_PLATFORM :
2023-06-10 11:46:48 +00:00
AddComponent < MovingPlatformComponent > ( GetVarAsString ( u " attached_path " ) ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : PET :
2023-06-09 11:05:04 +00:00
AddComponent < PetComponent > ( componentId ) ;
2023-06-12 08:29:43 +00:00
AddComponent < MovementAIComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 11:37:53 +00:00
case eReplicaComponentType : : HAVOK_VEHICLE_PHYSICS : {
auto * havokVehiclePhysicsComponent = AddComponent < HavokVehiclePhysicsComponent > ( ) ;
if ( havokVehiclePhysicsComponent ) {
havokVehiclePhysicsComponent - > SetPosition ( m_DefaultPosition ) ;
havokVehiclePhysicsComponent - > SetRotation ( m_DefaultRotation ) ;
}
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 11:37:53 +00:00
}
2023-06-12 08:29:43 +00:00
case eReplicaComponentType : : MOVEMENT_AI :
AddComponent < MovementAIComponent > ( ) ;
break ;
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : PROPERTY :
2023-06-09 11:05:04 +00:00
AddComponent < PropertyComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : SCRIPTED_ACTIVITY :
2023-06-09 11:05:04 +00:00
AddComponent < ScriptedActivityComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 11:37:53 +00:00
case eReplicaComponentType : : PHANTOM_PHYSICS : {
auto * phantomPhysicsComponent = AddComponent < PhantomPhysicsComponent > ( ) ;
if ( phantomPhysicsComponent ) phantomPhysicsComponent - > SetPhysicsEffectActive ( false ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 11:37:53 +00:00
}
case eReplicaComponentType : : MODEL_BEHAVIOR : {
2023-06-10 11:46:48 +00:00
AddComponent < ModelBehaviorComponent > ( ) ;
2023-06-11 11:39:28 +00:00
if ( ! HasComponent ( eReplicaComponentType : : DESTROYABLE ) ) {
2023-06-12 08:29:43 +00:00
auto * destroyableComponent = AddComponent < DestroyableComponent > ( componentId ) ;
2023-06-11 11:37:53 +00:00
if ( destroyableComponent ) {
destroyableComponent - > SetHealth ( 1 ) ;
destroyableComponent - > SetMaxHealth ( 1.0f ) ;
destroyableComponent - > SetFaction ( - 1 , true ) ;
destroyableComponent - > SetIsSmashable ( true ) ;
}
}
2023-06-07 03:48:30 +00:00
break ;
2023-06-11 11:37:53 +00:00
}
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : PROPERTY_ENTRANCE :
2023-06-09 11:05:04 +00:00
AddComponent < PropertyEntranceComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : PROPERTY_MANAGEMENT :
2023-06-09 11:05:04 +00:00
AddComponent < PropertyManagementComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 12:10:00 +00:00
case eReplicaComponentType : : QUICK_BUILD :
2023-06-11 11:37:53 +00:00
AddComponent < QuickBuildComponent > ( componentId ) ;
2023-06-12 08:29:43 +00:00
if ( ! HasComponent ( eReplicaComponentType : : DESTROYABLE ) ) AddComponent < DestroyableComponent > ( componentId ) ;
2023-06-10 12:10:00 +00:00
break ;
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : SWITCH :
2023-06-09 11:05:04 +00:00
AddComponent < SwitchComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-08 15:29:17 +00:00
case eReplicaComponentType : : MINIGAME_CONTROL :
2023-06-09 11:05:04 +00:00
AddComponent < MinigameControlComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-12 08:29:43 +00:00
case eReplicaComponentType : : BASE_COMBAT_AI : {
auto * baseCombatAiComponent = AddComponent < BaseCombatAIComponent > ( componentId ) ;
if ( baseCombatAiComponent & & baseCombatAiComponent - > GetTetherSpeed ( ) > 0.0f ) {
auto * movementAiComponent = AddComponent < MovementAIComponent > ( ) ;
if ( ! movementAiComponent ) break ;
MovementAIInfo movementAiInfo { } ;
movementAiInfo . movementType = " " ;
movementAiInfo . wanderChance = 0 ;
movementAiInfo . wanderRadius = 16 ;
movementAiInfo . wanderSpeed = 2.5f ;
movementAiInfo . wanderDelayMax = 5 ;
movementAiInfo . wanderDelayMin = 2 ;
movementAiComponent - > SetMoveInfo ( movementAiInfo ) ;
}
2023-06-07 03:48:30 +00:00
break ;
2023-06-12 08:29:43 +00:00
}
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : MODULE_ASSEMBLY :
2023-06-09 11:05:04 +00:00
AddComponent < ModuleAssemblyComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : PROPERTY_VENDOR :
2023-06-09 11:05:04 +00:00
AddComponent < PropertyVendorComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-08 15:29:17 +00:00
case eReplicaComponentType : : ROCKET_LAUNCHPAD_CONTROL :
2023-06-10 11:46:48 +00:00
AddComponent < RocketLaunchpadControlComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : RACING_CONTROL :
2023-06-09 11:05:04 +00:00
AddComponent < RacingControlComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : MISSION_OFFER :
2023-06-09 11:05:04 +00:00
AddComponent < MissionOfferComponent > ( GetLOT ( ) ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : RACING_STATS :
2023-06-09 11:05:04 +00:00
AddComponent < RacingStatsComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : LUP_EXHIBIT :
2023-06-09 11:05:04 +00:00
AddComponent < LUPExhibitComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
case eReplicaComponentType : : SOUND_TRIGGER :
2023-06-10 11:46:48 +00:00
AddComponent < SoundTriggerComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-12 08:29:43 +00:00
case eReplicaComponentType : : PROXIMITY_MONITOR :
AddComponent < ProximityMonitorComponent > ( ) ;
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : MULTI_ZONE_ENTRANCE :
AddComponent < MultiZoneEntranceComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : BUFF :
AddComponent < BuffComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : RAIL_ACTIVATOR :
AddComponent < RailActivatorComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : POSSESSABLE :
AddComponent < PossessableComponent > ( componentId ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : BUILD_BORDER :
AddComponent < BuildBorderComponent > ( ) ;
2023-06-07 03:48:30 +00:00
break ;
2023-06-10 11:46:48 +00:00
case eReplicaComponentType : : GHOST :
case eReplicaComponentType : : SPAWN :
case eReplicaComponentType : : MODULAR_BUILD :
case eReplicaComponentType : : BUILD_CONTROLLER :
case eReplicaComponentType : : BUILD_ACTIVATOR :
case eReplicaComponentType : : ICON_ONLY :
case eReplicaComponentType : : PROJECTILE_PHYSICS :
case eReplicaComponentType : : DROP_EFFECT :
case eReplicaComponentType : : CHEST :
case eReplicaComponentType : : BLUEPRINT :
case eReplicaComponentType : : PLATFORM_BOUNDARY :
case eReplicaComponentType : : MODULE :
case eReplicaComponentType : : JETPACKPAD :
case eReplicaComponentType : : EXHIBIT :
case eReplicaComponentType : : OVERHEAD_ICON :
case eReplicaComponentType : : PET_CONTROL :
case eReplicaComponentType : : MINIFIG :
case eReplicaComponentType : : PET_CREATOR :
case eReplicaComponentType : : MODEL_BUILDER :
case eReplicaComponentType : : SPRINGPAD :
case eReplicaComponentType : : FX :
case eReplicaComponentType : : VEHICLE_PHYSICS :
case eReplicaComponentType : : PHYSICS_SYSTEM :
case eReplicaComponentType : : CHANGLING_BUILD :
case eReplicaComponentType : : CHOICE_BUILD :
case eReplicaComponentType : : PACKAGE :
case eReplicaComponentType : : SOUND_REPEATER :
case eReplicaComponentType : : SOUND_AMBIENT_2D :
case eReplicaComponentType : : SOUND_AMBIENT_3D :
case eReplicaComponentType : : PRECONDITION :
case eReplicaComponentType : : FLAG :
case eReplicaComponentType : : CUSTOM_BUILD_ASSEMBLY :
case eReplicaComponentType : : SHOWCASE_MODEL_HANDLER :
case eReplicaComponentType : : RACING_MODULE :
case eReplicaComponentType : : GENERIC_ACTIVATOR :
case eReplicaComponentType : : HF_LIGHT_DIRECTION_GADGET :
case eReplicaComponentType : : ROCKET_ANIMATION_CONTROL :
case eReplicaComponentType : : TRIGGER :
case eReplicaComponentType : : DROPPED_LOOT :
case eReplicaComponentType : : FACTION_TRIGGER :
case eReplicaComponentType : : BBB :
case eReplicaComponentType : : RACING_SOUND_TRIGGER :
case eReplicaComponentType : : CHAT_BUBBLE :
case eReplicaComponentType : : FRIENDS_LIST :
case eReplicaComponentType : : GUILD :
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : LOCAL_SYSTEM :
case eReplicaComponentType : : MISSION :
case eReplicaComponentType : : MUTABLE_MODEL_BEHAVIORS :
case eReplicaComponentType : : PATHFINDING :
case eReplicaComponentType : : PET_TAMING_CONTROL :
case eReplicaComponentType : : PROPERTY_EDITOR :
case eReplicaComponentType : : SKINNED_RENDER :
case eReplicaComponentType : : SLASH_COMMAND :
case eReplicaComponentType : : STATUS_EFFECT :
case eReplicaComponentType : : TEAMS :
case eReplicaComponentType : : TEXT_EFFECT :
case eReplicaComponentType : : TRADE :
case eReplicaComponentType : : USER_CONTROL :
case eReplicaComponentType : : IGNORE_LIST :
case eReplicaComponentType : : INTERACTION_MANAGER :
case eReplicaComponentType : : DONATION_VENDOR :
case eReplicaComponentType : : COMBAT_MEDIATOR :
2023-06-08 15:29:17 +00:00
case eReplicaComponentType : : ACHIEVEMENT_VENDOR :
2023-06-07 03:48:30 +00:00
case eReplicaComponentType : : GATE_RUSH_CONTROL :
case eReplicaComponentType : : ROLLER :
case eReplicaComponentType : : PLAYER_FORCED_MOVEMENT :
case eReplicaComponentType : : CRAFTING :
case eReplicaComponentType : : LEVEL_PROGRESSION :
case eReplicaComponentType : : POSSESSOR :
case eReplicaComponentType : : MOUNT_CONTROL :
case eReplicaComponentType : : UNKNOWN_112 :
case eReplicaComponentType : : PROPERTY_PLAQUE :
case eReplicaComponentType : : UNKNOWN_115 :
case eReplicaComponentType : : CULLING_PLANE :
case eReplicaComponentType : : NUMBER_OF_COMPONENTS :
case eReplicaComponentType : : INVALID :
default :
2023-06-12 11:37:38 +00:00
Game : : logger - > Log ( " Entity " , " Attempted to create component %i for lot %i but no creator exists. Component will not be created. " , componentId , m_TemplateID ) ;
2021-12-05 17:54:36 +00:00
}
}
2023-06-09 09:46:01 +00:00
2023-06-12 08:29:43 +00:00
AddCallbackTimer ( 0.0f , [ this ] ( ) {
2023-06-12 22:32:46 +00:00
GetScript ( ) - > OnStartup ( this ) ;
2023-06-12 08:29:43 +00:00
} ) ;
2023-06-12 11:37:38 +00:00
// Load data specific to this LOT first. These act as defaults for the components.
2023-06-11 10:06:18 +00:00
std : : for_each ( m_Components . begin ( ) , m_Components . end ( ) , [ this ] ( auto & component ) {
component . second - > LoadTemplateData ( ) ;
} ) ;
2023-06-09 09:46:01 +00:00
2023-06-12 11:27:14 +00:00
// Then load data specific to this Entity. This will vary on an Entity to Entity basis.
// If there is data you want to override the LOT default value, generally you would attach it via LDF
// and it would get loaded and overridden here.
2023-06-11 10:06:18 +00:00
std : : for_each ( m_Components . begin ( ) , m_Components . end ( ) , [ this ] ( auto & component ) {
component . second - > LoadConfigData ( ) ;
} ) ;
2023-06-09 09:46:01 +00:00
2023-06-12 11:27:14 +00:00
/**
2023-06-12 22:32:46 +00:00
* Startup all the components . Some components need or want data from other components so
2023-06-12 11:27:14 +00:00
* we want to ensure that
* A ) Most if not all components are newed and ready to be accessed .
* B ) All components have their personal data loaded and ready to be used .
*/
2023-06-11 10:06:18 +00:00
std : : for_each ( m_Components . begin ( ) , m_Components . end ( ) , [ this ] ( auto & component ) {
component . second - > Startup ( ) ;
} ) ;
2023-06-12 11:27:14 +00:00
/**
2023-06-12 22:32:46 +00:00
* Load the player save data from XML . Ideally we do this after all initialization so the player
2023-06-12 11:27:14 +00:00
* save data overrides any defaults that may be applied .
*/
2023-06-12 08:29:43 +00:00
if ( ! IsPlayer ( ) ) std : : for_each ( m_Components . begin ( ) , m_Components . end ( ) , [ this ] ( auto & component ) {
2023-06-11 10:06:18 +00:00
component . second - > LoadFromXml ( m_Character - > GetXMLDoc ( ) ) ;
} ) ;
2023-06-12 08:29:43 +00:00
TriggerEvent ( eTriggerEventType : : CREATE , this ) ;
2023-06-12 11:27:14 +00:00
if ( ! m_Character & & EntityManager : : Instance ( ) - > GetGhostingEnabled ( ) ) IsGhosted ( ) ;
2023-06-12 08:29:43 +00:00
}
void Entity : : IsGhosted ( ) {
2023-06-12 11:27:14 +00:00
// Don't ghost what is likely large scene elements
if ( HasComponent ( eReplicaComponentType : : SIMPLE_PHYSICS ) & & HasComponent ( eReplicaComponentType : : RENDER ) & & ( m_Components . size ( ) = = 2 | | ( HasComponent ( eReplicaComponentType : : TRIGGER ) & & m_Components . size ( ) = = 3 ) ) ) {
return ;
}
2023-06-12 08:29:43 +00:00
2023-06-12 11:27:14 +00:00
/* 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 ( eReplicaComponentType : : SCRIPTED_ACTIVITY ) & &
! HasComponent ( eReplicaComponentType : : MOVING_PLATFORM ) & &
! HasComponent ( eReplicaComponentType : : PHANTOM_PHYSICS ) & &
! HasComponent ( eReplicaComponentType : : PROPERTY ) & &
! HasComponent ( eReplicaComponentType : : RACING_CONTROL ) & &
! HasComponent ( eReplicaComponentType : : VEHICLE_PHYSICS ) ) {
m_IsGhostingCandidate = true ;
}
2023-06-12 08:29:43 +00:00
2023-06-12 11:27:14 +00:00
if ( GetLOT ( ) = = LOT_3D_AMBIENT_SOUND ) m_IsGhostingCandidate = true ;
2023-06-12 08:29:43 +00:00
2023-06-12 11:27:14 +00:00
// Special case for collectibles in Ninjago
if ( HasComponent ( eReplicaComponentType : : COLLECTIBLE ) & & Game : : server - > GetZoneID ( ) = = 2000 ) {
m_IsGhostingCandidate = true ;
2023-06-12 08:29:43 +00:00
}
2021-12-05 17:54:36 +00:00
}
bool Entity : : operator = = ( const Entity & other ) const {
return other . m_ObjectID = = m_ObjectID ;
}
bool Entity : : operator ! = ( const Entity & other ) const {
2023-06-09 08:04:42 +00:00
return ! ( other . m_ObjectID = = m_ObjectID ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
User * Entity : : GetParentUser ( ) const {
if ( ! IsPlayer ( ) ) {
2021-12-05 17:54:36 +00:00
return nullptr ;
}
return static_cast < const Player * > ( this ) - > GetParentUser ( ) ;
}
2023-03-04 07:16:37 +00:00
bool Entity : : HasComponent ( const eReplicaComponentType componentId ) const {
2021-12-05 17:54:36 +00:00
return m_Components . find ( componentId ) ! = m_Components . end ( ) ;
}
2023-06-09 08:04:42 +00:00
std : : vector < ScriptComponent * > Entity : : GetScriptComponents ( ) {
std : : vector < ScriptComponent * > comps ;
2023-06-09 11:05:04 +00:00
for ( const auto & [ componentType , component ] : m_Components ) {
2023-06-07 03:48:30 +00:00
if ( componentType = = eReplicaComponentType : : SCRIPT ) {
2023-06-09 08:04:42 +00:00
comps . push_back ( dynamic_cast < ScriptComponent * > ( component . get ( ) ) ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return comps ;
}
2023-06-09 08:04:42 +00:00
void Entity : : Subscribe ( const LWOOBJID & scriptObjId , CppScripts : : Script * scriptToAdd , const std : : string & notificationName ) {
2022-12-21 22:33:41 +00:00
if ( notificationName = = " HitOrHealResult " | | notificationName = = " Hit " ) {
2023-06-12 11:00:44 +00:00
auto * destroyableComponent = GetComponent < DestroyableComponent > ( ) ;
2022-12-21 22:33:41 +00:00
if ( ! destroyableComponent ) return ;
destroyableComponent - > Subscribe ( scriptObjId , scriptToAdd ) ;
}
}
2023-06-09 08:04:42 +00:00
void Entity : : Unsubscribe ( const LWOOBJID & scriptObjId , const std : : string & notificationName ) {
2022-12-21 22:33:41 +00:00
if ( notificationName = = " HitOrHealResult " | | notificationName = = " Hit " ) {
2023-06-12 11:00:44 +00:00
auto * destroyableComponent = GetComponent < DestroyableComponent > ( ) ;
2022-12-21 22:33:41 +00:00
if ( ! destroyableComponent ) return ;
destroyableComponent - > Unsubscribe ( scriptObjId ) ;
}
}
2023-06-09 08:04:42 +00:00
void Entity : : SetProximityRadius ( const float proxRadius , const std : : string & name ) {
2023-06-12 11:04:45 +00:00
auto * proximityMonitorComponent = AddComponent < ProximityMonitorComponent > ( ) ;
2023-06-07 03:48:30 +00:00
if ( proximityMonitorComponent ) proximityMonitorComponent - > SetProximityRadius ( proxRadius , name ) ;
2021-12-05 17:54:36 +00:00
}
2023-06-09 08:04:42 +00:00
void Entity : : SetProximityRadius ( dpEntity * entity , const std : : string & name ) {
2023-06-12 11:04:45 +00:00
auto * proximityMonitorComponent = AddComponent < ProximityMonitorComponent > ( ) ;
2023-06-07 03:48:30 +00:00
if ( proximityMonitorComponent ) proximityMonitorComponent - > SetProximityRadius ( entity , name ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
void Entity : : SetGMLevel ( eGameMasterLevel value ) {
2021-12-05 17:54:36 +00:00
m_GMLevel = value ;
if ( GetParentUser ( ) ) {
Character * character = GetParentUser ( ) - > GetLastUsedChar ( ) ;
if ( character ) {
character - > SetGMLevel ( value ) ;
}
}
2023-06-12 11:00:44 +00:00
auto * character = GetComponent < CharacterComponent > ( ) ;
2021-12-05 17:54:36 +00:00
if ( character ) character - > SetGMLevel ( value ) ;
GameMessages : : SendGMLevelBroadcast ( m_ObjectID , value ) ;
}
2023-06-12 22:32:46 +00:00
void Entity : : WriteBaseReplicaData ( RakNet : : BitStream * outBitStream , const eReplicaPacketType packetType ) {
2023-05-02 22:39:21 +00:00
if ( packetType = = eReplicaPacketType : : CONSTRUCTION ) {
2021-12-05 17:54:36 +00:00
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 ] ) ;
}
2022-07-28 13:39:57 +00:00
} else {
2021-12-05 17:54:36 +00:00
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.
2023-06-08 15:29:17 +00:00
if ( m_Settings . size ( ) > 0 & & ( GetComponent < ModelBehaviorComponent > ( ) & & ! 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 ) ;
2022-07-28 13:39:57 +00:00
} else if ( ! syncLDF . empty ( ) ) {
2021-12-05 17:54:36 +00:00
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 ) ;
2022-07-28 13:39:57 +00:00
} else {
outBitStream - > Write0 ( ) ; //No ldf data
2021-12-05 17:54:36 +00:00
}
2023-06-12 11:00:44 +00:00
auto * triggerComponent = GetComponent < TriggerComponent > ( ) ;
2023-06-07 03:48:30 +00:00
if ( triggerComponent ) {
2023-02-10 08:29:53 +00:00
// has trigger component, check to see if we have events to handle
auto * trigger = triggerComponent - > GetTrigger ( ) ;
outBitStream - > Write < bool > ( trigger & & trigger - > events . size ( ) > 0 ) ;
} else { // no trigger componenet, so definitely no triggers
2021-12-05 17:54:36 +00:00
outBitStream - > Write0 ( ) ;
}
2023-02-10 08:29:53 +00:00
2021-12-05 17:54:36 +00:00
if ( m_ParentEntity ! = nullptr | | m_SpawnerID ! = 0 ) {
outBitStream - > Write1 ( ) ;
2023-04-25 18:17:40 +00:00
if ( m_ParentEntity ! = nullptr ) outBitStream - > Write ( GeneralUtils : : SetBit ( m_ParentEntity - > GetObjectID ( ) , static_cast < uint32_t > ( eObjectBits : : CLIENT ) ) ) ;
2021-12-05 17:54:36 +00:00
else if ( m_Spawner ! = nullptr & & m_Spawner - > m_Info . isNetwork ) outBitStream - > Write ( m_SpawnerID ) ;
2023-04-25 18:17:40 +00:00
else outBitStream - > Write ( GeneralUtils : : SetBit ( m_SpawnerID , static_cast < uint32_t > ( eObjectBits : : CLIENT ) ) ) ;
2022-07-28 13:39:57 +00:00
} else outBitStream - > Write0 ( ) ;
2021-12-05 17:54:36 +00:00
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
2023-03-24 23:16:45 +00:00
if ( m_GMLevel ! = eGameMasterLevel : : CIVILIAN ) {
2021-12-05 17:54:36 +00:00
outBitStream - > Write1 ( ) ;
outBitStream - > Write ( m_GMLevel ) ;
2022-07-28 13:39:57 +00:00
} else outBitStream - > Write0 ( ) ; //No GM Level
2021-12-05 17:54:36 +00:00
}
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.
2023-05-02 22:39:21 +00:00
outBitStream - > Write ( m_IsParentChildDirty | | packetType = = eReplicaPacketType : : CONSTRUCTION ) ;
if ( m_IsParentChildDirty | | packetType = = eReplicaPacketType : : 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 ( ) ) ;
}
}
}
}
2023-06-12 22:32:46 +00:00
void Entity : : WriteComponents ( RakNet : : BitStream * outBitStream , const eReplicaPacketType packetType ) {
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.
2022-07-28 13:39:57 +00:00
for ( const auto & pair : m_Components ) {
2021-12-05 17:54:36 +00:00
if ( pair . second = = nullptr ) continue ;
pair . second - > UpdateXml ( doc ) ;
}
}
2023-06-12 22:32:46 +00:00
CppScripts : : Script * Entity : : GetScript ( ) const {
auto * scriptComponent = GetComponent < ScriptComponent > ( ) ;
2023-06-14 02:47:14 +00:00
if ( ! scriptComponent ) return CppScripts : : invalidScript . get ( ) ;
2023-06-12 22:32:46 +00:00
auto * script = scriptComponent - > GetScript ( ) ;
DluAssert ( script ! = nullptr ) ;
return script ;
}
2021-12-05 17:54:36 +00:00
void Entity : : Update ( const float deltaTime ) {
2023-06-12 22:32:46 +00:00
auto namedTimerItr = std : : remove_if ( m_Timers . begin ( ) , m_Timers . end ( ) , [ this , & deltaTime ] ( EntityTimer * timer ) {
timer - > Update ( deltaTime ) ;
if ( timer - > GetTime ( ) < = 0 ) {
GetScript ( ) - > OnTimerDone ( this , timer - > GetName ( ) ) ;
2023-04-18 17:48:03 +00:00
TriggerEvent ( eTriggerEventType : : TIMER_DONE , this ) ;
2023-06-12 22:32:46 +00:00
delete timer ;
return true ;
2021-12-05 17:54:36 +00:00
}
2023-06-12 22:32:46 +00:00
return false ;
} ) ;
m_Timers . erase ( namedTimerItr , m_Timers . end ( ) ) ;
2021-12-05 17:54:36 +00:00
2023-06-12 22:32:46 +00:00
auto callbackTimerItr = std : : remove_if ( m_CallbackTimers . begin ( ) , m_CallbackTimers . end ( ) , [ this , & deltaTime ] ( EntityCallbackTimer * timer ) {
timer - > Update ( deltaTime ) ;
if ( timer - > GetTime ( ) < = 0 ) {
timer - > GetCallback ( ) ( ) ;
delete timer ;
return true ;
2021-12-05 17:54:36 +00:00
}
2023-06-12 22:32:46 +00:00
return false ;
} ) ;
m_CallbackTimers . erase ( callbackTimerItr , m_CallbackTimers . end ( ) ) ;
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
2022-07-28 13:39:57 +00:00
if ( IsSleeping ( ) ) {
2021-12-05 17:54:36 +00:00
Sleep ( ) ;
return ;
2022-07-28 13:39:57 +00:00
} else {
2021-12-05 17:54:36 +00:00
Wake ( ) ;
}
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnUpdate ( this ) ;
}
2022-07-28 13:39:57 +00:00
for ( const auto & pair : m_Components ) {
2021-12-05 17:54:36 +00:00
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 ) ;
}
2023-06-12 11:00:44 +00:00
auto * rocketComp = GetComponent < RocketLaunchpadControlComponent > ( ) ;
2021-12-05 17:54:36 +00:00
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 ) ;
}
2022-07-28 13:39:57 +00:00
for ( const auto & callback : m_PhantomCollisionCallbacks ) {
callback ( other ) ;
2021-12-05 17:54:36 +00:00
}
2023-06-12 11:00:44 +00:00
auto * switchComp = GetComponent < SwitchComponent > ( ) ;
2021-12-05 17:54:36 +00:00
if ( switchComp ) {
switchComp - > EntityEnter ( other ) ;
}
2023-02-10 08:29:53 +00:00
TriggerEvent ( eTriggerEventType : : ENTER , other ) ;
2021-12-05 17:54:36 +00:00
// POI system
const auto & poi = GetVar < std : : u16string > ( u " POI " ) ;
if ( ! poi . empty ( ) ) {
2023-06-09 08:27:05 +00:00
auto * missionComponent = other - > GetComponent < MissionComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( missionComponent ! = nullptr ) {
2023-01-22 23:38:47 +00:00
missionComponent - > Progress ( eMissionTaskType : : EXPLORE , 0 , 0 , GeneralUtils : : UTF16ToWTF8 ( poi ) ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-28 13:39:57 +00:00
if ( ! other - > GetIsDead ( ) ) {
2023-06-12 11:00:44 +00:00
auto * combat = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( combat ! = nullptr ) {
2021-12-05 17:54:36 +00:00
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 ) ;
}
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnCollisionLeavePhantom ( const LWOOBJID otherEntity ) {
2021-12-05 17:54:36 +00:00
auto * other = EntityManager : : Instance ( ) - > GetEntity ( otherEntity ) ;
if ( ! other ) return ;
2023-04-12 16:46:31 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnOffCollisionPhantom ( this , other ) ;
}
2023-02-10 08:29:53 +00:00
TriggerEvent ( eTriggerEventType : : EXIT , other ) ;
2021-12-05 17:54:36 +00:00
2023-06-12 11:00:44 +00:00
auto * switchComp = GetComponent < SwitchComponent > ( ) ;
2021-12-05 17:54:36 +00:00
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 ) {
2022-07-28 13:39:57 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnFireEventServerSide ( this , sender , args , param1 , param2 , param3 ) ;
2021-12-05 17:54:36 +00:00
}
}
void Entity : : OnActivityStateChangeRequest ( LWOOBJID senderID , int32_t value1 , int32_t value2 , const std : : u16string & stringValue ) {
2022-07-28 13:39:57 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnActivityStateChangeRequest ( this , senderID , value1 , value2 , stringValue ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-28 13:39:57 +00:00
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 ) ;
}
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
void Entity : : NotifyObject ( Entity * sender , const std : : string & name , int32_t param1 , int32_t param2 ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendNotifyObject ( GetObjectID ( ) , sender - > GetObjectID ( ) , GeneralUtils : : ASCIIToUTF16 ( name ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
2022-07-28 13:39:57 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnNotifyObject ( this , sender , name , param1 , param2 ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnEmoteReceived ( const int32_t emote , Entity * target ) {
for ( auto * script : CppScripts : : GetEntityScripts ( this ) ) {
2021-12-05 17:54:36 +00:00
script - > OnEmoteReceived ( this , emote , target ) ;
}
}
void Entity : : OnUse ( Entity * originator ) {
2023-03-25 10:26:39 +00:00
TriggerEvent ( eTriggerEventType : : INTERACT , originator ) ;
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnUse ( this , originator ) ;
}
// component base class when
2022-07-28 13:39:57 +00:00
for ( const auto & pair : m_Components ) {
2021-12-05 17:54:36 +00:00
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 ) {
2023-03-25 10:26:39 +00:00
TriggerEvent ( eTriggerEventType : : HIT , attacker ) ;
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnHit ( this , attacker ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyEditBegin ( ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyEditBegin ( this ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyEditEnd ( ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyEditEnd ( this ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelEquipped ( ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelEquipped ( this ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelPlaced ( Entity * player ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelPlaced ( this , player ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelPickedUp ( Entity * player ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelPickedUp ( this , player ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelRemoved ( Entity * player ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRemoved ( this , player ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelRemovedWhileEquipped ( Entity * player ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRemovedWhileEquipped ( this , player ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnZonePropertyModelRotated ( Entity * player ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnZonePropertyModelRotated ( this , player ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnMessageBoxResponse ( Entity * sender , int32_t button , const std : : u16string & identifier , const std : : u16string & userData ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnMessageBoxResponse ( this , sender , button , identifier , userData ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : OnChoiceBoxResponse ( Entity * sender , int32_t button , const std : : u16string & buttonIdentifier , const std : : u16string & identifier ) {
2021-12-05 17:54:36 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnChoiceBoxResponse ( this , sender , button , buttonIdentifier , identifier ) ;
}
}
2023-06-09 08:04:42 +00:00
void Entity : : RequestActivityExit ( Entity * sender , const LWOOBJID & player , const bool canceled ) {
2023-05-11 00:26:04 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
script - > OnRequestActivityExit ( sender , player , canceled ) ;
}
}
2022-07-28 13:39:57 +00:00
void Entity : : Smash ( const LWOOBJID source , const eKillType killType , const std : : u16string & deathType ) {
2021-12-05 17:54:36 +00:00
if ( ! m_PlayerIsReadyForUpdates ) return ;
2023-06-12 11:00:44 +00:00
auto * destroyableComponent = GetComponent < DestroyableComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( destroyableComponent = = nullptr ) {
2021-12-05 17:54:36 +00:00
Kill ( EntityManager : : Instance ( ) - > GetEntity ( source ) ) ;
return ;
}
2023-06-12 11:00:44 +00:00
auto * possessorComponent = GetComponent < PossessorComponent > ( ) ;
2022-09-02 18:49:19 +00:00
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
2022-07-28 13:39:57 +00:00
for ( CppScripts : : Script * script : CppScripts : : GetEntityScripts ( this ) ) {
2021-12-05 17:54:36 +00:00
script - > OnDie ( this , murderer ) ;
}
2022-07-28 13:39:57 +00:00
if ( m_Spawner ! = nullptr ) {
2021-12-05 17:54:36 +00:00
m_Spawner - > NotifyOfEntityDeath ( m_ObjectID ) ;
}
2022-07-28 13:39:57 +00:00
if ( ! IsPlayer ( ) ) {
2021-12-05 17:54:36 +00:00
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 " ) ;
2022-07-28 13:39:57 +00:00
if ( ! grpNameQBShowBricks . empty ( ) ) {
2021-12-05 17:54:36 +00:00
auto spawners = dZoneManager : : Instance ( ) - > GetSpawnersByName ( grpNameQBShowBricks ) ;
Spawner * spawner = nullptr ;
2022-07-28 13:39:57 +00:00
if ( ! spawners . empty ( ) ) {
2021-12-05 17:54:36 +00:00
spawner = spawners [ 0 ] ;
2022-07-28 13:39:57 +00:00
} else {
2021-12-05 17:54:36 +00:00
spawners = dZoneManager : : Instance ( ) - > GetSpawnersInGroup ( grpNameQBShowBricks ) ;
2022-07-28 13:39:57 +00:00
if ( ! spawners . empty ( ) ) {
2021-12-05 17:54:36 +00:00
spawner = spawners [ 0 ] ;
}
}
2022-07-28 13:39:57 +00:00
if ( spawner ! = nullptr ) {
2021-12-05 17:54:36 +00:00
spawner - > Spawn ( ) ;
}
}
2022-07-28 13:39:57 +00:00
// Track a player being smashed
2023-06-12 11:00:44 +00:00
auto * characterComponent = GetComponent < CharacterComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( characterComponent ! = nullptr ) {
characterComponent - > UpdatePlayerStatistic ( TimesSmashed ) ;
}
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
// Track a player smashing something else
if ( murderer ! = nullptr ) {
2023-06-09 08:27:05 +00:00
auto * murdererCharacterComponent = murderer - > GetComponent < CharacterComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( murdererCharacterComponent ! = nullptr ) {
murdererCharacterComponent - > UpdatePlayerStatistic ( SmashablesSmashed ) ;
}
}
2021-12-05 17:54:36 +00:00
}
void Entity : : AddDieCallback ( const std : : function < void ( ) > & callback ) {
m_DieCallbacks . push_back ( callback ) ;
}
void Entity : : AddCollisionPhantomCallback ( const std : : function < void ( Entity * target ) > & callback ) {
2022-07-28 13:39:57 +00:00
m_PhantomCollisionCallbacks . push_back ( callback ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
void Entity : : AddRebuildCompleteCallback ( const std : : function < void ( Entity * user ) > & callback ) const {
2023-06-12 11:00:44 +00:00
auto * quickBuildComponent = GetComponent < QuickBuildComponent > ( ) ;
2023-06-09 22:12:57 +00:00
if ( quickBuildComponent ! = nullptr ) {
quickBuildComponent - > AddRebuildCompleteCallback ( callback ) ;
2022-07-28 13:39:57 +00:00
}
2021-12-05 17:54:36 +00:00
}
bool Entity : : GetIsDead ( ) const {
2023-06-12 11:00:44 +00:00
auto * dest = GetComponent < DestroyableComponent > ( ) ;
2021-12-05 17:54:36 +00:00
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 ;
2023-06-12 11:00:44 +00:00
auto * inv = GetComponent < InventoryComponent > ( ) ;
2021-12-05 17:54:36 +00:00
if ( ! inv ) return ;
2023-03-17 14:36:21 +00:00
CDObjectsTable * objectsTable = CDClientManager : : Instance ( ) . GetTable < CDObjectsTable > ( ) ;
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 ) {
2023-06-12 11:00:44 +00:00
auto * characterComponent = GetComponent < CharacterComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( characterComponent ! = nullptr ) {
characterComponent - > TrackLOTCollection ( p . second . lot ) ;
}
2021-12-05 17:54:36 +00:00
const CDObjects & object = objectsTable - > GetByID ( p . second . lot ) ;
if ( object . id ! = 0 & & object . type = = " Powerup " ) {
2023-03-17 14:36:21 +00:00
CDObjectSkillsTable * skillsTable = CDClientManager : : Instance ( ) . GetTable < CDObjectSkillsTable > ( ) ;
2021-12-05 17:54:36 +00:00
std : : vector < CDObjectSkills > skills = skillsTable - > Query ( [ = ] ( CDObjectSkills entry ) { return ( entry . objectTemplate = = p . second . lot ) ; } ) ;
for ( CDObjectSkills skill : skills ) {
2023-03-17 14:36:21 +00:00
CDSkillBehaviorTable * skillBehTable = CDClientManager : : Instance ( ) . GetTable < CDSkillBehaviorTable > ( ) ;
2021-12-05 17:54:36 +00:00
CDSkillBehavior behaviorData = skillBehTable - > GetSkillByID ( skill . skillID ) ;
SkillComponent : : HandleUnmanaged ( behaviorData . behaviorID , GetObjectID ( ) ) ;
2023-06-12 11:00:44 +00:00
auto * missionComponent = GetComponent < MissionComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( missionComponent ! = nullptr ) {
2023-01-22 23:38:47 +00:00
missionComponent - > Progress ( eMissionTaskType : : POWERUP , skill . skillID ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-07-28 13:39:57 +00:00
} else {
2023-05-02 22:39:21 +00:00
inv - > AddItem ( p . second . lot , p . second . count , eLootSourceType : : PICKUP , eInventoryType : : INVALID , { } , LWOOBJID_EMPTY , true , false , LWOOBJID_EMPTY , eInventoryType : : INVALID , 1 ) ;
2021-12-05 17:54:36 +00:00
}
}
}
droppedLoot . erase ( objectID ) ;
}
2023-06-09 08:04:42 +00:00
bool Entity : : CanPickupCoins ( const 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 ( ) ;
2022-07-28 13:39:57 +00:00
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 ;
}
}
2023-06-09 08:04:42 +00:00
void Entity : : RegisterCoinDrop ( const 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 ;
}
2023-06-09 08:04:42 +00:00
void Entity : : AddTimer ( const std : : string & name , float time ) {
2021-12-05 17:54:36 +00:00
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
}
2023-06-09 08:04:42 +00:00
void Entity : : AddCallbackTimer ( const float time , const std : : function < void ( ) > & callback ) {
2021-12-05 17:54:36 +00:00
EntityCallbackTimer * timer = new EntityCallbackTimer ( time , callback ) ;
m_CallbackTimers . push_back ( timer ) ;
}
2022-07-28 13:39:57 +00:00
bool Entity : : HasTimer ( const std : : string & name ) {
for ( auto * timer : m_Timers ) {
if ( timer - > GetName ( ) = = name ) {
2021-12-05 17:54:36 +00:00
return true ;
}
}
return false ;
}
2022-07-28 13:39:57 +00:00
void Entity : : CancelCallbackTimers ( ) {
for ( auto * callback : m_CallbackTimers ) {
2021-12-05 17:54:36 +00:00
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 ) {
2022-07-28 13:39:57 +00:00
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 ;
}
}
2021-12-05 17:54:36 +00:00
}
void Entity : : CancelAllTimers ( ) {
2022-07-28 13:39:57 +00:00
for ( auto * timer : m_Timers ) {
2021-12-05 17:54:36 +00:00
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
}
2023-02-10 08:29:53 +00:00
void Entity : : TriggerEvent ( eTriggerEventType event , Entity * optionalTarget ) {
2023-06-12 11:00:44 +00:00
auto * triggerComponent = GetComponent < TriggerComponent > ( ) ;
2023-02-10 08:29:53 +00:00
if ( triggerComponent ) triggerComponent - > TriggerEvent ( event , optionalTarget ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
Entity * Entity : : GetOwner ( ) const {
if ( m_OwnerOverride ! = LWOOBJID_EMPTY ) {
2021-12-05 17:54:36 +00:00
auto * other = EntityManager : : Instance ( ) - > GetEntity ( m_OwnerOverride ) ;
2022-07-28 13:39:57 +00:00
if ( other ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return other - > GetOwner ( ) ;
}
}
return const_cast < Entity * > ( this ) ;
}
2022-07-28 13:39:57 +00:00
const NiPoint3 & Entity : : GetDefaultPosition ( ) const {
2021-12-05 17:54:36 +00:00
return m_DefaultPosition ;
}
2022-07-28 13:39:57 +00:00
const NiQuaternion & Entity : : GetDefaultRotation ( ) const {
2021-12-05 17:54:36 +00:00
return m_DefaultRotation ;
}
2023-06-09 08:04:42 +00:00
void Entity : : SetOwnerOverride ( const LWOOBJID & value ) {
2021-12-05 17:54:36 +00:00
m_OwnerOverride = value ;
}
2022-07-28 13:39:57 +00:00
void Entity : : SetObservers ( int8_t value ) {
if ( value < 0 ) {
2021-12-05 17:54:36 +00:00
value = 0 ;
}
m_Observers = value ;
}
2022-07-28 13:39:57 +00:00
void Entity : : Sleep ( ) {
2023-06-12 11:00:44 +00:00
auto * baseCombatAIComponent = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( baseCombatAIComponent ! = nullptr ) {
2021-12-05 17:54:36 +00:00
baseCombatAIComponent - > Sleep ( ) ;
2022-07-28 13:39:57 +00:00
}
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
void Entity : : Wake ( ) {
2023-06-12 11:00:44 +00:00
auto * baseCombatAIComponent = GetComponent < BaseCombatAIComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( baseCombatAIComponent ! = nullptr ) {
2021-12-05 17:54:36 +00:00
baseCombatAIComponent - > Wake ( ) ;
}
}
2022-07-28 13:39:57 +00:00
bool Entity : : IsSleeping ( ) const {
2021-12-05 17:54:36 +00:00
return m_IsGhostingCandidate & & m_Observers = = 0 ;
}
2022-07-28 13:39:57 +00:00
const NiPoint3 & Entity : : GetPosition ( ) const {
2021-12-05 17:54:36 +00:00
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
2022-07-28 13:39:57 +00:00
if ( controllable ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return controllable - > GetPosition ( ) ;
}
2023-06-12 11:00:44 +00:00
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( phantom ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return phantom - > GetPosition ( ) ;
}
2023-06-12 11:00:44 +00:00
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( simple ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return simple - > GetPosition ( ) ;
}
2023-06-12 11:00:44 +00:00
auto * vehicle = GetComponent < HavokVehiclePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2023-06-07 03:48:30 +00:00
if ( vehicle ! = nullptr ) {
return vehicle - > GetPosition ( ) ;
2021-12-05 17:54:36 +00:00
}
return NiPoint3 : : ZERO ;
}
2022-07-28 13:39:57 +00:00
const NiQuaternion & Entity : : GetRotation ( ) const {
2023-06-12 11:00:44 +00:00
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( controllable ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return controllable - > GetRotation ( ) ;
}
2023-06-12 11:00:44 +00:00
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( phantom ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return phantom - > GetRotation ( ) ;
}
2023-06-12 11:00:44 +00:00
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( simple ! = nullptr ) {
2021-12-05 17:54:36 +00:00
return simple - > GetRotation ( ) ;
}
2022-07-28 13:39:57 +00:00
2023-06-12 11:00:44 +00:00
auto * vehicle = GetComponent < HavokVehiclePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2023-06-07 03:48:30 +00:00
if ( vehicle ! = nullptr ) {
return vehicle - > GetRotation ( ) ;
2021-12-05 17:54:36 +00:00
}
return NiQuaternion : : IDENTITY ;
}
2023-06-09 08:04:42 +00:00
void Entity : : SetPosition ( const NiPoint3 & position ) {
2023-06-12 11:00:44 +00:00
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( controllable ! = nullptr ) {
2021-12-05 17:54:36 +00:00
controllable - > SetPosition ( position ) ;
}
2023-06-12 11:00:44 +00:00
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( phantom ! = nullptr ) {
2021-12-05 17:54:36 +00:00
phantom - > SetPosition ( position ) ;
}
2023-06-12 11:00:44 +00:00
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( simple ! = nullptr ) {
2021-12-05 17:54:36 +00:00
simple - > SetPosition ( position ) ;
}
2023-06-12 11:00:44 +00:00
auto * vehicle = GetComponent < HavokVehiclePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2023-06-07 03:48:30 +00:00
if ( vehicle ! = nullptr ) {
vehicle - > SetPosition ( position ) ;
2021-12-05 17:54:36 +00:00
}
EntityManager : : Instance ( ) - > SerializeEntity ( this ) ;
}
2023-06-09 08:04:42 +00:00
void Entity : : SetRotation ( const NiQuaternion & rotation ) {
2023-06-12 11:00:44 +00:00
auto * controllable = GetComponent < ControllablePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( controllable ! = nullptr ) {
2021-12-05 17:54:36 +00:00
controllable - > SetRotation ( rotation ) ;
}
2023-06-12 11:00:44 +00:00
auto * phantom = GetComponent < PhantomPhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( phantom ! = nullptr ) {
2021-12-05 17:54:36 +00:00
phantom - > SetRotation ( rotation ) ;
}
2023-06-12 11:00:44 +00:00
auto * simple = GetComponent < SimplePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-28 13:39:57 +00:00
if ( simple ! = nullptr ) {
2021-12-05 17:54:36 +00:00
simple - > SetRotation ( rotation ) ;
}
2023-06-12 11:00:44 +00:00
auto * vehicle = GetComponent < HavokVehiclePhysicsComponent > ( ) ;
2021-12-05 17:54:36 +00:00
2023-06-07 03:48:30 +00:00
if ( vehicle ! = nullptr ) {
vehicle - > SetRotation ( rotation ) ;
2021-12-05 17:54:36 +00:00
}
EntityManager : : Instance ( ) - > SerializeEntity ( this ) ;
}
2022-07-28 13:39:57 +00:00
bool Entity : : GetBoolean ( const std : : u16string & name ) const {
2021-12-05 17:54:36 +00:00
return GetVar < bool > ( name ) ;
}
2022-07-28 13:39:57 +00:00
int32_t Entity : : GetI32 ( const std : : u16string & name ) const {
2021-12-05 17:54:36 +00:00
return GetVar < int32_t > ( name ) ;
}
2022-07-28 13:39:57 +00:00
int64_t Entity : : GetI64 ( const std : : u16string & name ) const {
2021-12-05 17:54:36 +00:00
return GetVar < int64_t > ( name ) ;
}
2022-07-28 13:39:57 +00:00
void Entity : : SetBoolean ( const std : : u16string & name , const bool value ) {
2021-12-05 17:54:36 +00:00
SetVar ( name , value ) ;
}
2022-07-28 13:39:57 +00:00
void Entity : : SetI32 ( const std : : u16string & name , const int32_t value ) {
2021-12-05 17:54:36 +00:00
SetVar ( name , value ) ;
}
2022-07-28 13:39:57 +00:00
void Entity : : SetI64 ( const std : : u16string & name , const int64_t value ) {
2021-12-05 17:54:36 +00:00
SetVar ( name , value ) ;
}
2022-07-28 13:39:57 +00:00
bool Entity : : HasVar ( const std : : u16string & name ) const {
for ( auto * data : m_Settings ) {
if ( data - > GetKey ( ) = = name ) {
2021-12-05 17:54:36 +00:00
return true ;
}
}
2022-07-28 13:39:57 +00:00
2021-12-05 17:54:36 +00:00
return false ;
}
2022-07-28 13:39:57 +00:00
void Entity : : SetNetworkId ( const uint16_t id ) {
2021-12-05 17:54:36 +00:00
m_NetworkID = id ;
}
2022-07-28 13:39:57 +00:00
std : : vector < LWOOBJID > & Entity : : GetTargetsInPhantom ( ) {
2021-12-05 17:54:36 +00:00
std : : vector < LWOOBJID > valid ;
// Clean up invalid targets, like disconnected players
2022-07-28 13:39:57 +00:00
for ( auto i = 0u ; i < m_TargetsInPhantom . size ( ) ; + + i ) {
2021-12-05 17:54:36 +00:00
const auto id = m_TargetsInPhantom . at ( i ) ;
auto * entity = EntityManager : : Instance ( ) - > GetEntity ( id ) ;
2022-07-28 13:39:57 +00:00
if ( entity = = nullptr ) {
2021-12-05 17:54:36 +00:00
continue ;
}
valid . push_back ( id ) ;
}
m_TargetsInPhantom = valid ;
return m_TargetsInPhantom ;
}
void Entity : : SendNetworkVar ( const std : : string & data , const SystemAddress & sysAddr ) {
2022-07-28 13:39:57 +00:00
GameMessages : : SendSetNetworkScriptVar ( this , sysAddr , data ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-28 13:39:57 +00:00
LDFBaseData * Entity : : GetVarData ( const std : : u16string & name ) const {
for ( auto * data : m_Settings ) {
if ( data = = nullptr ) {
2021-12-05 17:54:36 +00:00
continue ;
}
2022-07-28 13:39:57 +00:00
if ( data - > GetKey ( ) ! = name ) {
2021-12-05 17:54:36 +00:00
continue ;
}
return data ;
}
return nullptr ;
}
2022-07-28 13:39:57 +00:00
std : : string Entity : : GetVarAsString ( const std : : u16string & name ) const {
2021-12-05 17:54:36 +00:00
auto * data = GetVarData ( name ) ;
2022-07-28 13:39:57 +00:00
if ( data = = nullptr ) {
2021-12-05 17:54:36 +00:00
return " " ;
}
return data - > GetValueAsString ( ) ;
}
void Entity : : Resurrect ( ) {
2022-07-28 13:39:57 +00:00
if ( IsPlayer ( ) ) {
GameMessages : : SendResurrect ( this ) ;
}
2021-12-05 17:54:36 +00:00
}
2023-06-09 08:04:42 +00:00
void Entity : : AddToGroups ( const std : : string & group ) {
2022-07-28 13:39:57 +00:00
if ( std : : find ( m_Groups . begin ( ) , m_Groups . end ( ) , group ) = = m_Groups . end ( ) ) {
m_Groups . push_back ( group ) ;
}
2021-12-05 17:54:36 +00:00
}
2022-04-13 08:49:55 +00:00
void Entity : : RetroactiveVaultSize ( ) {
2023-06-12 11:00:44 +00:00
auto * inventoryComponent = GetComponent < InventoryComponent > ( ) ;
2022-04-13 08:49:55 +00:00
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 ( ) ) ;
}