Unstable 1.8.4.0
This commit is contained in:
@@ -1,20 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable enable
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CombatMission
|
||||
{
|
||||
class KillCount
|
||||
{
|
||||
public readonly Character Victim;
|
||||
public readonly Client? VictimClient;
|
||||
public readonly Character? Killer;
|
||||
public readonly Client? KillerClient;
|
||||
public KillCount(Character victim, Character? killer)
|
||||
{
|
||||
Victim = victim;
|
||||
VictimClient = GameMain.Server.ConnectedClients.FirstOrDefault(c => victim.IsClientOwner(c));
|
||||
Killer = killer;
|
||||
if (killer != null)
|
||||
{
|
||||
KillerClient = GameMain.Server.ConnectedClients.FirstOrDefault(c => killer.IsClientOwner(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float RoundEndDuration = 5.0f;
|
||||
|
||||
private readonly bool[] teamDead = new bool[2];
|
||||
|
||||
/// <summary>
|
||||
/// Lists of characters currently alive in the teams
|
||||
/// </summary>
|
||||
private List<Character>[] crews;
|
||||
|
||||
private bool initialized = false;
|
||||
/// <summary>
|
||||
/// List of all kills (of the characters in either team) during the round
|
||||
/// </summary>
|
||||
private readonly List<KillCount> kills = new List<KillCount>();
|
||||
|
||||
private float roundEndTimer;
|
||||
|
||||
private float timeInTargetSubmarineTimer;
|
||||
|
||||
public override LocalizedString Description
|
||||
{
|
||||
get
|
||||
@@ -28,51 +58,16 @@ namespace Barotrauma
|
||||
|
||||
protected override void UpdateMissionSpecific(float deltaTime)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
crews[0].Clear();
|
||||
crews[1].Clear();
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
crews[0].Add(character);
|
||||
}
|
||||
else if (character.TeamID == CharacterTeamType.Team2)
|
||||
{
|
||||
crews[1].Add(character);
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if (crews[0].Count == 0 || crews[1].Count == 0)
|
||||
{
|
||||
//if there are no characters in either crew, end the round
|
||||
teamDead[0] = teamDead[1] = true;
|
||||
state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
teamDead[0] = crews[0].All(c => c.IsDead || c.IsIncapacitated);
|
||||
teamDead[1] = crews[1].All(c => c.IsDead || c.IsIncapacitated);
|
||||
if (teamDead[0] && teamDead[1]) { state = 1; }
|
||||
}
|
||||
CheckTeamCharacters();
|
||||
|
||||
if (state == 0)
|
||||
{
|
||||
CheckWinCondition(deltaTime);
|
||||
for (int i = 0; i < teamDead.Length; i++)
|
||||
{
|
||||
if (!teamDead[i] && teamDead[1 - i])
|
||||
{
|
||||
//make sure nobody in the other team can be revived because that would be pretty weird
|
||||
crews[1 - i].ForEach(c => { if (!c.IsDead) c.Kill(CauseOfDeathType.Unknown, null); });
|
||||
|
||||
GameMain.GameSession.WinningTeam = i == 0 ? CharacterTeamType.Team1 : CharacterTeamType.Team2;
|
||||
|
||||
//state 1 = team 1 won, 2 = team 2 won
|
||||
State = i + 1;
|
||||
SetWinningTeam(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -85,7 +80,7 @@ namespace Barotrauma
|
||||
if (teamDead[0] && teamDead[1])
|
||||
{
|
||||
GameMain.GameSession.WinningTeam = CharacterTeamType.None;
|
||||
if (GameMain.Server != null) { GameMain.Server.EndGame(); }
|
||||
GameMain.Server?.EndGame();
|
||||
}
|
||||
else if (GameMain.GameSession.WinningTeam != CharacterTeamType.None)
|
||||
{
|
||||
@@ -93,5 +88,180 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckTeamCharacters()
|
||||
{
|
||||
for (int i = 0; i < crews.Length; i++)
|
||||
{
|
||||
foreach (var character in crews[i])
|
||||
{
|
||||
if (character.IsDead)
|
||||
{
|
||||
AddKill(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crews[0].Clear();
|
||||
crews[1].Clear();
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.IsDead) { continue; }
|
||||
if (character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
crews[0].Add(character);
|
||||
}
|
||||
else if (character.TeamID == CharacterTeamType.Team2)
|
||||
{
|
||||
crews[1].Add(character);
|
||||
}
|
||||
if (character.IsBot && character.AIController is HumanAIController humanAi)
|
||||
{
|
||||
if (!humanAi.ObjectiveManager.HasOrder<AIObjectiveFightIntruders>(o => o.TargetCharactersInOtherSubs) &&
|
||||
OrderPrefab.Prefabs.TryGet(Tags.AssaultEnemyOrder, out OrderPrefab? assaultOrder))
|
||||
{
|
||||
character.SetOrder(assaultOrder.CreateInstance(
|
||||
OrderPrefab.OrderTargetType.Entity, orderGiver: null).WithManualPriority(CharacterInfo.HighestManualOrderPriority),
|
||||
isNewOrder: true, speak: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckWinCondition(float deltaTime)
|
||||
{
|
||||
switch (winCondition)
|
||||
{
|
||||
case WinCondition.LastManStanding:
|
||||
if (crews[0].Count == 0 || crews[1].Count == 0)
|
||||
{
|
||||
//if there are no characters in either crew, end the round
|
||||
teamDead[0] = teamDead[1] = true;
|
||||
state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
teamDead[0] = crews[0].All(c => c.IsDead || c.IsIncapacitated);
|
||||
teamDead[1] = crews[1].All(c => c.IsDead || c.IsIncapacitated);
|
||||
if (teamDead[0] && teamDead[1]) { state = 1; }
|
||||
}
|
||||
break;
|
||||
case WinCondition.KillCount:
|
||||
//no need to do anything, kills are counted in AddKill
|
||||
break;
|
||||
case WinCondition.ControlSubmarine:
|
||||
CheckTargetSubmarineControl(deltaTime);
|
||||
break;
|
||||
}
|
||||
CheckScore();
|
||||
}
|
||||
|
||||
private void CheckScore()
|
||||
{
|
||||
for (int i = 0; i < crews.Length; i++)
|
||||
{
|
||||
if (Scores[i] >= WinScore)
|
||||
{
|
||||
SetWinningTeam(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckTargetSubmarineControl(float deltaTime)
|
||||
{
|
||||
if (targetSubmarine == null) { return; }
|
||||
|
||||
//score updates at 1 second intervals, so the score represents the time in seconds
|
||||
timeInTargetSubmarineTimer += deltaTime;
|
||||
if (timeInTargetSubmarineTimer < 1.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
timeInTargetSubmarineTimer = 0.0f;
|
||||
|
||||
bool crew1InSubmarine = crews[0].Any(c => c.Submarine == targetSubmarine);
|
||||
bool crew2InSubmarine = crews[1].Any(c => c.Submarine == targetSubmarine);
|
||||
|
||||
for (int i = 0; i < crews.Length; i++)
|
||||
{
|
||||
if (crews[i].Any(c => c.Submarine == targetSubmarine) &&
|
||||
crews[1 - i].None(c => c.Submarine == targetSubmarine))
|
||||
{
|
||||
Scores[i]++;
|
||||
GameMain.Server?.UpdateMissionState(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToScore(CharacterTeamType team, int amount)
|
||||
{
|
||||
if (!HasWinScore) { return; }
|
||||
int index;
|
||||
switch (team)
|
||||
{
|
||||
case CharacterTeamType.Team1:
|
||||
index = 0;
|
||||
break;
|
||||
case CharacterTeamType.Team2:
|
||||
index = 1;
|
||||
break;
|
||||
default:
|
||||
DebugConsole.AddSafeError($"Attempted to increase the score of an invalid team ({team}).");
|
||||
return;
|
||||
}
|
||||
Scores[index] = MathHelper.Clamp(Scores[index] + amount, 0, WinScore);
|
||||
GameMain.Server?.UpdateMissionState(this);
|
||||
}
|
||||
|
||||
private void AddKill(Character character)
|
||||
{
|
||||
kills.Add(new KillCount(character, character.CauseOfDeath?.Killer));
|
||||
if (winCondition == WinCondition.KillCount)
|
||||
{
|
||||
Scores[character.TeamID == CharacterTeamType.Team1 ? 1 : 0] += PointsPerKill;
|
||||
}
|
||||
GameMain.Server?.UpdateMissionState(this);
|
||||
}
|
||||
|
||||
private void SetWinningTeam(int teamIndex)
|
||||
{
|
||||
//state 1 = team 1 won, 2 = team 2 won
|
||||
State = teamIndex + 1;
|
||||
GameMain.GameSession.WinningTeam = teamIndex == 0 ? CharacterTeamType.Team1 : CharacterTeamType.Team2;
|
||||
}
|
||||
|
||||
public override void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
base.ServerWrite(msg);
|
||||
msg.WriteUInt16((ushort)Scores[0]);
|
||||
msg.WriteUInt16((ushort)Scores[1]);
|
||||
|
||||
IEnumerable<Client> uniqueClients = kills
|
||||
.Select(k => k.VictimClient)
|
||||
.Union(kills.Select(k => k.KillerClient))
|
||||
.NotNull();
|
||||
msg.WriteVariableUInt32((uint)uniqueClients.Count());
|
||||
foreach (Client client in uniqueClients)
|
||||
{
|
||||
msg.WriteByte(client.SessionId);
|
||||
msg.WriteVariableUInt32((uint)kills.Count(k => k.VictimClient == client));
|
||||
msg.WriteVariableUInt32((uint)kills.Count(k => k.KillerClient == client));
|
||||
}
|
||||
|
||||
IEnumerable<CharacterInfo> uniqueBots = kills
|
||||
.Select(k => k.Killer)
|
||||
.Union(kills.Select(k => k.Victim))
|
||||
.NotNull()
|
||||
.Where(c => c.Info != null && c.IsBot)
|
||||
.Select(c => c.Info);
|
||||
msg.WriteVariableUInt32((uint)uniqueBots.Count());
|
||||
foreach (CharacterInfo botInfo in uniqueBots)
|
||||
{
|
||||
msg.WriteUInt16(botInfo.ID);
|
||||
msg.WriteVariableUInt32((uint)kills.Count(k => k.Victim?.Info == botInfo));
|
||||
msg.WriteVariableUInt32((uint)kills.Count(k => k.Killer?.Info == botInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user