3 using FarseerPhysics.Dynamics;
4 using FarseerPhysics.Dynamics.Contacts;
5 using Microsoft.Xna.Framework;
7 using System.Collections.Generic;
43 private readonly NetworkMember networkMember;
44 private readonly
Steering shuttleSteering;
45 private readonly List<Door> shuttleDoors;
50 private readonly List<Item> respawnItems =
new List<Item>();
53 private readonly List<Character> respawnedCharacters =
new List<Character>();
84 private float maxTransportTime;
86 private float updateReturnTimer;
97 this.networkMember = networkMember;
99 if (shuttleInfo !=
null && networkMember.ServerSettings is not { RespawnMode: RespawnMode.Permadeath })
107 List<WifiComponent> wifiComponents =
new List<WifiComponent>();
119 shuttleDoors =
new List<Door>();
124 if (item.
HasTag(Tags.RespawnContainer))
129 var steering = item.GetComponent<
Steering>();
130 if (steering !=
null) { shuttleSteering = steering; }
132 var door = item.GetComponent<
Door>();
133 if (door !=
null) { shuttleDoors.Add(door); }
137 if (connectionPanel !=
null)
139 foreach (
Connection connection
in connectionPanel.Connections)
146 if (wire !=
null) wire.
Locked =
true;
160 if (networkMember is GameServer server)
162 maxTransportTime = server.ServerSettings.MaxTransportTime;
167 private bool OnShuttleCollision(Fixture sender, Fixture other, Contact contact)
176 if (result !=
null && result.Value)
return;
189 UpdateWaiting(deltaTime);
191 case State.Transporting:
192 UpdateTransporting(deltaTime);
194 case State.Returning:
195 UpdateReturning(deltaTime);
200 partial
void UpdateWaiting(
float deltaTime);
202 private void UpdateTransporting(
float deltaTime)
205 if (maxTransportTime <= 0.0f)
return;
206 UpdateTransportingProjSpecific(deltaTime);
209 partial
void UpdateTransportingProjSpecific(
float deltaTime);
219 private void UpdateReturning(
float deltaTime)
221 updateReturnTimer += deltaTime;
222 if (updateReturnTimer > 1.0f)
224 updateReturnTimer = 0.0f;
225 shuttleSteering?.SetDestinationLevelStart();
226 UpdateReturningProjSpecific(deltaTime);
230 partial
void UpdateReturningProjSpecific(
float deltaTime);
232 private IEnumerable<CoroutineStatus> ForceShuttleToPos(Vector2 position,
float speed)
236 if (GameMain.LuaCs.Game.overrideRespawnSub)
238 yield
return CoroutineStatus.Success;
244 yield
return CoroutineStatus.Success;
250 if (diff.LengthSquared() > 0.01f)
252 Vector2 displayVel = Vector2.Normalize(diff) * speed;
255 yield
return CoroutineStatus.Running;
260 yield
return CoroutineStatus.Success;
263 private void ResetShuttle()
265 ReturnTime = DateTime.Now +
new TimeSpan(0, 0, 0, 0, milliseconds: (
int)(maxTransportTime * 1000));
268 despawnTime =
ReturnTime +
new TimeSpan(0, 0, seconds: 30);
273 foreach (Item item
in Item.ItemList)
278 if (respawnItems.Contains(item) || respawnContainer?.Item !=
null && item.IsOwnedBy(respawnContainer.Item))
285 foreach (var itemComponent
in item.Components)
287 itemComponent.StopLoopingSound();
292 item.Condition = item.MaxCondition;
293 item.GetComponent<
Repairable>()?.ResetDeterioration();
295 if (powerContainer !=
null)
297 powerContainer.
Charge = powerContainer.GetCapacity();
300 var door = item.GetComponent<
Door>();
301 if (door !=
null) { door.
Stuck = 0.0f; }
303 var steering = item.GetComponent<
Steering>();
304 if (steering !=
null)
307 steering.AutoPilot =
true;
309 steering.UnsentChanges =
true;
313 respawnItems.Clear();
315 foreach (Structure wall
in Structure.WallList)
318 for (
int i = 0; i < wall.SectionCount; i++)
320 wall.AddDamage(i, -100000.0f);
324 foreach (Hull hull
in Hull.HullList)
327 hull.OxygenPercentage = 100.0f;
328 hull.WaterVolume = 0.0f;
329 hull.BallastFlora?.Remove();
332 Dictionary<Character, Vector2> characterPositions =
new Dictionary<Character, Vector2>();
333 foreach (Character c
in Character.CharacterList)
336 if (!respawnedCharacters.Contains(c))
338 characterPositions.Add(c, c.WorldPosition);
348 if (c.Inventory !=
null)
350 foreach (Item item
in c.Inventory.AllItems)
360 foreach (var characterPosition
in characterPositions)
362 characterPosition.Key.TeleportTo(characterPosition.Value);
369 float currentLevel = currentSkillLevel ?? skill.
Level;
370 if (skillPrefab ==
null || currentLevel < skillPrefab.LevelRange.End) {
return currentLevel; }
371 return MathHelper.Lerp(currentLevel, skillPrefab.LevelRange.End, skillLossPercentage / 100.0f);
374 partial
void RespawnCharactersProjSpecific(Vector2? shuttlePos);
377 RespawnCharactersProjSpecific(shuttlePos);
393 if (respawnPenaltyAffliction !=
null)
404 Vector2 diffFromDockedBorders =
405 new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2)
408 int minWidth = Math.Max(dockedBorders.Width, 1000);
409 int minHeight = Math.Max(dockedBorders.Height, 1000);
414 bool invalid =
false;
418 if (Math.Abs(ruin.Area.Center.X - potentialSpawnPos.Position.X) < (minWidth + ruin.Area.Width) / 2) { invalid =
true;
break; }
419 if (Math.Abs(ruin.Area.Center.Y - potentialSpawnPos.Position.Y) < (minHeight + ruin.Area.Height) / 2) { invalid =
true;
break; }
421 if (invalid) {
continue; }
424 var tooCloseCells =
Level.
Loaded.GetTooCloseCells(potentialSpawnPos.Position.ToVector2(), Math.Max(minWidth, minHeight));
425 if (tooCloseCells.Any()) {
continue; }
431 float minDist = Math.Max(Math.Max(minWidth, minHeight) + Math.Max(sub.
Borders.Width, sub.
Borders.Height), 10000.0f);
432 if (Vector2.DistanceSquared(sub.
WorldPosition, potentialSpawnPos.Position.ToVector2()) < minDist * minDist)
438 if (invalid) {
continue; }
445 if (Math.Abs(character.
WorldPosition.X - potentialSpawnPos.Position.X) < minWidth) { invalid =
true;
break; }
446 if (Math.Abs(character.
WorldPosition.Y - potentialSpawnPos.Position.Y) < minHeight) { invalid =
true;
break; }
452 if (Vector2.DistanceSquared(character.
WorldPosition, potentialSpawnPos.Position.ToVector2()) < 5000.0f * 5000.0f)
459 if (invalid) {
continue; }
461 potentialSpawnPositions.Add(potentialSpawnPos);
464 float bestSpawnPosValue = 0.0f;
465 foreach (var potentialSpawnPos
in potentialSpawnPositions)
473 spawnPosValue *= 0.1f;
476 if (spawnPosValue > bestSpawnPosValue)
478 bestSpawnPos = potentialSpawnPos.Position.ToVector2();
479 bestSpawnPosValue = spawnPosValue;
AfflictionPrefab is a prefab that defines a type of affliction that can be applied to a character....
Affliction Instantiate(float strength, Character source=null)
static readonly PrefabCollection< AfflictionPrefab > Prefabs
void ApplyAffliction(Limb targetLimb, Affliction affliction, bool allowStacking=true, bool ignoreUnkillability=false)
CharacterHealth CharacterHealth
static readonly List< Character > CharacterList
Stores information about the Character that is needed between rounds in the menu etc....
static EntitySpawner Spawner
virtual Vector2 WorldPosition
const ushort RespawnManagerID
void AddItemToRemoveQueue(Item item)
void AddEntityToRemoveQueue(Entity entity)
static GameSession?? GameSession
static NetworkMember NetworkMember
bool HasTag(Identifier tag)
static readonly List< Item > ItemList
IReadOnlyCollection< Wire > Wires
readonly List< SkillPrefab > Skills
List< InterestingPosition > PositionsOfInterest
object Call(string name, params object[] args)
static float SkillLossPercentageOnDeath
How much skills drop towards the job's default skill levels when dying
static AfflictionPrefab GetRespawnPenaltyAfflictionPrefab()
void Update(float deltaTime)
DateTime RespawnTime
When will the shuttle be dispatched with respawned characters
void RespawnCharacters(Vector2? shuttlePos)
bool RespawnCountdownStarted
bool ReturnCountdownStarted
static void GiveRespawnPenaltyAffliction(Character character)
static float GetReducedSkill(CharacterInfo characterInfo, Skill skill, float skillLossPercentage, float? currentSkillLevel=null)
DateTime ReturnTime
When will the sub start heading back out of the level
static Affliction GetRespawnPenaltyAffliction()
static bool? UseDeathPrompt
RespawnManager(NetworkMember networkMember, SubmarineInfo shuttleInfo)
static float SkillLossPercentageOnImmediateRespawn
How much more the skills drop towards the job's default skill levels when dying, in addition to Skill...
readonly Identifier Identifier
readonly PhysicsBody Body
override Vector2? WorldPosition
IEnumerable< Submarine > DockedTo
void SetCrushDepth(float realWorldCrushDepth)
Normally crush depth is determined by the crush depths of the walls and upgrades applied on them....
static List< Submarine > Loaded
float RealWorldCrushDepth
Rectangle? Borders
Extents of the solid items/structures (ones with a physics body) and hulls
Rectangle GetDockedBorders(bool allowDifferentTeam=true)
Returns a rect that contains the borders of this sub and all subs docked to it, excluding outposts
void SetPosition(Vector2 position, List< Submarine > checkd=null, bool forceUndockFromStaticSubmarines=true)
Interface for entities that the server can send events to the clients