mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 07:24:53 +00:00
commit
9ce60e7eff
49 changed files with 1074 additions and 1338 deletions
|
|
@ -8540,19 +8540,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1219,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1097,
|
|
||||||
"AbsX": 3096.68848,
|
|
||||||
"AbsY": 3181.219,
|
|
||||||
"AbsZ": 81.5115,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 676,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 796,
|
"Id": 796,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -8566,45 +8553,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1077,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 945,
|
|
||||||
"AbsX": 3709.01025,
|
|
||||||
"AbsY": 2115.38623,
|
|
||||||
"AbsZ": 57.0175171,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 678,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 394,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 262,
|
|
||||||
"AbsX": 3807.348,
|
|
||||||
"AbsY": 5458.795,
|
|
||||||
"AbsZ": 38.2669373,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 679,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 515,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 414,
|
|
||||||
"AbsX": 4271.57471,
|
|
||||||
"AbsY": 4504.82471,
|
|
||||||
"AbsZ": 73.70659,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 680,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 936,
|
"Id": 936,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -8618,32 +8566,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 124,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 4,
|
|
||||||
"AbsX": 4503.59473,
|
|
||||||
"AbsY": 6168.89941,
|
|
||||||
"AbsZ": 52.4856033,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 682,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 667,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 535,
|
|
||||||
"AbsX": 4602.546,
|
|
||||||
"AbsY": 3341.289,
|
|
||||||
"AbsZ": 37.3147659,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 683,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 242,
|
"Id": 242,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
|
||||||
|
|
@ -10256,32 +10256,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 2157,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 2056,
|
|
||||||
"AbsX": 1896.58,
|
|
||||||
"AbsY": 2983.99878,
|
|
||||||
"AbsZ": 52.99063,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 812,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 972,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 852,
|
|
||||||
"AbsX": 2434.74072,
|
|
||||||
"AbsY": 3695.22168,
|
|
||||||
"AbsZ": 35.8926926,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 813,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1211,
|
"Id": 1211,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -10308,58 +10282,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 551,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 419,
|
|
||||||
"AbsX": 3499.93652,
|
|
||||||
"AbsY": 4014.81616,
|
|
||||||
"AbsZ": 13.9436874,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 816,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 843,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 723,
|
|
||||||
"AbsX": 3972.74072,
|
|
||||||
"AbsY": 5945.22168,
|
|
||||||
"AbsZ": 33.9761276,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 817,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 105,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 4,
|
|
||||||
"AbsX": 4488.001,
|
|
||||||
"AbsY": 3474.57983,
|
|
||||||
"AbsZ": 42.84017,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 818,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 703,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 571,
|
|
||||||
"AbsX": 4520.795,
|
|
||||||
"AbsY": 2592.652,
|
|
||||||
"AbsZ": 14.5540581,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 819,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 247,
|
"Id": 247,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -10373,32 +10295,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1351,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1231,
|
|
||||||
"AbsX": 5602.91162,
|
|
||||||
"AbsY": 2873.561,
|
|
||||||
"AbsZ": 31.6628265,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 821,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 399,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 267,
|
|
||||||
"AbsX": 6707.348,
|
|
||||||
"AbsY": 2332.795,
|
|
||||||
"AbsZ": 113.330261,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 822,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 2148,
|
"Id": 2148,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -15508,32 +15508,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 781,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 661,
|
|
||||||
"AbsX": 579.2592,
|
|
||||||
"AbsY": 7032.77832,
|
|
||||||
"AbsZ": 54.5858879,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1234,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 2289,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 2157,
|
|
||||||
"AbsX": 621.848267,
|
|
||||||
"AbsY": 2375.897,
|
|
||||||
"AbsZ": 38.1845856,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1235,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 109,
|
"Id": 109,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -15547,19 +15521,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 230,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 129,
|
|
||||||
"AbsX": 1193.9021,
|
|
||||||
"AbsY": 4565.57031,
|
|
||||||
"AbsZ": 72.3534,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1237,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1302,
|
"Id": 1302,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -15573,32 +15534,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1063,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 943,
|
|
||||||
"AbsX": 2755.58032,
|
|
||||||
"AbsY": 1433.88428,
|
|
||||||
"AbsZ": 58.6747551,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1239,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1173,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1072,
|
|
||||||
"AbsX": 2962.00122,
|
|
||||||
"AbsY": 2320.57983,
|
|
||||||
"AbsZ": 72.81362,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1240,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 2008,
|
"Id": 2008,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -15612,71 +15547,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 383,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 251,
|
|
||||||
"AbsX": 4202.795,
|
|
||||||
"AbsY": 6984.652,
|
|
||||||
"AbsZ": 38.1436462,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1242,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1856,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1734,
|
|
||||||
"AbsX": 4988.68848,
|
|
||||||
"AbsY": 4439.21875,
|
|
||||||
"AbsZ": 60.90174,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1243,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 652,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 532,
|
|
||||||
"AbsX": 5045.78662,
|
|
||||||
"AbsY": 5840.68945,
|
|
||||||
"AbsZ": 51.4351578,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1244,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 922,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 790,
|
|
||||||
"AbsX": 5172.795,
|
|
||||||
"AbsY": 3356.652,
|
|
||||||
"AbsZ": 32.1784973,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1245,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 512,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 403,
|
|
||||||
"AbsX": 5638.105,
|
|
||||||
"AbsY": 6598.934,
|
|
||||||
"AbsZ": 57.89732,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1246,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 2137,
|
"Id": 2137,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -15703,32 +15573,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1443,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1323,
|
|
||||||
"AbsX": 7037.47266,
|
|
||||||
"AbsY": 1186.01941,
|
|
||||||
"AbsZ": 51.6652679,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1249,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1561,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1452,
|
|
||||||
"AbsX": 7331.6543,
|
|
||||||
"AbsY": 3069.78076,
|
|
||||||
"AbsZ": 69.8796158,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 1250,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 760,
|
"Id": 760,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -12076,58 +12076,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 266,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 146,
|
|
||||||
"AbsX": 928.198,
|
|
||||||
"AbsY": 5564.63672,
|
|
||||||
"AbsZ": 67.040596,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 954,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 407,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 275,
|
|
||||||
"AbsX": 1742.43945,
|
|
||||||
"AbsY": 5716.78564,
|
|
||||||
"AbsZ": 23.85953,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 955,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 126,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 4,
|
|
||||||
"AbsX": 2746.68848,
|
|
||||||
"AbsY": 4419.21875,
|
|
||||||
"AbsZ": 46.284523,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 956,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1359,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1239,
|
|
||||||
"AbsX": 3070.05664,
|
|
||||||
"AbsY": 2282.41748,
|
|
||||||
"AbsZ": 65.20178,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 957,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 536,
|
"Id": 536,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -12154,32 +12102,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1469,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1368,
|
|
||||||
"AbsX": 3986.8877,
|
|
||||||
"AbsY": 2494.16553,
|
|
||||||
"AbsZ": 94.4665756,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 960,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 676,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 556,
|
|
||||||
"AbsX": 4336.439,
|
|
||||||
"AbsY": 5866.91162,
|
|
||||||
"AbsZ": 72.2181549,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 961,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1621,
|
"Id": 1621,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -12193,45 +12115,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 938,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 837,
|
|
||||||
"AbsX": 4818.013,
|
|
||||||
"AbsY": 5254.69775,
|
|
||||||
"AbsZ": 80.30203,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 963,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1078,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 958,
|
|
||||||
"AbsX": 6638.752,
|
|
||||||
"AbsY": 4596.15527,
|
|
||||||
"AbsZ": 40.2804756,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 964,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1219,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1087,
|
|
||||||
"AbsX": 6998.91943,
|
|
||||||
"AbsY": 5326.044,
|
|
||||||
"AbsZ": 21.9767818,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 965,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 245,
|
"Id": 245,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -8969,32 +8969,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1219,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1110,
|
|
||||||
"AbsX": 2700.56641,
|
|
||||||
"AbsY": 2938.72949,
|
|
||||||
"AbsZ": 60.2481575,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 711,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 959,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 839,
|
|
||||||
"AbsX": 3376.60767,
|
|
||||||
"AbsY": 2457.89429,
|
|
||||||
"AbsZ": 50.8711739,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 712,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 136,
|
"Id": 136,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -9008,45 +8982,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1090,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 968,
|
|
||||||
"AbsX": 3664.68848,
|
|
||||||
"AbsY": 4789.21875,
|
|
||||||
"AbsZ": 64.9002762,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 714,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 288,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 156,
|
|
||||||
"AbsX": 4365.159,
|
|
||||||
"AbsY": 4282.131,
|
|
||||||
"AbsZ": 60.087677,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 715,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1817,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1716,
|
|
||||||
"AbsX": 4649.79736,
|
|
||||||
"AbsY": 2642.05566,
|
|
||||||
"AbsZ": 70.51741,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 716,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 819,
|
"Id": 819,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -9060,32 +8995,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 580,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 460,
|
|
||||||
"AbsX": 5467.6167,
|
|
||||||
"AbsY": 3842.79272,
|
|
||||||
"AbsZ": 55.66716,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 718,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 690,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 589,
|
|
||||||
"AbsX": 5904.2207,
|
|
||||||
"AbsY": 4439.24854,
|
|
||||||
"AbsZ": 69.2569962,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 719,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 440,
|
"Id": 440,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
|
||||||
|
|
@ -9346,45 +9346,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1063,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 931,
|
|
||||||
"AbsX": 2961.79932,
|
|
||||||
"AbsY": 2185.03418,
|
|
||||||
"AbsZ": 221.338272,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 738,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 391,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 271,
|
|
||||||
"AbsX": 3254.05664,
|
|
||||||
"AbsY": 5804.41748,
|
|
||||||
"AbsZ": 229.117279,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 739,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 641,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 521,
|
|
||||||
"AbsX": 3631.02051,
|
|
||||||
"AbsY": 3791.069,
|
|
||||||
"AbsZ": 217.111908,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 740,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 501,
|
"Id": 501,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -9411,32 +9372,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 251,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 129,
|
|
||||||
"AbsX": 3996.68848,
|
|
||||||
"AbsY": 4335.21875,
|
|
||||||
"AbsZ": 273.429138,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 743,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 109,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 0,
|
|
||||||
"AbsX": 4421.5625,
|
|
||||||
"AbsY": 3720.8457,
|
|
||||||
"AbsZ": 225.8448,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 744,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1215,
|
"Id": 1215,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -9450,19 +9385,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 770,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 650,
|
|
||||||
"AbsX": 5926.77832,
|
|
||||||
"AbsY": 3396.74072,
|
|
||||||
"AbsZ": 91.09625,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 746,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1048,
|
"Id": 1048,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -11608,19 +11608,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 653,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 533,
|
|
||||||
"AbsX": 910.7408,
|
|
||||||
"AbsY": 2667.22168,
|
|
||||||
"AbsZ": 68.7458649,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 920,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1454,
|
"Id": 1454,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -11634,71 +11621,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1575,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1474,
|
|
||||||
"AbsX": 2006.28674,
|
|
||||||
"AbsY": 5523.80127,
|
|
||||||
"AbsZ": 82.80721,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 922,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1727,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1595,
|
|
||||||
"AbsX": 2346.10083,
|
|
||||||
"AbsY": 1945.51868,
|
|
||||||
"AbsZ": 69.6338654,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 923,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 513,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 404,
|
|
||||||
"AbsX": 2915.07471,
|
|
||||||
"AbsY": 3768.05469,
|
|
||||||
"AbsZ": 62.5202637,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 924,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 126,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 4,
|
|
||||||
"AbsX": 3224.68848,
|
|
||||||
"AbsY": 7367.21875,
|
|
||||||
"AbsZ": 84.523674,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 925,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 395,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 275,
|
|
||||||
"AbsX": 3324.40527,
|
|
||||||
"AbsY": 4578.996,
|
|
||||||
"AbsZ": 69.99102,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 926,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1302,
|
"Id": 1302,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -11712,32 +11634,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 266,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 146,
|
|
||||||
"AbsX": 3992.53369,
|
|
||||||
"AbsY": 6048.867,
|
|
||||||
"AbsZ": 54.7470245,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 928,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 900,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 791,
|
|
||||||
"AbsX": 4019.30933,
|
|
||||||
"AbsY": 1613.07593,
|
|
||||||
"AbsZ": 75.31056,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 929,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1052,
|
"Id": 1052,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -11751,32 +11647,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 782,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 662,
|
|
||||||
"AbsX": 5400.74072,
|
|
||||||
"AbsY": 2541.22168,
|
|
||||||
"AbsZ": 48.0176964,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 931,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1181,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1072,
|
|
||||||
"AbsX": 6832.797,
|
|
||||||
"AbsY": 4254.491,
|
|
||||||
"AbsZ": 53.264,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 932,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 632,
|
"Id": 632,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -8683,32 +8683,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 645,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 525,
|
|
||||||
"AbsX": 2226.74072,
|
|
||||||
"AbsY": 3381.22168,
|
|
||||||
"AbsZ": 47.1299973,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 687,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 763,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 654,
|
|
||||||
"AbsX": 2532.84058,
|
|
||||||
"AbsY": 4528.31738,
|
|
||||||
"AbsZ": 50.48315,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 688,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 915,
|
"Id": 915,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -8735,32 +8709,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 376,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 275,
|
|
||||||
"AbsX": 3904.129,
|
|
||||||
"AbsY": 4695.489,
|
|
||||||
"AbsZ": 63.15471,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 691,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1219,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1087,
|
|
||||||
"AbsX": 3958.74463,
|
|
||||||
"AbsY": 2196.716,
|
|
||||||
"AbsZ": 45.3599777,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 692,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1067,
|
"Id": 1067,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -8774,32 +8722,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 266,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 146,
|
|
||||||
"AbsX": 4748.437,
|
|
||||||
"AbsY": 5469.24854,
|
|
||||||
"AbsZ": 48.33355,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 694,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 516,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 396,
|
|
||||||
"AbsX": 5497.22266,
|
|
||||||
"AbsY": 3957.127,
|
|
||||||
"AbsZ": 45.2092972,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 695,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 624,
|
"Id": 624,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -12297,84 +12297,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1760,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1640,
|
|
||||||
"AbsX": 1224.89941,
|
|
||||||
"AbsY": 4202.40527,
|
|
||||||
"AbsZ": 54.66005,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 975,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1870,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1769,
|
|
||||||
"AbsX": 1742.0011,
|
|
||||||
"AbsY": 5306.58,
|
|
||||||
"AbsZ": 77.51988,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 976,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 731,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 611,
|
|
||||||
"AbsX": 3749.88428,
|
|
||||||
"AbsY": 5510.41943,
|
|
||||||
"AbsZ": 230.786942,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 977,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1478,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1369,
|
|
||||||
"AbsX": 3756.67651,
|
|
||||||
"AbsY": 2149.56226,
|
|
||||||
"AbsZ": 66.70892,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 978,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 287,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 155,
|
|
||||||
"AbsX": 3765.75122,
|
|
||||||
"AbsY": 2659.72437,
|
|
||||||
"AbsZ": 135.187622,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 979,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1110,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 990,
|
|
||||||
"AbsX": 4018.3623,
|
|
||||||
"AbsY": 4194.70264,
|
|
||||||
"AbsZ": 199.684,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 980,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1349,
|
"Id": 1349,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -12388,19 +12310,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 439,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 307,
|
|
||||||
"AbsX": 4610.795,
|
|
||||||
"AbsY": 5718.652,
|
|
||||||
"AbsZ": 174.196381,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 982,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 841,
|
"Id": 841,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -12414,19 +12323,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1220,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1119,
|
|
||||||
"AbsX": 4890.966,
|
|
||||||
"AbsY": 4531.238,
|
|
||||||
"AbsZ": 222.527054,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 984,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 135,
|
"Id": 135,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -12440,45 +12336,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 970,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 861,
|
|
||||||
"AbsX": 5289.592,
|
|
||||||
"AbsY": 5012.38135,
|
|
||||||
"AbsZ": 246.0418,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 986,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1620,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1498,
|
|
||||||
"AbsX": 5819.02344,
|
|
||||||
"AbsY": 2305.157,
|
|
||||||
"AbsZ": 97.94419,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 987,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 591,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 459,
|
|
||||||
"AbsX": 6428.63965,
|
|
||||||
"AbsY": 5190.393,
|
|
||||||
"AbsZ": 39.42817,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 988,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1739,
|
"Id": 1739,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -10932,45 +10932,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 528,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 396,
|
|
||||||
"AbsX": 2734.795,
|
|
||||||
"AbsY": 2374.652,
|
|
||||||
"AbsZ": 41.2234421,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 866,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 961,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 829,
|
|
||||||
"AbsX": 3390.795,
|
|
||||||
"AbsY": 5754.652,
|
|
||||||
"AbsZ": 32.0256653,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 867,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 247,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 146,
|
|
||||||
"AbsX": 3507.72119,
|
|
||||||
"AbsY": 2540.61621,
|
|
||||||
"AbsZ": 62.4884148,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 868,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 1082,
|
"Id": 1082,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -10997,58 +10958,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 1351,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1231,
|
|
||||||
"AbsX": 4675.94336,
|
|
||||||
"AbsY": 6243.58252,
|
|
||||||
"AbsZ": 64.11465,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 871,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1211,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1102,
|
|
||||||
"AbsX": 4686.31738,
|
|
||||||
"AbsY": 5569.15967,
|
|
||||||
"AbsZ": 78.99428,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 872,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 2403,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 2294,
|
|
||||||
"AbsX": 4902.087,
|
|
||||||
"AbsY": 3510.83838,
|
|
||||||
"AbsZ": 54.2062263,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 873,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 680,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 548,
|
|
||||||
"AbsX": 5534.78564,
|
|
||||||
"AbsY": 2273.56055,
|
|
||||||
"AbsZ": 46.44301,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 874,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 820,
|
"Id": 820,
|
||||||
"ObjectName": "llm_socket",
|
"ObjectName": "llm_socket",
|
||||||
|
|
@ -11062,32 +10971,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 126,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 4,
|
|
||||||
"AbsX": 6312.68848,
|
|
||||||
"AbsY": 5329.21875,
|
|
||||||
"AbsZ": 68.8674545,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 876,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 1492,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 1360,
|
|
||||||
"AbsX": 6643.15137,
|
|
||||||
"AbsY": 4448.6543,
|
|
||||||
"AbsZ": 40.43171,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 877,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 513,
|
"Id": 513,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -1169,19 +1169,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 122,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 0,
|
|
||||||
"AbsX": 1974.68848,
|
|
||||||
"AbsY": 2035.21887,
|
|
||||||
"AbsZ": 42.69806,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 93,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 109,
|
"Id": 109,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -3782,45 +3782,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 449,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 317,
|
|
||||||
"AbsX": 1739.221,
|
|
||||||
"AbsY": 1776.55054,
|
|
||||||
"AbsZ": 74.7683,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 298,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 299,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 198,
|
|
||||||
"AbsX": 1839.926,
|
|
||||||
"AbsY": 2669.99561,
|
|
||||||
"AbsZ": 105.1724,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 299,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 831,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 722,
|
|
||||||
"AbsX": 2672.99951,
|
|
||||||
"AbsY": 2277.26343,
|
|
||||||
"AbsZ": 97.5842,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 300,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 434,
|
"Id": 434,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -3249,45 +3249,6 @@
|
||||||
"MapID": null,
|
"MapID": null,
|
||||||
"IsChildObject": true
|
"IsChildObject": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Id": 693,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 561,
|
|
||||||
"AbsX": 1273.68921,
|
|
||||||
"AbsY": 2544.30444,
|
|
||||||
"AbsZ": 72.1122742,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 257,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 246,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 145,
|
|
||||||
"AbsX": 1496.34106,
|
|
||||||
"AbsY": 1233.22192,
|
|
||||||
"AbsZ": 103.060211,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 258,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 127,
|
|
||||||
"ObjectName": "llm_socket",
|
|
||||||
"ObjectType": "llm_socket",
|
|
||||||
"Owner": 18,
|
|
||||||
"AbsX": 2862.687,
|
|
||||||
"AbsY": 2759.684,
|
|
||||||
"AbsZ": 95.47642,
|
|
||||||
"Yaw": 0.0,
|
|
||||||
"GUID": 259,
|
|
||||||
"MapID": null,
|
|
||||||
"IsChildObject": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Id": 678,
|
"Id": 678,
|
||||||
"ObjectName": "lock_external",
|
"ObjectName": "lock_external",
|
||||||
|
|
|
||||||
|
|
@ -404,6 +404,8 @@ class ChatActor(
|
||||||
case ("nc", pos) => Some(PlanetSideEmpire.NC, pos)
|
case ("nc", pos) => Some(PlanetSideEmpire.NC, pos)
|
||||||
case ("vs", pos) => Some(PlanetSideEmpire.VS, pos)
|
case ("vs", pos) => Some(PlanetSideEmpire.VS, pos)
|
||||||
case ("none", pos) => Some(PlanetSideEmpire.NEUTRAL, pos)
|
case ("none", pos) => Some(PlanetSideEmpire.NEUTRAL, pos)
|
||||||
|
case ("bo", pos) => Some(PlanetSideEmpire.NEUTRAL, pos)
|
||||||
|
case ("neutral", pos) => Some(PlanetSideEmpire.NEUTRAL, pos)
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
.headOption match {
|
.headOption match {
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,11 @@
|
||||||
package net.psforever.actors.session
|
package net.psforever.actors.session
|
||||||
|
|
||||||
import akka.actor.typed
|
|
||||||
import akka.actor.typed.receptionist.Receptionist
|
import akka.actor.typed.receptionist.Receptionist
|
||||||
import akka.actor.typed.scaladsl.adapter._
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
import akka.actor.{Actor, ActorRef, Cancellable, MDCContextAware}
|
import akka.actor.{Actor, ActorRef, Cancellable, MDCContextAware, typed}
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import net.psforever.actors.net.MiddlewareActor
|
import net.psforever.actors.net.MiddlewareActor
|
||||||
import net.psforever.services.ServiceManager.Lookup
|
|
||||||
import net.psforever.objects.locker.LockerContainer
|
|
||||||
import org.log4s.MDC
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.concurrent.{Await, Future}
|
|
||||||
import scala.concurrent.duration._
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
|
||||||
import scala.util.Success
|
|
||||||
import net.psforever.login.WorldSession._
|
import net.psforever.login.WorldSession._
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.avatar._
|
import net.psforever.objects.avatar._
|
||||||
|
|
@ -27,7 +17,7 @@ import net.psforever.objects.entity.{SimpleWorldEntity, WorldEntity}
|
||||||
import net.psforever.objects.equipment._
|
import net.psforever.objects.equipment._
|
||||||
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||||
import net.psforever.objects.inventory.{Container, InventoryItem}
|
import net.psforever.objects.inventory.{Container, InventoryItem}
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
import net.psforever.objects.locker.LockerContainer
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.serverobject.containable.Containable
|
import net.psforever.objects.serverobject.containable.Containable
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
import net.psforever.objects.serverobject.damage.Damageable
|
||||||
|
|
@ -35,6 +25,7 @@ import net.psforever.objects.serverobject.deploy.Deployment
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.generator.Generator
|
import net.psforever.objects.serverobject.generator.Generator
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
import net.psforever.objects.serverobject.locks.IFFLock
|
import net.psforever.objects.serverobject.locks.IFFLock
|
||||||
import net.psforever.objects.serverobject.mblocker.Locker
|
import net.psforever.objects.serverobject.mblocker.Locker
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
|
|
@ -47,9 +38,10 @@ import net.psforever.objects.serverobject.terminals.implant.ImplantTerminalMech
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
import net.psforever.objects.serverobject.turret.{FacilityTurret, WeaponTurret}
|
import net.psforever.objects.serverobject.turret.{FacilityTurret, WeaponTurret}
|
||||||
import net.psforever.objects.serverobject.zipline.ZipLinePath
|
import net.psforever.objects.serverobject.zipline.ZipLinePath
|
||||||
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.objects.teamwork.Squad
|
import net.psforever.objects.teamwork.Squad
|
||||||
import net.psforever.objects.vehicles._
|
|
||||||
import net.psforever.objects.vehicles.Utility.InternalTelepad
|
import net.psforever.objects.vehicles.Utility.InternalTelepad
|
||||||
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.vital._
|
import net.psforever.objects.vital._
|
||||||
import net.psforever.objects.vital.base._
|
import net.psforever.objects.vital.base._
|
||||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||||
|
|
@ -57,14 +49,14 @@ import net.psforever.objects.vital.projectile.ProjectileReason
|
||||||
import net.psforever.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
|
import net.psforever.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
|
||||||
import net.psforever.packet._
|
import net.psforever.packet._
|
||||||
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
||||||
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo, _}
|
|
||||||
import net.psforever.packet.game.objectcreate._
|
import net.psforever.packet.game.objectcreate._
|
||||||
import net.psforever.services.ServiceManager.LookupResult
|
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo, _}
|
||||||
|
import net.psforever.services.ServiceManager.{Lookup, LookupResult}
|
||||||
import net.psforever.services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
|
import net.psforever.services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
import net.psforever.services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
||||||
import net.psforever.services.chat.ChatService
|
import net.psforever.services.chat.ChatService
|
||||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse}
|
import net.psforever.services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse}
|
||||||
import net.psforever.services.local.support.{HackCaptureActor, RouterTelepadActivation}
|
import net.psforever.services.local.support.{CaptureFlagManager, HackCaptureActor, RouterTelepadActivation}
|
||||||
import net.psforever.services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
import net.psforever.services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
||||||
import net.psforever.services.properties.PropertyOverrideManager
|
import net.psforever.services.properties.PropertyOverrideManager
|
||||||
import net.psforever.services.support.SupportActor
|
import net.psforever.services.support.SupportActor
|
||||||
|
|
@ -75,6 +67,13 @@ import net.psforever.services.{RemoverActor, Service, ServiceManager, Interstell
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
import net.psforever.util.{Config, DefinitionUtil}
|
import net.psforever.util.{Config, DefinitionUtil}
|
||||||
import net.psforever.zones.Zones
|
import net.psforever.zones.Zones
|
||||||
|
import org.log4s.MDC
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import scala.concurrent.{Await, Future}
|
||||||
|
import scala.util.Success
|
||||||
|
|
||||||
object SessionActor {
|
object SessionActor {
|
||||||
sealed trait Command
|
sealed trait Command
|
||||||
|
|
@ -203,6 +202,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
var setupAvatarFunc: () => Unit = AvatarCreate
|
var setupAvatarFunc: () => Unit = AvatarCreate
|
||||||
var setCurrentAvatarFunc: Player => Unit = SetCurrentAvatarNormally
|
var setCurrentAvatarFunc: Player => Unit = SetCurrentAvatarNormally
|
||||||
var persist: () => Unit = NoPersistence
|
var persist: () => Unit = NoPersistence
|
||||||
|
var specialItemSlotGuid : Option[PlanetSideGUID] = None // If a special item (e.g. LLU) has been attached to the player the GUID should be stored here, or cleared when dropped, since the drop hotkey doesn't send the GUID of the object to be dropped.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used during zone transfers to maintain reference to seated vehicle (which does not yet exist in the new zone)
|
* used during zone transfers to maintain reference to seated vehicle (which does not yet exist in the new zone)
|
||||||
|
|
@ -555,6 +555,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case GalaxyResponse.MapUpdate(msg) =>
|
case GalaxyResponse.MapUpdate(msg) =>
|
||||||
sendResponse(msg)
|
sendResponse(msg)
|
||||||
|
|
||||||
|
case GalaxyResponse.FlagMapUpdate(msg) =>
|
||||||
|
sendResponse(msg)
|
||||||
|
|
||||||
case GalaxyResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete, manifest) =>
|
case GalaxyResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete, manifest) =>
|
||||||
(manifest.passengers.find { case (name, _) => player.Name.equals(name) } match {
|
(manifest.passengers.find { case (name, _) => player.Name.equals(name) } match {
|
||||||
case Some((name, index)) if vehicle.Seats(index).occupant.isEmpty =>
|
case Some((name, index)) if vehicle.Seats(index).occupant.isEmpty =>
|
||||||
|
|
@ -968,6 +971,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
CancelZoningProcess()
|
CancelZoningProcess()
|
||||||
PlayerActionsToCancel()
|
PlayerActionsToCancel()
|
||||||
CancelAllProximityUnits()
|
CancelAllProximityUnits()
|
||||||
|
DropSpecialSlotItem()
|
||||||
continent.Population ! Zone.Population.Release(avatar)
|
continent.Population ! Zone.Population.Release(avatar)
|
||||||
response match {
|
response match {
|
||||||
case Some((zone, spawnPoint)) =>
|
case Some((zone, spawnPoint)) =>
|
||||||
|
|
@ -1802,6 +1806,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
CancelZoningProcessWithDescriptiveReason("cancel_dmg")
|
CancelZoningProcessWithDescriptiveReason("cancel_dmg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AvatarResponse.DropSpecialItem() =>
|
||||||
|
DropSpecialSlotItem()
|
||||||
|
|
||||||
case AvatarResponse.Killed(mount) =>
|
case AvatarResponse.Killed(mount) =>
|
||||||
val respawnTimer = 300.seconds
|
val respawnTimer = 300.seconds
|
||||||
//drop free hand item
|
//drop free hand item
|
||||||
|
|
@ -1810,25 +1817,32 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
DropEquipmentFromInventory(player)(item)
|
DropEquipmentFromInventory(player)(item)
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DropSpecialSlotItem()
|
||||||
ToggleMaxSpecialState(enable = false)
|
ToggleMaxSpecialState(enable = false)
|
||||||
|
|
||||||
keepAliveFunc = NormalKeepAlive
|
keepAliveFunc = NormalKeepAlive
|
||||||
zoningStatus = Zoning.Status.None
|
zoningStatus = Zoning.Status.None
|
||||||
deadState = DeadState.Dead
|
deadState = DeadState.Dead
|
||||||
|
|
||||||
continent.GUID(mount) match {
|
continent.GUID(mount) match {
|
||||||
case Some(obj: Vehicle) =>
|
case Some(obj: Vehicle) =>
|
||||||
TotalDriverVehicleControl(obj)
|
TotalDriverVehicleControl(obj)
|
||||||
UnaccessContainer(obj)
|
UnaccessContainer(obj)
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerActionsToCancel()
|
PlayerActionsToCancel()
|
||||||
CancelAllProximityUnits()
|
CancelAllProximityUnits()
|
||||||
CancelZoningProcessWithDescriptiveReason("cancel")
|
CancelZoningProcessWithDescriptiveReason("cancel")
|
||||||
|
|
||||||
if (shotsWhileDead > 0) {
|
if (shotsWhileDead > 0) {
|
||||||
log.warn(
|
log.warn(
|
||||||
s"KillPlayer/SHOTS_WHILE_DEAD: client of ${avatar.name} fired $shotsWhileDead rounds while character was dead on server"
|
s"KillPlayer/SHOTS_WHILE_DEAD: client of ${avatar.name} fired $shotsWhileDead rounds while character was dead on server"
|
||||||
)
|
)
|
||||||
shotsWhileDead = 0
|
shotsWhileDead = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
reviveTimer.cancel()
|
reviveTimer.cancel()
|
||||||
if (player.death_by == 0) {
|
if (player.death_by == 0) {
|
||||||
reviveTimer = context.system.scheduler.scheduleOnce(respawnTimer) {
|
reviveTimer = context.system.scheduler.scheduleOnce(respawnTimer) {
|
||||||
|
|
@ -2133,6 +2147,28 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def DropSpecialSlotItem(): Unit = {
|
||||||
|
specialItemSlotGuid match {
|
||||||
|
case Some(guid: PlanetSideGUID) =>
|
||||||
|
specialItemSlotGuid = None
|
||||||
|
continent.GUID(guid) match {
|
||||||
|
case Some(llu: CaptureFlag) =>
|
||||||
|
llu.Carrier match {
|
||||||
|
case Some(carrier: Player) if carrier.GUID == player.GUID =>
|
||||||
|
continent.LocalEvents ! CaptureFlagManager.DropFlag(llu)
|
||||||
|
case Some(carrier: Player) =>
|
||||||
|
log.warn(s"${player.toString} tried to drop LLU, but it is currently held by ${carrier.toString}")
|
||||||
|
case None =>
|
||||||
|
log.warn(s"${player.toString} tried to drop LLU, but nobody is holding it.")
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
log.warn(s"${player.toString} Tried to drop a special item that wasn't recognized. GUID: $guid")
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ => ; // Nothing to drop, do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enforce constraints on bulk purchases as determined by a given player's previous purchase times and hard acquisition delays.
|
* Enforce constraints on bulk purchases as determined by a given player's previous purchase times and hard acquisition delays.
|
||||||
* Intended to assist in sanitizing loadout information from the perspective of the player, or target owner.
|
* Intended to assist in sanitizing loadout information from the perspective of the player, or target owner.
|
||||||
|
|
@ -2290,6 +2326,40 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case LocalResponse.SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value) =>
|
case LocalResponse.SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value) =>
|
||||||
SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value)
|
SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value)
|
||||||
|
|
||||||
|
case LocalResponse.SendGenericObjectActionMessage(target_guid, action_number) =>
|
||||||
|
sendResponse(GenericObjectActionMessage(target_guid, action_number))
|
||||||
|
|
||||||
|
case LocalResponse.SendGenericActionMessage(action_number) =>
|
||||||
|
sendResponse(GenericActionMessage(action_number))
|
||||||
|
|
||||||
|
case LocalResponse.SendChatMsg(msg) =>
|
||||||
|
sendResponse(msg)
|
||||||
|
|
||||||
|
case LocalResponse.SendPacket(packet) =>
|
||||||
|
sendResponse(packet)
|
||||||
|
|
||||||
|
case LocalResponse.LluSpawned(llu) =>
|
||||||
|
// Create LLU on client
|
||||||
|
sendResponse(ObjectCreateMessage(
|
||||||
|
llu.Definition.ObjectId,
|
||||||
|
llu.GUID,
|
||||||
|
llu.Definition.Packet.ConstructorData(llu).get
|
||||||
|
))
|
||||||
|
|
||||||
|
sendResponse(TriggerSoundMessage(TriggeredSound.LLUMaterialize, llu.Position, unk = 20, 0.8000001f))
|
||||||
|
|
||||||
|
case LocalResponse.LluDespawned(llu) =>
|
||||||
|
sendResponse(TriggerSoundMessage(TriggeredSound.LLUDeconstruct, llu.Position, unk = 20, 0.8000001f))
|
||||||
|
sendResponse(ObjectDeleteMessage(llu.GUID, 0))
|
||||||
|
|
||||||
|
// If the player was holding the LLU, remove it from their tracked special item slot
|
||||||
|
specialItemSlotGuid match {
|
||||||
|
case Some(guid) =>
|
||||||
|
if (guid == llu.GUID) {
|
||||||
|
specialItemSlotGuid = None
|
||||||
|
}
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
case LocalResponse.ObjectDelete(object_guid, unk) =>
|
case LocalResponse.ObjectDelete(object_guid, unk) =>
|
||||||
if (tplayer_guid != guid) {
|
if (tplayer_guid != guid) {
|
||||||
sendResponse(ObjectDeleteMessage(object_guid, unk))
|
sendResponse(ObjectDeleteMessage(object_guid, unk))
|
||||||
|
|
@ -4144,7 +4214,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case None =>
|
case None =>
|
||||||
log.warn(s"DropItem: ${player.Name} wanted to drop a $anItem, but it wasn't at hand")
|
log.warn(s"DropItem: ${player.Name} wanted to drop a $anItem, but it wasn't at hand")
|
||||||
}
|
}
|
||||||
case Some(obj) => //TODO LLU
|
case Some(obj) =>
|
||||||
log.warn(s"DropItem: ${player.Name} wanted to drop a $obj, but that isn't possible")
|
log.warn(s"DropItem: ${player.Name} wanted to drop a $obj, but that isn't possible")
|
||||||
case None =>
|
case None =>
|
||||||
sendResponse(ObjectDeleteMessage(item_guid, 0)) //this is fine; item doesn't exist to the server anyway
|
sendResponse(ObjectDeleteMessage(item_guid, 0)) //this is fine; item doesn't exist to the server anyway
|
||||||
|
|
@ -4719,7 +4789,16 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case Some(item) =>
|
case Some(item) =>
|
||||||
CancelZoningProcessWithDescriptiveReason("cancel_use")
|
CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||||
captureTerminal.Actor ! CommonMessages.Use(player, Some(item))
|
captureTerminal.Actor ! CommonMessages.Use(player, Some(item))
|
||||||
case _ => ;
|
case _ if specialItemSlotGuid.nonEmpty =>
|
||||||
|
continent.GUID(specialItemSlotGuid) match {
|
||||||
|
case Some(llu: CaptureFlag) =>
|
||||||
|
if (llu.Target.GUID == captureTerminal.Owner.GUID) {
|
||||||
|
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.LluCaptured(llu))
|
||||||
|
} else {
|
||||||
|
log.info(s"LLU target is not this base. Target GUID: ${llu.Target.GUID} This base: ${captureTerminal.Owner.GUID}")
|
||||||
|
}
|
||||||
|
case _ => log.warn("Item in specialItemSlotGuid is not registered with continent or is not a LLU")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case Some(obj: FacilityTurret) =>
|
case Some(obj: FacilityTurret) =>
|
||||||
|
|
@ -4945,6 +5024,19 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case None => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Some(obj: CaptureFlag) =>
|
||||||
|
// LLU can normally only be picked up the faction that owns it
|
||||||
|
if (specialItemSlotGuid.isEmpty) {
|
||||||
|
if(obj.Faction == player.Faction) {
|
||||||
|
specialItemSlotGuid = Some(obj.GUID)
|
||||||
|
continent.LocalEvents ! CaptureFlagManager.PickupFlag(obj, player)
|
||||||
|
} else {
|
||||||
|
log.warn(s"Player ${player.toString} tried to pick up LLU ${obj.GUID} - ${obj.Faction} that doesn't belong to their faction")
|
||||||
|
}
|
||||||
|
} else if(specialItemSlotGuid.get != obj.GUID) { // Ignore duplicate pickup requests
|
||||||
|
log.warn(s"Player ${player.toString} tried to pick up LLU ${obj.GUID} - ${obj.Faction} but their special slot already contains $specialItemSlotGuid")
|
||||||
|
}
|
||||||
|
|
||||||
case Some(obj) =>
|
case Some(obj) =>
|
||||||
CancelZoningProcessWithDescriptiveReason("cancel_use")
|
CancelZoningProcessWithDescriptiveReason("cancel_use")
|
||||||
log.warn(s"UseItem: ${player.Name} does not know how to handle $obj")
|
log.warn(s"UseItem: ${player.Name} does not know how to handle $obj")
|
||||||
|
|
@ -5048,6 +5140,9 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
log.info(s"${player.Name} is back")
|
log.info(s"${player.Name} is back")
|
||||||
player.AwayFromKeyboard = false
|
player.AwayFromKeyboard = false
|
||||||
}
|
}
|
||||||
|
if (action == GenericActionEnum.DropSpecialItem.id) {
|
||||||
|
DropSpecialSlotItem()
|
||||||
|
}
|
||||||
if (action == 15) { //max deployment
|
if (action == 15) { //max deployment
|
||||||
log.info(s"${player.Name} has anchored ${player.Sex.pronounObject}self to the ground")
|
log.info(s"${player.Name} has anchored ${player.Sex.pronounObject}self to the ground")
|
||||||
player.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
player.UsingSpecial = SpecialExoSuitDefinition.Mode.Anchored
|
||||||
|
|
@ -6715,11 +6810,13 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
//sync model access state
|
//sync model access state
|
||||||
sendResponse(PlanetsideAttributeMessage(amenityId, 50, 0))
|
sendResponse(PlanetsideAttributeMessage(amenityId, 50, 0))
|
||||||
sendResponse(PlanetsideAttributeMessage(amenityId, 51, 0))
|
sendResponse(PlanetsideAttributeMessage(amenityId, 51, 0))
|
||||||
|
|
||||||
//sync damageable, if
|
//sync damageable, if
|
||||||
val health = amenity.Health
|
val health = amenity.Health
|
||||||
if (amenity.Definition.Damageable && health < amenity.MaxHealth) {
|
if (amenity.Definition.Damageable && health < amenity.MaxHealth) {
|
||||||
sendResponse(PlanetsideAttributeMessage(amenityId, 0, health))
|
sendResponse(PlanetsideAttributeMessage(amenityId, 0, health))
|
||||||
}
|
}
|
||||||
|
|
||||||
//sync special object type cases
|
//sync special object type cases
|
||||||
amenity match {
|
amenity match {
|
||||||
case silo: ResourceSilo =>
|
case silo: ResourceSilo =>
|
||||||
|
|
@ -6733,19 +6830,30 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
case door: Door if door.isOpen =>
|
case door: Door if door.isOpen =>
|
||||||
sendResponse(GenericObjectStateMsg(amenityId, 16))
|
sendResponse(GenericObjectStateMsg(amenityId, 16))
|
||||||
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
//sync hack state
|
|
||||||
amenity match {
|
|
||||||
case obj: Hackable if obj.HackedBy.nonEmpty =>
|
case obj: Hackable if obj.HackedBy.nonEmpty =>
|
||||||
|
//sync hack state
|
||||||
amenity.Definition match {
|
amenity.Definition match {
|
||||||
case GlobalDefinitions.capture_terminal =>
|
case GlobalDefinitions.capture_terminal =>
|
||||||
SendPlanetsideAttributeMessage(
|
SendPlanetsideAttributeMessage(
|
||||||
amenity.GUID,
|
amenity.GUID,
|
||||||
PlanetsideAttributeEnum.ControlConsoleHackUpdate,
|
PlanetsideAttributeEnum.ControlConsoleHackUpdate,
|
||||||
HackCaptureActor.GetHackUpdateAttributeValue(amenity.asInstanceOf[CaptureTerminal], isResecured = false))
|
HackCaptureActor.GetHackUpdateAttributeValue(amenity.asInstanceOf[CaptureTerminal], isResecured = false))
|
||||||
case _ =>
|
case _ =>
|
||||||
HackObject(amenity.GUID, 1114636288L, 8L) //generic hackable object
|
HackObject(amenity.GUID, 1114636288L, 8L) //generic hackable object
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync capture flags
|
||||||
|
case llu: CaptureFlag =>
|
||||||
|
// Create LLU
|
||||||
|
sendResponse(ObjectCreateMessage(
|
||||||
|
llu.Definition.ObjectId,
|
||||||
|
llu.GUID,
|
||||||
|
llu.Definition.Packet.ConstructorData(llu).get
|
||||||
|
))
|
||||||
|
|
||||||
|
// Attach it to a player if it has a carrier
|
||||||
|
if (llu.Carrier.nonEmpty) {
|
||||||
|
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.SendPacket(ObjectAttachMessage(llu.Carrier.get.GUID, llu.GUID, 252)))
|
||||||
}
|
}
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, Ca
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.persistence
|
import net.psforever.persistence
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState}
|
|
||||||
import net.psforever.util.Database._
|
|
||||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.services.{InterstellarClusterService, Service, ServiceManager}
|
import net.psforever.services.{InterstellarClusterService, Service, ServiceManager}
|
||||||
|
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState}
|
||||||
|
import net.psforever.util.Database._
|
||||||
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success}
|
||||||
|
|
@ -197,8 +197,8 @@ class BuildingActor(
|
||||||
|
|
||||||
case AmenityStateChange(gen: Generator, data) =>
|
case AmenityStateChange(gen: Generator, data) =>
|
||||||
if (generatorStateChange(gen, data)) {
|
if (generatorStateChange(gen, data)) {
|
||||||
//update the map
|
// Request all buildings update their map data to refresh lattice linked benefits
|
||||||
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||||
}
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
|
|
@ -364,7 +364,7 @@ class BuildingActor(
|
||||||
}
|
}
|
||||||
building.Faction = faction
|
building.Faction = faction
|
||||||
alignForceDomeStatus(mapUpdateOnChange = false)
|
alignForceDomeStatus(mapUpdateOnChange = false)
|
||||||
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
zone.actor ! ZoneActor.ZoneMapUpdate() // Update entire lattice to show lattice benefits
|
||||||
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import net.psforever.objects.vital.prop.DamageWithPosition
|
||||||
import net.psforever.objects.vital.{ComplexDeployableResolutions, MaxResolutions, SimpleResolutions}
|
import net.psforever.objects.vital.{ComplexDeployableResolutions, MaxResolutions, SimpleResolutions}
|
||||||
import net.psforever.types.{ExoSuitType, ImplantType, PlanetSideEmpire, Vector3}
|
import net.psforever.types.{ExoSuitType, ImplantType, PlanetSideEmpire, Vector3}
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
|
import net.psforever.objects.serverobject.llu.{CaptureFlagDefinition, CaptureFlagSocketDefinition}
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
@ -1069,6 +1070,11 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val vanu_control_console = new CaptureTerminalDefinition(930) // Cavern CC
|
val vanu_control_console = new CaptureTerminalDefinition(930) // Cavern CC
|
||||||
|
|
||||||
|
val llm_socket = new CaptureFlagSocketDefinition()
|
||||||
|
|
||||||
|
val capture_flag = new CaptureFlagDefinition()
|
||||||
|
capture_flag.Packet = new CaptureFlagConverter
|
||||||
|
|
||||||
val lodestar_repair_terminal = new MedicalTerminalDefinition(461)
|
val lodestar_repair_terminal = new MedicalTerminalDefinition(461)
|
||||||
|
|
||||||
val multivehicle_rearm_terminal = new OrderTerminalDefinition(576)
|
val multivehicle_rearm_terminal = new OrderTerminalDefinition(576)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ object ObjectType extends Enumeration {
|
||||||
val BoomerTrigger = "boomer_trigger"
|
val BoomerTrigger = "boomer_trigger"
|
||||||
val Building = "building"
|
val Building = "building"
|
||||||
val CaptureFlag = "capture_flag"
|
val CaptureFlag = "capture_flag"
|
||||||
val CaptureFlagSocket = "capture_flag_socket"
|
val CaptureFlagSocket = "llm_socket"
|
||||||
val CaptureTerminal = "capture_terminal"
|
val CaptureTerminal = "capture_terminal"
|
||||||
val CertTerminal = "cert_terminal"
|
val CertTerminal = "cert_terminal"
|
||||||
val ChainLashDamager = "chain_lash_damager"
|
val ChainLashDamager = "chain_lash_damager"
|
||||||
|
|
|
||||||
|
|
@ -710,12 +710,18 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
||||||
super.CancelJammeredStatus(target)
|
super.CancelJammeredStatus(target)
|
||||||
//uninitialize implants
|
//uninitialize implants
|
||||||
avatarActor ! AvatarActor.DeinitializeImplants()
|
avatarActor ! AvatarActor.DeinitializeImplants()
|
||||||
|
|
||||||
cause.adversarial match {
|
cause.adversarial match {
|
||||||
case Some(a) =>
|
case Some(a) =>
|
||||||
damageLog.info(s"DisplayDestroy: ${a.defender} was killed by ${a.attacker}")
|
damageLog.info(s"DisplayDestroy: ${a.defender} was killed by ${a.attacker}")
|
||||||
case _ =>
|
case _ =>
|
||||||
damageLog.info(s"DisplayDestroy: ${player.Name} killed ${player.Sex.pronounObject}self.")
|
damageLog.info(s"DisplayDestroy: ${player.Name} killed ${player.Sex.pronounObject}self.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This would normally happen async as part of AvatarAction.Killed, but if it doesn't happen before deleting calling AvatarAction.ObjectDelete on the player the LLU will end up invisible to others if carried
|
||||||
|
// Therefore, queue it up to happen first.
|
||||||
|
events ! AvatarServiceMessage(nameChannel, AvatarAction.DropSpecialItem())
|
||||||
|
|
||||||
events ! AvatarServiceMessage(
|
events ! AvatarServiceMessage(
|
||||||
nameChannel,
|
nameChannel,
|
||||||
AvatarAction.Killed(player_guid, target.VehicleSeated)
|
AvatarAction.Killed(player_guid, target.VehicleSeated)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package net.psforever.objects.definition.converter
|
||||||
|
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
|
import net.psforever.objects.serverobject.structures.Building
|
||||||
|
import net.psforever.packet.game.objectcreate.{CaptureFlagData, PlacementData}
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import scala.util.{Success, Try}
|
||||||
|
|
||||||
|
class CaptureFlagConverter extends ObjectCreateConverter[CaptureFlag]() {
|
||||||
|
override def ConstructorData(obj : CaptureFlag) : Try[CaptureFlagData] = {
|
||||||
|
val hackInfo = obj.Owner.asInstanceOf[Building].CaptureTerminal.get.HackedBy.get
|
||||||
|
val millisecondsRemaining = TimeUnit.MILLISECONDS.convert(math.max(0, hackInfo.hackStartTime + hackInfo.hackDuration - System.nanoTime), TimeUnit.NANOSECONDS)
|
||||||
|
|
||||||
|
Success(
|
||||||
|
CaptureFlagData(
|
||||||
|
new PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||||
|
obj.Faction,
|
||||||
|
obj.Owner.asInstanceOf[Building].GUID.guid,
|
||||||
|
obj.Target.GUID.guid,
|
||||||
|
millisecondsRemaining
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package net.psforever.objects.serverobject.llu
|
||||||
|
|
||||||
|
import net.psforever.objects.serverobject.structures.{Amenity, AmenityOwner, Building}
|
||||||
|
import net.psforever.objects.{GlobalDefinitions, Player}
|
||||||
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object represents the LLU that gets spawned at a LLU socket when a LLU control console is hacked
|
||||||
|
*/
|
||||||
|
class CaptureFlag(tDef: CaptureFlagDefinition) extends Amenity {
|
||||||
|
def Definition : CaptureFlagDefinition = tDef
|
||||||
|
|
||||||
|
private var target: Building = Building.NoBuilding
|
||||||
|
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||||
|
private var carrier: Option[Player] = None
|
||||||
|
|
||||||
|
def Target: Building = target
|
||||||
|
def Target_=(new_target: Building): Building = {
|
||||||
|
target = new_target
|
||||||
|
target
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since a LLU belongs to a base, but needs to be picked up by the enemy faction we need to be able to override the faction that owns the LLU to the hacker faction
|
||||||
|
override def Faction: PlanetSideEmpire.Value = faction
|
||||||
|
override def Faction_=(new_faction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
|
||||||
|
faction = new_faction
|
||||||
|
faction
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the flag is carried by a player, the position returned should be that of the carrier not the flag
|
||||||
|
override def Position: Vector3 = if (Carrier.nonEmpty) {
|
||||||
|
carrier.get.Position
|
||||||
|
} else {
|
||||||
|
Entity.Position
|
||||||
|
}
|
||||||
|
|
||||||
|
def Carrier: Option[Player] = carrier
|
||||||
|
def Carrier_=(new_carrier: Option[Player]) : Option[Player] = {
|
||||||
|
carrier = new_carrier
|
||||||
|
carrier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlag {
|
||||||
|
def apply(tDef: CaptureFlagDefinition): CaptureFlag = {
|
||||||
|
new CaptureFlag(tDef)
|
||||||
|
}
|
||||||
|
|
||||||
|
def Constructor(pos: Vector3, ori: Vector3, target: Building, owner: AmenityOwner, faction: PlanetSideEmpire.Value) : CaptureFlag = {
|
||||||
|
val obj = CaptureFlag(GlobalDefinitions.capture_flag)
|
||||||
|
obj.Position = pos
|
||||||
|
obj.Orientation = ori
|
||||||
|
obj.Target = target
|
||||||
|
obj.Owner = owner
|
||||||
|
obj.Faction = faction
|
||||||
|
|
||||||
|
obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package net.psforever.objects.serverobject.llu
|
||||||
|
|
||||||
|
import net.psforever.objects.serverobject.structures.AmenityDefinition
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The definition for any 'CaptureFlag'
|
||||||
|
* Object Id 157
|
||||||
|
*/
|
||||||
|
class CaptureFlagDefinition extends AmenityDefinition(157) {
|
||||||
|
Name = "capture_flag"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package net.psforever.objects.serverobject.llu
|
||||||
|
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
import net.psforever.objects.GlobalDefinitions
|
||||||
|
import net.psforever.objects.serverobject.structures.Amenity
|
||||||
|
import net.psforever.types.Vector3
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the LLU sockets found within bases that require LLU hacks.
|
||||||
|
* It is used as a position reference for spawning the LLU in the correct location when the base is hacked
|
||||||
|
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
|
*/
|
||||||
|
class CaptureFlagSocket(tDef: CaptureFlagSocketDefinition) extends Amenity {
|
||||||
|
def Definition : CaptureFlagSocketDefinition = tDef
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlagSocket {
|
||||||
|
def apply(tDef: CaptureFlagSocketDefinition) : CaptureFlagSocket = {
|
||||||
|
new CaptureFlagSocket(tDef)
|
||||||
|
}
|
||||||
|
|
||||||
|
def Constructor(pos: Vector3)(id: Int, context: ActorContext) : CaptureFlagSocket = {
|
||||||
|
Constructor(GlobalDefinitions.llm_socket, pos)(id, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
def Constructor(tdef: CaptureFlagSocketDefinition, pos: Vector3)(id: Int, context: ActorContext) : CaptureFlagSocket = {
|
||||||
|
val obj = CaptureFlagSocket(tdef)
|
||||||
|
obj.Position = pos
|
||||||
|
obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package net.psforever.objects.serverobject.llu
|
||||||
|
|
||||||
|
import net.psforever.objects.serverobject.structures.AmenityDefinition
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The definition for any 'CaptureFlagSocket'
|
||||||
|
* Object Id 450
|
||||||
|
*/
|
||||||
|
class CaptureFlagSocketDefinition extends AmenityDefinition(450) {
|
||||||
|
Name = "llm_socket"
|
||||||
|
}
|
||||||
|
|
@ -18,4 +18,9 @@ abstract class AmenityOwner extends PlanetSideServerObject {
|
||||||
obj.Owner = this
|
obj.Owner = this
|
||||||
amenities
|
amenities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def RemoveAmenity(obj: Amenity): List[Amenity] = {
|
||||||
|
amenities = amenities.filterNot(x => x == obj)
|
||||||
|
amenities
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import net.psforever.packet.game.BuildingInfoUpdateMessage
|
||||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState, Vector3}
|
||||||
import scalax.collection.{Graph, GraphEdge}
|
import scalax.collection.{Graph, GraphEdge}
|
||||||
import akka.actor.typed.scaladsl.adapter._
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
|
import net.psforever.objects.serverobject.llu.{CaptureFlag, CaptureFlagSocket}
|
||||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||||
|
|
||||||
class Building(
|
class Building(
|
||||||
|
|
@ -27,10 +28,6 @@ class Building(
|
||||||
private val buildingDefinition: BuildingDefinition
|
private val buildingDefinition: BuildingDefinition
|
||||||
) extends AmenityOwner {
|
) extends AmenityOwner {
|
||||||
|
|
||||||
/**
|
|
||||||
* The map_id is the identifier number used in BuildingInfoUpdateMessage. This is the index that the building appears in the MPO file starting from index 1
|
|
||||||
* The GUID is the identifier number used in SetEmpireMessage / Facility hacking / PlanetSideAttributeMessage.
|
|
||||||
*/
|
|
||||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||||
private var playersInSOI: List[Player] = List.empty
|
private var playersInSOI: List[Player] = List.empty
|
||||||
private val capitols = List("Thoth", "Voltan", "Neit", "Anguta", "Eisa", "Verica")
|
private val capitols = List("Thoth", "Voltan", "Neit", "Anguta", "Eisa", "Verica")
|
||||||
|
|
@ -43,6 +40,10 @@ class Building(
|
||||||
|
|
||||||
def Name: String = name
|
def Name: String = name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map_id is the identifier number used in BuildingInfoUpdateMessage. This is the index that the building appears in the MPO file starting from index 1
|
||||||
|
* The GUID is the identifier number used in SetEmpireMessage / Facility hacking / PlanetSideAttributeMessage.
|
||||||
|
*/
|
||||||
def MapId: Int = map_id
|
def MapId: Int = map_id
|
||||||
|
|
||||||
def IsCapitol: Boolean = capitols.contains(name)
|
def IsCapitol: Boolean = capitols.contains(name)
|
||||||
|
|
@ -122,6 +123,14 @@ class Building(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def IsCtfBase: Boolean = GetFlagSocket match {
|
||||||
|
case Some(_) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
def GetFlagSocket: Option[CaptureFlagSocket] = this.Amenities.find(_.Definition == GlobalDefinitions.llm_socket).asInstanceOf[Option[CaptureFlagSocket]]
|
||||||
|
def GetFlag: Option[CaptureFlag] = this.Amenities.find(_.Definition == GlobalDefinitions.capture_flag).asInstanceOf[Option[CaptureFlag]]
|
||||||
|
|
||||||
def HackableAmenities: List[Amenity with Hackable] = {
|
def HackableAmenities: List[Amenity with Hackable] = {
|
||||||
Amenities.filter(x => x.isInstanceOf[Hackable]).map(x => x.asInstanceOf[Amenity with Hackable])
|
Amenities.filter(x => x.isInstanceOf[Hackable]).map(x => x.asInstanceOf[Amenity with Hackable])
|
||||||
}
|
}
|
||||||
|
|
@ -200,9 +209,11 @@ class Building(
|
||||||
// Check this Building is on the lattice first
|
// Check this Building is on the lattice first
|
||||||
zone.Lattice find this match {
|
zone.Lattice find this match {
|
||||||
case Some(_) =>
|
case Some(_) =>
|
||||||
// todo: generator destruction state
|
|
||||||
val subGraph = Zone.Lattice filter ((b: Building) =>
|
val subGraph = Zone.Lattice filter ((b: Building) =>
|
||||||
b.Faction == this.Faction && !b.CaptureTerminalIsHacked && b.NtuLevel > 0
|
b.Faction == this.Faction
|
||||||
|
&& !b.CaptureTerminalIsHacked
|
||||||
|
&& b.NtuLevel > 0
|
||||||
|
&& (b.Generator.isEmpty || b.Generator.get.Condition != PlanetSideGeneratorState.Destroyed)
|
||||||
)
|
)
|
||||||
|
|
||||||
var stackedBenefit = 0
|
var stackedBenefit = 0
|
||||||
|
|
@ -226,13 +237,13 @@ class Building(
|
||||||
hackingFaction,
|
hackingFaction,
|
||||||
hackTime,
|
hackTime,
|
||||||
if (ntuLevel > 0) Faction else PlanetSideEmpire.NEUTRAL,
|
if (ntuLevel > 0) Faction else PlanetSideEmpire.NEUTRAL,
|
||||||
0, // Field != 0 will cause malformed packet
|
0, // unk1 Field != 0 will cause malformed packet
|
||||||
None,
|
None, // unk1x
|
||||||
generatorState,
|
generatorState,
|
||||||
spawnTubesNormal,
|
spawnTubesNormal,
|
||||||
forceDomeActive,
|
forceDomeActive,
|
||||||
latticeBenefit,
|
if (generatorState != PlanetSideGeneratorState.Destroyed) latticeBenefit else 0,
|
||||||
48, // cavern benefit
|
if (generatorState != PlanetSideGeneratorState.Destroyed) 48 else 0, // cavern benefit
|
||||||
Nil, // unk4,
|
Nil, // unk4,
|
||||||
0, // unk5
|
0, // unk5
|
||||||
false, // unk6
|
false, // unk6
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ object GamePacketOpcode extends Enumeration {
|
||||||
case 0xbf => game.ZipLineMessage.decode
|
case 0xbf => game.ZipLineMessage.decode
|
||||||
|
|
||||||
// OPCODES 0xc0-cf
|
// OPCODES 0xc0-cf
|
||||||
case 0xc0 => noDecoder(CaptureFlagUpdateMessage)
|
case 0xc0 => game.CaptureFlagUpdateMessage.decode
|
||||||
case 0xc1 => noDecoder(VanuModuleUpdateMessage)
|
case 0xc1 => noDecoder(VanuModuleUpdateMessage)
|
||||||
case 0xc2 => game.FacilityBenefitShieldChargeRequestMessage.decode
|
case 0xc2 => game.FacilityBenefitShieldChargeRequestMessage.decode
|
||||||
case 0xc3 => game.ProximityTerminalUseMessage.decode
|
case 0xc3 => game.ProximityTerminalUseMessage.decode
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.newcodecs.newcodecs
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
import shapeless.{::, HNil}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param zone_number The zone number this packet applies to
|
||||||
|
* @param flagInfoList The list of LLUs/Monolith units for this zone
|
||||||
|
*/
|
||||||
|
final case class CaptureFlagUpdateMessage(zone_number: Int, flagInfoList: List[FlagInfo]) extends PlanetSideGamePacket {
|
||||||
|
type Packet = CaptureFlagUpdateMessage
|
||||||
|
def opcode = GamePacketOpcode.CaptureFlagUpdateMessage
|
||||||
|
def encode = CaptureFlagUpdateMessage.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param u1 No effect. Faction ID perhaps?
|
||||||
|
* @param owner_map_id The mapID of the base the LLU belongs to
|
||||||
|
* @param target_map_id The mapID of the base the LLU must be delivered to
|
||||||
|
* @param x X map position
|
||||||
|
* @param y Y map position
|
||||||
|
* @param hack_time_remaining Time remaining on hack - will override BuildingInfoUpdateMessage when displaying hack timer on map base details
|
||||||
|
* @param is_monolith_unit Changes the icon on the map to the monolith unit icon
|
||||||
|
*/
|
||||||
|
final case class FlagInfo(u1: Int, owner_map_id: Int, target_map_id: Int, x: Float, y: Float, hack_time_remaining: Long, is_monolith_unit: Boolean)
|
||||||
|
object FlagInfo extends Marshallable[FlagInfo] {
|
||||||
|
implicit val codec: Codec[FlagInfo] = {
|
||||||
|
(("u1" | uint2L)
|
||||||
|
:: ("owner_map_id" | uint16L)
|
||||||
|
:: ("target_map_id" | uint16L)
|
||||||
|
:: ("u4" | newcodecs.q_float(0.0, 8192.0, 20))
|
||||||
|
:: ("u5" | newcodecs.q_float(0.0, 8192.0, 20))
|
||||||
|
:: ("hack_time_remaining" | uint32L)
|
||||||
|
:: ("is_monolith_unit" | bool))
|
||||||
|
}.as[FlagInfo]
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlagUpdateMessage extends Marshallable[CaptureFlagUpdateMessage] {
|
||||||
|
implicit val codec: Codec[CaptureFlagUpdateMessage] = (
|
||||||
|
("zone_number" | uint16L)
|
||||||
|
:: ("flagInfoList" | PacketHelpers.listOfNAligned(longL(4), alignment = 0, FlagInfo.codec)) // Maximum of 7 on any map
|
||||||
|
).xmap[CaptureFlagUpdateMessage] (
|
||||||
|
{
|
||||||
|
case zone_number :: flagInfoList :: HNil =>
|
||||||
|
CaptureFlagUpdateMessage(zone_number, flagInfoList)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
case CaptureFlagUpdateMessage(zone_number, flagInfoList) =>
|
||||||
|
zone_number :: flagInfoList :: HNil
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -19,8 +19,11 @@ import scodec.codecs._
|
||||||
* 07 - warning: missile lock<br>
|
* 07 - warning: missile lock<br>
|
||||||
* 08 - warning: Wasp missile lock<br>
|
* 08 - warning: Wasp missile lock<br>
|
||||||
* 09 - warning: T-REK lock<br>
|
* 09 - warning: T-REK lock<br>
|
||||||
|
* 11 - Drop special item e.g. LLU<br>
|
||||||
* 12 - sound: base captured fanfare<br>
|
* 12 - sound: base captured fanfare<br>
|
||||||
* 14 - prompt: new character basic training<br>
|
* 14 - prompt: new character basic training<br>
|
||||||
|
* 15 - MAX Deploy<br>
|
||||||
|
* 16 - MAX Undeploy<br>
|
||||||
* 22 - message: awarded a cavern capture (updates cavern capture status)<br>
|
* 22 - message: awarded a cavern capture (updates cavern capture status)<br>
|
||||||
* 23 - award a cavern kill<br>
|
* 23 - award a cavern kill<br>
|
||||||
* 24 - message: you have been imprinted (updates imprinted status; does it?)<br>
|
* 24 - message: you have been imprinted (updates imprinted status; does it?)<br>
|
||||||
|
|
@ -54,7 +57,21 @@ final case class GenericActionMessage(action: Int) extends PlanetSideGamePacket
|
||||||
}
|
}
|
||||||
|
|
||||||
object GenericActionMessage extends Marshallable[GenericActionMessage] {
|
object GenericActionMessage extends Marshallable[GenericActionMessage] {
|
||||||
|
def apply(action: GenericActionEnum.GenericActionEnum): GenericActionMessage = {
|
||||||
|
GenericActionMessage(action.id)
|
||||||
|
}
|
||||||
|
|
||||||
implicit val codec: Codec[GenericActionMessage] = (
|
implicit val codec: Codec[GenericActionMessage] = (
|
||||||
"action" | uint(6)
|
"action" | uint(6)
|
||||||
).as[GenericActionMessage]
|
).as[GenericActionMessage]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object GenericActionEnum extends Enumeration {
|
||||||
|
type GenericActionEnum = Value
|
||||||
|
|
||||||
|
/** Drop special item e.g. LLU */
|
||||||
|
val DropSpecialItem = Value(11)
|
||||||
|
|
||||||
|
/** Plays the base capture fanfare sound */
|
||||||
|
val BaseCaptureFanfare = Value(12)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,36 +11,38 @@ import shapeless.{::, HNil}
|
||||||
/**
|
/**
|
||||||
* Dispatched by the server to enact an effect on some game object.
|
* Dispatched by the server to enact an effect on some game object.
|
||||||
* (Write more some other time.)
|
* (Write more some other time.)
|
||||||
* @param object_guid the target object
|
* @param object_guid the target object<br/>
|
||||||
* @param code the action code (0-63)
|
* @param code the action code (0-63)<br/>
|
||||||
* 6 - Deconstructs player
|
* 6 - Deconstructs player<br/>
|
||||||
* 7 - Start imprinting process (progress bar + character animation)
|
* 7 - Start imprinting process (progress bar + character animation)<br/>
|
||||||
* 8 - Finish imprinting?
|
* 8 - Finish imprinting?<br/>
|
||||||
* 9 - Cloak
|
* 9 - Cloak<br/>
|
||||||
* 10 - Uncloak
|
* 10 - Uncloak<br/>
|
||||||
* 11 - Deploy capital base shield pole with animation and broadcasts "The capitol force dome at X has been activated"
|
* 11 - Deploy capital base shield pole with animation and broadcasts "The capitol force dome at X has been activated"<br/>
|
||||||
* 12 - Stow capital base shield pole with animation and broadcasts "The capitol force dome at X has been deactivated"
|
* 12 - Stow capital base shield pole with animation and broadcasts "The capitol force dome at X has been deactivated"<br/>
|
||||||
* 13 - Deploy capital base shield pole (instantly, unless still in the middle of the stow animation)
|
* 13 - Deploy capital base shield pole (instantly, unless still in the middle of the stow animation)<br/>
|
||||||
* 15 - Displays "This facility's generator is under attack!"
|
* 14 - Changes capture console to say "Facility hacked by the <Faction> LLU has been spawned." when looked at<br/>
|
||||||
* 16 - Displays "Generator has Overloaded! Evacuate Generator Room Immediately!"
|
* 15 - Displays "This facility's generator is under attack!"<br/>
|
||||||
* 17 - Displays "This facility's generator is back on line"
|
* 16 - Displays "Generator has Overloaded! Evacuate Generator Room Immediately!"<br/>
|
||||||
* 19 - Cause mines to explode
|
* 17 - Displays "This facility's generator is back on line"<br/>
|
||||||
* 20 - Hit flinch? (orig, 82->80)
|
* 19 - Cause mines to explode<br/>
|
||||||
* 21 - Reset build cooldown from using an ACE
|
* 20 - Hit flinch? (orig, 82->80)<br/>
|
||||||
* 22 - ???? (Has been seen on vehicle pad objects, possibly some sort of reset flag after base faction flip / hack clear?)
|
* 21 - Reset build cooldown from using an ACE<br/>
|
||||||
* 23 - Plays vehicle pad animation moving downwards
|
* 22 - ???? (Has been seen on vehicle pad objects, possibly some sort of reset flag after base faction flip / hack clear?)<br/>
|
||||||
* 24 - Makes the vehicle bounce slightly. Have seen this in packet captures after taking a vehicle through a warpgate
|
* 23 - Plays vehicle pad animation moving downwards<br/>
|
||||||
* 27 - Activates the router internal telepad for linking
|
* 24 - Makes the vehicle bounce slightly. Have seen this in packet captures after taking a vehicle through a warpgate<br/>
|
||||||
* 28 - Activates the router internal telepad for linking
|
* 27 - Activates the router internal telepad for linking<br/>
|
||||||
* 29 - Activates the telepad deployable (also used on the router's internal telepad)
|
* 28 - Activates the router internal telepad for linking<br/>
|
||||||
* 30 - Activates the telepad deployable (also used on the router's internal telepad)
|
* 29 - Activates the telepad deployable (also used on the router's internal telepad)<br/>
|
||||||
* 31 - Animation during router teleportation (source)
|
* 30 - Activates the telepad deployable (also used on the router's internal telepad)<br/>
|
||||||
* 32 - Animation during router teleportation (destination)
|
* 31 - Animation during router teleportation (source)<br/>
|
||||||
* 34 - Time until item can be used ?????
|
* 32 - Animation during router teleportation (destination)<br/>
|
||||||
* 50 - For aircraft - client shows "The bailing mechanism failed! To fix the mechanism, land and repair the vehicle!"
|
* 34 - Time until item can be used ?????<br/>
|
||||||
* 53 - Put down an FDU
|
* 50 - For aircraft - client shows "The bailing mechanism failed! To fix the mechanism, land and repair the vehicle!"<br/>
|
||||||
* 56 - Sets vehicle or player to be black ops
|
* 53 - Put down an FDU<br/>
|
||||||
* 57 - Reverts player from black ops
|
* 56 - Sets vehicle or player to be black ops<br/>
|
||||||
|
* 57 - Reverts player from black ops<br/>
|
||||||
|
* @see GenericObjectActionEnum
|
||||||
*/
|
*/
|
||||||
final case class GenericObjectActionMessage(object_guid: PlanetSideGUID, code: Int) extends PlanetSideGamePacket {
|
final case class GenericObjectActionMessage(object_guid: PlanetSideGUID, code: Int) extends PlanetSideGamePacket {
|
||||||
type Packet = GenericObjectActionMessage
|
type Packet = GenericObjectActionMessage
|
||||||
|
|
@ -49,6 +51,10 @@ final case class GenericObjectActionMessage(object_guid: PlanetSideGUID, code: I
|
||||||
}
|
}
|
||||||
|
|
||||||
object GenericObjectActionMessage extends Marshallable[GenericObjectActionMessage] {
|
object GenericObjectActionMessage extends Marshallable[GenericObjectActionMessage] {
|
||||||
|
def apply(object_guid: PlanetSideGUID, code: GenericObjectActionEnum.GenericObjectActionEnum): GenericObjectActionMessage = {
|
||||||
|
GenericObjectActionMessage(object_guid, code.id)
|
||||||
|
}
|
||||||
|
|
||||||
implicit val codec: Codec[GenericObjectActionMessage] = (
|
implicit val codec: Codec[GenericObjectActionMessage] = (
|
||||||
("object_guid" | PlanetSideGUID.codec) ::
|
("object_guid" | PlanetSideGUID.codec) ::
|
||||||
("code" | uint(bits = 6)) ::
|
("code" | uint(bits = 6)) ::
|
||||||
|
|
@ -64,3 +70,12 @@ object GenericObjectActionMessage extends Marshallable[GenericObjectActionMessag
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object GenericObjectActionEnum extends Enumeration {
|
||||||
|
type GenericObjectActionEnum = Value
|
||||||
|
|
||||||
|
/** <b>Effect:</b> Capture console displays "Facility hacked by the <Faction> LLU has been spawned." when looked at<br>
|
||||||
|
* <b>Target</b>: CaptureTerminal
|
||||||
|
*/
|
||||||
|
val FlagSpawned = Value(14)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import scodec.codecs._
|
||||||
* `0x84` - 4 - knife holster<br>
|
* `0x84` - 4 - knife holster<br>
|
||||||
* `0x86` - 6 - grid (1,1)<br>
|
* `0x86` - 6 - grid (1,1)<br>
|
||||||
* `0x00FA` - 250 - is a special dest/extra code that "attaches the item to the player's cursor"
|
* `0x00FA` - 250 - is a special dest/extra code that "attaches the item to the player's cursor"
|
||||||
|
* `0x00FC` - 252 - special item slot e.g. LLU (Possibly also cavern modules)
|
||||||
* @param parent_guid the parent object
|
* @param parent_guid the parent object
|
||||||
* @param child_guid the child object
|
* @param child_guid the child object
|
||||||
* @param slot a codified location within the parent object's inventory;
|
* @param slot a codified location within the parent object's inventory;
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,8 @@ import scodec.codecs._
|
||||||
* `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`<br>
|
* `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`<br>
|
||||||
* `45 - NTU charge bar 0-10, 5 = 50% full. Seems to apply to both ANT and NTU Silo (possibly siphons?)`<br>
|
* `45 - NTU charge bar 0-10, 5 = 50% full. Seems to apply to both ANT and NTU Silo (possibly siphons?)`<br>
|
||||||
* `46 - Sends "Generator damage is at a critical level!" message`
|
* `46 - Sends "Generator damage is at a critical level!" message`
|
||||||
* `47 - Sets base NTU level to CRITICAL. MUST use base MapId not base GUID`<br>
|
* `47 - Sets base NTU level to CRITICAL.`<br>
|
||||||
* `48 - Set to 1 to send base power loss message & turns on red warning lights throughout base. MUST use base MapId not base GUID`?<br>
|
* `48 - Set to 1 to send base power loss message & turns on red warning lights throughout base.<br>
|
||||||
* `49 - Vehicle texture effects state? (>0 turns on ANT panel glow or ntu silo panel glow + orbs) (bit?)`<br>
|
* `49 - Vehicle texture effects state? (>0 turns on ANT panel glow or ntu silo panel glow + orbs) (bit?)`<br>
|
||||||
* `52 - Vehicle particle effects? (>0 turns on orbs going towards ANT. Doesn't affect silo) (bit?)`<br>
|
* `52 - Vehicle particle effects? (>0 turns on orbs going towards ANT. Doesn't affect silo) (bit?)`<br>
|
||||||
* `53 - LFS. Value is 1 to flag LFS`<br>
|
* `53 - LFS. Value is 1 to flag LFS`<br>
|
||||||
|
|
@ -161,7 +161,7 @@ import scodec.codecs._
|
||||||
* `55 - "Someone is attempting to Heal you". Value is 1`<br>
|
* `55 - "Someone is attempting to Heal you". Value is 1`<br>
|
||||||
* `56 - "Someone is attempting to Repair you". Value is 1`<br>
|
* `56 - "Someone is attempting to Repair you". Value is 1`<br>
|
||||||
* `64 - ????? related to using router telepads`
|
* `64 - ????? related to using router telepads`
|
||||||
* `67 - Enables base shields (from cavern module/lock). MUST use base MapId not GUID`<br>
|
* `67 - Enables base shields (from cavern module/lock)`<br>
|
||||||
* `73 - "You are locked into the Core Beam. Charging your Module now.". Value is 1 to active`<br>
|
* `73 - "You are locked into the Core Beam. Charging your Module now.". Value is 1 to active`<br>
|
||||||
* `77 - Cavern Facility Captures. Value is the number of captures`<br>
|
* `77 - Cavern Facility Captures. Value is the number of captures`<br>
|
||||||
* `78 - Cavern Kills. Value is the number of kills`<br>
|
* `78 - Cavern Kills. Value is the number of kills`<br>
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,18 @@ import shapeless.{::, HNil}
|
||||||
* Whenever an applicable player is nearby, that client will rapidly fire off `ItemUseMessage` packets to the server.
|
* Whenever an applicable player is nearby, that client will rapidly fire off `ItemUseMessage` packets to the server.
|
||||||
* The capture flag will be picked-up by the player and stored in a special slot that is not part of their inventory.
|
* The capture flag will be picked-up by the player and stored in a special slot that is not part of their inventory.
|
||||||
* A special dropping keybind has been prepared to relinquish the capture flag back to the game world.
|
* A special dropping keybind has been prepared to relinquish the capture flag back to the game world.
|
||||||
|
* @param pos the position + orientation + velocity of the LLU where it is dropped/spawned
|
||||||
* @param faction the empire whose players may interact with this capture flag
|
* @param faction the empire whose players may interact with this capture flag
|
||||||
* @param unk1 na
|
* @param owningBaseGuid The GUID of the base that this LLU belongs to
|
||||||
* @param unk2 na
|
* @param targetBaseGuid The GUID of the base that this LLU must be taken to
|
||||||
* @param unk3 na
|
* @param milliseconds_remaining The number of milliseconds left on the timer for this LLU - should match the CC timer
|
||||||
* @param unk4 na
|
|
||||||
*/
|
*/
|
||||||
final case class CaptureFlagData(
|
final case class CaptureFlagData(
|
||||||
pos: PlacementData,
|
pos: PlacementData,
|
||||||
faction: PlanetSideEmpire.Value,
|
faction: PlanetSideEmpire.Value,
|
||||||
unk1: Int,
|
owningBaseGuid : Int,
|
||||||
unk2: Int,
|
targetBaseGuid : Int,
|
||||||
unk3: Int,
|
milliseconds_remaining : Long
|
||||||
unk4: Int
|
|
||||||
) extends ConstructorData {
|
) extends ConstructorData {
|
||||||
override def bitsize: Long = 88L + pos.bitsize
|
override def bitsize: Long = 88L + pos.bitsize
|
||||||
}
|
}
|
||||||
|
|
@ -40,24 +39,23 @@ object CaptureFlagData extends Marshallable[CaptureFlagData] {
|
||||||
bool ::
|
bool ::
|
||||||
uint4L ::
|
uint4L ::
|
||||||
uint16L ::
|
uint16L ::
|
||||||
("unk1" | uint8L) ::
|
("owningBaseGuid" | uint8L) ::
|
||||||
uint8L ::
|
uint8L ::
|
||||||
("unk2" | uint8L) ::
|
("targetBaseGuid" | uint8L) ::
|
||||||
uint8L ::
|
uint8L ::
|
||||||
("unk3" | uint16L) :: //probably a PlanetSideGUID
|
("milliseconds_remaining" | uint32L) ::
|
||||||
("unk4" | uint8L) ::
|
uint(1)
|
||||||
uint(9)
|
|
||||||
).exmap[CaptureFlagData](
|
).exmap[CaptureFlagData](
|
||||||
{
|
{
|
||||||
case pos :: fac :: false :: 4 :: 0 :: unk1 :: 0 :: unk2 :: 0 :: unk3 :: unk4 :: 0 :: HNil =>
|
case pos :: faction :: false :: 4 :: 0 :: owningBaseGuid :: 0 :: targetBaseGuid :: 0 :: milliseconds_remaining :: 0 :: HNil =>
|
||||||
Attempt.Successful(CaptureFlagData(pos, fac, unk1, unk2, unk3, unk4))
|
Attempt.Successful(CaptureFlagData(pos, faction, owningBaseGuid, targetBaseGuid, milliseconds_remaining))
|
||||||
|
|
||||||
case data =>
|
case data =>
|
||||||
Attempt.failure(Err(s"invalid capture flag data format - $data"))
|
Attempt.failure(Err(s"invalid capture flag data format - $data"))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
case CaptureFlagData(pos, fac, unk1, unk2, unk3, unk4) =>
|
case CaptureFlagData(pos, faction, owningBaseGuid, targetBaseGuid, milliseconds_remaining) =>
|
||||||
Attempt.successful(pos :: fac :: false :: 4 :: 0 :: unk1 :: 0 :: unk2 :: 0 :: unk3 :: unk4 :: 0 :: HNil)
|
Attempt.successful(pos :: faction :: false :: 4 :: 0 :: owningBaseGuid :: 0 :: targetBaseGuid :: 0 :: milliseconds_remaining :: 0 :: HNil)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -408,6 +408,9 @@ class AvatarService(zone: Zone) extends Actor {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case AvatarAction.DropSpecialItem() =>
|
||||||
|
AvatarEvents.publish(AvatarServiceResponse(s"/$forChannel/Avatar", Service.defaultPlayerGUID, AvatarResponse.DropSpecialItem()))
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ object AvatarAction {
|
||||||
inventory: List[InventoryItem],
|
inventory: List[InventoryItem],
|
||||||
drop: List[InventoryItem]
|
drop: List[InventoryItem]
|
||||||
) extends Action
|
) extends Action
|
||||||
|
final case class DropSpecialItem() extends Action
|
||||||
|
|
||||||
final case class TeardownConnection() extends Action
|
final case class TeardownConnection() extends Action
|
||||||
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ object AvatarResponse {
|
||||||
inventory: List[InventoryItem],
|
inventory: List[InventoryItem],
|
||||||
drop: List[InventoryItem]
|
drop: List[InventoryItem]
|
||||||
) extends Response
|
) extends Response
|
||||||
|
final case class DropSpecialItem() extends Response
|
||||||
|
|
||||||
final case class TeardownConnection() extends Response
|
final case class TeardownConnection() extends Response
|
||||||
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.services.galaxy
|
||||||
|
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.BuildingInfoUpdateMessage
|
import net.psforever.packet.game.{BuildingInfoUpdateMessage, FlagInfo}
|
||||||
import net.psforever.services.{GenericEventBus, Service}
|
import net.psforever.services.{GenericEventBus, Service}
|
||||||
|
|
||||||
class GalaxyService extends Actor {
|
class GalaxyService extends Actor {
|
||||||
|
|
@ -41,6 +41,11 @@ class GalaxyService extends Actor {
|
||||||
GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.MapUpdate(msg))
|
GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.MapUpdate(msg))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case GalaxyAction.FlagMapUpdate(msg) =>
|
||||||
|
GalaxyEvents.publish(
|
||||||
|
GalaxyServiceResponse(s"/Galaxy", GalaxyResponse.FlagMapUpdate(msg))
|
||||||
|
)
|
||||||
|
|
||||||
case GalaxyAction.TransferPassenger(_, temp_channel, vehicle, vehicle_to_delete, manifest) =>
|
case GalaxyAction.TransferPassenger(_, temp_channel, vehicle, vehicle_to_delete, manifest) =>
|
||||||
GalaxyEvents.publish(
|
GalaxyEvents.publish(
|
||||||
GalaxyServiceResponse(
|
GalaxyServiceResponse(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.services.galaxy
|
||||||
|
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.vehicles.VehicleManifest
|
import net.psforever.objects.vehicles.VehicleManifest
|
||||||
import net.psforever.packet.game.BuildingInfoUpdateMessage
|
import net.psforever.packet.game.{BuildingInfoUpdateMessage, CaptureFlagUpdateMessage, FlagInfo}
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
||||||
final case class GalaxyServiceMessage(forChannel: String, actionMessage: GalaxyAction.Action)
|
final case class GalaxyServiceMessage(forChannel: String, actionMessage: GalaxyAction.Action)
|
||||||
|
|
@ -16,6 +16,7 @@ object GalaxyAction {
|
||||||
trait Action
|
trait Action
|
||||||
|
|
||||||
final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Action
|
final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Action
|
||||||
|
final case class FlagMapUpdate(msg: CaptureFlagUpdateMessage) extends Action
|
||||||
|
|
||||||
final case class TransferPassenger(
|
final case class TransferPassenger(
|
||||||
player_guid: PlanetSideGUID,
|
player_guid: PlanetSideGUID,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package net.psforever.services.galaxy
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.vehicles.VehicleManifest
|
import net.psforever.objects.vehicles.VehicleManifest
|
||||||
import net.psforever.objects.zones.HotSpotInfo
|
import net.psforever.objects.zones.HotSpotInfo
|
||||||
import net.psforever.packet.game.BuildingInfoUpdateMessage
|
import net.psforever.packet.game.{BuildingInfoUpdateMessage, CaptureFlagUpdateMessage, FlagInfo}
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
import net.psforever.services.GenericEventBusMsg
|
import net.psforever.services.GenericEventBusMsg
|
||||||
|
|
||||||
|
|
@ -16,6 +16,8 @@ object GalaxyResponse {
|
||||||
|
|
||||||
final case class HotSpotUpdate(zone_id: Int, priority: Int, host_spot_info: List[HotSpotInfo]) extends Response
|
final case class HotSpotUpdate(zone_id: Int, priority: Int, host_spot_info: List[HotSpotInfo]) extends Response
|
||||||
final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Response
|
final case class MapUpdate(msg: BuildingInfoUpdateMessage) extends Response
|
||||||
|
final case class FlagMapUpdate(msg: CaptureFlagUpdateMessage) extends Response
|
||||||
|
|
||||||
|
|
||||||
final case class TransferPassenger(
|
final case class TransferPassenger(
|
||||||
temp_channel: String,
|
temp_channel: String,
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,26 @@
|
||||||
package net.psforever.services.local
|
package net.psforever.services.local
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorRef, Props}
|
import akka.actor.{Actor, ActorRef, Props}
|
||||||
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal
|
import net.psforever.objects.serverobject.terminals.Terminal
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.vehicles.{Utility, UtilityType}
|
||||||
import net.psforever.objects._
|
|
||||||
import net.psforever.packet.game.{TriggeredEffect, TriggeredEffectLocation}
|
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.services.local.support._
|
import net.psforever.packet.game.{TriggeredEffect, TriggeredEffectLocation}
|
||||||
|
import net.psforever.services.local.support.{CaptureFlagManager, _}
|
||||||
|
import net.psforever.services.support.SupportActor
|
||||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import net.psforever.services.{GenericEventBus, RemoverActor, Service}
|
import net.psforever.services.{GenericEventBus, RemoverActor, Service}
|
||||||
|
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration.{Duration, _}
|
||||||
import net.psforever.objects.vehicles.{Utility, UtilityType}
|
|
||||||
import net.psforever.services.support.SupportActor
|
|
||||||
|
|
||||||
import scala.concurrent.duration.Duration
|
|
||||||
|
|
||||||
class LocalService(zone: Zone) extends Actor {
|
class LocalService(zone: Zone) extends Actor {
|
||||||
private val doorCloser = context.actorOf(Props[DoorCloseActor](), s"${zone.id}-local-door-closer")
|
private val doorCloser = context.actorOf(Props[DoorCloseActor](), s"${zone.id}-local-door-closer")
|
||||||
private val hackClearer = context.actorOf(Props[HackClearActor](), s"${zone.id}-local-hack-clearer")
|
private val hackClearer = context.actorOf(Props[HackClearActor](), s"${zone.id}-local-hack-clearer")
|
||||||
private val hackCapturer = context.actorOf(Props[HackCaptureActor](), s"${zone.id}-local-hack-capturer")
|
private val hackCapturer = context.actorOf(Props(classOf[HackCaptureActor], zone.tasks), s"${zone.id}-local-hack-capturer")
|
||||||
|
private val captureFlagManager = context.actorOf(Props(classOf[CaptureFlagManager], zone.tasks, zone), s"${zone.id}-local-capture-flag-manager")
|
||||||
private val engineer = context.actorOf(Props(classOf[DeployableRemover], zone.tasks), s"${zone.id}-deployable-remover-agent")
|
private val engineer = context.actorOf(Props(classOf[DeployableRemover], zone.tasks), s"${zone.id}-deployable-remover-agent")
|
||||||
private val teleportDeployment: ActorRef =
|
private val teleportDeployment: ActorRef =
|
||||||
context.actorOf(Props[RouterTelepadActivation](), s"${zone.id}-telepad-activate-agent")
|
context.actorOf(Props[RouterTelepadActivation](), s"${zone.id}-telepad-activate-agent")
|
||||||
|
|
@ -93,10 +92,43 @@ class LocalService(zone: Zone) extends Actor {
|
||||||
)
|
)
|
||||||
case LocalAction.ClearTemporaryHack(_, target) =>
|
case LocalAction.ClearTemporaryHack(_, target) =>
|
||||||
hackClearer ! HackClearActor.ObjectIsResecured(target)
|
hackClearer ! HackClearActor.ObjectIsResecured(target)
|
||||||
|
|
||||||
case LocalAction.ResecureCaptureTerminal(target) =>
|
case LocalAction.ResecureCaptureTerminal(target) =>
|
||||||
hackCapturer ! HackCaptureActor.ResecureCaptureTerminal(target, zone)
|
hackCapturer ! HackCaptureActor.ResecureCaptureTerminal(target, zone)
|
||||||
case LocalAction.StartCaptureTerminalHack(target) =>
|
case LocalAction.StartCaptureTerminalHack(target) =>
|
||||||
hackCapturer ! HackCaptureActor.StartCaptureTerminalHack(target, zone, 0, 8L)
|
hackCapturer ! HackCaptureActor.StartCaptureTerminalHack(target, zone, 0, 8L)
|
||||||
|
case LocalAction.LluCaptured(llu) =>
|
||||||
|
hackCapturer ! HackCaptureActor.FlagCaptured(llu)
|
||||||
|
|
||||||
|
case LocalAction.LluSpawned(player_guid, llu) =>
|
||||||
|
// Forward to all clients to create object locally
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
player_guid,
|
||||||
|
LocalResponse.LluSpawned(llu)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
case LocalAction.LluDespawned(player_guid, llu) =>
|
||||||
|
// Forward to all clients to destroy object locally
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
player_guid,
|
||||||
|
LocalResponse.LluDespawned(llu)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
case LocalAction.SendPacket(packet) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
PlanetSideGUID(-1),
|
||||||
|
LocalResponse.SendPacket(packet)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
case LocalAction.SendPlanetsideAttributeMessage(player_guid, target_guid, attribute_number, attribute_value) =>
|
case LocalAction.SendPlanetsideAttributeMessage(player_guid, target_guid, attribute_number, attribute_value) =>
|
||||||
LocalEvents.publish(
|
LocalEvents.publish(
|
||||||
LocalServiceResponse(
|
LocalServiceResponse(
|
||||||
|
|
@ -105,6 +137,34 @@ class LocalService(zone: Zone) extends Actor {
|
||||||
LocalResponse.SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value)
|
LocalResponse.SendPlanetsideAttributeMessage(target_guid, attribute_number, attribute_value)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case LocalAction.SendGenericObjectActionMessage(player_guid, target_guid, action_number) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
player_guid,
|
||||||
|
LocalResponse.SendGenericObjectActionMessage(target_guid, action_number)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
case LocalAction.SendChatMsg(player_guid, msg) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
player_guid,
|
||||||
|
LocalResponse.SendChatMsg(msg)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
case LocalAction.SendGenericActionMessage(player_guid, action_number) =>
|
||||||
|
LocalEvents.publish(
|
||||||
|
LocalServiceResponse(
|
||||||
|
s"/$forChannel/Local",
|
||||||
|
player_guid,
|
||||||
|
LocalResponse.SendGenericActionMessage(action_number)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
case LocalAction.RouterTelepadTransport(player_guid, passenger_guid, src_guid, dest_guid) =>
|
case LocalAction.RouterTelepadTransport(player_guid, passenger_guid, src_guid, dest_guid) =>
|
||||||
LocalEvents.publish(
|
LocalEvents.publish(
|
||||||
LocalServiceResponse(
|
LocalServiceResponse(
|
||||||
|
|
@ -357,6 +417,16 @@ class LocalService(zone: Zone) extends Actor {
|
||||||
val cause = damage_func(target)
|
val cause = damage_func(target)
|
||||||
sender() ! Vitality.DamageResolution(target, cause)
|
sender() ! Vitality.DamageResolution(target, cause)
|
||||||
|
|
||||||
|
// Forward all CaptureFlagManager messages
|
||||||
|
case msg @
|
||||||
|
(CaptureFlagManager.SpawnCaptureFlag(_, _, _)
|
||||||
|
| CaptureFlagManager.PickupFlag(_, _)
|
||||||
|
| CaptureFlagManager.DropFlag(_)
|
||||||
|
| CaptureFlagManager.Captured(_)
|
||||||
|
| CaptureFlagManager.Lost(_, _)
|
||||||
|
| CaptureFlagManager) =>
|
||||||
|
captureFlagManager.forward(msg)
|
||||||
|
|
||||||
case msg =>
|
case msg =>
|
||||||
log.warn(s"Unhandled message $msg from ${sender()}")
|
log.warn(s"Unhandled message $msg from ${sender()}")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.services.local
|
package net.psforever.services.local
|
||||||
|
|
||||||
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||||
import net.psforever.objects.vehicles.Utility
|
import net.psforever.objects.vehicles.Utility
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.{DeployableInfo, DeploymentAction, TriggeredSound}
|
import net.psforever.packet.game.GenericActionEnum.GenericActionEnum
|
||||||
|
import net.psforever.packet.game.GenericObjectActionEnum.GenericObjectActionEnum
|
||||||
|
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
||||||
|
import net.psforever.packet.game.{ChatMsg, DeployableInfo, DeploymentAction, TriggeredSound}
|
||||||
import net.psforever.services.hart.HartTimer.OrbitalShuttleEvent
|
import net.psforever.services.hart.HartTimer.OrbitalShuttleEvent
|
||||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||||
|
|
||||||
|
|
@ -49,14 +52,37 @@ object LocalAction {
|
||||||
) extends Action
|
) extends Action
|
||||||
final case class ClearTemporaryHack(player_guid: PlanetSideGUID, target: PlanetSideServerObject with Hackable)
|
final case class ClearTemporaryHack(player_guid: PlanetSideGUID, target: PlanetSideServerObject with Hackable)
|
||||||
extends Action
|
extends Action
|
||||||
|
|
||||||
final case class ResecureCaptureTerminal(target: CaptureTerminal) extends Action
|
final case class ResecureCaptureTerminal(target: CaptureTerminal) extends Action
|
||||||
final case class StartCaptureTerminalHack(target: CaptureTerminal) extends Action
|
final case class StartCaptureTerminalHack(target: CaptureTerminal) extends Action
|
||||||
|
final case class LluCaptured(llu: CaptureFlag) extends Action
|
||||||
|
final case class LluSpawned(player_guid: PlanetSideGUID, llu: CaptureFlag) extends Action
|
||||||
|
final case class LluDespawned(player_guid: PlanetSideGUID, llu: CaptureFlag) extends Action
|
||||||
|
|
||||||
|
final case class SendPacket(packet: PlanetSideGamePacket) extends Action
|
||||||
final case class SendPlanetsideAttributeMessage(
|
final case class SendPlanetsideAttributeMessage(
|
||||||
player_guid: PlanetSideGUID,
|
player_guid: PlanetSideGUID,
|
||||||
target: PlanetSideGUID,
|
target: PlanetSideGUID,
|
||||||
attribute_number: PlanetsideAttributeEnum,
|
attribute_number: PlanetsideAttributeEnum,
|
||||||
attribute_value: Long
|
attribute_value: Long
|
||||||
) extends Action
|
) extends Action
|
||||||
|
|
||||||
|
final case class SendGenericObjectActionMessage(
|
||||||
|
player_guid: PlanetSideGUID,
|
||||||
|
target: PlanetSideGUID,
|
||||||
|
action_number: GenericObjectActionEnum
|
||||||
|
) extends Action
|
||||||
|
|
||||||
|
final case class SendChatMsg(
|
||||||
|
player_guid: PlanetSideGUID,
|
||||||
|
msg: ChatMsg
|
||||||
|
) extends Action
|
||||||
|
|
||||||
|
final case class SendGenericActionMessage(
|
||||||
|
player_guid: PlanetSideGUID,
|
||||||
|
action_number: GenericActionEnum
|
||||||
|
) extends Action
|
||||||
|
|
||||||
final case class RouterTelepadTransport(
|
final case class RouterTelepadTransport(
|
||||||
player_guid: PlanetSideGUID,
|
player_guid: PlanetSideGUID,
|
||||||
passenger_guid: PlanetSideGUID,
|
passenger_guid: PlanetSideGUID,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,13 @@ package net.psforever.services.local
|
||||||
|
|
||||||
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, TelepadDeployable, Vehicle}
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
|
import net.psforever.objects.serverobject.structures.{AmenityOwner, Building}
|
||||||
import net.psforever.objects.serverobject.terminals.{ProximityUnit, Terminal}
|
import net.psforever.objects.serverobject.terminals.{ProximityUnit, Terminal}
|
||||||
import net.psforever.objects.vehicles.Utility
|
import net.psforever.objects.vehicles.Utility
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
|
import net.psforever.packet.game.GenericActionEnum.GenericActionEnum
|
||||||
|
import net.psforever.packet.game.GenericObjectActionEnum.GenericObjectActionEnum
|
||||||
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
import net.psforever.packet.game.PlanetsideAttributeEnum.PlanetsideAttributeEnum
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
|
|
@ -33,8 +38,18 @@ object LocalResponse {
|
||||||
) extends Response
|
) extends Response
|
||||||
final case class SendHackMessageHackCleared(target_guid: PlanetSideGUID, unk1: Long, unk2: Long) extends Response
|
final case class SendHackMessageHackCleared(target_guid: PlanetSideGUID, unk1: Long, unk2: Long) extends Response
|
||||||
final case class HackObject(target_guid: PlanetSideGUID, unk1: Long, unk2: Long) extends Response
|
final case class HackObject(target_guid: PlanetSideGUID, unk1: Long, unk2: Long) extends Response
|
||||||
|
|
||||||
|
final case class SendPacket(packet: PlanetSideGamePacket) extends Response
|
||||||
final case class SendPlanetsideAttributeMessage(target_guid: PlanetSideGUID, attribute_number: PlanetsideAttributeEnum, attribute_value: Long)
|
final case class SendPlanetsideAttributeMessage(target_guid: PlanetSideGUID, attribute_number: PlanetsideAttributeEnum, attribute_value: Long)
|
||||||
extends Response
|
extends Response
|
||||||
|
final case class SendGenericObjectActionMessage(target_guid: PlanetSideGUID, action_number: GenericObjectActionEnum)
|
||||||
|
extends Response
|
||||||
|
final case class SendChatMsg(msg: ChatMsg) extends Response
|
||||||
|
final case class SendGenericActionMessage(action_num: GenericActionEnum) extends Response
|
||||||
|
|
||||||
|
final case class LluSpawned(llu: CaptureFlag) extends Response
|
||||||
|
final case class LluDespawned(llu: CaptureFlag) extends Response
|
||||||
|
|
||||||
final case class ObjectDelete(item_guid: PlanetSideGUID, unk: Int) extends Response
|
final case class ObjectDelete(item_guid: PlanetSideGUID, unk: Int) extends Response
|
||||||
final case class ProximityTerminalAction(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject)
|
final case class ProximityTerminalAction(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject)
|
||||||
extends Response
|
extends Response
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,282 @@
|
||||||
|
package net.psforever.services.local.support
|
||||||
|
|
||||||
|
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||||
|
import net.psforever.objects.{Default, Player}
|
||||||
|
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
|
import net.psforever.objects.serverobject.structures.Building
|
||||||
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||||
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.services.ServiceManager
|
||||||
|
import net.psforever.services.ServiceManager.{Lookup, LookupResult}
|
||||||
|
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||||
|
import net.psforever.services.local.support.CaptureFlagLostReasonEnum.CaptureFlagLostReasonEnum
|
||||||
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||||
|
|
||||||
|
import scala.concurrent.duration.DurationInt
|
||||||
|
import scala.util.Success
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for handling capture flag related lifecycles
|
||||||
|
* @param taskResolver A reference to a zone's task resolver actor
|
||||||
|
*/
|
||||||
|
class CaptureFlagManager(val taskResolver: ActorRef, zone: Zone) extends Actor{
|
||||||
|
private[this] val log = org.log4s.getLogger(self.path.name)
|
||||||
|
|
||||||
|
var galaxyService: ActorRef = ActorRef.noSender
|
||||||
|
|
||||||
|
private var mapUpdateTick: Cancellable = Default.Cancellable
|
||||||
|
|
||||||
|
/** An internally tracked list of current flags, to avoid querying AmenityOwners each second for flag lookups */
|
||||||
|
private var flags: List[CaptureFlag] = Nil
|
||||||
|
|
||||||
|
private def TrackFlag(flag: CaptureFlag): Unit = {
|
||||||
|
flag.Owner.Amenities = flag
|
||||||
|
flags = flags :+ flag
|
||||||
|
|
||||||
|
if (mapUpdateTick.isCancelled) {
|
||||||
|
// Start sending map updates periodically
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
mapUpdateTick = context.system.scheduler.scheduleAtFixedRate(0 seconds, 1 second, self, CaptureFlagManager.MapUpdate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def UntrackFlag(flag: CaptureFlag): Unit = {
|
||||||
|
flag.Owner.RemoveAmenity(flag)
|
||||||
|
flags = flags.filterNot(x => x == flag)
|
||||||
|
|
||||||
|
if (flags.isEmpty) {
|
||||||
|
mapUpdateTick.cancel()
|
||||||
|
|
||||||
|
// Send one final map update to clear the last flag from the map
|
||||||
|
self ! CaptureFlagManager.MapUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val serviceManager = ServiceManager.serviceManager
|
||||||
|
serviceManager ! Lookup("galaxy")
|
||||||
|
|
||||||
|
def receive: Receive = {
|
||||||
|
case LookupResult("galaxy", endpoint) =>
|
||||||
|
galaxyService = endpoint
|
||||||
|
|
||||||
|
case CaptureFlagManager.MapUpdate() =>
|
||||||
|
val flagInfo = flags.map(flag =>
|
||||||
|
FlagInfo(
|
||||||
|
u1 = 0,
|
||||||
|
owner_map_id = flag.Owner.asInstanceOf[Building].MapId,
|
||||||
|
target_map_id = flag.Target.MapId,
|
||||||
|
x = flag.Position.x,
|
||||||
|
y = flag.Position.y,
|
||||||
|
hack_time_remaining = flag.Owner.asInstanceOf[Building].infoUpdateMessage().hack_time_remaining,
|
||||||
|
is_monolith_unit = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
galaxyService ! GalaxyServiceMessage(GalaxyAction.FlagMapUpdate(CaptureFlagUpdateMessage(zone.Number, flagInfo)))
|
||||||
|
|
||||||
|
case CaptureFlagManager.SpawnCaptureFlag(capture_terminal, target, hackingFaction) =>
|
||||||
|
val zone = capture_terminal.Zone
|
||||||
|
val socket = capture_terminal.Owner.asInstanceOf[Building].GetFlagSocket.get
|
||||||
|
|
||||||
|
// Override CC message when looked at
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
|
zone.id,
|
||||||
|
LocalAction.SendGenericObjectActionMessage(
|
||||||
|
PlanetSideGUID(-1),
|
||||||
|
capture_terminal.GUID,
|
||||||
|
GenericObjectActionEnum.FlagSpawned
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register LLU object create task and callback to create on clients
|
||||||
|
val flag: CaptureFlag = CaptureFlag.Constructor(
|
||||||
|
Vector3(socket.Position.x, socket.Position.y, socket.Position.z - 1),
|
||||||
|
socket.Orientation,
|
||||||
|
target,
|
||||||
|
socket.Owner,
|
||||||
|
hackingFaction
|
||||||
|
)
|
||||||
|
|
||||||
|
// Add the flag as an amenity and track it internally
|
||||||
|
TrackFlag(flag)
|
||||||
|
|
||||||
|
taskResolver ! CallBackForTask(
|
||||||
|
TaskResolver.GiveTask(GUIDTask.RegisterObjectTask(flag)(socket.Zone.GUID).task),
|
||||||
|
socket.Zone.LocalEvents,
|
||||||
|
LocalServiceMessage(
|
||||||
|
socket.Zone.id,
|
||||||
|
LocalAction.LluSpawned(PlanetSideGUID(-1), flag)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Broadcast chat message for LLU spawn
|
||||||
|
val owner = flag.Owner.asInstanceOf[Building]
|
||||||
|
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_FlagSpawned(owner, flag.Target))
|
||||||
|
|
||||||
|
case CaptureFlagManager.Captured(flag: CaptureFlag) =>
|
||||||
|
// Trigger Install sound
|
||||||
|
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.TriggerSound(PlanetSideGUID(-1), TriggeredSound.LLUInstall, flag.Target.CaptureTerminal.get.Position, 20, 0.8000001f))
|
||||||
|
|
||||||
|
// Broadcast capture chat message
|
||||||
|
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_Success(flag.Carrier.get, flag.Owner.asInstanceOf[Building].Name))
|
||||||
|
|
||||||
|
// Despawn flag
|
||||||
|
HandleFlagDespawn(flag)
|
||||||
|
|
||||||
|
case CaptureFlagManager.Lost(flag: CaptureFlag, reason: CaptureFlagLostReasonEnum) =>
|
||||||
|
val message = reason match {
|
||||||
|
case CaptureFlagLostReasonEnum.Resecured =>
|
||||||
|
CaptureFlagChatMessageStrings.CTF_Failed_SourceResecured(flag.Owner.asInstanceOf[Building])
|
||||||
|
case CaptureFlagLostReasonEnum.TimedOut =>
|
||||||
|
CaptureFlagChatMessageStrings.CTF_Failed_TimedOut(flag.Owner.asInstanceOf[Building].Name, flag.Target)
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatBroadcast(flag.Zone, message)
|
||||||
|
|
||||||
|
HandleFlagDespawn(flag)
|
||||||
|
|
||||||
|
case CaptureFlagManager.PickupFlag(flag: CaptureFlag, player: Player) =>
|
||||||
|
val continent = flag.Zone
|
||||||
|
|
||||||
|
flag.Carrier = Some(player)
|
||||||
|
|
||||||
|
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.SendPacket(ObjectAttachMessage(player.GUID, flag.GUID, 252)))
|
||||||
|
continent.LocalEvents ! LocalServiceMessage(continent.id, LocalAction.TriggerSound(PlanetSideGUID(-1), TriggeredSound.LLUPickup, player.Position, 15, volume = 0.8f))
|
||||||
|
|
||||||
|
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_FlagPickedUp(player, flag.Owner.asInstanceOf[Building].Name), fanfare = false)
|
||||||
|
|
||||||
|
case CaptureFlagManager.DropFlag(flag: CaptureFlag) =>
|
||||||
|
flag.Carrier match {
|
||||||
|
case Some(player: Player) =>
|
||||||
|
// Set the flag position to where the player is that dropped it
|
||||||
|
flag.Position = player.Position
|
||||||
|
|
||||||
|
// Remove attached player from flag
|
||||||
|
flag.Carrier = None
|
||||||
|
|
||||||
|
// Send drop packet
|
||||||
|
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.SendPacket(ObjectDetachMessage(player.GUID, flag.GUID, player.Position, 0, 0, 0)))
|
||||||
|
|
||||||
|
// Send dropped chat message
|
||||||
|
ChatBroadcast(flag.Zone, CaptureFlagChatMessageStrings.CTF_FlagDropped(player, flag.Owner.asInstanceOf[Building].Name), fanfare = false)
|
||||||
|
|
||||||
|
case None =>
|
||||||
|
log.warn("Tried to drop flag but flag has no carrier")
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ =>
|
||||||
|
log.warn("Received unhandled message");
|
||||||
|
}
|
||||||
|
|
||||||
|
private def HandleFlagDespawn(flag: CaptureFlag): Unit = {
|
||||||
|
// Unregister LLU from clients,
|
||||||
|
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.LluDespawned(PlanetSideGUID(-1), flag))
|
||||||
|
|
||||||
|
// Then unregister it from the GUID pool
|
||||||
|
taskResolver ! TaskResolver.GiveTask(GUIDTask.UnregisterObjectTask(flag)(flag.Zone.GUID).task)
|
||||||
|
|
||||||
|
// Remove the flag as an amenity
|
||||||
|
UntrackFlag(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def ChatBroadcast(zone: Zone, message: String, fanfare: Boolean = true): Unit = {
|
||||||
|
val messageType: ChatMessageType = if (fanfare) {
|
||||||
|
ChatMessageType.UNK_223
|
||||||
|
} else {
|
||||||
|
ChatMessageType.UNK_229
|
||||||
|
}
|
||||||
|
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
|
zone.id,
|
||||||
|
LocalAction.SendChatMsg(
|
||||||
|
PlanetSideGUID(-1),
|
||||||
|
ChatMsg(messageType, wideContents = false, "", message, None)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: Duplicate from SessionActor. Make common.
|
||||||
|
def CallBackForTask(task: TaskResolver.GiveTask, sendTo: ActorRef, pass: Any): TaskResolver.GiveTask = {
|
||||||
|
TaskResolver.GiveTask(
|
||||||
|
new Task() {
|
||||||
|
private val localDesc = task.task.Description
|
||||||
|
private val destination = sendTo
|
||||||
|
private val passMsg = pass
|
||||||
|
|
||||||
|
override def Description: String = s"callback for tasking $localDesc"
|
||||||
|
|
||||||
|
def Execute(resolver: ActorRef): Unit = {
|
||||||
|
destination ! passMsg
|
||||||
|
resolver ! Success(this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
List(task)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlagManager {
|
||||||
|
final case class SpawnCaptureFlag(capture_terminal: CaptureTerminal, target: Building, hackingFaction: PlanetSideEmpire.Value)
|
||||||
|
final case class PickupFlag(flag: CaptureFlag, player: Player)
|
||||||
|
final case class DropFlag(flag: CaptureFlag)
|
||||||
|
final case class Captured(flag: CaptureFlag)
|
||||||
|
final case class Lost(flag: CaptureFlag, reason: CaptureFlagLostReasonEnum)
|
||||||
|
final case class MapUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlagChatMessageStrings {
|
||||||
|
/*
|
||||||
|
@CTF_Failed_TargetLost=%1's LLU target facility %2 was lost!\nHack canceled!
|
||||||
|
@CTF_Failed_FlagLost=The %1 lost %2's LLU!\nHack canceled!
|
||||||
|
@CTF_Warning_Carrier=%1 of the %2 has %3's LLU.\nIt must be taken to %4 within %5 minutes!
|
||||||
|
@CTF_Warning_NoCarrier=%1's LLU is in the field.\nThe %2 must take it to %3 within %4 minutes!
|
||||||
|
@CTF_Warning_Carrier1Min=%1 of the %2 has %3's LLU.\nIt must be taken to %4 within the next minute!
|
||||||
|
@CTF_Warning_NoCarrier1Min=%1's LLU is in the field.\nThe %2 must take it to %3 within the next minute!
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @CTF_Success=%1 captured %2's LLU for the %3!
|
||||||
|
/** {player.Name} captured {owner_name}'s LLU for the {player.Faction}! */
|
||||||
|
def CTF_Success(player: Player, owner_name: String): String = s"@CTF_Success^${player.Name}~^@$owner_name~^@${GetFactionString(player.Faction)}~"
|
||||||
|
|
||||||
|
// @CTF_Failed_TimedOut=The %1 failed to deliver %2's LLU to %3 in time!\nHack canceled!
|
||||||
|
/** The {target.Faction} failed to deliver {owner_name}'s LLU to {target.Name} in time!\nHack canceled! */
|
||||||
|
def CTF_Failed_TimedOut(owner_name: String, target: Building): String = s"@CTF_Failed_TimedOut^@${GetFactionString(target.Faction)}~^@$owner_name~^@${target.Name}~"
|
||||||
|
|
||||||
|
// @CTF_Failed_SourceResecured=The %1 resecured %2!\nThe LLU was lost!
|
||||||
|
/** The {owner.Faction} resecured {owner.Name}!\nThe LLU was lost! */
|
||||||
|
def CTF_Failed_SourceResecured(owner: Building): String = s"@CTF_Failed_SourceResecured^@${CaptureFlagChatMessageStrings.GetFactionString(owner.Faction)}~^@${owner.Name}~"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @CTF_FlagSpawned=%1 %2 has spawned a LLU.\nIt must be taken to %3 %4's Control Console within %5 minutes or the hack will fail!
|
||||||
|
/** {facilityType} {facilityName} has spawned a LLU.\nIt must be taken to {targetFacilityType} {targetFacilityName}'s Control Console within 15 minutes or the hack will fail! */
|
||||||
|
def CTF_FlagSpawned(owner: Building, target: Building): String = s"@CTF_FlagSpawned^@${owner.Definition.Name}~^@${owner.Name}~^@${target.Definition.Name}~^@${target.Name}~^15~"
|
||||||
|
|
||||||
|
|
||||||
|
// @CTF_FlagPickedUp=%1 of the %2 picked up %3's LLU
|
||||||
|
/** {playerName} of the {faction} picked up {facilityName}'s LLU */
|
||||||
|
def CTF_FlagPickedUp(player: Player, owner_name: String): String = s"@CTF_FlagPickedUp^${player.Name}~^@${CaptureFlagChatMessageStrings.GetFactionString(player.Faction)}~^@$owner_name~"
|
||||||
|
|
||||||
|
// @CTF_FlagDropped=%1 of the %2 dropped %3's LLU
|
||||||
|
/** {playerName} of the {faction} dropped {facilityName}'s LLU */
|
||||||
|
def CTF_FlagDropped(player: Player, owner_name: String): String = s"@CTF_FlagDropped^${player.Name}~^@${CaptureFlagChatMessageStrings.GetFactionString(player.Faction)}~^@$owner_name~"
|
||||||
|
|
||||||
|
// todo: make private
|
||||||
|
private def GetFactionString(faction: PlanetSideEmpire.Value): String = {
|
||||||
|
faction match {
|
||||||
|
case PlanetSideEmpire.TR => "TerranRepublic"
|
||||||
|
case PlanetSideEmpire.NC => "NewConglomerate"
|
||||||
|
case PlanetSideEmpire.VS => "VanuSovereigncy" // Yes, this is wrong. It is like that in packet captures.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object CaptureFlagLostReasonEnum extends Enumeration {
|
||||||
|
type CaptureFlagLostReasonEnum = Value
|
||||||
|
|
||||||
|
val Resecured, TimedOut = Value
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,26 @@
|
||||||
package net.psforever.services.local.support
|
package net.psforever.services.local.support
|
||||||
|
|
||||||
import akka.actor.{Actor, Cancellable}
|
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||||
import net.psforever.actors.zone.{BuildingActor, ZoneActor}
|
import net.psforever.actors.zone.{BuildingActor, ZoneActor}
|
||||||
import net.psforever.objects.serverobject.CommonMessages
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
|
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.Building
|
||||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.objects.{Default, GlobalDefinitions}
|
import net.psforever.objects.{Default, GlobalDefinitions}
|
||||||
import net.psforever.packet.game.PlanetsideAttributeEnum
|
import net.psforever.packet.game.{GenericActionEnum, PlanetsideAttributeEnum}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import scala.concurrent.duration.{FiniteDuration, _}
|
import scala.concurrent.duration.{FiniteDuration, _}
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
class HackCaptureActor extends Actor {
|
/**
|
||||||
|
* Responsible for handling the aspects related to hacking control consoles and capturing bases.
|
||||||
|
*/
|
||||||
|
class HackCaptureActor(val taskResolver: ActorRef) extends Actor {
|
||||||
private[this] val log = org.log4s.getLogger
|
private[this] val log = org.log4s.getLogger
|
||||||
|
|
||||||
private var clearTrigger: Cancellable = Default.Cancellable
|
private var clearTrigger: Cancellable = Default.Cancellable
|
||||||
|
|
@ -61,6 +66,7 @@ class HackCaptureActor extends Actor {
|
||||||
RestartTimer()
|
RestartTimer()
|
||||||
|
|
||||||
NotifyHackStateChange(target, isResecured = false)
|
NotifyHackStateChange(target, isResecured = false)
|
||||||
|
TrySpawnCaptureFlag(target)
|
||||||
|
|
||||||
case HackCaptureActor.ProcessCompleteHacks() =>
|
case HackCaptureActor.ProcessCompleteHacks() =>
|
||||||
log.trace("Processing complete hacks")
|
log.trace("Processing complete hacks")
|
||||||
|
|
@ -75,7 +81,19 @@ class HackCaptureActor extends Actor {
|
||||||
val hackedByFaction = entry.target.HackedBy.get.hackerFaction
|
val hackedByFaction = entry.target.HackedBy.get.hackerFaction
|
||||||
entry.target.Actor ! CommonMessages.ClearHack()
|
entry.target.Actor ! CommonMessages.ClearHack()
|
||||||
|
|
||||||
HackCompleted(entry.target, hackedByFaction)
|
entry.target.Owner.asInstanceOf[Building].GetFlagSocket match {
|
||||||
|
case Some(socket) =>
|
||||||
|
// LLU was not delivered in time. Send resecured notifications
|
||||||
|
entry.target.Owner.asInstanceOf[Building].GetFlag match {
|
||||||
|
case Some(flag: CaptureFlag) => entry.target.Zone.LocalEvents ! CaptureFlagManager.Lost(flag, CaptureFlagLostReasonEnum.TimedOut)
|
||||||
|
case None => log.warn(s"Failed to find capture flag matching socket ${socket.GUID}")
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyHackStateChange(entry.target, isResecured = true)
|
||||||
|
case None =>
|
||||||
|
// Timed hack finished, capture the base
|
||||||
|
HackCompleted(entry.target, hackedByFaction)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// If there's hacked objects left in the list restart the timer with the shortest hack time left
|
// If there's hacked objects left in the list restart the timer with the shortest hack time left
|
||||||
|
|
@ -84,32 +102,79 @@ class HackCaptureActor extends Actor {
|
||||||
case HackCaptureActor.ResecureCaptureTerminal(target, _) =>
|
case HackCaptureActor.ResecureCaptureTerminal(target, _) =>
|
||||||
hackedObjects = hackedObjects.filterNot(x => x.target == target)
|
hackedObjects = hackedObjects.filterNot(x => x.target == target)
|
||||||
|
|
||||||
|
// If LLU exists it was not delivered. Send resecured notifications
|
||||||
|
target.Owner.asInstanceOf[Building].GetFlag match {
|
||||||
|
case Some(flag: CaptureFlag) => target.Zone.LocalEvents ! CaptureFlagManager.Lost(flag, CaptureFlagLostReasonEnum.Resecured)
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
|
||||||
NotifyHackStateChange(target, isResecured = true)
|
NotifyHackStateChange(target, isResecured = true)
|
||||||
|
|
||||||
// Restart the timer in case the object we just removed was the next one scheduled
|
// Restart the timer in case the object we just removed was the next one scheduled
|
||||||
RestartTimer()
|
RestartTimer()
|
||||||
|
case HackCaptureActor.FlagCaptured(flag) =>
|
||||||
|
log.warn(hackedObjects.toString())
|
||||||
|
hackedObjects.find(_.target.GUID == flag.Owner.asInstanceOf[Building].CaptureTerminal.get.GUID) match {
|
||||||
|
case Some(entry) =>
|
||||||
|
val hackedByFaction = entry.target.HackedBy.get.hackerFaction
|
||||||
|
hackedObjects = hackedObjects.filterNot(x => x == entry)
|
||||||
|
HackCompleted(entry.target, hackedByFaction)
|
||||||
|
|
||||||
|
entry.target.Actor ! CommonMessages.ClearHack()
|
||||||
|
|
||||||
|
flag.Zone.LocalEvents ! CaptureFlagManager.Captured(flag)
|
||||||
|
|
||||||
|
// If there's hacked objects left in the list restart the timer with the shortest hack time left
|
||||||
|
RestartTimer()
|
||||||
|
case _ =>
|
||||||
|
log.error(s"Attempted LLU capture for ${flag.Owner.asInstanceOf[Building].Name} but CC GUID ${flag.Owner.asInstanceOf[Building].CaptureTerminal.get.GUID} was not in list of hacked objects")
|
||||||
|
}
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private def NotifyHackStateChange(target: CaptureTerminal, isResecured: Boolean): Unit = {
|
private def TrySpawnCaptureFlag(terminal: CaptureTerminal): Unit = {
|
||||||
val attribute_value = HackCaptureActor.GetHackUpdateAttributeValue(target, isResecured)
|
// Handle LLUs if the base contains a LLU socket
|
||||||
|
// If there are no neighbouring bases belonging to the hacking faction this will be handled as a regular timed hack (e.g. neutral base in enemy territory)
|
||||||
|
val owner = terminal.Owner.asInstanceOf[Building]
|
||||||
|
val hackingFaction = HackCaptureActor.GetHackingFaction(terminal).get
|
||||||
|
val hackingFactionNeighbourBases = owner.Neighbours(hackingFaction)
|
||||||
|
|
||||||
|
hackingFactionNeighbourBases match {
|
||||||
|
case Some(neighbours) =>
|
||||||
|
if(owner.IsCtfBase) {
|
||||||
|
// Find a random neighbouring base matching the hacking faction
|
||||||
|
val targetBase = neighbours.toVector((new Random).nextInt(neighbours.size))
|
||||||
|
|
||||||
|
// Request LLU is created by CaptureFlagActor via LocalService
|
||||||
|
terminal.Zone.LocalEvents ! CaptureFlagManager.SpawnCaptureFlag(terminal, targetBase, hackingFaction)
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
log.info("Couldn't find any neighbouring bases for LLU hack.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def NotifyHackStateChange(terminal: CaptureTerminal, isResecured: Boolean): Unit = {
|
||||||
|
val attribute_value = HackCaptureActor.GetHackUpdateAttributeValue(terminal, isResecured)
|
||||||
|
|
||||||
// Notify all clients that CC has been hacked
|
// Notify all clients that CC has been hacked
|
||||||
target.Zone.LocalEvents ! LocalServiceMessage(
|
terminal.Zone.LocalEvents ! LocalServiceMessage(
|
||||||
target.Zone.id,
|
terminal.Zone.id,
|
||||||
LocalAction.SendPlanetsideAttributeMessage(
|
LocalAction.SendPlanetsideAttributeMessage(
|
||||||
PlanetSideGUID(-1),
|
PlanetSideGUID(-1),
|
||||||
target.GUID,
|
terminal.GUID,
|
||||||
PlanetsideAttributeEnum.ControlConsoleHackUpdate,
|
PlanetsideAttributeEnum.ControlConsoleHackUpdate,
|
||||||
attribute_value
|
attribute_value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val owner = terminal.Owner.asInstanceOf[Building]
|
||||||
|
|
||||||
// Notify parent building that state has changed
|
// Notify parent building that state has changed
|
||||||
target.Owner.Actor ! BuildingActor.AmenityStateChange(target, Some(isResecured))
|
owner.Actor ! BuildingActor.AmenityStateChange(terminal, Some(isResecured))
|
||||||
|
|
||||||
// Push map update to clients
|
// Push map update to clients
|
||||||
target.Owner.asInstanceOf[Building].Zone.actor ! ZoneActor.ZoneMapUpdate()
|
owner.Zone.actor ! ZoneActor.ZoneMapUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
private def HackCompleted(terminal: CaptureTerminal with Hackable, hackedByFaction: PlanetSideEmpire.Value): Unit = {
|
||||||
|
|
@ -117,6 +182,9 @@ class HackCaptureActor extends Actor {
|
||||||
if (building.NtuLevel > 0) {
|
if (building.NtuLevel > 0) {
|
||||||
log.info(s"Setting base ${building.GUID} / MapId: ${building.MapId} as owned by $hackedByFaction")
|
log.info(s"Setting base ${building.GUID} / MapId: ${building.MapId} as owned by $hackedByFaction")
|
||||||
building.Actor! BuildingActor.SetFaction(hackedByFaction)
|
building.Actor! BuildingActor.SetFaction(hackedByFaction)
|
||||||
|
|
||||||
|
// todo: This should probably only go to those within the captured SOI who belong to the capturing faction
|
||||||
|
building.Zone.LocalEvents ! LocalServiceMessage(building.Zone.id, LocalAction.SendGenericActionMessage(PlanetSideGUID(-1), GenericActionEnum.BaseCaptureFanfare))
|
||||||
} else {
|
} else {
|
||||||
log.info("Base hack completed, but base was out of NTU.")
|
log.info("Base hack completed, but base was out of NTU.")
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +228,7 @@ object HackCaptureActor {
|
||||||
)
|
)
|
||||||
|
|
||||||
final case class ResecureCaptureTerminal(target: CaptureTerminal, zone: Zone)
|
final case class ResecureCaptureTerminal(target: CaptureTerminal, zone: Zone)
|
||||||
|
final case class FlagCaptured(flag: CaptureFlag)
|
||||||
|
|
||||||
private final case class ProcessCompleteHacks()
|
private final case class ProcessCompleteHacks()
|
||||||
|
|
||||||
|
|
@ -172,11 +241,19 @@ object HackCaptureActor {
|
||||||
hack_timestamp: Long
|
hack_timestamp: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
def GetHackUpdateAttributeValue(target: CaptureTerminal, isResecured: Boolean): Long = {
|
def GetHackingFaction(terminal: CaptureTerminal): Option[PlanetSideEmpire.Value] = {
|
||||||
|
terminal.HackedBy match {
|
||||||
|
case Some(Hackable.HackInfo(_, _, hackingFaction, _, _, _)) =>
|
||||||
|
Some(hackingFaction)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def GetHackUpdateAttributeValue(terminal: CaptureTerminal, isResecured: Boolean): Long = {
|
||||||
if (isResecured) {
|
if (isResecured) {
|
||||||
17039360L
|
17039360L
|
||||||
} else {
|
} else {
|
||||||
target.HackedBy match {
|
terminal.HackedBy match {
|
||||||
case Some(Hackable.HackInfo(_, _, hackingFaction, _, start, length)) =>
|
case Some(Hackable.HackInfo(_, _, hackingFaction, _, start, length)) =>
|
||||||
// See PlanetSideAttributeMessage #20 documentation for an explanation of how the timer is calculated
|
// See PlanetSideAttributeMessage #20 documentation for an explanation of how the timer is calculated
|
||||||
val hack_time_remaining_ms =
|
val hack_time_remaining_ms =
|
||||||
|
|
|
||||||
|
|
@ -248,14 +248,24 @@ object ChatMessageType extends Enum[ChatMessageType] {
|
||||||
case object CMT_REMOVE_VANUMODULE extends ChatMessageType // /moduleremove OR /modulerm
|
case object CMT_REMOVE_VANUMODULE extends ChatMessageType // /moduleremove OR /modulerm
|
||||||
case object CMT_DEBUG_MASSIVE extends ChatMessageType // /debugmassive
|
case object CMT_DEBUG_MASSIVE extends ChatMessageType // /debugmassive
|
||||||
case object CMT_WARP_TO_NEXT_BILLBOARD extends ChatMessageType // ???
|
case object CMT_WARP_TO_NEXT_BILLBOARD extends ChatMessageType // ???
|
||||||
case object UNK_222 extends ChatMessageType // ??? "CTF Flag stolen"
|
case object UNK_222 extends ChatMessageType // "CTF Flag stolen"
|
||||||
case object UNK_223 extends ChatMessageType // ??? "CTF Flag lost"
|
// Plays a trumpet-like sound and displays the message: "<Base Type> <Base Name> has spawned a LLU"
|
||||||
|
// "It must be taken to <Base Type> <Base Name>'s Control Console within 15 minutes or the hack will fail!"
|
||||||
|
// Example string: @CTF_FlagSpawned^@cryo_facility~^@Hanish~^@comm_station_dsp~^@Akkan~^15~
|
||||||
|
case object UNK_223 extends ChatMessageType // "CTF Flag lost"
|
||||||
|
// Handles both LLU lost and LLU resecured
|
||||||
|
// Example string: @CTF_Failed_SourceResecured^@TerranRepublic~^@Hanish~
|
||||||
|
// Output: "The Terran Republic resecured Hanish!" "The LLU was lost!"
|
||||||
|
// Example string: @CTF_Failed_FlagLost^@TerranRepublic~^@Hanish~
|
||||||
|
// Output: "The Terran Republic lost Hanish's LLU" "Hack canceled!"
|
||||||
case object UNK_224 extends ChatMessageType // ??? "Vehicle Dismount"
|
case object UNK_224 extends ChatMessageType // ??? "Vehicle Dismount"
|
||||||
case object UNK_225 extends ChatMessageType // ??? empty
|
case object UNK_225 extends ChatMessageType // ??? empty
|
||||||
case object UNK_226 extends ChatMessageType // ??? empty
|
case object UNK_226 extends ChatMessageType // ??? empty
|
||||||
case object UNK_227 extends ChatMessageType // ??? empty
|
case object UNK_227 extends ChatMessageType // ??? empty
|
||||||
case object UNK_228 extends ChatMessageType // ??? empty
|
case object UNK_228 extends ChatMessageType // ??? empty
|
||||||
case object UNK_229 extends ChatMessageType // ??? empty
|
case object UNK_229 extends ChatMessageType // See UNK_222 - seems to do the same except without trumpet-like sound
|
||||||
|
// Is used for flag pickup @CTF_FlagPickedUp^OzTurtle~^@NewConglomerate~^@Qumu~
|
||||||
|
// Or flag warning @CTF_Warning_Carrier^VanuHemlock~^@VanuSovereigncy~^@Mani~^@Dagur~^10~
|
||||||
case object UNK_230 extends ChatMessageType // ??? "Vehicle Mount"
|
case object UNK_230 extends ChatMessageType // ??? "Vehicle Mount"
|
||||||
case object UNK_231 extends ChatMessageType // ??? empty
|
case object UNK_231 extends ChatMessageType // ??? empty
|
||||||
case object UNK_232 extends ChatMessageType // ??? empty
|
case object UNK_232 extends ChatMessageType // ??? empty
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import net.psforever.objects.ballistics.Projectile
|
||||||
import net.psforever.objects.definition.BasicDefinition
|
import net.psforever.objects.definition.BasicDefinition
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.generator.Generator
|
import net.psforever.objects.serverobject.generator.Generator
|
||||||
|
import net.psforever.objects.serverobject.llu.{CaptureFlagSocket, CaptureFlagSocketDefinition}
|
||||||
import net.psforever.objects.serverobject.locks.IFFLock
|
import net.psforever.objects.serverobject.locks.IFFLock
|
||||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnPad, VehicleSpawnPadDefinition}
|
import net.psforever.objects.serverobject.pad.{VehicleSpawnPad, VehicleSpawnPadDefinition}
|
||||||
import net.psforever.objects.serverobject.painbox.{Painbox, PainboxDefinition}
|
import net.psforever.objects.serverobject.painbox.{Painbox, PainboxDefinition}
|
||||||
|
|
@ -338,6 +339,15 @@ object Zones {
|
||||||
),
|
),
|
||||||
owningBuildingGuid = ownerGuid
|
owningBuildingGuid = ownerGuid
|
||||||
)
|
)
|
||||||
|
case "llm_socket" =>
|
||||||
|
zoneMap.addLocalObject(
|
||||||
|
obj.guid,
|
||||||
|
CaptureFlagSocket.Constructor(
|
||||||
|
obj.objectDefinition.asInstanceOf[CaptureFlagSocketDefinition],
|
||||||
|
obj.position
|
||||||
|
),
|
||||||
|
owningBuildingGuid = ownerGuid
|
||||||
|
)
|
||||||
|
|
||||||
case "gr_door_mb_orb" =>
|
case "gr_door_mb_orb" =>
|
||||||
zoneMap
|
zoneMap
|
||||||
|
|
|
||||||
48
src/test/scala/game/CaptureFlagUpdateMessageTest.scala
Normal file
48
src/test/scala/game/CaptureFlagUpdateMessageTest.scala
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import net.psforever.packet.PacketCoding
|
||||||
|
import net.psforever.packet.game.{CaptureFlagUpdateMessage, FlagInfo}
|
||||||
|
import org.specs2.control.Debug
|
||||||
|
import org.specs2.mutable.Specification
|
||||||
|
import scodec.bits._
|
||||||
|
|
||||||
|
class CaptureFlagUpdateMessageTest extends Specification with Debug {
|
||||||
|
val stringZero = hex"c0 0a0000"
|
||||||
|
val stringOne = hex"c0 0a0014300018025281dd852830803000"
|
||||||
|
|
||||||
|
"decode (zero)" in {
|
||||||
|
PacketCoding.decodePacket(stringZero).require match {
|
||||||
|
case CaptureFlagUpdateMessage(zone_number, flagInfoList) =>
|
||||||
|
zone_number mustEqual 10
|
||||||
|
flagInfoList.length mustEqual 0
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"decode (one)" in {
|
||||||
|
PacketCoding.decodePacket(stringOne).require match {
|
||||||
|
case CaptureFlagUpdateMessage(zone_number, flagInfoList) =>
|
||||||
|
zone_number mustEqual 10
|
||||||
|
flagInfoList.length mustEqual 1
|
||||||
|
flagInfoList.head mustEqual FlagInfo(1, 12, 6, 3905.1562f, 5160.922f, 794636L, false)
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (zero)" in {
|
||||||
|
val msg = CaptureFlagUpdateMessage(10, Nil)
|
||||||
|
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual stringZero
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (one)" in {
|
||||||
|
val msg = CaptureFlagUpdateMessage(10, List(FlagInfo(1, 12, 6, 3905.1562f, 5160.922f, 794636L, false)))
|
||||||
|
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual stringOne
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -29,24 +29,16 @@ class CaptureFlagDataTest extends Specification {
|
||||||
flag.pos.orient.y mustEqual 0f
|
flag.pos.orient.y mustEqual 0f
|
||||||
flag.pos.orient.z mustEqual 47.8125f
|
flag.pos.orient.z mustEqual 47.8125f
|
||||||
flag.faction mustEqual PlanetSideEmpire.NC
|
flag.faction mustEqual PlanetSideEmpire.NC
|
||||||
flag.unk1 mustEqual 21
|
flag.owningBaseGuid mustEqual 21
|
||||||
flag.unk2 mustEqual 4
|
flag.targetBaseGuid mustEqual 4
|
||||||
flag.unk3 mustEqual 2838
|
flag.milliseconds_remaining mustEqual 592662
|
||||||
flag.unk4 mustEqual 9
|
|
||||||
case _ =>
|
case _ =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode" in {
|
"encode" in {
|
||||||
val obj = CaptureFlagData(
|
val obj = CaptureFlagData(PlacementData(3912.0312f, 5169.4375f, 59.96875f, 0f, 0f, 47.8125f), PlanetSideEmpire.NC, 21, 4, 592662)
|
||||||
PlacementData(3912.0312f, 5169.4375f, 59.96875f, 0f, 0f, 47.8125f),
|
|
||||||
PlanetSideEmpire.NC,
|
|
||||||
21,
|
|
||||||
4,
|
|
||||||
2838,
|
|
||||||
9
|
|
||||||
)
|
|
||||||
val msg = ObjectCreateMessage(ObjectClass.capture_flag, PlanetSideGUID(4330), obj)
|
val msg = ObjectCreateMessage(ObjectClass.capture_flag, PlanetSideGUID(4330), obj)
|
||||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||||
pkt mustEqual string_captureflag
|
pkt mustEqual string_captureflag
|
||||||
|
|
|
||||||
|
|
@ -526,7 +526,7 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
||||||
assert(player2.isAlive)
|
assert(player2.isAlive)
|
||||||
|
|
||||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar = avatarProbe.receiveN(7, 500 milliseconds)
|
val msg_avatar = avatarProbe.receiveN(8, 500 milliseconds)
|
||||||
val msg_stamina = probe.receiveOne(500 milliseconds)
|
val msg_stamina = probe.receiveOne(500 milliseconds)
|
||||||
activityProbe.expectNoMessage(200 milliseconds)
|
activityProbe.expectNoMessage(200 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
|
|
@ -543,25 +543,31 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(1) match {
|
msg_avatar(1) match {
|
||||||
|
case AvatarServiceMessage("TestCharacter2", AvatarAction.DropSpecialItem()) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
msg_avatar(2) match {
|
||||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.Killed(PlanetSideGUID(2), None)) => true
|
case AvatarServiceMessage("TestCharacter2", AvatarAction.Killed(PlanetSideGUID(2), None)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(2) match {
|
msg_avatar(3) match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(3) match {
|
msg_avatar(4) match {
|
||||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 7, _)) =>
|
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 7, _)) =>
|
||||||
true
|
true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(4) match {
|
msg_avatar(5) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
||||||
|
|
@ -571,7 +577,7 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(5) match {
|
msg_avatar(6) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.SendResponse(
|
AvatarAction.SendResponse(
|
||||||
|
|
@ -584,7 +590,7 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(6) match {
|
msg_avatar(7) match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||||
true
|
true
|
||||||
|
|
@ -666,7 +672,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
assert(player2.isAlive)
|
assert(player2.isAlive)
|
||||||
|
|
||||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar = avatarProbe.receiveN(8, 500 milliseconds)
|
val msg_avatar = avatarProbe.receiveN(9, 500 milliseconds)
|
||||||
val msg_stamina = probe.receiveOne(500 milliseconds)
|
val msg_stamina = probe.receiveOne(500 milliseconds)
|
||||||
activityProbe.expectNoMessage(200 milliseconds)
|
activityProbe.expectNoMessage(200 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
|
|
@ -677,6 +683,12 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar.head match {
|
msg_avatar.head match {
|
||||||
|
case AvatarServiceMessage("TestCharacter2", AvatarAction.DropSpecialItem()) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
msg_avatar(1) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.Killed(PlanetSideGUID(2), Some(PlanetSideGUID(7)))
|
AvatarAction.Killed(PlanetSideGUID(2), Some(PlanetSideGUID(7)))
|
||||||
|
|
@ -686,7 +698,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(1) match {
|
msg_avatar(2) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(7), PlanetSideGUID(2), _, _, _, _))
|
AvatarAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(7), PlanetSideGUID(2), _, _, _, _))
|
||||||
|
|
@ -696,7 +708,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(2) match {
|
msg_avatar(3) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 29, 1)
|
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 29, 1)
|
||||||
|
|
@ -706,19 +718,19 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(3) match {
|
msg_avatar(4) match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(2), PlanetSideGUID(2), _)) => true
|
case AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(2), PlanetSideGUID(2), _)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(4) match {
|
msg_avatar(5) match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(5) match {
|
msg_avatar(6) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
||||||
|
|
@ -728,7 +740,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(6) match {
|
msg_avatar(7) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter2",
|
"TestCharacter2",
|
||||||
AvatarAction.SendResponse(
|
AvatarAction.SendResponse(
|
||||||
|
|
@ -741,7 +753,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(7) match {
|
msg_avatar(8) match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||||
true
|
true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue