more accurate submarine body generation, multiplayer fixes, saving takes HiddenSubPosition into account, fire coordinate fixes, editscreen fixes, checking item triggers in AIObjectiveGoto, netlobbyscreen sync fixes, re-enabled level start/end positions, water edit fixed

This commit is contained in:
Regalis
2015-12-17 18:26:40 +02:00
parent 859be53d28
commit af470eab2e
53 changed files with 1065 additions and 427 deletions

View File

@@ -170,7 +170,7 @@ namespace Barotrauma
selectedTargetMemory.Priority -= deltaTime;
Vector2 attackSimPosition = Character.Submarine==null ? ConvertUnits.ToSimUnits(selectedAiTarget.WorldPosition) : selectedAiTarget.SimPosition;
if (wallAttackPos != Vector2.Zero)
if (wallAttackPos != Vector2.Zero && targetEntity != null)
{
attackSimPosition = wallAttackPos;

View File

@@ -28,6 +28,8 @@ namespace Barotrauma
objectiveManager = new AIObjectiveManager(c);
objectiveManager.AddObjective(new AIObjectiveFindSafety(c));
objectiveManager.AddObjective(new AIObjectiveIdle(c));
updateObjectiveTimer = Rand.Range(0.0f, UpdateObjectiveInterval);
}
public override void Update(float deltaTime)

View File

@@ -40,6 +40,8 @@ namespace Barotrauma
this.canOpenDoors = canOpenDoors;
character = (host as AIController).Character;
findPathTimer = Rand.Range(0.0f, 1.0f);
}
public override void Update(float speed = 1)
@@ -65,9 +67,9 @@ namespace Barotrauma
if (findPathTimer > 0.0f) return Vector2.Zero;
currentTarget = target;
currentPath = pathFinder.FindPath(host.SimPosition, target);
currentPath = pathFinder.FindPath(host.SimPosition+Rand.Vector(0.2f), target);
findPathTimer = 1.0f;
findPathTimer = Rand.Range(1.0f,1.2f);
return DiffToCurrentNode();
}

View File

@@ -92,10 +92,7 @@ namespace Barotrauma
if (Vector2.Distance(character.SimPosition, enemy.SimPosition) < 3.0f)
{
character.AIController.SteeringManager.SteeringManual(deltaTime, character.SimPosition - enemy.SimPosition);
}
else
{
character.AIController.SteeringManager.SteeringManual(deltaTime, (character.SimPosition - enemy.SimPosition)*0.1f);
coolDownTimer = CoolDown;
}
}

View File

@@ -57,17 +57,34 @@ namespace Barotrauma
character.AIController.SteeringManager.SteeringSeek(
target != null ? target.SimPosition : targetPos);
Vector2 currTargetPos = target != null ? target.SimPosition : targetPos;
if (Vector2.Distance(currTargetPos, character.SimPosition) < 1.0f)
{
character.AnimController.TargetDir = currTargetPos.X > character.SimPosition.X ? Direction.Right : Direction.Left;
}
}
public override bool IsCompleted()
{
if (repeat) return false;
bool completed = false;
float allowedDistance = 0.5f;
var item = target as Item;
if (item != null) allowedDistance = Math.Max(item.PickDistance,allowedDistance);
return Vector2.Distance(target != null ? target.SimPosition : targetPos, character.SimPosition) < allowedDistance;
if (item != null)
{
allowedDistance = Math.Max(item.PickDistance, allowedDistance);
if (item.IsInsideTrigger(character.WorldPosition)) completed = true;
}
completed = completed || Vector2.Distance(target != null ? target.SimPosition : targetPos, character.SimPosition) < allowedDistance;
if (completed) character.AIController.SteeringManager.SteeringManual(0.0f, -character.AIController.Steering);
return completed;
}
public override bool IsDuplicate(AIObjective otherObjective)

View File

