3 using System.Collections.Generic;
7 using Microsoft.Xna.Framework;
11 internal partial class Radiation : ISerializableEntity
13 public string Name => nameof(Radiation);
16 public float Amount {
get;
set; }
19 public bool Enabled {
get;
set; }
21 public Dictionary<Identifier, SerializableProperty> SerializableProperties {
get; }
23 public readonly Map Map;
24 public readonly RadiationParams Params;
28 private float radiationTimer;
30 private float increasedAmount;
31 private float lastIncrease;
33 public Radiation(Map map, RadiationParams radiationParams, XElement? element =
null)
35 SerializableProperties = SerializableProperty.DeserializeProperties(
this, element);
37 Params = radiationParams;
38 radiationTimer = Params.RadiationDamageDelay;
41 Amount = Params.StartingRadiation;
49 public void OnStep(
float steps = 1)
51 if (!Enabled) {
return; }
52 if (steps <= 0) {
return; }
54 float increaseAmount = Params.RadiationStep * steps;
56 if (Params.MaxRadiation > 0 && Params.MaxRadiation < Amount + increaseAmount)
58 increaseAmount = Params.MaxRadiation - Amount;
61 IncreaseRadiation(increaseAmount);
63 int amountOfOutposts = Map.Locations.Count(location => location.Type.HasOutpost && !location.IsCriticallyRadiated());
65 foreach (Location location
in Map.Locations.Where(Contains))
67 if (location.IsGateBetweenBiomes)
69 location.Connections.ForEach(c => c.Locked =
false);
73 if (amountOfOutposts <= Params.MinimumOutpostAmount) {
break; }
75 if (Map.CurrentLocation is { } currLocation)
78 if (currLocation == location || currLocation.Connections.Any(lc => lc.OtherLocation(currLocation) == location)) {
continue; }
81 bool wasCritical = location.IsCriticallyRadiated();
83 location.TurnsInRadiation++;
85 if (location.Type.HasOutpost && !wasCritical && location.IsCriticallyRadiated())
87 location.ClearMissions();
93 public void IncreaseRadiation(
float amount)
96 increasedAmount = lastIncrease = amount;
101 public void UpdateRadiation(
float deltaTime)
103 if (!(GameMain.GameSession?.IsCurrentLocationRadiated() ??
false)) {
return; }
105 if (GameMain.NetworkMember is { IsClient: true }) {
return; }
107 if (radiationTimer > 0)
109 radiationTimer -= deltaTime;
113 if (radiationAffliction ==
null)
115 float radiationStrengthChange = AfflictionPrefab.RadiationSickness.Effects.FirstOrDefault()?.StrengthChange ?? 0.0f;
117 AfflictionPrefab.RadiationSickness,
118 (Params.RadiationDamageAmount - radiationStrengthChange) * Params.RadiationDamageDelay);
121 radiationTimer = Params.RadiationDamageDelay;
123 foreach (Character character
in Character.CharacterList)
125 if (character.IsDead || character.Removed || !(character.CharacterHealth is { } health)) {
continue; }
127 if (IsEntityRadiated(character))
129 var limb = character.AnimController.MainLimb;
130 AttackResult attackResult = limb.AddDamage(limb.SimPosition, radiationAffliction.ToEnumerable(), playSound:
false);
131 character.CharacterHealth.ApplyDamage(limb, attackResult);
136 public bool Contains(Location location)
138 return Contains(location.MapPosition);
141 public bool Contains(Vector2 pos)
143 return pos.X < Amount;
146 public bool IsEntityRadiated(Entity entity)
148 if (!Enabled) {
return false; }
149 if (Level.Loaded is { Type: LevelData.LevelType.LocationConnection, StartLocation: { } startLocation, EndLocation: { } endLocation } level)
151 if (Contains(startLocation) && Contains(endLocation)) {
return true; }
153 float distance = MathHelper.Clamp((entity.WorldPosition.X - level.StartPosition.X) / (level.EndPosition.X - level.StartPosition.X), 0.0f, 1.0f);
154 var (startX, startY) = startLocation.MapPosition;
155 var (endX, endY) = endLocation.MapPosition;
156 Vector2 mapPos =
new Vector2(startX + (endX - startX), startY + (endY - startY)) * distance;
158 return Contains(mapPos);
164 public XElement Save()
166 XElement element =
new XElement(nameof(Radiation));
167 SerializableProperty.SerializeProperties(
this, element, saveIfDefault:
true);
@ Character
Characters only