77a07a95af
commit ece6ead54c021d084f406f4f99daa5a0a7ef4b19 Author: Regalis11 <poe.regalis@gmail.com> Date: Fri Mar 22 21:52:56 2019 +0200 v0.8.9.7 commit c10dd821ca1a89b4ae62046cf8e558589ff8e6af Author: Regalis11 <poe.regalis@gmail.com> Date: Fri Mar 22 21:00:02 2019 +0200 Fixed release builds crashing due to simulatedlatency etc commands not existing in release builds commit dee0dded80cbbf30d484232b6706dd705a577eb7 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Fri Mar 22 15:24:44 2019 +0200 Fixed nullref exception if a client disconnects while netstats is enabled commit c45d5bf0c5a4a68200c9eca461cd04090a5de23a Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Fri Mar 22 15:24:26 2019 +0200 Togglehud, toggleupperhud and togglecharacternames don't require a permission to use, made simulatedlatency, simulatedloss and simulatedduplicateschange usable to clients commit cec1ac6bccac058bc12ddf18c8e060a7a47c9301 Merge: 411cd9726 1473f77ba Author: itchyOwl <lauri.harkanen@gmail.com> Date: Fri Mar 22 14:01:58 2019 +0200 Merge branch 'dev' into enemy-ai commit 411cd9726979668764eea782b515c7510ec4f5a8 Author: itchyOwl <lauri.harkanen@gmail.com> Date: Fri Mar 22 14:01:09 2019 +0200 If the target has changed, re-evaluate the attacking limb. Fixes Hammerhead getting stuck next to the sub, because it treats the claw as the attacking limb when targeting characters inside the sub. It should use the head, because it has a wall target. commit 2522bec262f9cb1dea9df75e1d2c22307be5254c Author: itchyOwl <lauri.harkanen@gmail.com> Date: Fri Mar 22 13:58:18 2019 +0200 Enemy ai/steering fixes: - Store both sim and world positions. Offset the simposition with the subposition and use it for steering. Fixes enemy indoorsteering, which was broken. - Use head or torso for steering instead of always using the main limb. Fixes characters like Mudraptor overshooting their targets badly. commit c667ff9e4edf8af8f95278fbad42e0c8dd37d84c Author: itchyOwl <lauri.harkanen@gmail.com> Date: Fri Mar 22 13:54:21 2019 +0200 Improve the ai debug graphics. commit 4c6c13e07e43a4e3ce2a11dfc4064961c442044a Author: itchyOwl <lauri.harkanen@gmail.com> Date: Thu Mar 21 17:11:17 2019 +0200 Refactor, fix and adjust the enemy targeting logic: - Change the logic for fading the memories - When attacking a wall target, set it as the currently selected ai target so that we adjust the right memory - Significantly reduce the value of character targets that are not in the same submarine - In aggressive boarding, double the priority of walls when outside. Set the priority to 0 when inside. Reduce the attractiveness of doors, but still keep the values high. - Redefine priorities for Mudraptor and Crawler (wip) commit b085a95cff6bcf5e3f13e90dd1b71ac15e5ec1ab Author: itchyOwl <lauri.harkanen@gmail.com> Date: Thu Mar 21 13:16:22 2019 +0200 Allow enemies to target walls by decision (not only when they happen to be on their way). TODO: target only outer walls and only when outside of the sub.
303 lines
10 KiB
C#
303 lines
10 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
partial class StructurePrefab : MapEntityPrefab
|
|
{
|
|
public XElement ConfigElement { get; private set; }
|
|
|
|
private bool canSpriteFlipX, canSpriteFlipY;
|
|
|
|
private float health;
|
|
|
|
//default size
|
|
private Vector2 size;
|
|
|
|
//does the structure have a physics body
|
|
[Serialize(false, false)]
|
|
public bool Body
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
//rotation of the physics body in degrees
|
|
[Serialize(0.0f, false)]
|
|
public float BodyRotation
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
//in display units
|
|
[Serialize(0.0f, false)]
|
|
public float BodyWidth
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
//in display units
|
|
[Serialize(0.0f, false)]
|
|
public float BodyHeight
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
//in display units
|
|
[Serialize("0.0,0.0", false)]
|
|
public Vector2 BodyOffset
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
[Serialize(false, false)]
|
|
public bool Platform
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
[Serialize(false, false)]
|
|
public bool AllowAttachItems
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
[Serialize(100.0f, false)]
|
|
public float Health
|
|
{
|
|
get { return health; }
|
|
set { health = Math.Max(value, 0.0f); }
|
|
}
|
|
|
|
[Serialize(false, false)]
|
|
public bool CastShadow
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
[Serialize(Direction.None, false)]
|
|
public Direction StairDirection
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public bool CanSpriteFlipX
|
|
{
|
|
get { return canSpriteFlipX; }
|
|
}
|
|
|
|
public bool CanSpriteFlipY
|
|
{
|
|
get { return canSpriteFlipY; }
|
|
}
|
|
|
|
[Serialize("0,0", true)]
|
|
public Vector2 Size
|
|
{
|
|
get { return size; }
|
|
private set { size = value; }
|
|
}
|
|
|
|
public Vector2 ScaledSize => size * Scale;
|
|
|
|
protected Vector2 textureScale = Vector2.One;
|
|
[Editable(DecimalCount = 3), Serialize("1.0, 1.0", true)]
|
|
public Vector2 TextureScale
|
|
{
|
|
get { return textureScale; }
|
|
set
|
|
{
|
|
textureScale = new Vector2(
|
|
MathHelper.Clamp(value.X, 0.01f, 10),
|
|
MathHelper.Clamp(value.Y, 0.01f, 10));
|
|
}
|
|
}
|
|
|
|
public Sprite BackgroundSprite
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public static void LoadAll(IEnumerable<string> filePaths)
|
|
{
|
|
foreach (string filePath in filePaths)
|
|
{
|
|
XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
|
if (doc == null || doc.Root == null) return;
|
|
|
|
foreach (XElement el in doc.Root.Elements())
|
|
{
|
|
StructurePrefab sp = Load(el);
|
|
|
|
List.Add(sp);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static StructurePrefab Load(XElement element)
|
|
{
|
|
StructurePrefab sp = new StructurePrefab
|
|
{
|
|
name = element.GetAttributeString("name", "")
|
|
};
|
|
sp.ConfigElement = element;
|
|
if (string.IsNullOrEmpty(sp.name)) sp.name = element.Name.ToString();
|
|
sp.identifier = element.GetAttributeString("identifier", "");
|
|
|
|
string translatedName = TextManager.Get("EntityName." + sp.identifier, true);
|
|
if (!string.IsNullOrEmpty(translatedName)) sp.name = translatedName;
|
|
|
|
sp.Tags = new HashSet<string>();
|
|
string joinedTags = element.GetAttributeString("tags", "");
|
|
if (string.IsNullOrEmpty(joinedTags)) joinedTags = element.GetAttributeString("Tags", "");
|
|
foreach (string tag in joinedTags.Split(','))
|
|
{
|
|
sp.Tags.Add(tag.Trim().ToLowerInvariant());
|
|
}
|
|
|
|
foreach (XElement subElement in element.Elements())
|
|
{
|
|
switch (subElement.Name.ToString())
|
|
{
|
|
case "sprite":
|
|
sp.sprite = new Sprite(subElement);
|
|
if (subElement.Attribute("sourcerect") == null)
|
|
{
|
|
DebugConsole.ThrowError("Warning - sprite sourcerect not configured for structure \"" + sp.name + "\"!");
|
|
}
|
|
|
|
if (subElement.GetAttributeBool("fliphorizontal", false))
|
|
sp.sprite.effects = SpriteEffects.FlipHorizontally;
|
|
if (subElement.GetAttributeBool("flipvertical", false))
|
|
sp.sprite.effects = SpriteEffects.FlipVertically;
|
|
|
|
sp.canSpriteFlipX = subElement.GetAttributeBool("canflipx", true);
|
|
sp.canSpriteFlipY = subElement.GetAttributeBool("canflipy", true);
|
|
|
|
if (subElement.Attribute("name") == null && !string.IsNullOrWhiteSpace(sp.Name))
|
|
{
|
|
sp.sprite.Name = sp.Name;
|
|
}
|
|
sp.sprite.EntityID = sp.identifier;
|
|
break;
|
|
case "backgroundsprite":
|
|
sp.BackgroundSprite = new Sprite(subElement);
|
|
|
|
if (subElement.GetAttributeBool("fliphorizontal", false))
|
|
sp.BackgroundSprite.effects = SpriteEffects.FlipHorizontally;
|
|
if (subElement.GetAttributeBool("flipvertical", false))
|
|
sp.BackgroundSprite.effects = SpriteEffects.FlipVertically;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Enum.TryParse(element.GetAttributeString("category", "Structure"), true, out MapEntityCategory category))
|
|
{
|
|
category = MapEntityCategory.Structure;
|
|
}
|
|
sp.Category = category;
|
|
|
|
string aliases = element.GetAttributeString("aliases", "");
|
|
if (!string.IsNullOrWhiteSpace(aliases))
|
|
{
|
|
sp.Aliases = aliases.Split(',');
|
|
}
|
|
|
|
SerializableProperty.DeserializeProperties(sp, element);
|
|
if (sp.Body)
|
|
{
|
|
sp.Tags.Add("wall");
|
|
}
|
|
string translatedDescription = TextManager.Get("EntityDescription." + sp.identifier, true);
|
|
if (!string.IsNullOrEmpty(translatedDescription)) sp.Description = translatedDescription;
|
|
|
|
//backwards compatibility
|
|
if (element.Attribute("size") == null)
|
|
{
|
|
sp.size = Vector2.Zero;
|
|
if (element.Attribute("width") == null && element.Attribute("height") == null)
|
|
{
|
|
sp.size.X = sp.sprite.SourceRect.Width;
|
|
sp.size.Y = sp.sprite.SourceRect.Height;
|
|
}
|
|
else
|
|
{
|
|
sp.size.X = element.GetAttributeFloat("width", 0.0f);
|
|
sp.size.Y = element.GetAttributeFloat("height", 0.0f);
|
|
}
|
|
}
|
|
|
|
if (!category.HasFlag(MapEntityCategory.Legacy) && string.IsNullOrEmpty(sp.identifier))
|
|
{
|
|
DebugConsole.ThrowError(
|
|
"Structure prefab \"" + sp.name + "\" has no identifier. All structure prefabs have a unique identifier string that's used to differentiate between items during saving and loading.");
|
|
}
|
|
if (!string.IsNullOrEmpty(sp.identifier))
|
|
{
|
|
MapEntityPrefab existingPrefab = List.Find(e => e.Identifier == sp.identifier);
|
|
if (existingPrefab != null)
|
|
{
|
|
DebugConsole.ThrowError(
|
|
"Map entity prefabs \"" + sp.name + "\" and \"" + existingPrefab.Name + "\" have the same identifier!");
|
|
}
|
|
}
|
|
|
|
return sp;
|
|
}
|
|
|
|
public override void UpdatePlacing(Camera cam)
|
|
{
|
|
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
|
Vector2 size = ScaledSize;
|
|
Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
|
|
|
|
if (placePosition == Vector2.Zero)
|
|
{
|
|
if (PlayerInput.LeftButtonHeld())
|
|
placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
|
|
|
newRect.X = (int)position.X;
|
|
newRect.Y = (int)position.Y;
|
|
}
|
|
else
|
|
{
|
|
Vector2 placeSize = size;
|
|
if (ResizeHorizontal) placeSize.X = position.X - placePosition.X;
|
|
if (ResizeVertical) placeSize.Y = placePosition.Y - position.Y;
|
|
|
|
newRect = Submarine.AbsRect(placePosition, placeSize);
|
|
|
|
if (PlayerInput.LeftButtonReleased())
|
|
{
|
|
//don't allow resizing width/height to zero
|
|
if ((!ResizeHorizontal || placeSize.X != 0.0f) && (!ResizeVertical || placeSize.Y != 0.0f))
|
|
{
|
|
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
|
|
|
|
var structure = new Structure(newRect, this, Submarine.MainSub);
|
|
structure.Submarine = Submarine.MainSub;
|
|
}
|
|
|
|
selected = null;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (PlayerInput.RightButtonHeld()) selected = null;
|
|
}
|
|
}
|
|
}
|