@@ -63,7 +63,7 @@ namespace Barotrauma
{
if (character.Position.X < character.AnimController.CurrentHull.Rect.X + WallAvoidDistance)
{
pathSteering.SteeringManual(deltaTime, Vector2.UnitX);
pathSteering.SteeringManual(deltaTime, Vector2.UnitX*5.0f);
}
else if (character.Position.X > character.AnimController.CurrentHull.Rect.Right - WallAvoidDistance)
{

View File

@@ -30,7 +30,7 @@ namespace Barotrauma
ItemComponent target = itemController == null ? targetItem: itemController;
if (Vector2.Distance(character.SimPosition, target.Item.SimPosition) < target.Item.PickDistance
|| target.Item.IsInsideTrigger(character.Position))
|| target.Item.IsInsideTrigger(character.WorldPosition))
{
if (character.SelectedConstruction != target.Item && target.CanBeSelected)
{

View File

@@ -42,6 +42,7 @@ namespace Barotrauma
public AICharacter(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false)
: base(file, position, characterInfo, isNetworkPlayer)
{
soundInterval = Rand.Range(0.0f, soundInterval);
}
public void SetAI(AIController aiController)
@@ -113,7 +114,16 @@ namespace Barotrauma
aiController.FillNetworkData(message);
return true;
case NetworkEventType.EntityUpdate:
if ((AnimController.RefLimb.SimPosition - Submarine.Loaded.SimPosition).Length() > NetConfig.CharacterIgnoreDistance) return false;
if (Submarine == null)
{
if ((AnimController.RefLimb.SimPosition - Submarine.Loaded.SimPosition).Length() > NetConfig.CharacterIgnoreDistance) return false;
}
else
{
if (AnimController.RefLimb.SimPosition.Length() > NetConfig.CharacterIgnoreDistance) return false;
}
message.Write(AnimController.TargetDir == Direction.Right);
message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -1.0f, 1.0f), -1.0f, 1.0f, 8);

View File

@@ -9,7 +9,7 @@ using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundSprite : ISteerable
class BackgroundCreature : ISteerable
{
const float MaxDepth = 100.0f;
@@ -17,7 +17,7 @@ namespace Barotrauma
public bool Enabled;
private BackgroundSpritePrefab prefab;
private BackgroundCreaturePrefab prefab;
private Vector2 position;
@@ -53,7 +53,7 @@ namespace Barotrauma
set;
}
public BackgroundSprite(BackgroundSpritePrefab prefab, Vector2 position)
public BackgroundCreature(BackgroundCreaturePrefab prefab, Vector2 position)
{
this.prefab = prefab;
@@ -105,18 +105,6 @@ namespace Barotrauma
Vector2 midPoint = Swarm.MidPoint();
float midPointDist = Vector2.Distance(position, midPoint);
//steeringManager.SteeringSeek(midPoint + Swarm.AvgVelocity()*1000.0f, prefab.Speed*0.1f);
//float avgWanderAngle = 0.0f;
//foreach (var other in Swarm.Members)
//{
// avgWanderAngle += other.steeringManager.WanderAngle;
//}
//avgWanderAngle /= Swarm.Members.Count;
//steeringManager.WanderAngle = MathHelper.Lerp(steeringManager.WanderAngle, avgWanderAngle, 0.1f);
if (midPointDist > Swarm.MaxDistance)
{
steeringManager.SteeringSeek(midPoint, (midPointDist / Swarm.MaxDistance) * prefab.Speed);
@@ -169,7 +157,7 @@ namespace Barotrauma
class Swarm
{
public List<BackgroundSprite> Members;
public List<BackgroundCreature> Members;
public readonly float MaxDistance;
@@ -179,7 +167,7 @@ namespace Barotrauma
Vector2 midPoint = Vector2.Zero;
foreach (BackgroundSprite member in Members)
foreach (BackgroundCreature member in Members)
{
midPoint += member.SimPosition;
}
@@ -195,7 +183,7 @@ namespace Barotrauma
Vector2 avgVel = Vector2.Zero;
foreach (BackgroundSprite member in Members)
foreach (BackgroundCreature member in Members)
{
avgVel += member.Velocity;
}
@@ -205,13 +193,13 @@ namespace Barotrauma
return avgVel;
}
public Swarm(List<BackgroundSprite> members, float maxDistance)
public Swarm(List<BackgroundCreature> members, float maxDistance)
{
this.Members = members;
this.MaxDistance = maxDistance;
foreach (BackgroundSprite bgSprite in members)
foreach (BackgroundCreature bgSprite in members)
{
bgSprite.Swarm = this;
}

View File

@@ -0,0 +1,125 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreatureManager
{
const int MaxSprites = 100;
const float checkActiveInterval = 1.0f;
float checkActiveTimer;
private List<BackgroundCreaturePrefab> prefabs;
private List<BackgroundCreature> activeSprites;
public BackgroundCreatureManager(string configPath)
{
activeSprites = new List<BackgroundCreature>();
prefabs = new List<BackgroundCreaturePrefab>();
XDocument doc = ToolBox.TryLoadXml(configPath);
if (doc == null || doc.Root == null) return;
foreach (XElement element in doc.Root.Elements())
{
prefabs.Add(new BackgroundCreaturePrefab(element));
}
}
public void SpawnSprites(int count, Vector2? position = null)
{
activeSprites.Clear();
if (prefabs.Count == 0) return;
count = Math.Min(count, MaxSprites);
for (int i = 0; i < count; i++ )
{
Vector2 pos = Vector2.Zero;
if (position == null)
{
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null);
if (wayPoints.Any())
{
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count)];
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
pos += Rand.Vector(200.0f);
}
else
{
pos = Rand.Vector(2000.0f);
}
}
else
{
pos = (Vector2)position;
}
var prefab = prefabs[Rand.Int(prefabs.Count)];
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax);
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
for (int n = 0; n < amount; n++)
{
var newSprite = new BackgroundCreature(prefab, pos);
activeSprites.Add(newSprite);
swarmMembers.Add(newSprite);
}
if (amount > 0)
{
new Swarm(swarmMembers, prefab.SwarmRadius);
}
}
}
public void ClearSprites()
{
activeSprites.Clear();
}
public void Update(Camera cam, float deltaTime)
{
if (checkActiveTimer<0.0f)
{
foreach (BackgroundCreature sprite in activeSprites)
{
sprite.Enabled = (Math.Abs(sprite.TransformedPosition.X - cam.WorldViewCenter.X) < 4000.0f &&
Math.Abs(sprite.TransformedPosition.Y - cam.WorldViewCenter.Y) < 4000.0f);
}
checkActiveTimer = checkActiveInterval;
}
else
{
checkActiveTimer -= deltaTime;
}
foreach (BackgroundCreature sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Update(deltaTime);
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (BackgroundCreature sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Draw(spriteBatch);
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreaturePrefab
{
public readonly Sprite Sprite;
public readonly float Speed;
public readonly float WanderAmount;
public readonly float WanderZAmount;
public readonly int SwarmMin, SwarmMax;
public readonly float SwarmRadius;
public readonly bool DisableRotation;
public BackgroundCreaturePrefab(XElement element)
{
Speed = ToolBox.GetAttributeFloat(element, "speed", 1.0f);
WanderAmount = ToolBox.GetAttributeFloat(element, "wanderamount", 0.0f);
WanderZAmount = ToolBox.GetAttributeFloat(element, "wanderzamount", 0.0f);
SwarmMin = ToolBox.GetAttributeInt(element, "swarmmin", 1);
SwarmMax = ToolBox.GetAttributeInt(element, "swarmmax", 1);
SwarmRadius = ToolBox.GetAttributeFloat(element, "swarmradius", 200.0f);
DisableRotation = ToolBox.GetAttributeBool(element, "disablerotation", false);
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLower() != "sprite") continue;
Sprite = new Sprite(subElement);
break;
}
}
}
}

View File

@@ -5,23 +5,30 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Voronoi2;
namespace Barotrauma
{
class BackgroundSprite
{
public readonly BackgroundSpritePrefab Prefab;
public Vector2 Position;
public BackgroundSprite(BackgroundSpritePrefab prefab, Vector2 position)
{
this.Prefab = prefab;
this.Position = position;
}
}
class BackgroundSpriteManager
{
const int MaxSprites = 100;
const float checkActiveInterval = 1.0f;
float checkActiveTimer;
private List<BackgroundSpritePrefab> prefabs;
private List<BackgroundSprite> activeSprites;
private List<BackgroundSprite> sprites;
public BackgroundSpriteManager(string configPath)
{
activeSprites = new List<BackgroundSprite>();
sprites = new List<BackgroundSprite>();
prefabs = new List<BackgroundSpritePrefab>();
XDocument doc = ToolBox.TryLoadXml(configPath);
@@ -33,93 +40,92 @@ namespace Barotrauma
}
}
public void SpawnSprites(int count, Vector2? position = null)
public void PlaceSprites(Level level, int amount)
{
activeSprites.Clear();
sprites.Clear();
if (prefabs.Count == 0) return;
count = Math.Min(count, MaxSprites);
for (int i = 0; i < count; i++ )
for (int i = 0 ; i <amount; i++)
{
Vector2 pos = Vector2.Zero;
BackgroundSpritePrefab prefab = GetRandomPrefab();
Vector2 pos = FindSpritePosition(level, prefab);
if (position == null)
{
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null);
if (wayPoints.Any())
{
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count)];
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
pos += Rand.Vector(200.0f);
}
else
{
pos = Rand.Vector(2000.0f);
}
}
else
{
pos = (Vector2)position;
}
var prefab = prefabs[Rand.Int(prefabs.Count)];
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax);
List<BackgroundSprite> swarmMembers = new List<BackgroundSprite>();
for (int n = 0; n < amount; n++)
{
var newSprite = new BackgroundSprite(prefab, pos);
activeSprites.Add(newSprite);
swarmMembers.Add(newSprite);
}
if (amount > 0)
{
new Swarm(swarmMembers, prefab.SwarmRadius);
}
sprites.Add(new BackgroundSprite(prefab, pos));
}
}
public void ClearSprites()
private Vector2 FindSpritePosition(Level level, BackgroundSpritePrefab prefab)
{
activeSprites.Clear();
Vector2 randomPos = new Vector2(Rand.Range(0.0f, level.Size.X), Rand.Range(0.0f, level.Size.Y));
var cells = level.GetCells(randomPos);
if (!cells.Any()) return Vector2.Zero;
VoronoiCell cell = cells[Rand.Int(cells.Count)];
GraphEdge bestEdge = null;
foreach (GraphEdge edge in cell.edges)
{
if (prefab.Alignment.HasFlag(Alignment.Bottom))
{
if (bestEdge == null || edge.Center.Y > bestEdge.Center.Y) bestEdge = edge;
}
else if (prefab.Alignment.HasFlag(Alignment.Top))
{
if (bestEdge == null || edge.Center.Y < bestEdge.Center.Y) bestEdge = edge;
}
else if (prefab.Alignment.HasFlag(Alignment.Left))
{
if (bestEdge == null || edge.Center.X > bestEdge.Center.X) bestEdge = edge;
}
else if (prefab.Alignment.HasFlag(Alignment.Right))
{
if (bestEdge == null || edge.Center.X < bestEdge.Center.X) bestEdge = edge;
}
}
Vector2 dir = Vector2.Normalize(bestEdge.point1 - bestEdge.point2);
Vector2 pos = bestEdge.Center;
if (prefab.Alignment.HasFlag(Alignment.Bottom))
{
pos.Y -= Math.Abs(dir.Y) * prefab.Sprite.size.X/Math.Abs(dir.X);
}
else if (prefab.Alignment.HasFlag(Alignment.Top))
{
pos.Y += Math.Abs(dir.Y) * prefab.Sprite.size.X/Math.Abs(dir.X);
}
return pos;
}
public void Update(Camera cam, float deltaTime)
public void DrawSprites(SpriteBatch spriteBatch)
{
if (checkActiveTimer<0.0f)
foreach (BackgroundSprite sprite in sprites)
{
foreach (BackgroundSprite sprite in activeSprites)
sprite.Prefab.Sprite.Draw(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y));
}
}
private BackgroundSpritePrefab GetRandomPrefab()
{
int totalCommonness = 0;
foreach (BackgroundSpritePrefab prefab in prefabs)
{
totalCommonness += prefab.Commonness;
}
float randomNumber = Rand.Int(totalCommonness+1);
foreach (BackgroundSpritePrefab prefab in prefabs)
{
if (randomNumber <= prefab.Commonness)
{
sprite.Enabled = (Math.Abs(sprite.TransformedPosition.X - cam.WorldViewCenter.X) < 4000.0f &&
Math.Abs(sprite.TransformedPosition.Y - cam.WorldViewCenter.Y) < 4000.0f);
return prefab;
}
checkActiveTimer = checkActiveInterval;
}
else
{
checkActiveTimer -= deltaTime;
randomNumber -= prefab.Commonness;
}
foreach (BackgroundSprite sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Update(deltaTime);
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (BackgroundSprite sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Draw(spriteBatch);
}
return null;
}
}
}

