4 using FarseerPhysics.Dynamics;
5 using Microsoft.Xna.Framework;
6 using Microsoft.Xna.Framework.Graphics;
8 using System.Collections.Generic;
10 using System.Xml.Linq;
15 partial class Sprayer : RangedWeapon, IDrawableComponent
18 private Vector2 debugRayStartPos, debugRayEndPos;
23 get {
return Vector2.Zero; }
26 private readonly List<ParticleEmitter> particleEmitters =
new List<ParticleEmitter>();
27 private Hull targetHull;
29 private Vector2 rayStartWorldPosition;
37 foreach (var subElement
in element.
Elements())
39 switch (subElement.Name.ToString().ToLowerInvariant())
41 case "particleemitter":
48 private readonly List<BackgroundSection> targetSections =
new List<BackgroundSection>();
51 private int spraySetting = 0;
52 private readonly Point[] sprayArray =
new Point[8];
69 targetSections.Clear();
83 targetSections.Clear();
92 if (
Submarine.
PickBody(sourcePos, barrelPos, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall) ==
null)
100 targetSections.Clear();
105 Vector2 rayEnd = ConvertUnits.ToSimUnits(pos);
106 rayStartWorldPosition = ConvertUnits.ToDisplayUnits(rayStart);
108 if (Vector2.Distance(rayStartWorldPosition, pos) >
Range)
111 targetSections.Clear();
116 debugRayStartPos = ConvertUnits.ToDisplayUnits(rayStart);
117 debugRayEndPos = ConvertUnits.ToDisplayUnits(rayEnd);
121 if (parentSub !=
null)
127 var obstacles =
Submarine.
PickBodies(rayStart, rayEnd, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall);
128 foreach (var body
in obstacles)
132 var door =
item.GetComponent<
Door>();
133 if (door !=
null && (door.IsOpen || door.IsBroken)) {
continue; }
137 targetSections.Clear();
142 if (targetHull ==
null)
144 targetSections.Clear();
150 if (mousedOverSection ==
null)
152 targetSections.Clear();
157 if (targetSections.Count > 0 && mousedOverSection == targetSections[0])
162 targetSections.Clear();
164 targetSections.Add(mousedOverSection);
165 int mousedOverIndex = mousedOverSection.
Index;
168 if (spraySetting > 0)
170 sprayArray[0].X = mousedOverIndex + 1;
171 sprayArray[0].Y = mousedOverSection.
RowIndex;
174 sprayArray[1].Y = mousedOverSection.
RowIndex + 1;
176 sprayArray[2].X = sprayArray[1].X + 1;
177 sprayArray[2].Y = sprayArray[1].Y;
179 for (
int i = 0; i < 3; i++)
188 if (spraySetting == 2)
190 sprayArray[3].X = mousedOverIndex - 1;
191 sprayArray[3].Y = mousedOverSection.
RowIndex;
193 sprayArray[4].X = sprayArray[1].X - 1;
194 sprayArray[4].Y = sprayArray[1].Y;
197 sprayArray[5].Y = sprayArray[3].Y - 1;
199 sprayArray[6].X = sprayArray[5].X + 1;
200 sprayArray[6].Y = sprayArray[5].Y;
202 sprayArray[7].X = sprayArray[6].X + 1;
203 sprayArray[7].Y = sprayArray[6].Y;
205 for (
int i = 3; i < sprayArray.Length; i++)
219 GUI.HideCursor = targetSections.Count > 0;
224 if (character ==
null) {
return false; }
227 Spray(character, deltaTime, applyColors: targetSections.Count > 0);
233 Spray(character, deltaTime, applyColors:
false);
241 if (liquidItem ==
null) {
return; }
243 bool isCleaning =
false;
246 if (applyColors && targetSections.Any())
249 if (color.A == 0) { isCleaning =
true; }
250 float sizeAdjustedSprayStrength =
SprayStrength / targetSections.Count;
253 for (
int i = 0; i < targetSections.Count; i++)
264 for (
int i = 0; i < targetSections.Count; i++)
266 targetHull.
CleanSection(targetSections[i], -sizeAdjustedSprayStrength * deltaTime,
true);
279 float dist = Math.Min(Vector2.Distance(particleStartPos, particleEndPos),
Range * 0.5f);
284 particleEmitter.
Emit(
285 deltaTime, particleStartPos,
287 colorMultiplier:
new Color(color.R, color.G, color.B, (
byte)255));
291 public void Draw(SpriteBatch spriteBatch,
bool editing,
float itemDepth = -1, Color? overrideColor =
null)
296 GUI.DrawLine(spriteBatch,
297 new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
298 new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
305 Point sectionSize = targetSections[0].Rect.Size;
306 Rectangle drawPositionRect =
new Rectangle((
int)(drawOffset.X + targetHull.
Rect.X), (
int)(drawOffset.Y + targetHull.
Rect.Y), sectionSize.X, sectionSize.Y);
310 for (
int i = 0; i < targetSections.Count; i++)
312 GUI.DrawRectangle(spriteBatch,
new Vector2(drawPositionRect.X + targetSections[i].Rect.X, -(drawPositionRect.Y + targetSections[i].Rect.Y)),
new Vector2(sectionSize.X, sectionSize.Y), Color.White,
false, 0.0f, 1);
315 else if (targetSections.Count > 0)
317 Vector2 drawPos = Vector2.Zero;
318 for (
int i = 0; i < targetSections.Count; i++)
320 drawPos +=
new Vector2(drawPositionRect.X + targetSections[i].Rect.X + sectionSize.X / 2, -(drawPositionRect.Y + targetSections[i].Rect.Y - sectionSize.Y / 2));
322 drawPos /= targetSections.Count;
324 crosshairPointerSprite?.Draw(spriteBatch, drawPos, scale: sectionSize.X * (spraySetting + 1) / crosshairPointerSprite.size.X);
virtual Vector2 AimSourceSimPos
Vector2? CursorWorldPosition
bool HasEquippedItem(Item item, InvSlotType? slotType=null, Func< InvSlotType, bool > predicate=null)
static Character? Controlled
bool IsKeyDown(InputType inputType)
readonly AnimController AnimController
float GetAttributeFloat(string key, float def)
IEnumerable< ContentXElement > Elements()
static GameSession?? GameSession
void IncreaseSectionColorOrStrength(BackgroundSection section, Color? color, float? strength, bool requiresUpdate, bool isCleaning)
BackgroundSection GetBackgroundSection(Vector2 worldPosition)
static Hull GetCleanTarget(Vector2 worldPosition)
bool DoesSectionMatch(int index, int row)
List< BackgroundSection > BackgroundSections
void CleanSection(BackgroundSection section, float cleanVal, bool updateRequired)
Item FirstOrDefault()
Return the first item in the inventory, or null if the inventory is empty.
override Vector2? SimPosition
readonly ItemInventory Inventory
Vector2? TransformedBarrelPos
override void DrawHUD(SpriteBatch spriteBatch, Character character)
void Spray(Character user, float deltaTime, bool applyColors)
override void UpdateHUDComponentSpecific(Character character, float deltaTime, Camera cam)
void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth=-1, Color? overrideColor=null)
override bool Use(float deltaTime, Character character=null)
readonly ParticleEmitterPrefab Prefab
void Emit(float deltaTime, Vector2 position, Hull? hullGuess=null, float angle=0.0f, float particleRotation=0.0f, float velocityMultiplier=1.0f, float sizeMultiplier=1.0f, float amountMultiplier=1.0f, Color? colorMultiplier=null, ParticlePrefab? overrideParticle=null, bool mirrorAngle=false, Tuple< Vector2, Vector2 >? tracerPoints=null)
ParticlePrefab? ParticlePrefab
readonly ParticleEmitterProperties Properties
readonly Identifier Identifier
void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate=0.0f, float scale=1.0f, SpriteEffects spriteEffect=SpriteEffects.None)
static IEnumerable< Body > PickBodies(Vector2 rayStart, Vector2 rayEnd, IEnumerable< Body > ignoredBodies=null, Category? collisionCategory=null, bool ignoreSensors=true, Predicate< Fixture > customPredicate=null, bool allowInsideFixture=false)
Returns a list of physics bodies the ray intersects with, sorted according to distance (the closest b...
override Vector2 SimPosition
static Body PickBody(Vector2 rayStart, Vector2 rayEnd, IEnumerable< Body > ignoredBodies=null, Category? collisionCategory=null, bool ignoreSensors=true, Predicate< Fixture > customPredicate=null, bool allowInsideFixture=false)