diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbc b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbc
new file mode 100644
index 000000000..88a166f42
--- /dev/null
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbc
@@ -0,0 +1,2345 @@
+
+
+
+
+
+ Aristeas
+
+
+
+ 108055600967661582
+ CastShadows InScene
+ 108055600967661582
+
+
+
+
+
+ 0.01681527
+ -0.689737439
+ 0.0471778736
+ 0.722325265
+
+
+
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ ba5bfb16-27fe-4f83-8e1b-9fe04ed919d8
+
+
+
+
+
+
+
+
+ Large
+
+
+ LargeBlockSmallGenerator
+ 127494882478367085
+
+ Weldless
+ 144115188075855874
+
+
+
+ MyInventoryBase
+
+ true
+
+ 0
+ 1
+ 9223372036854.775807
+ 2147483647
+
+ CanReceive
+ false
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ false
+ false
+ Frame100
+ 0
+ 900
+ false
+
+
+
+
+ false
+ true
+ true
+ true
+ 1
+ true
+ 1
+
+
+ LargeBlockBeacon
+ 117397356654221988
+
+
+
+ Weldless
+ 144115188075855874
+ false
+ true
+ true
+ true
+ 1
+ true
+ 200000
+ THE BALL
+
+
+ LargeBlockCockpitSeat
+ 117809699502817722
+
+
+
+ 144115188075855874
+
+
+
+ MyInventoryBase
+
+ true
+
+ 0
+ 1
+ 9223372036854.775807
+ 2147483647
+
+ CanReceive CanSend
+ false
+
+
+
+ MyMultiTextPanelComponent
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+ SCRIPT
+ TSS_ArtificialHorizon
+ 2
+ true
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+ SCRIPT
+ TSS_EnergyHydrogen
+ 2
+ true
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+ SCRIPT
+ TSS_Gravity
+ 2
+ true
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+
+ 2
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+ SCRIPT
+ TSS_ClockAnalog
+ 2
+ true
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+ 0
+
+ 1
+ NONE
+
+ 4294967295
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+ 255
+
+
+ 4278190080
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 255
+
+ 0
+
+ 2
+
+ 4288108544
+ 0
+ 88
+ 151
+ 0
+ 88
+ 151
+ 255
+
+
+ 4294962611
+ 179
+ 237
+ 255
+ 179
+ 237
+ 255
+ 255
+
+
+ 0
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 1
+ false
+
+ Character
+
+
+
+
+
+
+ Character
+
+
+
+
+
+ Character
+
+
+
+
+
+
+
+
+
+ 0.322268754
+ 0.740566134
+ 0.339292675
+ -0.4822708
+
+
+
+ false
+ 0
+
+
+ 0
+ false
+ 0
+
+ 954916
+
+
+ LargeBlockGyro
+ 91430459503144092
+
+
+
+ 144115188075855874
+ false
+ true
+ true
+ true
+ 1
+ true
+ 0.01
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ AQD_LG_IonThrusterS_Armored
+ 91904584980615575
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 14
+ true
+
+
+ AQD_LG_IonThrusterS_Armored
+ 131191130628960182
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 13
+ true
+
+
+ AQD_LG_IonThrusterS_Armored
+ 120284295702293143
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 10
+ true
+
+
+ AQD_LG_IonThrusterS_Armored
+ 97962770887056127
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 9
+ true
+
+
+ AQD_LG_IonThrusterS_Armored
+ 91747736122410389
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 12
+ true
+
+
+ AQD_LG_IonThrusterS_Armored
+ 112660050684883642
+
+
+
+ Weldless
+
+
+
+ MyTimerComponent
+
+ true
+ 0
+ 0
+ true
+ false
+ Frame100
+ 0
+ 100
+ false
+
+
+
+ MyModStorageComponent
+
+
+
+ -
+ 74de02b3-27f9-4960-b1c4-27351f2b06d1
+ [FlameColors]
+0.27/0.41/0.65/0.75
+0.27/0.41/0.65/0.75
+False
+Linked
+True
+
+
+
+
+
+
+
+
+ false
+ true
+ true
+ true
+ 11
+ true
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Base
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlopedCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorInvCorner2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorCorner
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorCorner2Tip
+
+
+
+ Neon_Colorable_Lights
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorBlock
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ LargeBlockArmorSlope2Tip
+
+
+
+ Weldless
+
+
+ THE BALL
+ false
+ false
+ false
+ false
+ 0
+
+
+
+
+ None
+ 0
+ 76561198274566684
+ 0
+
+
+
\ No newline at end of file
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbcB5 b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbcB5
new file mode 100644
index 000000000..1fd0eaee0
Binary files /dev/null and b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbcB5 differ
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreGamemode.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreGamemode.cs
new file mode 100644
index 000000000..9b32138bf
--- /dev/null
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreGamemode.cs
@@ -0,0 +1,305 @@
+using SC.SUGMA.API;
+using SC.SUGMA.GameState;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using RichHudFramework;
+using VRage.Game.ModAPI;
+using SC.SUGMA.Utilities;
+using Sandbox.ModAPI;
+using Sandbox.Game.Entities;
+using Sandbox.Game;
+using VRageMath;
+using VRage.ModAPI;
+
+namespace SC.SUGMA.GameModes.RocketCore
+{
+ internal class RocketCoreGamemode : GamemodeBase
+ {
+ public static double MatchDuration = 20;
+
+ ///
+ /// Lists currently tracked factions.
+ ///
+ public readonly List TrackedFactions = new List();
+ public List InFactions { get; private set; } = new List();
+ protected IMyFaction _winningFaction;
+
+ public PointTracker PointTracker;
+
+ protected ShareTrackApi ShareTrackApi => SUGMA_SessionComponent.I.ShareTrackApi;
+ public MatchTimer MatchTimer => SUGMA_SessionComponent.I.GetComponent("MatchTimer");
+ public Dictionary FactionGoals = new Dictionary();
+ private bool _waitingForBallSpawn = false;
+ public override string ReadableName { get; internal set; } = "RocketCore";
+
+ public IMyCubeGrid BallEntity = null;
+
+ public override string Description { get; internal set; } =
+ "Score by pushing the ball into the enemy team's goal! Grids are made invincible.";
+
+ public RocketCoreGamemode()
+ {
+ ArgumentParser += new ArgumentParser(
+ new ArgumentParser.ArgumentDefinition(
+ time => double.TryParse(time, out MatchDuration),
+ "t",
+ "match-time",
+ "Match time, in minutes.")
+ );
+ }
+
+ public override void Close()
+ {
+ StopRound();
+ }
+
+ public override void UpdateActive()
+ {
+ if (PointTracker == null || MatchTimer == null ||
+ TrackedFactions == null) // ten billion nullchecks of aristeas
+ return;
+
+ if (MatchTimer.IsMatchEnded && MyAPIGateway.Session.IsServer)
+ StopRound();
+
+ if (_waitingForBallSpawn)
+ return;
+
+ foreach (var zoneSet in FactionGoals)
+ {
+ if (zoneSet.Value.ContainedGrids.Count <= 0)
+ continue;
+ // Goal was made
+ PointTracker.AddFactionPoints(zoneSet.Key, -1);
+ SUGMA_SessionComponent.I.GetComponent("rocHud")?.GoalScored(zoneSet.Key);
+
+ if (_winningFaction != null)
+ break;
+
+ SpawnBall();
+ Log.Info($"Goal was scored against {zoneSet.Key.Name}! New points: {PointTracker.GetFactionPoints(zoneSet.Key)}");
+
+ _waitingForBallSpawn = true;
+ }
+ }
+
+ public override void StartRound(string[] arguments = null)
+ {
+ _waitingForBallSpawn = false;
+ _winningFaction = null;
+ PointTracker = new PointTracker(3, 0);
+ PointTracker.OnFactionWin += OnFactionLose;
+
+ SUGMA_SessionComponent.I.UnregisterComponent("ROCPointTracker");
+ if (!MyAPIGateway.Utilities.IsDedicated)
+ SUGMA_SessionComponent.I.UnregisterComponent("rocHud");
+
+ foreach (var grid in ShareTrackApi.GetTrackedGrids())
+ {
+ var faction = PlayerTracker.I.GetGridFaction(grid);
+ if (faction == null || !ShareTrackApi.IsGridAlive(grid))
+ continue;
+
+ if (!TrackedFactions.Contains(faction))
+ TrackedFactions.Add(faction);
+
+ List subGrids = new List();
+ grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
+ foreach (var subGrid in subGrids)
+ {
+ ((MyCubeGrid)subGrid).Immune = true;
+ ((MyCubeGrid)subGrid).DestructibleBlocks = false;
+ }
+ }
+
+ if (TrackedFactions.Count <= 1)
+ {
+ MyAPIGateway.Utilities.ShowNotification("There aren't any combatants, idiot!", 10000, "Red");
+ StopRound();
+ return;
+ }
+
+ SUGMA_SessionComponent.I.RegisterComponent("ROCPointTracker", PointTracker);
+
+ var factionNames = new List();
+ var factionSpawns = SUtils.GetFactionSpawns();
+ foreach (var faction in TrackedFactions)
+ {
+ factionNames.Add($"|{faction.Tag}|");
+ foreach (var compareFaction in TrackedFactions)
+ {
+ if (faction == compareFaction)
+ continue;
+
+ MyAPIGateway.Session.Factions.DeclareWar(faction.FactionId, compareFaction.FactionId);
+ //MyAPIGateway.Utilities.ShowMessage("ROC", $"Declared war between {factionKvp.Key.Name} and {faction.Name}");
+ }
+
+ if (factionSpawns.ContainsKey(faction))
+ {
+ var zone = new SphereZone(
+ factionSpawns[faction].GetPosition() - factionSpawns[faction].GetPosition().Normalized() * 2500,
+ 750)
+ {
+ SphereDrawColor = faction.CustomColor.ColorMaskToRgb().SetAlphaPct(0.25f),
+ GridFilter = Array.Empty()
+ };
+ FactionGoals[faction] = zone;
+ SUGMA_SessionComponent.I.RegisterComponent($"RocZone{faction.FactionId}", zone);
+ }
+ }
+
+ InFactions = new List(TrackedFactions);
+
+ base.StartRound(arguments);
+ MyAPIGateway.Utilities.ShowNotification("Combatants: " + string.Join(" vs ", factionNames), 10000, "Red");
+ MatchTimer.Start(MatchDuration);
+
+ if (!MyAPIGateway.Utilities.IsDedicated)
+ SUGMA_SessionComponent.I.RegisterComponent("rocHud", new RocketCoreHud(this));
+
+ SpawnBall();
+
+ Log.Info("Started a ROC match." +
+ $"\n- Combatants: {string.Join(" vs ", factionNames)}");
+ }
+
+ private void OnFactionLose(IMyFaction loser)
+ {
+ foreach (var grid in ShareTrackApi.GetTrackedGrids())
+ {
+ var faction = PlayerTracker.I.GetGridFaction(grid);
+ if (faction == null || !ShareTrackApi.IsGridAlive(grid) || faction != loser) continue;
+
+ List subGrids = new List();
+ grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
+ foreach (var subGrid in subGrids)
+ {
+ ((MyCubeGrid)subGrid).Immune = false;
+ ((MyCubeGrid)subGrid).DestructibleBlocks = true;
+ }
+
+ FactionGoals[loser].IsVisible = false;
+ InFactions.Remove(loser);
+ }
+
+ if (InFactions.Count > 1) return;
+
+ _winningFaction = InFactions[0];
+ StopRound();
+ }
+
+ public override void StopRound()
+ {
+ BallEntity?.Close();
+ bool setWinnerFromArgs = false;
+ foreach (var arg in Arguments)
+ {
+ if (arg.StartsWith("win"))
+ {
+ long factionId;
+ long.TryParse(arg.Remove(0, 3), out factionId);
+
+ _winningFaction = MyAPIGateway.Session.Factions.TryGetFactionById(factionId);
+ setWinnerFromArgs = true;
+ Log.Info($"Winner in arguments found: {factionId} ({_winningFaction?.Name})");
+ break;
+ }
+ }
+
+ if (!setWinnerFromArgs && MyAPIGateway.Session.IsServer)
+ {
+ Arguments = Arguments.Concat(new[] { $"win{_winningFaction?.FactionId ?? -1}" }).ToArray();
+ }
+
+ SUGMA_SessionComponent.I.GetComponent("rocHud")?.MatchEnded(_winningFaction);
+
+ foreach (var factionKvp in TrackedFactions)
+ {
+ foreach (var faction in TrackedFactions)
+ {
+ if (faction == factionKvp)
+ continue;
+
+ MyAPIGateway.Session.Factions.SendPeaceRequest(factionKvp.FactionId, faction.FactionId);
+ MyAPIGateway.Session.Factions.AcceptPeace(faction.FactionId, factionKvp.FactionId);
+ }
+ }
+
+ // Reset destructibility
+ foreach (var grid in ShareTrackApi.GetTrackedGrids())
+ {
+ List subGrids = new List();
+ grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
+ foreach (var subGrid in subGrids)
+ {
+ ((MyCubeGrid)subGrid).Immune = false;
+ ((MyCubeGrid)subGrid).DestructibleBlocks = true;
+ }
+ }
+
+ foreach (var zone in FactionGoals)
+ SUGMA_SessionComponent.I.UnregisterComponent(zone.Value.ComponentId);
+
+ MatchTimer?.Stop();
+ SUGMA_SessionComponent.I.UnregisterComponent("PointTracker");
+
+ base.StopRound();
+ InFactions.Clear();
+ TrackedFactions.Clear();
+ FactionGoals.Clear();
+ PointTracker = null;
+ }
+
+ protected void SpawnBall()
+ {
+ if (!MyAPIGateway.Session.IsServer)
+ return;
+
+ BallEntity?.Close();
+ MyVisualScriptLogicProvider.PrefabSpawned += PrefabSpawned;
+ MyVisualScriptLogicProvider.SpawnPrefab("THE BALL", SUtils.RandVector().Normalized() * 250, Vector3D.Forward, Vector3D.Up, entityName: "SugmaTheBall");
+ }
+
+ private void PrefabSpawned(string entityName)
+ {
+ try
+ {
+ IMyEntity ballEnt;
+ if (!MyAPIGateway.Entities.TryGetEntityByName(entityName, out ballEnt))
+ throw new Exception("Could not find ball entity!");
+
+ BallEntity = (IMyCubeGrid) ballEnt;
+ SUGMA_SessionComponent.I.ShareTrackApi.TrackGrid(BallEntity);
+
+ MyVisualScriptLogicProvider.PrefabSpawned -= PrefabSpawned;
+ Log.Info("RocketCoreGamemode spawned ball entity " + entityName + " at " + BallEntity.GetPosition());
+
+ var array = new[]
+ {
+ BallEntity
+ };
+
+ foreach (var zone in FactionGoals)
+ zone.Value.GridFilter = array;
+ _waitingForBallSpawn = false;
+ }
+ catch (Exception ex)
+ {
+ Log.Exception(ex, typeof(RocketCoreGamemode));
+ }
+ }
+
+ internal override void DisplayWinMessage()
+ {
+ if (_winningFaction == null)
+ {
+ MyAPIGateway.Utilities.ShowNotification("YOU ARE ALL LOSERS.", 10000, "Red");
+ return;
+ }
+
+ MyAPIGateway.Utilities.ShowNotification($"A WINNER IS [{_winningFaction?.Name}]!", 10000);
+ }
+ }
+}
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreHud.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreHud.cs
new file mode 100644
index 000000000..3b4270e2d
--- /dev/null
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/RocketCore/RocketCoreHud.cs
@@ -0,0 +1,172 @@
+using RichHudFramework.Client;
+using RichHudFramework.UI;
+using RichHudFramework.UI.Client;
+using Sandbox.Game.Entities;
+using SC.SUGMA.GameModes.Elimination;
+using SC.SUGMA.GameState;
+using SC.SUGMA.Utilities;
+using System;
+using System.Collections.Generic;
+using Sandbox.ModAPI;
+using VRage.Game.ModAPI;
+using VRageMath;
+
+namespace SC.SUGMA.GameModes.RocketCore
+{
+ internal class RocketCoreHud : ComponentBase
+ {
+ private int _closeTime = -1;
+ private readonly RocketCoreGamemode _gamemode;
+ public RocHud_Window Window;
+
+ public MySoundPair CaptureSound = new MySoundPair("SUGMA_CaptureSound_TF2");
+ private List _zoneGpses = new List();
+
+ public RocketCoreHud(RocketCoreGamemode gamemode)
+ {
+ _gamemode = gamemode;
+ }
+
+ public override void Init(string id)
+ {
+ base.Init(id);
+
+ if (!RichHudClient.Registered)
+ throw new Exception("RichHudAPI was not initialized in time!");
+
+ Window = new RocHud_Window(HudMain.HighDpiRoot, _gamemode);
+ foreach (var zone in _gamemode.FactionGoals)
+ {
+ var gps = MyAPIGateway.Session.GPS.Create($"{zone.Key.Name} Goal", "", zone.Value.Sphere.Center, true,
+ false);
+ MyAPIGateway.Session.GPS.AddLocalGps(gps);
+ _zoneGpses.Add(gps);
+ }
+ }
+
+ public override void Close()
+ {
+ HudMain.HighDpiRoot.RemoveChild(Window);
+ foreach (var gps in _zoneGpses)
+ MyAPIGateway.Session.GPS.RemoveLocalGps(gps);
+ }
+
+ public override void UpdateTick()
+ {
+ Window.Update();
+ if (_closeTime > 0)
+ _closeTime--;
+
+ if (_closeTime == 0) SUGMA_SessionComponent.I.UnregisterComponent(ComponentId);
+ }
+
+ public void MatchEnded(IMyFaction winner)
+ {
+ Window.MatchEnded(winner);
+ _closeTime = HudConstants.MatchResultsVisibleTicks;
+ }
+
+ public void GoalScored(IMyFaction faction)
+ {
+ MyAPIGateway.Utilities.ShowNotification($"Goal was scored against {faction.Name}!", 10000);
+ SUtils.PlaySound(CaptureSound);
+ }
+ }
+
+ internal class RocHud_Window : HudElementBase
+ {
+ private readonly RocketCoreGamemode _gamemode;
+
+ private bool _matchEnded;
+ private readonly MatchTimer _timer;
+ private readonly LabelBox _timerLabel;
+
+ private readonly Dictionary _factionLabels = new Dictionary();
+
+ public RocHud_Window(HudParentBase parent, RocketCoreGamemode gamemode) : base(parent)
+ {
+ _gamemode = gamemode;
+ _timer = gamemode.MatchTimer;
+
+ if (_gamemode == null)
+ throw new Exception("Null gamemode!");
+ if (_timer == null)
+ throw new Exception("Null match timer!");
+
+ Size = new Vector2(100, 24);
+
+ Offset = new Vector2(0, 515); // Regardless of screen size, this is out of 1920x1080
+
+ _timerLabel = new LabelBox(this)
+ {
+ ParentAlignment = ParentAlignments.Inner | ParentAlignments.Top,
+ Height = 24,
+ DimAlignment = DimAlignments.Height,
+ Text = "20:00",
+ TextPadding = new Vector2(2.5f, 0),
+ FitToTextElement = false,
+ Color = HudConstants.HudBackgroundColor
+ };
+
+ var idx = 0;
+ foreach (var faction in _gamemode.TrackedFactions)
+ {
+ _factionLabels[faction] = new LabelBox(this)
+ {
+ Format = GlyphFormat.White.WithColor(faction.CustomColor.ColorMaskToRgb()).WithSize(2)
+ .WithAlignment(TextAlignment.Center),
+ ParentAlignment =
+ ParentAlignments.InnerV |
+ (idx % 2 == 0 ? ParentAlignments.Right : ParentAlignments.Left) |
+ ParentAlignments.Top,
+ Color = HudConstants.HudBackgroundColor,
+ Offset = new Vector2(0, (int)-Math.Floor(idx / 2f) * (24 + 5)),
+ Text = $"{_gamemode.PointTracker.StartingPoints} GOALS LEFT"
+ };
+ idx++;
+ }
+
+ _gamemode.PointTracker.OnPointsUpdated += OnPointsUpdated;
+ }
+
+ private void OnPointsUpdated(IMyFaction faction, int points)
+ {
+ if (!_factionLabels.ContainsKey(faction))
+ return;
+
+ _factionLabels[faction].Text = $"{points} GOAL{(points == 1 ? "" : "S")} LEFT";
+ }
+
+ public void Update()
+ {
+ if (_matchEnded)
+ return;
+
+ _timerLabel.Text = _timer.RemainingTimeString();
+ }
+
+ public void MatchEnded(IMyFaction winner)
+ {
+ _matchEnded = true;
+ var winnerPoints = 0;
+
+ _timerLabel?.Unregister();
+ foreach (var label in _factionLabels)
+ label.Value.Unregister();
+
+ var winnerLabel = new LabelBox(_timerLabel)
+ {
+ Text = winner != null
+ ? $"A WINNER IS {winner.Name}."
+ : "YOU ARE ALL LOSERS",
+ ParentAlignment = ParentAlignments.Bottom,
+ Height = EliminationHud_TeamBanner.BaseHeight,
+ TextPadding = new Vector2(2.5f, 0),
+ Color = HudConstants.HudBackgroundColor
+ };
+
+ winnerLabel.TextBoard.SetFormatting(GlyphFormat.White.WithColor(Color.Red).WithSize(3)
+ .WithAlignment(TextAlignment.Center));
+ }
+ }
+}
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/TeamDeathMatch/TeamDeathmatchGamemode.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/TeamDeathMatch/TeamDeathmatchGamemode.cs
index 1c006051f..8ab8ffdbc 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/TeamDeathMatch/TeamDeathmatchGamemode.cs
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameModes/TeamDeathMatch/TeamDeathmatchGamemode.cs
@@ -139,7 +139,7 @@ public override void StopRound()
if (!setWinnerFromArgs && MyAPIGateway.Session.IsServer)
{
if (WinningFaction == null)
- WinningFaction = PointTracker.FactionPoints.MaxBy(f => f.Value).Key;
+ WinningFaction = PointTracker.GetHighestPoints();
Arguments = Arguments.Concat(new[] { $"win{WinningFaction?.FactionId ?? -1}" }).ToArray();
}
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameState/PointTracker.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameState/PointTracker.cs
index d20ed34a5..f984cf3bb 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameState/PointTracker.cs
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/GameState/PointTracker.cs
@@ -2,11 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using Sandbox.Game.Multiplayer;
using Sandbox.ModAPI;
using SC.SUGMA.HeartNetworking;
using SC.SUGMA.HeartNetworking.Custom;
-using SC.SUGMA.Utilities;
using VRage.Game.ModAPI;
namespace SC.SUGMA.GameState
@@ -14,10 +12,10 @@ namespace SC.SUGMA.GameState
internal class PointTracker : ComponentBase
{
private bool _pointsUpdated;
- public int StartingPoints;
- public int VictoryPoints = 3;
+ public readonly int StartingPoints;
+ public readonly int VictoryPoints;
- public Dictionary FactionPoints { get; internal set; } = new Dictionary();
+ protected Dictionary FactionPoints = new Dictionary();
public Action OnPointsUpdated = null;
private void OnFactionCreated(long factionId)
@@ -49,7 +47,7 @@ public override void UpdateTick()
{
if (_pointsUpdated && MyAPIGateway.Session.IsServer)
{
- HeartNetwork.I.SendToEveryone(new PointsPacket(this));
+ HeartNetwork.I.SendToEveryone((PointsPacket) this);
_pointsUpdated = false;
}
}
@@ -70,6 +68,11 @@ public int GetFactionPoints(long factionId)
return GetFactionPoints(MyAPIGateway.Session.Factions.TryGetFactionById(factionId));
}
+ public IMyFaction GetHighestPoints()
+ {
+ return FactionPoints.MaxBy(f => f.Value).Key;
+ }
+
public void SetFactionPoints(IMyFaction faction, int value)
{
if (!MyAPIGateway.Session.IsServer || !FactionPoints.ContainsKey(faction))
@@ -137,5 +140,7 @@ public override string ToString()
sb.Append($"{faction.Key.Name}: {faction.Value}pts\n");
return sb.ToString();
}
+
+ public static explicit operator PointsPacket(PointTracker tracker) => new PointsPacket(tracker.ComponentId, tracker.FactionPoints);
}
}
\ No newline at end of file
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/HeartNetworking/Custom/PointsPacket.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/HeartNetworking/Custom/PointsPacket.cs
index 7e6c18d1d..d798e645d 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/HeartNetworking/Custom/PointsPacket.cs
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/HeartNetworking/Custom/PointsPacket.cs
@@ -17,11 +17,11 @@ private PointsPacket()
{
}
- public PointsPacket(PointTracker pointTracker)
+ public PointsPacket(string componentId, Dictionary points)
{
- _senderObjectId = pointTracker.ComponentId;
+ _senderObjectId = componentId;
_points = new Dictionary();
- foreach (var factionKvp in pointTracker.FactionPoints)
+ foreach (var factionKvp in points)
_points.Add(factionKvp.Key.FactionId, factionKvp.Value);
//string data = "";
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/SUGMA_SessionComponent.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/SUGMA_SessionComponent.cs
index e863fb505..24e477159 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/SUGMA_SessionComponent.cs
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/SUGMA_SessionComponent.cs
@@ -11,14 +11,11 @@
using SC.SUGMA.GameModes.Elimination;
using SC.SUGMA.GameModes.TeamDeathmatch;
using SC.SUGMA.GameModes.KOTH;
+using SC.SUGMA.GameModes.RocketCore;
using SC.SUGMA.GameState;
using SC.SUGMA.HeartNetworking;
using SC.SUGMA.HeartNetworking.Custom;
-using SC.SUGMA.Utilities;
using VRage.Game.Components;
-using VRage.Scripting;
-using Sandbox.Game;
-using VRageMath;
namespace SC.SUGMA
{
@@ -38,6 +35,7 @@ internal class SUGMA_SessionComponent : MySessionComponentBase
["dom"] = new DominationGamemode(),
["tdm"] = new TeamDeathmatchGamemode(),
["koth"] = new KOTHGamemode(),
+ ["roc"] = new RocketCoreGamemode(),
};
///
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/Utilities/SUtils.cs b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/Utilities/SUtils.cs
index aec9bd4a1..b19f1603b 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/Utilities/SUtils.cs
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/Data/Scripts/SUGMA/Utilities/SUtils.cs
@@ -43,6 +43,9 @@ public static void SetDamageEnabled(bool value)
public static void SetWorldPermissionsForMatch(bool matchActive)
{
+ if (MyAPIGateway.Session == null)
+ return;
+
MyAPIGateway.Utilities.ShowMessage("SUGMA",
$"Match global permissions {(matchActive ? "enabled" : "disabled")}.");
diff --git a/Gamemode Mods/StarCore SUGMA Gamemodes/StarCore SUGMA Gamemodes.csproj.DotSettings b/Gamemode Mods/StarCore SUGMA Gamemodes/StarCore SUGMA Gamemodes.csproj.DotSettings
index 07eaf28c4..53b65eeda 100644
--- a/Gamemode Mods/StarCore SUGMA Gamemodes/StarCore SUGMA Gamemodes.csproj.DotSettings
+++ b/Gamemode Mods/StarCore SUGMA Gamemodes/StarCore SUGMA Gamemodes.csproj.DotSettings
@@ -2,4 +2,4 @@
True
True
True
- True
\ No newline at end of file
+ False
\ No newline at end of file