Spark & smoke particle effects when welding or cutting something. Closes #155.

This commit is contained in:
Joonas Rikkonen
2018-02-12 11:20:25 +02:00
parent 3cbff6bd7b
commit 43d6ee5e06
5 changed files with 276 additions and 41 deletions
@@ -21,7 +21,7 @@ namespace Barotrauma.Particles
Prefab = prefab; Prefab = prefab;
} }
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null) public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f)
{ {
emitTimer += deltaTime; emitTimer += deltaTime;
@@ -30,23 +30,23 @@ namespace Barotrauma.Particles
float emitInterval = 1.0f / Prefab.ParticlesPerSecond; float emitInterval = 1.0f / Prefab.ParticlesPerSecond;
while (emitTimer > emitInterval) while (emitTimer > emitInterval)
{ {
Emit(position, hullGuess); Emit(position, hullGuess, angle, particleRotation);
emitTimer -= emitInterval; emitTimer -= emitInterval;
} }
} }
for (int i = 0; i < Prefab.ParticleAmount; i++) for (int i = 0; i < Prefab.ParticleAmount; i++)
{ {
Emit(position, hullGuess); Emit(position, hullGuess, particleRotation);
} }
} }
private void Emit(Vector2 position, Hull hullGuess = null) private void Emit(Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f)
{ {
float angle = Rand.Range(Prefab.AngleMin, Prefab.AngleMax); angle += Rand.Range(Prefab.AngleMin, Prefab.AngleMax);
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Rand.Range(Prefab.VelocityMin, Prefab.VelocityMax); Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Rand.Range(Prefab.VelocityMin, Prefab.VelocityMax);
var particle = GameMain.ParticleManager.CreateParticle(Prefab.ParticlePrefab, position, velocity, 0.0f, hullGuess); var particle = GameMain.ParticleManager.CreateParticle(Prefab.ParticlePrefab, position, velocity, particleRotation, hullGuess);
if (particle != null) if (particle != null)
{ {
@@ -28,6 +28,13 @@
<!-- the item must contain a welding fuel tank for it to work --> <!-- the item must contain a welding fuel tank for it to work -->
<RequiredItems name="Welding Fuel Tank" type="Contained" msg="Welding fuel required"/> <RequiredItems name="Welding Fuel Tank" type="Contained" msg="Welding fuel required"/>
<ParticleEmitter particle="weld" particlespersecond="50"/>
<ParticleEmitterHitStructure particle="weldspark" particlespersecond="100" anglemin="-40" anglemax="40" velocitymin="100" velocitymax="800"/>
<ParticleEmitterHitItem particle="weldspark" particlespersecond="100" anglemin="-40" anglemax="40" velocitymin="100" velocitymax="800"/>
<ParticleEmitterHitStructure particle="weldsmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="20"/>
<ParticleEmitterHitItem particle="weldsmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="100"/>
<ParticleEmitterHitCharacter particle="fleshsmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="100"/>
<sound file="weldingTool.ogg" type="OnUse" range="500.0" loop="true"/> <sound file="weldingTool.ogg" type="OnUse" range="500.0" loop="true"/>
<!-- when using, the contained welding fuel tank will detoriate (= lose fuel) --> <!-- when using, the contained welding fuel tank will detoriate (= lose fuel) -->
@@ -77,11 +84,18 @@
<Holdable slots="Any,RightHand+LeftHand" controlpose="true" <Holdable slots="Any,RightHand+LeftHand" controlpose="true"
aimpos="50,0" handle1="-12,4"/> aimpos="50,0" handle1="-12,4"/>
<RepairTool structurefixamount="-2.0" limbfixamount="-0.5" range="100" barrelpos="28,8" particles="plasma"> <RepairTool structurefixamount="-2.0" limbfixamount="-0.5" range="100" barrelpos="28,8">
<RequiredItems name="Oxygen Tank" type="Contained" msg="Oxygen tank required"/> <RequiredItems name="Oxygen Tank" type="Contained" msg="Oxygen tank required"/>
<StatusEffect type="OnUse" target="Contained" targetnames="Oxygen Tank" Condition="-1.0"/> <StatusEffect type="OnUse" target="Contained" targetnames="Oxygen Tank" Condition="-1.0"/>
<StatusEffect type="OnUse" target="UseTarget" targetnames="Door,Windowed Door" Stuck="-20.0" Condition="-3.0"/> <StatusEffect type="OnUse" target="UseTarget" targetnames="Door,Windowed Door" Stuck="-20.0" Condition="-3.0"/>
<ParticleEmitter particle="plasma" particlespersecond="50"/>
<ParticleEmitterHitStructure particle="plasmaspark" particlespersecond="100" anglemin="-40" anglemax="40" velocitymin="100" velocitymax="800"/>
<ParticleEmitterHitItem particle="plasmaspark" particlespersecond="100" anglemin="-40" anglemax="40" velocitymin="100" velocitymax="800"/>
<ParticleEmitterHitStructure particle="plasmasmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="20"/>
<ParticleEmitterHitItem particle="plasmasmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="100"/>
<ParticleEmitterHitCharacter particle="fleshsmoke" particlespersecond="3" anglemin="-5" anglemax="5" velocitymin="10" velocitymax="100"/>
<sound file="plasmaCutter.ogg" type="OnUse" range="500.0" loop="true"/> <sound file="plasmaCutter.ogg" type="OnUse" range="500.0" loop="true"/>
<Fixable name="structure"/> <Fixable name="structure"/>
@@ -144,7 +158,8 @@
<Holdable slots="Any,RightHand+LeftHand" controlpose="false" <Holdable slots="Any,RightHand+LeftHand" controlpose="false"
aimpos="40,-20" handle1="-2,30"/> aimpos="40,-20" handle1="-2,30"/>
<RepairTool extinquishamount="30.0" range="300" barrelpos="21,25" particles="extinguisher" particlespeed="650.0"> <RepairTool extinquishamount="60.0" range="500" barrelpos="21,25">
<ParticleEmitter particle="extinguisher" velocitymin="500.0" velocitymax="650.0" particlespersecond="50"/>
<StatusEffect type="OnUse" target="This" Condition="-2.0"/> <StatusEffect type="OnUse" target="This" Condition="-2.0"/>
<sound file="extinguisher.ogg" type="OnUse" range="500.0" loop="true"/> <sound file="extinguisher.ogg" type="OnUse" range="500.0" loop="true"/>
</RepairTool> </RepairTool>
@@ -375,6 +375,68 @@
<sprite texture="Content/Particles/flames.png" sourcerect="0,0,128,64" origin="0.15,0.5"/> <sprite texture="Content/Particles/flames.png" sourcerect="0,0,128,64" origin="0.15,0.5"/>
</weld> </weld>
<weldspark
lifetime="1"
angularvelocitymin="0"
angularvelocitymax="0"
startrotationmin="0"
startrotationmax="360"
rotatetodirection="True"
drag="0"
waterdrag="0"
velocitychange="0,-5"
velocitychangewater="0,-5"
collisionradius="1"
collideswithwalls="False"
deleteoncollision="True"
friction="0.5"
restitution="0.5"
startsizemin="0.2,0.2"
startsizemax="0.5,0.2"
sizechangemin="-0.5,-0.5"
sizechangemax="-1,-1"
growtime="0.1"
startcolor="1,0.76,0.39,1"
startalpha="1"
colorchange="0,0,0,-0.3"
drawtarget="Both"
blendstate="Additive"
animduration="1"
loopanim="True">
<sprite texture="Content/Particles/explosion.png" sourcerect="128,0,128,64"/>
</weldspark>
<weldsmoke
lifetime="3"
angularvelocitymin="0"
angularvelocitymax="0"
startrotationmin="0"
startrotationmax="360"
rotatetodirection="False"
drag="0"
waterdrag="0"
velocitychange="0,0.2"
velocitychangewater="0,0.2"
collisionradius="1"
collideswithwalls="False"
deleteoncollision="False"
friction="0.5"
restitution="0.5"
startsizemin="0.1,0.1"
startsizemax="0.2,0.2"
sizechangemin="0.1,0.1"
sizechangemax="0.1,0.1"
growtime="0.1"
startcolor="1,1,1,1"
startalpha="1"
colorchange="-0.3,-0.3,-0.3,-0.2"
drawtarget="Both"
blendstate="AlphaBlend"
animduration="3"
loopanim="True">
<animatedsprite texture="Content/Particles/Smoke.png" sourcerect="0,0,4096,4096" columns="8" rows="8" origin="0.5,0.5"/>
</weldsmoke>
<plasma <plasma
startsizemin="0.9,0.9" startsizemax="1.1,1.1" startsizemin="0.9,0.9" startsizemax="1.1,1.1"
sizechange="-4.0,-0.5" sizechange="-4.0,-0.5"
@@ -387,6 +449,68 @@
<sprite texture="Content/Particles/flames.png" sourcerect="0,64,128,64" origin="0.15,0.5"/> <sprite texture="Content/Particles/flames.png" sourcerect="0,64,128,64" origin="0.15,0.5"/>
</plasma> </plasma>
<plasmaspark
lifetime="1"
angularvelocitymin="0"
angularvelocitymax="0"
startrotationmin="0"
startrotationmax="360"
rotatetodirection="True"
drag="0"
waterdrag="0"
velocitychange="0,-2"
velocitychangewater="0,-2"
collisionradius="1"
collideswithwalls="False"
deleteoncollision="True"
friction="0.5"
restitution="0.5"
startsizemin="0.2,0.2"
startsizemax="0.5,0.4"
sizechangemin="-0.5,-0.5"
sizechangemax="-1,-1"
growtime="0.1"
startcolor="0.1960784,1,1,1"
startalpha="1"
colorchange="2,-2,-3,-0.3"
drawtarget="Both"
blendstate="Additive"
animduration="1"
loopanim="True">
<sprite texture="Content/Particles/explosion.png" sourcerect="128,0,128,64"/>
</plasmaspark>
<plasmasmoke
lifetime="3"
angularvelocitymin="0"
angularvelocitymax="0"
startrotationmin="0"
startrotationmax="360"
rotatetodirection="False"
drag="0"
waterdrag="0"
velocitychange="0,0.2"
velocitychangewater="0,0.2"
collisionradius="1"
collideswithwalls="False"
deleteoncollision="False"
friction="0.5"
restitution="0.5"
startsizemin="0.1,0.1"
startsizemax="0.2,0.2"
sizechangemin="0.1,0.1"
sizechangemax="0.1,0.1"
growtime="0.1"
startcolor="1,1,1,1"
startalpha="1"
colorchange="-0.5,-0.5,-0.45,-0.2"
drawtarget="Both"
blendstate="AlphaBlend"
animduration="3"
loopanim="True">
<animatedsprite texture="Content/Particles/Smoke.png" sourcerect="0,0,4096,4096" columns="8" rows="8" origin="0.5,0.5"/>
</plasmasmoke>
<largeplasma <largeplasma
startsizemin="0.9,3.0" startsizemax="5.0,5.0" startsizemin="0.9,3.0" startsizemax="5.0,5.0"
sizechange="20.0,-0.5" sizechange="20.0,-0.5"
@@ -399,6 +523,37 @@
<sprite texture="Content/Particles/flames.png" sourcerect="0,64,128,64" origin="0.0,0.5"/> <sprite texture="Content/Particles/flames.png" sourcerect="0,64,128,64" origin="0.0,0.5"/>
</largeplasma> </largeplasma>
<fleshsmoke
lifetime="3"
angularvelocitymin="0"
angularvelocitymax="0"
startrotationmin="0"
startrotationmax="360"
rotatetodirection="False"
drag="0"
waterdrag="0"
velocitychange="0,0.2"
velocitychangewater="0,0.2"
collisionradius="1"
collideswithwalls="False"
deleteoncollision="False"
friction="0.5"
restitution="0.5"
startsizemin="0.1,0.1"
startsizemax="0.2,0.2"
sizechangemin="0.1,0.1"
sizechangemax="0.1,0.1"
growtime="0.1"
startcolor="0.6,0.6,0.6,1"
startalpha="0.4"
colorchange="0,0,0,0"
drawtarget="Both"
blendstate="AlphaBlend"
animduration="3"
loopanim="True">
<animatedsprite texture="Content/Particles/Smoke.png" sourcerect="0,0,4096,4096" columns="8" rows="8" origin="0.5,0.5"/>
</fleshsmoke>
<extinguisher <extinguisher
startsizemin="1.2,1.2" startsizemax="1.5,1.5" startsizemin="1.2,1.2" startsizemax="1.5,1.5"
sizechangemin="1.5,1.5" sizechangemax="2.0,2.0" sizechangemin="1.5,1.5" sizechangemax="2.0,2.0"
@@ -493,4 +648,5 @@
<sprite texture="Content/Particles/shrapnel.png" sourcerect="224,96,32,32"/> <sprite texture="Content/Particles/shrapnel.png" sourcerect="224,96,32,32"/>
</iceshards> </iceshards>
</prefabs> </prefabs>
@@ -5,6 +5,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq; using System.Xml.Linq;
#if CLIENT
using Barotrauma.Particles;
#endif
namespace Barotrauma.Items.Components namespace Barotrauma.Items.Components
{ {
class RepairTool : ItemComponent class RepairTool : ItemComponent
@@ -45,18 +49,19 @@ namespace Barotrauma.Items.Components
get; set; get; set;
} }
[Serialize("", false)] #if CLIENT
public string Particles public ParticleEmitter ParticleEmitter
{ {
get { return particles; } get;
set { particles = value; } private set;
} }
[Serialize(0.0f, false)] private List<ParticleEmitter> ParticleEmitterHitStructure = new List<ParticleEmitter>();
public float ParticleSpeed
{ private List<ParticleEmitter> ParticleEmitterHitItem = new List<ParticleEmitter>();
get; set;
} private List<ParticleEmitter> ParticleEmitterHitCharacter = new List<ParticleEmitter>();
#endif
[Serialize("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 BarrelPos public Vector2 BarrelPos
@@ -89,6 +94,20 @@ namespace Barotrauma.Items.Components
case "fixable": case "fixable":
fixableEntities.Add(subElement.Attribute("name").Value); fixableEntities.Add(subElement.Attribute("name").Value);
break; break;
#if CLIENT
case "particleemitter":
ParticleEmitter = new ParticleEmitter(subElement);
break;
case "particleemitterhititem":
ParticleEmitterHitItem.Add(new ParticleEmitter(subElement));
break;
case "particleemitterhitstructure":
ParticleEmitterHitStructure.Add(new ParticleEmitter(subElement));
break;
case "particleemitterhitcharacter":
ParticleEmitterHitCharacter.Add(new ParticleEmitter(subElement));
break;
#endif
} }
} }
} }
@@ -144,8 +163,10 @@ namespace Barotrauma.Items.Components
} }
#if CLIENT #if CLIENT
GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition + TransformedBarrelPos, float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
-item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi), ParticleSpeed); ParticleEmitter.Emit(
deltaTime, item.WorldPosition + TransformedBarrelPos,
item.CurrentHull, particleAngle, -particleAngle);
#endif #endif
return true; return true;
@@ -191,10 +212,7 @@ namespace Barotrauma.Items.Components
#if CLIENT #if CLIENT
Vector2 progressBarPos = targetStructure.SectionPosition(sectionIndex); Vector2 progressBarPos = targetStructure.SectionPosition(sectionIndex);
if (targetStructure.Submarine != null) if (targetStructure.Submarine != null) progressBarPos += targetStructure.Submarine.DrawPosition;
{
progressBarPos += targetStructure.Submarine.DrawPosition;
}
var progressBar = user.UpdateHUDProgressBar( var progressBar = user.UpdateHUDProgressBar(
targetStructure, targetStructure,
@@ -203,6 +221,14 @@ namespace Barotrauma.Items.Components
Color.Red, Color.Green); Color.Red, Color.Green);
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f); if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
foreach (var emitter in ParticleEmitterHitStructure)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
#endif #endif
targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess,user); targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess,user);
@@ -224,12 +250,47 @@ namespace Barotrauma.Items.Components
else if ((targetLimb = (targetBody.UserData as Limb)) != null) else if ((targetLimb = (targetBody.UserData as Limb)) != null)
{ {
targetLimb.character.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, user); targetLimb.character.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, user);
#if CLIENT
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
if (targetLimb.character.Submarine != null) particlePos += targetLimb.character.Submarine.DrawPosition;
foreach (var emitter in ParticleEmitterHitCharacter)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
#endif
} }
else if ((targetItem = (targetBody.UserData as Item)) != null) else if ((targetItem = (targetBody.UserData as Item)) != null)
{ {
targetItem.IsHighlighted = true; targetItem.IsHighlighted = true;
ApplyStatusEffects(ActionType.OnUse, targetItem.AllPropertyObjects, deltaTime); float prevCondition = targetItem.Condition;
ApplyStatusEffectsOnTarget(deltaTime, ActionType.OnUse, targetItem.AllPropertyObjects);
#if CLIENT
if (item.Condition != prevCondition)
{
Vector2 progressBarPos = targetItem.DrawPosition;
var progressBar = user.UpdateHUDProgressBar(
targetItem,
progressBarPos,
targetItem.Condition / 100.0f,
Color.Red, Color.Green);
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
foreach (var emitter in ParticleEmitterHitItem)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
}
#endif
} }
} }
@@ -267,5 +328,21 @@ namespace Barotrauma.Items.Components
return leak.Open <= 0.0f; return leak.Open <= 0.0f;
} }
private void ApplyStatusEffectsOnTarget(float deltaTime, ActionType actionType, List<ISerializableEntity> targets)
{
if (statusEffectLists == null) return;
List<StatusEffect> statusEffects;
if (!statusEffectLists.TryGetValue(actionType, out statusEffects)) return;
foreach (StatusEffect effect in statusEffects)
{
if (effect.Targets.HasFlag(StatusEffect.TargetType.UseTarget))
{
effect.Apply(actionType, deltaTime, item, targets);
}
}
}
} }
} }
@@ -535,19 +535,6 @@ namespace Barotrauma.Items.Components
} }
} }
public void ApplyStatusEffects(ActionType type, List<ISerializableEntity> targets, float deltaTime)
{
if (statusEffectLists == null) return;
List<StatusEffect> statusEffects;
if (!statusEffectLists.TryGetValue(type, out statusEffects)) return;
foreach (StatusEffect effect in statusEffects)
{
effect.Apply(type, deltaTime, item, targets);
}
}
public virtual void Load(XElement componentElement) public virtual void Load(XElement componentElement)
{ {
if (componentElement == null) return; if (componentElement == null) return;