Added ambassador support (for Math Blaster).

Tons of config options too.
This commit is contained in:
Hipposgrumm 2024-12-27 20:23:35 -07:00
parent d2a11b04e2
commit 912b294c70
5 changed files with 89 additions and 7 deletions

View File

@ -0,0 +1,27 @@
using sodoffmmo.Attributes;
using sodoffmmo.Core;
using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("SCE")]
class CounterEventHandler : CommandHandler {
public override Task Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"SCE","p":{"NAME":"COUNT"},"r":-1}}
if (client.Room?.HasAmbassador() is bool b && b) {
string name = receivedObject.Get<NetworkObject>("p").Get<string>("NAME");
if (name == "COUNT" || name == "COUNT2" || name == "COUNT3") {
int index = name switch {
"COUNT" => 0,
"COUNT2" => 1,
"COUNT3" => 2
};
client.Room.ambassadorGauges[index] = Math.Min(100, client.Room.ambassadorGauges[index]+(1/Configuration.ServerConfiguration.AmbassadorGaugePlayers));
client.Room.Send(Utils.VlNetworkPacket(client.Room.AddAmbassadorData(new()), client.Room.Id));
} else {
Console.WriteLine("Invalid attempt to increment room var "+name+".");
}
}
return Task.CompletedTask;
}
}

View File

@ -33,6 +33,11 @@ internal sealed class ServerConfiguration {
public int EventTimer { get; set; } = 30;
public int FirstEventTimer { get; set; } = 10;
public Dictionary<string, string[][]> RoomAlerts { get; set; } = new();
public string[] AmbassadorRooms { get; set; } = Array.Empty<string>();
public int AmbassadorGaugeStart { get; set; } = 75;
public float AmbassadorGaugeDecayRate { get; set; } = 60;
public bool AmbassadorGaugeDecayOnlyWhenInRoom { get; set; } = true;
public float AmbassadorGaugePlayers { get; set; } = 0.5f;
public int RacingMaxPlayers { get; set; } = 6;
public int RacingMinPlayers { get; set; } = 2;
public int RacingMainLobbyTimer { get; set; } = 15;

View File

@ -111,7 +111,7 @@ public class Room {
roomInfo.Add(false); // is password protected
roomInfo.Add((short)clients.Count); // player count
roomInfo.Add((short)4096); // max player count
roomInfo.Add(RoomVariables); // variables
roomInfo.Add(AddAmbassadorData(RoomVariables)); // variables
roomInfo.Add((short)0); // spectator count
roomInfo.Add((short)0); // max spectator count
@ -143,7 +143,7 @@ public class Room {
r1.Add(false);
r1.Add((short)clients.Count); // player count
r1.Add((short)4096); // max player count
r1.Add(new NetworkArray());
r1.Add(AddAmbassadorData(new()));
r1.Add((short)0);
r1.Add((short)0);
@ -154,6 +154,35 @@ public class Room {
return NetworkObject.WrapObject(0, 15, obj).Serialize();
}
public double[] ambassadorGauges;
System.Timers.Timer? ambassadorTimer;
public bool HasAmbassador() {
return ambassadorTimer != null;
}
public void InitAmbassador() {
ambassadorGauges = new double[3]; // There is always a maximum of 3.
for (int i=0;i<3;i++) ambassadorGauges[i] = Configuration.ServerConfiguration.AmbassadorGaugeStart;
ambassadorTimer = new System.Timers.Timer(Configuration.ServerConfiguration.AmbassadorGaugeDecayRate*1000);
ambassadorTimer.AutoReset = true;
ambassadorTimer.Enabled = true;
ambassadorTimer.Elapsed += (sender, e) => {
if (!Configuration.ServerConfiguration.AmbassadorGaugeDecayOnlyWhenInRoom || clients.Count > 0) {
for (int i=0;i<3;i++) ambassadorGauges[i] = Math.Max(0, ambassadorGauges[i]-1);
Send(Utils.VlNetworkPacket(AddAmbassadorData(new()), Id));
}
};
}
internal NetworkArray AddAmbassadorData(NetworkArray array) {
if (HasAmbassador()) { // If this isn't null that means ambassadors are initialized.
array.Add(NetworkArray.VlElement("COUNT", (int)Math.Round(ambassadorGauges[0]), isPersistent: true));
array.Add(NetworkArray.VlElement("COUNT2", (int)Math.Round(ambassadorGauges[1]), isPersistent: true));
array.Add(NetworkArray.VlElement("COUNT3", (int)Math.Round(ambassadorGauges[2]), isPersistent: true));
}
return array;
}
private int alertId = -1;
private Random random = new Random();
@ -166,6 +195,8 @@ public class Room {
}
public void SendAllAlerts(Client client) {
return; // Disables joining ongoing alerts (since it doesn't work properly).
foreach (AlertInfo alert in alerts) {
if (alert.IsRunning()) StartAlert(alert, client);
}
@ -173,8 +204,6 @@ public class Room {
private void StartAlert(AlertInfo alert, Client? specificClient = null) {
if (specificClient != null) return; // Disables joining ongoing alerts.
NetworkArray NewRoomVariables = new();
NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_START, alertId++, isPersistent: true));
NewRoomVariables.Add(NetworkArray.VlElement(REDALERT_TYPE, alert.type, isPersistent: true));

View File

@ -31,16 +31,22 @@ public class Server {
foreach (var room in Configuration.ServerConfiguration.RoomAlerts) {
foreach (var alert in room.Value) {
Console.WriteLine($"Setup alert \"{alert[0]}\" for {room.Key}");
Room.GetOrAdd(room.Key).AddAlert(new Room.AlertInfo(
Room.AlertInfo alertInfo = new Room.AlertInfo(
alert[0], // type
float.Parse(alert[1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat), // duration
Int32.Parse(alert[2]), Int32.Parse(alert[3]), // start min - max for random start time
Int32.Parse(alert[4]), Int32.Parse(alert[5]) // extra parameters for specific alarm types
));
);
Console.WriteLine($"Setup alert {alertInfo} for {room.Key}");
Room.GetOrAdd(room.Key).AddAlert(alertInfo);
}
}
foreach (var room in Configuration.ServerConfiguration.AmbassadorRooms) {
Console.WriteLine($"Setup Ambassador for {room}");
Room.GetOrAdd(room).InitAmbassador();
}
await Listen(listener);
}

View File

@ -30,6 +30,21 @@
"ClubSSInt" : [ ["3", 20.0, 30, 240, 0, 16] ],
},
"// AmbassadorRooms": "Rooms with ambassadors (MB funzones).",
"AmbassadorRooms": ["Spaceport"],
"// AmbassadorGaugeStart": "The starting value for all ambassador gauges (MB funzones).",
"AmbassadorGaugeStart": 75,
"// AmbassadorGaugeDecayRate": "Time in seconds before ambassador gauges decrease (MB funzones).",
"AmbassadorGaugeDecayRate": 60,
"// AmbassadorGaugeDecayOnlyWhenInRoom": "Only decrease ambassador gauges when there is at least one player in the room (MB funzones).",
"AmbassadorGaugeDecayOnlyWhenInRoom": true,
"// AmbassadorGaugePlayers": "Denominator for filling the ambassador gauges (MB funzones).",
"AmbassadorGaugePlayers": 0.5,
"// RacingMaxPlayers": "maximum players allowed in Thunder Run Racing (no more than 6)",
"RacingMaxPlayers": 6,