View File

@@ -10,32 +10,17 @@ namespace Barotrauma
{
public readonly Sprite Sprite;
public readonly float Speed;
public readonly Alignment Alignment;
public readonly float WanderAmount;
public readonly int Commonness;
public readonly float WanderZAmount;
public readonly int SwarmMin, SwarmMax;
public readonly float SwarmRadius;
public readonly bool DisableRotation;
public BackgroundSpritePrefab(XElement element)
{
Speed = ToolBox.GetAttributeFloat(element, "speed", 1.0f);
string alignmentStr = ToolBox.GetAttributeString(element, "alignment", "BottomCenter");
WanderAmount = ToolBox.GetAttributeFloat(element, "wanderamount", 0.0f);
if (!Enum.TryParse(alignmentStr, out Alignment)) Alignment = Alignment.BottomCenter;
WanderZAmount = ToolBox.GetAttributeFloat(element, "wanderzamount", 0.0f);
SwarmMin = ToolBox.GetAttributeInt(element, "swarmmin", 1);
SwarmMax = ToolBox.GetAttributeInt(element, "swarmmax", 1);
SwarmRadius = ToolBox.GetAttributeFloat(element, "swarmradius", 200.0f);
DisableRotation = ToolBox.GetAttributeBool(element, "disablerotation", false);
Commonness = ToolBox.GetAttributeInt(element, "commonness", 1);
foreach (XElement subElement in element.Elements())
{
@@ -45,6 +30,6 @@ namespace Barotrauma
break;
}
}
}
}
}

