+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-
-namespace Impostor.Api.Innersloth
-{
- public class MapSpawn
- {
- private MapSpawn(float spawnRadius, Vector2 initialSpawnCenter, Vector2 meetingSpawnCenter)
- {
- SpawnRadius = spawnRadius;
- InitialSpawnCenter = initialSpawnCenter;
- MeetingSpawnCenter = meetingSpawnCenter;
- }
-
- public static Dictionary<MapTypes, MapSpawn> Maps { get; } = new Dictionary<MapTypes, MapSpawn>
- {
- [MapTypes.Skeld] = new MapSpawn(1.6f, new Vector2(-0.72f, 0.62f), new Vector2(-0.72f, 0.62f)),
- [MapTypes.MiraHQ] = new MapSpawn(1.55f, new Vector2(-4.4f, 2.2f), new Vector2(24.043f, 1.72f)),
- [MapTypes.Polus] = new MapSpawn(1f, new Vector2(16.64f, -2.46f), new Vector2(17.726f, -16.286f)),
- [MapTypes.Airship] = new MapSpawn(0f, new Vector2(-0.66f, -0.5f), new Vector2(-0.66f, -0.5f)),
- };
-
- public float SpawnRadius { get; }
-
- public Vector2 InitialSpawnCenter { get; }
-
- public Vector2 MeetingSpawnCenter { get; }
-
- public Vector2 GetSpawnLocation(int playerId, int numPlayer, bool initialSpawn)
- {
- var vector = new Vector2(0, 1);
- vector = Rotate(vector, (playerId - 1) * (360f / numPlayer));
- vector *= this.SpawnRadius;
- return (initialSpawn ? this.InitialSpawnCenter : this.MeetingSpawnCenter) + vector + new Vector2(0f, 0.3636f);
- }
-
- private static Vector2 Rotate(Vector2 self, float degrees)
- {
- var f = 0.017453292f * degrees;
- var num = (float)Math.Cos(f);
- var num2 = (float)Math.Sin(f);
- return new Vector2((self.X * num) - (num2 * self.Y), (self.X * num2) + (num * self.Y));
- }
- }
-}
-using System.Numerics;
+using System.Linq;
+using System.Numerics;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Events.Managers;
using Impostor.Api.Net.Messages;
using Impostor.Api.Net.Messages.Rpcs;
using Impostor.Server.Events.Player;
+using Impostor.Server.Net.Inner.Objects.ShipStatus;
using Impostor.Server.Net.State;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
private readonly ObjectPool<PlayerMovementEvent> _pool;
private ushort _lastSequenceId;
+ private bool _spawnSnapAllowed;
public InnerCustomNetworkTransform(Game game, ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool) : base(game)
{
{
if (call == RpcCalls.SnapTo)
{
- if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
+ if (!await ValidateOwnership(call, sender))
{
return false;
}
Rpc21SnapTo.Deserialize(reader, out var position, out var minSid);
+ if (Game.GameNet.ShipStatus is InnerAirshipStatus airshipStatus)
+ {
+ // As part of airship spawning, clients are sending snap to -25 40 for no reason(?), cancelling it works just fine
+ if (Approximately(position, airshipStatus.PreSpawnLocation))
+ {
+ return false;
+ }
+
+ if (_spawnSnapAllowed && airshipStatus.SpawnLocations.Any(location => Approximately(position, location)))
+ {
+ _spawnSnapAllowed = false;
+ return true;
+ }
+ }
+
+ if (!await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
+ {
+ return false;
+ }
+
+ // TODO validate vent location
await SnapToAsync(sender, position, minSid);
return true;
}
_pool.Return(playerMovementEvent);
}
+ internal void OnPlayerSpawn()
+ {
+ _spawnSnapAllowed = true;
+ }
+
private static bool SidGreaterThan(ushort newSid, ushort prevSid)
{
var num = (ushort)(prevSid + (uint)short.MaxValue);
: newSid > prevSid || newSid <= num;
}
+ private static bool Approximately(Vector2 a, Vector2 b, float tolerance = 0.1f)
+ {
+ var abs = Vector2.Abs(a - b);
+ return abs.X <= tolerance && abs.Y <= tolerance;
+ }
+
private ValueTask SnapToAsync(IClientPlayer sender, Vector2 position, ushort minSid)
{
if (!SidGreaterThan(minSid, _lastSequenceId))
+using System;
using System.Collections.Generic;
+using System.Numerics;
using Impostor.Api.Innersloth;
using Impostor.Api.Net.Inner.Objects.ShipStatus;
using Impostor.Server.Net.Inner.Objects.Systems;
public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(21);
+ public override float SpawnRadius => throw new NotSupportedException();
+
+ public override Vector2 InitialSpawnCenter => throw new NotSupportedException();
+
+ public override Vector2 MeetingSpawnCenter => throw new NotSupportedException();
+
+ public Vector2 PreSpawnLocation { get; } = new Vector2(-25f, 40f);
+
+ public Vector2[] SpawnLocations { get; } =
+ {
+ new Vector2(-0.7f, 8.5f), // Brig
+ new Vector2(-0.7f, -1.0f), // Engine
+ new Vector2(15.5f, 0.0f), // MainHall
+ new Vector2(-7.0f, -11.5f), // Kitchen
+ new Vector2(20.0f, 10.5f), // Records
+ new Vector2(33.5f, -1.5f), // CargoBay
+ };
+
+ public override Vector2 GetSpawnLocation(InnerPlayerControl player, int numPlayers, bool initialSpawn)
+ {
+ return new Vector2(-25, 40);
+ }
+
protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
{
base.AddSystems(systems);
using System.Collections.Generic;
+using System.Numerics;
using Impostor.Api.Innersloth;
using Impostor.Api.Net.Inner.Objects.ShipStatus;
using Impostor.Server.Net.Inner.Objects.Systems;
public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(0);
+ public override float SpawnRadius => 1.55f;
+
+ public override Vector2 InitialSpawnCenter { get; } = new Vector2(-4.4f, 2.2f);
+
+ public override Vector2 MeetingSpawnCenter { get; } = new Vector2(24.043f, 1.72f);
+
protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
{
base.AddSystems(systems);
using System.Collections.Generic;
+using System.Numerics;
using Impostor.Api.Innersloth;
using Impostor.Api.Net.Inner.Objects.ShipStatus;
using Impostor.Server.Net.Inner.Objects.Systems;
public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(12);
+ public override float SpawnRadius => 1f;
+
+ public override Vector2 InitialSpawnCenter { get; } = new Vector2(16.64f, -2.46f);
+
+ public override Vector2 MeetingSpawnCenter { get; } = new Vector2(17.726f, -16.286f);
+
+ public Vector2 MeetingSpawnCenter2 { get; } = new Vector2(-17.7f, -17.5f);
+
+ public override Vector2 GetSpawnLocation(InnerPlayerControl player, int numPlayers, bool initialSpawn)
+ {
+ if (initialSpawn)
+ {
+ return base.GetSpawnLocation(player, numPlayers, initialSpawn);
+ }
+
+ Vector2 position;
+ if (player.PlayerId < 5)
+ {
+ position = this.MeetingSpawnCenter + (new Vector2(1, 0) * player.PlayerId);
+ }
+ else
+ {
+ position = this.MeetingSpawnCenter2 + (new Vector2(1, 0) * (player.PlayerId - 5));
+ }
+
+ return position;
+ }
+
protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
{
base.AddSystems(systems);
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Numerics;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Innersloth;
public abstract Dictionary<int, bool> Doors { get; }
+ public abstract float SpawnRadius { get; }
+
+ public abstract Vector2 InitialSpawnCenter { get; }
+
+ public abstract Vector2 MeetingSpawnCenter { get; }
+
public override ValueTask OnSpawnAsync()
{
for (var i = 0; i < Doors.Count; i++)
return true;
}
+ public virtual Vector2 GetSpawnLocation(InnerPlayerControl player, int numPlayers, bool initialSpawn)
+ {
+ var vector = new Vector2(0, 1);
+ vector = Rotate(vector, (player.PlayerId - 1) * (360f / numPlayers));
+ vector *= this.SpawnRadius;
+ return (initialSpawn ? this.InitialSpawnCenter : this.MeetingSpawnCenter) + vector + new Vector2(0f, 0.3636f);
+ }
+
protected virtual void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
{
systems.Add(SystemTypes.Electrical, new SwitchSystem());
systems.Add(SystemTypes.MedBay, new MedScanSystem());
}
+
+ private static Vector2 Rotate(Vector2 self, float degrees)
+ {
+ var f = 0.017453292f * degrees;
+ var cos = MathF.Cos(f);
+ var sin = MathF.Sin(f);
+
+ return new Vector2((self.X * cos) - (sin * self.Y), (self.X * sin) + (cos * self.Y));
+ }
}
}
using System.Collections.Generic;
+using System.Numerics;
using Impostor.Api.Innersloth;
using Impostor.Api.Net.Inner.Objects.ShipStatus;
using Impostor.Server.Net.Inner.Objects.Systems;
public override Dictionary<int, bool> Doors { get; } = new Dictionary<int, bool>(13);
+ public override float SpawnRadius => 1.6f;
+
+ public override Vector2 InitialSpawnCenter { get; } = new Vector2(-0.72f, 0.62f);
+
+ public override Vector2 MeetingSpawnCenter { get; } = new Vector2(-0.72f, 0.62f);
+
protected override void AddSystems(Dictionary<SystemTypes, ISystemType> systems)
{
base.AddSystems(systems);
case InnerMeetingHud meetingHud:
{
+ foreach (var player in _players.Values)
+ {
+ player.Character?.NetworkTransform.OnPlayerSpawn();
+ }
+
await _eventManager.CallAsync(new MeetingStartedEvent(this, meetingHud));
break;
}
{
if (GameState == GameStates.Starting)
{
- for (var i = 0; i < _players.Values.Count; i++)
+ foreach (var player in _players.Values)
{
- var player = _players.Values.ElementAt(i);
- await player.Character!.NetworkTransform.SetPositionAsync(player, MapSpawn.Maps[Options.Map].GetSpawnLocation(i, PlayerCount, true), Vector2.Zero);
+ player.Character?.NetworkTransform.OnPlayerSpawn();
+ await player.Character!.NetworkTransform.SetPositionAsync(player, GameNet.ShipStatus!.GetSpawnLocation(player.Character, PlayerCount, true), Vector2.Zero);
}
GameState = GameStates.Started;