Merge branch 'master' into dedicated-server
# Conflicts: # BarotraumaClient/Source/GameSettings.cs # BarotraumaClient/Source/Screens/NetLobbyScreen.cs
This commit is contained in:
@@ -75,6 +75,14 @@ namespace Barotrauma
|
||||
return (Duration == 0.0f) ? structureDamage : structureDamage * deltaTime;
|
||||
}
|
||||
|
||||
public Attack(float damage, float structureDamage, float bleedingDamage, float range = 0.0f)
|
||||
{
|
||||
Range = range;
|
||||
this.damage = damage;
|
||||
this.structureDamage = structureDamage;
|
||||
this.bleedingDamage = bleedingDamage;
|
||||
}
|
||||
|
||||
public Attack(XElement element)
|
||||
{
|
||||
try
|
||||
@@ -111,9 +119,7 @@ namespace Barotrauma
|
||||
Duration = ToolBox.GetAttributeFloat(element, "duration", 0.0f);
|
||||
|
||||
priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f);
|
||||
|
||||
statusEffects = new List<StatusEffect>();
|
||||
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -124,6 +130,10 @@ namespace Barotrauma
|
||||
break;
|
||||
#endif
|
||||
case "statuseffect":
|
||||
if (statusEffects == null)
|
||||
{
|
||||
statusEffects = new List<StatusEffect>();
|
||||
}
|
||||
statusEffects.Add(StatusEffect.Load(subElement));
|
||||
break;
|
||||
}
|
||||
@@ -150,6 +160,11 @@ namespace Barotrauma
|
||||
|
||||
var effectType = attackResult.Damage > 0.0f ? ActionType.OnUse : ActionType.OnFailure;
|
||||
|
||||
if (statusEffects == null)
|
||||
{
|
||||
return attackResult;
|
||||
}
|
||||
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (effect.Targets.HasFlag(StatusEffect.TargetType.This) && attacker is Character)
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace Barotrauma
|
||||
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
||||
healedCharacter.Oxygen = 100.0f;
|
||||
healedCharacter.Bleeding = 0.0f;
|
||||
healedCharacter.Stun = 0.0f;
|
||||
healedCharacter.SetStun(0.0f, true);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -444,6 +444,14 @@ namespace Barotrauma
|
||||
case "water":
|
||||
if (GameMain.Client == null) Hull.EditWater = !Hull.EditWater;
|
||||
|
||||
break;
|
||||
case "explosion":
|
||||
Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
float range = 500, force = 10, damage=50;
|
||||
if (commands.Length > 1) float.TryParse(commands[1], out range);
|
||||
if (commands.Length > 2) float.TryParse(commands[2], out force);
|
||||
if (commands.Length > 3) float.TryParse(commands[3], out damage);
|
||||
new Explosion(range, force, damage, damage).Explode(explosionPos);
|
||||
break;
|
||||
case "fire":
|
||||
if (GameMain.Client == null) Hull.EditFire = !Hull.EditFire;
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class Holdable : Pickable
|
||||
class Holdable : Pickable, IServerSerializable
|
||||
{
|
||||
//the position(s) in the item that the Character grabs
|
||||
protected Vector2[] handlePos;
|
||||
|
||||
private List<RelatedItem> prevRequiredItems;
|
||||
|
||||
string prevMsg;
|
||||
|
||||
private InputType prevPickKey;
|
||||
private string prevMsg;
|
||||
|
||||
//the distance from the holding characters elbow to center of the physics body of the item
|
||||
protected Vector2 holdPos;
|
||||
@@ -94,25 +95,28 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (attachable)
|
||||
{
|
||||
prevRequiredItems = new List<RelatedItem>(requiredItems);
|
||||
prevMsg = Msg;
|
||||
prevPickKey = PickKey;
|
||||
|
||||
requiredItems.Clear();
|
||||
Msg = "";
|
||||
DeattachFromWall();
|
||||
}
|
||||
|
||||
if (attachedByDefault || (Screen.Selected == GameMain.EditMapScreen)) Use(1.0f);
|
||||
|
||||
|
||||
//holdAngle = ToolBox.GetAttributeFloat(element, "holdangle", 0.0f);
|
||||
//holdAngle = MathHelper.ToRadians(holdAngle);
|
||||
|
||||
if ((Screen.Selected == GameMain.EditMapScreen)) Use(1.0f);
|
||||
}
|
||||
|
||||
public override void Drop(Character dropper)
|
||||
{
|
||||
DropConnectedWires(dropper);
|
||||
|
||||
if (body != null) item.body = body;
|
||||
if (attachable)
|
||||
{
|
||||
DeattachFromWall();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
item.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.body != null) item.body.Enabled = true;
|
||||
IsActive = false;
|
||||
@@ -121,7 +125,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (dropper == null) return;
|
||||
picker = dropper;
|
||||
|
||||
}
|
||||
if (picker.Inventory == null) return;
|
||||
|
||||
@@ -190,29 +193,36 @@ namespace Barotrauma.Items.Components
|
||||
return base.Pick(picker);
|
||||
}
|
||||
|
||||
if (!base.Pick(picker))
|
||||
if (Attached)
|
||||
{
|
||||
return false;
|
||||
return base.Pick(picker);
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredItems.Clear();
|
||||
Msg = "";
|
||||
//not attached -> pick the item instantly, ignoring picking time
|
||||
return OnPicked(picker);
|
||||
}
|
||||
|
||||
attached = false;
|
||||
if (body != null) item.body = body;
|
||||
//item.body.Enabled = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
protected override bool OnPicked(Character picker)
|
||||
{
|
||||
if (!attachable || item.body == null) return true;
|
||||
if (character != null && !character.IsKeyDown(InputType.Aim)) return false;
|
||||
if (base.OnPicked(picker))
|
||||
{
|
||||
DeattachFromWall();
|
||||
|
||||
item.Drop();
|
||||
if (GameMain.Server != null && attachable)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AttachToWall()
|
||||
{
|
||||
if (!attachable) return;
|
||||
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems != null)
|
||||
@@ -226,12 +236,40 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
item.body.Enabled = false;
|
||||
item.body = null;
|
||||
|
||||
requiredItems = new List<RelatedItem>(prevRequiredItems);
|
||||
|
||||
Msg = prevMsg;
|
||||
PickKey = prevPickKey;
|
||||
|
||||
attached = true;
|
||||
}
|
||||
|
||||
private void DeattachFromWall()
|
||||
{
|
||||
if (!attachable) return;
|
||||
|
||||
attached = false;
|
||||
|
||||
//make the item pickable with the default pick key and with no specific tools/items when it's deattached
|
||||
requiredItems.Clear();
|
||||
Msg = "";
|
||||
PickKey = InputType.Select;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (!attachable || item.body == null) return true;
|
||||
if (character != null)
|
||||
{
|
||||
if (!character.IsKeyDown(InputType.Aim)) return false;
|
||||
if (character != null && GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
item.Drop();
|
||||
}
|
||||
|
||||
AttachToWall();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -284,13 +322,39 @@ namespace Barotrauma.Items.Components
|
||||
item.body = body;
|
||||
body.Enabled = false;
|
||||
}
|
||||
attached = false;
|
||||
}
|
||||
attached = false;
|
||||
|
||||
requiredItems.Clear();
|
||||
Msg = "";
|
||||
DeattachFromWall();
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(Attached);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
bool isAttached = msg.ReadBoolean();
|
||||
if (isAttached)
|
||||
{
|
||||
item.Drop();
|
||||
AttachToWall();
|
||||
}
|
||||
else
|
||||
{
|
||||
DropConnectedWires(null);
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
item.body = body;
|
||||
item.body.Enabled = true;
|
||||
}
|
||||
IsActive = false;
|
||||
|
||||
DeattachFromWall();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +70,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
return OnPicked(picker);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private bool OnPicked(Character picker)
|
||||
protected virtual bool OnPicked(Character picker)
|
||||
{
|
||||
if (picker.Inventory.TryPutItem(item, allowedSlots))
|
||||
{
|
||||
|
||||
@@ -130,13 +130,13 @@ namespace Barotrauma.Items.Components
|
||||
public InputType PickKey
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public InputType SelectKey
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
protected set;
|
||||
}
|
||||
|
||||
[HasDefaultValue(false, false)]
|
||||
|
||||
@@ -53,6 +53,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Select(Character picker)
|
||||
{
|
||||
//attaching wires to items with a body is not allowed
|
||||
//(signal items remove their bodies when attached to a wall)
|
||||
if (item.body != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
user = picker;
|
||||
IsActive = true;
|
||||
return true;
|
||||
|
||||
@@ -17,6 +17,15 @@ namespace Barotrauma
|
||||
|
||||
private bool sparks, shockwave, flames, smoke;
|
||||
|
||||
public Explosion(float range, float force, float damage, float structureDamage)
|
||||
{
|
||||
attack = new Attack(damage, structureDamage, 0.0f, range);
|
||||
this.force = force;
|
||||
sparks = true;
|
||||
shockwave = true;
|
||||
flames = true;
|
||||
}
|
||||
|
||||
public Explosion(XElement element)
|
||||
{
|
||||
attack = new Attack(element);
|
||||
|
||||
@@ -257,8 +257,20 @@ namespace Barotrauma
|
||||
var targetCells = new List<VoronoiCell>();
|
||||
for (int i = 0; i < pathNodes.Count; i++)
|
||||
{
|
||||
int cellIndex = FindCellIndex(pathNodes[i], cells, cellGrid, gridCellSize, 2, gridOffset);
|
||||
targetCells.Add(cells[cellIndex]);
|
||||
//a search depth of 2 is large enough to find a cell in almost all maps, but in case it fails, we increase the depth
|
||||
int searchDepth = 2;
|
||||
while (searchDepth < 5)
|
||||
{
|
||||
int cellIndex = FindCellIndex(pathNodes[i], cells, cellGrid, gridCellSize, searchDepth, gridOffset);
|
||||
if (cellIndex > -1)
|
||||
{
|
||||
targetCells.Add(cells[cellIndex]);
|
||||
break;
|
||||
}
|
||||
|
||||
searchDepth++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return GeneratePath(targetCells, cells, cellGrid, gridCellSize, limits, wanderAmount, mirror);
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -12,55 +8,66 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
public const int MaxEventBufferLength = 1024;
|
||||
public const int MaxEventsPerWrite = 64;
|
||||
|
||||
//public UInt16 LastReceivedEntityEventID
|
||||
//{
|
||||
// get { return lastReceivedEntityEventID; }
|
||||
//}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write the events to the outgoing message. The recipient parameter is only needed for ServerEntityEventManager
|
||||
/// </summary>
|
||||
protected void Write(NetOutgoingMessage msg, List<NetEntityEvent> eventsToSync, Client recipient = null)
|
||||
{
|
||||
msg.Write(eventsToSync[0].ID);
|
||||
msg.Write((byte)eventsToSync.Count);
|
||||
//write into a temporary buffer so we can write the number of events before the actual data
|
||||
NetBuffer tempBuffer = new NetBuffer();
|
||||
|
||||
int eventCount = 0;
|
||||
foreach (NetEntityEvent e in eventsToSync)
|
||||
{
|
||||
//write into a temporary buffer so we can write the length before the actual data
|
||||
NetBuffer tempBuffer = new NetBuffer();
|
||||
NetBuffer tempEventBuffer = new NetBuffer();
|
||||
try
|
||||
{
|
||||
WriteEvent(tempBuffer, e, recipient);
|
||||
WriteEvent(tempEventBuffer, e, recipient);
|
||||
}
|
||||
|
||||
catch (Exception exception)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to write an event for the entity \""+e.Entity+"\"", exception);
|
||||
DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception);
|
||||
|
||||
//write an empty event to avoid messing up IDs
|
||||
//(otherwise the clients might read the next event in the message and think its ID
|
||||
//is consecutive to the previous one, even though we skipped over this broken event)
|
||||
tempBuffer.Write((UInt16)0);
|
||||
tempBuffer.WritePadBits();
|
||||
eventCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(
|
||||
tempBuffer.LengthBytes < 128,
|
||||
"Maximum EntityEvent size exceeded when serializing \""+e.Entity+"\"!");
|
||||
|
||||
if (msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > NetPeerConfiguration.kDefaultMTU - 20)
|
||||
{
|
||||
//no more room in this packet
|
||||
break;
|
||||
}
|
||||
|
||||
//the ID has been taken by another entity (the original entity has been removed) -> write an empty event
|
||||
if (Entity.FindEntityByID(e.Entity.ID) != e.Entity)
|
||||
{
|
||||
//technically the clients don't have any use for these, but removing events and shifting the IDs of all
|
||||
//consecutive ones is so error-prone that I think this is a safer option
|
||||
msg.Write((UInt16)0);
|
||||
msg.WritePadBits();
|
||||
tempBuffer.Write((UInt16)0);
|
||||
tempBuffer.WritePadBits();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write((UInt16)e.Entity.ID);
|
||||
msg.Write((byte)tempBuffer.LengthBytes);
|
||||
msg.Write(tempBuffer);
|
||||
msg.WritePadBits();
|
||||
tempBuffer.Write((UInt16)e.Entity.ID);
|
||||
tempBuffer.Write((byte)tempEventBuffer.LengthBytes);
|
||||
tempBuffer.Write(tempEventBuffer);
|
||||
tempBuffer.WritePadBits();
|
||||
}
|
||||
|
||||
eventCount++;
|
||||
}
|
||||
|
||||
msg.Write(eventsToSync[0].ID);
|
||||
msg.Write((byte)eventCount);
|
||||
msg.Write(tempBuffer);
|
||||
}
|
||||
|
||||
protected virtual void WriteEvent(NetBuffer buffer, NetEntityEvent entityEvent, Client recipient = null)
|
||||
|
||||
Reference in New Issue
Block a user