diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 81dd2bc5..00238b9b 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -21,3 +21,63 @@ ConnectionType=USBOnly bUseManualIPAddress=False ManualIPAddress= +[/Script/Engine.UserInterfaceSettings] +UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000)),DefaultValue=340282346638528859811704183484516925440.000000,PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant),ExternalCurve=None) + +[/Script/Engine.CollisionProfile] +-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False) +-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +-Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False) +-Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False) +-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False) +-Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False) +-Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False) +-Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False) +-Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False) +-Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) ++Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision") ++Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="BlockAllDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=,HelpMessage="WorldDynamic object that blocks all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="OverlapAllDynamic",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.") ++Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ") ++Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ") ++Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.") ++Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.") ++Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors") ++Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors") ++Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.") ++Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.") ++Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.") ++Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.") ++Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.") ++Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Clickable") +-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") +-ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") +-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") +-ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") +-ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") ++ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") ++ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") ++ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") ++ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") ++ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") +-CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") +-CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") +-CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +-CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") ++CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") ++CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") ++CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") ++CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") + diff --git a/Content/Characters/Mannequins/Meshes/SKM_Quinn_Simple.uasset b/Content/Characters/Mannequins/Meshes/SKM_Quinn_Simple.uasset index 7e901388..0b606fd2 100644 --- a/Content/Characters/Mannequins/Meshes/SKM_Quinn_Simple.uasset +++ b/Content/Characters/Mannequins/Meshes/SKM_Quinn_Simple.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c152c57376b944884b51e946c6f63ac7659e15f11d9e666b374b80d7e4e9090 -size 20192554 +oid sha256:c9f925b0340d7923dc686caf959893a7be4fdde267fad75170759bcc636faccc +size 20189606 diff --git a/Content/ConsoleBP.uasset b/Content/ConsoleBP.uasset deleted file mode 100644 index 1bfa8e95..00000000 --- a/Content/ConsoleBP.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44894a71555443b2e286d11e1b096f3b51229a1691747a294a449e9f16348899 -size 69985 diff --git a/Content/LpxLevel.umap b/Content/LpxLevel.umap index aebb8219..57d259ab 100644 --- a/Content/LpxLevel.umap +++ b/Content/LpxLevel.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e701643051248919d97ef49aab113b70850b4c32ddad6c296b459cccc44eeb4d -size 11962 +oid sha256:b081e31151154830f103c56374bf2d98006a0d0896cff3c0a9a0b8b31f536f28 +size 12394 diff --git a/Content/Luprex/Widgets/lxConsoleWidget.uasset b/Content/Luprex/Widgets/lxConsoleWidget.uasset new file mode 100644 index 00000000..7329c3ad --- /dev/null +++ b/Content/Luprex/Widgets/lxConsoleWidget.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46d9c6bd495d3b1b2e39bf9e8c22206e5caf878ad107594b6030f93efc87bcb3 +size 70316 diff --git a/Content/Luprex/Widgets/lxCrosshairImage.uasset b/Content/Luprex/Widgets/lxCrosshairImage.uasset new file mode 100644 index 00000000..5e0afff0 --- /dev/null +++ b/Content/Luprex/Widgets/lxCrosshairImage.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1a5ba9cdf9bb9172629790c999fc68eabaf46e49e680aab347031b5afbde410 +size 8098 diff --git a/Content/Luprex/Widgets/lxCrosshairWidget.uasset b/Content/Luprex/Widgets/lxCrosshairWidget.uasset new file mode 100644 index 00000000..90ebb56d --- /dev/null +++ b/Content/Luprex/Widgets/lxCrosshairWidget.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca2f1bdb208e3fdf94f879e3b43fba531edadb4f80995249410a49ce3a1eaec6 +size 100225 diff --git a/Content/Luprex/lxCrosshairImage.uasset b/Content/Luprex/lxCrosshairImage.uasset new file mode 100644 index 00000000..ed91d253 --- /dev/null +++ b/Content/Luprex/lxCrosshairImage.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3560d4788e77b90c908e26cd058469f939122c2b8cfe2c75ef8fe0a40d404503 +size 1156 diff --git a/Content/Luprex/lxGameMode.uasset b/Content/Luprex/lxGameMode.uasset old mode 100755 new mode 100644 index 02b9c9f9..f8f28a0f --- a/Content/Luprex/lxGameMode.uasset +++ b/Content/Luprex/lxGameMode.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f98cfcb8de9d911f6578aec8989768fbb0d0147a5c1cfaa96dca50866125d3e -size 91884 +oid sha256:a3388383be8e9d8cf2cf5ba6f115be6e15578c8a1953aea7d16052a91b06a8cf +size 123371 diff --git a/Content/Luprex/lxLookAtDetectionLibrary.uasset b/Content/Luprex/lxLookAtDetectionLibrary.uasset deleted file mode 100644 index 38b68e07..00000000 --- a/Content/Luprex/lxLookAtDetectionLibrary.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a65cbfd4c1963480f8133f9cae8d0c322498aad2cab2d6de4adfd9aefe3f67b -size 78667 diff --git a/Content/Tangibles/tangiblecharacter.uasset b/Content/Tangibles/tangiblecharacter.uasset index a5e04f15..52ccc390 100644 --- a/Content/Tangibles/tangiblecharacter.uasset +++ b/Content/Tangibles/tangiblecharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d007d75d8a5cbe759673a17a353f2fb5fd4f7892256aedcea40f84f8aaf91f45 -size 377808 +oid sha256:e867bfbaed611387e5649533a7dafc441163cddd09908621422ea5ca334d6ac2 +size 367701 diff --git a/Content/__ExternalActors__/LpxLevel/0/66/X0GCYH1TGNOYLDB0SFDV03.uasset b/Content/__ExternalActors__/LpxLevel/0/66/X0GCYH1TGNOYLDB0SFDV03.uasset index b47dcb64..a9c29332 100644 --- a/Content/__ExternalActors__/LpxLevel/0/66/X0GCYH1TGNOYLDB0SFDV03.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/66/X0GCYH1TGNOYLDB0SFDV03.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c43585730eef2a6fec270b9a78107acd5c0f0033a26a462eab9e50cf551a75a -size 455885 +oid sha256:bf136ca891aaf4d355e7648198f7b0707a2caf425a13c871062bf3429e8d9014 +size 404269 diff --git a/Content/__ExternalActors__/LpxLevel/0/9J/EALUP75HHV6CSV3JMBUCXH.uasset b/Content/__ExternalActors__/LpxLevel/0/9J/EALUP75HHV6CSV3JMBUCXH.uasset index 2d7cfc5b..e0333223 100644 --- a/Content/__ExternalActors__/LpxLevel/0/9J/EALUP75HHV6CSV3JMBUCXH.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/9J/EALUP75HHV6CSV3JMBUCXH.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d5fe78f62ce99b3498baa8bb3a236e98b18292c1aa518196f5cfd3ce7fa7c3a -size 5759 +oid sha256:9c1d2db43ad65c73825f5f00f8bb0360d2472fd0ef04c45939ccf87f136ec688 +size 5647 diff --git a/Content/__ExternalActors__/LpxLevel/0/JE/A3W7IQYEBHC39R6JJPSDRO.uasset b/Content/__ExternalActors__/LpxLevel/0/JE/A3W7IQYEBHC39R6JJPSDRO.uasset index 083801bc..df8f0d41 100644 --- a/Content/__ExternalActors__/LpxLevel/0/JE/A3W7IQYEBHC39R6JJPSDRO.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/JE/A3W7IQYEBHC39R6JJPSDRO.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83e7bce5e52931decfa660f933ce2c648484481fd31af628c44d04359124e4da -size 2352 +oid sha256:959cde969ddcbec6020ab33805293b85923c7bf02aa17c06f314e9cc29822b3a +size 2196 diff --git a/Content/__ExternalActors__/LpxLevel/0/WZ/DDRQBDEVFRQ5E4D5G53TW8.uasset b/Content/__ExternalActors__/LpxLevel/0/WZ/DDRQBDEVFRQ5E4D5G53TW8.uasset index c86425dc..f0d6c14e 100644 --- a/Content/__ExternalActors__/LpxLevel/0/WZ/DDRQBDEVFRQ5E4D5G53TW8.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/WZ/DDRQBDEVFRQ5E4D5G53TW8.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5886fcb7fa163341fb03b54a7da7e078e344d0818844e87a0f6fdea7dbf44a38 -size 3843 +oid sha256:dc1b922033067320a0f9dcd2100b2fd9b9d1331bf8a8bf035aad5fe05dc7faac +size 3731 diff --git a/Content/__ExternalActors__/LpxLevel/0/YE/DJEJUUG7D4AHDPSW85KN6S.uasset b/Content/__ExternalActors__/LpxLevel/0/YE/DJEJUUG7D4AHDPSW85KN6S.uasset index f8121a34..8a84c82f 100644 --- a/Content/__ExternalActors__/LpxLevel/0/YE/DJEJUUG7D4AHDPSW85KN6S.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/YE/DJEJUUG7D4AHDPSW85KN6S.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6f642dbbde12e4f69f66fa53c54f474dc7e158c63833ee00ff707c0b6938d3d -size 478909 +oid sha256:0d8fa49bf293c193c60a6ca94cf64f6e114c4fce644d625c90f69b52cf2c0288 +size 447679 diff --git a/Content/__ExternalActors__/LpxLevel/0/ZA/FB9A5WXXDA0YOT88V30JGA.uasset b/Content/__ExternalActors__/LpxLevel/0/ZA/FB9A5WXXDA0YOT88V30JGA.uasset index a891e47f..bba6ebdc 100644 --- a/Content/__ExternalActors__/LpxLevel/0/ZA/FB9A5WXXDA0YOT88V30JGA.uasset +++ b/Content/__ExternalActors__/LpxLevel/0/ZA/FB9A5WXXDA0YOT88V30JGA.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9481b8c44f637deb5a56de8dd6cd635ad4d3decea658b9a66bd26eb4e8e14f1 -size 426869 +oid sha256:ca3562797a123b0f401a0cd1a0f76585c94240eae983824130c314dae3a259f9 +size 387129 diff --git a/Content/__ExternalActors__/LpxLevel/1/7B/D182Z2V501JNQZNWKL2U14.uasset b/Content/__ExternalActors__/LpxLevel/1/7B/D182Z2V501JNQZNWKL2U14.uasset index f9e3f623..7c00b97c 100644 --- a/Content/__ExternalActors__/LpxLevel/1/7B/D182Z2V501JNQZNWKL2U14.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/7B/D182Z2V501JNQZNWKL2U14.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21a23eb34f07c0bdce6ff5e7711fce12e4de8927361ab021fdb6d13b4c3c685c -size 554090 +oid sha256:f7f4c4ae69ffaf001222a47a3a6dcbb7af020b584ad3dde3189b56eb1a3578fc +size 518476 diff --git a/Content/__ExternalActors__/LpxLevel/1/C9/53FF0O85Z9UKFQ7GEBWPQ6.uasset b/Content/__ExternalActors__/LpxLevel/1/C9/53FF0O85Z9UKFQ7GEBWPQ6.uasset index c3c56d32..fa37631f 100644 --- a/Content/__ExternalActors__/LpxLevel/1/C9/53FF0O85Z9UKFQ7GEBWPQ6.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/C9/53FF0O85Z9UKFQ7GEBWPQ6.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:173e0b6747c6e4c9bd5d91dfd543238eb96dfde85d4426eccf4a1f92484a6148 -size 497687 +oid sha256:86bd273f7697618c5a704d554cc2e90475ee32e9bf82512b2e22151525220a6d +size 468096 diff --git a/Content/__ExternalActors__/LpxLevel/1/F1/ABNLWBX0GPBQB6VZ2YK27H.uasset b/Content/__ExternalActors__/LpxLevel/1/F1/ABNLWBX0GPBQB6VZ2YK27H.uasset index edba9b1f..b1685c23 100644 --- a/Content/__ExternalActors__/LpxLevel/1/F1/ABNLWBX0GPBQB6VZ2YK27H.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/F1/ABNLWBX0GPBQB6VZ2YK27H.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6aba9ebfbd8ffc81cde2624356d347b629d857da34c2ecf9a4418ad3df633522 -size 494934 +oid sha256:582542506544590e775b03fe188e220bf7b9498eeecbaac651f60622dbb27bfd +size 460559 diff --git a/Content/__ExternalActors__/LpxLevel/1/FW/Y2ARK4XBC9FW3QDSIEZAR9.uasset b/Content/__ExternalActors__/LpxLevel/1/FW/Y2ARK4XBC9FW3QDSIEZAR9.uasset index 22842396..7047df7b 100644 --- a/Content/__ExternalActors__/LpxLevel/1/FW/Y2ARK4XBC9FW3QDSIEZAR9.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/FW/Y2ARK4XBC9FW3QDSIEZAR9.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7735b0677f9c379ec0d5dbc76c3e476ab7b2700b3a9c3f90139e75671981bd25 -size 531095 +oid sha256:9202a76219c57bd0879376c569bdaef857bea7877b8d62774e891bfdcce58fe1 +size 491554 diff --git a/Content/__ExternalActors__/LpxLevel/1/KM/BSUWM0S3UGKUW23BTTPFM5.uasset b/Content/__ExternalActors__/LpxLevel/1/KM/BSUWM0S3UGKUW23BTTPFM5.uasset index 46b42540..337ae63d 100644 --- a/Content/__ExternalActors__/LpxLevel/1/KM/BSUWM0S3UGKUW23BTTPFM5.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/KM/BSUWM0S3UGKUW23BTTPFM5.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f0b8adaa281bad903948588cbf8a4d8a01d32a6bb6928ea37f2504a298487ea -size 462735 +oid sha256:8b1ce4a9875d59c89e80e653f9284b053b6134c298bc40479a8df969bd576459 +size 442220 diff --git a/Content/__ExternalActors__/LpxLevel/1/MC/PH6ZWMCYT7IC0RK7CY3EZ1.uasset b/Content/__ExternalActors__/LpxLevel/1/MC/PH6ZWMCYT7IC0RK7CY3EZ1.uasset index 0194120c..cf7d5887 100644 --- a/Content/__ExternalActors__/LpxLevel/1/MC/PH6ZWMCYT7IC0RK7CY3EZ1.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/MC/PH6ZWMCYT7IC0RK7CY3EZ1.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69f2b31615d6420fd4e6a950fb72b8c47bd89a3cf051dcbad3220ecbe6471119 -size 557975 +oid sha256:ecee29099f06e8012af1fbda4a4ca993e8011e567188ced2cb9536a9c0f5c751 +size 497595 diff --git a/Content/__ExternalActors__/LpxLevel/1/TY/JNZGNBHFTKC7OHII22ZYW6.uasset b/Content/__ExternalActors__/LpxLevel/1/TY/JNZGNBHFTKC7OHII22ZYW6.uasset index 505b971d..7268d4e3 100644 --- a/Content/__ExternalActors__/LpxLevel/1/TY/JNZGNBHFTKC7OHII22ZYW6.uasset +++ b/Content/__ExternalActors__/LpxLevel/1/TY/JNZGNBHFTKC7OHII22ZYW6.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:13c067251cb7a904e249d3bd3a6c912f980179c6e6d46bb5b1a2b2ba96fd3255 -size 544780 +oid sha256:a1a1c52a7125048e5068dac061a2f5b8b28eab6c5558376466039df86ef71465 +size 503958 diff --git a/Content/__ExternalActors__/LpxLevel/2/0E/7Z9OZV0NBAB3ECAOPE37Z3.uasset b/Content/__ExternalActors__/LpxLevel/2/0E/7Z9OZV0NBAB3ECAOPE37Z3.uasset index e9b37fa4..bbd66c3e 100644 --- a/Content/__ExternalActors__/LpxLevel/2/0E/7Z9OZV0NBAB3ECAOPE37Z3.uasset +++ b/Content/__ExternalActors__/LpxLevel/2/0E/7Z9OZV0NBAB3ECAOPE37Z3.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d31af03d902df755313c1ada89749d0baf80c2c5c5fdf3e089a0dce74b9b9922 -size 542222 +oid sha256:2d8e13a5f56c9f0785871f93f5f40c3b59e854d1b7ac7b975bf43ac2cfcab847 +size 499136 diff --git a/Content/__ExternalActors__/LpxLevel/2/GG/0S5O6PMMYW733CDV7EYSKZ.uasset b/Content/__ExternalActors__/LpxLevel/2/GG/0S5O6PMMYW733CDV7EYSKZ.uasset index 7ea65952..c94dbb62 100644 --- a/Content/__ExternalActors__/LpxLevel/2/GG/0S5O6PMMYW733CDV7EYSKZ.uasset +++ b/Content/__ExternalActors__/LpxLevel/2/GG/0S5O6PMMYW733CDV7EYSKZ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6809d889d6ddbc5b5b8c6b0097fbc7c26de2fe5ed697fdb0ca8c4956e18d23bf -size 516932 +oid sha256:de2b0d45360095ac8e3c57fb4e9e73a1ec8a97da6643d1d1fe3af07c8379a7b6 +size 483365 diff --git a/Content/__ExternalActors__/LpxLevel/2/Q6/YMP5D8XSQBJ0UEALIMNTO7.uasset b/Content/__ExternalActors__/LpxLevel/2/Q6/YMP5D8XSQBJ0UEALIMNTO7.uasset index 8659ecb0..c1beb5b3 100644 --- a/Content/__ExternalActors__/LpxLevel/2/Q6/YMP5D8XSQBJ0UEALIMNTO7.uasset +++ b/Content/__ExternalActors__/LpxLevel/2/Q6/YMP5D8XSQBJ0UEALIMNTO7.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7fe2d2d905e70e0a25f419e9a991e0a4ae9100ebef2794fe91aeb54ac28c47d -size 539623 +oid sha256:b0bc006907aa3f70c3aa30e7394989225420095aab31a320cb02ba723181faa0 +size 501153 diff --git a/Content/__ExternalActors__/LpxLevel/2/ZP/RIL53ZYYUIQU7T49V8SVIR.uasset b/Content/__ExternalActors__/LpxLevel/2/ZP/RIL53ZYYUIQU7T49V8SVIR.uasset index b38370e8..2b54b50d 100644 --- a/Content/__ExternalActors__/LpxLevel/2/ZP/RIL53ZYYUIQU7T49V8SVIR.uasset +++ b/Content/__ExternalActors__/LpxLevel/2/ZP/RIL53ZYYUIQU7T49V8SVIR.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76b44846578f9e872bb6427f8072f98c5caa43d010b6afd6f9fe95ac045e97fb -size 527986 +oid sha256:081132cd67e95345b7686feee5af2b1840cb11d2b2943829d05d2fdfada0649b +size 491711 diff --git a/Content/__ExternalActors__/LpxLevel/3/0N/YZ8ENDP16S9U7P5Z2DTV0T.uasset b/Content/__ExternalActors__/LpxLevel/3/0N/YZ8ENDP16S9U7P5Z2DTV0T.uasset index 12dae810..e3f43c20 100644 --- a/Content/__ExternalActors__/LpxLevel/3/0N/YZ8ENDP16S9U7P5Z2DTV0T.uasset +++ b/Content/__ExternalActors__/LpxLevel/3/0N/YZ8ENDP16S9U7P5Z2DTV0T.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45c81d06a174d5930cc82b976794c9d0f6bc99d97af9620d22af8fa91ed0c48b -size 546041 +oid sha256:024ec672282699bc6d7658d128d054340a50fb2de5cf6aba429bdec3738da74b +size 507205 diff --git a/Content/__ExternalActors__/LpxLevel/3/32/BGCMNOM57RY2GJX7RDALOD.uasset b/Content/__ExternalActors__/LpxLevel/3/32/BGCMNOM57RY2GJX7RDALOD.uasset index 71610f30..d87289d1 100644 --- a/Content/__ExternalActors__/LpxLevel/3/32/BGCMNOM57RY2GJX7RDALOD.uasset +++ b/Content/__ExternalActors__/LpxLevel/3/32/BGCMNOM57RY2GJX7RDALOD.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3f626e76c9b13be2526513b5214f03e0dda9bc7f8ba23ad822b63d3f9ae6b07 -size 271227 +oid sha256:772b0c48602b8056da44364e1b4347c2cd730f6ac99a062cc880e20760dbf58a +size 251510 diff --git a/Content/__ExternalActors__/LpxLevel/3/GM/U35C5K9RQL4TOC145ZLQMN.uasset b/Content/__ExternalActors__/LpxLevel/3/GM/U35C5K9RQL4TOC145ZLQMN.uasset index 5782512c..5ff12b18 100644 --- a/Content/__ExternalActors__/LpxLevel/3/GM/U35C5K9RQL4TOC145ZLQMN.uasset +++ b/Content/__ExternalActors__/LpxLevel/3/GM/U35C5K9RQL4TOC145ZLQMN.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5290e6a9b014f9f5dae66779c162c48a2b6bfb845538144109fed721ae8d988d -size 527904 +oid sha256:cd8cbd76851ed6e6b97a5ab358b211aed58252de46c8661269f5d9e40a3d5009 +size 488909 diff --git a/Content/__ExternalActors__/LpxLevel/3/PO/YAC0CYBJLUVKHEJY1D2Q5L.uasset b/Content/__ExternalActors__/LpxLevel/3/PO/YAC0CYBJLUVKHEJY1D2Q5L.uasset index ad2dfbeb..1d54ff0d 100644 --- a/Content/__ExternalActors__/LpxLevel/3/PO/YAC0CYBJLUVKHEJY1D2Q5L.uasset +++ b/Content/__ExternalActors__/LpxLevel/3/PO/YAC0CYBJLUVKHEJY1D2Q5L.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cafdc738cfdb960b09884686df0aa8863ca5add393751aaa832dad9290808ce4 -size 3636 +oid sha256:3b894fedaf324c9f868ba700e16c486337dca7853f8d6c79891045e7dbd718cc +size 3524 diff --git a/Content/__ExternalActors__/LpxLevel/4/70/CZT1XDA48XTK9JWAPYETCS.uasset b/Content/__ExternalActors__/LpxLevel/4/70/CZT1XDA48XTK9JWAPYETCS.uasset index 16561be9..0c490461 100644 --- a/Content/__ExternalActors__/LpxLevel/4/70/CZT1XDA48XTK9JWAPYETCS.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/70/CZT1XDA48XTK9JWAPYETCS.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8021a138ae6f740d562817e50b1e67c34f3a95d4e9c616085cee0bd3f9b9ba3 -size 525726 +oid sha256:d8202cb15402c11138930e41e7cb65dba495f61ee797dd8308b45fbd780c87ab +size 487383 diff --git a/Content/__ExternalActors__/LpxLevel/4/7S/SGVWPRCU5C9ENKYRBZTDOP.uasset b/Content/__ExternalActors__/LpxLevel/4/7S/SGVWPRCU5C9ENKYRBZTDOP.uasset index e6575dab..693acff6 100644 --- a/Content/__ExternalActors__/LpxLevel/4/7S/SGVWPRCU5C9ENKYRBZTDOP.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/7S/SGVWPRCU5C9ENKYRBZTDOP.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db6337c40dfaa5d778487812bcfe6a959f06aa51a2b642bd09345573a429cf08 -size 516007 +oid sha256:06e4503b45b08cf15b7267e534f3618fdf9ab8827bb1cfeda6ec54fb779bc8ed +size 480278 diff --git a/Content/__ExternalActors__/LpxLevel/4/DN/V3OJDYMQXDDXIC0U3KCDBJ.uasset b/Content/__ExternalActors__/LpxLevel/4/DN/V3OJDYMQXDDXIC0U3KCDBJ.uasset index 9d3b85a9..d6858610 100644 --- a/Content/__ExternalActors__/LpxLevel/4/DN/V3OJDYMQXDDXIC0U3KCDBJ.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/DN/V3OJDYMQXDDXIC0U3KCDBJ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e174ed6b000f6b1dd2535583fc6b677f44508dd596921c6fc70ce33243c9348 -size 575175 +oid sha256:9de7a24c9349befc5b77a59abcd42b140051df619ad1e8f46ec7c20906cbfe6f +size 529268 diff --git a/Content/__ExternalActors__/LpxLevel/4/GP/MFFSXILHW8020GMNLATPZ5.uasset b/Content/__ExternalActors__/LpxLevel/4/GP/MFFSXILHW8020GMNLATPZ5.uasset index 4c7fa01b..9f437af4 100644 --- a/Content/__ExternalActors__/LpxLevel/4/GP/MFFSXILHW8020GMNLATPZ5.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/GP/MFFSXILHW8020GMNLATPZ5.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e26db11dd43c31c15a33c4c1eedd6091f0a35fc608499d830875904213595c0 -size 537825 +oid sha256:95acf6a6288ec63ae1bcf4857306691a7288edca0983daebdb559a21b8d4e013 +size 495091 diff --git a/Content/__ExternalActors__/LpxLevel/4/KS/REPMECANMEVOCZ4CKD7JP9.uasset b/Content/__ExternalActors__/LpxLevel/4/KS/REPMECANMEVOCZ4CKD7JP9.uasset index a9f86be1..7e5632fd 100644 --- a/Content/__ExternalActors__/LpxLevel/4/KS/REPMECANMEVOCZ4CKD7JP9.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/KS/REPMECANMEVOCZ4CKD7JP9.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b506b964069cc0bddcdd23ceaed52bc5174123a3e0ff4e474eeea5708a59ef0 -size 517245 +oid sha256:b23a6eea6e3b59d15cfcaf5a0508f8d68d26cadbed734ea150f086a26aeb6d80 +size 479218 diff --git a/Content/__ExternalActors__/LpxLevel/4/TU/D24BM58KTSRT4W0ZQPEVI3.uasset b/Content/__ExternalActors__/LpxLevel/4/TU/D24BM58KTSRT4W0ZQPEVI3.uasset index de239307..a36158f3 100644 --- a/Content/__ExternalActors__/LpxLevel/4/TU/D24BM58KTSRT4W0ZQPEVI3.uasset +++ b/Content/__ExternalActors__/LpxLevel/4/TU/D24BM58KTSRT4W0ZQPEVI3.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b7c9c07bc0374ac41d00f69fe4f61891f18e815621884cf981ed9d825b8a88b -size 545757 +oid sha256:6f9ac1fea354e14e5b967eade9b9d177ad0847551816c7488aed41336815ff23 +size 506813 diff --git a/Content/__ExternalActors__/LpxLevel/5/6L/8ESEBJ5AYNJ4RE4WUIYOE5.uasset b/Content/__ExternalActors__/LpxLevel/5/6L/8ESEBJ5AYNJ4RE4WUIYOE5.uasset index 0cdd6c17..f063a2af 100644 --- a/Content/__ExternalActors__/LpxLevel/5/6L/8ESEBJ5AYNJ4RE4WUIYOE5.uasset +++ b/Content/__ExternalActors__/LpxLevel/5/6L/8ESEBJ5AYNJ4RE4WUIYOE5.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afeedd6d5565115ccef5cd427fbe7de71cd58b5775818919319e82ca4f970340 -size 4860 +oid sha256:64e820c477503dfcf05135d036fb722783e3f745a3a6ac8d1a844265569fc6a2 +size 4869 diff --git a/Content/__ExternalActors__/LpxLevel/5/AR/EQWL8GV4N07EQV6LMHLVEQ.uasset b/Content/__ExternalActors__/LpxLevel/5/AR/EQWL8GV4N07EQV6LMHLVEQ.uasset index c7e4c5df..628449b8 100644 --- a/Content/__ExternalActors__/LpxLevel/5/AR/EQWL8GV4N07EQV6LMHLVEQ.uasset +++ b/Content/__ExternalActors__/LpxLevel/5/AR/EQWL8GV4N07EQV6LMHLVEQ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1dc55da38f6d40b7a125273748f461d582b26fcd21c3f17de47fdecc1766fc22 -size 302991 +oid sha256:f8578b899f0ae2cbc748c2cbb05e7992d7b29fbc585094cc0239871b1fe4c9e6 +size 279169 diff --git a/Content/__ExternalActors__/LpxLevel/5/E3/6W1QQ735Z2MC0YDNXGPPEN.uasset b/Content/__ExternalActors__/LpxLevel/5/E3/6W1QQ735Z2MC0YDNXGPPEN.uasset index 20b35c38..cd672d71 100644 --- a/Content/__ExternalActors__/LpxLevel/5/E3/6W1QQ735Z2MC0YDNXGPPEN.uasset +++ b/Content/__ExternalActors__/LpxLevel/5/E3/6W1QQ735Z2MC0YDNXGPPEN.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89423edbcd5d22d7a7b4e7938931221871c598d9a556799eae0e2848edb2e69c -size 551448 +oid sha256:7d5f174576ce3cfa5e7f6bce2b0a8c8b9eb8980c103cb3dc570e17078d00855e +size 504996 diff --git a/Content/__ExternalActors__/LpxLevel/5/ES/7MWGLAX0MNX238E8NWVX3T.uasset b/Content/__ExternalActors__/LpxLevel/5/ES/7MWGLAX0MNX238E8NWVX3T.uasset index e4b73f0a..ad51d935 100644 --- a/Content/__ExternalActors__/LpxLevel/5/ES/7MWGLAX0MNX238E8NWVX3T.uasset +++ b/Content/__ExternalActors__/LpxLevel/5/ES/7MWGLAX0MNX238E8NWVX3T.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:055315ac8b3fdbfede9b7620c2c3db54382ff664ab54851ee146f80570b1c112 -size 581170 +oid sha256:365746d8c7f926a012e6c36353757a7e68e75e19e2c0be1475a858c9c645c9a2 +size 530919 diff --git a/Content/__ExternalActors__/LpxLevel/5/G0/BOPGTRL6RL28BZS06KKECQ.uasset b/Content/__ExternalActors__/LpxLevel/5/G0/BOPGTRL6RL28BZS06KKECQ.uasset index 7b757327..1ff42eab 100644 --- a/Content/__ExternalActors__/LpxLevel/5/G0/BOPGTRL6RL28BZS06KKECQ.uasset +++ b/Content/__ExternalActors__/LpxLevel/5/G0/BOPGTRL6RL28BZS06KKECQ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc6895a1ede90429d3d1c11e840d706f02c50af2f646b8ce5aeacb8bdde72fd3 -size 521388 +oid sha256:f0a668148bdce77cab133ba90cf2ce49a60a219e3c5b530ddbe39b062d723ed7 +size 488281 diff --git a/Content/__ExternalActors__/LpxLevel/6/8R/WYP0TPIUHZG0ZEKEITDVNZ.uasset b/Content/__ExternalActors__/LpxLevel/6/8R/WYP0TPIUHZG0ZEKEITDVNZ.uasset index 0a26ae07..11a45851 100644 --- a/Content/__ExternalActors__/LpxLevel/6/8R/WYP0TPIUHZG0ZEKEITDVNZ.uasset +++ b/Content/__ExternalActors__/LpxLevel/6/8R/WYP0TPIUHZG0ZEKEITDVNZ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:445ee2d579fc92f23f9dcce331c987a03f1c163b22f67066b9388194d1b584ce -size 550320 +oid sha256:63a60abafba9475ffffe2adc8bcbb06995e006f28f9e73c1958cc64ed56b7a7d +size 510723 diff --git a/Content/__ExternalActors__/LpxLevel/6/BQ/OA50G8T8F5A3P422BSW3HU.uasset b/Content/__ExternalActors__/LpxLevel/6/BQ/OA50G8T8F5A3P422BSW3HU.uasset index b0335e56..b4d59c1c 100644 --- a/Content/__ExternalActors__/LpxLevel/6/BQ/OA50G8T8F5A3P422BSW3HU.uasset +++ b/Content/__ExternalActors__/LpxLevel/6/BQ/OA50G8T8F5A3P422BSW3HU.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8febd15d10ae235977b68a7e7da20c941141cf9943b83d8be174214eb23b9bec -size 545932 +oid sha256:5746e127ff39ed0584382baa56e87a58afe4cfa6abc4a6c6870a86e4d57361d4 +size 508616 diff --git a/Content/__ExternalActors__/LpxLevel/6/F1/M94BS3VXLPSHZT3R5FBB19.uasset b/Content/__ExternalActors__/LpxLevel/6/F1/M94BS3VXLPSHZT3R5FBB19.uasset index d04ade7c..e920bc73 100644 --- a/Content/__ExternalActors__/LpxLevel/6/F1/M94BS3VXLPSHZT3R5FBB19.uasset +++ b/Content/__ExternalActors__/LpxLevel/6/F1/M94BS3VXLPSHZT3R5FBB19.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:192a1b69b0f3a6b56ae77dc39ee436057734471d460a8327de8027f4e1f594ae -size 544589 +oid sha256:114940d458309f5e61f778ed0a8ba87b2ef5ab732b3d6a1dc98334c98e54d94d +size 501510 diff --git a/Content/__ExternalActors__/LpxLevel/6/UQ/52SWUY6HU9ZFO9DS515O41.uasset b/Content/__ExternalActors__/LpxLevel/6/UQ/52SWUY6HU9ZFO9DS515O41.uasset index 90c305a2..ef4e9039 100644 --- a/Content/__ExternalActors__/LpxLevel/6/UQ/52SWUY6HU9ZFO9DS515O41.uasset +++ b/Content/__ExternalActors__/LpxLevel/6/UQ/52SWUY6HU9ZFO9DS515O41.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e1c9f24954c6ac14f3d77d2f22a8604402587292ba3231e5a0dc2d54d751b36 -size 541887 +oid sha256:f85216d64b6c1825259888922d5a243217629e0bcdc80aada195882f9d4c47fa +size 505990 diff --git a/Content/__ExternalActors__/LpxLevel/7/0L/21SJVQFLZ6MT00BSO2I232.uasset b/Content/__ExternalActors__/LpxLevel/7/0L/21SJVQFLZ6MT00BSO2I232.uasset index 3710d078..9095b194 100644 --- a/Content/__ExternalActors__/LpxLevel/7/0L/21SJVQFLZ6MT00BSO2I232.uasset +++ b/Content/__ExternalActors__/LpxLevel/7/0L/21SJVQFLZ6MT00BSO2I232.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d4038f9e84f46a3215d7a0d52ee6e41eb5ac22572aa23efdd071080ff4bfec6 -size 514475 +oid sha256:d1195fb59dc2829eee57353f62a9eba4d5bb2a0282365834808323d6ff6fffb1 +size 478935 diff --git a/Content/__ExternalActors__/LpxLevel/7/FG/EEOQAWK4GRMZZ2GRLP3TO1.uasset b/Content/__ExternalActors__/LpxLevel/7/FG/EEOQAWK4GRMZZ2GRLP3TO1.uasset index 1bdb9e68..54d79ce6 100644 --- a/Content/__ExternalActors__/LpxLevel/7/FG/EEOQAWK4GRMZZ2GRLP3TO1.uasset +++ b/Content/__ExternalActors__/LpxLevel/7/FG/EEOQAWK4GRMZZ2GRLP3TO1.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f04557687998cd0cdb55862309586edf005498b4a528ed295b63996c08750d7 -size 540635 +oid sha256:8a418e306616f3cb3811ddd78687e00fe8c95b350a44cc5bc38522687ed7e8b3 +size 500164 diff --git a/Content/__ExternalActors__/LpxLevel/7/XT/TY4BAA54R2BEUM5ZCL57E0.uasset b/Content/__ExternalActors__/LpxLevel/7/XT/TY4BAA54R2BEUM5ZCL57E0.uasset index 71b6fa47..edbea01b 100644 --- a/Content/__ExternalActors__/LpxLevel/7/XT/TY4BAA54R2BEUM5ZCL57E0.uasset +++ b/Content/__ExternalActors__/LpxLevel/7/XT/TY4BAA54R2BEUM5ZCL57E0.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5893eb7bb60ddae591db1262b25f303d76d4504dbd338ad48f3fd1ec7bd85200 -size 396166 +oid sha256:a1509f14d7c339f6caabb0ff5827403b1c3d62d6b502ad20f496926ac4672ccc +size 362387 diff --git a/Content/__ExternalActors__/LpxLevel/8/K6/TWFLKL0PX81QX634FBUIYM.uasset b/Content/__ExternalActors__/LpxLevel/8/K6/TWFLKL0PX81QX634FBUIYM.uasset index 4af165d5..42197d1a 100644 --- a/Content/__ExternalActors__/LpxLevel/8/K6/TWFLKL0PX81QX634FBUIYM.uasset +++ b/Content/__ExternalActors__/LpxLevel/8/K6/TWFLKL0PX81QX634FBUIYM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:087d8d8e9a25ca03e9792b629cdd7045aa388476407894021a706726c7b98ece -size 526399 +oid sha256:ec1756878718cdbcf1ab70bfd55237bf5c35d2b0fd4ea1dfc9e5ec395f6d6c31 +size 493703 diff --git a/Content/__ExternalActors__/LpxLevel/8/XB/NADW47JMVFMWCF1Y1N1VZO.uasset b/Content/__ExternalActors__/LpxLevel/8/XB/NADW47JMVFMWCF1Y1N1VZO.uasset index 4d8d271c..2cc7508e 100644 --- a/Content/__ExternalActors__/LpxLevel/8/XB/NADW47JMVFMWCF1Y1N1VZO.uasset +++ b/Content/__ExternalActors__/LpxLevel/8/XB/NADW47JMVFMWCF1Y1N1VZO.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff6bc307e25b1ddee376f28b02a6d44b6e285321c5267e0e5f8b436633054983 -size 554021 +oid sha256:d47bed4a35bf995c9dccbf7f5ae9ef35217263b5dac51377ebdd32bce21a75e0 +size 499803 diff --git a/Content/__ExternalActors__/LpxLevel/9/7X/R2Q49DF24Q68HAV9MM6UZJ.uasset b/Content/__ExternalActors__/LpxLevel/9/7X/R2Q49DF24Q68HAV9MM6UZJ.uasset index d9184866..54241b96 100644 --- a/Content/__ExternalActors__/LpxLevel/9/7X/R2Q49DF24Q68HAV9MM6UZJ.uasset +++ b/Content/__ExternalActors__/LpxLevel/9/7X/R2Q49DF24Q68HAV9MM6UZJ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcf6287c424c42900399782dedcf06492fbc2c214b9bcc213bbce37810281a3e -size 568790 +oid sha256:0f241bb90746a92abf9e5b3a316fad78743aba78ca9fa38c5b560b5bdc9af66c +size 527881 diff --git a/Content/__ExternalActors__/LpxLevel/9/EO/BBUO3HXDXA2WV69YYFXJKR.uasset b/Content/__ExternalActors__/LpxLevel/9/EO/BBUO3HXDXA2WV69YYFXJKR.uasset index 090b96bd..37aa82cb 100644 --- a/Content/__ExternalActors__/LpxLevel/9/EO/BBUO3HXDXA2WV69YYFXJKR.uasset +++ b/Content/__ExternalActors__/LpxLevel/9/EO/BBUO3HXDXA2WV69YYFXJKR.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a954ab21de115486119b045746d642093aabb51f5c73de572f2bca25c29f44b0 -size 537545 +oid sha256:43a82e3aba6796e396ac57d07b56ef3115c0f8563cfafb3859da34bcd9c9271f +size 504554 diff --git a/Content/__ExternalActors__/LpxLevel/9/JY/MLMI853NKXWU7SWUI84K82.uasset b/Content/__ExternalActors__/LpxLevel/9/JY/MLMI853NKXWU7SWUI84K82.uasset index b7ae350b..85c42677 100644 --- a/Content/__ExternalActors__/LpxLevel/9/JY/MLMI853NKXWU7SWUI84K82.uasset +++ b/Content/__ExternalActors__/LpxLevel/9/JY/MLMI853NKXWU7SWUI84K82.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df20d31c707acda24519c6d04b669eb82f9fb269cfddf1b21da0d356611fd5d2 -size 3609 +oid sha256:5fff21ed1931158f0b6972f73e611e7789d72b7d645346696e8c104f903811eb +size 3610 diff --git a/Content/__ExternalActors__/LpxLevel/9/TE/RLQXH8BEV5EOJPXHB3SF66.uasset b/Content/__ExternalActors__/LpxLevel/9/TE/RLQXH8BEV5EOJPXHB3SF66.uasset index 919c7ef6..21014ed6 100644 --- a/Content/__ExternalActors__/LpxLevel/9/TE/RLQXH8BEV5EOJPXHB3SF66.uasset +++ b/Content/__ExternalActors__/LpxLevel/9/TE/RLQXH8BEV5EOJPXHB3SF66.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f1b4ce1a795a3e135312cc05121fd57ea8323fb3b6fd53bd698d402dcddc36a -size 429600 +oid sha256:f1ab67b07a054ace3010e8633aef04ad52b992c7bc9d94aa512fef479d313ca3 +size 382984 diff --git a/Content/__ExternalActors__/LpxLevel/A/20/QAC8G0FQHORTCB491O73B9.uasset b/Content/__ExternalActors__/LpxLevel/A/20/QAC8G0FQHORTCB491O73B9.uasset index fe158c96..01b6d721 100644 --- a/Content/__ExternalActors__/LpxLevel/A/20/QAC8G0FQHORTCB491O73B9.uasset +++ b/Content/__ExternalActors__/LpxLevel/A/20/QAC8G0FQHORTCB491O73B9.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c157910bc6cf92210f8221708ee82a57f75417e52bb8b562a9488ab7f0d7082c -size 271558 +oid sha256:2362ba2f31c0ad2f2e19c72a714e00665df789b93529c06089714eba3a5178cb +size 252851 diff --git a/Content/__ExternalActors__/LpxLevel/A/I6/C0JQARY7HIKL5WKH0BWHO0.uasset b/Content/__ExternalActors__/LpxLevel/A/I6/C0JQARY7HIKL5WKH0BWHO0.uasset index 36f257ba..2a53c2d3 100644 --- a/Content/__ExternalActors__/LpxLevel/A/I6/C0JQARY7HIKL5WKH0BWHO0.uasset +++ b/Content/__ExternalActors__/LpxLevel/A/I6/C0JQARY7HIKL5WKH0BWHO0.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f09982fbc894c6efa47a501389199f609099b3ee56867400e20ef9e771099db -size 536244 +oid sha256:eb3eb6fc4212d20b0512130c54b366af4478cf4e9ff4bba19e7e285974d2506e +size 498684 diff --git a/Content/__ExternalActors__/LpxLevel/A/WP/9LYGHRSIIW4G3GKFDZOTJ9.uasset b/Content/__ExternalActors__/LpxLevel/A/WP/9LYGHRSIIW4G3GKFDZOTJ9.uasset index e9d66086..4db213cd 100644 --- a/Content/__ExternalActors__/LpxLevel/A/WP/9LYGHRSIIW4G3GKFDZOTJ9.uasset +++ b/Content/__ExternalActors__/LpxLevel/A/WP/9LYGHRSIIW4G3GKFDZOTJ9.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:611d1ac28681cc6e3d851069cd42a9bc13253970f03fb7aaf0c388ed96dcaf1b -size 5257 +oid sha256:115ce0aea53767bb6301a8ae379ec1d6a89c86ad25b371804fc4c546536c62a5 +size 5149 diff --git a/Content/__ExternalActors__/LpxLevel/B/JD/23FYGTHS8SAKS8VN61M339.uasset b/Content/__ExternalActors__/LpxLevel/B/JD/23FYGTHS8SAKS8VN61M339.uasset index 43eeb29a..c4065904 100644 --- a/Content/__ExternalActors__/LpxLevel/B/JD/23FYGTHS8SAKS8VN61M339.uasset +++ b/Content/__ExternalActors__/LpxLevel/B/JD/23FYGTHS8SAKS8VN61M339.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d99fb482246dbf0bd00daeebdcb142523eb0c4c541e6ea311c99d7440b3c4e5f -size 537432 +oid sha256:11a9e392f9697934fa42a1083ff7e611b4026a154d0b2a4ba774c722cd971f20 +size 502506 diff --git a/Content/__ExternalActors__/LpxLevel/B/ST/KFFU6MP42RP327SVCPYKG7.uasset b/Content/__ExternalActors__/LpxLevel/B/ST/KFFU6MP42RP327SVCPYKG7.uasset index 68e8633f..ffbae296 100644 --- a/Content/__ExternalActors__/LpxLevel/B/ST/KFFU6MP42RP327SVCPYKG7.uasset +++ b/Content/__ExternalActors__/LpxLevel/B/ST/KFFU6MP42RP327SVCPYKG7.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b872ddcb08aa83f7aed2fca1958710c450c036af548bc129a1327f493514913 -size 539776 +oid sha256:73eab3242cefb03809c5f5da7a62b9bc820e4d70ec56427186555e7f75b5f3b6 +size 502811 diff --git a/Content/__ExternalActors__/LpxLevel/B/YG/BLDCSYZTVQCMKQYEQEXI33.uasset b/Content/__ExternalActors__/LpxLevel/B/YG/BLDCSYZTVQCMKQYEQEXI33.uasset index 05c8f449..c9cf3598 100644 --- a/Content/__ExternalActors__/LpxLevel/B/YG/BLDCSYZTVQCMKQYEQEXI33.uasset +++ b/Content/__ExternalActors__/LpxLevel/B/YG/BLDCSYZTVQCMKQYEQEXI33.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79cb3fa08ecdd54f647886ef5ac798846903c5e1cbc766345afdc4605faedfa0 -size 516411 +oid sha256:f53d8f60da7e65cff3e77e64457a7b4aa0d9c20d2e4b89d81a83e95f255043fc +size 484146 diff --git a/Content/__ExternalActors__/LpxLevel/C/7K/IBNSIA4DIK58Z5C5P3ANMT.uasset b/Content/__ExternalActors__/LpxLevel/C/7K/IBNSIA4DIK58Z5C5P3ANMT.uasset index c9154277..5cb78cec 100644 --- a/Content/__ExternalActors__/LpxLevel/C/7K/IBNSIA4DIK58Z5C5P3ANMT.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/7K/IBNSIA4DIK58Z5C5P3ANMT.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fce960afce82f6dccde28e5a9b142aa685e435cd0ed92f36203c79b5ba3834fe -size 554645 +oid sha256:95498244568c72da1969bc6c0ecf4346a83874091c646ce970b9350c90b6cf2d +size 508223 diff --git a/Content/__ExternalActors__/LpxLevel/C/I0/PD8PFYUQW6I310NQDZKDID.uasset b/Content/__ExternalActors__/LpxLevel/C/I0/PD8PFYUQW6I310NQDZKDID.uasset index b6098ee6..7eca104d 100644 --- a/Content/__ExternalActors__/LpxLevel/C/I0/PD8PFYUQW6I310NQDZKDID.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/I0/PD8PFYUQW6I310NQDZKDID.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3877ca55b08a295b743b25569e261a888e6013a232ac457f611c14c3cae140b4 -size 509643 +oid sha256:bdf3f5dbfe1f46476a08ecdc0573ab228432788afe54f9c1cc15222a2a5f56ca +size 474545 diff --git a/Content/__ExternalActors__/LpxLevel/C/M4/RO8VUGJYROLY2WFCQSVTCL.uasset b/Content/__ExternalActors__/LpxLevel/C/M4/RO8VUGJYROLY2WFCQSVTCL.uasset index bab672c0..4a9ca745 100644 --- a/Content/__ExternalActors__/LpxLevel/C/M4/RO8VUGJYROLY2WFCQSVTCL.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/M4/RO8VUGJYROLY2WFCQSVTCL.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bb46c6eb0ae20e49766392ec5e073176f4178ead75fd37eaa8d3dd33c821446 -size 255988 +oid sha256:3e5aa99ce3f9f23cd0349ccdb35cb5f8aa0fc748022734b2b68e56866cf8eab4 +size 241967 diff --git a/Content/__ExternalActors__/LpxLevel/C/UL/GTYCXLUXC9XK4I40BWY38T.uasset b/Content/__ExternalActors__/LpxLevel/C/UL/GTYCXLUXC9XK4I40BWY38T.uasset index d699d572..0ca3c4a7 100644 --- a/Content/__ExternalActors__/LpxLevel/C/UL/GTYCXLUXC9XK4I40BWY38T.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/UL/GTYCXLUXC9XK4I40BWY38T.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2e61e65b24efc2a26a0afd475f638c93c201e9e059ffdbbc17edcab245f7598 -size 544153 +oid sha256:86c8e1a8bf788d5aaf213792ae206a62f5cf8acafd9e4327dcc0f678c2f6e162 +size 503696 diff --git a/Content/__ExternalActors__/LpxLevel/C/VN/SYHGKTZPJBVNDZKD6UHWT7.uasset b/Content/__ExternalActors__/LpxLevel/C/VN/SYHGKTZPJBVNDZKD6UHWT7.uasset index e2d9bc8c..f56fbb72 100644 --- a/Content/__ExternalActors__/LpxLevel/C/VN/SYHGKTZPJBVNDZKD6UHWT7.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/VN/SYHGKTZPJBVNDZKD6UHWT7.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:367034ce219af18b958db8acb773950f4a5487ec1a5623ac508512c4b99bf00d -size 542125 +oid sha256:ee2a8dba5caaf18f4d1712c2089b9f188118ba4223fd917d9b06d14bb36beaf5 +size 492675 diff --git a/Content/__ExternalActors__/LpxLevel/C/Y3/XBNUIA9KEWG45TH4VM9WVJ.uasset b/Content/__ExternalActors__/LpxLevel/C/Y3/XBNUIA9KEWG45TH4VM9WVJ.uasset index 4cb06d3b..53b1c6ef 100644 --- a/Content/__ExternalActors__/LpxLevel/C/Y3/XBNUIA9KEWG45TH4VM9WVJ.uasset +++ b/Content/__ExternalActors__/LpxLevel/C/Y3/XBNUIA9KEWG45TH4VM9WVJ.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c41c1d0c2ee0ba378af632cef291ebb853aea0c0d06b61e925598443408c4ddc -size 536442 +oid sha256:845ce923f9f3937de4989b73f6b2b09dc758aff19c0017bcc52f0f50e89a8883 +size 489542 diff --git a/Content/__ExternalActors__/LpxLevel/D/3Y/RDVHA06OO92WCW0SJUEE2W.uasset b/Content/__ExternalActors__/LpxLevel/D/3Y/RDVHA06OO92WCW0SJUEE2W.uasset index e66bcf37..e02b8b2a 100644 --- a/Content/__ExternalActors__/LpxLevel/D/3Y/RDVHA06OO92WCW0SJUEE2W.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/3Y/RDVHA06OO92WCW0SJUEE2W.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2ea8f43667ff7a29d93f910c01f9601b092438038f611bcfc1324ac44ac66f0 -size 542322 +oid sha256:926a0551f55f1f36ee89b0aeb10a7619b67cce3d1e839064f158018c7e9f7278 +size 506263 diff --git a/Content/__ExternalActors__/LpxLevel/D/IT/NJMO6BLSNKI3MOUN28EG9I.uasset b/Content/__ExternalActors__/LpxLevel/D/IT/NJMO6BLSNKI3MOUN28EG9I.uasset index c9456c3e..4c2dc424 100644 --- a/Content/__ExternalActors__/LpxLevel/D/IT/NJMO6BLSNKI3MOUN28EG9I.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/IT/NJMO6BLSNKI3MOUN28EG9I.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a620978635958091a42f6fc0e68b0b752df59e9bf8e88f244e772a0b11a38aaa -size 805532 +oid sha256:446e5c1b121fe17d75ee913e9516bd13b6ab42b17794974af45eb75056f44ddb +size 805384 diff --git a/Content/__ExternalActors__/LpxLevel/D/LW/P9Z0MOIOZSSRZXN7OZ7GGR.uasset b/Content/__ExternalActors__/LpxLevel/D/LW/P9Z0MOIOZSSRZXN7OZ7GGR.uasset index 8b3c7df4..1d044cc0 100644 --- a/Content/__ExternalActors__/LpxLevel/D/LW/P9Z0MOIOZSSRZXN7OZ7GGR.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/LW/P9Z0MOIOZSSRZXN7OZ7GGR.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:389e6a8aab4d5fedc63d59c166d5b894643afff92512196620c1c6bbf73a9a0e -size 441008 +oid sha256:ca1c69ccbab4f681848966f31012e1e6d13a324a77649e6ebdbd2721c8b334c1 +size 394036 diff --git a/Content/__ExternalActors__/LpxLevel/D/MM/8M1YGMGC1BS1KPUZSOAL1K.uasset b/Content/__ExternalActors__/LpxLevel/D/MM/8M1YGMGC1BS1KPUZSOAL1K.uasset index 780b4aad..57fb9f48 100644 --- a/Content/__ExternalActors__/LpxLevel/D/MM/8M1YGMGC1BS1KPUZSOAL1K.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/MM/8M1YGMGC1BS1KPUZSOAL1K.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a220613df68db170d94b979e6d913ab3b4bcb2a161785506d7d12c9cd8603c6 -size 409120 +oid sha256:f9cd134f045ac1ff1dd4c620c006a31bcfeb7f50d2a546bbf4113751c025713e +size 369138 diff --git a/Content/__ExternalActors__/LpxLevel/D/NG/60ZFTY70NQMHXIOSNGJ43R.uasset b/Content/__ExternalActors__/LpxLevel/D/NG/60ZFTY70NQMHXIOSNGJ43R.uasset index 0d270c4c..c5cab186 100644 --- a/Content/__ExternalActors__/LpxLevel/D/NG/60ZFTY70NQMHXIOSNGJ43R.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/NG/60ZFTY70NQMHXIOSNGJ43R.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c28a7c8d509d7b9426fe21235c9e938fa665134a95946795cd27e7aafac8f21 -size 548259 +oid sha256:cae976072a07879f91e53c149b28c189874ac3b40beed88594b3c077357defa4 +size 505475 diff --git a/Content/__ExternalActors__/LpxLevel/D/WM/WBUXHD6OZ2LWV61FSG4SB9.uasset b/Content/__ExternalActors__/LpxLevel/D/WM/WBUXHD6OZ2LWV61FSG4SB9.uasset index 7acea7b2..f19433b6 100644 --- a/Content/__ExternalActors__/LpxLevel/D/WM/WBUXHD6OZ2LWV61FSG4SB9.uasset +++ b/Content/__ExternalActors__/LpxLevel/D/WM/WBUXHD6OZ2LWV61FSG4SB9.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a0ba850be120f574ee568e7956c83c95569c06640208434f8c560bc25b196b2 -size 3635 +oid sha256:83432f04d75829191916dc6cbbdb70464b07f4bc4db499f0aa1f8d0e898018c3 +size 3527 diff --git a/Content/__ExternalActors__/LpxLevel/E/09/FS4YJ3PRO90CDZNMPRJ5F7.uasset b/Content/__ExternalActors__/LpxLevel/E/09/FS4YJ3PRO90CDZNMPRJ5F7.uasset index 71a4e8ab..12923d16 100644 --- a/Content/__ExternalActors__/LpxLevel/E/09/FS4YJ3PRO90CDZNMPRJ5F7.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/09/FS4YJ3PRO90CDZNMPRJ5F7.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f9e631423e5afd26bc07ecedaa45fdf51a5a6f28f40819fdb165b633a52450f -size 539411 +oid sha256:aea3f063874e6674ce25fd92b62b52a31fd5c741484434532a1c15e2b4adc02f +size 504551 diff --git a/Content/__ExternalActors__/LpxLevel/E/6Z/I698LRKUTN63SF0Y75EZ1E.uasset b/Content/__ExternalActors__/LpxLevel/E/6Z/I698LRKUTN63SF0Y75EZ1E.uasset index cc66e32b..3b0f84f2 100644 --- a/Content/__ExternalActors__/LpxLevel/E/6Z/I698LRKUTN63SF0Y75EZ1E.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/6Z/I698LRKUTN63SF0Y75EZ1E.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35eeeef53ed95e6128f77c563bb2c8be4cba12ed7cce3a0c9e7c6b597133b921 -size 533606 +oid sha256:d8b873f75ed6d0c78ae0769bd2d9599d9881187df60b6981ccfddf9fd02088de +size 493836 diff --git a/Content/__ExternalActors__/LpxLevel/E/9Q/NGAUKYIQ0ILXBND0RRPBAT.uasset b/Content/__ExternalActors__/LpxLevel/E/9Q/NGAUKYIQ0ILXBND0RRPBAT.uasset new file mode 100644 index 00000000..e46fc00b --- /dev/null +++ b/Content/__ExternalActors__/LpxLevel/E/9Q/NGAUKYIQ0ILXBND0RRPBAT.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:283117b0c9c83b8a51f13c706998ba9cf668788aa4cb46737e2f36d78f938467 +size 3925 diff --git a/Content/__ExternalActors__/LpxLevel/E/E5/NFSR26GWQ9QFRWF0438IIC.uasset b/Content/__ExternalActors__/LpxLevel/E/E5/NFSR26GWQ9QFRWF0438IIC.uasset index b7624150..11c99bf4 100644 --- a/Content/__ExternalActors__/LpxLevel/E/E5/NFSR26GWQ9QFRWF0438IIC.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/E5/NFSR26GWQ9QFRWF0438IIC.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c361b62e5bd3794b74f222bcab29c639e72f820f9d9621ef738be936f34d023 -size 546004 +oid sha256:26a2ba70aa7f4a135135d105151bea3479315d476741cdde2984572959a72385 +size 504534 diff --git a/Content/__ExternalActors__/LpxLevel/E/M0/F1QGQL3ZSV2XA8HZN485TI.uasset b/Content/__ExternalActors__/LpxLevel/E/M0/F1QGQL3ZSV2XA8HZN485TI.uasset index 8f6a4f30..3859c3d7 100644 --- a/Content/__ExternalActors__/LpxLevel/E/M0/F1QGQL3ZSV2XA8HZN485TI.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/M0/F1QGQL3ZSV2XA8HZN485TI.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f3533c9a44081fb0d1991345fab5be42779aafb96886bb30af46997375ffdac -size 540912 +oid sha256:391a688ed009e035d66bb003e92e5b3a39a57e0e4c317cbd95400515ad7c7f03 +size 502239 diff --git a/Content/__ExternalActors__/LpxLevel/E/M9/S19PMTMAUVUTTZO7GWFKVW.uasset b/Content/__ExternalActors__/LpxLevel/E/M9/S19PMTMAUVUTTZO7GWFKVW.uasset index 401d9807..19d0e402 100644 --- a/Content/__ExternalActors__/LpxLevel/E/M9/S19PMTMAUVUTTZO7GWFKVW.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/M9/S19PMTMAUVUTTZO7GWFKVW.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0862aac112ee0a5a55ea25e43196e4359d2a95657e6a5bd5be8c1df3d22d9c2f -size 414447 +oid sha256:62cba68daf2810dbd049de917a611e30aff47041525ad72d74e12024458c3ad4 +size 366911 diff --git a/Content/__ExternalActors__/LpxLevel/E/VM/ELXLGPXPVCSRNH24O0NX61.uasset b/Content/__ExternalActors__/LpxLevel/E/VM/ELXLGPXPVCSRNH24O0NX61.uasset index 467730d4..bf375f59 100644 --- a/Content/__ExternalActors__/LpxLevel/E/VM/ELXLGPXPVCSRNH24O0NX61.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/VM/ELXLGPXPVCSRNH24O0NX61.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cc0c1eca67df958f64245c740986c3fdbad0b16917384f03849146c71f21c65 -size 541556 +oid sha256:eb3e86e70ea0fcafae254a554b89542680639409db53840d57b9cba5048903c7 +size 501470 diff --git a/Content/__ExternalActors__/LpxLevel/E/Y1/31ZXJI54PQ1COAYOTNL8CX.uasset b/Content/__ExternalActors__/LpxLevel/E/Y1/31ZXJI54PQ1COAYOTNL8CX.uasset index 61655f3d..9129f063 100644 --- a/Content/__ExternalActors__/LpxLevel/E/Y1/31ZXJI54PQ1COAYOTNL8CX.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/Y1/31ZXJI54PQ1COAYOTNL8CX.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8794469d5b96d121caf7018654034884949f5711d1fee2552cb9a626f9eb824 -size 413715 +oid sha256:de3db7368ae99c606706ab79126d451b12d0a0eb02d382b683e4ec56ad7a54b0 +size 370628 diff --git a/Content/__ExternalActors__/LpxLevel/E/YG/JXTR2CRRJEH8KEEQXBYP9W.uasset b/Content/__ExternalActors__/LpxLevel/E/YG/JXTR2CRRJEH8KEEQXBYP9W.uasset index 47461ed8..a4eea051 100644 --- a/Content/__ExternalActors__/LpxLevel/E/YG/JXTR2CRRJEH8KEEQXBYP9W.uasset +++ b/Content/__ExternalActors__/LpxLevel/E/YG/JXTR2CRRJEH8KEEQXBYP9W.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:888a7b8819afc2865e91c4c52db7fb1398d06c7db67add5f7b4e3540ba32f6e4 -size 517054 +oid sha256:46fcb5aebc274f36e07b9e8e3cdb7c27ef8b7614154baefb279ab66c12ace860 +size 482659 diff --git a/Content/__ExternalActors__/LpxLevel/F/2Z/FBLI63GQ38CR698NOF9S2G.uasset b/Content/__ExternalActors__/LpxLevel/F/2Z/FBLI63GQ38CR698NOF9S2G.uasset index 1a1213e5..2a1fe46f 100644 --- a/Content/__ExternalActors__/LpxLevel/F/2Z/FBLI63GQ38CR698NOF9S2G.uasset +++ b/Content/__ExternalActors__/LpxLevel/F/2Z/FBLI63GQ38CR698NOF9S2G.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bb3f6d464cc7f1aedcaf921cabfc72caec9d903c6955a39a5529651f93adcb5 -size 551780 +oid sha256:896fae8c7ff21514ae3fa727d648be0169f9058d6bb1ef7e418b5c1315273e34 +size 507688 diff --git a/Content/__ExternalActors__/LpxLevel/F/3F/NQNV246FGH57UDI6AOLD9K.uasset b/Content/__ExternalActors__/LpxLevel/F/3F/NQNV246FGH57UDI6AOLD9K.uasset index bbaab9e6..29503097 100644 --- a/Content/__ExternalActors__/LpxLevel/F/3F/NQNV246FGH57UDI6AOLD9K.uasset +++ b/Content/__ExternalActors__/LpxLevel/F/3F/NQNV246FGH57UDI6AOLD9K.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3613d6e47bf84ccaf28727cc4a0455e7d805e77ba09e501d313f72f5738efc57 -size 531824 +oid sha256:06e1065e922fad6ab1cddd705e676a0f7b0890ad6360e80116c6393437420559 +size 496375 diff --git a/Content/__ExternalObjects__/LpxLevel/0/T9/CHGBHNEM6RWV6FH5EYMZ0F.uasset b/Content/__ExternalObjects__/LpxLevel/0/T9/CHGBHNEM6RWV6FH5EYMZ0F.uasset index 3c42c9a5..88c48cae 100644 --- a/Content/__ExternalObjects__/LpxLevel/0/T9/CHGBHNEM6RWV6FH5EYMZ0F.uasset +++ b/Content/__ExternalObjects__/LpxLevel/0/T9/CHGBHNEM6RWV6FH5EYMZ0F.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9c32fad6e49e460f0c452f540cad323fcdea492f1a92b9e1620a067febbd43b -size 2133 +oid sha256:70842688311b4b19fbbc5f1ef4748bcb0f2b7e0f793fe4e405a83491c55a535f +size 2089 diff --git a/Content/__ExternalObjects__/LpxLevel/3/J5/HLI5DH1KOVASPDJSTZ326D.uasset b/Content/__ExternalObjects__/LpxLevel/3/J5/HLI5DH1KOVASPDJSTZ326D.uasset index 828b6288..2c0794b2 100644 --- a/Content/__ExternalObjects__/LpxLevel/3/J5/HLI5DH1KOVASPDJSTZ326D.uasset +++ b/Content/__ExternalObjects__/LpxLevel/3/J5/HLI5DH1KOVASPDJSTZ326D.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b117c6a7cd244487990bb8bf1a161118cbed036e4496d1ae7567b692394100fd -size 2297 +oid sha256:3ab704f68489d70ff5c516f1e418d0032541aa50d2622e3de8d25b01fc3cd95f +size 2253 diff --git a/Content/__ExternalObjects__/LpxLevel/5/1G/WNB7FEXDBFPEALQN195YO4.uasset b/Content/__ExternalObjects__/LpxLevel/5/1G/WNB7FEXDBFPEALQN195YO4.uasset index 37022333..e90c1a2f 100644 --- a/Content/__ExternalObjects__/LpxLevel/5/1G/WNB7FEXDBFPEALQN195YO4.uasset +++ b/Content/__ExternalObjects__/LpxLevel/5/1G/WNB7FEXDBFPEALQN195YO4.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16de2135363013e89738b63646e19fd064a01010a1306bc63e9593f5b75538d3 -size 2191 +oid sha256:25b12e91a92c0c92901c6cec9ade920fa646fa4f449f930f28fdae241dab45da +size 2147 diff --git a/Content/__ExternalObjects__/LpxLevel/D/92/H90XJ0APCI2RIXH60MBT08.uasset b/Content/__ExternalObjects__/LpxLevel/D/92/H90XJ0APCI2RIXH60MBT08.uasset index 635a6055..c3d64070 100644 --- a/Content/__ExternalObjects__/LpxLevel/D/92/H90XJ0APCI2RIXH60MBT08.uasset +++ b/Content/__ExternalObjects__/LpxLevel/D/92/H90XJ0APCI2RIXH60MBT08.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de77ab88797999e8c81d5a8bf0e73b35b24ee4bf535e14a4c73827fd6e932c5b -size 2283 +oid sha256:b47df643f313bf49540f72759d10fe0f5b5bad59e6066473d19cd74c56240db0 +size 2239 diff --git a/Content/__ExternalObjects__/LpxLevel/F/08/BR4JW99WQMZKPD1XI23MX2.uasset b/Content/__ExternalObjects__/LpxLevel/F/08/BR4JW99WQMZKPD1XI23MX2.uasset index 23eed88d..d16a1ccf 100644 --- a/Content/__ExternalObjects__/LpxLevel/F/08/BR4JW99WQMZKPD1XI23MX2.uasset +++ b/Content/__ExternalObjects__/LpxLevel/F/08/BR4JW99WQMZKPD1XI23MX2.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc0bc63de3c56979f485c6194825cba0e0a9877fad6e361c250a2a12eb31c964 -size 2205 +oid sha256:9581297dfc994460b56193fc9ceb8d9810118ad0db391c4bfe8971d520c59463 +size 2161 diff --git a/EnginePatches/EnginePatch b/EnginePatches/EnginePatch index 04625e97..8666ec81 100644 --- a/EnginePatches/EnginePatch +++ b/EnginePatches/EnginePatch @@ -1,3 +1,28 @@ +diff --git a/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py b/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py +index f56f5ea9cac4..ff1c4030b38f 100644 +--- a/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py ++++ b/Engine/Extras/LLDBDataFormatters/UEDataFormatters_2ByteChars.py +@@ -32,7 +32,7 @@ def UETCharSummaryProvider(valobj,dict): + if DataVal == 0: + Val = 'NULL' + else: +- Expr = '(char16_t*)(%s)' % Data ++ Expr = '(char16_t*)(%s)' % DataVal + ValRef = valobj.CreateValueFromExpression('string', Expr) + Val = ValRef.GetSummary() + elif Type.IsReferenceType(): +@@ -47,6 +47,11 @@ def UETCharSummaryProvider(valobj,dict): + Expr = '(char16_t*)(%s)' % valobj.GetAddress() + ValRef = valobj.CreateValueFromExpression('string', Expr) + Val = ValRef.GetSummary() ++ else: ++ DataVal = valobj.GetValueAsUnsigned(0) ++ Expr = '(char16_t)(%s)' % DataVal ++ ValRef = valobj.CreateValueFromExpression('string', Expr) ++ Val = ValRef.GetSummary() + return Val + + def UESignedCharSummaryProvider(valobj,dict): diff --git a/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp b/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp index ca5f4b5fb5ff..a436a624d5b7 100644 --- a/Engine/Source/Runtime/ApplicationCore/Private/Linux/LinuxPlatformApplicationMisc.cpp diff --git a/Source/Integration/AnimQueue.cpp b/Source/Integration/AnimQueue.cpp index 1309b659..7cc130eb 100644 --- a/Source/Integration/AnimQueue.cpp +++ b/Source/Integration/AnimQueue.cpp @@ -81,8 +81,9 @@ void UlxAnimationStepLibrary::UnpackAnimationStep(bool &bChanged, FString &Actio bChanged = false; Action = TEXT(""); - if (prefix.IsEmpty()) { - UlxUtilityLibrary::Assert(false, TEXT("You may not pass an empty string for prefix")); + if (prefix.IsEmpty()) + { + UE_LOG(LogBlueprint, Error, TEXT("UnpackAnimationStep: You may not pass an empty string for prefix")); return; } @@ -92,8 +93,7 @@ void UlxAnimationStepLibrary::UnpackAnimationStep(bool &bChanged, FString &Actio FStructProperty* stepproperty = FindAnimationStepProperty(uclass, prefix); if (stepproperty == nullptr) { - UE_LOG(LogBlueprint, Error, TEXT("Target object: %s Prefix: %s"), *(target->GetName()), *prefix); - UlxUtilityLibrary::Assert(false, TEXT("Target object does not have an variable named ' Animation Step'")); + UE_LOG(LogBlueprint, Error, TEXT("UnpackAnimationStep: Target object does not have a variable named: '%s Animation Step'"), *prefix); return; } diff --git a/Source/Integration/AnimQueue.h b/Source/Integration/AnimQueue.h index 7acafc42..35dc4f2d 100644 --- a/Source/Integration/AnimQueue.h +++ b/Source/Integration/AnimQueue.h @@ -16,7 +16,7 @@ // //////////////////////////////////////////////// -USTRUCT(Blueprintable) +USTRUCT(BlueprintType) struct INTEGRATION_API FlxAnimationStep { GENERATED_BODY() diff --git a/Source/Integration/BlueprintErrors.cpp b/Source/Integration/BlueprintErrors.cpp new file mode 100644 index 00000000..6271ec76 --- /dev/null +++ b/Source/Integration/BlueprintErrors.cpp @@ -0,0 +1,137 @@ + +#include "BlueprintErrors.h" +#include "Internationalization/TextFormatter.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Kismet2/KismetDebugUtilities.h" + +#include "Kismet/KismetTextLibrary.h" + +ELogVerbosity::Type UlxBlueprintErrorLibrary::ConvertElxLogVerbosity(ElxLogVerbosity Verbosity) { + switch (Verbosity) { + case ElxLogVerbosity::Error: return ELogVerbosity::Error; + case ElxLogVerbosity::Warning: return ELogVerbosity::Warning; + case ElxLogVerbosity::Display: return ELogVerbosity::Display; + case ElxLogVerbosity::Log: return ELogVerbosity::Log; + case ElxLogVerbosity::Verbose: return ELogVerbosity::Verbose; + case ElxLogVerbosity::VeryVerbose: return ELogVerbosity::VeryVerbose; + case ElxLogVerbosity::Fatal: return ELogVerbosity::Fatal; + } +} + +void UlxBlueprintErrorLibrary::FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxErrorDisplayDuration DisplayDuration, const FString &InPattern, TArray InArgs) +{ + // Generate the formatted string. + // + FText InPatternText(FText::FromString(InPattern)); + FText Message = FTextFormatter::Format(MoveTemp(InPatternText), MoveTemp(InArgs), false, false); + FString MessageString = Message.ToString(); + + // Convert the DisplayDuration enum into a number of seconds. + // + int Seconds = int(DisplayDuration); + if (Seconds > 100) Seconds = (Seconds - 100) * 60; + + // Choose a color appropriate to the verbosity level. + // + FLinearColor Color; + switch (Verbosity) { + case ElxLogVerbosity::Fatal : Color = FLinearColor(1.0, 0.6, 0.6); break; + case ElxLogVerbosity::Error : Color = FLinearColor(1.0, 0.6, 0.6); break; + case ElxLogVerbosity::Warning : Color = FLinearColor(0.9, 0.9, 0.6); break; + default: Color = FLinearColor(0.8, 0.8, 0.8); break; + } + + // Get the blueprint name. + // + // Normally, the log function expects you to pass in a filename, and a log + // category name. We use the blueprint name for both. + // + // Using the blueprint name as a log category name is not technically + // correct. However, there is no correct way to create log categories + // from inside of blueprints. Doing it this way at least produces a reasonable + // message inside the log. What doesn't work correctly is the log message + // suppression system. Ie, console commands like 'log verbose' + // don't have any effect here. The design of the log message suppression + // system is such that there just is no reasonable way to hook into it from + // inside of blueprints. + // + FString BlueprintNameString = Context->GetClass()->GetName(); + auto BlueprintNameAnsi = StringCast(*BlueprintNameString); + FLogCategoryName BlueprintNameLogCategory(Context->GetClass()->GetFName()); + + // Output to Screen, if requested. + // + if (Seconds != 0) + { + UKismetSystemLibrary::PrintText(NULL, Message, true, false, Color, Seconds, NAME_None); + } + + // Output to Log + // + ELogVerbosity::Type VerbosityValue = ConvertElxLogVerbosity(Verbosity); + if (VerbosityValue <= ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY) + { + FMsg::Logf(BlueprintNameAnsi.Get(), 0, BlueprintNameLogCategory, VerbosityValue, TEXT("%s"), *MessageString); + } +} + + +FlxDebugBlueprintErrorsOutputDevice::FlxDebugBlueprintErrorsOutputDevice(const ElxLogVerbosity &SensitivityRef) + : Sensitivity(SensitivityRef) +{ + GLog->AddOutputDevice(this); +} + +FlxDebugBlueprintErrorsOutputDevice::~FlxDebugBlueprintErrorsOutputDevice() +{ + GLog->RemoveOutputDevice(this); +} + +namespace UBreakPoint { + static volatile int V; + FORCENOINLINE static void OnLogFatal() { + V = 0; + } + FORCENOINLINE static void OnLogError() { + V = 1; + OnLogFatal(); + } + FORCENOINLINE static void OnLogWarning() { + V = 2; + OnLogError(); + } +} + +static const FName LogBlueprintDebugName(TEXT("LogBlueprintDebug")); + + +void FlxDebugBlueprintErrorsOutputDevice::Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) +{ + // If the error isn't serious enough, do nothing. + // + if (Verbosity > UlxBlueprintErrorLibrary::ConvertElxLogVerbosity(Sensitivity)) + { + return; + } + + // If the Category is LogBlueprintDebug, then we're inside the debugger already. + // + if (Category == LogBlueprintDebugName) + { + return; + } + + // Find out if we're running in a blueprint thread. If not, return. + // + FFrame* Frame = FFrame::GetThreadLocalTopStackFrame(); + if (Frame == nullptr) return; + UObject *TopObject = Frame->Object; + if (TopObject == nullptr) return; + + // Notify the debugger that there's been an exception. + // + FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::Breakpoint, FText::FromStringView(FStringView(V))); + FBlueprintCoreDelegates::ThrowScriptException(TopObject, *Frame, ExceptionInfo); +} + + diff --git a/Source/Integration/BlueprintErrors.h b/Source/Integration/BlueprintErrors.h new file mode 100644 index 00000000..5bab638d --- /dev/null +++ b/Source/Integration/BlueprintErrors.h @@ -0,0 +1,181 @@ +// +// BlueprintErrors: Better error handling for blueprint errors. +// + +#pragma once + +#include "Containers/Array.h" +#include "CoreMinimal.h" +#include "HAL/Platform.h" +#include "Misc/OutputDeviceError.h" +#include "UObject/NameTypes.h" +#include "UObject/ObjectMacros.h" +#include "UObject/UObjectGlobals.h" + +#include "BlueprintErrors.generated.h" + +/* + * enum class ElxLogVerbosity, below, contains all the same error severity levels + * as ELogVerbosity, but in a form that the blueprint editor can manipulate. + * + * We deliberately moved 'Fatal' to the end of the list, and made 'Error' option 0. + * We did that because we want the editor to default to 'Error' in most cases. + * Unfortunately, that means the numeric values of the two enums don't match up, + * so we will need a conversion function. + * + */ + + +/** Log Verbosity: The importance of an error message, which affects which logs the error + * message gets written to, and how that message gets filtered. + * + */ +UENUM(BlueprintType) +enum class ElxLogVerbosity : uint8 { + + /* Prints an error to the console and log file. The editor collects and reports errors. */ + Error, + + /* Prints a warning to the console and log file. The editor collects and report warnings. */ + Warning, + + /* Prints a message to the console and log file. */ + Display, + + /* Prints a message to the log file, however, it does not print to the console. */ + Log, + + /* Prints a message to a log file only if Verbose logging is enabled for the given category. This is usually used for detailed logging. */ + Verbose, + + /* Prints a message to a log file. If VeryVerbose logging is enabled, then this is used for detailed logging that would otherwise spam output. */ + VeryVerbose, + + /* Danger! Prints a fatal error to the console and log file, then crashes (this crashes the editor too). */ + Fatal, +}; + + +/** Display Duration: How long to display an error message in the game's viewport. + * + */ +UENUM(BlueprintType) +enum class ElxErrorDisplayDuration : uint8 { + + /* Do not display the message in the viewport */ + No_Show = 0, + + /* Display the message in the viewport for 1 seconds */ + Show_1_Seconds = 1, + + /* Display the message in the viewport for 2 seconds */ + Show_2_Seconds = 2, + + /* Display the message in the viewport for 3 seconds */ + Show_3_Seconds = 3, + + /* Display the message in the viewport for 4 seconds */ + Show_4_Seconds = 4, + + /* Display the message in the viewport for 5 seconds */ + Show_5_Seconds = 5, + + /* Display the message in the viewport for 10 seconds */ + Show_10_Seconds = 10, + + /* Display the message in the viewport for 20 seconds */ + Show_20_Seconds = 20, + + /* Display the message in the viewport for 30 seconds */ + Show_30_Seconds = 30, + + /* Display the message in the viewport for 40 seconds */ + Show_40_Seconds = 40, + + /* Display the message in the viewport for 50 seconds */ + Show_50_Seconds = 50, + + /* Display the message in the viewport for 60 seconds */ + Show_60_Seconds = 60, + + /* Display the message in the viewport for 70 seconds */ + Show_70_Seconds = 70, + + /* Display the message in the viewport for 80 seconds */ + Show_80_Seconds = 80, + + /* Display the message in the viewport for 90 seconds */ + Show_90_Seconds = 90, + + /* Display the message in the viewport for 1 minutes */ + Show_1_Minutes = 101, + + /* Display the message in the viewport for 2 minutes */ + Show_2_Minutes = 102, + + /* Display the message in the viewport for 3 minutes */ + Show_3_Minutes = 103, + + /* Display the message in the viewport for 4 minutes */ + Show_4_Minutes = 104, + + /* Display the message in the viewport for 5 minutes */ + Show_5_Minutes = 105, +}; + +/* A library containing assorted useful functions for blueprint error handling. + * + */ +UCLASS(MinimalAPI) +class UlxBlueprintErrorLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + // The Format Error Message blueprint node macroexpands, the following + // function is the core of the expansion. The actual K2Node itself is in + // its own source file. + // + UFUNCTION(BlueprintCallable, meta=(WorldContext = "Context", BlueprintInternalUseOnly = "true")) + static void FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxErrorDisplayDuration DisplayDuration, const FString &InPattern, TArray InArgs); + + // Convert an ElxLogVerbosity to an ELogVerbosity::Type + // + static ELogVerbosity::Type ConvertElxLogVerbosity(ElxLogVerbosity Verbosity); +}; + +/* Debug Blueprint Errors output device. + * + * When an error message gets written to the log, using "Format Error Message," + * or any other means that writes an error message to the log, + * we can optionally notify the blueprint debugger to pause execution. + * This only affects errors that are generated during blueprint execution. + * Errors in other threads do not pause the blueprint. + * + */ +struct FlxDebugBlueprintErrorsOutputDevice : public FOutputDevice +{ +public: + // The constructor and destructor automatically register this output device with GLog. + // + // This struct doesn't store the sensitivity threshold. It relies on some blueprint + // class to do that, so that the threshold can be easily edited with the blueprint + // editor. This struct must be initialized with a reference to the threshold variable. + // + FlxDebugBlueprintErrorsOutputDevice(const ElxLogVerbosity &SensitivityRef); + ~FlxDebugBlueprintErrorsOutputDevice(); + + // Inspect a log message. + // + INTEGRATION_API virtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) override; + + // If the device is marked 'CanBeUsedOnMultipleThreads,' then UE_LOG will + // call Serialize from the current thread, otherwise, it will call Serialize from + // the logging thread. Using the logging thread would defeat the purpose of this + // device, so it's imperative that we set this flag. + // + INTEGRATION_API virtual bool CanBeUsedOnMultipleThreads() const override { return true; } + +private: + const ElxLogVerbosity &Sensitivity; +}; diff --git a/Source/Integration/FormatError.cpp b/Source/Integration/FormatError.cpp index 12d04150..f1de0e29 100644 --- a/Source/Integration/FormatError.cpp +++ b/Source/Integration/FormatError.cpp @@ -15,12 +15,10 @@ #include "Engine/Blueprint.h" #include "HAL/PlatformCrt.h" #include "Internationalization/Internationalization.h" -#include "Internationalization/TextFormatter.h" #include "K2Node_CallFunction.h" #include "K2Node_MakeArray.h" #include "K2Node_MakeStruct.h" #include "Kismet/KismetMathLibrary.h" -#include "Kismet/KismetSystemLibrary.h" #include "Kismet/KismetTextLibrary.h" #include "Kismet2/BlueprintEditorUtils.h" #include "Kismet2/CompilerResultsLog.h" @@ -104,8 +102,8 @@ void UK2Node_FormatError::CreateCorrectPins() } if (FindPin(FormatPinName, EGPD_Input) == nullptr) { - UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Text, FormatPinName); - P->DefaultTextValue = LOCTEXT("FormatErrorMessage_DefaultMessage", "Error Message"); + UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FormatPinName); + P->DefaultValue = TEXT("Error Message"); } if (FindPin(VerbosityPinName, EGPD_Input) == nullptr) { @@ -115,7 +113,7 @@ void UK2Node_FormatError::CreateCorrectPins() } if (FindPin(DisplayDurationPinName, EGPD_Input) == nullptr) { - UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum(), DisplayDurationPinName); + UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum(), DisplayDurationPinName); P->DefaultValue = TEXT("No_Display"); P->AutogeneratedDefaultValue = P->DefaultValue; } @@ -252,7 +250,7 @@ void UK2Node_FormatError::PinDefaultValueChanged(UEdGraphPin* Pin) if(IsFormatPin(Pin)) { PinNames.Empty(); - FText::GetFormatPatternParameters(Pin->DefaultTextValue, PinNames); + FText::GetFormatPatternParameters(FText::FromString(Pin->DefaultValue), PinNames); CreateCorrectPins(); GetGraph()->NotifyNodeChanged(this); } @@ -318,7 +316,7 @@ void UK2Node_FormatError::ExpandNode(class FKismetCompilerContext& CompilerConte // This is the node that does all the Format work and outputs the message. UK2Node_CallFunction* CallFormatFunction = CompilerContext.SpawnIntermediateNode(this, SourceGraph); - UFunction *FormatFunction = UlxFormatErrorLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxFormatErrorLibrary, FormatErrorInternal)); + UFunction *FormatFunction = UlxBlueprintErrorLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxBlueprintErrorLibrary, FormatErrorInternal)); CallFormatFunction->SetFromFunction(FormatFunction); CallFormatFunction->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFormatFunction, this); @@ -608,71 +606,5 @@ FText UK2Node_FormatError::GetMenuCategory() const return FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Text); } -void UlxFormatErrorLibrary::FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray InArgs) -{ - // Generate the formatted string. - // - FText Message = FTextFormatter::Format(MoveTemp(InPattern), MoveTemp(InArgs), false, false); - FString MessageString = Message.ToString(); - - // Convert the DisplayDuration enum into a number of seconds. - // - int Seconds = int(DisplayDuration); - if (Seconds > 100) Seconds = (Seconds - 100) * 60; - - // Choose a color appropriate to the verbosity level. - // - FLinearColor Color; - switch (Verbosity) { - case ElxLogVerbosity::Fatal : Color = FLinearColor(1.0, 0.6, 0.6); break; - case ElxLogVerbosity::Error : Color = FLinearColor(1.0, 0.6, 0.6); break; - case ElxLogVerbosity::Warning : Color = FLinearColor(0.9, 0.9, 0.6); break; - default: Color = FLinearColor(0.8, 0.8, 0.8); break; - } - - // Convert verbosity to an internal value. - // - ELogVerbosity::Type VerbosityValue; - switch (Verbosity) { - case ElxLogVerbosity::Error: VerbosityValue = ELogVerbosity::Error; break; - case ElxLogVerbosity::Warning: VerbosityValue = ELogVerbosity::Warning; break; - case ElxLogVerbosity::Display: VerbosityValue = ELogVerbosity::Display; break; - case ElxLogVerbosity::Log: VerbosityValue = ELogVerbosity::Log; break; - case ElxLogVerbosity::Verbose: VerbosityValue = ELogVerbosity::Verbose; break; - case ElxLogVerbosity::VeryVerbose: VerbosityValue = ELogVerbosity::VeryVerbose; break; - case ElxLogVerbosity::Fatal: VerbosityValue = ELogVerbosity::Fatal; break; - } - - // Get the blueprint name. - // - // Normally, the log function expects you to pass in a filename, and a log - // category name. We use the blueprint name for both. - // - // Using the blueprint name as a log category name is not technically - // correct. However, there is no correct way to create log categories - // from inside of blueprints. Doing it this way at least produces a reasonable - // message inside the log. What doesn't work correctly is the log message - // suppression system. Ie, console commands like 'log verbose' - // don't have any effect here. The design of the log message suppression - // system is such that there just is no reasonable way to hook into it from - // inside of blueprints. - // - FString BlueprintNameString = Context->GetClass()->GetName(); - auto BlueprintNameAnsi = StringCast(*BlueprintNameString); - FLogCategoryName BlueprintNameLogCategory(Context->GetClass()->GetFName()); - - - // Output to Screen, if requested. - // - if (Seconds != 0) - { - UKismetSystemLibrary::PrintText(NULL, Message, true, false, Color, Seconds, NAME_None); - } - - // Output to Log - // - FMsg::Logf(BlueprintNameAnsi.Get(), 0, BlueprintNameLogCategory, VerbosityValue, TEXT("%s"), *MessageString); -} - #undef LOCTEXT_NAMESPACE diff --git a/Source/Integration/FormatError.h b/Source/Integration/FormatError.h index 0a9bcd6a..6735f652 100644 --- a/Source/Integration/FormatError.h +++ b/Source/Integration/FormatError.h @@ -2,6 +2,7 @@ #pragma once +#include "BlueprintErrors.h" #include "Containers/Array.h" #include "CoreMinimal.h" #include "EdGraph/EdGraphNode.h" @@ -12,6 +13,7 @@ #include "UObject/NameTypes.h" #include "UObject/ObjectMacros.h" #include "UObject/UObjectGlobals.h" +#include "BlueprintErrors.h" #include "FormatError.generated.h" @@ -23,121 +25,6 @@ class UObject; -// -// The following UENUM contains all the ELogVerbosity levels, in a form -// that the blueprint editor can manipulate. -// -// We deliberately moved Fatal to the end of the list, because the editor -// will display these values in the order shown here, and we want Error to -// be the value that is 'promoted', and we want Fatal to be buried as a -// rarely-used option. -// - -/** Log Verbosity: The importance of the message, which affects where the message goes and how it is filtered. */ -UENUM(BlueprintType) -enum class ElxLogVerbosity : uint8 { - - /* Prints an error to the console and log file. The editor collects and reports errors. */ - Error, - - /* Prints a warning to the console and log file. The editor collects and report warnings. */ - Warning, - - /* Prints a message to the console and log file. */ - Display, - - /* Prints a message to the log file, however, it does not print to the console. */ - Log, - - /* Prints a message to a log file only if Verbose logging is enabled for the given category. This is usually used for detailed logging. */ - Verbose, - - /* Prints a message to a log file. If VeryVerbose logging is enabled, then this is used for detailed logging that would otherwise spam output. */ - VeryVerbose, - - /* Danger! Prints a fatal error to the console and log file, then crashes (this crashes the editor too). */ - Fatal, -}; - -/** Display Duration: How long to display a message in the game's viewport */ -UENUM(BlueprintType) -enum class ElxDisplayDuration : uint8 { - - /* Do not display the message in the viewport */ - No_Display_in_Viewport = 0, - - /* Display the message in the viewport for 1 second */ - Display_1_Seconds = 1, - - /* Display the message in the viewport for 2 second */ - Display_2_Seconds = 2, - - /* Display the message in the viewport for 3 second */ - Display_3_Seconds = 3, - - /* Display the message in the viewport for 4 second */ - Display_4_Seconds = 4, - - /* Display the message in the viewport for 5 second */ - Display_5_Seconds = 5, - - /* Display the message in the viewport for 10 second */ - Display_10_Seconds = 10, - - /* Display the message in the viewport for 20 second */ - Display_20_Seconds = 20, - - /* Display the message in the viewport for 30 second */ - Display_30_Seconds = 30, - - /* Display the message in the viewport for 1 second */ - Display_40_Seconds = 40, - - /* Display the message in the viewport for 1 second */ - Display_50_Seconds = 50, - - /* Display the message in the viewport for 1 second */ - Display_60_Seconds = 60, - - /* Display the message in the viewport for 1 second */ - Display_70_Seconds = 70, - - /* Display the message in the viewport for 1 second */ - Display_80_Seconds = 80, - - /* Display the message in the viewport for 1 second */ - Display_90_Seconds = 90, - - /* Display the message in the viewport for 1 second */ - Display_1_Minute = 101, - - /* Display the message in the viewport for 1 second */ - Display_2_Minutes = 102, - - /* Display the message in the viewport for 1 second */ - Display_3_Minutes = 103, - - /* Display the message in the viewport for 1 second */ - Display_4_Minutes = 104, - - /* Display the message in the viewport for 1 second */ - Display_5_Minutes = 105, -}; - -// -// Library functions used by Format Error Message. -// -UCLASS(MinimalAPI) -class UlxFormatErrorLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - -public: - UFUNCTION(BlueprintCallable, meta=(WorldContext = "Context", BlueprintInternalUseOnly = "true")) - static void FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray InArgs); -}; - - // // The Format Error Message K2Node. // diff --git a/Source/Integration/IntegrationGameModeBase.cpp b/Source/Integration/IntegrationGameModeBase.cpp index ce254d82..c860c31b 100644 --- a/Source/Integration/IntegrationGameModeBase.cpp +++ b/Source/Integration/IntegrationGameModeBase.cpp @@ -77,6 +77,9 @@ void AIntegrationGameModeBase::ResetToInitialState() w->release(w.Get()); } + // Stop trapping log errors to the debugger. + BreakToDebuggerLogVerbosityDevice.Reset(); + // Clear the lua call assembly buffer. LuaCallBuffer.clear(); @@ -84,8 +87,8 @@ void AIntegrationGameModeBase::ResetToInitialState() PlayerId = 0; // Clear the look-at state; - PreviousLookAt = nullptr; - CurrentLookAt = nullptr; + PreviousLookAt.Init(); + CurrentLookAt.Init(); // Reset the clocks. EngineSeconds = 0.0; @@ -316,6 +319,10 @@ void AIntegrationGameModeBase::BeginPlay() // Initialize the tangible manager. TangibleManager = NewObject(); TangibleManager->Init(GetWorld(), this); + + // If somebody generates a log message that's severe enough, break to debugger. + BreakToDebuggerLogVerbosityDevice.Reset( + new FlxDebugBlueprintErrorsOutputDevice(BreakToDebuggerLogVerbosity)); } void AIntegrationGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -342,8 +349,8 @@ AIntegrationGameModeBase *AIntegrationGameModeBase::GetFromContext(UObject *cont void AIntegrationGameModeBase::UpdateLookAt() { // Rotate the variables. PreviousLookAt = CurrentLookAt; - CurrentLookAt = nullptr; - + CurrentLookAt.Init(); + // Make sure the world is fully configured before we attempt to cast rays. UlxTangible *possessed = TangibleManager->GetPossessedTangible(); if (possessed == nullptr) return; diff --git a/Source/Integration/IntegrationGameModeBase.h b/Source/Integration/IntegrationGameModeBase.h index 05f2bda3..2312ed32 100644 --- a/Source/Integration/IntegrationGameModeBase.h +++ b/Source/Integration/IntegrationGameModeBase.h @@ -10,6 +10,7 @@ #include "TangibleManager.h" #include "LuprexSockets.h" #include "TriggeredTask.h" +#include "BlueprintErrors.h" #include "IntegrationGameModeBase.generated.h" @@ -46,13 +47,13 @@ public: int64 GetPlayerId(); UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") - void SetLookAt(AActor *actor) { CurrentLookAt = actor; } + void SetLookAt(const FHitResult &hit) { CurrentLookAt = hit; } UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") - AActor *GetLookAt() const { return CurrentLookAt; } + const FHitResult &GetLookAt() const { return CurrentLookAt; } UFUNCTION(BlueprintCallable, Category = "Luprex|Look-At Detection") - bool LookAtChanged() const { return CurrentLookAt != PreviousLookAt; } + bool LookAtChanged() const { return CurrentLookAt.HitObjectHandle != PreviousLookAt.HitObjectHandle; } UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") void CalculateLookAt(AActor *Player, APlayerController *PlayerController, APlayerCameraManager *Camera); @@ -110,13 +111,17 @@ public: UPROPERTY() UlxTangibleManager *TangibleManager; - // The actor that the player is looking at, previous frame. + // The actor that the player was looking at, previous frame. UPROPERTY() - AActor *PreviousLookAt; + FHitResult PreviousLookAt; // The actor that the player is looking at, current frame. UPROPERTY() - AActor *CurrentLookAt; + FHitResult CurrentLookAt; + + // The sensitivity level at which a log message triggers a debugger breakpoint. + UPROPERTY(EditAnywhere, Category="Debugging Tools") + ElxLogVerbosity BreakToDebuggerLogVerbosity; // This stores the entire text currently visible in the console. FlxConsoleOutput ConsoleOutput; @@ -150,4 +155,7 @@ public: // These allow us to pre-tick and post-tick. FDelegateHandle OnWorldPreActorTickHandle; FDelegateHandle OnWorldPostActorTickHandle; + + // The device that implements BreakToDebuggerLogVerbosity, above. + TUniquePtr BreakToDebuggerLogVerbosityDevice; }; diff --git a/Source/Integration/UtilityLibrary.cpp b/Source/Integration/UtilityLibrary.cpp index 05a3733f..b3c21715 100644 --- a/Source/Integration/UtilityLibrary.cpp +++ b/Source/Integration/UtilityLibrary.cpp @@ -4,24 +4,17 @@ #include "UtilityLibrary.h" #include "GameFramework/PlayerController.h" #include "EnhancedInputSubsystems.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Kismet/GameplayStatics.h" + #define LOCTEXT_NAMESPACE "Luprex Utility" -void UlxUtilityLibrary::Assert(bool condition, const FString &message) { - if (!condition) { - FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::FatalError, FText::FromString(message)); - FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo); - } -} void UlxUtilityLibrary::CallFunctionByName(UObject *object, const FString &namepart1, const FString &namepart2, const FString &fallback, bool bFailIfNotFound) { FString fullname = namepart1 + namepart2; if (!IsValid(object)) { - const FBlueprintExceptionInfo ExceptionInfo( - EBlueprintExceptionType::FatalError, - LOCTEXT("CallFunctionByName_ObjectIsNotValid", "In CallFunctionByName, object passed in is not valid.") - ); - FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo); + UE_LOG(LogBlueprint, Error, TEXT("In CallFunctionByName, object passed in is not valid.")); return; } UFunction* function = object->FindFunction(FName(*fullname)); @@ -31,20 +24,12 @@ void UlxUtilityLibrary::CallFunctionByName(UObject *object, const FString &namep if (!bFailIfNotFound) { return; } - const FBlueprintExceptionInfo ExceptionInfo( - EBlueprintExceptionType::FatalError, - LOCTEXT("CallFunctionByName_NoSuchFunction", "In CallFunctionByName, cannot find the named function or the fallback function.") - ); - FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo); + UE_LOG(LogBlueprint, Error, TEXT("In CallFunctionByName, cannot find the named function or the fallback function")); return; } } if (function->ParmsSize != 0) { - const FBlueprintExceptionInfo ExceptionInfo( - EBlueprintExceptionType::FatalError, - LOCTEXT("CallFunctionByName_FunctionHasParameters", "CallFunctionByName can only call functions that have no parameters and no return values.") - ); - FBlueprintCoreDelegates::ThrowScriptException(FFrame::GetThreadLocalTopStackFrame()->Object, *FFrame::GetThreadLocalTopStackFrame(), ExceptionInfo); + UE_LOG(LogBlueprint, Error, TEXT("CallFunctionByName can only call functions that have no parameters and no return values")); return; } object->ProcessEvent(function, nullptr); @@ -91,3 +76,45 @@ UEnhancedInputLocalPlayerSubsystem *UlxUtilityLibrary::GetEnhancedInputLocalPlay } return nullptr; } + +bool UlxUtilityLibrary::LineTraceThroughPixel(const APlayerController* PlayerController, + FVector2D PixelXY, double MaxDistanceFromCamera, + ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn, + const TArray& ActorsToIgnore, FHitResult& HitResult) +{ + const FLinearColor TraceColor = FLinearColor::Red; + const FLinearColor TraceHitColor = FLinearColor::Green; + const double DrawTime = 1.0; + + // Zero out the return values. + HitResult.Init(); + + // Sanity check the distance. + if (MaxDistanceFromCamera <= 0.0) + { + return false; + } + + // Make sure there's a player pawn. + AActor *PlayerPawn = PlayerController->GetPawn(); + if (!PlayerPawn) return false; + + // Calculate the trace start and trace end positions in world space. + FVector WorldStart, WorldDirection, WorldEnd; + if (!UGameplayStatics::DeprojectScreenToWorld(PlayerController, PixelXY, WorldStart, WorldDirection)) + { + return false; + } + WorldEnd = WorldStart + (WorldDirection * MaxDistanceFromCamera); + + // Find the hit. + if (UKismetSystemLibrary::LineTraceSingle(PlayerPawn, WorldStart, WorldEnd, TraceChannel, bTraceComplex, + ActorsToIgnore, DrawDebugType, HitResult, bIgnorePlayerPawn, TraceColor, TraceHitColor, DrawTime)) + { + return true; + } + + // Fail. + HitResult.Init(); + return false; +} diff --git a/Source/Integration/UtilityLibrary.h b/Source/Integration/UtilityLibrary.h index f183adc7..8fbfbd8e 100644 --- a/Source/Integration/UtilityLibrary.h +++ b/Source/Integration/UtilityLibrary.h @@ -3,6 +3,8 @@ #pragma once #include "CoreMinimal.h" +#include "Kismet/KismetSystemLibrary.h" + #include "UtilityLibrary.generated.h" class UEnhancedInputLocalPlayerSubsystem; @@ -20,11 +22,6 @@ class INTEGRATION_API UlxUtilityLibrary : public UObject GENERATED_BODY() public: - - // If condition is false, quit the game, reporting an error message to the log. - // - UFUNCTION(BlueprintCallable, Category = "Luprex|Utility") - static void Assert(bool condition, const FString &ErrorMessage); // Call a function by name, on any UObject. If the function doesn't exist, calls // the fallback function instead. If that isn't found either, returns false. @@ -52,4 +49,19 @@ public: // enhanced input subsystem, return nullptr. UFUNCTION(BlueprintCallable, BlueprintPure, Category="Player Controller|Local Player Subsystems") static UEnhancedInputLocalPlayerSubsystem *GetEnhancedInputLocalPlayerSubsystem(AController *Controller); + + // Do a Line Trace from the camera through a specified pixel. + // + // This can be used when you have a crosshair on the screen and you want to + // determine the object that the crosshairs are pointing at. It can also + // be used to do a line trace through the mouse. + // + // Fractional pixels are allowed. Therefore, (0.0, 0.0) is the upper-left corner + // of the upper-left pixel, whereas (0.5, 0.5) is the center of the upper-left pixel. + // + UFUNCTION(BlueprintCallable, Category="Collision", meta=(AutoCreateRefTerm="ActorsToIgnore", Keywords="raycast")) + static bool LineTraceThroughPixel(const APlayerController* PlayerController, + FVector2D PixelXY, double MaxDistanceFromCamera, + ETraceTypeQuery TraceChannel, bool bTraceComplex, EDrawDebugTrace::Type DrawDebugType, bool bIgnorePlayerPawn, + const TArray& ActorsToIgnore, FHitResult& HitResult); }; diff --git a/build-everything.py b/build-everything.py index e991383f..4f39c396 100755 --- a/build-everything.py +++ b/build-everything.py @@ -183,6 +183,14 @@ LUPREXBUILDTASK["type"] = "shell" LUPREXBUILDTASK["options"] = {} LUPREXBUILDTASK["options"]["cwd"] = f"{INTEGRATION}/luprex" +# +# Add a presentation { clear=true } to all build tasks. +# + +for task in WORKSPACE["tasks"]["tasks"]: + task["presentation"] = {} + task["presentation"]["clear"] = True + # # Convert all launch configurations to lldb. # @@ -229,6 +237,13 @@ WORKSPACE["settings"]["files.watcherExclude"] = { f'{UNREALENGINE}/Templates/**' : True } +# +# Tell the LLDB plugin not to dereference pointers. This is dumb behavior, +# it dereferences "char *" and shows only the first character. Not dereferencing +# the pointer shows the whole string. +# +WORKSPACE["settings"]["lldb.dereferencePointers"] = False + # # Write Integration.code-workspace. # diff --git a/luprex/Makefile b/luprex/Makefile index 176694a5..5dd341f9 100644 --- a/luprex/Makefile +++ b/luprex/Makefile @@ -115,7 +115,7 @@ ifeq "$(OS)" "Linux" LUPREXSTATIC_EXE=luprexstatic COMPILE=g++ -Wall $(OPT) -std=c++20 -fvisibility=hidden -c -MMD -fPIC -o LINKDLL=g++ -Wall $(OPT) -std=c++20 -export-dynamic -Wl,--no-allow-shlib-undefined -Wl,-z,defs -shared -o - LINKEXE=g++ -Wall $(OPT) -std=c++20 -o + LINKEXE=g++ -Wall $(OPT) -std=c++20 -export-dynamic -o MAKEDEPS=true OPENSSL_INCLUDE=-I./ext/openssl-3.0.1/inc LUA_FLAGS=-DLUA_USE_APICHECK -DLUA_USE_POSIX diff --git a/luprex/cpp/core/drivenengine.cpp b/luprex/cpp/core/drivenengine.cpp index 6da6d905..1c5ab0a2 100644 --- a/luprex/cpp/core/drivenengine.cpp +++ b/luprex/cpp/core/drivenengine.cpp @@ -927,12 +927,6 @@ static void replaycore_step(EngineWrapper *w) { ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -#if defined(__linux__) - #define DLLEXPORT __attribute__((visibility("default"))) -#elif defined(_WIN32) - #define DLLEXPORT __declspec(dllexport) -#endif - static void init_engine_wrapper_helper(EngineWrapper *w) { static bool called_initializer; assert(DrivenEngineInitializerReg::func != nullptr); @@ -973,6 +967,12 @@ static void init_engine_wrapper_helper(EngineWrapper *w) { w->release = release; }; +#if defined(__linux__) + #define DLLEXPORT __attribute__((visibility("default"))) +#elif defined(_WIN32) + #define DLLEXPORT __declspec(dllexport) +#endif + extern "C" { DLLEXPORT void init_engine_wrapper(EngineWrapper *w) { init_engine_wrapper_helper(w); diff --git a/luprex/cpp/core/http.cpp b/luprex/cpp/core/http.cpp index 35c6eb83..cd068129 100644 --- a/luprex/cpp/core/http.cpp +++ b/luprex/cpp/core/http.cpp @@ -744,51 +744,51 @@ void HttpClientRequest::set_defaults() { void HttpClientRequest::configure(LuaKeywordParser &kp) { LuaVar val; LuaExtStack LS(kp.state(), val); - if (kp.parse(val, "method")) { + if (kp.optional(val, "method")) { set_method(LS, val); } - if (kp.parse(val, "host")) { + if (kp.optional(val, "host")) { set_host(LS, val); } - if (kp.parse(val, "port")) { + if (kp.optional(val, "port")) { set_port(LS, val); } - if (kp.parse(val, "path")) { + if (kp.optional(val, "path")) { set_path(LS, val); } - if (kp.parse(val, "params")) { + if (kp.optional(val, "params")) { set_params(LS, val); } - if (kp.parse(val, "url")) { + if (kp.optional(val, "url")) { set_url(LS, val); } - if (kp.parse(val, "verifycertificate")) { + if (kp.optional(val, "verifycertificate")) { set_verify_certificate(LS, val); } - if (kp.parse(val, "mimetype")) { + if (kp.optional(val, "mimetype")) { set_mime_type(LS, val); } - if (kp.parse(val, "content")) { + if (kp.optional(val, "content")) { set_content(LS, val); } - if (kp.parse(val, "html")) { + if (kp.optional(val, "html")) { set_content(LS, val); set_mime_type("text/html"); } - if (kp.parse(val, "text")) { + if (kp.optional(val, "text")) { set_content(LS, val); set_mime_type("text/plain"); } - if (kp.parse(val, "json")) { + if (kp.optional(val, "json")) { set_content(LS, val); set_mime_type("application/json"); } - if (kp.parse(val, "bytes")) { + if (kp.optional(val, "bytes")) { set_content(LS, val); set_mime_type("application/octet-stream"); } - if (kp.parse(val, "jsonvalue")) { + if (kp.optional(val, "jsonvalue")) { set_jsonvalue(LS, val); } } @@ -1044,35 +1044,35 @@ void HttpServerResponse::set_jsonvalue(LuaCoreStack &LS, LuaSlot val) { void HttpServerResponse::configure(LuaKeywordParser &kp) { LuaVar val; LuaExtStack LS(kp.state(), val); - if (kp.parse(val, "status")) { + if (kp.optional(val, "status")) { set_status(LS, val); } - if (kp.parse(val, "maxage")) { + if (kp.optional(val, "maxage")) { set_max_age(LS, val); } - if (kp.parse(val, "mimetype")) { + if (kp.optional(val, "mimetype")) { set_mime_type(LS, val); } - if (kp.parse(val, "content")) { + if (kp.optional(val, "content")) { set_content(LS, val); } - if (kp.parse(val, "html")) { + if (kp.optional(val, "html")) { set_content(LS, val); set_mime_type("text/html"); } - if (kp.parse(val, "text")) { + if (kp.optional(val, "text")) { set_content(LS, val); set_mime_type("text/plain"); } - if (kp.parse(val, "json")) { + if (kp.optional(val, "json")) { set_content(LS, val); set_mime_type("application/json"); } - if (kp.parse(val, "bytes")) { + if (kp.optional(val, "bytes")) { set_content(LS, val); set_mime_type("application/octet-stream"); } - if (kp.parse(val, "jsonvalue")) { + if (kp.optional(val, "jsonvalue")) { set_jsonvalue(LS, val); } } diff --git a/luprex/cpp/core/luastack.cpp b/luprex/cpp/core/luastack.cpp index dd92856c..618c65cd 100644 --- a/luprex/cpp/core/luastack.cpp +++ b/luprex/cpp/core/luastack.cpp @@ -10,6 +10,9 @@ LuaSpecial LuaRegistry(LUA_REGISTRYINDEX); LuaNilMarker LuaNil; LuaNewTableMarker LuaNewTable; +static LuaToken token_error("error"); +static LuaToken token_found("found"); + LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, bool s, lua_CFunction f) { name_ = n; @@ -655,52 +658,119 @@ void LuaCoreStack::guard_nopredict(const char *fn) { } } -LuaKeywordParser::LuaKeywordParser(lua_State *L, int slot) { - L_ = L; - slot_ = slot; - not_table_ = !lua_istable(L_, slot_); - if (not_table_) { - lua_newtable(L_); - lua_replace(L_, slot_); +static int tailcall_continuation(lua_State *L) +{ + int base; + lua_getctx(L, &base); + return lua_gettop(L) - base; +} + +int LuaDefStack::tailcall_internal(bool passup, int base, int nargs) { + lua_callk(L_, nargs, passup ? LUA_MULTRET : 0, base, tailcall_continuation); + return lua_gettop(L_) - base; +} + +LuaKeywordParser::LuaKeywordParser(const LuaCoreStack &LS0, LuaSlot slot) + : keytab(slot.index()), LS(LS0.state()) { + lua_State *L = LS0.state(); + lua_pushnil(L); found.index_ = lua_gettop(L); + lua_pushnil(L); error.index_ = lua_gettop(L); + lua_pushnil(L); key.index_ = lua_gettop(L); + lua_pushnil(L); val.index_ = lua_gettop(L); + + istable = LS.istable(keytab); + if (istable) { + LS.rawget(found, keytab, token_found); + if (!LS.istable(found)) { + LS.set(found, LuaNewTable); + LS.rawset(keytab, token_found, found); + } } } -bool LuaKeywordParser::parse(LuaSlot out, const char *kw) { - lua_pushstring(L_, kw); - lua_rawget(L_, slot_); - lua_replace(L_, out.index()); - if (!lua_isnil(L_, out.index())) { - parsed_.insert(kw); +bool LuaKeywordParser::optional(LuaSlot out, std::string_view kw) { + if (!istable) { + LS.set(out, LuaNil); + return false; + } + + LS.rawget(out, keytab, kw); + if (!LS.isnil(out)) { + LS.rawset(found, kw, true); return true; } else { return false; } }; -eng::string LuaKeywordParser::final_check() { - if (not_table_) { - return "expected a keyword table"; +bool LuaKeywordParser::required(LuaSlot out, std::string_view kw) { + if (!istable) { + LS.set(out, LuaNil); + return false; } - lua_pushnil(L_); - while (lua_next(L_, slot_) != 0) { - lua_pop(L_, 1); // Don't need the value. - if (!lua_isstring(L_, -1)) { - return "keyword table contains non-string key"; + + LS.rawget(out, keytab, kw); + if (!LS.isnil(out)) { + LS.rawset(found, kw, true); + return true; + } else { + LS.rawget(error, keytab, token_error); + if (!LS.isstring(error)) { + LS.rawset(keytab, token_error, util::ss("required keyword argument not present: ", kw)); } - const char *kw = lua_tostring(L_, -1); - if (parsed_.find(kw) == parsed_.end()) { - eng::ostringstream oss; - oss << "keyword " << kw << " not known"; - return oss.str(); + return false; + } +}; + +eng::string LuaKeywordParser::check() { + if (!istable) { + return "keyword arguments must be a table"; + } + + LS.rawget(error, keytab, token_error); + auto str = LS.trystring(error); + if (str.has_value()) return str.value(); + + return ""; +} + +eng::string LuaKeywordParser::final_check() { + if (!istable) { + return "keyword arguments must be a table"; + } + + LS.rawget(error, keytab, token_error); + auto str = LS.trystring(error); + if (str.has_value()) return str.value(); + + LS.set(key, LuaNil); + while (LS.next(keytab, key, val)) { + if (LS.istoken(key)) { + continue; + } + auto kw = LS.trystringview(key); + if (!kw.has_value()) { + return "keyword arguments include a non-string key"; + } + LS.rawget(val, found, key); + if (!LS.rawequal(val, true)) { + return util::ss("unrecognized keyword argument: ", kw.value()); } } return ""; } +void LuaKeywordParser::check_throw() { + eng::string err = check(); + if (!err.empty()) { + luaL_error(LS.state(), "%s", err.c_str()); + } +} + void LuaKeywordParser::final_check_throw() { eng::string err = final_check(); if (!err.empty()) { - luaL_error(L_, "%s", err.c_str()); + luaL_error(LS.state(), "%s", err.c_str()); } } @@ -712,3 +782,127 @@ const char *LuaByteReader::lua_reader(lua_State *L, void *ud, size_t *size) { reader->size_ = 0; return data; } + +static const char *kwdoc = + "|Parse lua keyword arguments." + "|" + "|The keywords module is used to help parse keyword arguments" + "|for functions. The error handling is strong, it throws useful" + "|error messages when the caller passes in incorrect arguments." + "|This is a typical example of how it is used:" + "|" + "| function drawrect(args)" + "| local x1,y1 = keywords.required(args, 'x1', 'y1')" + "| local x2,y2 = keywords.required(args, 'x2', 'y2')" + "| local color = keywords.optional(args, 'color')" + "| keywords.finalcheckthrow(args)" + "| ..." + "| end" + "|" + "|The function above expects four required keyword arguments and one" + "|optional one. The example code above handles all the following" + "|error cases:" + "|" + "| * That 'args' actually is a table." + "| * That the required keywords x1,y1,x2,y2 are all present." + "| * That the table doesn't contain extraneous unknown keywords." + "|" + "|The functions keywords.required and keywords.optional don't throw" + "|lua errors. Instead, they store status information in the keyword" + "|table itself. Using the status information, the function" + "|keywords.finalcheckthrow will throw an error if anything went wrong" + "|along the way." + "|" + "|You can check errors when you're not finished parsing using the" + "|function keywords.checkthrow() instead of keywords.finalcheckthrow()." + "|Unlike finalcheckthrow, this function doesn't verify the absence of" + "|extraneous keywords, which can only be done at the end." + "|" + "|If you don't want to throw errors at all, you can use" + "|keywords.finalcheck() instead of keywords.finalcheckthrow()." + "|This returns the error message, rather than throwing it." + "|"; + + +LuaDefine(keywords_optional, "table, keyword, keyword, keyword...", kwdoc) { + LuaArg table; + LuaExtraArgs keywords; + LuaDefStack LS(L, table, keywords); + LuaKeywordParser KP(LS, table); + + if (keywords.size() < 1) { + luaL_error(L, "expected at least one keyword"); + return 0; + } + for (int i = 0; i < keywords.size(); i++) { + eng::string kw = LS.ckstring(keywords[i], "keyword"); + KP.optional(keywords[i], kw); + } + + // Return the results without using LS.result, because it doesn't + // support multiple return values. + lua_settop(L, keywords[keywords.size() - 1].index()); + return keywords.size(); +} + +LuaDefine(keywords_required, "table, keyword, keyword, keyword...", kwdoc) { + LuaArg table; + LuaExtraArgs keywords; + LuaDefStack LS(L, table, keywords); + LuaKeywordParser KP(LS, table); + + if (keywords.size() < 1) { + luaL_error(L, "expected at least one keyword"); + return 0; + } + for (int i = 0; i < keywords.size(); i++) { + eng::string kw = LS.ckstring(keywords[i], "keyword"); + KP.required(keywords[i], kw); + } + + // Return the results without using LS.result, because it doesn't + // support multiple return values. + lua_settop(L, keywords[keywords.size() - 1].index()); + return keywords.size(); +} + +LuaDefine(keywords_check, "table", kwdoc) { + LuaArg table; + LuaRet result; + LuaDefStack LS(L, table, result); + LuaKeywordParser KP(LS, table); + eng::string err = KP.check(); + if (!err.empty()) { + LS.set(result, err); + } + return LS.result(); +} + +LuaDefine(keywords_finalcheck, "table", kwdoc) { + LuaArg table; + LuaRet result; + LuaDefStack LS(L, table, result); + LuaKeywordParser KP(LS, table); + eng::string err = KP.final_check(); + if (!err.empty()) { + LS.set(result, err); + } + return LS.result(); +} + +LuaDefine(keywords_checkthrow, "table", kwdoc) { + LuaArg table; + LuaDefStack LS(L, table); + LuaKeywordParser KP(LS, table); + KP.check_throw(); + return LS.result(); +} + +LuaDefine(keywords_finalcheckthrow, "table", kwdoc) { + LuaArg table; + LuaDefStack LS(L, table); + LuaKeywordParser KP(LS, table); + KP.final_check_throw(); + return LS.result(); +} + diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 565a4068..83715634 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -538,6 +538,7 @@ private: friend class LuaCoreStack; friend class LuaDefStack; friend class LuaExtStack; + friend class LuaKeywordParser; }; class LuaArg : public LuaSlot {}; @@ -563,10 +564,8 @@ private: int size_; public: - LuaExtraArgs() { - index_ = 0; - size_ = 0; - } + LuaExtraArgs() : index_(0), size_(0) {} + LuaExtraArgs(int i, int s) : index_(i), size_(s) {} LuaSpecial operator[] (int n) const { return LuaSpecial(index_ + n); } int size() const { return size_; } @@ -1183,7 +1182,33 @@ public: return nret_; } + // Tail-call into lua. + // + // This is meant to be used as follows: return LS.tailcall(passup, func, arg, arg...) + // + // If passup is true, the return value to our caller consists of our + // LuaRet arguments concatenated to the return values from the tail-call. + // If passup is false, the return value to our caller consists solely + // of our LuaRet arguments. + // + template + int tailcall(bool passup, LuaSlot func, T... args) { + lua_checkstack(L_, nret_ + 20); + int base = lua_gettop(L_); + for (int i = 1; i <= nret_; i++) { + lua_pushvalue(L_, i); + } + push_any_value(func); + int argbase = lua_gettop(L_); + push_any_values(args...); + int nargs = lua_gettop(L_) - argbase; + return tailcall_internal(passup, base, nargs); + } + ~LuaDefStack() { } + +private: + int tailcall_internal(bool passup, int base, int nargs); }; //////////////////////////////////////////////////////////////////// @@ -1231,7 +1256,9 @@ public: ~LuaExtStack() { if (!lua_isthrowing(L_)) { - lua_settop(L_, oldtop_); + if (lua_gettop(L_) > oldtop_) { + lua_settop(L_, oldtop_); + } } } }; @@ -1246,49 +1273,85 @@ public: // // * It makes sure the keyword table actually is a table. // -// * It makes sure that you didn't put an unrecognized keyword -// into the keyword table. Unrecognized keywords are defined -// as keywords that are never checked using 'parse'. +// * It makes sure that all required keywords are present. // // * It makes sure that you didn't put anything that isn't a -// keyword into the keyword table. +// known keyword into the keyword table. +// +// This module adds two fields to the table: +// +// [ERROR] - stores an error message, initially nil. +// [FOUND] - the set of keywords successfully parsed. +// +// If at any time, this module detects an error, it doesn't throw. +// Instead, it stores an error report in the table key [ERROR]. +// Later, you can check for an error string using the function +// final_check or final_check_throw. If an error is +// detected when there is already an error report in the table, +// the error report is not overwritten, so therefore, the error +// reported is always the first error detected. +// +// When this module finds a keyword in the table, it adds the keyword +// to the [FOUND] set of all keywords successfully parsed. +// +// If the keyword table that you pass in isn't a table at all, +// then the keyword-fetching functions will always return false. +// Later, when you call 'check', an appropriate error will be +// generated. +// +// The lua module 'keywords' contains the same functions as this +// C++ class. You can write code where a C++ function does some +// of the parsing, and the lua code does the rest of the parsing. // //////////////////////////////////////////////////////////////////// class LuaKeywordParser { - struct cmp_char { - bool operator () (const char *s1, const char *s2) const { - return strcmp(s1, s2) < 0; - }; - }; private: - bool not_table_; - lua_State *L_; - int slot_; - eng::set parsed_; + LuaVar found, error, key, val; + LuaSpecial keytab; + LuaCoreStack LS; + bool istable; void init(const lua_State *L, int slot); public: - // If the slot is not a table, sets the not_table - // flag and creates a dummy table in the slot. - LuaKeywordParser(lua_State *L, int slot); - LuaKeywordParser(const LuaCoreStack &LS, LuaSlot slot) : LuaKeywordParser(LS.state(), slot.index()) {} + LuaKeywordParser(const LuaCoreStack &LS, LuaSlot slot); - // Fetch a value from the table. This never throws. - // Return true if the value is non-nil. - bool parse(LuaSlot slot, const char *kw); + // Fetch the value of the keyword. If the keyword is found, then the + // keyword is added to the [FOUND] set, the value is returned in slot, + // and returns true. Otherwise, sets slot to nil and returns false. + bool optional(LuaSlot slot, std::string_view kw); - // Check if there were any errors. If so, return an - // error message. + // Fetch the value of the keyword. If the keyword is found, then the + // keyword is added to the [FOUND] set, the value is returned in slot, + // and returns true. Otherwise, sets slot to nil, returns false, and + // stores an [ERROR] report in the keyword table. + bool required(LuaSlot slot, std::string_view kw); + + // Check if there are any errors so far, by checking for an [ERROR] + // report in the keyword table. If any error has been + // detected, returns an error message, otherwise, returns empty + // string. + eng::string check(); + + // Check if there are any errors so far, by checking for an [ERROR] + // report in the keyword table. Also check that all keyword + // arguments present in the table are in the [FOUND] set. If there are + // any errors, returns an error message, otherwise returns empty string. eng::string final_check(); - // Check if there are any errors. If so, throw a lua error. + // If check() returns an error, throws the error using luaL_error. + void check_throw(); + + // If final_check() returns an error, throws the error using luaL_error. void final_check_throw(); // Fetch the state pointer. - lua_State *state() const { return L_; } + lua_State *state() const { return LS.state(); } }; + + + //////////////////////////////////////////////////////////////////// // // Lua Byte Reader diff --git a/luprex/cpp/core/planemap.cpp b/luprex/cpp/core/planemap.cpp index fb6ebb46..9e4d1252 100644 --- a/luprex/cpp/core/planemap.cpp +++ b/luprex/cpp/core/planemap.cpp @@ -834,18 +834,20 @@ void PlaneScan::configure(LuaKeywordParser &kp) { bool have_shape = false; bool have_near = false; - if (kp.parse(val, "plane")) { + kp.check_throw(); + + if (kp.optional(val, "plane")) { plane_ = LS.ckstring(val, "plane"); have_plane = true; } - if (kp.parse(val, "center")) { + if (kp.optional(val, "center")) { util::DXYZ xyz = LS.ckxyz(val, "center"); center_ = xyz; have_center = true; } - if (kp.parse(val, "radius")) { + if (kp.optional(val, "radius")) { auto simple = LS.trynumber(val); if (simple) { radius_ = *simple; @@ -862,7 +864,7 @@ void PlaneScan::configure(LuaKeywordParser &kp) { } } - if (kp.parse(val, "shape")) { + if (kp.optional(val, "shape")) { eng::string shape = LS.ckstring(val, "shape"); if (shape == "box") { shape_ = BOX; @@ -876,7 +878,7 @@ void PlaneScan::configure(LuaKeywordParser &kp) { have_shape = true; } - if (kp.parse(val, "near")) { + if (kp.optional(val, "near")) { int64_t id = LS.tanid(val); if (id == 0) { luaL_error(L, "scan configuration: 'near' must be a tangible"); @@ -893,14 +895,14 @@ void PlaneScan::configure(LuaKeywordParser &kp) { have_near = true; } - if (kp.parse(val, "include")) { + if (kp.optional(val, "include")) { if (!have_near) { luaL_error(L, "scan configuration: 'include' specified without 'near'"); } include_near_ = LS.ckboolean(val, "include"); } - if (kp.parse(val, "wholeplane")) { + if (kp.optional(val, "wholeplane")) { if (have_plane || have_center || have_radius || have_shape) { luaL_error(L, "scan configuration: do not specify plane, center, shape, or radius with 'wholeplane'"); } diff --git a/luprex/cpp/core/pprint.cpp b/luprex/cpp/core/pprint.cpp index 73817f02..3f9016d5 100644 --- a/luprex/cpp/core/pprint.cpp +++ b/luprex/cpp/core/pprint.cpp @@ -173,6 +173,8 @@ public: tabify(level + 1); if (LS.isstring(key) && sv::is_lua_id(LS.ckstring(key))) { (*output_) << LS.ckstring(key); + } else if (LS.istoken(key)) { + atomic_print(LUA_TLIGHTUSERDATA, key, false); } else { (*output_) << "["; pprint_r(level + 1, false, key); @@ -243,13 +245,14 @@ public: void PrettyPrintOptions::parse(LuaKeywordParser &kp) { LuaVar option; LuaExtStack LS(kp.state(), option); - if (kp.parse(option, "indent")) { + kp.check_throw(); + if (kp.optional(option, "indent")) { indent = LS.ckboolean(option); } - if (kp.parse(option, "level")) { + if (kp.optional(option, "level")) { level = LS.ckint(option); } - if (kp.parse(option, "expand")) { + if (kp.optional(option, "expand")) { expand = LS.ckboolean(option); } } @@ -306,7 +309,7 @@ LuaDefine(string_pprintx, "options", PrettyPrintOptions options; LuaKeywordParser kp(LS, loptions); options.parse(kp); - if (!kp.parse(value, "value")) { + if (!kp.optional(value, "value")) { LS.set(value, LuaNil); } kp.final_check_throw(); diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index cc7cf082..b81532c2 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -1,6 +1,7 @@ #include "world.hpp" #include "pprint.hpp" +#include "serializelua.hpp" #include static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) { @@ -108,8 +109,8 @@ LuaDefine(tangible_animinit, "tan,config", "|get persisted: they stay the same unless you change them in" "|the 'animate' command." "|" - "|There are five hardwired persistent variables: plane,xyz,facing,bp,model." - "|These five variables are persistent no matter what. This function," + "|There are four hardwired persistent variables: plane,xyz,facing,bp." + "|These variables are persistent no matter what. This function," "|tangible.animinit, optionally allows you to create more persistent" "|variables. For example, let's say you have a pirate chest. You might" "|want to add two persistent variables in addition to the usual set:" @@ -182,7 +183,7 @@ LuaDefine(tangible_animate, "tan,options,config", bool replace = false; if (!LS.isnil(options)) { LuaKeywordParser kp(LS, options); - if (kp.parse(option, "replace")) { + if (kp.optional(option, "replace")) { replace = LS.ckboolean(option); } kp.final_check_throw(); @@ -273,27 +274,48 @@ LuaDefine(tangible_delete, "tan", return LS.result(); } -LuaDefine(tangible_build, "config", +LuaDefine(tangible_build, "config", "|Build a new tangible object." "|" - "|The config table must contain: class,animstate." - "|" ){ + "|The configuration table must contain the keyword 'class', which" + "|must be the name of a class created with 'makeclass'. It may also" + "|contain the following values:" + "|" + "| bp - the unreal blueprint, defaults to class name." + "| plane - the plane, defaults to actor.plane" + "| xyz - the xyz coordinate, defaults to actor.xyz" + "| facing - the rotation, defaults to actor.facing" + "|" + "|Tangible.build will create an initial animstate containing only" + "|bp, plane, xyz, and facing." + "|" + "|After creating the tangible and setting up the initial animation" + "|state, build will call the constructor for the tangible." + "|The constructor must have this prototype:" + "|" + "| function myclass.init(place, actor, config)" + "|" + "|The configuration table passed to tangible.build is then passed" + "|directly to the init function. The constructor should use the keywords" + "|module to parse the keyword arguments." + "|" + "|The constructor is not allowed to block." + ){ LuaArg config; - LuaVar classname, classtab, mt, animstate; + LuaVar classname, classtab, bp, plane, xyz, facing, mt, func; LuaRet database; - LuaDefStack LS(L, config, classname, classtab, database, mt, animstate); + LuaDefStack LS(L, config, classname, classtab, bp, plane, xyz, facing, mt, func, database); + World *w = World::fetch_global_pointer(L); + LuaKeywordParser kp(LS, config); + kp.required(classname, "class"); + kp.optional(bp, "bp"); + kp.optional(plane, "plane"); + kp.optional(xyz, "xyz"); + kp.optional(facing, "facing"); + kp.check_throw(); - // Get the keyword arguments. - if (!kp.parse(classname, "class")) { - luaL_error(L, "You must specify a class for the tangible"); - } - if (!kp.parse(animstate, "animstate")) { - luaL_error(L, "You must specify an animstate table"); - } - kp.final_check_throw(); - - // Find the class. + // Verify the class. eng::string err = LS.getclass(classtab, classname); if (err != "") { luaL_error(L, "%s", err.c_str()); @@ -301,19 +323,29 @@ LuaDefine(tangible_build, "config", // Calculate the initial animation state. AnimState state; - err = state.from_lua(LS, animstate, true, false); - if (err != "") { - luaL_error(L, "%s", err.c_str()); + if (!LS.isnil(bp)) { + state.set_string("bp", LS.ckstring(bp)); + } else { + state.set_string("bp", LS.ckstring(classname)); } - if (!state.contains("xyz") || !state.contains("plane")) { - luaL_error(L, "You must specify both xyz and plane in animstate"); + if (!LS.isnil(plane)) { + state.set_string("plane", LS.ckstring(plane)); } - err = state.add_defaults(nullptr); + if (!LS.isnil(xyz)) { + state.set_dxyz("xyz", LS.ckxyz(xyz)); + } + if (!LS.isnil(facing)) { + state.set_number("facing", LS.cknumber(facing)); + } + + // Add default values from the actor. Set persistent flags. + Tangible *actor = w->tangible_get(w->lthread_actor_id_); + AnimState actorstate = actor->anim_queue_.get_final_persistent(); + err = state.add_defaults(&actorstate); if (err != "") { luaL_error(L, "%s", err.c_str()); } - World *w = World::fetch_global_pointer(L); int64_t new_id = w->alloc_id_predictable(); Tangible *tan = w->tangible_make(LS, database, new_id); @@ -321,10 +353,16 @@ LuaDefine(tangible_build, "config", LS.getmetatable(mt, database); LS.rawset(mt, "__index", classtab); + // Initialize the animstate of the new tangible. tan->anim_queue_.clear(state); tan->update_plane_item(); - - return LS.result(); + + // Call the constructor and finish. + LS.rawget(func, classtab, "init"); + if (!LS.isfunction(func)) { + return LS.result(); + } + return LS.tailcall(false, func, database, config); } LuaDefine(tangible_get, "id", @@ -838,7 +876,7 @@ LuaDefine(pprintx, "options", PrettyPrintOptions options; LuaKeywordParser kp(LS, loptions); options.parse(kp); - if (!kp.parse(value, "value")) { + if (!kp.optional(value, "value")) { LS.set(value, LuaNil); } kp.final_check_throw(); @@ -949,14 +987,7 @@ LuaDefine(global_set, "varname, value", "|lua identifier." "|" "|You can store global data using global.set, then you can" - "|retrieve it using global.get. You can also retrieve data using" - "|gv.varname, which is just shorthand for global.get. You may not" - "|store data using gv.varname=value, this yields the error 'Use " - "|global.set to store data in the global data table.'" - "|" - "|Values stored using global.set are transmitted to all" - "|connected clients immediately. When a new client connects," - "|he will receive all the global data." + "|retrieve it using global.get." "|" "|The global data table is not the same thing as the lua " "|environment table. Trying to store data in the lua environment" @@ -966,18 +997,16 @@ LuaDefine(global_set, "varname, value", "|global data table (using global.set) instead of in the lua" "|environment table." "|" - "|There are certain restrictions on the values that you store." - "|Only data that can be serialized according to doc(table.serialize)" - "|can be stored." + "|Data is stored in a serialized form. The data is serialized" + "|at the moment you call global.set. It is deserialized when you" + "|call global.get. Therefore, each time you call global.get, you" + "|construct another copy of the value." "|" - "|When you store the value, it is immediately serialized and then" - "|deserialized again, and the deserialized copy is stored in the" - "|variable." - "|" -// "|When you call global.get, you obtain the copy. Any attempt to" -// "|mutate the copy will fail with this lua error message: 'Tables" -// "|returned by global.get are immutable.' This rule prevents'" -// "|aliasing between global data and other data structures." + "|The serialization routine can only serialize certain kinds of" + "|values. For example, closures cannot be serialized at all." + "|Serializing a tangible serializes the tangible's ID, but" + "|none of the contents of the tangible. See doc(table.serialize)" + "|for more information about what can and can't be serialized." "|") { LuaArg varname; LuaArg value; @@ -990,8 +1019,16 @@ LuaDefine(global_set, "varname, value", return LS.result(); } + // Serialize the data. + StreamBuffer sb; + eng::string error = serialize_lua(LS, value, &sb); + if (!error.empty()) { + luaL_error(L, "%s", error.c_str()); + return LS.result(); + } + World *w = World::fetch_global_pointer(L); - w->set_global(LS, gvar, value); + w->set_global(gvar, sb.view()); return LS.result(); } @@ -1000,16 +1037,33 @@ LuaDefine(global_get, "varname", "|" "|See doc(global.set) for information on how to store global data." "|" - "|Do not mutate data returned by global.get: doing so will produce" - "|unpredictable results. Instead, using global.set to mutate global" - "|variables." + "|Performance note: each time you call global.get, you deserialize the" + "|stored serialized version, constructing another copy of the data." "|") { LuaArg varname; LuaRet value; - LuaVar globaldb; - LuaDefStack LS(L, varname, value, globaldb); - LS.rawget(globaldb, LuaRegistry, "globaldb"); - LS.rawget(value, globaldb, varname); + LuaDefStack LS(L, varname, value); + LS.set(value, LuaNil); + + // Check the varname argument. + eng::string gvar = LS.ckstring(varname); + if (!sv::is_lua_id(gvar)) { + luaL_error(L, "variable name must be a valid lua identifier: %s", gvar.c_str()); + return LS.result(); + } + + // Fetch the serialized blob. + World *w = World::fetch_global_pointer(L); + std::string_view data = w->get_global(gvar); + if (data.empty()) return LS.result(); + + // Deserialize the blob. + StreamBuffer sb(data); + eng::string error = deserialize_lua(LS, value, &sb); + if (!error.empty()) { + luaL_error(L, "%s", error.c_str()); + return LS.result(); + } return LS.result(); } @@ -1022,8 +1076,8 @@ LuaDefine(global_once, "varname", "|") { LuaArg varname; LuaRet result; - LuaVar globaldb, flag; - LuaDefStack LS(L, varname, flag, result, globaldb); + LuaDefStack LS(L, varname, result); + LS.set(result, false); // Check the varname argument. eng::string gvar = LS.ckstring(varname); @@ -1033,17 +1087,12 @@ LuaDefine(global_once, "varname", } gvar += ":once"; - LS.rawget(globaldb, LuaRegistry, "globaldb"); - LS.rawget(flag, globaldb, gvar); - - if (!LS.isnil(flag)) { - LS.set(result, false); - return LS.result(); - } - - LS.set(result, true); World *w = World::fetch_global_pointer(L); - w->set_global(LS, gvar, result); + LS.set(result, false); + if (w->get_global(gvar).empty()) { + LS.set(result, true); + w->set_global(gvar, "x"); + } return LS.result(); } @@ -1055,8 +1104,7 @@ LuaDefine(global_clearonce, "varname", "|uses global.set under the covers." "|") { LuaArg varname; - LuaVar null; - LuaDefStack LS(L, varname, null); + LuaDefStack LS(L, varname); // Check the varname argument. eng::string gvar = LS.ckstring(varname); @@ -1066,8 +1114,7 @@ LuaDefine(global_clearonce, "varname", } gvar += ":once"; - LS.set(null, LuaNil); World *w = World::fetch_global_pointer(L); - w->set_global(LS, gvar, null); + w->set_global(gvar, ""); return LS.result(); } diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 5f4235c5..e2a33b4e 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -5,7 +5,6 @@ #include "traceback.hpp" #include "pprint.hpp" #include "util.hpp" -#include "serializelua.hpp" #include @@ -332,7 +331,7 @@ int64_t World::create_login_actor() { tan->print_buffer_.clear(); if (is_authoritative()) { - LS.rawget(func, classtab, "initialize"); + LS.rawget(func, classtab, "init"); spawn(LS, id, id, func, true, 0, false); } } @@ -1101,31 +1100,10 @@ std::ostream *World::lthread_print_stream() const { } } -void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value) { - lua_State *L = LS0.state(); - LuaVar globaldb, copy; - LuaExtStack LS(L, globaldb, copy); - - // Serialize then deserialize the data, to produce a copy. - StreamBuffer sb; - eng::string error = serialize_lua(LS, value, &sb); - if (!error.empty()) { - luaL_error(L, "%s", error.c_str()); - return; - } - eng::string serialized(sb.view()); - error = deserialize_lua(LS, copy, &sb); - if (!error.empty()) { - luaL_error(L, "%s", error.c_str()); - return; - } - - // Store the copy in the globalDB. - LS.rawget(globaldb, LuaRegistry, "globaldb"); - LS.rawset(globaldb, gvar, copy); - +void World::set_global(const eng::string &gvar, std::string_view value) { // Store the serialized blob. - gvname_to_serial_[gvar] = serialized; + // + gvname_to_serial_[gvar] = value; // Implement the tracking so that we can rapidly determine which global // variables need to be difference transmitted. @@ -1147,6 +1125,15 @@ void World::set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value } } +const eng::string &World::get_global(const eng::string &gvar) { + static eng::string empty; + auto iter = gvname_to_serial_.find(gvar); + if (iter == gvname_to_serial_.end()) { + return empty; + } else { + return iter->second; + } +} void World::serialize(StreamBuffer *sb) { assert(stack_is_clear()); diff --git a/luprex/cpp/core/world-diffxmit.cpp b/luprex/cpp/core/world-diffxmit.cpp index d86a26e8..3d8c16ec 100644 --- a/luprex/cpp/core/world-diffxmit.cpp +++ b/luprex/cpp/core/world-diffxmit.cpp @@ -305,36 +305,15 @@ void World::diff_source(World *master, StreamBuffer *sb) { assert(tsb.empty()); } -const eng::string &World::get_gvname_serial(const eng::string &gvar) { - static eng::string empty; - auto iter = gvname_to_serial_.find(gvar); - if (iter == gvname_to_serial_.end()) { - return empty; - } else { - return iter->second; - } -} - void World::patch_globals(StreamBuffer *sb, DebugCollector *dbc) { DebugBlock dbb(dbc, "patch_globals"); int64_t seqno = sb->read_int64(); int32_t total = sb->read_int32(); if (total > 0) { - lua_State *L = state(); - LuaVar globaldb, copy; - LuaExtStack LS(L, globaldb, copy); - LS.rawget(globaldb, LuaRegistry, "globaldb"); for (int i = 0; i < total; i++) { eng::string gvar = sb->read_string(); eng::string serial = sb->read_string(); gvname_to_serial_[gvar] = serial; - StreamBuffer sb(serial); - eng::string error = deserialize_lua(LS, copy, &sb); - if (error.empty()) { - LS.rawset(globaldb, gvar, copy); - } else { - DebugLine(dbc) << "Invalid global serialized data: " << gvar << ":" << error; - } } } assign_seqno_ = seqno; @@ -350,8 +329,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) { int64_t count_pos = tsb.total_writes(); int32_t total_mods = 0; for (const eng::string &gvar : gvname_modified_) { - const eng::string &mval = master->get_gvname_serial(gvar); - const eng::string &sval = get_gvname_serial(gvar); + const eng::string &mval = master->get_global(gvar); + const eng::string &sval = get_global(gvar); if (mval != sval) { total_mods += 1; tsb.write_string(gvar); @@ -362,8 +341,8 @@ void World::diff_globals(World *master, StreamBuffer *sb) { while (iter != master->seqno_to_gvname_.end()) { const auto &gvar = iter->second; if (gvname_modified_.find(gvar) == gvname_modified_.end()) { - const eng::string &mval = master->get_gvname_serial(gvar); - const eng::string &sval = get_gvname_serial(gvar); + const eng::string &mval = master->get_global(gvar); + const eng::string &sval = get_global(gvar); if (mval != sval) { total_mods += 1; tsb.write_string(gvar); diff --git a/luprex/cpp/core/world-testing.cpp b/luprex/cpp/core/world-testing.cpp index 1872f9dd..491846c9 100644 --- a/luprex/cpp/core/world-testing.cpp +++ b/luprex/cpp/core/world-testing.cpp @@ -241,32 +241,6 @@ void World::tangible_set_class(int64_t id, const eng::string &c) const { LS.rawset(meta, "__index", sclass); } -void World::set_global_json(const eng::string &gvar, const eng::string &json) { - LuaVar decoded; - LuaExtStack LS(state(), decoded); - bool ok = json::decode(LS, decoded, json); - if (!ok) { - luaL_error(state(), "invalid json"); - return; - } - set_global(LS, gvar, decoded); -} - -eng::string World::get_global_json(const eng::string &gvar) { - LuaVar value, globaldb; - LuaExtStack LS(state(), globaldb, value); - LS.rawget(globaldb, LuaRegistry, "globaldb"); - LS.rawget(value, globaldb, gvar); - eng::string out; - eng::string error = json::encode(LS, value, out, false, 10000); - if (!error.empty()) { - luaL_error(state(), "%s", error.c_str()); - return ""; - } - return out; -} - - eng::string World::tangible_get_class(int64_t id) const { LuaVar tangibles, tan, meta, sclass; LuaExtStack LS(state(), tangibles, tan, meta, sclass); @@ -495,24 +469,24 @@ LuaDefine(unittests_world5diffglobals, "", "some unit tests") { UniqueWorld cs(new World(WORLD_TYPE_PREDICTIVE)); StreamBuffer sb; - m->set_global_json("x", "3"); + m->set_global("x", "3"); ss->diff_globals(m.get(), &sb); cs->patch_globals(&sb, nullptr); - LuaAssertStrEq(L, cs->get_global_json("x"), "3"); + LuaAssertStrEq(L, cs->get_global("x"), "3"); - m->set_global_json("x", "4"); - m->set_global_json("x", "5"); - m->set_global_json("y", "6"); + m->set_global("x", "4"); + m->set_global("x", "5"); + m->set_global("y", "6"); ss->diff_globals(m.get(), &sb); cs->patch_globals(&sb, nullptr); - LuaAssertStrEq(L, cs->get_global_json("x"), "5"); - LuaAssertStrEq(L, cs->get_global_json("y"), "6"); + LuaAssertStrEq(L, cs->get_global("x"), "5"); + LuaAssertStrEq(L, cs->get_global("y"), "6"); - cs->set_global_json("x", "2"); - ss->set_global_json("x", "2"); + cs->set_global("x", "2"); + ss->set_global("x", "2"); ss->diff_globals(m.get(), &sb); cs->patch_globals(&sb, nullptr); - LuaAssertStrEq(L, cs->get_global_json("x"), "5"); + LuaAssertStrEq(L, cs->get_global("x"), "5"); return 0; } diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index fe6e8a0a..d9ab3931 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -357,17 +357,18 @@ public: std::ostream *lthread_print_stream() const; - // Set a global variable. + // Set a lua global variable. // - // This will throw lua errors if there's a problem. + // The table just stores strings, and the difference transmitter + // just difference transmits those strings. The strings are meant + // to be serialized lua data structures, but there is no enforcement + // of that here. // - void set_global(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value); + void set_global(const eng::string &var, std::string_view value); - // Get the serialized value of a global variable. + // Get a lua global variable. // - // This accessor is used during difference transmission. - // - const eng::string &get_gvname_serial(const eng::string &gvar); + const eng::string &get_global(const eng::string &var); // Allocate a single ID. // @@ -491,14 +492,6 @@ public: // eng::string tangible_get_class(int64_t id) const; - // Store json in a global variable. - // - void set_global_json(const eng::string &gvar, const eng::string &json); - - // Get a global variable as json. - // - eng::string get_global_json(const eng::string &gvar); - public: /////////////////////////////////////////////////////////// // @@ -671,7 +664,6 @@ private: std::unique_ptr lthread_prints_; friend class Tangible; - friend void global_set(LuaCoreStack &LS0, const eng::string &gvar, LuaSlot value); friend int lfn_tangible_animate(lua_State *L); friend int lfn_tangible_build(lua_State *L); friend int lfn_tangible_redirect(lua_State *L); diff --git a/luprex/cpp/drv/driver-linux.cpp b/luprex/cpp/drv/driver-linux.cpp index 23cbba86..cc087ca0 100644 --- a/luprex/cpp/drv/driver-linux.cpp +++ b/luprex/cpp/drv/driver-linux.cpp @@ -238,9 +238,11 @@ static std::u32string console_read() { static void call_init_engine_wrapper(const std::filesystem::path &luprexroot, EngineWrapper *w) { using InitFn = void (*)(EngineWrapper *); - InitFn initfn = (InitFn)dlsym(nullptr, "init_engine_wrapper"); + void *exe_handle = dlopen(nullptr, RTLD_NOW | RTLD_LOCAL); + InitFn initfn = (InitFn)dlsym(exe_handle, "init_engine_wrapper"); if (initfn == nullptr) { - std::string path = luprexroot / "build/linux/luprexlib.so"; + fprintf(stderr, "loading luprexlib.so...\n"); + std::string path = luprexroot / "build/Linux/luprexlib.so"; void *dll_handle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); assert(dll_handle != nullptr); initfn = (InitFn)dlsym(dll_handle, "init_engine_wrapper"); diff --git a/luprex/lua/control.lst b/luprex/lua/control.lst index 4a6a9ba5..0425faf0 100644 --- a/luprex/lua/control.lst +++ b/luprex/lua/control.lst @@ -5,6 +5,4 @@ ut-table.lua ut-tablecmp.lua -basics.lua -uglyglobals.lua login.lua diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index 185b41ab..2076d01b 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -1,60 +1,24 @@ makeclass('login') +makeclass("engio") +makeclass('tree') -function login.initialize(actor, place) - dprint("login.initialize:", actor) +function tree.init(self, config) + print("In tree.init:") + pprint{self=self, config=config} + wait(1) + print("tick"); + wait(1) +end + +function login.init(actor, place) + dprint("login.init:", actor) local x = math.random(1, 100) local y = math.random(1, 100) tangible.animate(actor, nil, {bp="tangiblecharacter", action="warpto", plane="earth", xyz={x, y, 90}}) - end - -function login.interface(actor, place) - gui.menu_item("cb_becomeplayer", "Become a Player") - gui.menu_item("cb_p123", "Print 1, 2, 3") - gui.menu_item("cb_p123_nopredict", "Print 1, 2, 3 nopredict") - gui.menu_item("cb_uglytimedaemon","Start the Time Daemon") - gui.menu_item("cb_seedprng","Seed the PRNG") - end - -function login.cb_seedprng(actor,place,dialog) - local result=http.get{method='GET',host='www.random.org',path='/cgi-bin/randbyte',params={nbytes='32',format='f'},verifycertificate=false} - pprint(result) - end -- "GET /cgi-bin/randbyte?nbytes=16384&format=f HTTP/1.0\nHost: www.random.org\n\n" - - -function login.cb_becomeplayer(actor, place, dialog) - actor.kind='P' - actor.Count={} setmetatable(actor.Count,NilIsZero) - actor.food={} setmetatable(actor.food,NilIsZero) - actor.spectra={} setmetatable(actor.spectra,NilIsZero) - actor.stack={} - actor.team='red' - tangible.setclass(actor, player) - tangible.animate(actor,{action="warp",plane="main",x=0,y=0,z=0}) - end - -function login.cb_p123(actor, place, dialog) - print("CB_P123 actor=", actor, " place=", place, " dialog=", dialog); - print(1); - print(2); - print(3); - end - -function bechar() - local a = tangible.actor() - tangible.animate(a, nil, {bp="TangibleCharacter", xyz={0,0,90}}) - end - -makeclass("engio") -function engio.myfunction(actor, place, a, b, c) - print("Myfunction actor=", actor," place=", place) - print("A:", a) - print("B:", b) - print("C:", c) - return {13, "chicken", {2,3,4}, false} - end +end function engio.move(actor, place, action, xyz, facing) -- todo: sanity check the parameters. dprint("engio.move ", action, " ", xyz[1], " ", xyz[2], " ", xyz[3]) tangible.animate(actor, nil, {action=action, xyz=xyz, facing=facing}) - end +end diff --git a/luprex/lua/basics.lua b/luprex/lua/old/basics.lua similarity index 100% rename from luprex/lua/basics.lua rename to luprex/lua/old/basics.lua diff --git a/luprex/lua/horps.lua b/luprex/lua/old/horps.lua similarity index 100% rename from luprex/lua/horps.lua rename to luprex/lua/old/horps.lua diff --git a/luprex/lua/spectra.lua b/luprex/lua/old/spectra.lua similarity index 100% rename from luprex/lua/spectra.lua rename to luprex/lua/old/spectra.lua diff --git a/luprex/lua/teppygame.lua b/luprex/lua/old/teppygame.lua similarity index 100% rename from luprex/lua/teppygame.lua rename to luprex/lua/old/teppygame.lua diff --git a/luprex/lua/uglyglobals.lua b/luprex/lua/old/uglyglobals.lua similarity index 100% rename from luprex/lua/uglyglobals.lua rename to luprex/lua/old/uglyglobals.lua diff --git a/luprex/lua/ut-globaldb.lua b/luprex/lua/old/ut-globaldb.lua similarity index 100% rename from luprex/lua/ut-globaldb.lua rename to luprex/lua/old/ut-globaldb.lua diff --git a/luprex/lua/prng.lua b/luprex/lua/prng.lua deleted file mode 100644 index b0bd98dd..00000000 --- a/luprex/lua/prng.lua +++ /dev/null @@ -1,7 +0,0 @@ -makeclass('prng') - -function prng.seed(n) - ug.set(prngseed,n) - end - -function \ No newline at end of file