mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-01-02 09:00:10 -06:00
Compare commits
54 Commits
cdcinstanc
...
fixDestCom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8a4da0679 | ||
|
|
623da4bed9 | ||
|
|
50921cce2d | ||
|
|
3806891db0 | ||
|
|
ba91058736 | ||
|
|
73e70badb7 | ||
|
|
e4cae35edb | ||
|
|
c6087ce77a | ||
|
|
e96fd56fbd | ||
|
|
500ae4d6e5 | ||
|
|
094797881b | ||
|
|
3dd2791066 | ||
| 570c597148 | |||
|
|
ad003634f4 | ||
| d8ac148cee | |||
|
|
471d65707c | ||
|
|
94f8a99fba | ||
|
|
288991ef49 | ||
|
|
74cc4176e1 | ||
| b33e9935f5 | |||
|
|
258ee5c1ee | ||
|
|
a8820c14f2 | ||
| 1ec8da8bf7 | |||
|
|
b24775f472 | ||
|
|
bd65fc6e33 | ||
|
|
44f466ac72 | ||
|
|
51540568fb | ||
| 08020cd86d | |||
| ca78a166d9 | |||
| 2e386d29df | |||
| d893ecddeb | |||
|
|
f4f13e081a | ||
|
|
c26086aff5 | ||
|
|
0337449aa7 | ||
|
|
598f4e1663 | ||
|
|
5eca25e42a | ||
|
|
d233c7e2aa | ||
| beaceb947b | |||
|
|
2cc13c6499 | ||
|
|
ad81e341da | ||
|
|
fe6be21008 | ||
| cefdfc696a | |||
| 7e2747a2d2 | |||
| a29253d2f0 | |||
|
|
e5b69745aa | ||
|
|
040a78c386 | ||
|
|
d8a5fd49a4 | ||
|
|
208ed02158 | ||
| 952786c166 | |||
|
|
9a07020a51 | ||
| a22ecf385f | |||
| c2b4aa4026 | |||
|
|
0d48cfe8c0 | ||
| e299bf9b62 |
@@ -14,4 +14,4 @@ EXTERNAL_IP=localhost
|
|||||||
MARIADB_USER=darkflame
|
MARIADB_USER=darkflame
|
||||||
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_DATABASE=darkflame
|
MARIADB_DATABASE=darkflame
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=1
|
PROJECT_VERSION_MINOR=1
|
||||||
PROJECT_VERSION_PATCH=0
|
PROJECT_VERSION_PATCH=1
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
# The network version.
|
|
||||||
# 171023 - Darkflame Universe client
|
|
||||||
# 171022 - Unmodded client
|
|
||||||
NET_VERSION=171022
|
|
||||||
# Debugging
|
# Debugging
|
||||||
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
__dynamic=1
|
__dynamic=1
|
||||||
@@ -22,3 +18,5 @@ __maria_db_connector_compile_jobs__=1
|
|||||||
__enable_testing__=1
|
__enable_testing__=1
|
||||||
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
||||||
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
||||||
|
# Uncomment the below line to cache the entire CDClient into memory
|
||||||
|
# CDCLIENT_CACHE_ALL=1
|
||||||
|
|||||||
264
ComponentDefinitions.py
Normal file
264
ComponentDefinitions.py
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
components = {
|
||||||
|
'COMPONENT_TYPE_CONTROLLABLE_PHYSICS': 1,
|
||||||
|
'COMPONENT_TYPE_RENDER': 2,
|
||||||
|
'COMPONENT_TYPE_SIMPLE_PHYSICS': 3,
|
||||||
|
'COMPONENT_TYPE_CHARACTER': 4,
|
||||||
|
'COMPONENT_TYPE_SCRIPT': 5,
|
||||||
|
'COMPONENT_TYPE_BOUNCER': 6,
|
||||||
|
'COMPONENT_TYPE_DESTROYABLE': 7,
|
||||||
|
'COMPONENT_TYPE_GHOST': 8,
|
||||||
|
'COMPONENT_TYPE_SKILL': 9,
|
||||||
|
'COMPONENT_TYPE_SPAWNER': 10,
|
||||||
|
'COMPONENT_TYPE_ITEM': 11,
|
||||||
|
'COMPONENT_TYPE_MODULAR_BUILD': 12,
|
||||||
|
'COMPONENT_TYPE_BUILD_CONTROLLER': 13,
|
||||||
|
'COMPONENT_TYPE_REBUILD_ACTIVATOR': 14,
|
||||||
|
'COMPONENT_TYPE_ICON_ONLY': 15,
|
||||||
|
'COMPONENT_TYPE_VENDOR': 16,
|
||||||
|
'COMPONENT_TYPE_INVENTORY': 17,
|
||||||
|
'COMPONENT_TYPE_PROJECTILE_PHYSICS': 18,
|
||||||
|
'COMPONENT_TYPE_SHOOTING_GALLERY': 19,
|
||||||
|
'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS': 20,
|
||||||
|
'COMPONENT_TYPE_DROP_EFFECT': 21,
|
||||||
|
'COMPONENT_TYPE_CHEST': 22,
|
||||||
|
'COMPONENT_TYPE_COLLECTIBLE': 23,
|
||||||
|
'COMPONENT_TYPE_BLUEPRINT': 24,
|
||||||
|
'COMPONENT_TYPE_MOVING_PLATFORM': 25,
|
||||||
|
'COMPONENT_TYPE_PET': 26,
|
||||||
|
'COMPONENT_TYPE_PLATFORM_BOUNDARY': 27,
|
||||||
|
'COMPONENT_TYPE_MODULE': 28,
|
||||||
|
'COMPONENT_TYPE_ARCADE': 29,
|
||||||
|
'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS': 30,
|
||||||
|
'COMPONENT_TYPE_MOVEMENT_AI': 31,
|
||||||
|
'COMPONENT_TYPE_EXHIBIT': 32,
|
||||||
|
'COMPONENT_TYPE_OVERHEAD_ICON': 33,
|
||||||
|
'COMPONENT_TYPE_PET_CONTROL': 34,
|
||||||
|
'COMPONENT_TYPE_MINIFIG': 35,
|
||||||
|
'COMPONENT_TYPE_PROPERTY': 36,
|
||||||
|
'COMPONENT_TYPE_PET_CREATOR': 37,
|
||||||
|
'COMPONENT_TYPE_MODEL_BUILDER': 38,
|
||||||
|
'COMPONENT_TYPE_SCRIPTED_ACTIVITY': 39,
|
||||||
|
'COMPONENT_TYPE_PHANTOM_PHYSICS': 40,
|
||||||
|
'COMPONENT_TYPE_SPRING_PAD': 41,
|
||||||
|
'COMPONENT_TYPE_MODEL': 42,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_ENTRANCE': 43,
|
||||||
|
'COMPONENT_TYPE_FX': 44,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_MANAGEMENT': 45,
|
||||||
|
'COMPONENT_TYPE_VEHICLE_PHYSICS': 46,
|
||||||
|
'COMPONENT_TYPE_PHYSICS_SYSTEM': 47,
|
||||||
|
'COMPONENT_TYPE_REBUILD': 48,
|
||||||
|
'COMPONENT_TYPE_SWITCH': 49,
|
||||||
|
'COMPONENT_TYPE_ZONE_CONTROL': 50,
|
||||||
|
'COMPONENT_TYPE_CHANGELING': 51,
|
||||||
|
'COMPONENT_TYPE_CHOICE_BUILD': 52,
|
||||||
|
'COMPONENT_TYPE_PACKAGE': 53,
|
||||||
|
'COMPONENT_TYPE_SOUND_REPEATER': 54,
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_2D': 55,
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_3D': 56,
|
||||||
|
'COMPONENT_TYPE_PRECONDITION': 57,
|
||||||
|
'COMPONENT_TYPE_PLAYER_FLAG': 58,
|
||||||
|
'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY': 59,
|
||||||
|
'COMPONENT_TYPE_BASE_COMBAT_AI': 60,
|
||||||
|
'COMPONENT_TYPE_MODULE_ASSEMBLY': 61,
|
||||||
|
'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER': 62,
|
||||||
|
'COMPONENT_TYPE_RACING_MODULE': 63,
|
||||||
|
'COMPONENT_TYPE_GENERIC_ACTIVATOR': 64,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_VENDOR': 65,
|
||||||
|
'COMPONENT_TYPE_HF_LIGHT_DIRECTION_GADGET': 66,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH': 67,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT': 68,
|
||||||
|
'COMPONENT_TYPE_TRIGGER': 69,
|
||||||
|
'COMPONENT_TYPE_DROPPED_LOOT': 70,
|
||||||
|
'COMPONENT_TYPE_RACING_CONTROL': 71,
|
||||||
|
'COMPONENT_TYPE_FACTION_TRIGGER': 72,
|
||||||
|
'COMPONENT_TYPE_MISSION_OFFER': 73,
|
||||||
|
'COMPONENT_TYPE_RACING_STATS': 74,
|
||||||
|
'COMPONENT_TYPE_LUP_EXHIBIT': 75,
|
||||||
|
'COMPONENT_TYPE_BBB': 76,
|
||||||
|
'COMPONENT_TYPE_SOUND_TRIGGER': 77,
|
||||||
|
'COMPONENT_TYPE_PROXIMITY_MONITOR': 78,
|
||||||
|
'COMPONENT_TYPE_RACING_SOUND_TRIGGER': 79,
|
||||||
|
'COMPONENT_TYPE_CHAT': 80,
|
||||||
|
'COMPONENT_TYPE_FRIENDS_LIST': 81,
|
||||||
|
'COMPONENT_TYPE_GUILD': 82,
|
||||||
|
'COMPONENT_TYPE_LOCAL_SYSTEM': 83,
|
||||||
|
'COMPONENT_TYPE_MISSION': 84,
|
||||||
|
'COMPONENT_TYPE_MUTUABLE_MODEL_BEHAVIORS': 85,
|
||||||
|
'COMPONENT_TYPE_PATHFINDING_CONTROL': 86,
|
||||||
|
'COMPONENT_TYPE_PLAYER_PET_TAMING': 87,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_EDITOR': 88,
|
||||||
|
'COMPONENT_TYPE_SKINNED_RENDER': 89,
|
||||||
|
'COMPONENT_TYPE_SLASH_COMMAND': 90,
|
||||||
|
'COMPONENT_TYPE_STATUS_EFFECT': 91,
|
||||||
|
'COMPONENT_TYPE_TEAMS': 92,
|
||||||
|
'COMPONENT_TYPE_TEXT_EFFECT': 93,
|
||||||
|
'COMPONENT_TYPE_TRADE': 94,
|
||||||
|
'COMPONENT_TYPE_USER_CONTROL': 95,
|
||||||
|
'COMPONENT_TYPE_IGNORE_LIST': 96,
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH_LUP': 97,
|
||||||
|
'COMPONENT_TYPE_BUFF': 98,
|
||||||
|
'COMPONENT_TYPE_INTERACTION_MANAGER': 99,
|
||||||
|
'COMPONENT_TYPE_DONATION_VENDOR': 100,
|
||||||
|
'COMPONENT_TYPE_COMBAT_MEDIATOR': 101,
|
||||||
|
'COMPONENT_TYPE_ACHIEVEMENT_VENDOR': 102,
|
||||||
|
'COMPONENT_TYPE_GATE_RUSH': 103,
|
||||||
|
'COMPONENT_TYPE_RAIL_ACTIVATOR': 104,
|
||||||
|
'COMPONENT_TYPE_ROLLER': 105,
|
||||||
|
'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT': 106,
|
||||||
|
'COMPONENT_TYPE_CRAFTING': 107,
|
||||||
|
'COMPONENT_TYPE_POSSESSABLE': 108,
|
||||||
|
'COMPONENT_TYPE_LEVEL_PROGRESSION': 109,
|
||||||
|
'COMPONENT_TYPE_POSSESSOR': 110,
|
||||||
|
'COMPONENT_TYPE_MOUNT_CONTROL': 111,
|
||||||
|
'UNKNOWN_112': 112,
|
||||||
|
'COMPONENT_TYPE_PROPERTY_PLAQUE': 113,
|
||||||
|
'COMPONENT_TYPE_BUILD_BORDER': 114,
|
||||||
|
'UNKNOWN_115': 115,
|
||||||
|
'COMPONENT_TYPE_CULLING_PLANE': 116,
|
||||||
|
'INVALID': 4294967295
|
||||||
|
}
|
||||||
|
|
||||||
|
component_initialization_order = [
|
||||||
|
'COMPONENT_TYPE_POSSESSABLE',
|
||||||
|
'COMPONENT_TYPE_BLUEPRINT',
|
||||||
|
'COMPONENT_TYPE_MODULE_ASSEMBLY',
|
||||||
|
'COMPONENT_TYPE_CONTROLLABLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PROJECTILE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PHYSICS_SYSTEM',
|
||||||
|
'COMPONENT_TYPE_VEHICLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_SIMPLE_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_PHANTOM_PHYSICS',
|
||||||
|
'COMPONENT_TYPE_DESTROYABLE',
|
||||||
|
'COMPONENT_TYPE_MINIFIG',
|
||||||
|
'COMPONENT_TYPE_CHARACTER',
|
||||||
|
'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT',
|
||||||
|
'COMPONENT_TYPE_POSSESSOR',
|
||||||
|
'COMPONENT_TYPE_MOUNT_CONTROL',
|
||||||
|
'COMPONENT_TYPE_PET',
|
||||||
|
'COMPONENT_TYPE_INVENTORY',
|
||||||
|
'COMPONENT_TYPE_PROXIMITY_MONITOR',
|
||||||
|
'COMPONENT_TYPE_MOVEMENT_AI',
|
||||||
|
'COMPONENT_TYPE_SCRIPT',
|
||||||
|
'COMPONENT_TYPE_SKILL',
|
||||||
|
'COMPONENT_TYPE_BASE_COMBAT_AI',
|
||||||
|
'COMPONENT_TYPE_SPAWNER',
|
||||||
|
'COMPONENT_TYPE_ITEM',
|
||||||
|
'COMPONENT_TYPE_REBUILD',
|
||||||
|
'COMPONENT_TYPE_BUILD_BORDER',
|
||||||
|
'COMPONENT_TYPE_MODULE',
|
||||||
|
'COMPONENT_TYPE_BUILD_CONTROLLER',
|
||||||
|
'COMPONENT_TYPE_REBUILD_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_MODULAR_BUILD',
|
||||||
|
'COMPONENT_TYPE_MISSION_OFFER',
|
||||||
|
'COMPONENT_TYPE_VENDOR',
|
||||||
|
'COMPONENT_TYPE_DONATION_VENDOR',
|
||||||
|
'COMPONENT_TYPE_ACHIEVEMENT_VENDOR',
|
||||||
|
'COMPONENT_TYPE_SHOOTING_GALLERY',
|
||||||
|
'COMPONENT_TYPE_ROLLER',
|
||||||
|
'COMPONENT_TYPE_SCRIPTED_ACTIVITY',
|
||||||
|
'COMPONENT_TYPE_COLLECTIBLE',
|
||||||
|
'COMPONENT_TYPE_MOVING_PLATFORM',
|
||||||
|
'COMPONENT_TYPE_CHANGELING',
|
||||||
|
'COMPONENT_TYPE_CHOICE_BUILD',
|
||||||
|
'COMPONENT_TYPE_PACKAGE',
|
||||||
|
'COMPONENT_TYPE_PLATFORM_BOUNDARY',
|
||||||
|
'COMPONENT_TYPE_HF_LIGHT_DIRECTION_GADGET',
|
||||||
|
'COMPONENT_TYPE_CULLING_PLANE',
|
||||||
|
'COMPONENT_TYPE_EXHIBIT',
|
||||||
|
'COMPONENT_TYPE_LUP_EXHIBIT',
|
||||||
|
'COMPONENT_TYPE_PROPERTY',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_PLAQUE',
|
||||||
|
'COMPONENT_TYPE_MODEL',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_ENTRANCE',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH_LUP',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_MANAGEMENT',
|
||||||
|
'COMPONENT_TYPE_RAIL_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_BOUNCER',
|
||||||
|
'COMPONENT_TYPE_SPRING_PAD',
|
||||||
|
'COMPONENT_TYPE_SWITCH',
|
||||||
|
'COMPONENT_TYPE_ZONE_CONTROL',
|
||||||
|
'COMPONENT_TYPE_MODEL_BUILDER',
|
||||||
|
'COMPONENT_TYPE_SOUND_REPEATER',
|
||||||
|
'COMPONENT_TYPE_CHEST',
|
||||||
|
'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER',
|
||||||
|
'COMPONENT_TYPE_ARCADE',
|
||||||
|
'COMPONENT_TYPE_RENDER',
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_2D',
|
||||||
|
'COMPONENT_TYPE_SOUND_AMBIENT_3D',
|
||||||
|
'COMPONENT_TYPE_SOUND_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_RACING_SOUND_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY',
|
||||||
|
'COMPONENT_TYPE_GENERIC_ACTIVATOR',
|
||||||
|
'COMPONENT_TYPE_PROPERTY_VENDOR',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LAUNCH',
|
||||||
|
'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT',
|
||||||
|
'COMPONENT_TYPE_FACTION_TRIGGER',
|
||||||
|
'COMPONENT_TYPE_RACING_CONTROL',
|
||||||
|
'COMPONENT_TYPE_GATE_RUSH',
|
||||||
|
'COMPONENT_TYPE_BBB',
|
||||||
|
'COMPONENT_TYPE_CRAFTING'
|
||||||
|
]
|
||||||
|
component_order_as_ints = {}
|
||||||
|
|
||||||
|
component_int_to_name = {}
|
||||||
|
|
||||||
|
for component in component_initialization_order:
|
||||||
|
component_order_as_ints[components[component]] = component
|
||||||
|
|
||||||
|
for component in components:
|
||||||
|
component_int_to_name[components[component]] = component
|
||||||
|
|
||||||
|
class GameObject:
|
||||||
|
type = ""
|
||||||
|
|
||||||
|
class ObjectLoadState:
|
||||||
|
createdGameObject = GameObject()
|
||||||
|
components = []
|
||||||
|
hasPhysicsComponent = False
|
||||||
|
hasDestroyable = False
|
||||||
|
hasPathfindingComponent = False
|
||||||
|
hasProximityMonitorComponent = False
|
||||||
|
hasScriptComponent = False
|
||||||
|
hasDroppedLootComponent = False
|
||||||
|
hasModelbehaviors = False
|
||||||
|
somethingOrNothing = False
|
||||||
|
physicsComponentId = -1
|
||||||
|
|
||||||
|
# Begin custom attributes
|
||||||
|
serializedOrder = []
|
||||||
|
hasMissionOffer = False
|
||||||
|
|
||||||
|
class NiPoint3:
|
||||||
|
x = 0.0
|
||||||
|
y = 0.0
|
||||||
|
z = 0.0
|
||||||
|
|
||||||
|
class NiQuaternion:
|
||||||
|
w = 0.0
|
||||||
|
x = 0.0
|
||||||
|
y = 0.0
|
||||||
|
z = 0.0
|
||||||
|
|
||||||
|
class LoadObject:
|
||||||
|
objId = 0
|
||||||
|
owner = 0
|
||||||
|
lotToSpawn = 0
|
||||||
|
isLocalPlayer = False
|
||||||
|
hasDropEffect = False
|
||||||
|
bIsSmashable = False
|
||||||
|
dynamicPhysics = False
|
||||||
|
spawnPosition = NiPoint3()
|
||||||
|
spawnRotation = NiQuaternion()
|
||||||
|
scale = 0.0
|
||||||
|
legoBrickID = 0
|
||||||
|
legoColorID = 0
|
||||||
|
configData = {}
|
||||||
|
isHFPaletteObject = False
|
||||||
|
objType = 0
|
||||||
|
useSimplePhysics = False
|
||||||
|
bDelayedLoad = False
|
||||||
|
|
||||||
|
# Don't know the name yet of this
|
||||||
|
field8_0x20 = True
|
||||||
408
ComponentFactories.py
Normal file
408
ComponentFactories.py
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
import ComponentDefinitions as cd
|
||||||
|
|
||||||
|
def ApplyComponentWhitelist():
|
||||||
|
# Dont care to actually do this, just want the call for now.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ControllablePhysFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
if not loadObject.useSimplePhysics:
|
||||||
|
objectLoadState.components.append('CONTROLLABLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
loadObject.physicsComponentId = componentId
|
||||||
|
|
||||||
|
def RenderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if loadObject.lotToSpawn == 176:
|
||||||
|
return
|
||||||
|
gmlevel = loadObject.configData.get('gmlevel', 0)
|
||||||
|
if gmlevel > 0 and gmlevel < 6:
|
||||||
|
componentId = 9940 # Override the componentId of the render component to be 9940, the Mythran Render Component
|
||||||
|
renderDisabled = loadObject.configData.get('renderDisabled', False)
|
||||||
|
if renderDisabled:
|
||||||
|
return
|
||||||
|
if objectLoadState.createdGameObject.type == 'BlockingVolume':
|
||||||
|
return
|
||||||
|
rejectedLots = [5937, 5938, 9741, 9742, 9862, 9863]
|
||||||
|
if loadObject.lotToSpawn in rejectedLots:
|
||||||
|
return
|
||||||
|
if loadObject.lotToSpawn == 6368:
|
||||||
|
FxFactory(loadObject, objectLoadState, componentId)
|
||||||
|
return
|
||||||
|
FxFactory(loadObject, objectLoadState, componentId)
|
||||||
|
defaultWrapperAsset = ""
|
||||||
|
hasNifAsset = False
|
||||||
|
hasKfmAsset = False
|
||||||
|
allowRenderWrapping = False
|
||||||
|
nifName = loadObject.configData.get('nif_name', '')
|
||||||
|
if nifName == '':
|
||||||
|
print('TODO query cdc for this data in the Render component')
|
||||||
|
nifName = 'mesh/something.nif' # if empty get nifname as the render_asset column of the RenderComponent table from the database
|
||||||
|
if nifName[-1] == 'f':
|
||||||
|
hasNifAsset = True
|
||||||
|
elif nifName[-1] == 'm':
|
||||||
|
hasKfmAsset = True
|
||||||
|
if defaultWrapperAsset != '':
|
||||||
|
if defaultWrapperAsset[-1] == 'm':
|
||||||
|
allowRenderWrapping = not loadObject.configData.get('preventRenderWrapping', False)
|
||||||
|
if allowRenderWrapping or hasKfmAsset or (not defaultWrapperAsset == 'PrimitiveModels' and not hasNifAsset and not loadObject.configData.get('CreateNULLRender', False)):
|
||||||
|
objectLoadState.components.append('SKINNED_RENDER')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('RENDER')
|
||||||
|
|
||||||
|
def FxFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('FX')
|
||||||
|
|
||||||
|
def SimplePhysFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
objectLoadState.physicsComponentId = componentId
|
||||||
|
return
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
return
|
||||||
|
markedAsPhantom = loadObject.configData.get('markedAsPhantom', False)
|
||||||
|
if markedAsPhantom:
|
||||||
|
objectLoadState.components.append('PHANTOM_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def CharacterFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSOR')
|
||||||
|
objectLoadState.components.append('MOUNT_CONTROL')
|
||||||
|
objectLoadState.components.append('PET_CREATOR')
|
||||||
|
objectLoadState.components.append('LEVEL_PROGRESSION')
|
||||||
|
objectLoadState.components.append('PLAYER_FORCED_MOVEMENT')
|
||||||
|
objectLoadState.components.append('CHARACTER')
|
||||||
|
|
||||||
|
def ScriptFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int, add_pathfinding_control: bool):
|
||||||
|
custom_script_client = loadObject.configData.get('custom_script_client', '')
|
||||||
|
custom_script_server = loadObject.configData.get('custom_script_server', '')
|
||||||
|
if componentId == 0 and custom_script_client == '' and custom_script_server == '':
|
||||||
|
return
|
||||||
|
objectLoadState.components.append('SCRIPT')
|
||||||
|
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent and add_pathfinding_control:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
def BouncerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BOUNCER')
|
||||||
|
|
||||||
|
def DestroyableFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('STATUS_EFFECT')
|
||||||
|
objectLoadState.components.append('BUFF')
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
|
||||||
|
def SkillFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SKILL')
|
||||||
|
|
||||||
|
def SpawnerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SPAWNER')
|
||||||
|
# If game state is happy flower
|
||||||
|
spawntemplate = loadObject.configData.get('spawntemplate', '')
|
||||||
|
|
||||||
|
print('TODO query cdc for this data in the Spawner component')
|
||||||
|
render_asset = loadObject.configData.get('render_asset', 'test.nif') # Get this from RenderComponent table
|
||||||
|
render_id = loadObject.configData.get('render_id', '') # Get this from RenderComponent table
|
||||||
|
|
||||||
|
if render_asset[-1] == 'f':
|
||||||
|
objectLoadState.components.append('SKINNED_RENDER')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('RENDER')
|
||||||
|
|
||||||
|
def ItemFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ITEM')
|
||||||
|
|
||||||
|
def ModularBuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULAR_BUILD')
|
||||||
|
|
||||||
|
def BuildControllerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BUILD_CONTROLLER')
|
||||||
|
|
||||||
|
def VendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
objectLoadState.components.append('VENDOR')
|
||||||
|
|
||||||
|
def InventoryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('INVENTORY')
|
||||||
|
|
||||||
|
def ProjectilePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PROJECTILE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def ShootingGalleryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SHOOTING_GALLERY')
|
||||||
|
|
||||||
|
def RigibBodyPhantomPhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RIGID_BODY_PHANTOM_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def ChestFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHEST')
|
||||||
|
|
||||||
|
def CollectibleFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('COLLECTIBLE')
|
||||||
|
if not objectLoadState.hasDestroyable:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
|
||||||
|
def BlueprintFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BLUEPRINT')
|
||||||
|
|
||||||
|
def MovingPlatformFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MOVING_PLATFORM')
|
||||||
|
|
||||||
|
def PetFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
inInventory = loadObject.configData.get('inInventory', False)
|
||||||
|
if inInventory:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
objectLoadState.components.append('PET')
|
||||||
|
|
||||||
|
def PlatformBoundaryFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PLATFORM_BOUNDARY')
|
||||||
|
|
||||||
|
def ModuleFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULE')
|
||||||
|
|
||||||
|
def ArcadeFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ARCADE')
|
||||||
|
|
||||||
|
def HavokVehiclePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
use_simple_physics = loadObject.configData.get('use_simple_physics', False)
|
||||||
|
if use_simple_physics:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
else:
|
||||||
|
objectWorldState = loadObject.configData.get('objectWorldState', '')
|
||||||
|
if objectWorldState == 0 or objectWorldState != 2:
|
||||||
|
objectLoadState.components.append('HAVOK_VEHICLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def MovementAiFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MOVEMENT_AI')
|
||||||
|
|
||||||
|
def ExhibitFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Sorry aron, doesnt do anything :(
|
||||||
|
pass
|
||||||
|
|
||||||
|
def MinifigFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MINIFIG')
|
||||||
|
|
||||||
|
def PropertyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY')
|
||||||
|
|
||||||
|
def ModelBuilderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODEL_BUILDER')
|
||||||
|
|
||||||
|
def ScriptedActivityFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SCRIPTED_ACTIVITY')
|
||||||
|
|
||||||
|
def PhantomPhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PHANTOM_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def SpringPadFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SPRING_PAD')
|
||||||
|
|
||||||
|
def ModelFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
modelType = loadObject.configData.get('modelType', 0)
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not objectLoadState.hasPhysicsComponent:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
elif not objectLoadState.hasPhysicsComponent:
|
||||||
|
if modelType == 0:
|
||||||
|
objectLoadState.components.append('CONTROLLABLE_PHYSICS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('SIMPLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
if modelType != 0 and not objectLoadState.hasPathfindingComponent:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
hasPropertyObjectID = loadObject.configData.get('propertyObjectID', 0) != 0
|
||||||
|
inInventory = loadObject.configData.get('inInventory', False)
|
||||||
|
if hasPropertyObjectID and inInventory:
|
||||||
|
objectLoadState.components.append('MODEL_BEHAVIORS')
|
||||||
|
else:
|
||||||
|
objectLoadState.components.append('MUTABLE_MODEL_BEHAVIORS')
|
||||||
|
|
||||||
|
def PropertyEntranceFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_ENTRANCE')
|
||||||
|
|
||||||
|
def PropertyManagementFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_MANAGEMENT')
|
||||||
|
|
||||||
|
def VehiclePhysicsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('VEHICLE_PHYSICS')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def PhysicsSystemFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasModelbehaviors:
|
||||||
|
if not loadObject.hasDropEffect:
|
||||||
|
objectLoadState.components.append('PHYSICS_SYSTEM')
|
||||||
|
objectLoadState.hasPhysicsComponent = True
|
||||||
|
|
||||||
|
def RebuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('REBUILD')
|
||||||
|
if not objectLoadState.hasDestroyable:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
objectLoadState.hasDestroyable = True
|
||||||
|
loadObject.bIsSmashable = True
|
||||||
|
|
||||||
|
def BaseCombatAiFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int, add_pathfinding_control: bool):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if not objectLoadState.hasPathfindingComponent and add_pathfinding_control:
|
||||||
|
objectLoadState.components.append('PATHFINDING_CONTROL')
|
||||||
|
objectLoadState.hasPathfindingComponent = True
|
||||||
|
|
||||||
|
objectLoadState.components.append('BASE_COMBAT_AI')
|
||||||
|
|
||||||
|
def ProximityMonitorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
print('TODO query cdc for this data in prox mon')
|
||||||
|
# There must be a row for this component in the ProximityMonitorComponent table to get this component
|
||||||
|
LoadOnClient = loadObject.configData.get('LoadOnClient', False) # Get this from ProximityMonitorComponent table if you know there is a column for it
|
||||||
|
if LoadOnClient:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
def DonationVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
objectLoadState.components.append('DONATION_VENDOR')
|
||||||
|
|
||||||
|
def AchievmentVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
objectLoadState.components.append('ACHIEVEMENT_VENDOR')
|
||||||
|
|
||||||
|
def CraftingFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Game verson must be above 999 for this to work!
|
||||||
|
gameVersion = 1000
|
||||||
|
if gameVersion > 999:
|
||||||
|
objectLoadState.components.append('CRAFTING')
|
||||||
|
|
||||||
|
# Technically Possessable and Possessor are the exact same thing
|
||||||
|
def PossessableFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSABLE')
|
||||||
|
|
||||||
|
def PossessorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('POSSESSOR')
|
||||||
|
|
||||||
|
def PropertyPlaqueFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_PLAQUE')
|
||||||
|
|
||||||
|
def BuildBorderFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BUILD_BORDER')
|
||||||
|
|
||||||
|
def CullingPlaneFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CULLING_PLANE')
|
||||||
|
|
||||||
|
def GateRushFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('GATE_RUSH')
|
||||||
|
|
||||||
|
def RailActivatorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RAIL_ACTIVATOR')
|
||||||
|
|
||||||
|
def RollerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROLLER')
|
||||||
|
|
||||||
|
def PlayerForcedMovementFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PLAYER_FORCED_MOVEMENT')
|
||||||
|
|
||||||
|
def RacingSoundTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_SOUND_TRIGGER')
|
||||||
|
|
||||||
|
def RocketLaunchLupFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LAUNCH_LUP')
|
||||||
|
|
||||||
|
|
||||||
|
def ModuleAssemblyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MODULE_ASSEMBLY')
|
||||||
|
|
||||||
|
def ShowcaseModelHandlerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SHOWCASE_MODEL_HANDLER')
|
||||||
|
|
||||||
|
def GenericActivatorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('GENERIC_ACTIVATOR')
|
||||||
|
|
||||||
|
def PropertyVendorFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('PROPERTY_VENDOR')
|
||||||
|
|
||||||
|
def RocketLaunchFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LAUNCH')
|
||||||
|
|
||||||
|
def RocketLandingComponentFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ROCKET_LANDING_COMPONENT')
|
||||||
|
|
||||||
|
def RacingControlFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_CONTROL')
|
||||||
|
|
||||||
|
def FactionTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('FACTION_TRIGGER')
|
||||||
|
|
||||||
|
def MissionOfferFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('MISSION_OFFER')
|
||||||
|
objectLoadState.hasMissionOffer = True
|
||||||
|
|
||||||
|
def RacingStatsFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('RACING_STATS')
|
||||||
|
|
||||||
|
def LupExhibitFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('LUP_EXHIBIT')
|
||||||
|
|
||||||
|
def BBBFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('BBB')
|
||||||
|
|
||||||
|
def SoundTriggerFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_TRIGGER')
|
||||||
|
|
||||||
|
def SwitchFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SWITCH')
|
||||||
|
|
||||||
|
def ZoneControlFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('ZONE_CONTROL')
|
||||||
|
|
||||||
|
def ChanglingFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHANGELING')
|
||||||
|
|
||||||
|
def ChoiceBuildFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CHOICE_BUILD')
|
||||||
|
|
||||||
|
def PackageFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
# Literally returns nothing
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SoundRepeaterFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_REPEATER')
|
||||||
|
|
||||||
|
def SoundAmbient2DFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
if loadObject.isLocalPlayer:
|
||||||
|
objectLoadState.components.append('SOUND_AMBIENT_2D')
|
||||||
|
|
||||||
|
def SoundAmbient3DFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('SOUND_AMBIENT_3D')
|
||||||
|
|
||||||
|
def CustomBuildAssemblyFactory(loadObject: cd.LoadObject, objectLoadState: cd.ObjectLoadState, componentId: int):
|
||||||
|
objectLoadState.components.append('CUSTOM_BUILD_ASSEMBLY')
|
||||||
306
DoObjectPreLoad.py
Normal file
306
DoObjectPreLoad.py
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
import ComponentDefinitions as cd
|
||||||
|
import ComponentFactories as cf
|
||||||
|
|
||||||
|
# If we have any of these components, we need pathfinding control
|
||||||
|
def CheckIfNeedsPathfindingControl(components_to_load: dict):
|
||||||
|
add_pathfinding_control = cd.components['COMPONENT_TYPE_CONTROLLABLE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_PROJECTILE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS'] in components_to_load
|
||||||
|
add_pathfinding_control |= cd.components['COMPONENT_TYPE_VEHICLE_PHYSICS'] in components_to_load
|
||||||
|
return add_pathfinding_control
|
||||||
|
|
||||||
|
def DoObjectPreLoad(components_to_load: dict):
|
||||||
|
isHfActive = False
|
||||||
|
cf.ApplyComponentWhitelist()
|
||||||
|
objectLoadState = cd.ObjectLoadState()
|
||||||
|
loadObject = cd.LoadObject()
|
||||||
|
|
||||||
|
for componentType in cd.component_order_as_ints.keys():
|
||||||
|
try:
|
||||||
|
componentId = components_to_load[componentType]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
match cd.component_int_to_name[componentType]:
|
||||||
|
case 'COMPONENT_TYPE_CONTROLLABLE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.ControllablePhysFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RENDER':
|
||||||
|
cf.RenderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SIMPLE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.SimplePhysFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHARACTER':
|
||||||
|
cf.CharacterFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SCRIPT':
|
||||||
|
cf.ScriptFactory(loadObject, objectLoadState, componentId, CheckIfNeedsPathfindingControl(components_to_load))
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BOUNCER':
|
||||||
|
cf.BouncerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_DESTROYABLE':
|
||||||
|
cf.DestroyableFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SKILL':
|
||||||
|
cf.SkillFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SPAWNER':
|
||||||
|
cf.SpawnerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ITEM':
|
||||||
|
cf.ItemFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULAR_BUILD':
|
||||||
|
cf.ModularBuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BUILD_CONTROLLER':
|
||||||
|
cf.BuildControllerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_VENDOR':
|
||||||
|
cf.VendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_INVENTORY':
|
||||||
|
cf.InventoryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROJECTILE_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.ProjectilePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SHOOTING_GALLERY':
|
||||||
|
cf.ShootingGalleryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RIGID_BODY_PHANTOM_PHYSICS':
|
||||||
|
cf.RigibBodyPhantomPhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHEST':
|
||||||
|
cf.ChestFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_COLLECTIBLE':
|
||||||
|
cf.CollectibleFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BLUEPRINT':
|
||||||
|
cf.BlueprintFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MOVING_PLATFORM':
|
||||||
|
cf.MovingPlatformFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PET':
|
||||||
|
cf.PetFactory(loadObject, objectLoadState, componentId)
|
||||||
|
print('Deleting COMPONENT_TYPE_MODEL and COMPONENT_TYPE_ITEM due to COMPONENT_TYPE_PET being loaded')
|
||||||
|
toDel = cd.components['COMPONENT_TYPE_MODEL']
|
||||||
|
del components_to_load[toDel]
|
||||||
|
toDel = cd.components['COMPONENT_TYPE_ITEM']
|
||||||
|
del components_to_load[toDel]
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PLATFORM_BOUNDARY':
|
||||||
|
cf.PlatformBoundaryFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULE':
|
||||||
|
cf.ModuleFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ARCADE':
|
||||||
|
cf.ArcadeFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_HAVOK_VEHICLE_PHYSICS':
|
||||||
|
cf.HavokVehiclePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MOVEMENT_AI':
|
||||||
|
cf.MovementAiFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_EXHIBIT':
|
||||||
|
cf.ExhibitFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MINIFIG':
|
||||||
|
cf.MinifigFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY':
|
||||||
|
cf.PropertyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODEL_BUILDER':
|
||||||
|
cf.ModelBuilderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SCRIPTED_ACTIVITY':
|
||||||
|
cf.ScriptedActivityFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PHANTOM_PHYSICS':
|
||||||
|
if objectLoadState.hasDroppedLootComponent: continue
|
||||||
|
cf.PhantomPhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SPRING_PAD':
|
||||||
|
cf.SpringPadFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODEL':
|
||||||
|
cf.ModelFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_ENTRANCE':
|
||||||
|
cf.PropertyEntranceFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_MANAGEMENT':
|
||||||
|
cf.PropertyManagementFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_VEHICLE_PHYSICS':
|
||||||
|
cf.VehiclePhysicsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PHYSICS_SYSTEM':
|
||||||
|
cf.PhysicsSystemFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_REBUILD':
|
||||||
|
cf.RebuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SWITCH':
|
||||||
|
cf.SwitchFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ZONE_CONTROL':
|
||||||
|
cf.ZoneControlFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHANGELING':
|
||||||
|
cf.ChanglingFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CHOICE_BUILD':
|
||||||
|
cf.ChoiceBuildFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PACKAGE':
|
||||||
|
cf.PackageFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_REPEATER':
|
||||||
|
cf.SoundRepeaterFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_AMBIENT_2D':
|
||||||
|
cf.SoundAmbient2DFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_AMBIENT_3D':
|
||||||
|
cf.SoundAmbient3DFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CUSTOM_BUILD_ASSEMBLY':
|
||||||
|
cf.CustomBuildAssemblyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BASE_COMBAT_AI':
|
||||||
|
cf.BaseCombatAiFactory(loadObject, objectLoadState, componentId, CheckIfNeedsPathfindingControl(components_to_load))
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MODULE_ASSEMBLY':
|
||||||
|
cf.ModuleAssemblyFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SHOWCASE_MODEL_HANDLER':
|
||||||
|
cf.ShowcaseModelHandlerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_GENERIC_ACTIVATOR':
|
||||||
|
cf.GenericActivatorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_VENDOR':
|
||||||
|
cf.PropertyVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LAUNCH':
|
||||||
|
cf.RocketLaunchFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LANDING_COMPONENT':
|
||||||
|
cf.RocketLandingComponentFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_CONTROL':
|
||||||
|
cf.RacingControlFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_FACTION_TRIGGER':
|
||||||
|
cf.FactionTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_MISSION_OFFER':
|
||||||
|
cf.MissionOfferFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_STATS':
|
||||||
|
cf.RacingStatsFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_LUP_EXHIBIT':
|
||||||
|
cf.LupExhibitFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BBB':
|
||||||
|
cf.BBBFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_SOUND_TRIGGER':
|
||||||
|
cf.SoundTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROXIMITY_MONITOR':
|
||||||
|
cf.ProximityMonitorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RACING_SOUND_TRIGGER':
|
||||||
|
cf.RacingSoundTriggerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROCKET_LAUNCH_LUP':
|
||||||
|
cf.RocketLaunchLupFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_DONATION_VENDOR':
|
||||||
|
cf.DonationVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ACHIEVEMENT_VENDOR':
|
||||||
|
cf.AchievmentVendorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_GATE_RUSH':
|
||||||
|
cf.GateRushFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_RAIL_ACTIVATOR':
|
||||||
|
cf.RailActivatorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_ROLLER':
|
||||||
|
cf.RollerFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT':
|
||||||
|
cf.PlayerForcedMovementFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CRAFTING':
|
||||||
|
cf.CraftingFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_POSSESSABLE':
|
||||||
|
cf.PossessableFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_POSSESSOR':
|
||||||
|
cf.PossessorFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_PROPERTY_PLAQUE':
|
||||||
|
cf.PropertyPlaqueFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_BUILD_BORDER':
|
||||||
|
cf.BuildBorderFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
case 'COMPONENT_TYPE_CULLING_PLANE':
|
||||||
|
cf.CullingPlaneFactory(loadObject, objectLoadState, componentId)
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
print(f'Unknown component: {componentType}')
|
||||||
|
|
||||||
|
if not 'is_smashable' in loadObject.configData and loadObject.bIsSmashable:
|
||||||
|
loadObject.configData['is_smashable'] = True
|
||||||
|
|
||||||
|
is_smashable = loadObject.configData['is_smashable']
|
||||||
|
if is_smashable and not objectLoadState.hasDestroyable and loadObject.lotToSpawn != 176:
|
||||||
|
objectLoadState.components.append('DESTROYABLE')
|
||||||
|
|
||||||
|
if objectLoadState.hasMissionOffer and not objectLoadState.hasProximityMonitorComponent:
|
||||||
|
objectLoadState.components.append('PROXIMITY_MONITOR')
|
||||||
|
objectLoadState.hasProximityMonitorComponent = True
|
||||||
|
|
||||||
|
if loadObject.field8_0x20 and loadObject.owner != 0:
|
||||||
|
objectLoadState.components.append('OVERHEAD_ICON')
|
||||||
|
|
||||||
|
trigger_id = loadObject.configData.get('trigger_id', 0)
|
||||||
|
if trigger_id != 0:
|
||||||
|
objectLoadState.components.append('TRIGGER')
|
||||||
|
|
||||||
|
return objectLoadState
|
||||||
|
|
||||||
|
components_to_load = {}
|
||||||
|
|
||||||
|
# Testing code to load all components
|
||||||
|
for i in range(110):
|
||||||
|
components_to_load[i] = i
|
||||||
|
|
||||||
|
objectLoadState = DoObjectPreLoad(components_to_load)
|
||||||
|
|
||||||
|
# Convert the components to ints
|
||||||
|
components_to_int = []
|
||||||
|
for component in objectLoadState.components:
|
||||||
|
components_to_int.append([cd.components[f'COMPONENT_TYPE_{component}'], component])
|
||||||
|
|
||||||
|
# Print out the components in a more readable format
|
||||||
|
for comp in components_to_int:
|
||||||
|
print(comp[0], comp[1])
|
||||||
@@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j<number>` where number i
|
|||||||
### Notes
|
### Notes
|
||||||
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
||||||
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
||||||
* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023.
|
* If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
|
||||||
|
|
||||||
## Configuring your server
|
## Configuring your server
|
||||||
This server has a few steps that need to be taken to configure the server for your use case.
|
This server has a few steps that need to be taken to configure the server for your use case.
|
||||||
|
|||||||
BIN
__pycache__/ComponentDefinitions.cpython-310.pyc
Normal file
BIN
__pycache__/ComponentDefinitions.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ComponentFactories.cpython-310.pyc
Normal file
BIN
__pycache__/ComponentFactories.cpython-310.pyc
Normal file
Binary file not shown.
@@ -3,6 +3,7 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "PacketUtils.h"
|
#include "PacketUtils.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
@@ -75,11 +76,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(0);
|
bitStream.Write<uint8_t>(0);
|
||||||
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
||||||
bitStream.Write((uint16_t)friends.size());
|
bitStream.Write((uint16_t)friends.size());
|
||||||
@@ -412,21 +413,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
bitStream.Write<uint8_t>(8);
|
bitStream.Write<uint8_t>(8);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(senderName, 33, &bitStream);
|
bitStream.Write(LUWString(senderName));
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(otherName, 33, &bitStream);
|
bitStream.Write(LUWString(otherName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //teams?
|
bitStream.Write<uint8_t>(0); //teams?
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = otherMember->sysAddr;
|
SystemAddress sysAddr = otherMember->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -434,7 +435,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||||
LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet);
|
LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
|
||||||
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
||||||
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
||||||
|
|
||||||
@@ -451,21 +452,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the sender:
|
//To the sender:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //success
|
bitStream.Write<uint8_t>(0); //success
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonA->sysAddr;
|
SystemAddress sysAddr = goonA->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -474,21 +475,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the receiver:
|
//To the receiver:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonB->playerID);
|
bitStream.Write(goonB->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(3); //new whisper
|
bitStream.Write<uint8_t>(3); //new whisper
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonB->sysAddr;
|
SystemAddress sysAddr = goonB->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -709,13 +710,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -724,7 +725,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -751,7 +752,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -776,7 +777,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -793,7 +794,7 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -822,7 +823,7 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -848,7 +849,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -882,16 +883,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(friendData->playerID);
|
bitStream.Write(friendData->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
||||||
bitStream.Write<uint8_t>(notifyType);
|
bitStream.Write<uint8_t>(notifyType);
|
||||||
|
|
||||||
std::string playerName = playerData->playerName.c_str();
|
std::string playerName = playerData->playerName.c_str();
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
bitStream.Write(LUWString(playerName));
|
||||||
|
|
||||||
bitStream.Write(playerData->zoneID.GetMapID());
|
bitStream.Write(playerData->zoneID.GetMapID());
|
||||||
bitStream.Write(playerData->zoneID.GetInstanceID());
|
bitStream.Write(playerData->zoneID.GetInstanceID());
|
||||||
@@ -921,12 +922,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -937,16 +938,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen
|
|||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
||||||
bitStream.Write(responseCode);
|
bitStream.Write(responseCode);
|
||||||
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
||||||
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
// Then write the player name
|
// Then write the player name
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
// Then if this is an acceptance code, write the following extra info.
|
// Then if this is an acceptance code, write the following extra info.
|
||||||
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
@@ -962,13 +963,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers
|
|||||||
if (!receiver) return;
|
if (!receiver) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
PacketUtils::WritePacketWString(personToRemove, 33, &bitStream);
|
bitStream.Write(LUWString(personToRemove));
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace Game {
|
|||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -114,6 +115,8 @@ int main(int argc, char** argv) {
|
|||||||
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
||||||
|
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
||||||
|
|
||||||
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "PacketUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "ChatPackets.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
PlayerContainer::PlayerContainer() {
|
PlayerContainer::PlayerContainer() {
|
||||||
}
|
}
|
||||||
@@ -18,6 +20,10 @@ PlayerContainer::~PlayerContainer() {
|
|||||||
mPlayers.clear();
|
mPlayers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TeamData::TeamData() {
|
||||||
|
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerContainer::InsertPlayer(Packet* packet) {
|
void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
PlayerData* data = new PlayerData();
|
PlayerData* data = new PlayerData();
|
||||||
@@ -146,7 +152,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -207,6 +213,14 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||||
|
if (team->memberIDs.size() >= 4){
|
||||||
|
Game::logger->Log("PlayerContainer", "Tried to add player to team that already had 4 players");
|
||||||
|
auto* player = GetPlayerData(playerID);
|
||||||
|
if (!player) return;
|
||||||
|
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
||||||
|
|
||||||
if (index != team->memberIDs.end()) return;
|
if (index != team->memberIDs.end()) return;
|
||||||
@@ -345,7 +359,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct PlayerData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TeamData {
|
struct TeamData {
|
||||||
|
TeamData();
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
std::vector<LWOOBJID> memberIDs{};
|
std::vector<LWOOBJID> memberIDs{};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ set(DCOMMON_SOURCES
|
|||||||
"NiPoint3.cpp"
|
"NiPoint3.cpp"
|
||||||
"NiQuaternion.cpp"
|
"NiQuaternion.cpp"
|
||||||
"SHA512.cpp"
|
"SHA512.cpp"
|
||||||
"Type.cpp"
|
"Demangler.cpp"
|
||||||
"ZCompression.cpp"
|
"ZCompression.cpp"
|
||||||
"BrickByBrickFix.cpp"
|
"BrickByBrickFix.cpp"
|
||||||
"BinaryPathFinder.cpp"
|
"BinaryPathFinder.cpp"
|
||||||
|
|||||||
29
dCommon/Demangler.cpp
Normal file
29
dCommon/Demangler.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "Demangler.h"
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
std::string Demangler::Demangle(const char* name) {
|
||||||
|
// some arbitrary value to eliminate the compiler warning
|
||||||
|
// -4 is not a valid return value for __cxa_demangle so we'll use that.
|
||||||
|
int status = -4;
|
||||||
|
|
||||||
|
// __cxa_demangle requires that we free the returned char*
|
||||||
|
std::unique_ptr<char, void (*)(void*)> res{
|
||||||
|
abi::__cxa_demangle(name, NULL, NULL, &status),
|
||||||
|
std::free
|
||||||
|
};
|
||||||
|
|
||||||
|
return (status == 0) ? res.get() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // __GNUG__
|
||||||
|
|
||||||
|
// does nothing if not g++
|
||||||
|
std::string Demangler::Demangle(const char* name) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __GNUG__
|
||||||
9
dCommon/Demangler.h
Normal file
9
dCommon/Demangler.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Demangler {
|
||||||
|
// Given a char* containing a mangled name, return a std::string containing the demangled name.
|
||||||
|
// If the function fails for any reason, it returns an empty string.
|
||||||
|
std::string Demangle(const char* name);
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Type.h"
|
#include "Demangler.h"
|
||||||
|
|
||||||
void GenerateDump() {
|
void GenerateDump() {
|
||||||
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
||||||
@@ -122,41 +122,43 @@ void CatchUnhandled(int sig) {
|
|||||||
if (Diagnostics::GetProduceMemoryDump()) {
|
if (Diagnostics::GetProduceMemoryDump()) {
|
||||||
GenerateDump();
|
GenerateDump();
|
||||||
}
|
}
|
||||||
|
constexpr uint8_t MaxStackTrace = 32;
|
||||||
void* array[10];
|
void* array[MaxStackTrace];
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
// get void*'s for all entries on the stack
|
// get void*'s for all entries on the stack
|
||||||
size = backtrace(array, 10);
|
size = backtrace(array, MaxStackTrace);
|
||||||
|
|
||||||
#if defined(__GNUG__) and defined(__dynamic)
|
# if defined(__GNUG__)
|
||||||
|
|
||||||
// Loop through the returned addresses, and get the symbols to be demangled
|
// Loop through the returned addresses, and get the symbols to be demangled
|
||||||
char** strings = backtrace_symbols(array, size);
|
char** strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
// Print the stack trace
|
// Print the stack trace
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name
|
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]'
|
||||||
|
// and extract '_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress' from it to be demangled into a proper name
|
||||||
std::string functionName = strings[i];
|
std::string functionName = strings[i];
|
||||||
std::string::size_type start = functionName.find('(');
|
std::string::size_type start = functionName.find('(');
|
||||||
std::string::size_type end = functionName.find('+');
|
std::string::size_type end = functionName.find('+');
|
||||||
if (start != std::string::npos && end != std::string::npos) {
|
if (start != std::string::npos && end != std::string::npos) {
|
||||||
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
||||||
|
|
||||||
demangled = demangle(functionName.c_str());
|
demangled = Demangler::Demangle(demangled.c_str());
|
||||||
|
|
||||||
if (demangled.empty()) {
|
// If the demangled string is not empty, then we can replace the mangled string with the demangled one
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str());
|
if (!demangled.empty()) {
|
||||||
} else {
|
demangled.push_back('(');
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
demangled += functionName.substr(end);
|
||||||
|
functionName = demangled;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
#else
|
# else // defined(__GNUG__)
|
||||||
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
||||||
#endif
|
# endif // defined(__GNUG__)
|
||||||
|
|
||||||
FILE* file = fopen(fileName.c_str(), "w+");
|
FILE* file = fopen(fileName.c_str(), "w+");
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
@@ -166,7 +168,7 @@ void CatchUnhandled(int sig) {
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else // __include_backtrace__
|
||||||
|
|
||||||
struct backtrace_state* state = backtrace_create_state(
|
struct backtrace_state* state = backtrace_create_state(
|
||||||
Diagnostics::GetProcessFileName().c_str(),
|
Diagnostics::GetProcessFileName().c_str(),
|
||||||
@@ -177,7 +179,7 @@ void CatchUnhandled(int sig) {
|
|||||||
struct bt_ctx ctx = { state, 0 };
|
struct bt_ctx ctx = { state, 0 };
|
||||||
Bt(state);
|
Bt(state);
|
||||||
|
|
||||||
#endif
|
#endif // __include_backtrace__
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ namespace GeneralUtils {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T Parse(const char* value);
|
T Parse(const char* value);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool Parse(const char* value) {
|
||||||
|
return std::stoi(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int32_t Parse(const char* value) {
|
inline int32_t Parse(const char* value) {
|
||||||
return std::stoi(value);
|
return std::stoi(value);
|
||||||
|
|||||||
@@ -61,35 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
case LDF_TYPE_S32: {
|
||||||
try {
|
int32_t data;
|
||||||
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<int32_t>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<int32_t>(key, data);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_FLOAT: {
|
case LDF_TYPE_FLOAT: {
|
||||||
try {
|
float data;
|
||||||
float data = strtof(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<float>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<float>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_DOUBLE: {
|
case LDF_TYPE_DOUBLE: {
|
||||||
try {
|
double data;
|
||||||
double data = strtod(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<double>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<double>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,9 +100,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = 0;
|
data = 0;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<uint32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -122,9 +118,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<bool>(strtol(ldfTypeAndValue.second.data(), &storage, 10));
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -135,24 +129,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
case LDF_TYPE_U64: {
|
||||||
try {
|
uint64_t data;
|
||||||
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<uint64_t>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<uint64_t>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_OBJID: {
|
case LDF_TYPE_OBJID: {
|
||||||
try {
|
LWOOBJID data;
|
||||||
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<LWOOBJID>(key, data);
|
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
returnValue = new LDFData<LWOOBJID>(key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,10 +129,19 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const {
|
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
||||||
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
this->x += point.x;
|
||||||
|
this->y += point.y;
|
||||||
|
this->z += point.z;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NiPoint3& NiPoint3::operator*=(const float scalar) {
|
||||||
|
this->x *= scalar;
|
||||||
|
this->y *= scalar;
|
||||||
|
this->z *= scalar;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ public:
|
|||||||
NiPoint3 operator+(const NiPoint3& point) const;
|
NiPoint3 operator+(const NiPoint3& point) const;
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3 operator+=(const NiPoint3& point) const;
|
NiPoint3& operator+=(const NiPoint3& point);
|
||||||
|
|
||||||
|
NiPoint3& operator*=(const float scalar);
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 operator-(const NiPoint3& point) const;
|
NiPoint3 operator-(const NiPoint3& point) const;
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#include "Type.h"
|
|
||||||
#ifdef __GNUG__
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <memory>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
std::string demangle(const char* name) {
|
|
||||||
|
|
||||||
int status = -4; // some arbitrary value to eliminate the compiler warning
|
|
||||||
|
|
||||||
// enable c++11 by passing the flag -std=c++11 to g++
|
|
||||||
std::unique_ptr<char, void(*)(void*)> res{
|
|
||||||
abi::__cxa_demangle(name, NULL, NULL, &status),
|
|
||||||
std::free
|
|
||||||
};
|
|
||||||
|
|
||||||
return (status == 0) ? res.get() : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// does nothing if not g++
|
|
||||||
std::string demangle(const char* name) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
std::string demangle(const char* name);
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
std::string type(const T& t) {
|
|
||||||
|
|
||||||
return demangle(typeid(t).name());
|
|
||||||
}
|
|
||||||
@@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
delete m_Base;
|
free(m_Base);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
|||||||
#define CBITSTREAM RakNet::BitStream bitStream;
|
#define CBITSTREAM RakNet::BitStream bitStream;
|
||||||
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
||||||
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
||||||
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
TRADE,
|
TRADE,
|
||||||
USER_CONTROL,
|
USER_CONTROL,
|
||||||
IGNORE_LIST,
|
IGNORE_LIST,
|
||||||
ROCKET_LAUNCH_LUP,
|
MULTI_ZONE_ENTRANCE,
|
||||||
BUFF_REAL, // the real buff component, should just be name BUFF
|
BUFF_REAL, // the real buff component, should just be name BUFF
|
||||||
INTERACTION_MANAGER,
|
INTERACTION_MANAGER,
|
||||||
DONATION_VENDOR,
|
DONATION_VENDOR,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ CDClientManager::CDClientManager() {
|
|||||||
CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
|
CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
|
||||||
CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
|
CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
|
||||||
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDComponentsRegistryTable::Instance().LoadValuesFromDatabase();
|
CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
|
||||||
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
||||||
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
||||||
@@ -65,8 +65,8 @@ CDClientManager::CDClientManager() {
|
|||||||
CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
|
CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDItemSetsTable::Instance().LoadValuesFromDatabase();
|
CDItemSetsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
|
CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
|
||||||
CDLootMatrixTable::Instance().LoadValuesFromDatabase();
|
CDCLIENT_DONT_CACHE_TABLE(CDLootMatrixTable::Instance().LoadValuesFromDatabase());
|
||||||
CDLootTableTable::Instance().LoadValuesFromDatabase();
|
CDCLIENT_DONT_CACHE_TABLE(CDLootTableTable::Instance().LoadValuesFromDatabase());
|
||||||
CDMissionEmailTable::Instance().LoadValuesFromDatabase();
|
CDMissionEmailTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
|
CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDMissionTasksTable::Instance().LoadValuesFromDatabase();
|
CDMissionTasksTable::Instance().LoadValuesFromDatabase();
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
#include "CDBehaviorParameterTable.h"
|
#include "CDBehaviorParameterTable.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
|
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
|
||||||
|
uint64_t key = behaviorID;
|
||||||
|
key <<= 31U;
|
||||||
|
key |= parameterID;
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
||||||
uint32_t uniqueParameterId = 0;
|
|
||||||
uint64_t hash = 0;
|
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDBehaviorParameter entry;
|
uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
|
||||||
entry.behaviorID = tableData.getIntField("behaviorID", -1);
|
|
||||||
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
||||||
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
||||||
|
uint32_t parameterId;
|
||||||
if (parameter != m_ParametersList.end()) {
|
if (parameter != m_ParametersList.end()) {
|
||||||
entry.parameterID = parameter;
|
parameterId = parameter->second;
|
||||||
} else {
|
} else {
|
||||||
entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first;
|
parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
|
||||||
uniqueParameterId++;
|
|
||||||
}
|
}
|
||||||
hash = entry.behaviorID;
|
uint64_t hash = GetKey(behaviorID, parameterId);
|
||||||
hash = (hash << 31U) | entry.parameterID->second;
|
float value = tableData.getFloatField("value", -1.0f);
|
||||||
entry.value = tableData.getFloatField("value", -1.0f);
|
|
||||||
|
|
||||||
m_Entries.insert(std::make_pair(hash, entry));
|
m_Entries.insert(std::make_pair(hash, value));
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
@@ -30,25 +34,21 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
|||||||
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
||||||
auto parameterID = this->m_ParametersList.find(name);
|
auto parameterID = this->m_ParametersList.find(name);
|
||||||
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
||||||
|
auto hash = GetKey(behaviorID, parameterID->second);
|
||||||
uint64_t hash = behaviorID;
|
|
||||||
|
|
||||||
hash = (hash << 31U) | parameterID->second;
|
|
||||||
|
|
||||||
// Search for specific parameter
|
// Search for specific parameter
|
||||||
const auto& it = m_Entries.find(hash);
|
auto it = m_Entries.find(hash);
|
||||||
return it != m_Entries.end() ? it->second.value : defaultValue;
|
return it != m_Entries.end() ? it->second : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
||||||
uint64_t hashBase = behaviorID;
|
uint64_t hashBase = behaviorID;
|
||||||
std::map<std::string, float> returnInfo;
|
std::map<std::string, float> returnInfo;
|
||||||
uint64_t hash;
|
for (auto& [parameterString, parameterId] : m_ParametersList) {
|
||||||
for (auto& parameterCandidate : m_ParametersList) {
|
uint64_t hash = GetKey(hashBase, parameterId);
|
||||||
hash = (hashBase << 31U) | parameterCandidate.second;
|
|
||||||
auto infoCandidate = m_Entries.find(hash);
|
auto infoCandidate = m_Entries.find(hash);
|
||||||
if (infoCandidate != m_Entries.end()) {
|
if (infoCandidate != m_Entries.end()) {
|
||||||
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value));
|
returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnInfo;
|
return returnInfo;
|
||||||
|
|||||||
@@ -5,15 +5,11 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
struct CDBehaviorParameter {
|
|
||||||
unsigned int behaviorID; //!< The Behavior ID
|
|
||||||
std::unordered_map<std::string, uint32_t>::iterator parameterID; //!< The Parameter ID
|
|
||||||
float value; //!< The value of the behavior template
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint64_t, CDBehaviorParameter> m_Entries;
|
typedef uint64_t BehaviorParameterHash;
|
||||||
|
typedef float BehaviorParameterValue;
|
||||||
|
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
|
||||||
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
|||||||
entry.component_id = tableData.getIntField("component_id", -1);
|
entry.component_id = tableData.getIntField("component_id", -1);
|
||||||
|
|
||||||
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
||||||
|
this->mappedEntries.insert_or_assign(entry.id, 0);
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
@@ -19,19 +20,18 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
||||||
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
auto exists = mappedEntries.find(id);
|
||||||
|
if (exists != mappedEntries.end()) {
|
||||||
if (iter == this->mappedEntries.end()) {
|
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
return defaultValue;
|
return iter == mappedEntries.end() ? defaultValue : iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return iter->second;
|
// Now get the data. Get all components of this entity so we dont do a query for each component
|
||||||
// Now get the data
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ? AND component_type = ?;");
|
|
||||||
query.bind(1, static_cast<int32_t>(id));
|
query.bind(1, static_cast<int32_t>(id));
|
||||||
query.bind(2, static_cast<int32_t>(componentType));
|
|
||||||
|
|
||||||
auto tableData = query.execQuery();
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDComponentsRegistry entry;
|
CDComponentsRegistry entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
@@ -43,7 +43,9 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent
|
|||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
mappedEntries.insert_or_assign(id, 0);
|
||||||
|
|
||||||
|
auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
|
|
||||||
return iter == this->mappedEntries.end() ? defaultValue : iter->second;
|
return iter == this->mappedEntries.end() ? defaultValue : iter->second;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct CDComponentsRegistry {
|
|||||||
|
|
||||||
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
||||||
private:
|
private:
|
||||||
std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
#include "CDLootMatrixTable.h"
|
#include "CDLootMatrixTable.h"
|
||||||
|
|
||||||
|
CDLootMatrix CDLootMatrixTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
|
CDLootMatrix entry{};
|
||||||
|
if (tableData.eof()) return entry;
|
||||||
|
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
||||||
|
entry.percent = tableData.getFloatField("percent", -1.0f);
|
||||||
|
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
||||||
|
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
||||||
|
entry.flagID = tableData.getIntField("flagID", -1);
|
||||||
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
void CDLootMatrixTable::LoadValuesFromDatabase() {
|
void CDLootMatrixTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
@@ -11,8 +24,6 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -20,33 +31,28 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootMatrix entry;
|
CDLootMatrix entry;
|
||||||
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
|
||||||
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
|
||||||
entry.percent = tableData.getFloatField("percent", -1.0f);
|
|
||||||
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
|
||||||
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
entry.flagID = tableData.getIntField("flagID", -1);
|
|
||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->entries[lootMatrixIndex].push_back(ReadRow(tableData));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
|
||||||
|
auto itr = this->entries.find(matrixId);
|
||||||
|
if (itr != this->entries.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;");
|
||||||
|
query.bind(1, static_cast<int32_t>(matrixId));
|
||||||
|
|
||||||
|
auto tableData = query.execQuery();
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
this->entries[matrixId].push_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
return this->entries[matrixId];
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CDLootMatrix> CDLootMatrixTable::Query(std::function<bool(CDLootMatrix)> predicate) {
|
|
||||||
|
|
||||||
std::vector<CDLootMatrix> data = cpplinq::from(this->entries)
|
|
||||||
>> cpplinq::where(predicate)
|
|
||||||
>> cpplinq::to_vector();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries() const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,26 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDLootMatrix {
|
struct CDLootMatrix {
|
||||||
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
|
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
||||||
float percent; //!< The percent that this matrix is used?
|
float percent; //!< The percent that this matrix is used?
|
||||||
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
||||||
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
||||||
unsigned int id; //!< The ID of the Loot Matrix
|
|
||||||
unsigned int flagID; //!< ???
|
unsigned int flagID; //!< ???
|
||||||
UNUSED(std::string gate_version); //!< The Gate Version
|
UNUSED(std::string gate_version); //!< The Gate Version
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
typedef uint32_t LootMatrixIndex;
|
||||||
private:
|
typedef std::vector<CDLootMatrix> LootMatrixEntries;
|
||||||
std::vector<CDLootMatrix> entries;
|
|
||||||
|
|
||||||
|
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
|
|
||||||
|
|
||||||
const std::vector<CDLootMatrix>& GetEntries() const;
|
// Gets a matrix by ID or inserts a blank one if none existed.
|
||||||
|
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
|
||||||
|
private:
|
||||||
|
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,42 @@
|
|||||||
#include "CDLootTableTable.h"
|
#include "CDLootTableTable.h"
|
||||||
|
#include "CDClientManager.h"
|
||||||
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "CDItemComponentTable.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
// Sort the tables by their rarity so the highest rarity items are first.
|
||||||
|
void SortTable(LootTableEntries& table) {
|
||||||
|
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||||
|
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
|
||||||
|
// We modify the table in place so the outer loop keeps track of what is sorted
|
||||||
|
// and the inner loop finds the highest rarity item and swaps it with the current position
|
||||||
|
// of the outer loop.
|
||||||
|
for (auto oldItrOuter = table.begin(); oldItrOuter != table.end(); oldItrOuter++) {
|
||||||
|
auto lootToInsert = oldItrOuter;
|
||||||
|
// Its fine if this starts at 0, even if this doesnt match lootToInsert as the actual highest will
|
||||||
|
// either be found and overwrite these values, or the original is somehow zero and is still the highest rarity.
|
||||||
|
uint32_t highestLootRarity = 0;
|
||||||
|
for (auto oldItrInner = oldItrOuter; oldItrInner != table.end(); oldItrInner++) {
|
||||||
|
uint32_t itemComponentId = componentsRegistryTable->GetByIDAndType(oldItrInner->itemid, eReplicaComponentType::ITEM);
|
||||||
|
uint32_t rarity = itemComponentTable->GetItemComponentByID(itemComponentId).rarity;
|
||||||
|
if (rarity > highestLootRarity) {
|
||||||
|
highestLootRarity = rarity;
|
||||||
|
lootToInsert = oldItrInner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Game::logger->LogDebug("CDLootTableTable", "highest rarity %i item id %i", highestLootRarity, lootToInsert->itemid);
|
||||||
|
std::swap(*oldItrOuter, *lootToInsert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CDLootTable CDLootTableTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
|
CDLootTable entry{};
|
||||||
|
if (tableData.eof()) return entry;
|
||||||
|
entry.itemid = tableData.getIntField("itemid", -1);
|
||||||
|
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
||||||
|
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
void CDLootTableTable::LoadValuesFromDatabase() {
|
void CDLootTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
@@ -11,8 +49,6 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -20,32 +56,32 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootTable entry;
|
CDLootTable entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
entry.itemid = tableData.getIntField("itemid", -1);
|
|
||||||
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
|
||||||
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->entries[lootTableIndex].push_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
for (auto& [id, table] : this->entries) {
|
||||||
tableData.finalize();
|
SortTable(table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
|
||||||
std::vector<CDLootTable> CDLootTableTable::Query(std::function<bool(CDLootTable)> predicate) {
|
auto itr = this->entries.find(tableId);
|
||||||
|
if (itr != this->entries.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CDLootTable> data = cpplinq::from(this->entries)
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;");
|
||||||
>> cpplinq::where(predicate)
|
query.bind(1, static_cast<int32_t>(tableId));
|
||||||
>> cpplinq::to_vector();
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
return data;
|
while (!tableData.eof()) {
|
||||||
|
CDLootTable entry;
|
||||||
|
this->entries[tableId].push_back(ReadRow(tableData));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
SortTable(this->entries[tableId]);
|
||||||
|
|
||||||
|
return this->entries[tableId];
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
|
||||||
const std::vector<CDLootTable>& CDLootTableTable::GetEntries() const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,21 @@
|
|||||||
struct CDLootTable {
|
struct CDLootTable {
|
||||||
unsigned int itemid; //!< The LOT of the item
|
unsigned int itemid; //!< The LOT of the item
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
unsigned int id; //!< The ID
|
|
||||||
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
||||||
unsigned int sortPriority; //!< The sorting priority
|
unsigned int sortPriority; //!< The sorting priority
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint32_t LootTableIndex;
|
||||||
|
typedef std::vector<CDLootTable> LootTableEntries;
|
||||||
|
|
||||||
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
||||||
private:
|
private:
|
||||||
std::vector<CDLootTable> entries;
|
CDLootTable ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootTableIndex, LootTableEntries> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate);
|
const LootTableEntries& GetTable(uint32_t tableId);
|
||||||
|
|
||||||
const std::vector<CDLootTable>& GetEntries() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,34 @@
|
|||||||
#include "CDRarityTableTable.h"
|
#include "CDRarityTableTable.h"
|
||||||
|
|
||||||
void CDRarityTableTable::LoadValuesFromDatabase() {
|
void CDRarityTableTable::LoadValuesFromDatabase() {
|
||||||
// Now get the data
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RarityTable");
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
CDRarityTable entry;
|
|
||||||
uint32_t id = tableData.getIntField("id", -1);
|
|
||||||
entry.randmax = tableData.getFloatField("randmax", -1);
|
|
||||||
entry.rarity = tableData.getIntField("rarity", -1);
|
|
||||||
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
|
||||||
|
|
||||||
this->entries.insert_or_assign(id, entry);
|
// First, get the size of the table
|
||||||
tableData.nextRow();
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM RarityTable");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableSize.finalize();
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
this->entries.reserve(size);
|
||||||
|
|
||||||
|
// Now get the data
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RarityTable order by randmax desc;");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
uint32_t rarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
||||||
|
|
||||||
|
CDRarityTable entry;
|
||||||
|
entry.randmax = tableData.getFloatField("randmax", -1);
|
||||||
|
entry.rarity = tableData.getIntField("rarity", -1);
|
||||||
|
entries[rarityTableIndex].push_back(entry);
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
const std::vector<CDRarityTable>& CDRarityTableTable::GetRarityTable(uint32_t id) {
|
||||||
const std::optional<CDRarityTable> CDRarityTableTable::Get(uint32_t id) {
|
return entries[id];
|
||||||
auto it = this->entries.find(id);
|
|
||||||
return it != this->entries.end() ? std::make_optional(it->second) : std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,35 +4,20 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDRarityTable {
|
struct CDRarityTable {
|
||||||
unsigned int id;
|
|
||||||
float randmax;
|
float randmax;
|
||||||
unsigned int rarity;
|
unsigned int rarity;
|
||||||
unsigned int RarityTableIndex;
|
|
||||||
|
|
||||||
friend bool operator> (const CDRarityTable& c1, const CDRarityTable& c2) {
|
|
||||||
return c1.rarity > c2.rarity;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator>= (const CDRarityTable& c1, const CDRarityTable& c2) {
|
|
||||||
return c1.rarity >= c2.rarity;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator< (const CDRarityTable& c1, const CDRarityTable& c2) {
|
|
||||||
return c1.rarity < c2.rarity;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator<= (const CDRarityTable& c1, const CDRarityTable& c2) {
|
|
||||||
return c1.rarity <= c2.rarity;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<CDRarityTable> RarityTable;
|
||||||
|
|
||||||
class CDRarityTableTable : public CDTable<CDRarityTableTable> {
|
class CDRarityTableTable : public CDTable<CDRarityTableTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, CDRarityTable> entries;
|
typedef uint32_t RarityTableIndex;
|
||||||
|
std::unordered_map<RarityTableIndex, std::vector<CDRarityTable>> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
|
||||||
const std::optional<CDRarityTable> Get(uint32_t predicate);
|
const std::vector<CDRarityTable>& GetRarityTable(uint32_t predicate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
#include "CDRebuildComponentTable.h"
|
#include "CDRebuildComponentTable.h"
|
||||||
|
|
||||||
void CDRebuildComponentTable::LoadValuesFromDatabase() {
|
void CDRebuildComponentTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM RebuildComponent");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
this->entries.reserve(size);
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RebuildComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RebuildComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDRebuildComponent entry;
|
CDRebuildComponent entry;
|
||||||
uint32_t id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.reset_time = tableData.getFloatField("reset_time", -1.0f);
|
entry.reset_time = tableData.getFloatField("reset_time", -1.0f);
|
||||||
entry.complete_time = tableData.getFloatField("complete_time", -1.0f);
|
entry.complete_time = tableData.getFloatField("complete_time", -1.0f);
|
||||||
entry.take_imagination = tableData.getIntField("take_imagination", -1);
|
entry.take_imagination = tableData.getIntField("take_imagination", -1);
|
||||||
@@ -16,12 +31,23 @@ void CDRebuildComponentTable::LoadValuesFromDatabase() {
|
|||||||
entry.post_imagination_cost = tableData.getIntField("post_imagination_cost", -1);
|
entry.post_imagination_cost = tableData.getIntField("post_imagination_cost", -1);
|
||||||
entry.time_before_smash = tableData.getFloatField("time_before_smash", -1.0f);
|
entry.time_before_smash = tableData.getFloatField("time_before_smash", -1.0f);
|
||||||
|
|
||||||
this->entries.insert_or_assign(id, entry);
|
this->entries.push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<CDRebuildComponent> CDRebuildComponentTable::Get(uint32_t componentId) {
|
std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<bool(CDRebuildComponent)> predicate) {
|
||||||
auto it = this->entries.find(componentId);
|
|
||||||
return it != this->entries.end() ? std::make_optional(it->second) : std::nullopt;
|
std::vector<CDRebuildComponent> data = cpplinq::from(this->entries)
|
||||||
|
>> cpplinq::where(predicate)
|
||||||
|
>> cpplinq::to_vector();
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<CDRebuildComponent>& CDRebuildComponentTable::GetEntries() const {
|
||||||
|
return this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDRebuildComponent {
|
struct CDRebuildComponent {
|
||||||
|
unsigned int id; //!< The component Id
|
||||||
float reset_time; //!< The reset time
|
float reset_time; //!< The reset time
|
||||||
float complete_time; //!< The complete time
|
float complete_time; //!< The complete time
|
||||||
unsigned int take_imagination; //!< The amount of imagination it costs
|
unsigned int take_imagination; //!< The amount of imagination it costs
|
||||||
@@ -17,11 +18,13 @@ struct CDRebuildComponent {
|
|||||||
|
|
||||||
class CDRebuildComponentTable : public CDTable<CDRebuildComponentTable> {
|
class CDRebuildComponentTable : public CDTable<CDRebuildComponentTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, CDRebuildComponent> entries;
|
std::vector<CDRebuildComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
const std::optional<CDRebuildComponent> Get(uint32_t componentId);
|
std::vector<CDRebuildComponent> Query(std::function<bool(CDRebuildComponent)> predicate);
|
||||||
|
|
||||||
|
const std::vector<CDRebuildComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ void CDRewardsTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDRewards entry;
|
CDRewards entry;
|
||||||
uint32_t id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.levelID = tableData.getIntField("LevelID", -1);
|
entry.levelID = tableData.getIntField("LevelID", -1);
|
||||||
entry.missionID = tableData.getIntField("MissionID", -1);
|
entry.missionID = tableData.getIntField("MissionID", -1);
|
||||||
entry.rewardType = tableData.getIntField("RewardType", -1);
|
entry.rewardType = tableData.getIntField("RewardType", -1);
|
||||||
entry.value = tableData.getIntField("value", -1);
|
entry.value = tableData.getIntField("value", -1);
|
||||||
entry.count = tableData.getIntField("count", -1);
|
entry.count = tableData.getIntField("count", -1);
|
||||||
|
|
||||||
m_entries.push_back(entry);
|
m_entries.insert(std::make_pair(entry.id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ void CDRewardsTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDRewards> CDRewardsTable::GetByLevelID(uint32_t levelID) {
|
std::vector<CDRewards> CDRewardsTable::GetByLevelID(uint32_t levelID) {
|
||||||
std::vector<CDRewards> result;
|
std::vector<CDRewards> result{};
|
||||||
for (const auto& levelData : m_entries) {
|
for (const auto& e : m_entries) {
|
||||||
if (levelData.levelID == levelID) result.push_back(levelData);
|
if (e.second.levelID == levelID) result.push_back(e.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct CDRewards {
|
struct CDRewards {
|
||||||
|
int32_t id;
|
||||||
int32_t levelID;
|
int32_t levelID;
|
||||||
int32_t missionID;
|
int32_t missionID;
|
||||||
int32_t rewardType;
|
int32_t rewardType;
|
||||||
@@ -13,7 +14,10 @@ struct CDRewards {
|
|||||||
class CDRewardsTable : public CDTable<CDRewardsTable> {
|
class CDRewardsTable : public CDTable<CDRewardsTable> {
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
|
static const std::string GetTableName() { return "Rewards"; };
|
||||||
std::vector<CDRewards> GetByLevelID(uint32_t levelID);
|
std::vector<CDRewards> GetByLevelID(uint32_t levelID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<CDRewards> m_entries;
|
std::map<uint32_t, CDRewards> m_entries;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,39 @@
|
|||||||
#include "CDScriptComponentTable.h"
|
#include "CDScriptComponentTable.h"
|
||||||
|
|
||||||
void CDScriptComponentTable::LoadValuesFromDatabase() {
|
void CDScriptComponentTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ScriptComponent");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ScriptComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ScriptComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDScriptComponent entry;
|
CDScriptComponent entry;
|
||||||
uint32_t id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.script_name = tableData.getStringField("script_name", "");
|
entry.script_name = tableData.getStringField("script_name", "");
|
||||||
entry.client_script_name = tableData.getStringField("client_script_name", "");
|
entry.client_script_name = tableData.getStringField("client_script_name", "");
|
||||||
|
|
||||||
this->entries.insert_or_assign(id, entry);
|
this->entries.insert(std::make_pair(entry.id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<CDScriptComponent> CDScriptComponentTable::GetByID(unsigned int id) {
|
const CDScriptComponent& CDScriptComponentTable::GetByID(unsigned int id) {
|
||||||
auto it = this->entries.find(id);
|
std::map<unsigned int, CDScriptComponent>::iterator it = this->entries.find(id);
|
||||||
return (it != this->entries.end()) ? std::make_optional<CDScriptComponent>(it->second) : std::nullopt;
|
if (it != this->entries.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_ToReturnWhenNoneFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,19 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDScriptComponent {
|
struct CDScriptComponent {
|
||||||
std::string script_name; //!< The script name
|
unsigned int id; //!< The component ID
|
||||||
std::string client_script_name; //!< The client script name
|
std::string script_name; //!< The script name
|
||||||
|
std::string client_script_name; //!< The client script name
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDScriptComponentTable : public CDTable<CDScriptComponentTable> {
|
class CDScriptComponentTable : public CDTable<CDScriptComponentTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<unsigned int, CDScriptComponent> entries;
|
std::map<unsigned int, CDScriptComponent> entries;
|
||||||
|
CDScriptComponent m_ToReturnWhenNoneFound;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Gets an entry by scriptID
|
// Gets an entry by scriptID
|
||||||
const std::optional<CDScriptComponent> GetByID(unsigned int id);
|
const CDScriptComponent& GetByID(unsigned int id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
|
|
||||||
void CDSkillBehaviorTable::LoadValuesFromDatabase() {
|
void CDSkillBehaviorTable::LoadValuesFromDatabase() {
|
||||||
|
m_empty = CDSkillBehavior();
|
||||||
|
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM SkillBehavior");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
//this->entries.reserve(size);
|
||||||
|
|
||||||
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM SkillBehavior");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM SkillBehavior");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDSkillBehavior entry;
|
CDSkillBehavior entry;
|
||||||
uint32_t skillID = tableData.getIntField("skillID", -1);
|
entry.skillID = tableData.getIntField("skillID", -1);
|
||||||
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
||||||
entry.behaviorID = tableData.getIntField("behaviorID", -1);
|
entry.behaviorID = tableData.getIntField("behaviorID", -1);
|
||||||
entry.imaginationcost = tableData.getIntField("imaginationcost", -1);
|
entry.imaginationcost = tableData.getIntField("imaginationcost", -1);
|
||||||
@@ -24,13 +41,20 @@ void CDSkillBehaviorTable::LoadValuesFromDatabase() {
|
|||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
UNUSED(entry.cancelType = tableData.getIntField("cancelType", -1));
|
UNUSED(entry.cancelType = tableData.getIntField("cancelType", -1));
|
||||||
|
|
||||||
this->entries.insert_or_assign(skillID, entry);
|
this->entries.insert(std::make_pair(entry.skillID, entry));
|
||||||
|
//this->entries.push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<CDSkillBehavior> CDSkillBehaviorTable::GetSkillByID(unsigned int skillID) {
|
const CDSkillBehavior& CDSkillBehaviorTable::GetSkillByID(unsigned int skillID) {
|
||||||
auto it = this->entries.find(skillID);
|
std::map<unsigned int, CDSkillBehavior>::iterator it = this->entries.find(skillID);
|
||||||
return it != this->entries.end() ? std::make_optional(it->second) : std::nullopt;
|
if (it != this->entries.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDSkillBehavior {
|
struct CDSkillBehavior {
|
||||||
|
unsigned int skillID; //!< The Skill ID of the skill
|
||||||
UNUSED(unsigned int locStatus); //!< ??
|
UNUSED(unsigned int locStatus); //!< ??
|
||||||
unsigned int behaviorID; //!< The Behavior ID of the skill
|
unsigned int behaviorID; //!< The Behavior ID of the skill
|
||||||
unsigned int imaginationcost; //!< The imagination cost of the skill
|
unsigned int imaginationcost; //!< The imagination cost of the skill
|
||||||
@@ -26,11 +27,13 @@ struct CDSkillBehavior {
|
|||||||
|
|
||||||
class CDSkillBehaviorTable : public CDTable<CDSkillBehaviorTable> {
|
class CDSkillBehaviorTable : public CDTable<CDSkillBehaviorTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, CDSkillBehavior> entries;
|
std::map<unsigned int, CDSkillBehavior> entries;
|
||||||
|
CDSkillBehavior m_empty;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Gets an entry by skillID
|
// Gets an entry by skillID
|
||||||
const std::optional<CDSkillBehavior> GetSkillByID(unsigned int skillID);
|
const CDSkillBehavior& GetSkillByID(unsigned int skillID);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "DluAssert.h"
|
#include "DluAssert.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|||||||
@@ -1,22 +1,50 @@
|
|||||||
#include "CDVendorComponentTable.h"
|
#include "CDVendorComponentTable.h"
|
||||||
|
|
||||||
void CDVendorComponentTable::LoadValuesFromDatabase() {
|
void CDVendorComponentTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM VendorComponent");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
this->entries.reserve(size);
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM VendorComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM VendorComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDVendorComponent entry;
|
CDVendorComponent entry;
|
||||||
uint32_t id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.buyScalar = tableData.getFloatField("buyScalar", -1.0f);
|
entry.buyScalar = tableData.getFloatField("buyScalar", 0.0f);
|
||||||
entry.sellScalar = tableData.getFloatField("sellScalar", -1.0f);
|
entry.sellScalar = tableData.getFloatField("sellScalar", -1.0f);
|
||||||
entry.refreshTimeSeconds = tableData.getFloatField("refreshTimeSeconds", -1.0f);
|
entry.refreshTimeSeconds = tableData.getFloatField("refreshTimeSeconds", -1.0f);
|
||||||
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
|
|
||||||
this->entries.insert_or_assign(id, entry);
|
this->entries.push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<CDVendorComponent> CDVendorComponentTable::Query(uint32_t id) {
|
//! Queries the table with a custom "where" clause
|
||||||
const auto& iter = entries.find(id);
|
std::vector<CDVendorComponent> CDVendorComponentTable::Query(std::function<bool(CDVendorComponent)> predicate) {
|
||||||
return iter != entries.end() ? std::make_optional(iter->second) : std::nullopt;
|
|
||||||
|
std::vector<CDVendorComponent> data = cpplinq::from(this->entries)
|
||||||
|
>> cpplinq::where(predicate)
|
||||||
|
>> cpplinq::to_vector();
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Gets all the entries in the table
|
||||||
|
const std::vector<CDVendorComponent>& CDVendorComponentTable::GetEntries() const {
|
||||||
|
return this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDVendorComponent {
|
struct CDVendorComponent {
|
||||||
|
unsigned int id; //!< The Component ID
|
||||||
float buyScalar; //!< Buy Scalar (what does that mean?)
|
float buyScalar; //!< Buy Scalar (what does that mean?)
|
||||||
float sellScalar; //!< Sell Scalar (what does that mean?)
|
float sellScalar; //!< Sell Scalar (what does that mean?)
|
||||||
float refreshTimeSeconds; //!< The refresh time
|
float refreshTimeSeconds; //!< The refresh time
|
||||||
@@ -12,11 +13,13 @@ struct CDVendorComponent {
|
|||||||
|
|
||||||
class CDVendorComponentTable : public CDTable<CDVendorComponentTable> {
|
class CDVendorComponentTable : public CDTable<CDVendorComponentTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, CDVendorComponent> entries;
|
std::vector<CDVendorComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
const std::optional<CDVendorComponent> Query(uint32_t id);
|
std::vector<CDVendorComponent> Query(std::function<bool(CDVendorComponent)> predicate);
|
||||||
|
|
||||||
|
const std::vector<CDVendorComponent>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
#include "CDZoneTableTable.h"
|
#include "CDZoneTableTable.h"
|
||||||
|
|
||||||
void CDZoneTableTable::LoadValuesFromDatabase() {
|
void CDZoneTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ZoneTable");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ZoneTable");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ZoneTable");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
@@ -36,11 +48,18 @@ void CDZoneTableTable::LoadValuesFromDatabase() {
|
|||||||
this->m_Entries.insert(std::make_pair(entry.zoneID, entry));
|
this->m_Entries.insert(std::make_pair(entry.zoneID, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a zoneID to find.
|
//! Queries the table with a zoneID to find.
|
||||||
const std::optional<CDZoneTable> CDZoneTableTable::Query(unsigned int zoneID) {
|
const CDZoneTable* CDZoneTableTable::Query(unsigned int zoneID) {
|
||||||
const auto& iter = m_Entries.find(zoneID);
|
const auto& iter = m_Entries.find(zoneID);
|
||||||
return iter != m_Entries.end() ? std::make_optional(iter->second) : std::nullopt;
|
|
||||||
|
if (iter != m_Entries.end()) {
|
||||||
|
return &iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDZoneTable {
|
struct CDZoneTable {
|
||||||
@@ -34,11 +35,11 @@ struct CDZoneTable {
|
|||||||
|
|
||||||
class CDZoneTableTable : public CDTable<CDZoneTableTable> {
|
class CDZoneTableTable : public CDTable<CDZoneTableTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, CDZoneTable> m_Entries;
|
std::map<unsigned int, CDZoneTable> m_Entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a zoneID to find.
|
// Queries the table with a zoneID to find.
|
||||||
const std::optional<CDZoneTable> Query(unsigned int zoneID);
|
const CDZoneTable* Query(unsigned int zoneID);
|
||||||
};
|
};
|
||||||
|
|||||||
205
dGame/Entity.cpp
205
dGame/Entity.cpp
@@ -30,7 +30,7 @@
|
|||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "ControllablePhysicsComponent.h"
|
#include "ControllablePhysicsComponent.h"
|
||||||
#include "RenderComponent.h"
|
#include "RenderComponent.h"
|
||||||
#include "RocketLaunchLupComponent.h"
|
#include "MultiZoneEntranceComponent.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
#include "DestroyableComponent.h"
|
#include "DestroyableComponent.h"
|
||||||
#include "BuffComponent.h"
|
#include "BuffComponent.h"
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
#include "BuildBorderComponent.h"
|
#include "BuildBorderComponent.h"
|
||||||
#include "MovementAIComponent.h"
|
#include "MovementAIComponent.h"
|
||||||
#include "VendorComponent.h"
|
#include "VendorComponent.h"
|
||||||
|
#include "DonationVendorComponent.h"
|
||||||
#include "RocketLaunchpadControlComponent.h"
|
#include "RocketLaunchpadControlComponent.h"
|
||||||
#include "PropertyComponent.h"
|
#include "PropertyComponent.h"
|
||||||
#include "BaseCombatAIComponent.h"
|
#include "BaseCombatAIComponent.h"
|
||||||
@@ -70,6 +71,7 @@
|
|||||||
#include "ShootingGalleryComponent.h"
|
#include "ShootingGalleryComponent.h"
|
||||||
#include "RailActivatorComponent.h"
|
#include "RailActivatorComponent.h"
|
||||||
#include "LUPExhibitComponent.h"
|
#include "LUPExhibitComponent.h"
|
||||||
|
#include "RacingSoundTriggerComponent.h"
|
||||||
#include "TriggerComponent.h"
|
#include "TriggerComponent.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
@@ -317,6 +319,9 @@ void Entity::Initialize() {
|
|||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
|
||||||
auto* comp = new SoundTriggerComponent(this);
|
auto* comp = new SoundTriggerComponent(this);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp));
|
||||||
|
} else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) {
|
||||||
|
auto* comp = new RacingSoundTriggerComponent(this);
|
||||||
|
m_Components.insert(std::make_pair(eReplicaComponentType::RACING_SOUND_TRIGGER, comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Also check for the collectible id:
|
//Also check for the collectible id:
|
||||||
@@ -340,7 +345,7 @@ void Entity::Initialize() {
|
|||||||
int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
|
int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
|
||||||
int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
|
int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
|
||||||
|
|
||||||
int componentID = 0;
|
int componentID = -1;
|
||||||
if (collectibleComponentID > 0) componentID = collectibleComponentID;
|
if (collectibleComponentID > 0) componentID = collectibleComponentID;
|
||||||
if (rebuildComponentID > 0) componentID = rebuildComponentID;
|
if (rebuildComponentID > 0) componentID = rebuildComponentID;
|
||||||
if (buffComponentID > 0) componentID = buffComponentID;
|
if (buffComponentID > 0) componentID = buffComponentID;
|
||||||
@@ -348,7 +353,8 @@ void Entity::Initialize() {
|
|||||||
CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
|
CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
|
||||||
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
|
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
|
||||||
|
|
||||||
if (buffComponentID > 0 || collectibleComponentID > 0) {
|
bool isSmashable = GetVarAs<int32_t>(u"is_smashable") != 0;
|
||||||
|
if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) {
|
||||||
DestroyableComponent* comp = new DestroyableComponent(this);
|
DestroyableComponent* comp = new DestroyableComponent(this);
|
||||||
if (m_Character) {
|
if (m_Character) {
|
||||||
comp->LoadFromXml(m_Character->GetXMLDoc());
|
comp->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
@@ -368,10 +374,12 @@ void Entity::Initialize() {
|
|||||||
comp->SetMaxHealth(destCompData[0].life);
|
comp->SetMaxHealth(destCompData[0].life);
|
||||||
comp->SetMaxImagination(destCompData[0].imagination);
|
comp->SetMaxImagination(destCompData[0].imagination);
|
||||||
comp->SetMaxArmor(destCompData[0].armor);
|
comp->SetMaxArmor(destCompData[0].armor);
|
||||||
|
comp->SetDeathBehavior(destCompData[0].death_behavior);
|
||||||
|
|
||||||
comp->SetIsSmashable(destCompData[0].isSmashable);
|
comp->SetIsSmashable(destCompData[0].isSmashable);
|
||||||
|
|
||||||
comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
|
comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
|
||||||
|
Loot::CacheMatrix(destCompData[0].LootMatrixIndex);
|
||||||
|
|
||||||
// Now get currency information
|
// Now get currency information
|
||||||
uint32_t npcMinLevel = destCompData[0].level;
|
uint32_t npcMinLevel = destCompData[0].level;
|
||||||
@@ -387,7 +395,7 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
|
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
|
||||||
comp->SetIsSmashable(comp->GetIsSmashable() | (GetVarAs<int32_t>(u"is_smashable") != 0));
|
comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
comp->SetHealth(1);
|
comp->SetHealth(1);
|
||||||
@@ -420,6 +428,19 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override the factions if needed.
|
||||||
|
auto setFaction = GetVarAsString(u"set_faction");
|
||||||
|
if (!setFaction.empty()) {
|
||||||
|
// TODO also split on space here however we do not have a general util for splitting on multiple characters yet.
|
||||||
|
std::vector<std::string> factionsToAdd = GeneralUtils::SplitString(setFaction, ';');
|
||||||
|
int32_t factionToAdd;
|
||||||
|
for (const auto faction : factionsToAdd) {
|
||||||
|
if (GeneralUtils::TryParse(faction, factionToAdd)) {
|
||||||
|
comp->AddFaction(factionToAdd, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,9 +467,9 @@ void Entity::Initialize() {
|
|||||||
m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp));
|
||||||
}
|
}
|
||||||
// if this component exists, then we initialize it. it's value is always 0
|
// if this component exists, then we initialize it. it's value is always 0
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH_LUP, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
|
||||||
auto comp = new RocketLaunchLupComponent(this);
|
auto comp = new MultiZoneEntranceComponent(this);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH_LUP, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::MULTI_ZONE_ENTRANCE, comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,11 +484,9 @@ void Entity::Initialize() {
|
|||||||
if (scriptComponentID > 0 || m_Character) {
|
if (scriptComponentID > 0 || m_Character) {
|
||||||
std::string clientScriptName;
|
std::string clientScriptName;
|
||||||
if (!m_Character) {
|
if (!m_Character) {
|
||||||
auto scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||||
if (scriptCompData) {
|
scriptName = scriptCompData.script_name;
|
||||||
scriptName = scriptCompData->script_name;
|
clientScriptName = scriptCompData.client_script_name;
|
||||||
clientScriptName = scriptCompData->client_script_name;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
scriptName = "";
|
scriptName = "";
|
||||||
}
|
}
|
||||||
@@ -506,17 +525,16 @@ void Entity::Initialize() {
|
|||||||
|
|
||||||
// ZoneControl script
|
// ZoneControl script
|
||||||
if (m_TemplateID == 2365) {
|
if (m_TemplateID == 2365) {
|
||||||
auto* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
|
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
|
||||||
const auto zoneID = Game::zoneManager->GetZoneID();
|
const auto zoneID = Game::zoneManager->GetZoneID();
|
||||||
auto zoneData = zoneTable->Query(zoneID.GetMapID());
|
const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID());
|
||||||
|
|
||||||
if (zoneData) {
|
if (zoneData != nullptr) {
|
||||||
int zoneScriptID = zoneData->scriptID;
|
int zoneScriptID = zoneData->scriptID;
|
||||||
auto zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
|
CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
|
||||||
if (zoneScriptData) {
|
|
||||||
ScriptComponent* comp = new ScriptComponent(this, zoneScriptData->script_name, true);
|
ScriptComponent* comp = new ScriptComponent(this, zoneScriptData.script_name, true);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, comp));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,17 +554,17 @@ void Entity::Initialize() {
|
|||||||
m_Components.insert(std::make_pair(eReplicaComponentType::QUICK_BUILD, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::QUICK_BUILD, comp));
|
||||||
|
|
||||||
CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
|
CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
|
||||||
auto rebCompData = rebCompTable->Get(rebuildComponentID);
|
std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == rebuildComponentID); });
|
||||||
|
|
||||||
if (rebCompData) {
|
if (rebCompData.size() > 0) {
|
||||||
comp->SetResetTime(rebCompData->reset_time);
|
comp->SetResetTime(rebCompData[0].reset_time);
|
||||||
comp->SetCompleteTime(rebCompData->complete_time);
|
comp->SetCompleteTime(rebCompData[0].complete_time);
|
||||||
comp->SetTakeImagination(rebCompData->take_imagination);
|
comp->SetTakeImagination(rebCompData[0].take_imagination);
|
||||||
comp->SetInterruptible(rebCompData->interruptible);
|
comp->SetInterruptible(rebCompData[0].interruptible);
|
||||||
comp->SetSelfActivator(rebCompData->self_activator);
|
comp->SetSelfActivator(rebCompData[0].self_activator);
|
||||||
comp->SetActivityId(rebCompData->activityID);
|
comp->SetActivityId(rebCompData[0].activityID);
|
||||||
comp->SetPostImaginationCost(rebCompData->post_imagination_cost);
|
comp->SetPostImaginationCost(rebCompData[0].post_imagination_cost);
|
||||||
comp->SetTimeBeforeSmash(rebCompData->time_before_smash);
|
comp->SetTimeBeforeSmash(rebCompData[0].time_before_smash);
|
||||||
|
|
||||||
const auto rebuildResetTime = GetVar<float>(u"rebuild_reset_time");
|
const auto rebuildResetTime = GetVar<float>(u"rebuild_reset_time");
|
||||||
|
|
||||||
@@ -563,6 +581,7 @@ void Entity::Initialize() {
|
|||||||
|
|
||||||
if (activityID > 0) {
|
if (activityID > 0) {
|
||||||
comp->SetActivityId(activityID);
|
comp->SetActivityId(activityID);
|
||||||
|
Loot::CacheMatrix(activityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto compTime = GetVar<float>(u"compTime");
|
const auto compTime = GetVar<float>(u"compTime");
|
||||||
@@ -581,6 +600,9 @@ void Entity::Initialize() {
|
|||||||
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
|
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
|
||||||
VendorComponent* comp = new VendorComponent(this);
|
VendorComponent* comp = new VendorComponent(this);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp));
|
||||||
|
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
|
||||||
|
DonationVendorComponent* comp = new DonationVendorComponent(this);
|
||||||
|
m_Components.insert(std::make_pair(eReplicaComponentType::DONATION_VENDOR, comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
|
||||||
@@ -697,12 +719,12 @@ void Entity::Initialize() {
|
|||||||
const Path* path = Game::zoneManager->GetZone()->GetPath(pathName);
|
const Path* path = Game::zoneManager->GetZone()->GetPath(pathName);
|
||||||
|
|
||||||
//Check to see if we have an attached path and add the appropiate component to handle it:
|
//Check to see if we have an attached path and add the appropiate component to handle it:
|
||||||
if (path){
|
if (path) {
|
||||||
// if we have a moving platform path, then we need a moving platform component
|
// if we have a moving platform path, then we need a moving platform component
|
||||||
if (path->pathType == PathType::MovingPlatform) {
|
if (path->pathType == PathType::MovingPlatform) {
|
||||||
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
|
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
|
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
|
||||||
// else if we are a movement path
|
// else if we are a movement path
|
||||||
} /*else if (path->pathType == PathType::Movement) {
|
} /*else if (path->pathType == PathType::Movement) {
|
||||||
auto movementAIcomp = GetComponent<MovementAIComponent>();
|
auto movementAIcomp = GetComponent<MovementAIComponent>();
|
||||||
if (movementAIcomp){
|
if (movementAIcomp){
|
||||||
@@ -917,10 +939,20 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacke
|
|||||||
outBitStream->Write1(); //ldf data
|
outBitStream->Write1(); //ldf data
|
||||||
|
|
||||||
RakNet::BitStream settingStream;
|
RakNet::BitStream settingStream;
|
||||||
settingStream.Write<uint32_t>(m_Settings.size());
|
int32_t numberOfValidKeys = m_Settings.size();
|
||||||
|
|
||||||
|
// Writing keys value pairs the client does not expect to receive or interpret will result in undefined behavior,
|
||||||
|
// so we need to filter out any keys that are not valid and fix the number of valid keys to be correct.
|
||||||
|
// TODO should make this more efficient so that we dont waste loops evaluating the same condition twice
|
||||||
|
for (LDFBaseData* data : m_Settings) {
|
||||||
|
if (!data || data->GetValueType() == eLDFType::LDF_TYPE_UNKNOWN) {
|
||||||
|
numberOfValidKeys--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settingStream.Write<uint32_t>(numberOfValidKeys);
|
||||||
|
|
||||||
for (LDFBaseData* data : m_Settings) {
|
for (LDFBaseData* data : m_Settings) {
|
||||||
if (data) {
|
if (data && data->GetValueType() != eLDFType::LDF_TYPE_UNKNOWN) {
|
||||||
data->WriteToPacket(&settingStream);
|
data->WriteToPacket(&settingStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -939,7 +971,6 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacke
|
|||||||
|
|
||||||
RakNet::BitStream settingStream;
|
RakNet::BitStream settingStream;
|
||||||
settingStream.Write<uint32_t>(ldfData.size());
|
settingStream.Write<uint32_t>(ldfData.size());
|
||||||
|
|
||||||
for (LDFBaseData* data : ldfData) {
|
for (LDFBaseData* data : ldfData) {
|
||||||
if (data) {
|
if (data) {
|
||||||
data->WriteToPacket(&settingStream);
|
data->WriteToPacket(&settingStream);
|
||||||
@@ -1015,57 +1046,60 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool destroyableSerialized = false;
|
bool destroyableSerialized = false;
|
||||||
bool bIsInitialUpdate = false;
|
bool bIsInitialUpdate = packetType == eReplicaPacketType::CONSTRUCTION;
|
||||||
if (packetType == eReplicaPacketType::CONSTRUCTION) bIsInitialUpdate = true;
|
|
||||||
unsigned int flags = 0;
|
|
||||||
|
|
||||||
PossessableComponent* possessableComponent;
|
PossessableComponent* possessableComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) {
|
if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) {
|
||||||
possessableComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
possessableComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleAssemblyComponent* moduleAssemblyComponent;
|
ModuleAssemblyComponent* moduleAssemblyComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) {
|
if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) {
|
||||||
moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllablePhysicsComponent* controllablePhysicsComponent;
|
ControllablePhysicsComponent* controllablePhysicsComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) {
|
if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) {
|
||||||
controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimplePhysicsComponent* simplePhysicsComponent;
|
SimplePhysicsComponent* simplePhysicsComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) {
|
||||||
simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics;
|
RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics;
|
||||||
if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) {
|
if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) {
|
||||||
rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate, flags);
|
rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
VehiclePhysicsComponent* vehiclePhysicsComponent;
|
VehiclePhysicsComponent* vehiclePhysicsComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) {
|
if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) {
|
||||||
vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomPhysicsComponent* phantomPhysicsComponent;
|
PhantomPhysicsComponent* phantomPhysicsComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) {
|
if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) {
|
||||||
phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundTriggerComponent* soundTriggerComponent;
|
SoundTriggerComponent* soundTriggerComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) {
|
||||||
soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
RacingSoundTriggerComponent* racingSoundTriggerComponent;
|
||||||
|
if (TryGetComponent(eReplicaComponentType::RACING_SOUND_TRIGGER, racingSoundTriggerComponent)) {
|
||||||
|
racingSoundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuffComponent* buffComponent;
|
BuffComponent* buffComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) {
|
if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) {
|
||||||
buffComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
buffComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
|
|
||||||
DestroyableComponent* destroyableComponent;
|
DestroyableComponent* destroyableComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) {
|
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) {
|
||||||
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
destroyableSerialized = true;
|
destroyableSerialized = true;
|
||||||
}
|
}
|
||||||
@@ -1073,7 +1107,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
if (HasComponent(eReplicaComponentType::COLLECTIBLE)) {
|
if (HasComponent(eReplicaComponentType::COLLECTIBLE)) {
|
||||||
DestroyableComponent* destroyableComponent;
|
DestroyableComponent* destroyableComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
||||||
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
destroyableSerialized = true;
|
destroyableSerialized = true;
|
||||||
outBitStream->Write(m_CollectibleID); // Collectable component
|
outBitStream->Write(m_CollectibleID); // Collectable component
|
||||||
@@ -1081,7 +1115,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
|
|
||||||
PetComponent* petComponent;
|
PetComponent* petComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::PET, petComponent)) {
|
if (TryGetComponent(eReplicaComponentType::PET, petComponent)) {
|
||||||
petComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
petComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
CharacterComponent* characterComponent;
|
CharacterComponent* characterComponent;
|
||||||
@@ -1089,7 +1123,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
|
|
||||||
PossessorComponent* possessorComponent;
|
PossessorComponent* possessorComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) {
|
if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) {
|
||||||
possessorComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
possessorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
} else {
|
} else {
|
||||||
// Should never happen, but just to be safe
|
// Should never happen, but just to be safe
|
||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
@@ -1097,7 +1131,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
|
|
||||||
LevelProgressionComponent* levelProgressionComponent;
|
LevelProgressionComponent* levelProgressionComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) {
|
if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) {
|
||||||
levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
} else {
|
} else {
|
||||||
// Should never happen, but just to be safe
|
// Should never happen, but just to be safe
|
||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
@@ -1105,13 +1139,13 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
|
|
||||||
PlayerForcedMovementComponent* playerForcedMovementComponent;
|
PlayerForcedMovementComponent* playerForcedMovementComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) {
|
if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) {
|
||||||
playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
} else {
|
} else {
|
||||||
// Should never happen, but just to be safe
|
// Should never happen, but just to be safe
|
||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
characterComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
characterComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasComponent(eReplicaComponentType::ITEM)) {
|
if (HasComponent(eReplicaComponentType::ITEM)) {
|
||||||
@@ -1120,88 +1154,93 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
|
|
||||||
InventoryComponent* inventoryComponent;
|
InventoryComponent* inventoryComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) {
|
if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) {
|
||||||
inventoryComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
inventoryComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptComponent* scriptComponent;
|
ScriptComponent* scriptComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) {
|
||||||
scriptComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
scriptComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkillComponent* skillComponent;
|
SkillComponent* skillComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) {
|
||||||
skillComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
skillComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseCombatAIComponent* baseCombatAiComponent;
|
BaseCombatAIComponent* baseCombatAiComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) {
|
if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) {
|
||||||
baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
RebuildComponent* rebuildComponent;
|
RebuildComponent* rebuildComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) {
|
if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) {
|
||||||
DestroyableComponent* destroyableComponent;
|
DestroyableComponent* destroyableComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
||||||
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
destroyableSerialized = true;
|
destroyableSerialized = true;
|
||||||
rebuildComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
rebuildComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
MovingPlatformComponent* movingPlatformComponent;
|
MovingPlatformComponent* movingPlatformComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) {
|
if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) {
|
||||||
movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchComponent* switchComponent;
|
SwitchComponent* switchComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) {
|
||||||
switchComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
switchComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
VendorComponent* vendorComponent;
|
VendorComponent* vendorComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) {
|
if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) {
|
||||||
vendorComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
vendorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
DonationVendorComponent* donationVendorComponent;
|
||||||
|
if (TryGetComponent(eReplicaComponentType::DONATION_VENDOR, donationVendorComponent)) {
|
||||||
|
donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
BouncerComponent* bouncerComponent;
|
BouncerComponent* bouncerComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) {
|
if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) {
|
||||||
bouncerComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
bouncerComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptedActivityComponent* scriptedActivityComponent;
|
ScriptedActivityComponent* scriptedActivityComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) {
|
||||||
scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShootingGalleryComponent* shootingGalleryComponent;
|
ShootingGalleryComponent* shootingGalleryComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) {
|
if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) {
|
||||||
shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
RacingControlComponent* racingControlComponent;
|
RacingControlComponent* racingControlComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) {
|
if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) {
|
||||||
racingControlComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
racingControlComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
LUPExhibitComponent* lupExhibitComponent;
|
LUPExhibitComponent* lupExhibitComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) {
|
if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) {
|
||||||
lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelComponent* modelComponent;
|
ModelComponent* modelComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) {
|
if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) {
|
||||||
modelComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
modelComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderComponent* renderComponent;
|
RenderComponent* renderComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) {
|
if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) {
|
||||||
renderComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
renderComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modelComponent) {
|
if (modelComponent || !destroyableSerialized) {
|
||||||
DestroyableComponent* destroyableComponent;
|
DestroyableComponent* destroyableComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
|
||||||
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags);
|
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
destroyableSerialized = true;
|
destroyableSerialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1216,10 +1255,6 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::ResetFlags() {
|
|
||||||
// Unused
|
|
||||||
}
|
|
||||||
|
|
||||||
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
|
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.
|
//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.
|
//Naturally, we don't include any non-player components in this update function.
|
||||||
@@ -1541,7 +1576,17 @@ void Entity::Kill(Entity* murderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsPlayer()) {
|
if (!IsPlayer()) {
|
||||||
Game::entityManager->DestroyEntity(this);
|
auto* destroyableComponent = GetComponent<DestroyableComponent>();
|
||||||
|
bool waitForDeathAnimation = false;
|
||||||
|
|
||||||
|
if (destroyableComponent) {
|
||||||
|
waitForDeathAnimation = destroyableComponent->GetDeathBehavior() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction!
|
||||||
|
constexpr float DelayDeathTime = 12.0f;
|
||||||
|
if (waitForDeathAnimation) AddCallbackTimer(DelayDeathTime, [this]() { Game::entityManager->DestroyEntity(this); });
|
||||||
|
else Game::entityManager->DestroyEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks");
|
const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks");
|
||||||
@@ -1631,9 +1676,9 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
|
|||||||
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
|
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
|
||||||
for (CDObjectSkills skill : skills) {
|
for (CDObjectSkills skill : skills) {
|
||||||
CDSkillBehaviorTable* skillBehTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
CDSkillBehaviorTable* skillBehTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||||
auto behaviorData = skillBehTable->GetSkillByID(skill.skillID);
|
CDSkillBehavior behaviorData = skillBehTable->GetSkillByID(skill.skillID);
|
||||||
if (!behaviorData) continue;
|
|
||||||
SkillComponent::HandleUnmanaged(behaviorData->behaviorID, GetObjectID());
|
SkillComponent::HandleUnmanaged(behaviorData.behaviorID, GetObjectID());
|
||||||
|
|
||||||
auto* missionComponent = GetComponent<MissionComponent>();
|
auto* missionComponent = GetComponent<MissionComponent>();
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ public:
|
|||||||
bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; }
|
bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; }
|
||||||
|
|
||||||
bool GetIsGhostingCandidate() const;
|
bool GetIsGhostingCandidate() const;
|
||||||
|
void SetIsGhostingCandidate(bool value) { m_IsGhostingCandidate = value; };
|
||||||
|
|
||||||
int8_t GetObservers() const;
|
int8_t GetObservers() const;
|
||||||
|
|
||||||
@@ -173,7 +174,6 @@ public:
|
|||||||
|
|
||||||
void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
|
void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
|
||||||
void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
|
void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
|
||||||
void ResetFlags();
|
|
||||||
void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
|
void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
|
||||||
void Update(float deltaTime);
|
void Update(float deltaTime);
|
||||||
|
|
||||||
|
|||||||
@@ -298,6 +298,16 @@ std::vector<Entity*> EntityManager::GetEntitiesByLOT(const LOT& lot) const {
|
|||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Entity*> EntityManager::GetEntitiesByProximity(NiPoint3 reference, float radius) const{
|
||||||
|
std::vector<Entity*> entities = {};
|
||||||
|
if (radius > 1000.0f) return entities;
|
||||||
|
for (const auto& entity : m_Entities) {
|
||||||
|
if (NiPoint3::Distance(reference, entity.second->GetPosition()) <= radius) entities.push_back(entity.second);
|
||||||
|
}
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity* EntityManager::GetZoneControlEntity() const {
|
Entity* EntityManager::GetZoneControlEntity() const {
|
||||||
return m_ZoneControlEntity;
|
return m_ZoneControlEntity;
|
||||||
}
|
}
|
||||||
@@ -583,12 +593,6 @@ bool EntityManager::GetGhostingEnabled() const {
|
|||||||
return m_GhostingEnabled;
|
return m_GhostingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::ResetFlags() {
|
|
||||||
for (const auto& e : m_Entities) {
|
|
||||||
e.second->ResetFlags();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityManager::ScheduleForKill(Entity* entity) {
|
void EntityManager::ScheduleForKill(Entity* entity) {
|
||||||
// Deactivate switches if they die
|
// Deactivate switches if they die
|
||||||
if (!entity)
|
if (!entity)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
std::vector<Entity*> GetEntitiesInGroup(const std::string& group);
|
std::vector<Entity*> GetEntitiesInGroup(const std::string& group);
|
||||||
std::vector<Entity*> GetEntitiesByComponent(eReplicaComponentType componentType) const;
|
std::vector<Entity*> GetEntitiesByComponent(eReplicaComponentType componentType) const;
|
||||||
std::vector<Entity*> GetEntitiesByLOT(const LOT& lot) const;
|
std::vector<Entity*> GetEntitiesByLOT(const LOT& lot) const;
|
||||||
|
std::vector<Entity*> GetEntitiesByProximity(NiPoint3 reference, float radius) const;
|
||||||
Entity* GetZoneControlEntity() const;
|
Entity* GetZoneControlEntity() const;
|
||||||
|
|
||||||
// Get spawn point entity by spawn name
|
// Get spawn point entity by spawn name
|
||||||
@@ -59,8 +60,6 @@ public:
|
|||||||
Entity* GetGhostCandidate(int32_t id);
|
Entity* GetGhostCandidate(int32_t id);
|
||||||
bool GetGhostingEnabled() const;
|
bool GetGhostingEnabled() const;
|
||||||
|
|
||||||
void ResetFlags();
|
|
||||||
|
|
||||||
void ScheduleForKill(Entity* entity);
|
void ScheduleForKill(Entity* entity);
|
||||||
|
|
||||||
void ScheduleForDeletion(LWOOBJID entity);
|
void ScheduleForDeletion(LWOOBJID entity);
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
|
|||||||
// Time:1
|
// Time:1
|
||||||
break;
|
break;
|
||||||
case Type::Donations:
|
case Type::Donations:
|
||||||
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
|
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
|
||||||
// Score:1
|
// Score:1
|
||||||
break;
|
break;
|
||||||
case Type::None:
|
case Type::None:
|
||||||
// This type is included here simply to resolve a compiler warning on mac about unused enum types
|
// This type is included here simply to resolve a compiler warning on mac about unused enum types
|
||||||
@@ -170,32 +170,32 @@ void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t r
|
|||||||
resultEnd++;
|
resultEnd++;
|
||||||
// We need everything except 1 column so i'm selecting * from leaderboard
|
// We need everything except 1 column so i'm selecting * from leaderboard
|
||||||
const std::string queryBase =
|
const std::string queryBase =
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
WITH leaderboardsRanked AS (
|
WITH leaderboardsRanked AS (
|
||||||
SELECT leaderboard.*, charinfo.name,
|
SELECT leaderboard.*, charinfo.name,
|
||||||
RANK() OVER
|
RANK() OVER
|
||||||
(
|
(
|
||||||
ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC
|
ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC
|
||||||
) AS ranking
|
) AS ranking
|
||||||
FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id
|
FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id
|
||||||
WHERE game_id = ? %s
|
WHERE game_id = ? %s
|
||||||
),
|
),
|
||||||
myStanding AS (
|
myStanding AS (
|
||||||
SELECT
|
SELECT
|
||||||
ranking as myRank
|
ranking as myRank
|
||||||
FROM leaderboardsRanked
|
FROM leaderboardsRanked
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
),
|
),
|
||||||
lowestRanking AS (
|
lowestRanking AS (
|
||||||
SELECT MAX(ranking) AS lowestRank
|
SELECT MAX(ranking) AS lowestRank
|
||||||
FROM leaderboardsRanked
|
FROM leaderboardsRanked
|
||||||
)
|
)
|
||||||
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
|
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
|
||||||
WHERE leaderboardsRanked.ranking
|
WHERE leaderboardsRanked.ranking
|
||||||
BETWEEN
|
BETWEEN
|
||||||
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
|
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
|
||||||
AND
|
AND
|
||||||
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
|
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
|
||||||
ORDER BY ranking ASC;
|
ORDER BY ranking ASC;
|
||||||
)QUERY";
|
)QUERY";
|
||||||
|
|
||||||
@@ -277,15 +277,15 @@ std::string FormatInsert(const Leaderboard::Type& type, const Score& score, cons
|
|||||||
if (useUpdate) {
|
if (useUpdate) {
|
||||||
insertStatement =
|
insertStatement =
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
UPDATE leaderboard
|
UPDATE leaderboard
|
||||||
SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
||||||
timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;
|
timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;
|
||||||
)QUERY";
|
)QUERY";
|
||||||
} else {
|
} else {
|
||||||
insertStatement =
|
insertStatement =
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
INSERT leaderboard SET
|
INSERT leaderboard SET
|
||||||
primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
||||||
character_id = ?, game_id = ?;
|
character_id = ?, game_id = ?;
|
||||||
)QUERY";
|
)QUERY";
|
||||||
}
|
}
|
||||||
@@ -300,9 +300,8 @@ std::string FormatInsert(const Leaderboard::Type& type, const Score& score, cons
|
|||||||
|
|
||||||
void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) {
|
void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) {
|
||||||
const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId);
|
const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId);
|
||||||
auto* lookup = "SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;";
|
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookup));
|
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;"));
|
||||||
query->setInt(1, playerID);
|
query->setInt(1, playerID);
|
||||||
query->setInt(2, activityId);
|
query->setInt(2, activityId);
|
||||||
std::unique_ptr<sql::ResultSet> myScoreResult(query->executeQuery());
|
std::unique_ptr<sql::ResultSet> myScoreResult(query->executeQuery());
|
||||||
@@ -337,6 +336,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi
|
|||||||
case Leaderboard::Type::UnusedLeaderboard4:
|
case Leaderboard::Type::UnusedLeaderboard4:
|
||||||
case Leaderboard::Type::Donations: {
|
case Leaderboard::Type::Donations: {
|
||||||
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
newScore.SetPrimaryScore(oldScore.GetPrimaryScore() + newScore.GetPrimaryScore());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Leaderboard::Type::Racing: {
|
case Leaderboard::Type::Racing: {
|
||||||
@@ -382,7 +382,7 @@ void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activi
|
|||||||
saveStatement->setInt(1, playerID);
|
saveStatement->setInt(1, playerID);
|
||||||
saveStatement->setInt(2, activityId);
|
saveStatement->setInt(2, activityId);
|
||||||
saveStatement->execute();
|
saveStatement->execute();
|
||||||
|
|
||||||
// track wins separately
|
// track wins separately
|
||||||
if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) {
|
if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) {
|
||||||
std::unique_ptr<sql::PreparedStatement> winUpdate(Database::CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;"));
|
std::unique_ptr<sql::PreparedStatement> winUpdate(Database::CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;"));
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
#include "TeamManager.h"
|
#include "TeamManager.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
TeamManager* TeamManager::m_Address = nullptr; //For singleton method
|
TeamManager* TeamManager::m_Address = nullptr; //For singleton method
|
||||||
|
|
||||||
|
Team::Team() {
|
||||||
|
lootOption = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
TeamManager::TeamManager() {
|
TeamManager::TeamManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
|
||||||
struct Team
|
struct Team {
|
||||||
{
|
Team();
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY;
|
LWOOBJID teamID = LWOOBJID_EMPTY;
|
||||||
char lootOption = 0;
|
char lootOption = 0;
|
||||||
std::vector<LWOOBJID> members{};
|
std::vector<LWOOBJID> members{};
|
||||||
char lootRound = 0;
|
char lootRound = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TeamManager
|
class TeamManager {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
static TeamManager* Instance() {
|
static TeamManager* Instance() {
|
||||||
if (!m_Address) {
|
if (!m_Address) {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "eRenameResponse.h"
|
#include "eRenameResponse.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "CheatDetection.h"
|
||||||
|
|
||||||
UserManager* UserManager::m_Address = nullptr;
|
UserManager* UserManager::m_Address = nullptr;
|
||||||
|
|
||||||
@@ -203,40 +205,38 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
|
|||||||
stmt->setUInt(1, u->GetAccountID());
|
stmt->setUInt(1, u->GetAccountID());
|
||||||
|
|
||||||
sql::ResultSet* res = stmt->executeQuery();
|
sql::ResultSet* res = stmt->executeQuery();
|
||||||
if (res->rowsCount() > 0) {
|
std::vector<Character*>& chars = u->GetCharacters();
|
||||||
std::vector<Character*>& chars = u->GetCharacters();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < chars.size(); ++i) {
|
|
||||||
if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save
|
|
||||||
{
|
|
||||||
delete chars[i];
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* skillComponent = chars[i]->GetEntity()->GetComponent<SkillComponent>();
|
|
||||||
|
|
||||||
if (skillComponent != nullptr) {
|
|
||||||
skillComponent->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::entityManager->DestroyEntity(chars[i]->GetEntity());
|
|
||||||
|
|
||||||
chars[i]->SaveXMLToDatabase();
|
|
||||||
|
|
||||||
chars[i]->GetEntity()->SetCharacter(nullptr);
|
|
||||||
|
|
||||||
|
for (size_t i = 0; i < chars.size(); ++i) {
|
||||||
|
if (chars[i]->GetEntity() == nullptr) // We don't have entity data to save
|
||||||
|
{
|
||||||
delete chars[i];
|
delete chars[i];
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars.clear();
|
auto* skillComponent = chars[i]->GetEntity()->GetComponent<SkillComponent>();
|
||||||
|
|
||||||
while (res->next()) {
|
if (skillComponent != nullptr) {
|
||||||
LWOOBJID objID = res->getUInt64(1);
|
skillComponent->Reset();
|
||||||
Character* character = new Character(uint32_t(objID), u);
|
|
||||||
character->SetIsNewLogin();
|
|
||||||
chars.push_back(character);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game::entityManager->DestroyEntity(chars[i]->GetEntity());
|
||||||
|
|
||||||
|
chars[i]->SaveXMLToDatabase();
|
||||||
|
|
||||||
|
chars[i]->GetEntity()->SetCharacter(nullptr);
|
||||||
|
|
||||||
|
delete chars[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
chars.clear();
|
||||||
|
|
||||||
|
while (res->next()) {
|
||||||
|
LWOOBJID objID = res->getUInt64(1);
|
||||||
|
Character* character = new Character(uint32_t(objID), u);
|
||||||
|
character->SetIsNewLogin();
|
||||||
|
chars.push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete res;
|
delete res;
|
||||||
@@ -251,21 +251,21 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
|
|
||||||
std::string name = PacketUtils::ReadString(8, packet, true);
|
std::string name = PacketUtils::ReadString(8, packet, true);
|
||||||
|
|
||||||
uint32_t firstNameIndex = PacketUtils::ReadPacketU32(74, packet);
|
uint32_t firstNameIndex = PacketUtils::ReadU32(74, packet);
|
||||||
uint32_t middleNameIndex = PacketUtils::ReadPacketU32(78, packet);
|
uint32_t middleNameIndex = PacketUtils::ReadU32(78, packet);
|
||||||
uint32_t lastNameIndex = PacketUtils::ReadPacketU32(82, packet);
|
uint32_t lastNameIndex = PacketUtils::ReadU32(82, packet);
|
||||||
std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex);
|
std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex);
|
||||||
|
|
||||||
uint32_t shirtColor = PacketUtils::ReadPacketU32(95, packet);
|
uint32_t shirtColor = PacketUtils::ReadU32(95, packet);
|
||||||
uint32_t shirtStyle = PacketUtils::ReadPacketU32(99, packet);
|
uint32_t shirtStyle = PacketUtils::ReadU32(99, packet);
|
||||||
uint32_t pantsColor = PacketUtils::ReadPacketU32(103, packet);
|
uint32_t pantsColor = PacketUtils::ReadU32(103, packet);
|
||||||
uint32_t hairStyle = PacketUtils::ReadPacketU32(107, packet);
|
uint32_t hairStyle = PacketUtils::ReadU32(107, packet);
|
||||||
uint32_t hairColor = PacketUtils::ReadPacketU32(111, packet);
|
uint32_t hairColor = PacketUtils::ReadU32(111, packet);
|
||||||
uint32_t lh = PacketUtils::ReadPacketU32(115, packet);
|
uint32_t lh = PacketUtils::ReadU32(115, packet);
|
||||||
uint32_t rh = PacketUtils::ReadPacketU32(119, packet);
|
uint32_t rh = PacketUtils::ReadU32(119, packet);
|
||||||
uint32_t eyebrows = PacketUtils::ReadPacketU32(123, packet);
|
uint32_t eyebrows = PacketUtils::ReadU32(123, packet);
|
||||||
uint32_t eyes = PacketUtils::ReadPacketU32(127, packet);
|
uint32_t eyes = PacketUtils::ReadU32(127, packet);
|
||||||
uint32_t mouth = PacketUtils::ReadPacketU32(131, packet);
|
uint32_t mouth = PacketUtils::ReadU32(131, packet);
|
||||||
|
|
||||||
LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle);
|
LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle);
|
||||||
LOT pantsLOT = FindCharPantsID(pantsColor);
|
LOT pantsLOT = FindCharPantsID(pantsColor);
|
||||||
@@ -387,20 +387,19 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
|
LWOOBJID objectID = PacketUtils::ReadS64(8, packet);
|
||||||
uint32_t charID = static_cast<uint32_t>(objectID);
|
uint32_t charID = static_cast<uint32_t>(objectID);
|
||||||
|
|
||||||
Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)", objectID, charID);
|
Game::logger->Log("UserManager", "Received char delete req for ID: %llu (%u)", objectID, charID);
|
||||||
|
|
||||||
//Check if this user has this character:
|
bool hasCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
||||||
bool hasCharacter = false;
|
objectID,
|
||||||
std::vector<Character*>& characters = u->GetCharacters();
|
sysAddr,
|
||||||
for (size_t i = 0; i < characters.size(); ++i) {
|
CheckType::User,
|
||||||
if (characters[i]->GetID() == charID) { hasCharacter = true; }
|
"User %i tried to delete a character that it does not own!",
|
||||||
}
|
u->GetAccountID());
|
||||||
|
|
||||||
if (!hasCharacter) {
|
if (!hasCharacter) {
|
||||||
Game::logger->Log("UserManager", "User %i tried to delete a character that it does not own!", u->GetAccountID());
|
|
||||||
WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
|
WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("UserManager", "Deleting character %i", charID);
|
Game::logger->Log("UserManager", "Deleting character %i", charID);
|
||||||
@@ -423,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
stmt->execute();
|
stmt->execute();
|
||||||
delete stmt;
|
delete stmt;
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
|
||||||
bitStream.Write(objectID);
|
bitStream.Write(objectID);
|
||||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
}
|
}
|
||||||
@@ -483,7 +482,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID objectID = PacketUtils::ReadPacketS64(8, packet);
|
LWOOBJID objectID = PacketUtils::ReadS64(8, packet);
|
||||||
GeneralUtils::ClearBit(objectID, eObjectBits::CHARACTER);
|
GeneralUtils::ClearBit(objectID, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT);
|
GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
@@ -495,16 +494,24 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
Character* character = nullptr;
|
Character* character = nullptr;
|
||||||
|
|
||||||
//Check if this user has this character:
|
//Check if this user has this character:
|
||||||
bool hasCharacter = false;
|
bool ownsCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
||||||
std::vector<Character*>& characters = u->GetCharacters();
|
objectID,
|
||||||
for (size_t i = 0; i < characters.size(); ++i) {
|
sysAddr,
|
||||||
if (characters[i]->GetID() == charID) { hasCharacter = true; character = characters[i]; }
|
CheckType::User,
|
||||||
}
|
"User %i tried to rename a character that it does not own!",
|
||||||
|
u->GetAccountID());
|
||||||
|
|
||||||
if (!hasCharacter || !character) {
|
std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) {
|
||||||
Game::logger->Log("UserManager", "User %i tried to rename a character that it does not own!", u->GetAccountID());
|
if (c->GetID() == charID) {
|
||||||
|
character = c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ownsCharacter || !character) {
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
|
||||||
} else if (hasCharacter && character) {
|
} else if (ownsCharacter && character) {
|
||||||
if (newName == character->GetName()) {
|
if (newName == character->GetName()) {
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -20,134 +20,114 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetCount > this->m_maxTargets) {
|
if (this->m_useTargetPosition && branch.target == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
|
if (targetCount == 0){
|
||||||
|
PlayFx(u"miss", context->originator);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> targets;
|
if (targetCount > this->m_maxTargets) {
|
||||||
|
Game::logger->Log("AreaOfEffectBehavior", "Serialized size is greater than max targets! Size: %i, Max: %i", targetCount, this->m_maxTargets);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto caster = context->caster;
|
||||||
|
if (this->m_useTargetAsCaster) context->caster = branch.target;
|
||||||
|
|
||||||
|
std::vector<LWOOBJID> targets;
|
||||||
targets.reserve(targetCount);
|
targets.reserve(targetCount);
|
||||||
|
|
||||||
for (auto i = 0u; i < targetCount; ++i) {
|
for (auto i = 0u; i < targetCount; ++i) {
|
||||||
LWOOBJID target{};
|
LWOOBJID target{};
|
||||||
|
|
||||||
if (!bitStream->Read(target)) {
|
if (!bitStream->Read(target)) {
|
||||||
Game::logger->Log("AreaOfEffectBehavior", "failed to read in target %i from bitStream, aborting target Handle!", i);
|
Game::logger->Log("AreaOfEffectBehavior", "failed to read in target %i from bitStream, aborting target Handle!", i);
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto target : targets) {
|
for (auto target : targets) {
|
||||||
branch.target = target;
|
branch.target = target;
|
||||||
|
|
||||||
this->m_action->Handle(context, bitStream, branch);
|
this->m_action->Handle(context, bitStream, branch);
|
||||||
}
|
}
|
||||||
|
context->caster = caster;
|
||||||
|
PlayFx(u"cast", context->originator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* self = Game::entityManager->GetEntity(context->caster);
|
auto* caster = Game::entityManager->GetEntity(context->caster);
|
||||||
if (self == nullptr) {
|
if (!caster) return;
|
||||||
Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator);
|
|
||||||
|
|
||||||
return;
|
// determine the position we are casting the AOE from
|
||||||
|
auto reference = branch.isProjectile ? branch.referencePosition : caster->GetPosition();
|
||||||
|
if (this->m_useTargetPosition) {
|
||||||
|
if (branch.target == LWOOBJID_EMPTY) return;
|
||||||
|
auto branchTarget = Game::entityManager->GetEntity(branch.target);
|
||||||
|
if (branchTarget) reference = branchTarget->GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reference = branch.isProjectile ? branch.referencePosition : self->GetPosition();
|
reference += this->m_offset;
|
||||||
|
|
||||||
std::vector<Entity*> targets;
|
std::vector<Entity*> targets {};
|
||||||
|
targets = Game::entityManager->GetEntitiesByProximity(reference, this->m_radius);
|
||||||
auto* presetTarget = Game::entityManager->GetEntity(branch.target);
|
context->FilterTargets(targets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
||||||
|
|
||||||
if (presetTarget != nullptr) {
|
|
||||||
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition())) {
|
|
||||||
targets.push_back(presetTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t includeFaction = m_includeFaction;
|
|
||||||
|
|
||||||
if (self->GetLOT() == 14466) // TODO: Fix edge case
|
|
||||||
{
|
|
||||||
includeFaction = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets all of the valid targets, passing in if should target enemies and friends
|
|
||||||
for (auto validTarget : context->GetValidTargets(m_ignoreFaction, includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) {
|
|
||||||
auto* entity = Game::entityManager->GetEntity(validTarget);
|
|
||||||
|
|
||||||
if (entity == nullptr) {
|
|
||||||
Game::logger->Log("AreaOfEffectBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(targets.begin(), targets.end(), entity) != targets.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
|
||||||
|
|
||||||
if (destroyableComponent == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (destroyableComponent->HasFaction(m_ignoreFaction)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto distance = Vector3::DistanceSquared(reference, entity->GetPosition());
|
|
||||||
|
|
||||||
if (this->m_radius * this->m_radius >= distance && (this->m_maxTargets == 0 || targets.size() < this->m_maxTargets)) {
|
|
||||||
targets.push_back(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// sort by distance
|
||||||
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b) {
|
std::sort(targets.begin(), targets.end(), [reference](Entity* a, Entity* b) {
|
||||||
const auto aDistance = Vector3::DistanceSquared(a->GetPosition(), reference);
|
const auto aDistance = NiPoint3::Distance(a->GetPosition(), reference);
|
||||||
const auto bDistance = Vector3::DistanceSquared(b->GetPosition(), reference);
|
const auto bDistance = NiPoint3::Distance(b->GetPosition(), reference);
|
||||||
|
return aDistance < bDistance;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return aDistance > bDistance;
|
// resize if we have more than max targets allows
|
||||||
});
|
if (targets.size() > this->m_maxTargets) targets.resize(this->m_maxTargets);
|
||||||
|
|
||||||
const uint32_t size = targets.size();
|
bitStream->Write<uint32_t>(targets.size());
|
||||||
|
|
||||||
bitStream->Write(size);
|
if (targets.size() == 0) {
|
||||||
|
PlayFx(u"miss", context->originator);
|
||||||
if (size == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
|
context->foundTarget = true;
|
||||||
|
// write all the targets to the bitstream
|
||||||
|
for (auto* target : targets) {
|
||||||
|
bitStream->Write(target->GetObjectID());
|
||||||
|
}
|
||||||
|
|
||||||
context->foundTarget = true;
|
// then cast all the actions
|
||||||
|
for (auto* target : targets) {
|
||||||
for (auto* target : targets) {
|
branch.target = target->GetObjectID();
|
||||||
bitStream->Write(target->GetObjectID());
|
this->m_action->Calculate(context, bitStream, branch);
|
||||||
|
}
|
||||||
PlayFx(u"cast", context->originator, target->GetObjectID());
|
PlayFx(u"cast", context->originator);
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* target : targets) {
|
|
||||||
branch.target = target->GetObjectID();
|
|
||||||
|
|
||||||
this->m_action->Calculate(context, bitStream, branch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AreaOfEffectBehavior::Load() {
|
void AreaOfEffectBehavior::Load() {
|
||||||
this->m_action = GetAction("action");
|
this->m_action = GetAction("action"); // required
|
||||||
|
this->m_radius = GetFloat("radius", 0.0f); // required
|
||||||
|
this->m_maxTargets = GetInt("max targets", 100);
|
||||||
|
if (this->m_maxTargets == 0) this->m_maxTargets = 100;
|
||||||
|
this->m_useTargetPosition = GetBoolean("use_target_position", false);
|
||||||
|
this->m_useTargetAsCaster = GetBoolean("use_target_as_caster", false);
|
||||||
|
this->m_offset = NiPoint3(
|
||||||
|
GetFloat("offset_x", 0.0f),
|
||||||
|
GetFloat("offset_y", 0.0f),
|
||||||
|
GetFloat("offset_z", 0.0f)
|
||||||
|
);
|
||||||
|
|
||||||
this->m_radius = GetFloat("radius");
|
// params after this are needed for filter targets
|
||||||
|
const auto parameters = GetParameterNames();
|
||||||
this->m_maxTargets = GetInt("max targets");
|
for (const auto& parameter : parameters) {
|
||||||
|
if (parameter.first.rfind("include_faction", 0) == 0) {
|
||||||
this->m_ignoreFaction = GetInt("ignore_faction");
|
this->m_includeFactionList.push_front(parameter.second);
|
||||||
|
} else if (parameter.first.rfind("ignore_faction", 0) == 0) {
|
||||||
this->m_includeFaction = GetInt("include_faction");
|
this->m_ignoreFactionList.push_front(parameter.second);
|
||||||
|
}
|
||||||
this->m_TargetSelf = GetInt("target_self");
|
}
|
||||||
|
this->m_targetSelf = GetBoolean("target_self", false);
|
||||||
this->m_targetEnemy = GetInt("target_enemy");
|
this->m_targetEnemy = GetBoolean("target_enemy", false);
|
||||||
|
this->m_targetFriend = GetBoolean("target_friend", false);
|
||||||
this->m_targetFriend = GetInt("target_friend");
|
this->m_targetTeam = GetBoolean("target_team", false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Behavior.h"
|
#include "Behavior.h"
|
||||||
|
#include <forward_list>
|
||||||
|
|
||||||
class AreaOfEffectBehavior final : public Behavior
|
class AreaOfEffectBehavior final : public Behavior
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Behavior* m_action;
|
explicit AreaOfEffectBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {}
|
||||||
|
|
||||||
uint32_t m_maxTargets;
|
|
||||||
|
|
||||||
float m_radius;
|
|
||||||
|
|
||||||
int32_t m_ignoreFaction;
|
|
||||||
|
|
||||||
int32_t m_includeFaction;
|
|
||||||
|
|
||||||
int32_t m_TargetSelf;
|
|
||||||
|
|
||||||
int32_t m_targetEnemy;
|
|
||||||
|
|
||||||
int32_t m_targetFriend;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Inherited
|
|
||||||
*/
|
|
||||||
explicit AreaOfEffectBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
|
||||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
|
||||||
void Load() override;
|
void Load() override;
|
||||||
|
private:
|
||||||
|
Behavior* m_action;
|
||||||
|
uint32_t m_maxTargets;
|
||||||
|
float m_radius;
|
||||||
|
bool m_useTargetPosition;
|
||||||
|
bool m_useTargetAsCaster;
|
||||||
|
NiPoint3 m_offset;
|
||||||
|
|
||||||
|
std::forward_list<int32_t> m_ignoreFactionList {};
|
||||||
|
std::forward_list<int32_t> m_includeFactionList {};
|
||||||
|
bool m_targetSelf;
|
||||||
|
bool m_targetEnemy;
|
||||||
|
bool m_targetFriend;
|
||||||
|
bool m_targetTeam;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
|
|||||||
case BehaviorTemplates::BEHAVIOR_SPEED:
|
case BehaviorTemplates::BEHAVIOR_SPEED:
|
||||||
behavior = new SpeedBehavior(behaviorId);
|
behavior = new SpeedBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
|
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
|
||||||
behavior = new DarkInspirationBehavior(behaviorId);
|
behavior = new DarkInspirationBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
|
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "PacketUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "PhantomPhysicsComponent.h"
|
#include "PhantomPhysicsComponent.h"
|
||||||
#include "RebuildComponent.h"
|
#include "RebuildComponent.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
#include "TeamManager.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
|
|
||||||
BehaviorSyncEntry::BehaviorSyncEntry() {
|
BehaviorSyncEntry::BehaviorSyncEntry() {
|
||||||
@@ -253,7 +254,7 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime) {
|
|||||||
// Write message
|
// Write message
|
||||||
RakNet::BitStream message;
|
RakNet::BitStream message;
|
||||||
|
|
||||||
PacketUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
message.Write(this->originator);
|
message.Write(this->originator);
|
||||||
echo.Serialize(&message);
|
echo.Serialize(&message);
|
||||||
|
|
||||||
@@ -307,46 +308,123 @@ void BehaviorContext::Reset() {
|
|||||||
this->scheduledUpdates.clear();
|
this->scheduledUpdates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction, bool targetSelf, bool targetEnemy, bool targetFriend) const {
|
void BehaviorContext::FilterTargets(std::vector<Entity*>& targets, std::forward_list<int32_t>& ignoreFactionList, std::forward_list<int32_t>& includeFactionList, bool targetSelf, bool targetEnemy, bool targetFriend, bool targetTeam) const {
|
||||||
auto* entity = Game::entityManager->GetEntity(this->caster);
|
|
||||||
|
|
||||||
std::vector<LWOOBJID> targets;
|
// if we aren't targeting anything, then clear the targets vector
|
||||||
|
if (!targetSelf && !targetEnemy && !targetFriend && !targetTeam && ignoreFactionList.empty() && includeFactionList.empty()) {
|
||||||
if (entity == nullptr) {
|
targets.clear();
|
||||||
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!", this->originator);
|
return;
|
||||||
|
|
||||||
return targets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignoreFaction && !includeFaction) {
|
// if the caster is not there, return empty targets list
|
||||||
for (auto entry : entity->GetTargetsInPhantom()) {
|
auto* caster = Game::entityManager->GetEntity(this->caster);
|
||||||
auto* instance = Game::entityManager->GetEntity(entry);
|
if (!caster) {
|
||||||
|
Game::logger->LogDebug("BehaviorContext", "Invalid caster for (%llu)!", this->originator);
|
||||||
if (instance == nullptr) {
|
targets.clear();
|
||||||
continue;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
targets.push_back(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ignoreFaction || includeFaction || (!entity->HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) && targets.empty())) {
|
auto index = targets.begin();
|
||||||
DestroyableComponent* destroyableComponent;
|
while (index != targets.end()) {
|
||||||
if (!entity->TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) {
|
auto candidate = *index;
|
||||||
return targets;
|
|
||||||
|
// make sure we don't have a nullptr
|
||||||
|
if (!candidate) {
|
||||||
|
index = targets.erase(index);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
// handle targeting the caster
|
||||||
for (auto* candidate : entities) {
|
if (candidate == caster){
|
||||||
const auto id = candidate->GetObjectID();
|
// if we aren't targeting self, erase, otherise increment and continue
|
||||||
|
if (!targetSelf) index = targets.erase(index);
|
||||||
|
else index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ((id != entity->GetObjectID() || targetSelf) && destroyableComponent->CheckValidity(id, ignoreFaction || includeFaction, targetEnemy, targetFriend)) {
|
// make sure that the entity is targetable
|
||||||
targets.push_back(id);
|
if (!CheckTargetingRequirements(candidate)) {
|
||||||
|
index = targets.erase(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get factions to check against
|
||||||
|
// CheckTargetingRequirements checks for a destroyable component
|
||||||
|
// but we check again because bounds check are necessary
|
||||||
|
auto candidateDestroyableComponent = candidate->GetComponent<DestroyableComponent>();
|
||||||
|
if (!candidateDestroyableComponent) {
|
||||||
|
index = targets.erase(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if they are dead, then earse and continue
|
||||||
|
if (candidateDestroyableComponent->GetIsDead()){
|
||||||
|
index = targets.erase(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if their faction is explicitly included, increment and continue
|
||||||
|
auto candidateFactions = candidateDestroyableComponent->GetFactionIDs();
|
||||||
|
if (CheckFactionList(includeFactionList, candidateFactions)){
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if they are a team member
|
||||||
|
if (targetTeam){
|
||||||
|
auto* team = TeamManager::Instance()->GetTeam(this->caster);
|
||||||
|
if (team){
|
||||||
|
// if we find a team member keep it and continue to skip enemy checks
|
||||||
|
if(std::find(team->members.begin(), team->members.end(), candidate->GetObjectID()) != team->members.end()){
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return targets;
|
// if the caster doesn't have a destroyable component, return an empty targets list
|
||||||
|
auto* casterDestroyableComponent = caster->GetComponent<DestroyableComponent>();
|
||||||
|
if (!casterDestroyableComponent) {
|
||||||
|
targets.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we arent targeting a friend, and they are a friend OR
|
||||||
|
// if we are not targeting enemies and they are an enemy OR.
|
||||||
|
// if we are ignoring their faction is explicitly ignored
|
||||||
|
// erase and continue
|
||||||
|
auto isEnemy = casterDestroyableComponent->IsEnemy(candidate);
|
||||||
|
if ((!targetFriend && !isEnemy) ||
|
||||||
|
(!targetEnemy && isEnemy) ||
|
||||||
|
CheckFactionList(ignoreFactionList, candidateFactions)) {
|
||||||
|
index = targets.erase(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// some basic checks as well as the check that matters for this: if the quickbuild is complete
|
||||||
|
bool BehaviorContext::CheckTargetingRequirements(const Entity* target) const {
|
||||||
|
// if the target is a nullptr, then it's not valid
|
||||||
|
if (!target) return false;
|
||||||
|
|
||||||
|
// ignore quickbuilds that aren't completed
|
||||||
|
auto* targetQuickbuildComponent = target->GetComponent<RebuildComponent>();
|
||||||
|
if (targetQuickbuildComponent && targetQuickbuildComponent->GetState() != eRebuildState::COMPLETED) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if any of the object factions are in the faction list
|
||||||
|
bool BehaviorContext::CheckFactionList(std::forward_list<int32_t>& factionList, std::vector<int32_t>& objectsFactions) const {
|
||||||
|
if (factionList.empty() || objectsFactions.empty()) return false;
|
||||||
|
for (auto faction : factionList){
|
||||||
|
if(std::find(objectsFactions.begin(), objectsFactions.end(), faction) != objectsFactions.end()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <forward_list>
|
||||||
|
|
||||||
class Behavior;
|
class Behavior;
|
||||||
|
|
||||||
@@ -106,7 +107,11 @@ struct BehaviorContext
|
|||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
std::vector<LWOOBJID> GetValidTargets(int32_t ignoreFaction = 0, int32_t includeFaction = 0, const bool targetSelf = false, const bool targetEnemy = true, const bool targetFriend = false) const;
|
void FilterTargets(std::vector<Entity*>& targetsReference, std::forward_list<int32_t>& ignoreFaction, std::forward_list<int32_t>& includeFaction, const bool targetSelf = false, const bool targetEnemy = true, const bool targetFriend = false, const bool targetTeam = false) const;
|
||||||
|
|
||||||
|
bool CheckTargetingRequirements(const Entity* target) const;
|
||||||
|
|
||||||
|
bool CheckFactionList(std::forward_list<int32_t>& factionList, std::vector<int32_t>& objectsFactions) const;
|
||||||
|
|
||||||
explicit BehaviorContext(LWOOBJID originator, bool calculation = false);
|
explicit BehaviorContext(LWOOBJID originator, bool calculation = false);
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifndef BEHAVIORSLOT_H
|
#ifndef BEHAVIORSLOT_H
|
||||||
#define BEHAVIORSLOT_H
|
#define BEHAVIORSLOT_H
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
enum class BehaviorSlot
|
enum class BehaviorSlot : int32_t {
|
||||||
{
|
|
||||||
Invalid = -1,
|
Invalid = -1,
|
||||||
Primary,
|
Primary,
|
||||||
Offhand,
|
Offhand,
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ void OverTimeBehavior::Load() {
|
|||||||
// Since m_Action is a skillID and not a behavior, get is correlated behaviorID.
|
// Since m_Action is a skillID and not a behavior, get is correlated behaviorID.
|
||||||
|
|
||||||
CDSkillBehaviorTable* skillTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
CDSkillBehaviorTable* skillTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||||
auto skillData = skillTable->GetSkillByID(m_Action);
|
m_ActionBehaviorId = skillTable->GetSkillByID(m_Action).behaviorID;
|
||||||
if (skillData) m_ActionBehaviorId = skillData->behaviorID;
|
|
||||||
|
|
||||||
m_Delay = GetFloat("delay");
|
m_Delay = GetFloat("delay");
|
||||||
m_NumIntervals = GetInt("num_intervals");
|
m_NumIntervals = GetInt("num_intervals");
|
||||||
|
|||||||
@@ -12,16 +12,24 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
if (this->m_targetEnemy && this->m_usePickedTarget && branch.target > 0) {
|
std::vector<Entity*> targets = {};
|
||||||
this->m_action->Handle(context, bitStream, branch);
|
|
||||||
|
|
||||||
return;
|
if (this->m_usePickedTarget && branch.target != LWOOBJID_EMPTY) {
|
||||||
|
auto target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
if (!target) Game::logger->Log("TacArcBehavior", "target %llu is null", branch.target);
|
||||||
|
else {
|
||||||
|
targets.push_back(target);
|
||||||
|
context->FilterTargets(targets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
||||||
|
if (!targets.empty()) {
|
||||||
|
this->m_action->Handle(context, bitStream, branch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hit = false;
|
bool hasTargets = false;
|
||||||
|
if (!bitStream->Read(hasTargets)) {
|
||||||
if (!bitStream->Read(hit)) {
|
Game::logger->Log("TacArcBehavior", "Unable to read hasTargets from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
|
||||||
Game::logger->Log("TacArcBehavior", "Unable to read hit from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,26 +43,23 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
|
|||||||
|
|
||||||
if (blocked) {
|
if (blocked) {
|
||||||
this->m_blockedAction->Handle(context, bitStream, branch);
|
this->m_blockedAction->Handle(context, bitStream, branch);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit) {
|
if (hasTargets) {
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
|
||||||
if (!bitStream->Read(count)) {
|
if (!bitStream->Read(count)) {
|
||||||
Game::logger->Log("TacArcBehavior", "Unable to read count from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
|
Game::logger->Log("TacArcBehavior", "Unable to read count from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits());
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (count > m_maxTargets && m_maxTargets > 0) {
|
if (count > m_maxTargets) {
|
||||||
count = m_maxTargets;
|
Game::logger->Log("TacArcBehavior", "Bitstream has too many targets Max:%i Recv:%i", this->m_maxTargets, count);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> targets;
|
for (auto i = 0u; i < count; i++) {
|
||||||
|
|
||||||
for (auto i = 0u; i < count; ++i) {
|
|
||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
|
|
||||||
if (!bitStream->Read(id)) {
|
if (!bitStream->Read(id)) {
|
||||||
@@ -62,17 +67,19 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
targets.push_back(id);
|
if (id != LWOOBJID_EMPTY) {
|
||||||
|
auto* canidate = Game::entityManager->GetEntity(id);
|
||||||
|
if (canidate) targets.push_back(canidate);
|
||||||
|
} else {
|
||||||
|
Game::logger->Log("TacArcBehavior", "Bitstream has LWOOBJID_EMPTY as a target!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto target : targets) {
|
for (auto target : targets) {
|
||||||
branch.target = target;
|
branch.target = target->GetObjectID();
|
||||||
|
|
||||||
this->m_action->Handle(context, bitStream, branch);
|
this->m_action->Handle(context, bitStream, branch);
|
||||||
}
|
}
|
||||||
} else {
|
} else this->m_missAction->Handle(context, bitStream, branch);
|
||||||
this->m_missAction->Handle(context, bitStream, branch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
@@ -82,23 +89,15 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
std::vector<Entity*> targets = {};
|
||||||
|
if (this->m_usePickedTarget && branch.target != LWOOBJID_EMPTY) {
|
||||||
if ((this->m_usePickedTarget || context->clientInitalized) && branch.target > 0) {
|
auto target = Game::entityManager->GetEntity(branch.target);
|
||||||
const auto* target = Game::entityManager->GetEntity(branch.target);
|
targets.push_back(target);
|
||||||
|
context->FilterTargets(targets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
||||||
if (target == nullptr) {
|
if (!targets.empty()) {
|
||||||
|
this->m_action->Handle(context, bitStream, branch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the game is specific about who to target, check that
|
|
||||||
if (destroyableComponent == nullptr || ((!m_targetFriend && !m_targetEnemy
|
|
||||||
|| m_targetFriend && destroyableComponent->IsFriend(target)
|
|
||||||
|| m_targetEnemy && destroyableComponent->IsEnemy(target)))) {
|
|
||||||
this->m_action->Calculate(context, bitStream, branch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* combatAi = self->GetComponent<BaseCombatAIComponent>();
|
auto* combatAi = self->GetComponent<BaseCombatAIComponent>();
|
||||||
@@ -107,50 +106,25 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
|
|
||||||
auto reference = self->GetPosition(); //+ m_offset;
|
auto reference = self->GetPosition(); //+ m_offset;
|
||||||
|
|
||||||
std::vector<Entity*> targets;
|
targets.clear();
|
||||||
|
|
||||||
std::vector<LWOOBJID> validTargets;
|
std::vector<Entity*> validTargets = Game::entityManager->GetEntitiesByProximity(reference, this->m_maxRange);
|
||||||
|
|
||||||
if (combatAi != nullptr) {
|
// filter all valid targets, based on whether we target enemies or friends
|
||||||
if (combatAi->GetTarget() != LWOOBJID_EMPTY) {
|
context->FilterTargets(validTargets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
||||||
validTargets.push_back(combatAi->GetTarget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all valid targets, based on whether we target enemies or friends
|
|
||||||
for (const auto& contextTarget : context->GetValidTargets()) {
|
|
||||||
if (destroyableComponent != nullptr) {
|
|
||||||
const auto* targetEntity = Game::entityManager->GetEntity(contextTarget);
|
|
||||||
|
|
||||||
if (m_targetEnemy && destroyableComponent->IsEnemy(targetEntity)
|
|
||||||
|| m_targetFriend && destroyableComponent->IsFriend(targetEntity)) {
|
|
||||||
validTargets.push_back(contextTarget);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
validTargets.push_back(contextTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto validTarget : validTargets) {
|
for (auto validTarget : validTargets) {
|
||||||
if (targets.size() >= this->m_maxTargets) {
|
if (targets.size() >= this->m_maxTargets) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = Game::entityManager->GetEntity(validTarget);
|
if (std::find(targets.begin(), targets.end(), validTarget) != targets.end()) {
|
||||||
|
|
||||||
if (entity == nullptr) {
|
|
||||||
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(targets.begin(), targets.end(), entity) != targets.end()) {
|
if (validTarget->GetIsDead()) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->GetIsDead()) continue;
|
const auto otherPosition = validTarget->GetPosition();
|
||||||
|
|
||||||
const auto otherPosition = entity->GetPosition();
|
|
||||||
|
|
||||||
const auto heightDifference = std::abs(otherPosition.y - casterPosition.y);
|
const auto heightDifference = std::abs(otherPosition.y - casterPosition.y);
|
||||||
|
|
||||||
@@ -180,8 +154,8 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
|
|
||||||
const float degreeAngle = std::abs(Vector3::Angle(forward, normalized) * (180 / 3.14) - 180);
|
const float degreeAngle = std::abs(Vector3::Angle(forward, normalized) * (180 / 3.14) - 180);
|
||||||
|
|
||||||
if (distance >= this->m_minDistance && this->m_maxDistance >= distance && degreeAngle <= 2 * this->m_angle) {
|
if (distance >= this->m_minRange && this->m_maxRange >= distance && degreeAngle <= 2 * this->m_angle) {
|
||||||
targets.push_back(entity);
|
targets.push_back(validTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,43 +202,48 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TacArcBehavior::Load() {
|
void TacArcBehavior::Load() {
|
||||||
this->m_usePickedTarget = GetBoolean("use_picked_target");
|
this->m_maxRange = GetFloat("max range");
|
||||||
|
this->m_height = GetFloat("height", 2.2f);
|
||||||
|
this->m_distanceWeight = GetFloat("distance_weight", 0.0f);
|
||||||
|
this->m_angleWeight = GetFloat("angle_weight", 0.0f);
|
||||||
|
this->m_angle = GetFloat("angle", 45.0f);
|
||||||
|
this->m_minRange = GetFloat("min range", 0.0f);
|
||||||
|
this->m_offset = NiPoint3(
|
||||||
|
GetFloat("offset_x", 0.0f),
|
||||||
|
GetFloat("offset_y", 0.0f),
|
||||||
|
GetFloat("offset_z", 0.0f)
|
||||||
|
);
|
||||||
|
this->m_method = GetInt("method", 1);
|
||||||
|
this->m_upperBound = GetFloat("upper_bound", 4.4f);
|
||||||
|
this->m_lowerBound = GetFloat("lower_bound", 0.4f);
|
||||||
|
this->m_usePickedTarget = GetBoolean("use_picked_target", false);
|
||||||
|
this->m_useTargetPostion = GetBoolean("use_target_position", false);
|
||||||
|
this->m_checkEnv = GetBoolean("check_env", false);
|
||||||
|
this->m_useAttackPriority = GetBoolean("use_attack_priority", false);
|
||||||
|
|
||||||
this->m_action = GetAction("action");
|
this->m_action = GetAction("action");
|
||||||
|
|
||||||
this->m_missAction = GetAction("miss action");
|
this->m_missAction = GetAction("miss action");
|
||||||
|
|
||||||
this->m_checkEnv = GetBoolean("check_env");
|
|
||||||
|
|
||||||
this->m_blockedAction = GetAction("blocked action");
|
this->m_blockedAction = GetAction("blocked action");
|
||||||
|
|
||||||
this->m_minDistance = GetFloat("min range");
|
this->m_maxTargets = GetInt("max targets", 100);
|
||||||
|
if (this->m_maxTargets == 0) this->m_maxTargets = 100;
|
||||||
|
|
||||||
this->m_maxDistance = GetFloat("max range");
|
this->m_farHeight = GetFloat("far_height", 5.0f);
|
||||||
|
this->m_farWidth = GetFloat("far_width", 5.0f);
|
||||||
|
this->m_nearHeight = GetFloat("near_height", 5.0f);
|
||||||
|
this->m_nearWidth = GetFloat("near_width", 5.0f);
|
||||||
|
|
||||||
this->m_maxTargets = GetInt("max targets");
|
// params after this are needed for filter targets
|
||||||
|
const auto parameters = GetParameterNames();
|
||||||
this->m_targetEnemy = GetBoolean("target_enemy");
|
for (const auto& parameter : parameters) {
|
||||||
|
if (parameter.first.rfind("include_faction", 0) == 0) {
|
||||||
this->m_targetFriend = GetBoolean("target_friend");
|
this->m_includeFactionList.push_front(parameter.second);
|
||||||
|
} else if (parameter.first.rfind("ignore_faction", 0) == 0) {
|
||||||
this->m_targetTeam = GetBoolean("target_team");
|
this->m_ignoreFactionList.push_front(parameter.second);
|
||||||
|
}
|
||||||
this->m_angle = GetFloat("angle");
|
}
|
||||||
|
this->m_targetSelf = GetBoolean("target_caster", false);
|
||||||
this->m_upperBound = GetFloat("upper_bound");
|
this->m_targetEnemy = GetBoolean("target_enemy", false);
|
||||||
|
this->m_targetFriend = GetBoolean("target_friend", false);
|
||||||
this->m_lowerBound = GetFloat("lower_bound");
|
this->m_targetTeam = GetBoolean("target_team", false);
|
||||||
|
|
||||||
this->m_farHeight = GetFloat("far_height");
|
|
||||||
|
|
||||||
this->m_farWidth = GetFloat("far_width");
|
|
||||||
|
|
||||||
this->m_method = GetInt("method");
|
|
||||||
|
|
||||||
this->m_offset = {
|
|
||||||
GetFloat("offset_x"),
|
|
||||||
GetFloat("offset_y"),
|
|
||||||
GetFloat("offset_z")
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,56 +2,42 @@
|
|||||||
#include "Behavior.h"
|
#include "Behavior.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
#include <forward_list>
|
||||||
|
|
||||||
class TacArcBehavior final : public Behavior
|
class TacArcBehavior final : public Behavior {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
bool m_usePickedTarget;
|
explicit TacArcBehavior(const uint32_t behavior_id) : Behavior(behavior_id) {}
|
||||||
|
|
||||||
Behavior* m_action;
|
|
||||||
|
|
||||||
bool m_checkEnv;
|
|
||||||
|
|
||||||
Behavior* m_missAction;
|
|
||||||
|
|
||||||
Behavior* m_blockedAction;
|
|
||||||
|
|
||||||
float m_minDistance;
|
|
||||||
|
|
||||||
float m_maxDistance;
|
|
||||||
|
|
||||||
uint32_t m_maxTargets;
|
|
||||||
|
|
||||||
bool m_targetEnemy;
|
|
||||||
|
|
||||||
bool m_targetFriend;
|
|
||||||
|
|
||||||
bool m_targetTeam;
|
|
||||||
|
|
||||||
float m_angle;
|
|
||||||
|
|
||||||
float m_upperBound;
|
|
||||||
|
|
||||||
float m_lowerBound;
|
|
||||||
|
|
||||||
float m_farHeight;
|
|
||||||
|
|
||||||
float m_farWidth;
|
|
||||||
|
|
||||||
uint32_t m_method;
|
|
||||||
|
|
||||||
NiPoint3 m_offset;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Inherited
|
|
||||||
*/
|
|
||||||
|
|
||||||
explicit TacArcBehavior(const uint32_t behavior_id) : Behavior(behavior_id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
|
||||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
|
||||||
void Load() override;
|
void Load() override;
|
||||||
|
private:
|
||||||
|
float m_maxRange;
|
||||||
|
float m_height;
|
||||||
|
float m_distanceWeight;
|
||||||
|
float m_angleWeight;
|
||||||
|
float m_angle;
|
||||||
|
float m_minRange;
|
||||||
|
NiPoint3 m_offset;
|
||||||
|
uint32_t m_method;
|
||||||
|
float m_upperBound;
|
||||||
|
float m_lowerBound;
|
||||||
|
bool m_usePickedTarget;
|
||||||
|
bool m_useTargetPostion;
|
||||||
|
bool m_checkEnv;
|
||||||
|
bool m_useAttackPriority;
|
||||||
|
Behavior* m_action;
|
||||||
|
Behavior* m_missAction;
|
||||||
|
Behavior* m_blockedAction;
|
||||||
|
uint32_t m_maxTargets;
|
||||||
|
float m_farHeight;
|
||||||
|
float m_farWidth;
|
||||||
|
float m_nearHeight;
|
||||||
|
float m_nearWidth;
|
||||||
|
|
||||||
|
std::forward_list<int32_t> m_ignoreFactionList {};
|
||||||
|
std::forward_list<int32_t> m_includeFactionList {};
|
||||||
|
bool m_targetSelf;
|
||||||
|
bool m_targetEnemy;
|
||||||
|
bool m_targetFriend;
|
||||||
|
bool m_targetTeam;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
|||||||
// Speed towards start position
|
// Speed towards start position
|
||||||
if (m_MovementAI != nullptr) {
|
if (m_MovementAI != nullptr) {
|
||||||
m_MovementAI->SetHaltDistance(0);
|
m_MovementAI->SetHaltDistance(0);
|
||||||
m_MovementAI->SetSpeed(m_PursuitSpeed);
|
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
|
||||||
m_MovementAI->SetDestination(m_StartPosition);
|
m_MovementAI->SetDestination(m_StartPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,8 +382,6 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID BaseCombatAIComponent::FindTarget() {
|
LWOOBJID BaseCombatAIComponent::FindTarget() {
|
||||||
//const auto reference = m_MovementAI == nullptr ? m_StartPosition : m_MovementAI->ApproximateLocation();
|
|
||||||
|
|
||||||
NiPoint3 reference = m_StartPosition;
|
NiPoint3 reference = m_StartPosition;
|
||||||
|
|
||||||
if (m_MovementAI) reference = m_MovementAI->ApproximateLocation();
|
if (m_MovementAI) reference = m_MovementAI->ApproximateLocation();
|
||||||
@@ -522,7 +520,7 @@ bool BaseCombatAIComponent::IsMech() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write(m_DirtyStateOrTarget || bIsInitialUpdate);
|
outBitStream->Write(m_DirtyStateOrTarget || bIsInitialUpdate);
|
||||||
if (m_DirtyStateOrTarget || bIsInitialUpdate) {
|
if (m_DirtyStateOrTarget || bIsInitialUpdate) {
|
||||||
outBitStream->Write(uint32_t(m_State));
|
outBitStream->Write(uint32_t(m_State));
|
||||||
@@ -660,17 +658,17 @@ void BaseCombatAIComponent::Wander() {
|
|||||||
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination);
|
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vector3::DistanceSquared(destination, m_MovementAI->GetCurrentPosition()) < 2 * 2) {
|
if (Vector3::DistanceSquared(destination, m_MovementAI->GetParent()->GetPosition()) < 2 * 2) {
|
||||||
m_MovementAI->Stop();
|
m_MovementAI->Stop();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_MovementAI->SetSpeed(m_TetherSpeed);
|
m_MovementAI->SetMaxSpeed(m_TetherSpeed);
|
||||||
|
|
||||||
m_MovementAI->SetDestination(destination);
|
m_MovementAI->SetDestination(destination);
|
||||||
|
|
||||||
m_Timer += (m_MovementAI->GetCurrentPosition().x - destination.x) / m_TetherSpeed;
|
m_Timer += (m_MovementAI->GetParent()->GetPosition().x - destination.x) / m_TetherSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseCombatAIComponent::OnAggro() {
|
void BaseCombatAIComponent::OnAggro() {
|
||||||
@@ -685,21 +683,21 @@ void BaseCombatAIComponent::OnAggro() {
|
|||||||
m_MovementAI->SetHaltDistance(m_AttackRadius);
|
m_MovementAI->SetHaltDistance(m_AttackRadius);
|
||||||
|
|
||||||
NiPoint3 targetPos = target->GetPosition();
|
NiPoint3 targetPos = target->GetPosition();
|
||||||
NiPoint3 currentPos = m_MovementAI->GetCurrentPosition();
|
NiPoint3 currentPos = m_MovementAI->GetParent()->GetPosition();
|
||||||
|
|
||||||
// If the player's position is within range, attack
|
// If the player's position is within range, attack
|
||||||
if (Vector3::DistanceSquared(currentPos, targetPos) <= m_AttackRadius * m_AttackRadius) {
|
if (Vector3::DistanceSquared(currentPos, targetPos) <= m_AttackRadius * m_AttackRadius) {
|
||||||
m_MovementAI->Stop();
|
m_MovementAI->Stop();
|
||||||
} else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far
|
} else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far
|
||||||
{
|
{
|
||||||
m_MovementAI->SetSpeed(m_PursuitSpeed);
|
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
|
||||||
|
|
||||||
m_MovementAI->SetDestination(m_StartPosition);
|
m_MovementAI->SetDestination(m_StartPosition);
|
||||||
} else //Chase the player's new position
|
} else //Chase the player's new position
|
||||||
{
|
{
|
||||||
if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return;
|
if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return;
|
||||||
|
|
||||||
m_MovementAI->SetSpeed(m_PursuitSpeed);
|
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
|
||||||
|
|
||||||
m_MovementAI->SetDestination(targetPos);
|
m_MovementAI->SetDestination(targetPos);
|
||||||
|
|
||||||
@@ -725,7 +723,7 @@ void BaseCombatAIComponent::OnTether() {
|
|||||||
m_MovementAI->Stop();
|
m_MovementAI->Stop();
|
||||||
} else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far
|
} else if (Vector3::DistanceSquared(m_StartPosition, targetPos) > m_HardTetherRadius * m_HardTetherRadius) //Return to spawn if we're too far
|
||||||
{
|
{
|
||||||
m_MovementAI->SetSpeed(m_PursuitSpeed);
|
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
|
||||||
|
|
||||||
m_MovementAI->SetDestination(m_StartPosition);
|
m_MovementAI->SetDestination(m_StartPosition);
|
||||||
|
|
||||||
@@ -733,7 +731,7 @@ void BaseCombatAIComponent::OnTether() {
|
|||||||
} else {
|
} else {
|
||||||
if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return;
|
if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return;
|
||||||
|
|
||||||
m_MovementAI->SetSpeed(m_PursuitSpeed);
|
m_MovementAI->SetMaxSpeed(m_PursuitSpeed);
|
||||||
|
|
||||||
m_MovementAI->SetDestination(targetPos);
|
m_MovementAI->SetDestination(targetPos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
~BaseCombatAIComponent() override;
|
~BaseCombatAIComponent() override;
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current behavioral state of the enemy
|
* Get the current behavioral state of the enemy
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) {
|
|||||||
BouncerComponent::~BouncerComponent() {
|
BouncerComponent::~BouncerComponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write(m_PetEnabled);
|
outBitStream->Write(m_PetEnabled);
|
||||||
if (m_PetEnabled) {
|
if (m_PetEnabled) {
|
||||||
outBitStream->Write(m_PetBouncerEnabled);
|
outBitStream->Write(m_PetBouncerEnabled);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public:
|
|||||||
BouncerComponent(Entity* parentEntity);
|
BouncerComponent(Entity* parentEntity);
|
||||||
~BouncerComponent() override;
|
~BouncerComponent() override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
Entity* GetParentEntity() const;
|
Entity* GetParentEntity() const;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ BuffComponent::BuffComponent(Entity* parent) : Component(parent) {
|
|||||||
BuffComponent::~BuffComponent() {
|
BuffComponent::~BuffComponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
if (!bIsInitialUpdate) return;
|
if (!bIsInitialUpdate) return;
|
||||||
if (m_Buffs.empty()) {
|
if (m_Buffs.empty()) {
|
||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
@@ -104,12 +104,7 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO
|
|||||||
if (parameter.name == "overtime") {
|
if (parameter.name == "overtime") {
|
||||||
auto* behaviorTemplateTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
auto* behaviorTemplateTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||||
|
|
||||||
auto skillInfo = behaviorTemplateTable->GetSkillByID(parameter.values[0]);
|
behaviorID = behaviorTemplateTable->GetSkillByID(parameter.values[0]).behaviorID;
|
||||||
if (skillInfo) {
|
|
||||||
behaviorID = skillInfo->behaviorID;
|
|
||||||
} else {
|
|
||||||
Game::logger->Log("BuffComponent", "Failed to find skill info for skill ID %d!", parameter.values[0]);
|
|
||||||
}
|
|
||||||
stacks = static_cast<int32_t>(parameter.values[1]);
|
stacks = static_cast<int32_t>(parameter.values[1]);
|
||||||
tick = parameter.values[2];
|
tick = parameter.values[2];
|
||||||
const auto unknown2 = parameter.values[3]; // Always 0
|
const auto unknown2 = parameter.values[3]; // Always 0
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
|||||||
"Component.cpp"
|
"Component.cpp"
|
||||||
"ControllablePhysicsComponent.cpp"
|
"ControllablePhysicsComponent.cpp"
|
||||||
"DestroyableComponent.cpp"
|
"DestroyableComponent.cpp"
|
||||||
|
"DonationVendorComponent.cpp"
|
||||||
"InventoryComponent.cpp"
|
"InventoryComponent.cpp"
|
||||||
"LevelProgressionComponent.cpp"
|
"LevelProgressionComponent.cpp"
|
||||||
"LUPExhibitComponent.cpp"
|
"LUPExhibitComponent.cpp"
|
||||||
@@ -17,6 +18,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
|||||||
"MovingPlatformComponent.cpp"
|
"MovingPlatformComponent.cpp"
|
||||||
"PetComponent.cpp"
|
"PetComponent.cpp"
|
||||||
"PhantomPhysicsComponent.cpp"
|
"PhantomPhysicsComponent.cpp"
|
||||||
|
"PhysicsComponent.cpp"
|
||||||
"PlayerForcedMovementComponent.cpp"
|
"PlayerForcedMovementComponent.cpp"
|
||||||
"PossessableComponent.cpp"
|
"PossessableComponent.cpp"
|
||||||
"PossessorComponent.cpp"
|
"PossessorComponent.cpp"
|
||||||
@@ -30,7 +32,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
|||||||
"RebuildComponent.cpp"
|
"RebuildComponent.cpp"
|
||||||
"RenderComponent.cpp"
|
"RenderComponent.cpp"
|
||||||
"RigidbodyPhantomPhysicsComponent.cpp"
|
"RigidbodyPhantomPhysicsComponent.cpp"
|
||||||
"RocketLaunchLupComponent.cpp"
|
"MultiZoneEntranceComponent.cpp"
|
||||||
"RocketLaunchpadControlComponent.cpp"
|
"RocketLaunchpadControlComponent.cpp"
|
||||||
"ScriptedActivityComponent.cpp"
|
"ScriptedActivityComponent.cpp"
|
||||||
"ShootingGalleryComponent.cpp"
|
"ShootingGalleryComponent.cpp"
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
|||||||
CharacterComponent::~CharacterComponent() {
|
CharacterComponent::~CharacterComponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
|
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public:
|
|||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the rocket configuration using a LOT string separated by commas
|
* Updates the rocket configuration using a LOT string separated by commas
|
||||||
@@ -276,6 +276,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const;
|
void UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const;
|
||||||
|
|
||||||
|
void SetCurrentInteracting(LWOOBJID objectID) {m_CurrentInteracting = objectID;};
|
||||||
|
|
||||||
|
LWOOBJID GetCurrentInteracting() {return m_CurrentInteracting;};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Character info regarding this character, including clothing styles, etc.
|
* Character info regarding this character, including clothing styles, etc.
|
||||||
*/
|
*/
|
||||||
@@ -560,6 +564,8 @@ private:
|
|||||||
* ID of the last rocket used
|
* ID of the last rocket used
|
||||||
*/
|
*/
|
||||||
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
|
LWOOBJID m_CurrentInteracting = LWOOBJID_EMPTY;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHARACTERCOMPONENT_H
|
#endif // CHARACTERCOMPONENT_H
|
||||||
|
|||||||
@@ -28,3 +28,7 @@ void Component::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Component::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void LoadFromXml(tinyxml2::XMLDocument* doc);
|
virtual void LoadFromXml(tinyxml2::XMLDocument* doc);
|
||||||
|
|
||||||
|
virtual void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,15 +15,12 @@
|
|||||||
#include "LevelProgressionComponent.h"
|
#include "LevelProgressionComponent.h"
|
||||||
#include "eStateChangeType.h"
|
#include "eStateChangeType.h"
|
||||||
|
|
||||||
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Component(entity) {
|
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : PhysicsComponent(entity) {
|
||||||
m_Position = {};
|
|
||||||
m_Rotation = NiQuaternion::IDENTITY;
|
|
||||||
m_Velocity = {};
|
m_Velocity = {};
|
||||||
m_AngularVelocity = {};
|
m_AngularVelocity = {};
|
||||||
m_InJetpackMode = false;
|
m_InJetpackMode = false;
|
||||||
m_IsOnGround = true;
|
m_IsOnGround = true;
|
||||||
m_IsOnRail = false;
|
m_IsOnRail = false;
|
||||||
m_DirtyPosition = true;
|
|
||||||
m_DirtyVelocity = true;
|
m_DirtyVelocity = true;
|
||||||
m_DirtyAngularVelocity = true;
|
m_DirtyAngularVelocity = true;
|
||||||
m_dpEntity = nullptr;
|
m_dpEntity = nullptr;
|
||||||
@@ -74,7 +71,7 @@ void ControllablePhysicsComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
//If this is a creation, then we assume the position is dirty, even when it isn't.
|
//If this is a creation, then we assume the position is dirty, even when it isn't.
|
||||||
//This is because new clients will still need to receive the position.
|
//This is because new clients will still need to receive the position.
|
||||||
//if (bIsInitialUpdate) m_DirtyPosition = true;
|
//if (bIsInitialUpdate) m_DirtyPosition = true;
|
||||||
@@ -181,12 +178,6 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::ResetFlags() {
|
|
||||||
m_DirtyAngularVelocity = false;
|
|
||||||
m_DirtyPosition = false;
|
|
||||||
m_DirtyVelocity = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (!character) {
|
if (!character) {
|
||||||
@@ -208,26 +199,14 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::SetPosition(const NiPoint3& pos) {
|
void ControllablePhysicsComponent::SetPosition(const NiPoint3& pos) {
|
||||||
if (m_Static) {
|
if (m_Static) return;
|
||||||
return;
|
PhysicsComponent::SetPosition(pos);
|
||||||
}
|
|
||||||
|
|
||||||
m_Position.x = pos.x;
|
|
||||||
m_Position.y = pos.y;
|
|
||||||
m_Position.z = pos.z;
|
|
||||||
m_DirtyPosition = true;
|
|
||||||
|
|
||||||
if (m_dpEntity) m_dpEntity->SetPosition(pos);
|
if (m_dpEntity) m_dpEntity->SetPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::SetRotation(const NiQuaternion& rot) {
|
void ControllablePhysicsComponent::SetRotation(const NiQuaternion& rot) {
|
||||||
if (m_Static) {
|
if (m_Static) return;
|
||||||
return;
|
PhysicsComponent::SetRotation(rot);
|
||||||
}
|
|
||||||
|
|
||||||
m_Rotation = rot;
|
|
||||||
m_DirtyPosition = true;
|
|
||||||
|
|
||||||
if (m_dpEntity) m_dpEntity->SetRotation(rot);
|
if (m_dpEntity) m_dpEntity->SetRotation(rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
#include "NiQuaternion.h"
|
#include "NiQuaternion.h"
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
#include "Component.h"
|
#include "PhysicsComponent.h"
|
||||||
#include "dpCollisionChecks.h"
|
#include "dpCollisionChecks.h"
|
||||||
#include "PhantomPhysicsComponent.h"
|
#include "PhantomPhysicsComponent.h"
|
||||||
#include "eBubbleType.h"
|
#include "eBubbleType.h"
|
||||||
@@ -19,7 +19,7 @@ enum class eStateChangeType : uint32_t;
|
|||||||
/**
|
/**
|
||||||
* Handles the movement of controllable Entities, e.g. enemies and players
|
* Handles the movement of controllable Entities, e.g. enemies and players
|
||||||
*/
|
*/
|
||||||
class ControllablePhysicsComponent : public Component {
|
class ControllablePhysicsComponent : public PhysicsComponent {
|
||||||
public:
|
public:
|
||||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
||||||
|
|
||||||
@@ -27,9 +27,8 @@ public:
|
|||||||
~ControllablePhysicsComponent() override;
|
~ControllablePhysicsComponent() override;
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
||||||
void ResetFlags();
|
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,26 +36,14 @@ public:
|
|||||||
* If the entity is static, this is a no-op.
|
* If the entity is static, this is a no-op.
|
||||||
* @param pos The position to set
|
* @param pos The position to set
|
||||||
*/
|
*/
|
||||||
void SetPosition(const NiPoint3& pos);
|
void SetPosition(const NiPoint3& pos) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current position of the entity
|
|
||||||
* @return The current position of the entity
|
|
||||||
*/
|
|
||||||
const NiPoint3& GetPosition() const { return m_Position; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the rotation of this entity, ensures this change is serialized next tick. If the entity is static, this is
|
* Sets the rotation of this entity, ensures this change is serialized next tick. If the entity is static, this is
|
||||||
* a no-op.
|
* a no-op.
|
||||||
* @param rot the rotation to set
|
* @param rot the rotation to set
|
||||||
*/
|
*/
|
||||||
void SetRotation(const NiQuaternion& rot);
|
void SetRotation(const NiQuaternion& rot) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current rotation of this entity
|
|
||||||
* @return the current rotation of this entity
|
|
||||||
*/
|
|
||||||
const NiQuaternion& GetRotation() const { return m_Rotation; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current velocity of this entity, ensures that this change is serialized next tick. If the entity is
|
* Sets the current velocity of this entity, ensures that this change is serialized next tick. If the entity is
|
||||||
@@ -323,21 +310,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
dpEntity* m_dpEntity;
|
dpEntity* m_dpEntity;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the position is dirty, forcing a serialization update of the position
|
|
||||||
*/
|
|
||||||
bool m_DirtyPosition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current position of the entity
|
|
||||||
*/
|
|
||||||
NiPoint3 m_Position;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current rotation of the entity
|
|
||||||
*/
|
|
||||||
NiQuaternion m_Rotation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the velocity is dirty, forcing a serialization of the velocity
|
* Whether or not the velocity is dirty, forcing a serialization of the velocity
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
|||||||
m_ImmuneToImaginationLossCount = 0;
|
m_ImmuneToImaginationLossCount = 0;
|
||||||
m_ImmuneToQuickbuildInterruptCount = 0;
|
m_ImmuneToQuickbuildInterruptCount = 0;
|
||||||
m_ImmuneToPullToPointCount = 0;
|
m_ImmuneToPullToPointCount = 0;
|
||||||
|
m_DeathBehavior = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyableComponent::~DestroyableComponent() {
|
DestroyableComponent::~DestroyableComponent() {
|
||||||
@@ -119,7 +120,7 @@ void DestroyableComponent::Reinitialize(LOT templateID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
outBitStream->Write1(); // always write these on construction
|
outBitStream->Write1(); // always write these on construction
|
||||||
outBitStream->Write(m_ImmuneToBasicAttackCount);
|
outBitStream->Write(m_ImmuneToBasicAttackCount);
|
||||||
@@ -363,9 +364,10 @@ void DestroyableComponent::SetIsShielded(bool value) {
|
|||||||
|
|
||||||
void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignoreChecks) {
|
void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignoreChecks) {
|
||||||
// Ignore factionID -1
|
// Ignore factionID -1
|
||||||
if (factionID == -1 && !ignoreChecks) {
|
if (factionID == -1 && !ignoreChecks) return;
|
||||||
return;
|
|
||||||
}
|
// if we already have that faction, don't add it again
|
||||||
|
if (std::find(m_FactionIDs.begin(), m_FactionIDs.end(), factionID) != m_FactionIDs.end()) return;
|
||||||
|
|
||||||
m_FactionIDs.push_back(factionID);
|
m_FactionIDs.push_back(factionID);
|
||||||
m_DirtyHealth = true;
|
m_DirtyHealth = true;
|
||||||
@@ -407,6 +409,14 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DestroyableComponent::IsEnemy(const Entity* other) const {
|
bool DestroyableComponent::IsEnemy(const Entity* other) const {
|
||||||
|
if (m_Parent->IsPlayer() && other->IsPlayer()){
|
||||||
|
auto* thisCharacterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||||
|
if (!thisCharacterComponent) return false;
|
||||||
|
auto* otherCharacterComponent = other->GetComponent<CharacterComponent>();
|
||||||
|
if (!otherCharacterComponent) return false;
|
||||||
|
if (thisCharacterComponent->GetPvpEnabled() && otherCharacterComponent->GetPvpEnabled()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const auto* otherDestroyableComponent = other->GetComponent<DestroyableComponent>();
|
const auto* otherDestroyableComponent = other->GetComponent<DestroyableComponent>();
|
||||||
if (otherDestroyableComponent != nullptr) {
|
if (otherDestroyableComponent != nullptr) {
|
||||||
for (const auto enemyFaction : m_EnemyFactionIDs) {
|
for (const auto enemyFaction : m_EnemyFactionIDs) {
|
||||||
@@ -485,43 +495,6 @@ Entity* DestroyableComponent::GetKiller() const {
|
|||||||
return Game::entityManager->GetEntity(m_KillerID);
|
return Game::entityManager->GetEntity(m_KillerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DestroyableComponent::CheckValidity(const LWOOBJID target, const bool ignoreFactions, const bool targetEnemy, const bool targetFriend) const {
|
|
||||||
auto* targetEntity = Game::entityManager->GetEntity(target);
|
|
||||||
|
|
||||||
if (targetEntity == nullptr) {
|
|
||||||
Game::logger->Log("DestroyableComponent", "Invalid entity for checking validity (%llu)!", target);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* targetDestroyable = targetEntity->GetComponent<DestroyableComponent>();
|
|
||||||
|
|
||||||
if (targetDestroyable == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* targetQuickbuild = targetEntity->GetComponent<RebuildComponent>();
|
|
||||||
|
|
||||||
if (targetQuickbuild != nullptr) {
|
|
||||||
const auto state = targetQuickbuild->GetState();
|
|
||||||
|
|
||||||
if (state != eRebuildState::COMPLETED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreFactions) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get if the target entity is an enemy and friend
|
|
||||||
bool isEnemy = IsEnemy(targetEntity);
|
|
||||||
bool isFriend = IsFriend(targetEntity);
|
|
||||||
|
|
||||||
// Return true if the target type matches what we are targeting
|
|
||||||
return (isEnemy && targetEnemy) || (isFriend && targetFriend);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DestroyableComponent::Heal(const uint32_t health) {
|
void DestroyableComponent::Heal(const uint32_t health) {
|
||||||
auto current = static_cast<uint32_t>(GetHealth());
|
auto current = static_cast<uint32_t>(GetHealth());
|
||||||
const auto max = static_cast<uint32_t>(GetMaxHealth());
|
const auto max = static_cast<uint32_t>(GetMaxHealth());
|
||||||
@@ -763,18 +736,18 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
|
|
||||||
auto* member = Game::entityManager->GetEntity(specificOwner);
|
auto* member = Game::entityManager->GetEntity(specificOwner);
|
||||||
|
|
||||||
if (member) LootGenerator::Instance().DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
if (member) Loot::DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||||
} else {
|
} else {
|
||||||
for (const auto memberId : team->members) { // Free for all
|
for (const auto memberId : team->members) { // Free for all
|
||||||
auto* member = Game::entityManager->GetEntity(memberId);
|
auto* member = Game::entityManager->GetEntity(memberId);
|
||||||
|
|
||||||
if (member == nullptr) continue;
|
if (member == nullptr) continue;
|
||||||
|
|
||||||
LootGenerator::Instance().DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
Loot::DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // drop loot for non team user
|
} else { // drop loot for non team user
|
||||||
LootGenerator::Instance().DropLoot(owner, m_Parent, GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
Loot::DropLoot(owner, m_Parent, GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -792,7 +765,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
|
|
||||||
coinsTotal -= coinsToLose;
|
coinsTotal -= coinsToLose;
|
||||||
|
|
||||||
LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLose, coinsToLose);
|
Loot::DropLoot(m_Parent, m_Parent, -1, coinsToLose, coinsToLose);
|
||||||
character->SetCoins(coinsTotal, eLootSourceType::PICKUP);
|
character->SetCoins(coinsTotal, eLootSourceType::PICKUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
DestroyableComponent(Entity* parentEntity);
|
DestroyableComponent(Entity* parentEntity);
|
||||||
~DestroyableComponent() override;
|
~DestroyableComponent() override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
||||||
|
|
||||||
@@ -371,14 +371,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Entity* GetKiller() const;
|
Entity* GetKiller() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the target ID is a valid enemy of this entity
|
|
||||||
* @param target the target ID to check for
|
|
||||||
* @param ignoreFactions whether or not check for the factions, e.g. just return true if the entity cannot be smashed
|
|
||||||
* @return if the target ID is a valid enemy
|
|
||||||
*/
|
|
||||||
bool CheckValidity(LWOOBJID target, bool ignoreFactions = false, bool targetEnemy = true, bool targetFriend = false) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to damage this entity, handles everything from health and armor to absorption, immunity and callbacks.
|
* Attempt to damage this entity, handles everything from health and armor to absorption, immunity and callbacks.
|
||||||
* @param damage the damage to attempt to apply
|
* @param damage the damage to attempt to apply
|
||||||
@@ -424,6 +416,9 @@ public:
|
|||||||
const bool GetImmuneToQuickbuildInterrupt() {return m_ImmuneToQuickbuildInterruptCount > 0;};
|
const bool GetImmuneToQuickbuildInterrupt() {return m_ImmuneToQuickbuildInterruptCount > 0;};
|
||||||
const bool GetImmuneToPullToPoint() {return m_ImmuneToPullToPointCount > 0;};
|
const bool GetImmuneToPullToPoint() {return m_ImmuneToPullToPointCount > 0;};
|
||||||
|
|
||||||
|
int32_t GetDeathBehavior() const { return m_DeathBehavior; }
|
||||||
|
void SetDeathBehavior(int32_t value) { m_DeathBehavior = value; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility to reset all stats to the default stats based on items and completed missions
|
* Utility to reset all stats to the default stats based on items and completed missions
|
||||||
*/
|
*/
|
||||||
@@ -605,6 +600,11 @@ private:
|
|||||||
uint32_t m_ImmuneToImaginationLossCount;
|
uint32_t m_ImmuneToImaginationLossCount;
|
||||||
uint32_t m_ImmuneToQuickbuildInterruptCount;
|
uint32_t m_ImmuneToQuickbuildInterruptCount;
|
||||||
uint32_t m_ImmuneToPullToPointCount;
|
uint32_t m_ImmuneToPullToPointCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Death behavior type. If 0, the client plays a death animation as opposed to a smash animation.
|
||||||
|
*/
|
||||||
|
int32_t m_DeathBehavior;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DESTROYABLECOMPONENT_H
|
#endif // DESTROYABLECOMPONENT_H
|
||||||
|
|||||||
50
dGame/dComponents/DonationVendorComponent.cpp
Normal file
50
dGame/dComponents/DonationVendorComponent.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "DonationVendorComponent.h"
|
||||||
|
#include "Database.h"
|
||||||
|
|
||||||
|
DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) {
|
||||||
|
//LoadConfigData
|
||||||
|
m_PercentComplete = 0.0;
|
||||||
|
m_TotalDonated = 0;
|
||||||
|
m_TotalRemaining = 0;
|
||||||
|
|
||||||
|
// custom attribute to calculate other values
|
||||||
|
m_Goal = m_Parent->GetVar<int32_t>(u"donationGoal");
|
||||||
|
if (m_Goal == 0) m_Goal = INT32_MAX;
|
||||||
|
|
||||||
|
// Default to the nexus tower jawbox activity and setup settings
|
||||||
|
m_ActivityId = m_Parent->GetVar<uint32_t>(u"activityID");
|
||||||
|
if ((m_ActivityId == 0) || (m_ActivityId == 117)) {
|
||||||
|
m_ActivityId = 117;
|
||||||
|
m_PercentComplete = 1.0;
|
||||||
|
m_TotalDonated = INT32_MAX;
|
||||||
|
m_TotalRemaining = 0;
|
||||||
|
m_Goal = INT32_MAX;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt("SELECT SUM(primaryScore) as donation_total FROM leaderboard WHERE game_id = ?;"));
|
||||||
|
query->setInt(1, m_ActivityId);
|
||||||
|
std::unique_ptr<sql::ResultSet> donation_total(query->executeQuery());
|
||||||
|
if (donation_total->next()) m_TotalDonated = donation_total->getInt("donation_total");
|
||||||
|
m_TotalRemaining = m_Goal - m_TotalDonated;
|
||||||
|
m_PercentComplete = m_TotalDonated/static_cast<float>(m_Goal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DonationVendorComponent::SubmitDonation(uint32_t count) {
|
||||||
|
if (count <= 0 && ((m_TotalDonated + count) > 0)) return;
|
||||||
|
m_TotalDonated += count;
|
||||||
|
m_TotalRemaining = m_Goal - m_TotalDonated;
|
||||||
|
m_PercentComplete = m_TotalDonated/static_cast<float>(m_Goal);
|
||||||
|
m_DirtyDonationVendor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DonationVendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
|
VendorComponent::Serialize(outBitStream, bIsInitialUpdate);
|
||||||
|
outBitStream->Write(bIsInitialUpdate || m_DirtyDonationVendor);
|
||||||
|
if (bIsInitialUpdate || m_DirtyDonationVendor) {
|
||||||
|
outBitStream->Write(m_PercentComplete);
|
||||||
|
outBitStream->Write(m_TotalDonated);
|
||||||
|
outBitStream->Write(m_TotalRemaining);
|
||||||
|
if (!bIsInitialUpdate) m_DirtyDonationVendor = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
dGame/dComponents/DonationVendorComponent.h
Normal file
27
dGame/dComponents/DonationVendorComponent.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __DONATIONVENDORCOMPONENT__H__
|
||||||
|
#define __DONATIONVENDORCOMPONENT__H__
|
||||||
|
|
||||||
|
#include "VendorComponent.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
class DonationVendorComponent final : public VendorComponent {
|
||||||
|
public:
|
||||||
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
||||||
|
DonationVendorComponent(Entity* parent);
|
||||||
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
uint32_t GetActivityID() {return m_ActivityId;};
|
||||||
|
void SubmitDonation(uint32_t count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_DirtyDonationVendor = false;
|
||||||
|
float m_PercentComplete = 0.0;
|
||||||
|
int32_t m_TotalDonated = 0;
|
||||||
|
int32_t m_TotalRemaining = 0;
|
||||||
|
uint32_t m_ActivityId = 0;
|
||||||
|
int32_t m_Goal = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //!__DONATIONVENDORCOMPONENT__H__
|
||||||
@@ -116,6 +116,9 @@ Inventory* InventoryComponent::GetInventory(const eInventoryType type) {
|
|||||||
case eInventoryType::VENDOR_BUYBACK:
|
case eInventoryType::VENDOR_BUYBACK:
|
||||||
size = 27u;
|
size = 27u;
|
||||||
break;
|
break;
|
||||||
|
case eInventoryType::DONATION:
|
||||||
|
size = 24u;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -709,7 +712,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool bIsInitialUpdate, unsigned& flags) {
|
void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool bIsInitialUpdate) {
|
||||||
if (bIsInitialUpdate || m_Dirty) {
|
if (bIsInitialUpdate || m_Dirty) {
|
||||||
outBitStream->Write(true);
|
outBitStream->Write(true);
|
||||||
|
|
||||||
@@ -767,10 +770,6 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b
|
|||||||
outBitStream->Write(false);
|
outBitStream->Write(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::ResetFlags() {
|
|
||||||
m_Dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InventoryComponent::Update(float deltaTime) {
|
void InventoryComponent::Update(float deltaTime) {
|
||||||
for (auto* set : m_Itemsets) {
|
for (auto* set : m_Itemsets) {
|
||||||
set->Update(deltaTime);
|
set->Update(deltaTime);
|
||||||
@@ -933,9 +932,8 @@ void InventoryComponent::EquipScripts(Item* equippedItem) {
|
|||||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(equippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(equippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
||||||
if (scriptComponentID > -1) {
|
if (scriptComponentID > -1) {
|
||||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
||||||
auto scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||||
if (!scriptCompData) return;
|
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData->script_name);
|
|
||||||
if (!itemScript) {
|
if (!itemScript) {
|
||||||
Game::logger->Log("InventoryComponent", "null script?");
|
Game::logger->Log("InventoryComponent", "null script?");
|
||||||
}
|
}
|
||||||
@@ -949,9 +947,8 @@ void InventoryComponent::UnequipScripts(Item* unequippedItem) {
|
|||||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(unequippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(unequippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
||||||
if (scriptComponentID > -1) {
|
if (scriptComponentID > -1) {
|
||||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
||||||
auto scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||||
if (!scriptCompData) return;
|
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData->script_name);
|
|
||||||
if (!itemScript) {
|
if (!itemScript) {
|
||||||
Game::logger->Log("InventoryComponent", "null script?");
|
Game::logger->Log("InventoryComponent", "null script?");
|
||||||
}
|
}
|
||||||
@@ -1161,19 +1158,7 @@ void InventoryComponent::AddItemSkills(const LOT lot) {
|
|||||||
|
|
||||||
const auto skill = FindSkill(lot);
|
const auto skill = FindSkill(lot);
|
||||||
|
|
||||||
if (skill == 0) {
|
SetSkill(slot, skill);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index != m_Skills.end()) {
|
|
||||||
const auto old = index->second;
|
|
||||||
|
|
||||||
GameMessages::SendRemoveSkill(m_Parent, old);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMessages::SendAddSkill(m_Parent, skill, static_cast<int>(slot));
|
|
||||||
|
|
||||||
m_Skills.insert_or_assign(slot, skill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::RemoveItemSkills(const LOT lot) {
|
void InventoryComponent::RemoveItemSkills(const LOT lot) {
|
||||||
@@ -1200,7 +1185,7 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) {
|
|||||||
if (slot == BehaviorSlot::Primary) {
|
if (slot == BehaviorSlot::Primary) {
|
||||||
m_Skills.insert_or_assign(BehaviorSlot::Primary, 1);
|
m_Skills.insert_or_assign(BehaviorSlot::Primary, 1);
|
||||||
|
|
||||||
GameMessages::SendAddSkill(m_Parent, 1, static_cast<int>(BehaviorSlot::Primary));
|
GameMessages::SendAddSkill(m_Parent, 1, BehaviorSlot::Primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,12 +1328,8 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip
|
|||||||
for (const auto& result : results) {
|
for (const auto& result : results) {
|
||||||
if (result.castOnType == 1) {
|
if (result.castOnType == 1) {
|
||||||
const auto entry = behaviors->GetSkillByID(result.skillID);
|
const auto entry = behaviors->GetSkillByID(result.skillID);
|
||||||
if (!entry) {
|
|
||||||
Game::logger->Log("InventoryComponent", "Buff %i not in database!", result.skillID);
|
|
||||||
|
|
||||||
continue;
|
if (entry.skillID == 0) {
|
||||||
}
|
|
||||||
if (entry->skillID == 0) {
|
|
||||||
Game::logger->Log("InventoryComponent", "Failed to find buff behavior for skill (%i)!", result.skillID);
|
Game::logger->Log("InventoryComponent", "Failed to find buff behavior for skill (%i)!", result.skillID);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -1359,7 +1340,7 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If item is not a proxy, add its buff to the added buffs.
|
// If item is not a proxy, add its buff to the added buffs.
|
||||||
if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast<uint32_t>(entry->behaviorID));
|
if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast<uint32_t>(entry.behaviorID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1634,3 +1615,29 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) {
|
|||||||
petInventoryElement->LinkEndChild(petElement);
|
petInventoryElement->LinkEndChild(petElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId){
|
||||||
|
BehaviorSlot behaviorSlot = BehaviorSlot::Invalid;
|
||||||
|
if (slot == 1 ) behaviorSlot = BehaviorSlot::Primary;
|
||||||
|
else if (slot == 2 ) behaviorSlot = BehaviorSlot::Offhand;
|
||||||
|
else if (slot == 3 ) behaviorSlot = BehaviorSlot::Neck;
|
||||||
|
else if (slot == 4 ) behaviorSlot = BehaviorSlot::Head;
|
||||||
|
else if (slot == 5 ) behaviorSlot = BehaviorSlot::Consumable;
|
||||||
|
else return false;
|
||||||
|
return SetSkill(behaviorSlot, skillId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){
|
||||||
|
if (skillId == 0) return false;
|
||||||
|
const auto index = m_Skills.find(slot);
|
||||||
|
if (index != m_Skills.end()) {
|
||||||
|
const auto old = index->second;
|
||||||
|
GameMessages::SendRemoveSkill(m_Parent, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameMessages::SendAddSkill(m_Parent, skillId, slot);
|
||||||
|
m_Skills.insert_or_assign(slot, skillId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,10 +42,9 @@ public:
|
|||||||
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
|
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadXml(tinyxml2::XMLDocument* document);
|
void LoadXml(tinyxml2::XMLDocument* document);
|
||||||
void UpdateXml(tinyxml2::XMLDocument* document) override;
|
void UpdateXml(tinyxml2::XMLDocument* document) override;
|
||||||
void ResetFlags();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an inventory of the specified type, if it exists
|
* Returns an inventory of the specified type, if it exists
|
||||||
@@ -368,6 +367,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UnequipScripts(Item* unequippedItem);
|
void UnequipScripts(Item* unequippedItem);
|
||||||
|
|
||||||
|
std::map<BehaviorSlot, uint32_t> GetSkills(){ return m_Skills; };
|
||||||
|
|
||||||
|
bool SetSkill(int slot, uint32_t skillId);
|
||||||
|
bool SetSkill(BehaviorSlot slot, uint32_t skillId);
|
||||||
|
|
||||||
~InventoryComponent() override;
|
~InventoryComponent() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ void LUPExhibitComponent::NextExhibit() {
|
|||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write1(); // Dirty flag?
|
outBitStream->Write1(); // Dirty flag?
|
||||||
outBitStream->Write(m_Exhibit);
|
outBitStream->Write(m_Exhibit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
LUPExhibitComponent(Entity* parent);
|
LUPExhibitComponent(Entity* parent);
|
||||||
~LUPExhibitComponent();
|
~LUPExhibitComponent();
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the timer runs out, this changes the currently exhibited LOT to the next one
|
* After the timer runs out, this changes the currently exhibited LOT to the next one
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
m_CharacterVersion = static_cast<eCharacterVersion>(characterVersion);
|
m_CharacterVersion = static_cast<eCharacterVersion>(characterVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write(bIsInitialUpdate || m_DirtyLevelInfo);
|
outBitStream->Write(bIsInitialUpdate || m_DirtyLevelInfo);
|
||||||
if (bIsInitialUpdate || m_DirtyLevelInfo) outBitStream->Write(m_Level);
|
if (bIsInitialUpdate || m_DirtyLevelInfo) outBitStream->Write(m_Level);
|
||||||
m_DirtyLevelInfo = false;
|
m_DirtyLevelInfo = false;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
LevelProgressionComponent(Entity* parent);
|
LevelProgressionComponent(Entity* parent);
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save data from this componennt to character XML
|
* Save data from this componennt to character XML
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
|||||||
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
// ItemComponent Serialization. Pets do not get this serialization.
|
// ItemComponent Serialization. Pets do not get this serialization.
|
||||||
if (!m_Parent->HasComponent(eReplicaComponentType::PET)) {
|
if (!m_Parent->HasComponent(eReplicaComponentType::PET)) {
|
||||||
outBitStream->Write1();
|
outBitStream->Write1();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public:
|
|||||||
|
|
||||||
ModelComponent(Entity* parent);
|
ModelComponent(Entity* parent);
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the original position of the model
|
* Returns the original position of the model
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const std::u16string& ModuleAssemblyComponent::GetAssemblyPartsLOTs() const {
|
|||||||
return m_AssemblyPartsLOTs;
|
return m_AssemblyPartsLOTs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
outBitStream->Write1();
|
outBitStream->Write1();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public:
|
|||||||
ModuleAssemblyComponent(Entity* parent);
|
ModuleAssemblyComponent(Entity* parent);
|
||||||
~ModuleAssemblyComponent() override;
|
~ModuleAssemblyComponent() override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,85 +10,77 @@
|
|||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "SimplePhysicsComponent.h"
|
#include "SimplePhysicsComponent.h"
|
||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dZoneManager.h"
|
||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {};
|
namespace {
|
||||||
|
/**
|
||||||
|
* Cache of all lots and their respective speeds
|
||||||
|
*/
|
||||||
|
std::map<LOT, float> m_PhysicsSpeedCache;
|
||||||
|
}
|
||||||
|
|
||||||
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
||||||
m_Info = std::move(info);
|
m_Info = info;
|
||||||
m_Done = true;
|
m_AtFinalWaypoint = true;
|
||||||
|
|
||||||
m_BaseCombatAI = nullptr;
|
m_BaseCombatAI = nullptr;
|
||||||
|
|
||||||
m_BaseCombatAI = reinterpret_cast<BaseCombatAIComponent*>(m_Parent->GetComponent(eReplicaComponentType::BASE_COMBAT_AI));
|
m_BaseCombatAI = m_Parent->GetComponent<BaseCombatAIComponent>();
|
||||||
|
|
||||||
//Try and fix the insane values:
|
//Try and fix the insane values:
|
||||||
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius = m_Info.wanderRadius * 0.5f;
|
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f;
|
||||||
if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
|
if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
|
||||||
if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed = m_Info.wanderSpeed * 0.5f;
|
if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f;
|
||||||
|
|
||||||
m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT());
|
m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT());
|
||||||
|
|
||||||
m_NextWaypoint = GetCurrentPosition();
|
m_NextWaypoint = m_Parent->GetPosition();
|
||||||
m_Acceleration = 0.4f;
|
m_Acceleration = 0.4f;
|
||||||
m_Interrupted = false;
|
m_PullingToPoint = false;
|
||||||
m_PullPoint = {};
|
m_PullPoint = NiPoint3::ZERO;
|
||||||
m_HaltDistance = 0;
|
m_HaltDistance = 0;
|
||||||
m_Timer = 0;
|
m_TimeToTravel = 0;
|
||||||
|
m_TimeTravelled = 0;
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
m_Speed = 0;
|
m_MaxSpeed = 0;
|
||||||
m_TotalTime = 0;
|
|
||||||
m_LockRotation = false;
|
m_LockRotation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MovementAIComponent::~MovementAIComponent() = default;
|
|
||||||
|
|
||||||
void MovementAIComponent::Update(const float deltaTime) {
|
void MovementAIComponent::Update(const float deltaTime) {
|
||||||
if (m_Interrupted) {
|
if (m_PullingToPoint) {
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
const auto speed = deltaTime * 2.5f;
|
const auto speed = deltaTime * 2.5f;
|
||||||
|
|
||||||
NiPoint3 velocity;
|
NiPoint3 velocity = (m_PullPoint - source) * speed;
|
||||||
|
|
||||||
velocity.x = (m_PullPoint.x - source.x) * speed;
|
|
||||||
velocity.y = (m_PullPoint.y - source.y) * speed;
|
|
||||||
velocity.z = (m_PullPoint.z - source.z) * speed;
|
|
||||||
|
|
||||||
SetPosition(source + velocity);
|
SetPosition(source + velocity);
|
||||||
|
|
||||||
if (Vector3::DistanceSquared(GetCurrentPosition(), m_PullPoint) < 2 * 2) {
|
if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) {
|
||||||
m_Interrupted = false;
|
m_PullingToPoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AtFinalWaypoint()) // Are we done?
|
// Are we done?
|
||||||
{
|
if (AtFinalWaypoint()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_HaltDistance > 0) {
|
if (m_HaltDistance > 0) {
|
||||||
if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < m_HaltDistance * m_HaltDistance) // Prevent us from hugging the target
|
// Prevent us from hugging the target
|
||||||
{
|
if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < std::pow(m_HaltDistance, 2)) {
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Timer > 0) {
|
m_TimeTravelled += deltaTime;
|
||||||
m_Timer -= deltaTime;
|
if (m_TimeTravelled < m_TimeToTravel) return;
|
||||||
|
m_TimeTravelled = 0.0f;
|
||||||
if (m_Timer > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Timer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
@@ -101,48 +93,44 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
m_NextWaypoint = GetCurrentWaypoint();
|
m_NextWaypoint = GetCurrentWaypoint();
|
||||||
|
|
||||||
if (m_NextWaypoint == source) {
|
if (m_NextWaypoint == source) {
|
||||||
m_Timer = 0;
|
m_TimeToTravel = 0.0f;
|
||||||
|
|
||||||
goto nextAction;
|
goto nextAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_CurrentSpeed < m_Speed) {
|
if (m_CurrentSpeed < m_MaxSpeed) {
|
||||||
m_CurrentSpeed += m_Acceleration;
|
m_CurrentSpeed += m_Acceleration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_CurrentSpeed > m_Speed) {
|
if (m_CurrentSpeed > m_MaxSpeed) {
|
||||||
m_CurrentSpeed = m_Speed;
|
m_CurrentSpeed = m_MaxSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto speed = m_CurrentSpeed * m_BaseSpeed;
|
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
|
||||||
|
|
||||||
const auto delta = m_NextWaypoint - source;
|
const auto delta = m_NextWaypoint - source;
|
||||||
|
|
||||||
// Normalize the vector
|
// Normalize the vector
|
||||||
const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z);
|
const auto length = delta.Length();
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
velocity.x = (delta.x / length) * speed;
|
velocity = (delta / length) * speed;
|
||||||
velocity.y = (delta.y / length) * speed;
|
|
||||||
velocity.z = (delta.z / length) * speed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calclute the time it will take to reach the next waypoint with the current speed
|
// Calclute the time it will take to reach the next waypoint with the current speed
|
||||||
m_TotalTime = m_Timer = length / speed;
|
m_TimeTravelled = 0.0f;
|
||||||
|
m_TimeToTravel = length / speed;
|
||||||
|
|
||||||
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
||||||
} else {
|
} else {
|
||||||
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
||||||
if (!m_Queue.empty()) {
|
if (m_CurrentPath.empty()) {
|
||||||
SetDestination(m_Queue.top());
|
|
||||||
|
|
||||||
m_Queue.pop();
|
|
||||||
} else {
|
|
||||||
// We have reached our final waypoint
|
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SetDestination(m_CurrentPath.top());
|
||||||
|
|
||||||
|
m_CurrentPath.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
nextAction:
|
nextAction:
|
||||||
@@ -157,7 +145,7 @@ const MovementAIInfo& MovementAIComponent::GetInfo() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAIComponent::AdvanceWaypointIndex() {
|
bool MovementAIComponent::AdvanceWaypointIndex() {
|
||||||
if (m_PathIndex >= m_CurrentPath.size()) {
|
if (m_PathIndex >= m_InterpolatedWaypoints.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,37 +155,19 @@ bool MovementAIComponent::AdvanceWaypointIndex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
||||||
if (m_PathIndex >= m_CurrentPath.size()) {
|
return m_PathIndex >= m_InterpolatedWaypoints.size() ? m_Parent->GetPosition() : m_InterpolatedWaypoints[m_PathIndex];
|
||||||
return GetCurrentPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_CurrentPath[m_PathIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetNextWaypoint() const {
|
|
||||||
return m_NextWaypoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetCurrentPosition() const {
|
|
||||||
return m_Parent->GetPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
||||||
auto source = GetCurrentPosition();
|
auto source = m_Parent->GetPosition();
|
||||||
|
|
||||||
if (m_Done) {
|
if (AtFinalWaypoint()) return source;
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto destination = m_NextWaypoint;
|
auto destination = m_NextWaypoint;
|
||||||
|
|
||||||
auto factor = m_TotalTime > 0 ? (m_TotalTime - m_Timer) / m_TotalTime : 0;
|
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
|
||||||
|
|
||||||
auto x = source.x + factor * (destination.x - source.x);
|
auto approximation = source + ((destination - source) * percentageToWaypoint);
|
||||||
auto y = source.y + factor * (destination.y - source.y);
|
|
||||||
auto z = source.z + factor * (destination.z - source.z);
|
|
||||||
|
|
||||||
NiPoint3 approximation = NiPoint3(x, y, z);
|
|
||||||
|
|
||||||
if (dpWorld::Instance().IsLoaded()) {
|
if (dpWorld::Instance().IsLoaded()) {
|
||||||
approximation.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(approximation);
|
approximation.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(approximation);
|
||||||
@@ -226,28 +196,20 @@ bool MovementAIComponent::Warp(const NiPoint3& point) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MovementAIComponent::GetTimer() const {
|
|
||||||
return m_Timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MovementAIComponent::AtFinalWaypoint() const {
|
|
||||||
return m_Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementAIComponent::Stop() {
|
void MovementAIComponent::Stop() {
|
||||||
if (m_Done) {
|
if (AtFinalWaypoint()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetPosition(ApproximateLocation());
|
SetPosition(ApproximateLocation());
|
||||||
|
|
||||||
SetVelocity(NiPoint3::ZERO);
|
SetVelocity(NiPoint3::ZERO);
|
||||||
|
|
||||||
m_TotalTime = m_Timer = 0;
|
m_TimeToTravel = 0;
|
||||||
|
m_TimeTravelled = 0;
|
||||||
|
|
||||||
m_Done = true;
|
m_AtFinalWaypoint = true;
|
||||||
|
|
||||||
m_CurrentPath = {};
|
m_InterpolatedWaypoints.clear();
|
||||||
|
while (!m_CurrentPath.empty()) m_CurrentPath.pop();
|
||||||
|
|
||||||
m_PathIndex = 0;
|
m_PathIndex = 0;
|
||||||
|
|
||||||
@@ -259,20 +221,17 @@ void MovementAIComponent::Stop() {
|
|||||||
void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
m_Interrupted = true;
|
m_PullingToPoint = true;
|
||||||
m_PullPoint = point;
|
m_PullPoint = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
|
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
|
||||||
std::reverse(path.begin(), path.end());
|
if (path.empty()) return;
|
||||||
|
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
|
||||||
|
this->m_CurrentPath.push(point);
|
||||||
|
});
|
||||||
|
|
||||||
for (const auto& point : path) {
|
SetDestination(path.front());
|
||||||
m_Queue.push(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetDestination(m_Queue.top());
|
|
||||||
|
|
||||||
m_Queue.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||||
@@ -291,26 +250,14 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
|||||||
|
|
||||||
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::CONTROLLABLE_PHYSICS, -1);
|
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::CONTROLLABLE_PHYSICS, -1);
|
||||||
|
|
||||||
if (componentID != -1) {
|
if (componentID == -1) {
|
||||||
physicsComponent = physicsComponentTable->GetByID(componentID);
|
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1);
|
||||||
|
|
||||||
goto foundComponent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1);
|
physicsComponent = physicsComponentTable->GetByID(componentID);
|
||||||
|
|
||||||
if (componentID != -1) {
|
|
||||||
physicsComponent = physicsComponentTable->GetByID(componentID);
|
|
||||||
|
|
||||||
goto foundComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
foundComponent:
|
|
||||||
|
|
||||||
// Client defaults speed to 10 and if the speed is also null in the table, it defaults to 10.
|
// Client defaults speed to 10 and if the speed is also null in the table, it defaults to 10.
|
||||||
float speed = 10.0f;
|
float speed = physicsComponent != nullptr ? physicsComponent->speed : 10.0f;
|
||||||
|
|
||||||
if (physicsComponent) speed = physicsComponent->speed;
|
|
||||||
|
|
||||||
float delta = fabs(speed) - 1.0f;
|
float delta = fabs(speed) - 1.0f;
|
||||||
|
|
||||||
@@ -322,39 +269,11 @@ foundComponent:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetPosition(const NiPoint3& value) {
|
void MovementAIComponent::SetPosition(const NiPoint3& value) {
|
||||||
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
m_Parent->SetPosition(value);
|
||||||
|
|
||||||
if (controllablePhysicsComponent != nullptr) {
|
|
||||||
controllablePhysicsComponent->SetPosition(value);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
|
||||||
|
|
||||||
if (simplePhysicsComponent != nullptr) {
|
|
||||||
simplePhysicsComponent->SetPosition(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetRotation(const NiQuaternion& value) {
|
void MovementAIComponent::SetRotation(const NiQuaternion& value) {
|
||||||
if (m_LockRotation) {
|
if (!m_LockRotation) m_Parent->SetRotation(value);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
|
||||||
|
|
||||||
if (controllablePhysicsComponent != nullptr) {
|
|
||||||
controllablePhysicsComponent->SetRotation(value);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
|
||||||
|
|
||||||
if (simplePhysicsComponent != nullptr) {
|
|
||||||
simplePhysicsComponent->SetRotation(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
||||||
@@ -373,15 +292,8 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetDestination(const NiPoint3& value) {
|
void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
||||||
if (m_Interrupted) {
|
if (m_PullingToPoint) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (Vector3::DistanceSquared(value, GetDestination()) < 2 * 2)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const auto location = ApproximateLocation();
|
const auto location = ApproximateLocation();
|
||||||
|
|
||||||
@@ -390,97 +302,53 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NiPoint3> computedPath;
|
std::vector<NiPoint3> computedPath;
|
||||||
|
|
||||||
if (dpWorld::Instance().IsLoaded()) {
|
if (dpWorld::Instance().IsLoaded()) {
|
||||||
computedPath = dpWorld::Instance().GetNavMesh()->GetPath(GetCurrentPosition(), value, m_Info.wanderSpeed);
|
computedPath = dpWorld::Instance().GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
// Somehow failed
|
||||||
|
if (computedPath.empty()) {
|
||||||
// Than take 10 points between the current position and the destination and make that the path
|
// Than take 10 points between the current position and the destination and make that the path
|
||||||
|
|
||||||
auto point = location;
|
auto start = location;
|
||||||
|
|
||||||
auto delta = value - point;
|
auto delta = destination - start;
|
||||||
|
|
||||||
auto step = delta / 10;
|
auto step = delta / 10.0f;
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
point = point + step;
|
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
|
||||||
|
start = start + step;
|
||||||
|
|
||||||
computedPath.push_back(point);
|
computedPath.push_back(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (computedPath.empty()) // Somehow failed
|
m_InterpolatedWaypoints.clear();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_CurrentPath.clear();
|
|
||||||
|
|
||||||
m_CurrentPath.push_back(location);
|
|
||||||
|
|
||||||
// Simply path
|
// Simply path
|
||||||
for (auto point : computedPath) {
|
for (auto& point : computedPath) {
|
||||||
if (dpWorld::Instance().IsLoaded()) {
|
if (dpWorld::Instance().IsLoaded()) {
|
||||||
point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentPath.push_back(point);
|
m_InterpolatedWaypoints.push_back(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentPath.push_back(computedPath[computedPath.size() - 1]);
|
|
||||||
|
|
||||||
m_PathIndex = 0;
|
m_PathIndex = 0;
|
||||||
|
|
||||||
m_TotalTime = m_Timer = 0;
|
m_TimeTravelled = 0;
|
||||||
|
m_TimeToTravel = 0;
|
||||||
|
|
||||||
m_Done = false;
|
m_AtFinalWaypoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetDestination() const {
|
NiPoint3 MovementAIComponent::GetDestination() const {
|
||||||
if (m_CurrentPath.empty()) {
|
return m_InterpolatedWaypoints.empty() ? m_Parent->GetPosition() : m_InterpolatedWaypoints.back();
|
||||||
return GetCurrentPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_CurrentPath[m_CurrentPath.size() - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetSpeed(const float value) {
|
void MovementAIComponent::SetMaxSpeed(const float value) {
|
||||||
m_Speed = value;
|
if (value == m_MaxSpeed) return;
|
||||||
|
m_MaxSpeed = value;
|
||||||
m_Acceleration = value / 5;
|
m_Acceleration = value / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MovementAIComponent::GetSpeed() const {
|
|
||||||
return m_Speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementAIComponent::SetAcceleration(const float value) {
|
|
||||||
m_Acceleration = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovementAIComponent::GetAcceleration() const {
|
|
||||||
return m_Acceleration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementAIComponent::SetHaltDistance(const float value) {
|
|
||||||
m_HaltDistance = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovementAIComponent::GetHaltDistance() const {
|
|
||||||
return m_HaltDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementAIComponent::SetCurrentSpeed(float value) {
|
|
||||||
m_CurrentSpeed = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovementAIComponent::GetCurrentSpeed() const {
|
|
||||||
return m_CurrentSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementAIComponent::SetLockRotation(bool value) {
|
|
||||||
m_LockRotation = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MovementAIComponent::GetLockRotation() const {
|
|
||||||
return m_LockRotation;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Darkflame Universe
|
* Darkflame Universe
|
||||||
* Copyright 2018
|
* Copyright 2023
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MOVEMENTAICOMPONENT_H
|
#ifndef MOVEMENTAICOMPONENT_H
|
||||||
@@ -60,7 +60,6 @@ public:
|
|||||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
||||||
|
|
||||||
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
||||||
~MovementAIComponent() override;
|
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
|
||||||
@@ -86,61 +85,55 @@ public:
|
|||||||
* Sets the max speed at which this entity may run
|
* Sets the max speed at which this entity may run
|
||||||
* @param value the speed value to set
|
* @param value the speed value to set
|
||||||
*/
|
*/
|
||||||
void SetSpeed(float value);
|
void SetMaxSpeed(float value);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the max speed at which this entity may run
|
|
||||||
* @return the max speed at which this entity may run
|
|
||||||
*/
|
|
||||||
float GetSpeed() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets how fast the entity will accelerate when not running at full speed
|
* Sets how fast the entity will accelerate when not running at full speed
|
||||||
* @param value the acceleration to set
|
* @param value the acceleration to set
|
||||||
*/
|
*/
|
||||||
void SetAcceleration(float value);
|
void SetAcceleration(float value) { m_Acceleration = value; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current speed at which this entity accelerates when not running at full speed
|
* Returns the current speed at which this entity accelerates when not running at full speed
|
||||||
* @return the current speed at which this entity accelerates when not running at full speed
|
* @return the current speed at which this entity accelerates when not running at full speed
|
||||||
*/
|
*/
|
||||||
float GetAcceleration() const;
|
float GetAcceleration() const { return m_Acceleration; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the halting distance (the distance at which we consider the target to be reached)
|
* Sets the halting distance (the distance at which we consider the target to be reached)
|
||||||
* @param value the halting distance to set
|
* @param value the halting distance to set
|
||||||
*/
|
*/
|
||||||
void SetHaltDistance(float value);
|
void SetHaltDistance(float value) { m_HaltDistance = value; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current halting distance (the distance at which we consider the target to be reached)
|
* Returns the current halting distance (the distance at which we consider the target to be reached)
|
||||||
* @return the current halting distance
|
* @return the current halting distance
|
||||||
*/
|
*/
|
||||||
float GetHaltDistance() const;
|
float GetHaltDistance() const { return m_HaltDistance; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the speed the entity is currently running at
|
* Sets the speed the entity is currently running at
|
||||||
* @param value the speed value to set
|
* @param value the speed value to set
|
||||||
*/
|
*/
|
||||||
void SetCurrentSpeed(float value);
|
void SetCurrentSpeed(float value) { m_CurrentSpeed = value; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the speed the entity is currently running at
|
* Returns the speed the entity is currently running at
|
||||||
* @return the speed the entity is currently running at
|
* @return the speed the entity is currently running at
|
||||||
*/
|
*/
|
||||||
float GetCurrentSpeed() const;
|
float GetCurrentSpeed() const { return m_CurrentSpeed; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the rotation of this entity in place, depending on the argument
|
* Locks the rotation of this entity in place, depending on the argument
|
||||||
* @param value if true, the entity will be rotationally locked
|
* @param value if true, the entity will be rotationally locked
|
||||||
*/
|
*/
|
||||||
void SetLockRotation(bool value);
|
void SetLockRotation(bool value) { m_LockRotation = value; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this entity is currently rotationally locked
|
* Returns whether this entity is currently rotationally locked
|
||||||
* @return true if the entity is rotationally locked, false otherwise
|
* @return true if the entity is rotationally locked, false otherwise
|
||||||
*/
|
*/
|
||||||
bool GetLockRotation() const;
|
bool GetLockRotation() const { return m_LockRotation; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to update the waypoint index, making the entity move to the next waypoint
|
* Attempts to update the waypoint index, making the entity move to the next waypoint
|
||||||
@@ -158,13 +151,7 @@ public:
|
|||||||
* Returns the waypoint this entity is supposed to move towards next
|
* Returns the waypoint this entity is supposed to move towards next
|
||||||
* @return the waypoint this entity is supposed to move towards next
|
* @return the waypoint this entity is supposed to move towards next
|
||||||
*/
|
*/
|
||||||
NiPoint3 GetNextWaypoint() const;
|
NiPoint3 GetNextWaypoint() const { return m_NextWaypoint; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current position of this entity
|
|
||||||
* @return the current position of this entity
|
|
||||||
*/
|
|
||||||
NiPoint3 GetCurrentPosition() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the approximate current location of the entity, including y coordinates
|
* Returns the approximate current location of the entity, including y coordinates
|
||||||
@@ -180,17 +167,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool Warp(const NiPoint3& point);
|
bool Warp(const NiPoint3& point);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the time it will take to reach the final waypoint according to the current speed
|
|
||||||
* @return the time it will take to reach the final waypoint according to the current speed
|
|
||||||
*/
|
|
||||||
float GetTimer() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the entity is at its final waypoint
|
* Returns if the entity is at its final waypoint
|
||||||
* @return if the entity is at its final waypoint
|
* @return if the entity is at its final waypoint
|
||||||
*/
|
*/
|
||||||
bool AtFinalWaypoint() const;
|
bool AtFinalWaypoint() const { return m_AtFinalWaypoint; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the entity stationary
|
* Renders the entity stationary
|
||||||
@@ -250,17 +231,12 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The max speed this entity may move at
|
* The max speed this entity may move at
|
||||||
*/
|
*/
|
||||||
float m_Speed;
|
float m_MaxSpeed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time it will take to reach the next waypoint using the current speed
|
* The time it will take to reach the next waypoint using the current speed
|
||||||
*/
|
*/
|
||||||
float m_Timer;
|
float m_TimeTravelled;
|
||||||
|
|
||||||
/**
|
|
||||||
* The total time it will take to reach the waypoint form its starting point
|
|
||||||
*/
|
|
||||||
float m_TotalTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path this entity is currently traversing
|
* The path this entity is currently traversing
|
||||||
@@ -270,7 +246,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* If the entity has reached it last waypoint
|
* If the entity has reached it last waypoint
|
||||||
*/
|
*/
|
||||||
bool m_Done;
|
bool m_AtFinalWaypoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The speed the entity is currently moving at
|
* The speed the entity is currently moving at
|
||||||
@@ -287,6 +263,11 @@ private:
|
|||||||
*/
|
*/
|
||||||
float m_HaltDistance;
|
float m_HaltDistance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total time it will take to reach the waypoint form its starting point
|
||||||
|
*/
|
||||||
|
float m_TimeToTravel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base speed this entity has
|
* The base speed this entity has
|
||||||
*/
|
*/
|
||||||
@@ -295,7 +276,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* If the AI is currently turned of (e.g. when teleporting to some location)
|
* If the AI is currently turned of (e.g. when teleporting to some location)
|
||||||
*/
|
*/
|
||||||
bool m_Interrupted;
|
bool m_PullingToPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A position that the entity is currently moving towards while being interrupted
|
* A position that the entity is currently moving towards while being interrupted
|
||||||
@@ -315,17 +296,12 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The path the entity is currently following
|
* The path the entity is currently following
|
||||||
*/
|
*/
|
||||||
std::vector<NiPoint3> m_CurrentPath;
|
std::vector<NiPoint3> m_InterpolatedWaypoints;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue of positions to traverse
|
* The path from the current position to the destination.
|
||||||
*/
|
*/
|
||||||
std::stack<NiPoint3> m_Queue;
|
std::stack<NiPoint3> m_CurrentPath;
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache of all lots and their respective speeds
|
|
||||||
*/
|
|
||||||
static std::map<LOT, float> m_PhysicsSpeedCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOVEMENTAICOMPONENT_H
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) {
|
|||||||
|
|
||||||
MoverSubComponent::~MoverSubComponent() = default;
|
MoverSubComponent::~MoverSubComponent() = default;
|
||||||
|
|
||||||
void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const {
|
void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write<bool>(true);
|
outBitStream->Write<bool>(true);
|
||||||
|
|
||||||
outBitStream->Write<uint32_t>(static_cast<uint32_t>(mState));
|
outBitStream->Write<uint32_t>(static_cast<uint32_t>(mState));
|
||||||
@@ -71,7 +71,7 @@ MovingPlatformComponent::~MovingPlatformComponent() {
|
|||||||
delete static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
delete static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
// Here we don't serialize the moving platform to let the client simulate the movement
|
// Here we don't serialize the moving platform to let the client simulate the movement
|
||||||
|
|
||||||
if (!m_Serialize) {
|
if (!m_Serialize) {
|
||||||
@@ -112,7 +112,7 @@ void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bI
|
|||||||
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
|
if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) {
|
||||||
// TODO
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
mover->Serialize(outBitStream, bIsInitialUpdate, flags);
|
mover->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
MoverSubComponent(const NiPoint3& startPos);
|
MoverSubComponent(const NiPoint3& startPos);
|
||||||
~MoverSubComponent();
|
~MoverSubComponent();
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) const;
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state the platform is currently in
|
* The state the platform is currently in
|
||||||
@@ -111,7 +111,7 @@ public:
|
|||||||
MovingPlatformComponent(Entity* parent, const std::string& pathName);
|
MovingPlatformComponent(Entity* parent, const std::string& pathName);
|
||||||
~MovingPlatformComponent() override;
|
~MovingPlatformComponent() override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops all pathing, called when an entity starts a quick build associated with this platform
|
* Stops all pathing, called when an entity starts a quick build associated with this platform
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "RocketLaunchLupComponent.h"
|
#include "MultiZoneEntranceComponent.h"
|
||||||
#include "RocketLaunchpadControlComponent.h"
|
#include "RocketLaunchpadControlComponent.h"
|
||||||
#include "InventoryComponent.h"
|
#include "InventoryComponent.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
|
|
||||||
RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) {
|
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Component(parent) {
|
||||||
m_Parent = parent;
|
m_Parent = parent;
|
||||||
std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar<std::u16string>(u"MultiZoneIDs"));
|
std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar<std::u16string>(u"MultiZoneIDs"));
|
||||||
std::stringstream ss(zoneString);
|
std::stringstream ss(zoneString);
|
||||||
@@ -14,17 +14,17 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RocketLaunchLupComponent::~RocketLaunchLupComponent() {}
|
MultiZoneEntranceComponent::~MultiZoneEntranceComponent() {}
|
||||||
|
|
||||||
void RocketLaunchLupComponent::OnUse(Entity* originator) {
|
void MultiZoneEntranceComponent::OnUse(Entity* originator) {
|
||||||
auto* rocket = originator->GetComponent<CharacterComponent>()->RocketEquip(originator);
|
auto* rocket = originator->GetComponent<CharacterComponent>()->RocketEquip(originator);
|
||||||
if (!rocket) return;
|
if (!rocket) return;
|
||||||
|
|
||||||
// the LUP world menu is just the property menu, the client knows how to handle it
|
// the LUP world menu is just the property menu, the client knows how to handle it
|
||||||
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress());
|
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), originator->GetSystemAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) {
|
void MultiZoneEntranceComponent::OnSelectWorld(Entity* originator, uint32_t index) {
|
||||||
auto* rocketLaunchpadControlComponent = m_Parent->GetComponent<RocketLaunchpadControlComponent>();
|
auto* rocketLaunchpadControlComponent = m_Parent->GetComponent<RocketLaunchpadControlComponent>();
|
||||||
if (!rocketLaunchpadControlComponent) return;
|
if (!rocketLaunchpadControlComponent) return;
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "GameMessages.h"
|
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
@@ -9,16 +8,16 @@
|
|||||||
* Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds.
|
* Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class RocketLaunchLupComponent : public Component {
|
class MultiZoneEntranceComponent : public Component {
|
||||||
public:
|
public:
|
||||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH_LUP;
|
static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for this component, builds the m_LUPWorlds vector
|
* Constructor for this component, builds the m_LUPWorlds vector
|
||||||
* @param parent parent that contains this component
|
* @param parent parent that contains this component
|
||||||
*/
|
*/
|
||||||
RocketLaunchLupComponent(Entity* parent);
|
MultiZoneEntranceComponent(Entity* parent);
|
||||||
~RocketLaunchLupComponent() override;
|
~MultiZoneEntranceComponent() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user