Skip to content

Commit 65fac03

Browse files
authored
Add RocketCore Gamemode (#1973)
1 parent 93171de commit 65fac03

10 files changed

Lines changed: 2843 additions & 15 deletions

File tree

Gamemode Mods/StarCore SUGMA Gamemodes/Data/Prefabs/RocketBall.sbc

Lines changed: 2345 additions & 0 deletions
Large diffs are not rendered by default.
Binary file not shown.
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
using SC.SUGMA.API;
2+
using SC.SUGMA.GameState;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using RichHudFramework;
7+
using VRage.Game.ModAPI;
8+
using SC.SUGMA.Utilities;
9+
using Sandbox.ModAPI;
10+
using Sandbox.Game.Entities;
11+
using Sandbox.Game;
12+
using VRageMath;
13+
using VRage.ModAPI;
14+
15+
namespace SC.SUGMA.GameModes.RocketCore
16+
{
17+
internal class RocketCoreGamemode : GamemodeBase
18+
{
19+
public static double MatchDuration = 20;
20+
21+
/// <summary>
22+
/// Lists currently tracked factions.
23+
/// </summary>
24+
public readonly List<IMyFaction> TrackedFactions = new List<IMyFaction>();
25+
public List<IMyFaction> InFactions { get; private set; } = new List<IMyFaction>();
26+
protected IMyFaction _winningFaction;
27+
28+
public PointTracker PointTracker;
29+
30+
protected ShareTrackApi ShareTrackApi => SUGMA_SessionComponent.I.ShareTrackApi;
31+
public MatchTimer MatchTimer => SUGMA_SessionComponent.I.GetComponent<MatchTimer>("MatchTimer");
32+
public Dictionary<IMyFaction, SphereZone> FactionGoals = new Dictionary<IMyFaction, SphereZone>();
33+
private bool _waitingForBallSpawn = false;
34+
public override string ReadableName { get; internal set; } = "RocketCore";
35+
36+
public IMyCubeGrid BallEntity = null;
37+
38+
public override string Description { get; internal set; } =
39+
"Score by pushing the ball into the enemy team's goal! Grids are made invincible.";
40+
41+
public RocketCoreGamemode()
42+
{
43+
ArgumentParser += new ArgumentParser(
44+
new ArgumentParser.ArgumentDefinition(
45+
time => double.TryParse(time, out MatchDuration),
46+
"t",
47+
"match-time",
48+
"Match time, in minutes.")
49+
);
50+
}
51+
52+
public override void Close()
53+
{
54+
StopRound();
55+
}
56+
57+
public override void UpdateActive()
58+
{
59+
if (PointTracker == null || MatchTimer == null ||
60+
TrackedFactions == null) // ten billion nullchecks of aristeas
61+
return;
62+
63+
if (MatchTimer.IsMatchEnded && MyAPIGateway.Session.IsServer)
64+
StopRound();
65+
66+
if (_waitingForBallSpawn)
67+
return;
68+
69+
foreach (var zoneSet in FactionGoals)
70+
{
71+
if (zoneSet.Value.ContainedGrids.Count <= 0)
72+
continue;
73+
// Goal was made
74+
PointTracker.AddFactionPoints(zoneSet.Key, -1);
75+
SUGMA_SessionComponent.I.GetComponent<RocketCoreHud>("rocHud")?.GoalScored(zoneSet.Key);
76+
77+
if (_winningFaction != null)
78+
break;
79+
80+
SpawnBall();
81+
Log.Info($"Goal was scored against {zoneSet.Key.Name}! New points: {PointTracker.GetFactionPoints(zoneSet.Key)}");
82+
83+
_waitingForBallSpawn = true;
84+
}
85+
}
86+
87+
public override void StartRound(string[] arguments = null)
88+
{
89+
_waitingForBallSpawn = false;
90+
_winningFaction = null;
91+
PointTracker = new PointTracker(3, 0);
92+
PointTracker.OnFactionWin += OnFactionLose;
93+
94+
SUGMA_SessionComponent.I.UnregisterComponent("ROCPointTracker");
95+
if (!MyAPIGateway.Utilities.IsDedicated)
96+
SUGMA_SessionComponent.I.UnregisterComponent("rocHud");
97+
98+
foreach (var grid in ShareTrackApi.GetTrackedGrids())
99+
{
100+
var faction = PlayerTracker.I.GetGridFaction(grid);
101+
if (faction == null || !ShareTrackApi.IsGridAlive(grid))
102+
continue;
103+
104+
if (!TrackedFactions.Contains(faction))
105+
TrackedFactions.Add(faction);
106+
107+
List<IMyCubeGrid> subGrids = new List<IMyCubeGrid>();
108+
grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
109+
foreach (var subGrid in subGrids)
110+
{
111+
((MyCubeGrid)subGrid).Immune = true;
112+
((MyCubeGrid)subGrid).DestructibleBlocks = false;
113+
}
114+
}
115+
116+
if (TrackedFactions.Count <= 1)
117+
{
118+
MyAPIGateway.Utilities.ShowNotification("There aren't any combatants, idiot!", 10000, "Red");
119+
StopRound();
120+
return;
121+
}
122+
123+
SUGMA_SessionComponent.I.RegisterComponent("ROCPointTracker", PointTracker);
124+
125+
var factionNames = new List<string>();
126+
var factionSpawns = SUtils.GetFactionSpawns();
127+
foreach (var faction in TrackedFactions)
128+
{
129+
factionNames.Add($"|{faction.Tag}|");
130+
foreach (var compareFaction in TrackedFactions)
131+
{
132+
if (faction == compareFaction)
133+
continue;
134+
135+
MyAPIGateway.Session.Factions.DeclareWar(faction.FactionId, compareFaction.FactionId);
136+
//MyAPIGateway.Utilities.ShowMessage("ROC", $"Declared war between {factionKvp.Key.Name} and {faction.Name}");
137+
}
138+
139+
if (factionSpawns.ContainsKey(faction))
140+
{
141+
var zone = new SphereZone(
142+
factionSpawns[faction].GetPosition() - factionSpawns[faction].GetPosition().Normalized() * 2500,
143+
750)
144+
{
145+
SphereDrawColor = faction.CustomColor.ColorMaskToRgb().SetAlphaPct(0.25f),
146+
GridFilter = Array.Empty<IMyCubeGrid>()
147+
};
148+
FactionGoals[faction] = zone;
149+
SUGMA_SessionComponent.I.RegisterComponent($"RocZone{faction.FactionId}", zone);
150+
}
151+
}
152+
153+
InFactions = new List<IMyFaction>(TrackedFactions);
154+
155+
base.StartRound(arguments);
156+
MyAPIGateway.Utilities.ShowNotification("Combatants: " + string.Join(" vs ", factionNames), 10000, "Red");
157+
MatchTimer.Start(MatchDuration);
158+
159+
if (!MyAPIGateway.Utilities.IsDedicated)
160+
SUGMA_SessionComponent.I.RegisterComponent("rocHud", new RocketCoreHud(this));
161+
162+
SpawnBall();
163+
164+
Log.Info("Started a ROC match." +
165+
$"\n- Combatants: {string.Join(" vs ", factionNames)}");
166+
}
167+
168+
private void OnFactionLose(IMyFaction loser)
169+
{
170+
foreach (var grid in ShareTrackApi.GetTrackedGrids())
171+
{
172+
var faction = PlayerTracker.I.GetGridFaction(grid);
173+
if (faction == null || !ShareTrackApi.IsGridAlive(grid) || faction != loser) continue;
174+
175+
List<IMyCubeGrid> subGrids = new List<IMyCubeGrid>();
176+
grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
177+
foreach (var subGrid in subGrids)
178+
{
179+
((MyCubeGrid)subGrid).Immune = false;
180+
((MyCubeGrid)subGrid).DestructibleBlocks = true;
181+
}
182+
183+
FactionGoals[loser].IsVisible = false;
184+
InFactions.Remove(loser);
185+
}
186+
187+
if (InFactions.Count > 1) return;
188+
189+
_winningFaction = InFactions[0];
190+
StopRound();
191+
}
192+
193+
public override void StopRound()
194+
{
195+
BallEntity?.Close();
196+
bool setWinnerFromArgs = false;
197+
foreach (var arg in Arguments)
198+
{
199+
if (arg.StartsWith("win"))
200+
{
201+
long factionId;
202+
long.TryParse(arg.Remove(0, 3), out factionId);
203+
204+
_winningFaction = MyAPIGateway.Session.Factions.TryGetFactionById(factionId);
205+
setWinnerFromArgs = true;
206+
Log.Info($"Winner in arguments found: {factionId} ({_winningFaction?.Name})");
207+
break;
208+
}
209+
}
210+
211+
if (!setWinnerFromArgs && MyAPIGateway.Session.IsServer)
212+
{
213+
Arguments = Arguments.Concat(new[] { $"win{_winningFaction?.FactionId ?? -1}" }).ToArray();
214+
}
215+
216+
SUGMA_SessionComponent.I.GetComponent<RocketCoreHud>("rocHud")?.MatchEnded(_winningFaction);
217+
218+
foreach (var factionKvp in TrackedFactions)
219+
{
220+
foreach (var faction in TrackedFactions)
221+
{
222+
if (faction == factionKvp)
223+
continue;
224+
225+
MyAPIGateway.Session.Factions.SendPeaceRequest(factionKvp.FactionId, faction.FactionId);
226+
MyAPIGateway.Session.Factions.AcceptPeace(faction.FactionId, factionKvp.FactionId);
227+
}
228+
}
229+
230+
// Reset destructibility
231+
foreach (var grid in ShareTrackApi.GetTrackedGrids())
232+
{
233+
List<IMyCubeGrid> subGrids = new List<IMyCubeGrid>();
234+
grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(subGrids);
235+
foreach (var subGrid in subGrids)
236+
{
237+
((MyCubeGrid)subGrid).Immune = false;
238+
((MyCubeGrid)subGrid).DestructibleBlocks = true;
239+
}
240+
}
241+
242+
foreach (var zone in FactionGoals)
243+
SUGMA_SessionComponent.I.UnregisterComponent(zone.Value.ComponentId);
244+
245+
MatchTimer?.Stop();
246+
SUGMA_SessionComponent.I.UnregisterComponent("PointTracker");
247+
248+
base.StopRound();
249+
InFactions.Clear();
250+
TrackedFactions.Clear();
251+
FactionGoals.Clear();
252+
PointTracker = null;
253+
}
254+
255+
protected void SpawnBall()
256+
{
257+
if (!MyAPIGateway.Session.IsServer)
258+
return;
259+
260+
BallEntity?.Close();
261+
MyVisualScriptLogicProvider.PrefabSpawned += PrefabSpawned;
262+
MyVisualScriptLogicProvider.SpawnPrefab("THE BALL", SUtils.RandVector().Normalized() * 250, Vector3D.Forward, Vector3D.Up, entityName: "SugmaTheBall");
263+
}
264+
265+
private void PrefabSpawned(string entityName)
266+
{
267+
try
268+
{
269+
IMyEntity ballEnt;
270+
if (!MyAPIGateway.Entities.TryGetEntityByName(entityName, out ballEnt))
271+
throw new Exception("Could not find ball entity!");
272+
273+
BallEntity = (IMyCubeGrid) ballEnt;
274+
SUGMA_SessionComponent.I.ShareTrackApi.TrackGrid(BallEntity);
275+
276+
MyVisualScriptLogicProvider.PrefabSpawned -= PrefabSpawned;
277+
Log.Info("RocketCoreGamemode spawned ball entity " + entityName + " at " + BallEntity.GetPosition());
278+
279+
var array = new[]
280+
{
281+
BallEntity
282+
};
283+
284+
foreach (var zone in FactionGoals)
285+
zone.Value.GridFilter = array;
286+
_waitingForBallSpawn = false;
287+
}
288+
catch (Exception ex)
289+
{
290+
Log.Exception(ex, typeof(RocketCoreGamemode));
291+
}
292+
}
293+
294+
internal override void DisplayWinMessage()
295+
{
296+
if (_winningFaction == null)
297+
{
298+
MyAPIGateway.Utilities.ShowNotification("YOU ARE ALL LOSERS.", 10000, "Red");
299+
return;
300+
}
301+
302+
MyAPIGateway.Utilities.ShowNotification($"A WINNER IS [{_winningFaction?.Name}]!", 10000);
303+
}
304+
}
305+
}

0 commit comments

Comments
 (0)