Multiple particle emitters can be be attached to a background sprite, hydrothermal vents push characters and subs upwards, tweaked hydrothermal smoke particles & trigger positioning
This commit is contained in:
@@ -8,7 +8,7 @@ namespace Barotrauma
|
||||
{
|
||||
partial class BackgroundSprite
|
||||
{
|
||||
public ParticleEmitter ParticleEmitter;
|
||||
public List<ParticleEmitter> ParticleEmitters;
|
||||
public Sound Sound;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,13 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (BackgroundSprite s in visibleSprites)
|
||||
{
|
||||
if (s.ParticleEmitter != null)
|
||||
if (s.ParticleEmitters != null)
|
||||
{
|
||||
Vector2 emitterPos = s.LocalToWorld(new Vector2(s.Prefab.EmitterPosition.X, s.Prefab.EmitterPosition.Y));
|
||||
s.ParticleEmitter.Emit(deltaTime, emitterPos);
|
||||
for (int i = 0; i < s.ParticleEmitters.Count; i++)
|
||||
{
|
||||
Vector2 emitterPos = s.LocalToWorld(s.Prefab.EmitterPositions[i]);
|
||||
s.ParticleEmitters[i].Emit(deltaTime, emitterPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.Sound != null)
|
||||
@@ -38,7 +41,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
s.Sound.UpdatePosition(soundPos);
|
||||
s.Sound.UpdatePosition(soundPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class BackgroundSpritePrefab
|
||||
{
|
||||
public readonly Particles.ParticleEmitterPrefab ParticleEmitterPrefab;
|
||||
public readonly Vector2 EmitterPosition;
|
||||
public readonly List<ParticleEmitterPrefab> ParticleEmitterPrefabs;
|
||||
public readonly List<Vector2> EmitterPositions;
|
||||
|
||||
public readonly XElement SoundElement;
|
||||
public readonly Vector2 SoundPosition;
|
||||
|
||||
@@ -107,15 +107,14 @@
|
||||
</icechunk>
|
||||
|
||||
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="2" randomrotation="-5,5" commonness="0">
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="1.2" randomrotation="-5,5" commonness="0">
|
||||
<overridecommonness commonness="1" leveltype="Wastes" />
|
||||
<overridecommonness commonness="3" leveltype="Ridge" />
|
||||
<Sprite texture="Content/BackgroundSprites/seafloor.png" sourcerect="0,443,455,1605" origin="0.5,0.9"/>
|
||||
<Sound file ="Content/Sounds/Water/BlackSmoker.ogg" range="7000" position="0,4000"/>
|
||||
<Trigger position="0,5500" radius="2000" height="10000" camerashake="5">
|
||||
<Attack damage="10.0" duration="1.0" targetforce="10.0" damagetype="Burn" onlyhumans="true"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger position="0,7000" radius="2000" height="10000" camerashake="5" force="0,500">
|
||||
<Attack damage="10.0" duration="1.0" damagetype="Burn" onlyhumans="true"/>
|
||||
</Trigger>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmoke"
|
||||
particlespersecond="4"
|
||||
@@ -124,14 +123,22 @@
|
||||
anglemax="100"
|
||||
velocitymin="500"
|
||||
velocitymax="2000"/>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmokesmall"
|
||||
particlespersecond="10"
|
||||
position="0,1400"
|
||||
anglemin="60"
|
||||
anglemax="120"
|
||||
velocitymin="100"
|
||||
velocitymax="600"/>
|
||||
</blacksmoker>
|
||||
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="2" randomrotation="-10,10" commonness="0">
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="1.2" randomrotation="-10,10" commonness="0">
|
||||
<overridecommonness commonness="1" leveltype="Wastes" />
|
||||
<Sprite texture="Content/BackgroundSprites/seafloor.png" sourcerect="463,1329,525,719" origin="0.5,0.9"/>
|
||||
<Sound file ="Content/Sounds/Water/BlackSmoker.ogg" range="7000" position="0,4000"/>
|
||||
<Trigger position="0,5500" radius="2000" height="10000" camerashake="5">
|
||||
<Attack damage="10.0" duration="1.0" targetforce="10.0" damagetype="Burn" onlyhumans="true"/>
|
||||
<Trigger position="0,7000" radius="2000" height="10000" camerashake="5" force="0,500">
|
||||
<Attack damage="10.0" duration="1.0" damagetype="Burn" onlyhumans="true"/>
|
||||
</Trigger>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmoke"
|
||||
@@ -141,14 +148,22 @@
|
||||
anglemax="100"
|
||||
velocitymin="500"
|
||||
velocitymax="2000"/>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmokesmall"
|
||||
particlespersecond="10"
|
||||
position="-20,570"
|
||||
anglemin="60"
|
||||
anglemax="120"
|
||||
velocitymin="100"
|
||||
velocitymax="600"/>
|
||||
</blacksmoker>
|
||||
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="2" randomrotation="-10,10" commonness="0">
|
||||
<blacksmoker spawnpos="SeaFloor" alignment="Top" minsize="1" maxsize="1.2" randomrotation="-10,10" commonness="0">
|
||||
<overridecommonness commonness="1" leveltype="Wastes" />
|
||||
<Sprite texture="Content/BackgroundSprites/seafloor.png" sourcerect="1030,1245,440,803" origin="0.5,0.9"/>
|
||||
<Sound file ="Content/Sounds/Water/BlackSmoker.ogg" range="7000" position="0,4000"/>
|
||||
<Trigger position="0,5500" radius="2000" height="10000" camerashake="5">
|
||||
<Attack damage="10.0" duration="1.0" targetforce="10.0" damagetype="Burn" onlyhumans="true"/>
|
||||
<Trigger position="0,7000" radius="2000" height="10000" camerashake="5" force="0,500">
|
||||
<Attack damage="10.0" duration="1.0" damagetype="Burn" onlyhumans="true"/>
|
||||
</Trigger>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmoke"
|
||||
@@ -158,5 +173,13 @@
|
||||
anglemax="100"
|
||||
velocitymin="500"
|
||||
velocitymax="2000"/>
|
||||
<ParticleEmitter
|
||||
particle="hydrosmokesmall"
|
||||
particlespersecond="10"
|
||||
position="-50,700"
|
||||
anglemin="60"
|
||||
anglemax="120"
|
||||
velocitymin="100"
|
||||
velocitymax="600"/>
|
||||
</blacksmoker>
|
||||
</backgroundsprites>
|
||||
@@ -177,6 +177,21 @@
|
||||
<sprite texture="Content/Particles/SmokeParticleSheet.png" sourcerect="819,410,204,204"/>
|
||||
</hydrosmoke>
|
||||
|
||||
<hydrosmokesmall
|
||||
startsizemin="2.0,2.0" startsizemax="5.0,5.0"
|
||||
sizechangemin="0.25,0.25" sizechangemax="0.3,0.3"
|
||||
startrotationmin ="0.0" startrotationmax="360"
|
||||
startcolor="0.2, 0.2, 0.2" startalpha="1.0"
|
||||
angularvelocitymin="-20" angularvelocitymax="20"
|
||||
colorchange="0.0, 0.0, 0.0, -0.16"
|
||||
growtime="1"
|
||||
lifetime="6"
|
||||
drawtarget="water"
|
||||
animduration="3"
|
||||
loopanim="false">
|
||||
<animatedsprite texture="Content/Particles/SmokeParticleSheet.png" sourcerect="0,0,1024,1024" columns="5" rows="5"/>
|
||||
</hydrosmokesmall>
|
||||
|
||||
<explosionfire
|
||||
startsizemin="0.25,0.15" startsizemax="0.5,0.25"
|
||||
sizechangemin="0.2,0.2" sizechangemax="0.3,0.3"
|
||||
|
||||
@@ -45,13 +45,17 @@ namespace Barotrauma
|
||||
-sa * triggerPosition.X + ca * triggerPosition.Y);
|
||||
}
|
||||
|
||||
this.Trigger = new LevelTrigger(prefab.LevelTriggerElement, new Vector2(position.X, position.Y) + triggerPosition, -rotation);
|
||||
this.Trigger = new LevelTrigger(prefab.LevelTriggerElement, new Vector2(position.X, position.Y) + triggerPosition, -rotation, scale);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (prefab.ParticleEmitterPrefab != null)
|
||||
if (prefab.ParticleEmitterPrefabs != null)
|
||||
{
|
||||
this.ParticleEmitter = new ParticleEmitter(prefab.ParticleEmitterPrefab);
|
||||
ParticleEmitters = new List<ParticleEmitter>();
|
||||
foreach (ParticleEmitterPrefab emitterPrefab in prefab.ParticleEmitterPrefabs)
|
||||
{
|
||||
ParticleEmitters.Add(new ParticleEmitter(emitterPrefab));
|
||||
}
|
||||
}
|
||||
|
||||
if (prefab.SoundElement != null)
|
||||
@@ -172,34 +176,44 @@ namespace Barotrauma
|
||||
spriteCorners[j] += pos.Value + pivotOffset;
|
||||
}
|
||||
|
||||
float minX = spriteCorners.Min(c => c.X) - newSprite.Position.Z;
|
||||
float maxX = spriteCorners.Max(c => c.X) + newSprite.Position.Z;
|
||||
|
||||
float minY = spriteCorners.Min(c => c.Y) - newSprite.Position.Z - level.BottomPos;
|
||||
float maxY = spriteCorners.Max(c => c.Y) + newSprite.Position.Z - level.BottomPos;
|
||||
|
||||
#if CLIENT
|
||||
if (newSprite.ParticleEmitter != null)
|
||||
if (newSprite.ParticleEmitters != null)
|
||||
{
|
||||
Rectangle particleBounds = newSprite.ParticleEmitter.CalculateParticleBounds(pos.Value);
|
||||
spriteCorners.Add(particleBounds.Location.ToVector2());
|
||||
spriteCorners.Add(new Vector2(particleBounds.Right, particleBounds.Bottom));
|
||||
foreach (ParticleEmitter emitter in newSprite.ParticleEmitters)
|
||||
{
|
||||
Rectangle particleBounds = emitter.CalculateParticleBounds(pos.Value);
|
||||
minX = Math.Min(minX, particleBounds.X);
|
||||
maxX = Math.Max(maxX, particleBounds.Right);
|
||||
minY = Math.Min(minY, particleBounds.Y - level.BottomPos);
|
||||
maxY = Math.Max(maxY, particleBounds.Bottom - level.BottomPos);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sprites.Add(newSprite);
|
||||
|
||||
int minX = (int)Math.Floor((spriteCorners.Min(c => c.X) - newSprite.Position.Z) / GridSize);
|
||||
int maxX = (int)Math.Floor((spriteCorners.Max(c => c.X) + newSprite.Position.Z) / GridSize);
|
||||
int xStart = (int)Math.Floor(minX / GridSize);
|
||||
int xEnd = (int)Math.Floor(maxX / GridSize);
|
||||
if (xEnd < 0 || xStart >= spriteGrid.GetLength(0)) continue;
|
||||
|
||||
if (maxX < 0 || minX >= spriteGrid.GetLength(0)) continue;
|
||||
int yStart = (int)Math.Floor(minY / GridSize);
|
||||
int yEnd = (int)Math.Floor(maxY / GridSize);
|
||||
if (yEnd < 0 || yStart >= spriteGrid.GetLength(1)) continue;
|
||||
|
||||
int minY = (int)Math.Floor((spriteCorners.Min(c => c.Y) - newSprite.Position.Z - level.BottomPos) / GridSize);
|
||||
int maxY = (int)Math.Floor((spriteCorners.Max(c => c.Y) + newSprite.Position.Z - level.BottomPos) / GridSize);
|
||||
if (maxY < 0 || minY >= spriteGrid.GetLength(1)) continue;
|
||||
xStart = Math.Max(xStart, 0);
|
||||
xEnd = Math.Min(xEnd, spriteGrid.GetLength(0) - 1);
|
||||
yStart = Math.Max(yStart, 0);
|
||||
yEnd = Math.Min(yEnd, spriteGrid.GetLength(1) - 1);
|
||||
|
||||
minX = Math.Max(minX, 0);
|
||||
maxX = Math.Min(maxX, spriteGrid.GetLength(0) - 1);
|
||||
minY = Math.Max(minY, 0);
|
||||
maxY = Math.Min(maxY, spriteGrid.GetLength(1) - 1);
|
||||
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
for (int x = xStart; x <= xEnd; x++)
|
||||
{
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
for (int y = yStart; y <= yEnd; y++)
|
||||
{
|
||||
if (spriteGrid[x, y] == null) spriteGrid[x, y] = new List<BackgroundSprite>();
|
||||
spriteGrid[x, y].Add(newSprite);
|
||||
|
||||
@@ -94,8 +94,14 @@ namespace Barotrauma
|
||||
break;
|
||||
#if CLIENT
|
||||
case "particleemitter":
|
||||
ParticleEmitterPrefab = new Particles.ParticleEmitterPrefab(subElement);
|
||||
EmitterPosition = ToolBox.GetAttributeVector2(subElement, "position", Vector2.Zero);
|
||||
if (ParticleEmitterPrefabs == null)
|
||||
{
|
||||
ParticleEmitterPrefabs = new List<Particles.ParticleEmitterPrefab>();
|
||||
EmitterPositions = new List<Vector2>();
|
||||
}
|
||||
|
||||
ParticleEmitterPrefabs.Add(new Particles.ParticleEmitterPrefab(subElement));
|
||||
EmitterPositions.Add(ToolBox.GetAttributeVector2(subElement, "position", Vector2.Zero));
|
||||
break;
|
||||
case "sound":
|
||||
SoundElement = subElement;
|
||||
|
||||
@@ -25,9 +25,11 @@ namespace Barotrauma
|
||||
|
||||
private float cameraShake;
|
||||
|
||||
private Vector2 force;
|
||||
|
||||
public Vector2 WorldPosition
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(physicsBody.Position); }
|
||||
get { return physicsBody.Position; }
|
||||
set { physicsBody.SetTransform(ConvertUnits.ToSimUnits(value), physicsBody.Rotation); }
|
||||
}
|
||||
|
||||
@@ -56,6 +58,8 @@ namespace Barotrauma
|
||||
physicsBody.SetTransform(ConvertUnits.ToSimUnits(position), rotation);
|
||||
|
||||
cameraShake = ToolBox.GetAttributeFloat(element, "camerashake", 0.0f);
|
||||
|
||||
force = ToolBox.GetAttributeVector2(element, "force", Vector2.Zero);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -110,6 +114,7 @@ namespace Barotrauma
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
triggerers.RemoveAll(t => t.Removed);
|
||||
foreach (Entity triggerer in triggerers)
|
||||
{
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
@@ -133,6 +138,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (force != Vector2.Zero)
|
||||
{
|
||||
if (triggerer is Character)
|
||||
{
|
||||
((Character)triggerer).AnimController.Collider.ApplyForce(force * deltaTime);
|
||||
}
|
||||
else if (triggerer is Submarine)
|
||||
{
|
||||
((Submarine)triggerer).ApplyForce(force * deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerer == Character.Controlled || triggerer == Character.Controlled?.Submarine)
|
||||
{
|
||||
GameMain.GameScreen.Cam.Shake = Math.Max(GameMain.GameScreen.Cam.Shake, cameraShake);
|
||||
|
||||
@@ -368,15 +368,15 @@ namespace Barotrauma
|
||||
body.ApplyTorque(torque);
|
||||
}
|
||||
|
||||
public void SetTransform(Vector2 position, float rotation)
|
||||
public void SetTransform(Vector2 simPosition, float rotation)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(MathUtils.IsValid(position));
|
||||
System.Diagnostics.Debug.Assert(Math.Abs(position.X) < 1000000.0f);
|
||||
System.Diagnostics.Debug.Assert(Math.Abs(position.Y) < 1000000.0f);
|
||||
System.Diagnostics.Debug.Assert(MathUtils.IsValid(simPosition));
|
||||
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.X) < 1000000.0f);
|
||||
System.Diagnostics.Debug.Assert(Math.Abs(simPosition.Y) < 1000000.0f);
|
||||
|
||||
|
||||
body.SetTransform(position, rotation);
|
||||
SetPrevTransform(position, rotation);
|
||||
body.SetTransform(simPosition, rotation);
|
||||
SetPrevTransform(simPosition, rotation);
|
||||
}
|
||||
|
||||
public void SetPrevTransform(Vector2 position, float rotation)
|
||||
|
||||
Reference in New Issue
Block a user