- Hitscan projectiles, projectiles can be set to disappear after hitting something.
- Option to adjust ranged weapon spread (separate values for "normal spread" and when being used by an unskilled character). - Option to disable explosion flashes.
This commit is contained in:
@@ -42,12 +42,14 @@ namespace Barotrauma
|
|||||||
hull.AddDecal(decal, worldPosition, decalSize);
|
hull.AddDecal(decal, worldPosition, decalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
float displayRange = attack.Range;
|
if (flash)
|
||||||
if (displayRange < 0.1f) return;
|
{
|
||||||
|
float displayRange = attack.Range;
|
||||||
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
|
if (displayRange < 0.1f) return;
|
||||||
CoroutineManager.StartCoroutine(DimLight(light));
|
|
||||||
|
|
||||||
|
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
|
||||||
|
CoroutineManager.StartCoroutine(DimLight(light));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<object> DimLight(LightSource light)
|
private IEnumerable<object> DimLight(LightSource light)
|
||||||
|
|||||||
@@ -27,6 +27,20 @@ namespace Barotrauma.Items.Components
|
|||||||
set { reload = Math.Max(value, 0.0f); }
|
set { reload = Math.Max(value, 0.0f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(0.0f, false)]
|
||||||
|
public float Spread
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(0.0f, false)]
|
||||||
|
public float UnskilledSpread
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2 TransformedBarrelPos
|
public Vector2 TransformedBarrelPos
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -41,8 +55,6 @@ namespace Barotrauma.Items.Components
|
|||||||
public RangedWeapon(Item item, XElement element)
|
public RangedWeapon(Item item, XElement element)
|
||||||
: base(item, element)
|
: base(item, element)
|
||||||
{
|
{
|
||||||
//barrelPos = ToolBox.GetAttributeVector2(element, "barrelpos", Vector2.Zero);
|
|
||||||
//barrelPos = ConvertUnits.ToSimUnits(barrelPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime, Camera cam)
|
public override void Update(float deltaTime, Camera cam)
|
||||||
@@ -90,13 +102,16 @@ namespace Barotrauma.Items.Components
|
|||||||
Projectile projectileComponent= projectile.GetComponent<Projectile>();
|
Projectile projectileComponent= projectile.GetComponent<Projectile>();
|
||||||
if (projectileComponent == null) continue;
|
if (projectileComponent == null) continue;
|
||||||
|
|
||||||
float rotation = ((item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi) + Rand.Range(-degreeOfFailure, degreeOfFailure);
|
float spread = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
|
||||||
|
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
|
||||||
|
rotation += spread * Rand.Range(-0.5f, 0.5f);
|
||||||
|
|
||||||
projectile.body.ResetDynamics();
|
projectile.body.ResetDynamics();
|
||||||
projectile.SetTransform(TransformedBarrelPos, rotation);
|
projectile.SetTransform(TransformedBarrelPos, rotation);
|
||||||
|
projectileComponent.User = character;
|
||||||
|
projectileComponent.IgnoredBodies = new List<Body>(limbBodies);
|
||||||
|
|
||||||
projectile.Use(deltaTime);
|
projectile.Use(deltaTime);
|
||||||
projectileComponent.User = character;
|
|
||||||
|
|
||||||
projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
||||||
|
|
||||||
@@ -105,9 +120,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
//recoil
|
//recoil
|
||||||
item.body.ApplyLinearImpulse(
|
item.body.ApplyLinearImpulse(
|
||||||
new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f);
|
new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f);
|
||||||
|
|
||||||
projectileComponent.IgnoredBodies = limbBodies;
|
|
||||||
|
|
||||||
item.RemoveContained(projectile);
|
item.RemoveContained(projectile);
|
||||||
|
|
||||||
@@ -118,9 +131,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,20 @@ namespace Barotrauma.Items.Components
|
|||||||
set { doesStick = value; }
|
set { doesStick = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(false, false)]
|
||||||
|
public bool Hitscan
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HasDefaultValue(false, false)]
|
||||||
|
public bool RemoveOnHit
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public Projectile(Item item, XElement element)
|
public Projectile(Item item, XElement element)
|
||||||
: base (item, element)
|
: base (item, element)
|
||||||
{
|
{
|
||||||
@@ -60,11 +74,18 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
if (character != null && !characterUsable) return false;
|
if (character != null && !characterUsable) return false;
|
||||||
|
|
||||||
User = character;
|
Vector2 launchDir = new Vector2((float)Math.Cos(item.body.Rotation), (float)Math.Sin(item.body.Rotation));
|
||||||
|
|
||||||
Launch(new Vector2(
|
if (Hitscan)
|
||||||
(float)Math.Cos(item.body.Rotation),
|
{
|
||||||
(float)Math.Sin(item.body.Rotation)) * launchImpulse * item.body.Mass);
|
DoHitscan(launchDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Launch(launchDir * launchImpulse * item.body.Mass);
|
||||||
|
}
|
||||||
|
|
||||||
|
User = character;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -73,7 +94,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
item.Drop();
|
item.Drop();
|
||||||
|
|
||||||
item.body.Enabled = true;
|
item.body.Enabled = true;
|
||||||
item.body.ApplyLinearImpulse(impulse);
|
item.body.ApplyLinearImpulse(impulse);
|
||||||
|
|
||||||
item.body.FarseerBody.OnCollision += OnProjectileCollision;
|
item.body.FarseerBody.OnCollision += OnProjectileCollision;
|
||||||
@@ -104,12 +125,52 @@ namespace Barotrauma.Items.Components
|
|||||||
GameMain.World.RemoveJoint(stickJoint);
|
GameMain.World.RemoveJoint(stickJoint);
|
||||||
stickJoint = null;
|
stickJoint = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DoHitscan(Vector2 dir)
|
||||||
|
{
|
||||||
|
float rotation = item.body.Rotation;
|
||||||
|
item.Drop();
|
||||||
|
|
||||||
|
item.body.Enabled = true;
|
||||||
|
//set the velocity of the body because the OnProjectileCollision method
|
||||||
|
//uses it to determine the direction from which the projectile hit
|
||||||
|
item.body.LinearVelocity = dir;
|
||||||
|
IsActive = true;
|
||||||
|
|
||||||
|
Vector2 rayStart = item.SimPosition;
|
||||||
|
Vector2 rayEnd = item.SimPosition + dir * 1000.0f;
|
||||||
|
|
||||||
|
bool hitSomething = false;
|
||||||
|
GameMain.World.RayCast((fixture, point, normal, fraction) =>
|
||||||
|
{
|
||||||
|
if (fixture == null || fixture.IsSensor) return -1;
|
||||||
|
|
||||||
|
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
|
||||||
|
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||||
|
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) return -1;
|
||||||
|
|
||||||
|
item.body.SetTransform(point, rotation);
|
||||||
|
if (OnProjectileCollision(fixture, normal))
|
||||||
|
{
|
||||||
|
hitSomething = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}, rayStart, rayEnd);
|
||||||
|
|
||||||
|
//the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost
|
||||||
|
if (!hitSomething)
|
||||||
|
{
|
||||||
|
Item.Spawner.AddToRemoveQueue(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime, Camera cam)
|
public override void Update(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||||
|
|
||||||
if (stickJoint != null && stickJoint.JointTranslation < 0.01f)
|
if (stickJoint != null &&
|
||||||
|
(stickJoint.JointTranslation < stickJoint.LowerLimit * 0.9f || stickJoint.JointTranslation > stickJoint.UpperLimit * 0.9f))
|
||||||
{
|
{
|
||||||
if (stickTarget != null)
|
if (stickTarget != null)
|
||||||
{
|
{
|
||||||
@@ -117,7 +178,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
item.body.FarseerBody.RestoreCollisionWith(stickTarget);
|
item.body.FarseerBody.RestoreCollisionWith(stickTarget);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//the body that the projectile was stuck to has been removed
|
//the body that the projectile was stuck to has been removed
|
||||||
}
|
}
|
||||||
@@ -142,9 +203,14 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private bool OnProjectileCollision(Fixture f1, Fixture f2, Contact contact)
|
private bool OnProjectileCollision(Fixture f1, Fixture f2, Contact contact)
|
||||||
{
|
{
|
||||||
if (IgnoredBodies.Contains(f2.Body)) return false;
|
return OnProjectileCollision(f2, contact.Manifold.LocalNormal);
|
||||||
|
}
|
||||||
|
|
||||||
if (f2.CollisionCategories == Physics.CollisionCharacter && !(f2.Body.UserData is Limb))
|
private bool OnProjectileCollision(Fixture target, Vector2 collisionNormal)
|
||||||
|
{
|
||||||
|
if (IgnoredBodies.Contains(target.Body)) return false;
|
||||||
|
|
||||||
|
if (target.CollisionCategories == Physics.CollisionCharacter && !(target.Body.UserData is Limb))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -152,7 +218,7 @@ namespace Barotrauma.Items.Components
|
|||||||
AttackResult attackResult = new AttackResult();
|
AttackResult attackResult = new AttackResult();
|
||||||
if (attack != null)
|
if (attack != null)
|
||||||
{
|
{
|
||||||
var submarine = f2.Body.UserData as Submarine;
|
var submarine = target.Body.UserData as Submarine;
|
||||||
if (submarine != null)
|
if (submarine != null)
|
||||||
{
|
{
|
||||||
item.Move(-submarine.Position);
|
item.Move(-submarine.Position);
|
||||||
@@ -164,11 +230,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Limb limb;
|
Limb limb;
|
||||||
Structure structure;
|
Structure structure;
|
||||||
if ((limb = (f2.Body.UserData as Limb)) != null)
|
if ((limb = (target.Body.UserData as Limb)) != null)
|
||||||
{
|
{
|
||||||
attackResult = attack.DoDamage(User, limb.character, item.WorldPosition, 1.0f);
|
attackResult = attack.DoDamage(User, limb.character, item.WorldPosition, 1.0f);
|
||||||
}
|
}
|
||||||
else if ((structure = (f2.Body.UserData as Structure)) != null)
|
else if ((structure = (target.Body.UserData as Structure)) != null)
|
||||||
{
|
{
|
||||||
attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f);
|
attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f);
|
||||||
}
|
}
|
||||||
@@ -187,7 +253,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
IgnoredBodies.Clear();
|
IgnoredBodies.Clear();
|
||||||
|
|
||||||
f2.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass);
|
target.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass);
|
||||||
|
|
||||||
if (attackResult.HitArmor)
|
if (attackResult.HitArmor)
|
||||||
{
|
{
|
||||||
@@ -195,12 +261,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else if (doesStick)
|
else if (doesStick)
|
||||||
{
|
{
|
||||||
Vector2 normal = contact.Manifold.LocalNormal;
|
|
||||||
Vector2 dir = new Vector2(
|
Vector2 dir = new Vector2(
|
||||||
(float)Math.Cos(item.body.Rotation),
|
(float)Math.Cos(item.body.Rotation),
|
||||||
(float)Math.Sin(item.body.Rotation));
|
(float)Math.Sin(item.body.Rotation));
|
||||||
|
|
||||||
if (Vector2.Dot(f1.Body.LinearVelocity, normal) < 0.0f) return StickToTarget(f2.Body, dir);
|
if (Vector2.Dot(item.body.LinearVelocity, collisionNormal) < 0.0f)
|
||||||
|
{
|
||||||
|
StickToTarget(target.Body, dir);
|
||||||
|
return Hitscan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -220,27 +289,52 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return f2.CollisionCategories != Physics.CollisionCharacter;
|
if (RemoveOnHit)
|
||||||
|
{
|
||||||
|
Item.Spawner.AddToRemoveQueue(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool StickToTarget(Body targetBody, Vector2 axis)
|
private void StickToTarget(Body targetBody, Vector2 axis)
|
||||||
{
|
{
|
||||||
if (stickJoint != null) return false;
|
if (stickJoint != null) return;
|
||||||
|
|
||||||
stickJoint = new PrismaticJoint(targetBody, item.body.FarseerBody, item.body.SimPosition, axis, true);
|
stickJoint = new PrismaticJoint(targetBody, item.body.FarseerBody, item.body.SimPosition, axis, true);
|
||||||
stickJoint.MotorEnabled = true;
|
stickJoint.MotorEnabled = true;
|
||||||
stickJoint.MaxMotorForce = 30.0f;
|
stickJoint.MaxMotorForce = 30.0f;
|
||||||
|
|
||||||
stickJoint.LimitEnabled = true;
|
stickJoint.LimitEnabled = true;
|
||||||
if (item.Sprite != null) stickJoint.UpperLimit = ConvertUnits.ToSimUnits(item.Sprite.size.X*0.7f);
|
if (item.Sprite != null)
|
||||||
|
{
|
||||||
|
stickJoint.LowerLimit = ConvertUnits.ToSimUnits(item.Sprite.size.X * -0.3f);
|
||||||
|
stickJoint.UpperLimit = ConvertUnits.ToSimUnits(item.Sprite.size.X * 0.3f);
|
||||||
|
}
|
||||||
|
|
||||||
item.body.FarseerBody.IgnoreCollisionWith(targetBody);
|
item.body.FarseerBody.IgnoreCollisionWith(targetBody);
|
||||||
stickTarget = targetBody;
|
stickTarget = targetBody;
|
||||||
GameMain.World.AddJoint(stickJoint);
|
GameMain.World.AddJoint(stickJoint);
|
||||||
|
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveComponentSpecific()
|
||||||
|
{
|
||||||
|
if (stickJoint != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GameMain.World.RemoveJoint(stickJoint);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//the body that the projectile was stuck to has been removed
|
||||||
|
}
|
||||||
|
|
||||||
|
stickJoint = null;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public float CameraShake;
|
public float CameraShake;
|
||||||
|
|
||||||
private bool sparks, shockwave, flames, smoke;
|
private bool sparks, shockwave, flames, smoke, flash;
|
||||||
|
|
||||||
private string decal;
|
private string decal;
|
||||||
private float decalSize;
|
private float decalSize;
|
||||||
@@ -39,6 +39,7 @@ namespace Barotrauma
|
|||||||
shockwave = element.GetAttributeBool("shockwave", true);
|
shockwave = element.GetAttributeBool("shockwave", true);
|
||||||
flames = element.GetAttributeBool("flames", true);
|
flames = element.GetAttributeBool("flames", true);
|
||||||
smoke = element.GetAttributeBool("smoke", true);
|
smoke = element.GetAttributeBool("smoke", true);
|
||||||
|
flash = element.GetAttributeBool("flash", true);
|
||||||
|
|
||||||
decal = element.GetAttributeString("decal", "");
|
decal = element.GetAttributeString("decal", "");
|
||||||
decalSize = element.GetAttributeFloat("decalSize", 1.0f);
|
decalSize = element.GetAttributeFloat("decalSize", 1.0f);
|
||||||
|
|||||||
Reference in New Issue
Block a user