View File

@@ -300,7 +300,7 @@ namespace Barotrauma
public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false, bool hasAi=true)
{
return Create(characterInfo.File, position, characterInfo, isNetworkPlayer);
return Create(characterInfo.File, position, characterInfo, isNetworkPlayer, hasAi);
}
public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false, bool hasAi=true)
@@ -315,17 +315,19 @@ namespace Barotrauma
}
else
{
if (hasAi)
{
return new Character(file, position, characterInfo, isNetworkPlayer);
}
else
if (hasAi && !isNetworkPlayer)
{
var character = new AICharacter(file, position, characterInfo, isNetworkPlayer);
var ai = new HumanAIController(character);
character.SetAI(ai);
return character;
}
else
{
return new Character(file, position, characterInfo, isNetworkPlayer);
}
}
}
@@ -340,26 +342,12 @@ namespace Barotrauma
{
keys[i] = new Key(GameMain.Config.KeyBind((InputType)i));
}
//keys[(int)InputType.Select] = new Key(GameMain.Config.KeyBind(InputType.Select));
//keys[(int)InputType.ActionHeld] = new Key(true);
//keys[(int)InputType.ActionHit] = new Key(false);
//keys[(int)InputType.SecondaryHit] = new Key(false);
//keys[(int)InputType.SecondaryHeld] = new Key(true);
//keys[(int)InputType.Left] = new Key(true);
//keys[(int)InputType.Right] = new Key(true);
//keys[(int)InputType.Up] = new Key(true);
//keys[(int)InputType.Down] = new Key(true);
//keys[(int)InputType.Run] = new Key(true);
selectedItems = new Item[2];
IsNetworkPlayer = isNetworkPlayer;
oxygen = 100.0f;
//blood = 100.0f;
aiTarget = new AITarget(this);
lowPassMultiplier = 1.0f;
@@ -1259,22 +1247,6 @@ namespace Barotrauma
return inventory.FillNetworkData(NetworkEventType.InventoryUpdate, message, data);
case NetworkEventType.ImportantEntityUpdate:
//int i = 0;
//foreach (Limb limb in AnimController.Limbs)
//{
// if (limb.SimPosition.Length() > NetConfig.CharacterIgnoreDistance) return false;
// message.WriteRangedSingle(limb.body.SimPosition.X, -NetConfig.CharacterIgnoreDistance, NetConfig.CharacterIgnoreDistance, 16);
// message.WriteRangedSingle(limb.body.SimPosition.Y, -NetConfig.CharacterIgnoreDistance, NetConfig.CharacterIgnoreDistance, 16);
// //message.Write(limb.body.LinearVelocity.X);
// //message.Write(limb.body.LinearVelocity.Y);
// message.Write(limb.body.Rotation);
// //message.WriteRangedSingle(MathHelper.Clamp(limb.body.AngularVelocity, -10.0f, 10.0f), -10.0f, 10.0f, 8);
// i++;
//}
message.Write((byte)((health / maxHealth) * 255.0f));
if (AnimController.StunTimer<=0.0f && bleeding<=0.0f && oxygen>99.0f)
@@ -1291,10 +1263,8 @@ namespace Barotrauma
bleeding = MathHelper.Clamp(bleeding, 0.0f, 5.0f);
message.WriteRangedSingle(bleeding, 0.0f, 5.0f, 8);
}
return true;
case NetworkEventType.EntityUpdate:
message.Write(keys[(int)InputType.Use].DequeueHeld);