(5a377a8ee) Unstable v0.9.1000.0

This commit is contained in:
Juan Pablo Arce
2020-05-13 12:55:42 -03:00
parent b143329701
commit a1ca41aa5d
426 changed files with 14384 additions and 5708 deletions
@@ -4,10 +4,11 @@ using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using FarseerPhysics.Dynamics;
namespace Barotrauma.Items.Components
{
@@ -35,8 +36,16 @@ namespace Barotrauma.Items.Components
private int failedLaunchAttempts;
private readonly List<Item> activeProjectiles = new List<Item>();
public IEnumerable<Item> ActiveProjectiles => activeProjectiles;
private Character user;
private float resetUserTimer;
public float Rotation
{
get { return rotation; }
}
[Serialize("0,0", false, description: "The position of the barrel relative to the upper left corner of the base sprite (in pixels).")]
public Vector2 BarrelPos
@@ -74,7 +83,28 @@ namespace Barotrauma.Items.Components
set { reloadTime = value; }
}
[Serialize(1, false, description: "How projectiles the weapon launches when fired once.")]
[Editable(0.1f, 10f), Serialize(1.0f, false, description: "Modifies the duration of retraction of the barrell after recoil to get back to the original position after shooting. Reload time affects this too.")]
public float RetractionDurationMultiplier
{
get;
set;
}
[Editable(0.1f, 10f), Serialize(0.1f, false, description: "How quickly the recoil moves the barrel after launching.")]
public float RecoilTime
{
get;
set;
}
[Editable(0f, 1000f), Serialize(0f, false, description: "How long the barrell stays in place after the recoil and before retracting back to the original position.")]
public float RetractionDelay
{
get;
set;
}
[Serialize(1, false, description: "How many projectiles the weapon launches when fired once.")]
public int ProjectileCount
{
get;
@@ -88,7 +118,8 @@ namespace Barotrauma.Items.Components
set;
}
[Editable, Serialize("0.0,0.0", true, description: "The range at which the barrel can rotate. TODO")]
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
Serialize("0.0,0.0", true, description: "The range at which the barrel can rotate.", alwaysUseInstanceValues: true)]
public Vector2 RotationLimits
{
get
@@ -168,7 +199,7 @@ namespace Barotrauma.Items.Components
}
private float baseRotationRad;
[Editable(0.0f, 360.0f), Serialize(0.0f, true, description: "The angle of the turret's base in degrees.")]
[Editable(0.0f, 360.0f), Serialize(0.0f, true, description: "The angle of the turret's base in degrees.", alwaysUseInstanceValues: true)]
public float BaseRotation
{
get { return MathHelper.ToDegrees(baseRotationRad); }
@@ -224,6 +255,7 @@ namespace Barotrauma.Items.Components
//if (item.FlippedY) flippedRotation = 180.0f - flippedRotation;
transformedBarrelPos = MathUtils.RotatePointAroundTarget(barrelPos * item.Scale, new Vector2(item.Rect.Width / 2, item.Rect.Height / 2), flippedRotation);
#if CLIENT
item.ResetCachedVisibleSize();
item.SpriteRotation = MathHelper.ToRadians(flippedRotation);
#endif
}
@@ -252,6 +284,16 @@ namespace Barotrauma.Items.Components
if (reload > 0.0f) { reload -= deltaTime; }
if (user != null && user.Removed)
{
user = null;
}
else
{
resetUserTimer -= deltaTime;
if (resetUserTimer <= 0.0f) { user = null; }
}
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
UpdateProjSpecific(deltaTime);
@@ -356,7 +398,7 @@ namespace Barotrauma.Items.Components
{
linkedItem.Use(deltaTime, null);
var repairable = linkedItem.GetComponent<Repairable>();
if (repairable != null)
if (repairable != null && failedLaunchAttempts < 2)
{
repairable.LastActiveTime = (float)Timing.TotalTime + 1.0f;
}
@@ -411,7 +453,7 @@ namespace Barotrauma.Items.Components
#if SERVER
if (character != null && launchedProjectile != null)
{
string msg = character.LogName + " launched " + item.Name + " (projectile: " + launchedProjectile.Item.Name;
string msg = GameServer.CharacterLogName(character) + " launched " + item.Name + " (projectile: " + launchedProjectile.Item.Name;
var containedItems = launchedProjectile.Item.ContainedItems;
if (containedItems == null || !containedItems.Any())
{
@@ -428,7 +470,7 @@ namespace Barotrauma.Items.Components
return true;
}
private void Launch(Item projectile, Character user = null)
private void Launch(Item projectile, Character user = null, float? launchRotation = null)
{
reload = reloadTime;
@@ -444,7 +486,9 @@ namespace Barotrauma.Items.Components
}
float spread = MathHelper.ToRadians(Spread) * Rand.Range(-0.5f, 0.5f);
projectile.SetTransform(ConvertUnits.ToSimUnits(new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y)), -rotation + spread);
projectile.SetTransform(
ConvertUnits.ToSimUnits(new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y)),
-(launchRotation ?? rotation) + spread);
projectile.UpdateTransform();
projectile.Submarine = projectile.body?.Submarine;
@@ -456,12 +500,11 @@ namespace Barotrauma.Items.Components
projectileComponent.User = user;
}
if (projectile.Container != null) { projectile.Container.RemoveContained(projectile); }
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), projectile });
}
if (projectile.Container != null) { projectile.Container.RemoveContained(projectile); }
}
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
{
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), projectile });
}
ApplyStatusEffects(ActionType.OnUse, 1.0f, user: user);
@@ -476,8 +519,10 @@ namespace Barotrauma.Items.Components
private float prevTargetRotation;
private float updateTimer;
private bool updatePending;
public void ThalamusOperate(float deltaTime, bool targetHumans, bool targetOtherCreatures, bool targetSubmarines, bool ignoreDelay)
public void ThalamusOperate(WreckAI ai, float deltaTime, bool targetHumans, bool targetOtherCreatures, bool targetSubmarines, bool ignoreDelay)
{
if (ai == null) { return; }
IsActive = true;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
@@ -513,8 +558,8 @@ namespace Barotrauma.Items.Components
foreach (var character in Character.CharacterList)
{
if (character == null || character.Removed || character.IsDead) { continue; }
if (character.Params.Group.Equals("thalamus", StringComparison.OrdinalIgnoreCase)) { continue; }
bool isHuman = character.IsHuman || character.Params.Group.Equals("human", StringComparison.OrdinalIgnoreCase);
if (character.Params.Group.Equals(ai.Config.Entity, StringComparison.OrdinalIgnoreCase)) { continue; }
bool isHuman = character.IsHuman || character.Params.Group.Equals(CharacterPrefab.HumanSpeciesName, StringComparison.OrdinalIgnoreCase);
if (isHuman)
{
if (!targetHumans)
@@ -619,7 +664,8 @@ namespace Barotrauma.Items.Components
end -= target.Submarine.SimPosition;
}
var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel;
var pickedBody = Submarine.PickBody(start, end, null, collisionCategories);
var pickedBody = Submarine.PickBody(start, end, null, collisionCategories, allowInsideFixture: true,
customPredicate: (Fixture f) => { return !item.StaticFixtures.Contains(f); });
if (pickedBody == null) { return; }
Character targetCharacter = null;
if (pickedBody.UserData is Character c)
@@ -632,16 +678,28 @@ namespace Barotrauma.Items.Components
}
if (targetCharacter != null)
{
if (targetCharacter.Params.Group.Equals("thalamus", StringComparison.OrdinalIgnoreCase))
if (targetCharacter.Params.Group.Equals(ai.Config.Entity, StringComparison.OrdinalIgnoreCase))
{
// Don't shoot friendly characters
return;
}
}
else if (!(pickedBody.UserData is Structure) && !(pickedBody.UserData is Item))
else
{
// Hit something else than a wall or an item (probably a level wall)
return;
if (pickedBody.UserData is ISpatialEntity e)
{
Submarine sub = e.Submarine;
if (sub == null) { return; }
if (!targetSubmarines) { return; }
if (sub == Item.Submarine) { return; }
// Don't shoot non-player submarines, i.e. wrecks or outposts.
if (!sub.Info.IsPlayer) { return; }
}
else
{
// Hit something else, probably a level wall
return;
}
}
TryLaunch(deltaTime, ignorePower: true);
}
@@ -663,6 +721,7 @@ namespace Barotrauma.Items.Components
PowerContainer batteryToLoad = null;
foreach (PowerContainer battery in batteries)
{
if (battery.Item.NonInteractable) { continue; }
if (batteryToLoad == null || battery.Charge < lowestCharge)
{
batteryToLoad = battery;
@@ -683,20 +742,22 @@ namespace Barotrauma.Items.Components
int maxProjectileCount = 0;
foreach (MapEntity e in item.linkedTo)
{
if (!(e is Item projectileContainer)) continue;
var containedItems = projectileContainer.ContainedItems;
if (containedItems != null)
if (item.NonInteractable) { continue; }
if (e is Item projectileContainer)
{
var container = projectileContainer.GetComponent<ItemContainer>();
maxProjectileCount += container.Capacity;
var containedItems = projectileContainer.ContainedItems;
if (containedItems != null)
{
var container = projectileContainer.GetComponent<ItemContainer>();
maxProjectileCount += container.Capacity;
int projectiles = containedItems.Count(it => it.Condition > 0.0f);
usableProjectileCount += projectiles;
int projectiles = containedItems.Count(it => it.Condition > 0.0f);
usableProjectileCount += projectiles;
}
}
}
if (usableProjectileCount == 0 || (usableProjectileCount < maxProjectileCount && objective.Option.Equals("fireatwill", StringComparison.OrdinalIgnoreCase)))
if (usableProjectileCount == 0)
{
ItemContainer container = null;
Item containerItem = null;
@@ -704,11 +765,16 @@ namespace Barotrauma.Items.Components
{
containerItem = e as Item;
if (containerItem == null) { continue; }
if (containerItem.NonInteractable) { continue; }
if (character.AIController is HumanAIController aiController && aiController.IgnoredItems.Contains(containerItem)) { continue; }
container = containerItem.GetComponent<ItemContainer>();
if (container != null) { break; }
}
if (container == null || container.ContainableItems.Count == 0) { return true; }
if (container == null || container.ContainableItems.Count == 0)
{
character.Speak(TextManager.GetWithVariable("DialogCannotLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "cannotloadturret", 30.0f);
return true;
}
if (objective.SubObjectives.None())
{
if (!AIDecontainEmptyItems(character, objective, equip: true, sourceContainer: container))
@@ -719,10 +785,25 @@ namespace Barotrauma.Items.Components
if (objective.SubObjectives.None())
{
var loadItemsObjective = AIContainItems<Turret>(container, character, objective, usableProjectileCount + 1, equip: true, removeEmpty: true);
loadItemsObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
character.Speak(TextManager.GetWithVariable("DialogLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "loadturret", 30.0f);
if (loadItemsObjective == null)
{
if (usableProjectileCount == 0)
{
character.Speak(TextManager.GetWithVariable("DialogCannotLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "cannotloadturret", 30.0f);
return true;
}
}
else
{
loadItemsObjective.ignoredContainerIdentifiers = new string[] { containerItem.prefab.Identifier };
character.Speak(TextManager.GetWithVariable("DialogLoadTurret", "[itemname]", item.Name, true), null, 0.0f, "loadturret", 30.0f);
return false;
}
}
if (objective.SubObjectives.Any())
{
return false;
}
return false;
}
//enough shells and power
@@ -753,7 +834,10 @@ namespace Barotrauma.Items.Components
character.AIController.SelectTarget(closestEnemy.AiTarget);
character.CursorPosition = closestEnemy.WorldPosition;
if (item.Submarine != null) { character.CursorPosition -= item.Submarine.Position; }
if (character.Submarine != null)
{
character.CursorPosition -= character.Submarine.Position;
}
float enemyAngle = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition);
float turretAngle = -rotation;
@@ -769,7 +853,8 @@ namespace Barotrauma.Items.Components
end -= closestEnemy.Submarine.SimPosition;
}
var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel;
var pickedBody = Submarine.PickBody(start, end, null, collisionCategories);
var pickedBody = Submarine.PickBody(start, end, null, collisionCategories, allowInsideFixture: true,
customPredicate: (Fixture f) => { return !item.StaticFixtures.Contains(f); });
if (pickedBody == null) { return false; }
Character targetCharacter = null;
if (pickedBody.UserData is Character c)
@@ -780,23 +865,34 @@ namespace Barotrauma.Items.Components
{
targetCharacter = limb.character;
}
if (targetCharacter != null && HumanAIController.IsFriendly(character, targetCharacter))
if (targetCharacter != null)
{
// Don't shoot friendly characters
return false;
if (HumanAIController.IsFriendly(character, targetCharacter))
{
// Don't shoot friendly characters
return false;
}
}
else if (targetCharacter == null && !(pickedBody.UserData is Structure) && !(pickedBody.UserData is Item))
else
{
// Hit something else than a wall or an item (probably a level wall)
return false;
if (pickedBody.UserData is ISpatialEntity e)
{
Submarine sub = e.Submarine;
if (sub == null) { return false; }
if (sub == Item.Submarine) { return false; }
// Don't shoot non-player submarines, i.e. wrecks or outposts.
if (!sub.Info.IsPlayer) { return false; }
// Don't shoot friendly submarines.
if (sub.TeamID == Item.Submarine.TeamID) { return false; }
}
else
{
// Hit something else, probably a level wall
return false;
}
}
if (objective.Option.Equals("fireatwill", StringComparison.OrdinalIgnoreCase))
{
character?.Speak(TextManager.GetWithVariable("DialogFireTurret", "[itemname]", item.Name, true), null, 0.0f, "fireturret", 5.0f);
character.SetInput(InputType.Shoot, true, true);
}
character?.Speak(TextManager.GetWithVariable("DialogFireTurret", "[itemname]", item.Name, true), null, 0.0f, "fireturret", 5.0f);
character.SetInput(InputType.Shoot, true, true);
return false;
}
@@ -914,10 +1010,12 @@ namespace Barotrauma.Items.Components
IsActive = true;
}
user = sender;
resetUserTimer = 10.0f;
break;
case "trigger_in":
item.Use((float)Timing.Step, sender);
user = sender;
resetUserTimer = 10.0f;
//triggering the Use method through item.Use will fail if the item is not characterusable and the signal was sent by a character
//so lets do it manually
if (!characterUsable && sender != null)
@@ -936,9 +1034,25 @@ namespace Barotrauma.Items.Components
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
Item item = extraData.Length > 2 ? (Item)extraData[2] : null;
msg.Write(item == null || item.Removed ? (ushort)0 : item.ID);
msg.WriteRangedSingle(MathHelper.Clamp(targetRotation, minRotation, maxRotation), minRotation, maxRotation, 8);
if (extraData.Length > 2)
{
msg.Write(!(extraData[2] is Item item) || item.Removed ? ushort.MaxValue : item.ID);
msg.WriteRangedSingle(MathHelper.Clamp(rotation, minRotation, maxRotation), minRotation, maxRotation, 16);
}
else
{
msg.Write((ushort)0);
float wrappedTargetRotation = targetRotation;
while (wrappedTargetRotation < minRotation && MathUtils.IsValid(wrappedTargetRotation))
{
wrappedTargetRotation += MathHelper.TwoPi;
}
while (wrappedTargetRotation > maxRotation && MathUtils.IsValid(wrappedTargetRotation))
{
wrappedTargetRotation -= MathHelper.TwoPi;
}
msg.WriteRangedSingle(MathHelper.Clamp(wrappedTargetRotation, minRotation, maxRotation), minRotation, maxRotation, 16);
}
}
}
}