633e54b...7cc231b
commit 7cc231bc51890e7fde50bbac3413328dd7bc5189 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Wed Mar 20 14:23:06 2019 +0200 Fixed server creating network events in Item.Load due to CreateServerEvent calls in some of the ItemComponent properties (e.g. LightComponent.IsOn). Caused syncing problems because the entity spawn events aren't created until the item has been loaded, leading to situations where clients fail to read events because the entity doesn't exist at their end yet (see #1293). TODO: get rid of console errors when attempting to create events during component initialization in the Item constructor. commit ac1bf32edf125d95d56775e1e8ce54ac7671328c Author: itchyOwl <lauri.harkanen@gmail.com> Date: Wed Mar 20 13:49:55 2019 +0200 Fix Hammerhead attack causing warping. Adjust the targeting priorities. commit e3e032d7c3a753397269bb4236c1494ab0809004 Author: itchyOwl <lauri.harkanen@gmail.com> Date: Wed Mar 20 13:48:47 2019 +0200 Enemy AI fixes: - Fix enemies "fleeing" after they have been shot. There was a steering issue when they targeted characters that were inside the sub when they were outside of it - Fix the previous target resetting too often - Fix the wall target resetting too often - Use world positions instead of sim positions where possible, because the sub positions are then taken into account commit 847cf5ffd9212a542000dbf12332b2c08756579a Author: Daniel Asteljoki <daniel.asteljoki@gmail.com> Date: Wed Mar 20 12:00:15 2019 +0200 Remora: added power connection between sub and drone, removed non-scaling hull parts commit a9c2e8cc124713e90dd44a9adf2fcbb3204b2c4d Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Wed Mar 20 11:24:37 2019 +0200 Server sets clients' last received campaign save/update IDs to one before the current up-to-date IDs (instead of zero) when a campaign changes. Zero would get interpreted as a more up-to-date ID if the IDs of the current campaign are close to ushort.MaxValue where the IDs wrap around. commit 07d82b64e6990eacaf8905aed1a5d7c61224e47d Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Tue Mar 19 18:24:01 2019 +0200 Log level inequality error messages & client error reports handled by the server to GameAnalytics
This commit is contained in:
@@ -24,7 +24,7 @@ namespace Barotrauma
|
||||
if (wallTarget.Structure.Submarine != null) wallTargetPos += wallTarget.Structure.Submarine.Position;
|
||||
wallTargetPos.Y = -wallTargetPos.Y;
|
||||
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false);
|
||||
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
|
||||
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
|
||||
}
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.ToString()})", pos - Vector2.UnitY * 20.0f, Color.Red);
|
||||
|
||||
@@ -1103,8 +1103,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
|
||||
{
|
||||
string errorMsg = " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
DebugConsole.ThrowError(errorMsg, createMessageBox: true);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch"+levelSeed, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
CoroutineManager.StartCoroutine(EndGame(""));
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,6 @@ namespace Barotrauma
|
||||
{
|
||||
partial class CharacterInfo
|
||||
{
|
||||
partial void SpawnInventoryItemProjSpecific(Item item)
|
||||
{
|
||||
Entity.Spawner.CreateNetworkEvent(item, false);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg)
|
||||
{
|
||||
msg.Write(ID);
|
||||
|
||||
@@ -335,6 +335,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
|
||||
if (!ItemList.Contains(this))
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = components.IndexOf(ic);
|
||||
if (index == -1) return;
|
||||
|
||||
|
||||
@@ -782,6 +782,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:LevelsDontMatch" + error, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorStr);
|
||||
KickClient(c, errorStr);
|
||||
}
|
||||
|
||||
@@ -839,8 +840,8 @@ namespace Barotrauma.Networking
|
||||
//(the server started a new campaign and the client isn't aware of it yet?)
|
||||
if (campaign.CampaignID != campaignID)
|
||||
{
|
||||
c.LastRecvCampaignSave = 0;
|
||||
c.LastRecvCampaignUpdate = 0;
|
||||
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
||||
c.LastRecvCampaignUpdate = (ushort)(campaign.LastUpdateID - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
<Submarine file="Submarines/Bunyip.sub" />
|
||||
<Submarine file="Submarines/Humpback.sub" />
|
||||
<Submarine file="Submarines/Dugong.sub" />
|
||||
<Submarine file="Submarines/Remora.sub" />
|
||||
<Submarine file="Submarines/RemoraDrone.sub" />
|
||||
<Text file="Content/Texts/EnglishVanilla.xml" />
|
||||
<UIStyle file="Content/UI/style.xml"/>
|
||||
<Afflictions file="Content/Afflictions.xml"/>
|
||||
|
||||
@@ -3129,8 +3129,10 @@
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Remora.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\RemoraDrone.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)Submarines\Typhon.sub">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
@@ -419,12 +419,7 @@ namespace Barotrauma
|
||||
|
||||
selectedTargetMemory.Priority -= deltaTime * 0.1f;
|
||||
|
||||
Vector2 attackSimPosition = Character.Submarine == null ? ConvertUnits.ToSimUnits(SelectedAiTarget.WorldPosition) : SelectedAiTarget.SimPosition;
|
||||
|
||||
if (Character.Submarine != null && SelectedAiTarget.Entity.Submarine != null && Character.Submarine != SelectedAiTarget.Entity.Submarine)
|
||||
{
|
||||
attackSimPosition = ConvertUnits.ToSimUnits(SelectedAiTarget.WorldPosition - Character.Submarine.Position);
|
||||
}
|
||||
Vector2 attackPos = SelectedAiTarget.WorldPosition;
|
||||
|
||||
if (SelectedAiTarget.Entity is Item item)
|
||||
{
|
||||
@@ -440,35 +435,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (wallTarget != null)
|
||||
{
|
||||
attackSimPosition = ConvertUnits.ToSimUnits(wallTarget.Position);
|
||||
if (Character.Submarine == null && SelectedAiTarget.Entity?.Submarine != null)
|
||||
{
|
||||
attackSimPosition += ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position);
|
||||
}
|
||||
}
|
||||
else if (SelectedAiTarget.Entity is Character c)
|
||||
{
|
||||
//target the closest limb if the target is a character
|
||||
float closestDist = Vector2.DistanceSquared(SelectedAiTarget.SimPosition, SimPosition) * 10.0f;
|
||||
foreach (Limb limb in ((Character)SelectedAiTarget.Entity).AnimController.Limbs)
|
||||
{
|
||||
if (limb == null) continue;
|
||||
float dist = Vector2.DistanceSquared(limb.SimPosition, SimPosition) / Math.Max(limb.AttackPriority, 0.1f);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestDist = dist;
|
||||
attackSimPosition = limb.SimPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater)
|
||||
{
|
||||
Character.AnimController.TargetDir = Character.SimPosition.X < attackSimPosition.X ? Direction.Right : Direction.Left;
|
||||
}
|
||||
|
||||
if (raycastTimer > 0.0)
|
||||
{
|
||||
raycastTimer -= deltaTime;
|
||||
@@ -479,6 +445,35 @@ namespace Barotrauma
|
||||
raycastTimer = RaycastInterval;
|
||||
}
|
||||
|
||||
if (wallTarget != null)
|
||||
{
|
||||
attackPos = wallTarget.Position;
|
||||
if (Character.Submarine == null && wallTarget.Structure.Submarine != null)
|
||||
{
|
||||
attackPos += wallTarget.Structure.Submarine.Position;
|
||||
}
|
||||
}
|
||||
else if (SelectedAiTarget.Entity is Character c)
|
||||
{
|
||||
//target the closest limb if the target is a character
|
||||
float closestDist = Vector2.DistanceSquared(SelectedAiTarget.WorldPosition, WorldPosition) * 10.0f;
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb == null) continue;
|
||||
float dist = Vector2.DistanceSquared(limb.WorldPosition, WorldPosition) / Math.Max(limb.AttackPriority, 0.1f);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestDist = dist;
|
||||
attackPos = limb.WorldPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater)
|
||||
{
|
||||
Character.AnimController.TargetDir = Character.WorldPosition.X < attackPos.X ? Direction.Right : Direction.Left;
|
||||
}
|
||||
|
||||
if (aggressiveBoarding)
|
||||
{
|
||||
//targeting a wall section that can be passed through -> steer manually through the hole
|
||||
@@ -511,9 +506,9 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (SelectedAiTarget.Entity is Item)
|
||||
else if (SelectedAiTarget.Entity is Item i)
|
||||
{
|
||||
var door = ((Item)SelectedAiTarget.Entity).GetComponent<Door>();
|
||||
var door = i.GetComponent<Door>();
|
||||
//steer through the door manually if it's open or broken
|
||||
if (door?.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom && (door.IsOpen || door.Item.Condition <= 0.0f))
|
||||
{
|
||||
@@ -556,7 +551,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFallBack(attackSimPosition, deltaTime);
|
||||
UpdateFallBack(attackPos, deltaTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -564,14 +559,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (attackingLimb.attack.SecondaryCoolDownTimer <= 0)
|
||||
{
|
||||
// Don't allow attacking when the attack target has changed.
|
||||
// Don't allow attacking when the attack target has just changed.
|
||||
if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget)
|
||||
{
|
||||
canAttack = false;
|
||||
if (attackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.PursueIfCanAttack)
|
||||
{
|
||||
// Fall back if cannot attack.
|
||||
UpdateFallBack(attackSimPosition, deltaTime);
|
||||
UpdateFallBack(attackPos, deltaTime);
|
||||
return;
|
||||
}
|
||||
attackingLimb = null;
|
||||
@@ -580,7 +575,7 @@ namespace Barotrauma
|
||||
{
|
||||
// If the secondary cooldown is defined and expired, check if we can switch the attack
|
||||
var previousLimb = attackingLimb;
|
||||
var newLimb = GetAttackLimb(attackSimPosition, previousLimb);
|
||||
var newLimb = GetAttackLimb(attackPos, previousLimb);
|
||||
if (newLimb != null)
|
||||
{
|
||||
attackingLimb = newLimb;
|
||||
@@ -594,7 +589,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFallBack(attackSimPosition, deltaTime);
|
||||
UpdateFallBack(attackPos, deltaTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -609,7 +604,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case AIBehaviorAfterAttack.FallBack:
|
||||
default:
|
||||
UpdateFallBack(attackSimPosition, deltaTime);
|
||||
UpdateFallBack(attackPos, deltaTime);
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -617,7 +612,7 @@ namespace Barotrauma
|
||||
|
||||
if (attackingLimb == null)
|
||||
{
|
||||
attackingLimb = GetAttackLimb(attackSimPosition);
|
||||
attackingLimb = GetAttackLimb(attackPos);
|
||||
}
|
||||
if (canAttack)
|
||||
{
|
||||
@@ -627,18 +622,18 @@ namespace Barotrauma
|
||||
if (canAttack)
|
||||
{
|
||||
// Check that we can reach the target
|
||||
distance = ConvertUnits.ToDisplayUnits(Vector2.Distance(attackingLimb.SimPosition, attackSimPosition));
|
||||
distance = Vector2.Distance(attackingLimb.WorldPosition, attackPos);
|
||||
canAttack = distance < attackingLimb.attack.Range;
|
||||
}
|
||||
|
||||
Limb steeringLimb = Character.AnimController.MainLimb;
|
||||
if (steeringLimb != null)
|
||||
{
|
||||
Vector2 steeringVector = attackSimPosition - steeringLimb.SimPosition;
|
||||
Vector2 targetingVector = Vector2.Normalize(steeringVector) * attackingLimb.attack.Range;
|
||||
Vector2 toTarget = Vector2.Normalize(attackPos - steeringLimb.WorldPosition);
|
||||
Vector2 targetingVector = toTarget * attackingLimb.attack.Range;
|
||||
// Offset the position a bit so that we don't overshoot the movement.
|
||||
Vector2 steerPos = attackSimPosition + targetingVector;
|
||||
steeringManager.SteeringSeek(steerPos, 10);
|
||||
Vector2 steerPos = attackPos + targetingVector;
|
||||
steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(attackPos), 10);
|
||||
if (Character.CurrentHull == null)
|
||||
{
|
||||
SteeringManager.SteeringAvoid(deltaTime, colliderSize * 1.5f);
|
||||
@@ -656,7 +651,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (indoorsSteering.CurrentPath.Finished)
|
||||
{
|
||||
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(steeringVector));
|
||||
steeringManager.SteeringManual(deltaTime, toTarget);
|
||||
}
|
||||
else if (indoorsSteering.CurrentPath.CurrentNode?.ConnectedDoor != null)
|
||||
{
|
||||
@@ -674,11 +669,11 @@ namespace Barotrauma
|
||||
|
||||
if (canAttack)
|
||||
{
|
||||
UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition, distance);
|
||||
UpdateLimbAttack(deltaTime, attackingLimb, ConvertUnits.ToSimUnits(attackPos), distance);
|
||||
}
|
||||
}
|
||||
|
||||
private Limb GetAttackLimb(Vector2 attackSimPosition, Limb ignoredLimb = null)
|
||||
private Limb GetAttackLimb(Vector2 attackWorldPos, Limb ignoredLimb = null)
|
||||
{
|
||||
AttackContext currentContext = Character.GetAttackContext();
|
||||
var target = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity;
|
||||
@@ -692,7 +687,7 @@ namespace Barotrauma
|
||||
l.attack.IsValidTarget(target) &&
|
||||
l.attack.Conditionals.All(c => (target is ISerializableEntity se && c.Matches(se)) || !(target is ISerializableEntity) || !(target is Character)))
|
||||
.OrderByDescending(l => l.attack.Priority)
|
||||
.ThenBy(l => ConvertUnits.ToDisplayUnits(Vector2.Distance(l.SimPosition, attackSimPosition)));
|
||||
.ThenBy(l => Vector2.Distance(l.WorldPosition, attackWorldPos));
|
||||
// TODO: priority should probably not override the distance -> use values instead of booleans
|
||||
return limbs.FirstOrDefault();
|
||||
}
|
||||
@@ -705,12 +700,13 @@ namespace Barotrauma
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//check if there's a wall between the target and the Character
|
||||
Vector2 rayStart = Character.SimPosition;
|
||||
Vector2 rayEnd = SelectedAiTarget.SimPosition;
|
||||
bool offset = SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null;
|
||||
|
||||
if (SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
|
||||
if (offset)
|
||||
{
|
||||
rayStart -= ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position);
|
||||
}
|
||||
@@ -721,18 +717,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
Structure wall = closestBody.UserData as Structure;
|
||||
if (wall?.Submarine == null)
|
||||
{
|
||||
return;
|
||||
/*if (selectedAiTarget.Entity.Submarine != null)
|
||||
{
|
||||
wallTarget = new WallTarget(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition), selectedAiTarget.Entity.Submarine);
|
||||
latchOntoAI?.SetAttachTarget(closestBody, selectedAiTarget.Entity.Submarine, Submarine.LastPickedPosition);
|
||||
}*/
|
||||
//if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null) wallAttackPos += ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position);
|
||||
}
|
||||
else
|
||||
if (closestBody.UserData is Structure wall && wall.Submarine != null)
|
||||
{
|
||||
int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition));
|
||||
int passableHoleCount = GetMinimumPassableHoleCount();
|
||||
@@ -755,36 +740,27 @@ namespace Barotrauma
|
||||
if (wall.SectionDamage(i) > sectionDamage) sectionIndex = i;
|
||||
}
|
||||
|
||||
Vector2 sectionPos = ConvertUnits.ToSimUnits(wall.SectionPosition(sectionIndex));
|
||||
Vector2 sectionPos = wall.SectionPosition(sectionIndex);
|
||||
Vector2 attachTargetNormal;
|
||||
if (wall.IsHorizontal)
|
||||
{
|
||||
attachTargetNormal = new Vector2(0.0f, Math.Sign(Character.WorldPosition.Y - wall.WorldPosition.Y));
|
||||
sectionPos.Y += ConvertUnits.ToSimUnits((wall.BodyHeight <= 0.0f ? wall.Rect.Height : wall.BodyHeight) / 2) * attachTargetNormal.Y;
|
||||
sectionPos.Y += (wall.BodyHeight <= 0.0f ? wall.Rect.Height : wall.BodyHeight) / 2 * attachTargetNormal.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
attachTargetNormal = new Vector2(Math.Sign(Character.WorldPosition.X - wall.WorldPosition.X), 0.0f);
|
||||
sectionPos.X += ConvertUnits.ToSimUnits((wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2) * attachTargetNormal.X;
|
||||
sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X;
|
||||
}
|
||||
wallTarget = new WallTarget(ConvertUnits.ToDisplayUnits(sectionPos), wall, sectionIndex);
|
||||
latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, sectionPos, attachTargetNormal);
|
||||
|
||||
wallTarget = new WallTarget(sectionPos, wall, sectionIndex);
|
||||
latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAttacked(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
updateTargetsTimer = Math.Min(updateTargetsTimer, 0.1f);
|
||||
|
||||
// Reduce the cooldown so that the character can react
|
||||
foreach (var limb in Character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.attack != null)
|
||||
{
|
||||
limb.attack.CoolDownTimer *= 0.1f;
|
||||
// secondary cooldown?
|
||||
}
|
||||
}
|
||||
|
||||
if (attackResult.Damage > 0.0f && attackWhenProvoked)
|
||||
{
|
||||
@@ -801,18 +777,31 @@ namespace Barotrauma
|
||||
if (attacker == null || attacker.AiTarget == null) return;
|
||||
AITargetMemory targetMemory = FindTargetMemory(attacker.AiTarget);
|
||||
targetMemory.Priority += GetRelativeDamage(attackResult.Damage, Character.Vitality) * aggressionhurt;
|
||||
|
||||
// Reduce the cooldown so that the character can react
|
||||
// Only allow to react once. Otherwise would attack the target with only a fraction of cooldown
|
||||
if (SelectedAiTarget != attacker.AiTarget)
|
||||
{
|
||||
foreach (var limb in Character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.attack != null)
|
||||
{
|
||||
limb.attack.CoolDownTimer *= 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 10 dmg, 100 health -> 0.1
|
||||
private float GetRelativeDamage(float dmg, float vitality) => dmg / Math.Max(vitality, 1.0f);
|
||||
|
||||
private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition, float distance = -1)
|
||||
private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackSimPos, float distance = -1)
|
||||
{
|
||||
var damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity as IDamageable;
|
||||
if (damageTarget == null) return;
|
||||
|
||||
float prevHealth = damageTarget.Health;
|
||||
if (limb.UpdateAttack(deltaTime, attackPosition, damageTarget, out AttackResult attackResult, distance))
|
||||
if (limb.UpdateAttack(deltaTime, attackSimPos, damageTarget, out AttackResult attackResult, distance))
|
||||
{
|
||||
if (damageTarget.Health > 0)
|
||||
{
|
||||
@@ -820,24 +809,19 @@ namespace Barotrauma
|
||||
selectedTargetMemory.Priority += GetRelativeDamage(attackResult.Damage, damageTarget.Health) * aggressiongreed;
|
||||
}
|
||||
}
|
||||
|
||||
if (!limb.attack.IsRunning)
|
||||
{
|
||||
wallTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFallBack(Vector2 attackPosition, float deltaTime)
|
||||
{
|
||||
float dist = Vector2.Distance(attackPosition, Character.SimPosition);
|
||||
Vector2 attackVector = attackPosition - Character.WorldPosition;
|
||||
float dist = attackVector.Length();
|
||||
float desiredDist = colliderSize * 2.0f;
|
||||
if (dist < desiredDist)
|
||||
{
|
||||
Vector2 attackDir = Vector2.Normalize(Character.SimPosition - attackPosition);
|
||||
Vector2 attackDir = Vector2.Normalize(-attackVector);
|
||||
if (!MathUtils.IsValid(attackDir)) attackDir = Vector2.UnitY;
|
||||
steeringManager.SteeringManual(deltaTime, attackDir * (1.0f - (dist / 500.0f)));
|
||||
}
|
||||
|
||||
steeringManager.SteeringAvoid(deltaTime, colliderSize * 3.0f);
|
||||
}
|
||||
|
||||
@@ -888,8 +872,8 @@ namespace Barotrauma
|
||||
//sight/hearing range
|
||||
public void UpdateTargets(Character character, out TargetingPriority targetingPriority)
|
||||
{
|
||||
AITarget newTarget = null;
|
||||
targetingPriority = null;
|
||||
SelectedAiTarget = null;
|
||||
selectedTargetMemory = null;
|
||||
targetValue = 0.0f;
|
||||
|
||||
@@ -1021,13 +1005,15 @@ namespace Barotrauma
|
||||
|
||||
if (valueModifier > targetValue)
|
||||
{
|
||||
SelectedAiTarget = target;
|
||||
newTarget = target;
|
||||
selectedTargetMemory = targetMemory;
|
||||
targetingPriority = targetingPriorities[targetingTag];
|
||||
targetValue = valueModifier;
|
||||
}
|
||||
}
|
||||
|
||||
SelectedAiTarget = newTarget;
|
||||
|
||||
if (SelectedAiTarget != _previousAiTarget)
|
||||
{
|
||||
wallTarget = null;
|
||||
|
||||
@@ -801,7 +801,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (XElement itemElement in element.Elements())
|
||||
{
|
||||
var newItem = Item.Load(itemElement, inventory.Owner.Submarine);
|
||||
var newItem = Item.Load(itemElement, inventory.Owner.Submarine, createNetworkEvent: true);
|
||||
if (newItem == null) { continue; }
|
||||
|
||||
int[] slotIndices = itemElement.GetAttributeIntArray("i", new int[] { 0 });
|
||||
@@ -810,9 +810,7 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Invalid inventory data in character \"" + Name + "\" - no slot indices found");
|
||||
continue;
|
||||
}
|
||||
|
||||
SpawnInventoryItemProjSpecific(newItem);
|
||||
|
||||
|
||||
inventory.TryPutItem(newItem, slotIndices[0], false, false, null);
|
||||
|
||||
//force the item to the correct slots
|
||||
@@ -842,8 +840,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void SpawnInventoryItemProjSpecific(Item item);
|
||||
|
||||
public void ReloadHeadAttachments()
|
||||
{
|
||||
ResetLoadedAttachments();
|
||||
|
||||
@@ -491,10 +491,10 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Returns true if the attack successfully hit something. If the distance is not given, it will be calculated.
|
||||
/// </summary>
|
||||
public bool UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget, out AttackResult attackResult, float distance = -1)
|
||||
public bool UpdateAttack(float deltaTime, Vector2 attackSimPos, IDamageable damageTarget, out AttackResult attackResult, float distance = -1)
|
||||
{
|
||||
attackResult = default(AttackResult);
|
||||
float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition));
|
||||
float dist = distance > -1 ? distance : ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackSimPos));
|
||||
bool wasRunning = attack.IsRunning;
|
||||
attack.UpdateAttackTimer(deltaTime);
|
||||
|
||||
@@ -511,7 +511,7 @@ namespace Barotrauma
|
||||
ignoredBodies.Add(character.AnimController.Collider.FarseerBody);
|
||||
|
||||
structureBody = Submarine.PickBody(
|
||||
SimPosition, attackPosition,
|
||||
SimPosition, attackSimPos,
|
||||
ignoredBodies, Physics.CollisionWall);
|
||||
|
||||
if (damageTarget is Item)
|
||||
@@ -607,7 +607,7 @@ namespace Barotrauma
|
||||
attack.SetCoolDown();
|
||||
}
|
||||
|
||||
Vector2 diff = attackPosition - SimPosition;
|
||||
Vector2 diff = attackSimPos - SimPosition;
|
||||
bool applyForces = (!attack.ApplyForcesOnlyOnce || !wasRunning) && diff.LengthSquared() > 0.00001f;
|
||||
if (applyForces)
|
||||
{
|
||||
@@ -620,13 +620,13 @@ namespace Barotrauma
|
||||
|
||||
Limb limb = character.AnimController.Limbs[limbIndex];
|
||||
Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA;
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos);
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA;
|
||||
body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos);
|
||||
body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
|
||||
}
|
||||
}
|
||||
return wasHit;
|
||||
|
||||
@@ -60,7 +60,6 @@ namespace Barotrauma
|
||||
|
||||
public readonly XElement StaticBodyConfig;
|
||||
|
||||
private bool needsPositionUpdate;
|
||||
private float lastSentCondition;
|
||||
|
||||
private float condition;
|
||||
@@ -1811,8 +1810,20 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
partial void UpdateNetPosition(float deltaTime);
|
||||
|
||||
|
||||
public static Item Load(XElement element, Submarine submarine)
|
||||
{
|
||||
return Load(element, submarine, createNetworkEvent: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiate a new item and load its data from the XML element.
|
||||
/// </summary>
|
||||
/// <param name="element">The element containing the data of the item</param>
|
||||
/// <param name="submarine">The submarine to spawn the item in (can be null)</param>
|
||||
/// <param name="createNetworkEvent">Should an EntitySpawner event be created to notify clients about the item being created.</param>
|
||||
/// <returns></returns>
|
||||
public static Item Load(XElement element, Submarine submarine, bool createNetworkEvent)
|
||||
{
|
||||
string name = element.Attribute("name").Value;
|
||||
string identifier = element.GetAttributeString("identifier", "");
|
||||
@@ -1858,6 +1869,13 @@ namespace Barotrauma
|
||||
linkedToID = new List<ushort>()
|
||||
};
|
||||
|
||||
#if SERVER
|
||||
if (createNetworkEvent)
|
||||
{
|
||||
Spawner.CreateNetworkEvent(item, remove: false);
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
if (!item.properties.TryGetValue(attribute.Name.ToString(), out SerializableProperty property)) continue;
|
||||
@@ -1904,7 +1922,7 @@ namespace Barotrauma
|
||||
{
|
||||
component.OnItemLoaded();
|
||||
}
|
||||
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,16 @@ namespace Barotrauma
|
||||
|
||||
public override void CreateNetworkEvent()
|
||||
{
|
||||
if (!Item.ItemList.Contains(container.Item))
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + container.Item.Name + ") that hasn't been fully initialized yet.";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"ItemInventory.CreateServerEvent:EventForUninitializedItem" + container.Item.Name + container.Item.ID,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
int componentIndex = container.Item.GetComponentIndex(container);
|
||||
if (componentIndex == -1)
|
||||
{
|
||||
|
||||
@@ -407,7 +407,7 @@ namespace Barotrauma
|
||||
|
||||
try
|
||||
{
|
||||
MethodInfo loadMethod = t.GetMethod("Load");
|
||||
MethodInfo loadMethod = t.GetMethod("Load", new [] { typeof(XElement), typeof(Submarine) });
|
||||
if (loadMethod == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find the method \"Load\" in " + t + ".");
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Barotrauma
|
||||
private readonly Queue<IEntitySpawnInfo> spawnQueue;
|
||||
private readonly Queue<Entity> removeQueue;
|
||||
|
||||
class SpawnOrRemove
|
||||
public class SpawnOrRemove
|
||||
{
|
||||
public readonly Entity Entity;
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user