- Added "LevelTriggers", areas that apply statuseffects and/or damage to entities. Atm can only be attached to background sprites.
- Moved background sprites to the shared project. - The debug textures of physics bodies have a maximum size of 128x128 pixels to prevent large bodies from taking up excessive amounts of memory. - Attacks can be set to only affect humans.
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LevelTrigger
|
||||
{
|
||||
private PhysicsBody physicsBody;
|
||||
|
||||
/// <summary>
|
||||
/// Effects applied to entities that are inside the trigger
|
||||
/// </summary>
|
||||
private List<StatusEffect> statusEffects = new List<StatusEffect>();
|
||||
|
||||
/// <summary>
|
||||
/// Attacks applied to entities that are inside the trigger
|
||||
/// </summary>
|
||||
private List<Attack> attacks = new List<Attack>();
|
||||
|
||||
private List<Entity> triggerers = new List<Entity>();
|
||||
|
||||
public Vector2 WorldPosition
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(physicsBody.Position); }
|
||||
set { physicsBody.SetTransform(ConvertUnits.ToSimUnits(value), physicsBody.Rotation); }
|
||||
}
|
||||
|
||||
public float Rotation
|
||||
{
|
||||
get { return physicsBody.Rotation; }
|
||||
set { physicsBody.SetTransform(physicsBody.Position, value); }
|
||||
}
|
||||
|
||||
public PhysicsBody PhysicsBody
|
||||
{
|
||||
get { return physicsBody; }
|
||||
}
|
||||
|
||||
public LevelTrigger(XElement element, Vector2 position, float rotation, float scale = 1.0f)
|
||||
{
|
||||
physicsBody = new PhysicsBody(element, scale);
|
||||
physicsBody.CollisionCategories = Physics.CollisionLevel;
|
||||
physicsBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionProjectile | Physics.CollisionWall;
|
||||
physicsBody.FarseerBody.OnCollision += PhysicsBody_OnCollision;
|
||||
physicsBody.FarseerBody.OnSeparation += PhysicsBody_OnSeparation;
|
||||
physicsBody.FarseerBody.IsSensor = true;
|
||||
physicsBody.FarseerBody.IsStatic = true;
|
||||
physicsBody.FarseerBody.IsKinematic = true;
|
||||
|
||||
physicsBody.SetTransform(ConvertUnits.ToSimUnits(position), rotation);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "statuseffect":
|
||||
statusEffects.Add(StatusEffect.Load(subElement));
|
||||
break;
|
||||
case "attack":
|
||||
case "damage":
|
||||
attacks.Add(new Attack(subElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool PhysicsBody_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
|
||||
{
|
||||
Entity entity = GetEntity(fixtureB);
|
||||
if (entity == null) return false;
|
||||
|
||||
if (!triggerers.Contains(entity))
|
||||
{
|
||||
triggerers.Add(entity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PhysicsBody_OnSeparation(Fixture fixtureA, Fixture fixtureB)
|
||||
{
|
||||
Entity entity = GetEntity(fixtureB);
|
||||
if (entity == null) return;
|
||||
|
||||
if (triggerers.Contains(entity))
|
||||
{
|
||||
triggerers.Remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private Entity GetEntity(Fixture fixture)
|
||||
{
|
||||
if (fixture.Body == null || fixture.Body.UserData == null) return null;
|
||||
|
||||
var entity = fixture.Body.UserData as Entity;
|
||||
if (entity != null) return entity;
|
||||
|
||||
var limb = fixture.Body.UserData as Limb;
|
||||
if (limb != null) return limb.character;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
foreach (Entity triggerer in triggerers)
|
||||
{
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (triggerer is Character)
|
||||
{
|
||||
effect.Apply(effect.type, deltaTime, triggerer, (Character)triggerer);
|
||||
}
|
||||
else if (triggerer is Item)
|
||||
{
|
||||
effect.Apply(effect.type, deltaTime, triggerer, ((Item)triggerer).AllPropertyObjects);
|
||||
}
|
||||
}
|
||||
|
||||
IDamageable damageable = triggerer as IDamageable;
|
||||
if (damageable != null)
|
||||
{
|
||||
foreach (Attack attack in attacks)
|
||||
{
|
||||
attack.DoDamage(null, damageable, WorldPosition, deltaTime, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user