v1.5.7.0 (Summer Update)

This commit is contained in:
Regalis11
2024-06-18 16:49:51 +03:00
parent 4a63dacbce
commit 230d1b6e78
263 changed files with 7792 additions and 2845 deletions
@@ -15,6 +15,8 @@ namespace Barotrauma.Networking
private int pendingRespawnCount, requiredRespawnCount;
private int prevPendingRespawnCount, prevRequiredRespawnCount;
public bool IsShuttleInsideLevel => RespawnShuttle != null && RespawnShuttle.WorldPosition.Y < Level.Loaded.Size.Y;
private IEnumerable<Client> GetClientsToRespawn()
{
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
@@ -24,18 +26,27 @@ namespace Barotrauma.Networking
if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection)) { continue; }
if (c.Character != null && !c.Character.IsDead) { continue; }
//don't allow respawn if the client already has a character (they'll regain control once they're in sync)
var matchingData = campaign?.GetClientCharacterData(c);
//don't allow respawn if the client already has a character (they'll regain control once they're in sync)
if (matchingData != null && matchingData.HasSpawned &&
Character.CharacterList.Any(c => c.Info == matchingData.CharacterInfo && !c.IsDead))
{
continue;
}
if (UseRespawnPrompt)
// Respawning might also be needed in permadeath mode for disconnected characters, but never for permanently dead ones
if (GameMain.NetworkMember?.ServerSettings is { RespawnMode: RespawnMode.Permadeath } &&
(matchingData?.CharacterInfo is { PermanentlyDead: true } || c.Character is { IsDead: true }))
{
continue;
}
if (campaign != null)
{
if (matchingData != null && matchingData.HasSpawned)
{
//in the campaign mode, wait for the client to choose whether they want to spawn
if (!c.WaitForNextRoundRespawn.HasValue || c.WaitForNextRoundRespawn.Value) { continue; }
}
}
@@ -44,9 +55,9 @@ namespace Barotrauma.Networking
}
}
private static bool IsRespawnPromptPendingForClient(Client c)
private static bool IsRespawnDecisionPendingForClient(Client c)
{
if (!UseRespawnPrompt || !(GameMain.GameSession.GameMode is MultiPlayerCampaign campaign)) { return false; }
if (Level.Loaded == null || GameMain.GameSession.GameMode is not MultiPlayerCampaign campaign) { return false; }
if (!c.InGame) { return false; }
if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection)) { return false; }
@@ -55,7 +66,9 @@ namespace Barotrauma.Networking
var matchingData = campaign.GetClientCharacterData(c);
if (matchingData != null && matchingData.HasSpawned)
{
if (Character.CharacterList.Any(c => c.Info == matchingData.CharacterInfo && !c.IsDead))
if (Character.CharacterList.Any(c =>
c.Info == matchingData.CharacterInfo &&
(!c.IsDead || c.CauseOfDeath is { Type: CauseOfDeathType.Disconnected })))
{
return false;
}
@@ -180,22 +193,27 @@ namespace Barotrauma.Networking
shuttleSteering.TargetVelocity = Vector2.Zero;
}
GameServer.Log("Dispatching the respawn shuttle.", ServerLog.MessageType.Spawning);
Vector2 spawnPos = FindSpawnPos();
RespawnCharacters(spawnPos);
CoroutineManager.StopCoroutines("forcepos");
if (spawnPos.Y > Level.Loaded.Size.Y)
RespawnCharacters(spawnPos, out bool anyCharacterSpawnedInShuttle);
if (anyCharacterSpawnedInShuttle)
{
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
GameServer.Log("Dispatching the respawn shuttle.", ServerLog.MessageType.Spawning);
CoroutineManager.StopCoroutines("forcepos");
if (spawnPos.Y > Level.Loaded.Size.Y)
{
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
}
else
{
RespawnShuttle.SetPosition(spawnPos);
RespawnShuttle.Velocity = Vector2.Zero;
RespawnShuttle.NeutralizeBallast();
RespawnShuttle.EnableMaintainPosition();
}
}
else
{
RespawnShuttle.SetPosition(spawnPos);
RespawnShuttle.Velocity = Vector2.Zero;
RespawnShuttle.NeutralizeBallast();
RespawnShuttle.EnableMaintainPosition();
GameServer.Log("Respawning everyone in main sub.", ServerLog.MessageType.Spawning);
}
}
else
@@ -204,7 +222,7 @@ namespace Barotrauma.Networking
GameServer.Log("Respawning everyone in main sub.", ServerLog.MessageType.Spawning);
GameMain.Server.CreateEntityEvent(this);
RespawnCharacters(null);
RespawnCharacters(shuttlePos: null, out _);
}
}
@@ -244,7 +262,7 @@ namespace Barotrauma.Networking
}
}
if (RespawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || DateTime.Now > despawnTime)
if (!IsShuttleInsideLevel || DateTime.Now > despawnTime)
{
CoroutineManager.StopCoroutines("forcepos");
@@ -289,7 +307,10 @@ namespace Barotrauma.Networking
if (DateTime.Now > ReturnTime)
{
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
if (IsShuttleInsideLevel)
{
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
}
CurrentState = State.Returning;
GameMain.Server.CreateEntityEvent(this);
@@ -311,8 +332,8 @@ namespace Barotrauma.Networking
}
return shuttleEmptyTimer > 1.0f;
}
partial void RespawnCharactersProjSpecific(Vector2? shuttlePos)
private void RespawnCharacters(Vector2? shuttlePos, out bool anyCharacterSpawnedInShuttle)
{
respawnedCharacters.Clear();
@@ -337,7 +358,7 @@ namespace Barotrauma.Networking
//all characters are in Team 1 in game modes/missions with only one team.
//if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked
c.TeamID = CharacterTeamType.Team1;
if (c.CharacterInfo == null) { c.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name); }
c.CharacterInfo ??= new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name);
}
List<CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList();
@@ -378,6 +399,8 @@ namespace Barotrauma.Networking
var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo);
anyCharacterSpawnedInShuttle = false;
for (int i = 0; i < characterInfos.Count; i++)
{
bool bot = i >= clients.Count;
@@ -412,10 +435,19 @@ namespace Barotrauma.Networking
}
}
if (!forceSpawnInMainSub)
{
anyCharacterSpawnedInShuttle = true;
}
var character = Character.Create(characterInfos[i], (forceSpawnInMainSub ? mainSubSpawnPoints[i] : shuttleSpawnPoints[i]).WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
characterCampaignData?.ApplyWalletData(character);
character.TeamID = CharacterTeamType.Team1;
character.LoadTalents();
if (characterInfos[i].LastRewardDistribution.TryUnwrap(out int salary))
{
character.Wallet.SetRewardDistribution(salary);
}
respawnedCharacters.Add(character);
@@ -446,7 +478,7 @@ namespace Barotrauma.Networking
$"Respawning {GameServer.ClientLogName(clients[i])} ({clients[i].Connection.Endpoint}) as {characterInfos[i].Job.Name}", ServerLog.MessageType.Spawning);
}
if (RespawnShuttle != null)
if (RespawnShuttle != null && anyCharacterSpawnedInShuttle)
{
List<Item> newRespawnItems = new List<Item>();
Vector2 pos = cargoSp?.Position ?? character.Position;
@@ -567,9 +599,7 @@ namespace Barotrauma.Networking
foreach (Skill skill in characterInfo.Job.GetSkills())
{
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
if (skillPrefab == null || skill.Level < skillPrefab.LevelRange.End) { continue; }
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, skillLossPercentage / 100.0f);
skill.Level = GetReducedSkill(characterInfo, skill, skillLossPercentage);
}
}
@@ -585,14 +615,10 @@ namespace Barotrauma.Networking
msg.WriteSingle((float)(ReturnTime - DateTime.Now).TotalSeconds);
break;
case State.Waiting:
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
var matchingData = campaign?.GetClientCharacterData(c);
bool forceSpawnInMainSub = matchingData != null && !matchingData.HasSpawned;
msg.WriteUInt16((ushort)pendingRespawnCount);
msg.WriteUInt16((ushort)requiredRespawnCount);
msg.WriteBoolean(IsRespawnPromptPendingForClient(c));
msg.WriteBoolean(IsRespawnDecisionPendingForClient(c));
msg.WriteBoolean(RespawnCountdownStarted);
msg.WriteBoolean(forceSpawnInMainSub);
msg.WriteSingle((float)(RespawnTime - DateTime.Now).TotalSeconds);
break;
case State.Returning: