Mid-round chat messages have a limited range, headset item which can be used to communicate with players further away, new inventory slot for items like masks and headsets

This commit is contained in:
Regalis
2016-04-20 17:19:38 +03:00
parent a45f58cd08
commit e33f30dad1
21 changed files with 597 additions and 177 deletions
@@ -38,7 +38,7 @@
<Body radius="18" density="15"/> <Body radius="18" density="15"/>
<Wearable limbtype="Head" slots="Any,Head"> <Wearable limbtype="Head" slots="Any,Face">
<sprite texture="DivingMask.png" limb="Head" sourcerect="1,1,37,38"/> <sprite texture="DivingMask.png" limb="Head" sourcerect="1,1,37,38"/>
<StatusEffect type="OnWearing" target="Character" ObstructVision="true" setvalue="true" disabledeltatime="true"/> <StatusEffect type="OnWearing" target="Character" ObstructVision="true" setvalue="true" disabledeltatime="true"/>
<StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5"> <StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">
@@ -10,7 +10,7 @@
<Body width="18" height="6" density="30"/> <Body width="18" height="6" density="30"/>
<Wearable limbtype="Head" slots="Any,Head"> <Wearable limbtype="Head" slots="Any,Face">
<sprite texture ="doctorgear.png" sourcerect="0,120,20,8" limb="Head" origin="0.45,0.9"/> <sprite texture ="doctorgear.png" sourcerect="0,120,20,8" limb="Head" origin="0.45,0.9"/>
</Wearable> </Wearable>
Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

+26 -1
View File
@@ -1,4 +1,29 @@
<Items> <Items>
<Item
name="Headset"
category="Equipment"
pickdistance="150"
tags="smallitem">
<Sprite texture ="headset.png" depth="0.6"/>
<Body radius="8" density="10"/>
<WifiComponent range="20000.0" LinkToChat="true">
<RequiredItems name="Battery Cell" type="Contained"/>
</WifiComponent>
<ItemContainer capacity="1" hideitems="true">
<Containable name="Battery Cell"/>
<Containable name="Fulgurium Battery Cell"/>
</ItemContainer>
<Wearable limbtype="Head" slots="Any,Face">
<StatusEffect type="OnWearing" target="Contained" Condition="-0.1"/>
<sprite texture="headset.png" limb="Head" origin="0.5,0.5"/>
</Wearable>
</Item>
<Item <Item
name="Clown Mask" name="Clown Mask"
category="Equipment" category="Equipment"
@@ -10,7 +35,7 @@
<Body radius="8" density="10"/> <Body radius="8" density="10"/>
<Wearable limbtype="Head" slots="Any,Head"> <Wearable limbtype="Head" slots="Any,Face">
<sprite texture="clownmask.png" limb="Head" origin="0.5,0.5"/> <sprite texture="clownmask.png" limb="Head" origin="0.5,0.5"/>
</Wearable> </Wearable>
</Item> </Item>
+56 -27
View File
@@ -1,17 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Jobs> <Jobs>
<Job name="Captain" description="The Commanding Officer with authority over the entire crew. The captain is responsible for commanding the rest of the crew and trying to keep everything running smoothly." minnumber="1" maxnumber="1"> <Job name="Captain" description="The Commanding Officer with authority over the entire crew. The captain is responsible for commanding the rest of the crew and trying to keep everything running smoothly." minnumber="1" maxnumber="1">
<Item name="ID Card"/>
<Item name="Captain's Cap" equip="true"/>
<Item name="Captain's Jacket" equip="true"/>
<Item name="Captain's Trousers" equip="true"/>
<Skills> <Skills>
<Skill name="Weapons" level="50,60"/> <Skill name="Weapons" level="50,60"/>
<Skill name="Construction" level="20,30"/> <Skill name="Construction" level="20,30"/>
<Skill name="Electrical Engineering" level="20,30"/> <Skill name="Electrical Engineering" level="20,30"/>
<Skill name="Medical" level="10,30"/> <Skill name="Medical" level="10,30"/>
</Skills> </Skills>
<Items>
<Item name="ID Card"/>
<Item name="Captain's Cap" equip="true"/>
<Item name="Captain's Jacket" equip="true"/>
<Item name="Captain's Trousers" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
<Job name="Engineer" description="Engineers have above-average construction and mechanic skills, but fixing complex mechanical devices is still usually out of their skill set. They are competent at fixing electrical devices however, and are the ones to turn to when the power grid starts failing." minnumber="1"> <Job name="Engineer" description="Engineers have above-average construction and mechanic skills, but fixing complex mechanical devices is still usually out of their skill set. They are competent at fixing electrical devices however, and are the ones to turn to when the power grid starts failing." minnumber="1">
@@ -21,10 +25,15 @@
<Skill name="Electrical Engineering" level="50,60"/> <Skill name="Electrical Engineering" level="50,60"/>
<Skill name="Medical" level="10,20"/> <Skill name="Medical" level="10,20"/>
</Skills> </Skills>
<Item name="ID Card"/> <Items>
<Item name="Wrench"/> <Item name="ID Card"/>
<Item name="Screwdriver"/> <Item name="Wrench"/>
<Item name="Orange Jumpsuit" equip="true"/> <Item name="Screwdriver"/>
<Item name="Orange Jumpsuit" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
<Job name="Mechanic" description="Mechanics have high construction and mechanic skills. They are skilled at using tools such as plasma cutters and welders, and are usually the only ones who can fix broken mechanical devices." minnumber="1"> <Job name="Mechanic" description="Mechanics have high construction and mechanic skills. They are skilled at using tools such as plasma cutters and welders, and are usually the only ones who can fix broken mechanical devices." minnumber="1">
@@ -34,10 +43,15 @@
<Skill name="Electrical Engineering" level="30,35"/> <Skill name="Electrical Engineering" level="30,35"/>
<Skill name="Medical" level="10,20"/> <Skill name="Medical" level="10,20"/>
</Skills> </Skills>
<Item name="ID Card"/> <Items>
<Item name="Wrench"/> <Item name="ID Card"/>
<Item name="Screwdriver"/> <Item name="Wrench"/>
<Item name="Blue Jumpsuit" equip="true"/> <Item name="Screwdriver"/>
<Item name="Blue Jumpsuit" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
<Job name="Security Officer" description="Security officers are are responsible for keeping the submarine safe from potential attackers. The creatures inhabiting the ocean aren't the only threat they need to worry about, as several of the renegade groups opposing the Europa Coalition are known to have sent infiltrators on board the vessels." maxnumber="2"> <Job name="Security Officer" description="Security officers are are responsible for keeping the submarine safe from potential attackers. The creatures inhabiting the ocean aren't the only threat they need to worry about, as several of the renegade groups opposing the Europa Coalition are known to have sent infiltrators on board the vessels." maxnumber="2">
@@ -47,12 +61,17 @@
<Skill name="Construction" level="10,20"/> <Skill name="Construction" level="10,20"/>
<Skill name="Electrical Engineering" level="10,20"/> <Skill name="Electrical Engineering" level="10,20"/>
</Skills> </Skills>
<Item name="ID Card"/> <Items>
<Item name="Stun Baton"/> <Item name="ID Card"/>
<Item name="Battery Cell"/> <Item name="Stun Baton"/>
<Item name="Handcuffs"/> <Item name="Battery Cell"/>
<Item name="Body Armor" equip="true"/> <Item name="Handcuffs"/>
<Item name="Ballistic Helmet" equip="true"/> <Item name="Body Armor" equip="true"/>
<Item name="Ballistic Helmet" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
<Job name="Medical Doctor" description="The primary duty of the doctors is too help injured crew members, but their knowledge of chemistry and pharmaceutics can also be useful for creating various non-medicinal chemicals." maxnumber="2"> <Job name="Medical Doctor" description="The primary duty of the doctors is too help injured crew members, but their knowledge of chemistry and pharmaceutics can also be useful for creating various non-medicinal chemicals." maxnumber="2">
@@ -62,11 +81,16 @@
<Skill name="Electrical Engineering" level="10,20"/> <Skill name="Electrical Engineering" level="10,20"/>
<Skill name="Medical" level="50,70"/> <Skill name="Medical" level="50,70"/>
</Skills> </Skills>
<Item name="ID Card"/> <Items>
<Item name="Doctor's Coat" equip="true"/> <Item name="ID Card"/>
<Item name="Doctor's Trousers" equip="true"/> <Item name="Doctor's Coat" equip="true"/>
<Item name="Health Scanner HUD"/> <Item name="Doctor's Trousers" equip="true"/>
<Item name="Medical Syringe"/> <Item name="Health Scanner HUD"/>
<Item name="Medical Syringe"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
<Job name="Assistant" description="Assistants don't have any specific responsibilities or areas of expertise. This job is a good choice for newcomers who want to get a hang of working on board the submarine without taking up tasks that they aren't qualified for." allowalways="true"> <Job name="Assistant" description="Assistants don't have any specific responsibilities or areas of expertise. This job is a good choice for newcomers who want to get a hang of working on board the submarine without taking up tasks that they aren't qualified for." allowalways="true">
@@ -76,8 +100,13 @@
<Skill name="Electrical Engineering" level="20,30"/> <Skill name="Electrical Engineering" level="20,30"/>
<Skill name="Medical" level="10,20"/> <Skill name="Medical" level="10,20"/>
</Skills> </Skills>
<Item name="ID Card"/> <Items>
<Item name="Wrench"/> <Item name="ID Card"/>
<Item name="Screwdriver"/> <Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job> </Job>
</Jobs> </Jobs>
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

+12 -34
View File
@@ -454,7 +454,7 @@ namespace Barotrauma
{ {
AnimController = new HumanoidAnimController(this, doc.Root.Element("ragdoll")); AnimController = new HumanoidAnimController(this, doc.Root.Element("ragdoll"));
AnimController.TargetDir = Direction.Right; AnimController.TargetDir = Direction.Right;
inventory = new CharacterInventory(15, this); inventory = new CharacterInventory(16, this);
} }
else else
{ {
@@ -594,39 +594,7 @@ namespace Barotrauma
{ {
if (info == null || info.Job == null) return; if (info == null || info.Job == null) return;
for (int i = 0; i < info.Job.SpawnItemNames.Count; i++ ) info.Job.GiveJobItems(this, spawnPoint);
{
string itemName = info.Job.SpawnItemNames[i];
ItemPrefab itemPrefab = ItemPrefab.list.Find(ip => ip.Name == itemName) as ItemPrefab;
if (itemPrefab == null)
{
DebugConsole.ThrowError("Tried to spawn ''" + Name + "'' with the item ''" + itemName + "''. Matching item prefab not found.");
continue;
}
Item item = new Item(itemPrefab, Position, null);
if (info.Job.EquipSpawnItem[i])
{
List<LimbSlot> allowedSlots = new List<LimbSlot>(item.AllowedSlots);
allowedSlots.Remove(LimbSlot.Any);
inventory.TryPutItem(item, allowedSlots, false);
}
else
{
inventory.TryPutItem(item, item.AllowedSlots, false);
}
if (item.Prefab.Name == "ID Card" && spawnPoint != null)
{
foreach (string s in spawnPoint.IdCardTags)
{
item.AddTag(s);
}
}
}
} }
public int GetSkillLevel(string skillName) public int GetSkillLevel(string skillName)
@@ -989,6 +957,16 @@ namespace Barotrauma
obstructVisionAmount = Math.Max(obstructVisionAmount - deltaTime, 0.0f); obstructVisionAmount = Math.Max(obstructVisionAmount - deltaTime, 0.0f);
if (inventory!=null)
{
foreach (Item item in inventory.Items)
{
if (item == null || item.body == null || item.body.Enabled) continue;
item.Submarine = Submarine;
item.SetTransform(SimPosition, 0.0f);
}
}
if (isDead) return; if (isDead) return;
if (networkUpdateSent) if (networkUpdateSent)
+57 -6
View File
@@ -26,15 +26,15 @@ namespace Barotrauma
get { return prefab; } get { return prefab; }
} }
public List<string> SpawnItemNames public XElement SpawnItems
{ {
get { return prefab.ItemNames; } get { return prefab.Items; }
} }
public List<bool> EquipSpawnItem //public List<bool> EquipSpawnItem
{ //{
get { return prefab.EquipItem; } // get { return prefab.EquipItem; }
} //}
public List<Skill> Skills public List<Skill> Skills
{ {
@@ -84,6 +84,57 @@ namespace Barotrauma
return (skill==null) ? 0 : skill.Level; return (skill==null) ? 0 : skill.Level;
} }
public void GiveJobItems(Character character, WayPoint spawnPoint)
{
foreach (XElement itemElement in SpawnItems.Elements())
{
InitializeJobItem(character, spawnPoint, itemElement);
}
}
private void InitializeJobItem(Character character, WayPoint spawnPoint, XElement itemElement, Item parentItem = null)
{
string itemName = ToolBox.GetAttributeString(itemElement, "name", "");
ItemPrefab itemPrefab = ItemPrefab.list.Find(ip => ip.Name == itemName) as ItemPrefab;
if (itemPrefab == null)
{
DebugConsole.ThrowError("Tried to spawn ''" + Name + "'' with the item ''" + itemName + "''. Matching item prefab not found.");
return;
}
Item item = new Item(itemPrefab, character.Position, null);
if (ToolBox.GetAttributeBool(itemElement, "equip", false))
{
List<LimbSlot> allowedSlots = new List<LimbSlot>(item.AllowedSlots);
allowedSlots.Remove(LimbSlot.Any);
character.Inventory.TryPutItem(item, allowedSlots, false);
}
else
{
character.Inventory.TryPutItem(item, item.AllowedSlots, false);
}
if (item.Prefab.Name == "ID Card" && spawnPoint != null)
{
foreach (string s in spawnPoint.IdCardTags)
{
item.AddTag(s);
}
}
if (parentItem != null) parentItem.Combine(item);
foreach (XElement childItemElement in itemElement.Elements())
{
InitializeJobItem(character, spawnPoint, childItemElement, item);
}
}
public virtual XElement Save(XElement parentElement) public virtual XElement Save(XElement parentElement)
{ {
XElement jobElement = new XElement("job"); XElement jobElement = new XElement("job");
+15 -9
View File
@@ -10,9 +10,9 @@ namespace Barotrauma
{ {
public static List<JobPrefab> List; public static List<JobPrefab> List;
//names of the items the Character spawns with public readonly XElement Items;
public List<string> ItemNames; public readonly List<string> ItemNames;
public List<bool> EquipItem; //public List<bool> EquipItem;
public List<SkillPrefab> Skills; public List<SkillPrefab> Skills;
@@ -71,7 +71,7 @@ namespace Barotrauma
AllowAlways = ToolBox.GetAttributeBool(element, "allowalways", false); AllowAlways = ToolBox.GetAttributeBool(element, "allowalways", false);
ItemNames = new List<string>(); ItemNames = new List<string>();
EquipItem = new List<bool>(); //EquipItem = new List<bool>();
Skills = new List<SkillPrefab>(); Skills = new List<SkillPrefab>();
@@ -79,14 +79,20 @@ namespace Barotrauma
{ {
switch (subElement.Name.ToString().ToLower()) switch (subElement.Name.ToString().ToLower())
{ {
case "item": case "items":
string itemName = ToolBox.GetAttributeString(subElement, "name", ""); Items = subElement;
bool equipItem = ToolBox.GetAttributeBool(subElement, "equip", false); foreach (XElement itemElement in subElement.Elements())
if (!string.IsNullOrEmpty(itemName))
{ {
string itemName = ToolBox.GetAttributeString(subElement, "name", "");
ItemNames.Add(itemName); ItemNames.Add(itemName);
EquipItem.Add(equipItem);
} }
//string itemName = ToolBox.GetAttributeString(subElement, "name", "");
//bool equipItem = ToolBox.GetAttributeBool(subElement, "equip", false);
//if (!string.IsNullOrEmpty(itemName))
//{
// ItemNames.Add(itemName);
// EquipItem.Add(equipItem);
//}
break; break;
case "skills": case "skills":
foreach (XElement skillElement in subElement.Elements()) foreach (XElement skillElement in subElement.Elements())
+7 -3
View File
@@ -18,8 +18,10 @@ namespace Barotrauma
public enum GUISoundType public enum GUISoundType
{ {
Message = 0, Message,
Click = 1 RadioMessage,
DeadMessage,
Click
} }
public class GUI public class GUI
@@ -75,8 +77,10 @@ namespace Barotrauma
if (loadSounds) if (loadSounds)
{ {
sounds = new Sound[2]; sounds = new Sound[4];
sounds[(int)GUISoundType.Message] = Sound.Load("Content/Sounds/UI/UImsg.ogg", false); sounds[(int)GUISoundType.Message] = Sound.Load("Content/Sounds/UI/UImsg.ogg", false);
sounds[(int)GUISoundType.RadioMessage] = Sound.Load("Content/Sounds/UI/radiomsg.ogg", false);
sounds[(int)GUISoundType.DeadMessage] = Sound.Load("Content/Sounds/UI/deadmsg.ogg", false);
sounds[(int)GUISoundType.Click] = Sound.Load("Content/Sounds/UI/beep-shinymetal.ogg", false); sounds[(int)GUISoundType.Click] = Sound.Load("Content/Sounds/UI/beep-shinymetal.ogg", false);
} }
+6
View File
@@ -72,6 +72,12 @@ namespace Barotrauma
} }
} }
public Color TextColor
{
get { return textBlock.TextColor; }
set { textBlock.TextColor = value; }
}
public override Color HoverColor public override Color HoverColor
{ {
get get
+19 -6
View File
@@ -11,7 +11,7 @@ namespace Barotrauma
[Flags] [Flags]
public enum LimbSlot public enum LimbSlot
{ {
None = 0, Any = 1, RightHand = 2, LeftHand = 4, Head = 8, Torso = 16, Legs = 32 None = 0, Any = 1, RightHand = 2, LeftHand = 4, Head = 8, Torso = 16, Legs = 32, Face=64
}; };
class CharacterInventory : Inventory class CharacterInventory : Inventory
@@ -21,7 +21,7 @@ namespace Barotrauma
private Character character; private Character character;
public static LimbSlot[] limbSlots = new LimbSlot[] { public static LimbSlot[] limbSlots = new LimbSlot[] {
LimbSlot.Head, LimbSlot.Torso, LimbSlot.Legs, LimbSlot.LeftHand, LimbSlot.RightHand, LimbSlot.Head, LimbSlot.Torso, LimbSlot.Legs, LimbSlot.LeftHand, LimbSlot.RightHand, LimbSlot.Face,
LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any,
LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any}; LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any, LimbSlot.Any};
@@ -58,7 +58,7 @@ namespace Barotrauma
case 3: case 3:
case 4: case 4:
SlotPositions[i] = new Vector2( SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 3), spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2),
GameMain.GraphicsHeight - (spacing + rectHeight)*3); GameMain.GraphicsHeight - (spacing + rectHeight)*3);
useOnSelfButton[i - 3] = new GUIButton( useOnSelfButton[i - 3] = new GUIButton(
@@ -70,11 +70,17 @@ namespace Barotrauma
}; };
break;
case 5:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 5),
GameMain.GraphicsHeight - (spacing + rectHeight) * 3);
break; break;
default: default:
SlotPositions[i] = new Vector2( SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 3)%5), spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6)%5),
GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>9) ? 2 : 1)); GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>10) ? 2 : 1));
break; break;
} }
} }
@@ -298,6 +304,13 @@ namespace Barotrauma
new Vector2(18.0f, 20.0f), Vector2.One, new Vector2(18.0f, 20.0f), Vector2.One,
SpriteEffects.None, 0.1f); SpriteEffects.None, 0.1f);
} }
else if (i==5)
{
spriteBatch.Draw(icons, new Vector2(slotRect.Center.X, slotRect.Center.Y),
new Rectangle(57,0,31,32), Color.White * 0.7f, 0.0f,
new Vector2(15.0f, 16.0f), Vector2.One,
SpriteEffects.None, 0.1f);
}
} }
for (int i = 0; i < capacity; i++) for (int i = 0; i < capacity; i++)
@@ -334,7 +347,7 @@ namespace Barotrauma
highlightedSlot = slotRect; highlightedSlot = slotRect;
} }
UpdateSlot(spriteBatch, slotRect, i, Items[i], false, i>4 ? 0.2f : 0.4f); UpdateSlot(spriteBatch, slotRect, i, Items[i], false, i>5 ? 0.2f : 0.4f);
if (draggingItem!=null && draggingItem == Items[i]) draggingItemSlot = slotRect; if (draggingItem!=null && draggingItem == Items[i]) draggingItemSlot = slotRect;
} }
@@ -1,4 +1,6 @@
using Microsoft.Xna.Framework; using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq; using System.Xml.Linq;
@@ -6,11 +8,19 @@ namespace Barotrauma.Items.Components
{ {
class WifiComponent : ItemComponent class WifiComponent : ItemComponent
{ {
private static List<WifiComponent> list = new List<WifiComponent>(); private static List<WifiComponent> list = new List<WifiComponent>();
private float range;
private int channel; private int channel;
[HasDefaultValue(20000.0f, false)]
public float Range
{
get { return range; }
set { range = Math.Max(value, 0.0f); }
}
[InGameEditable, HasDefaultValue(1, true)] [InGameEditable, HasDefaultValue(1, true)]
public int Channel public int Channel
{ {
@@ -21,6 +31,13 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, HasDefaultValue(false, false)]
public bool LinkToChat
{
get;
set;
}
public WifiComponent(Item item, XElement element) public WifiComponent(Item item, XElement element)
: base (item, element) : base (item, element)
{ {
@@ -28,17 +45,52 @@ namespace Barotrauma.Items.Components
list.Add(this); list.Add(this);
} }
public void Transmit(string signal)
{
if (!HasRequiredContainedItems(true)) return;
var receivers = GetReceiversInRange();
foreach (WifiComponent w in receivers)
{
var connections = w.item.Connections;
w.ReceiveSignal(1, signal, connections == null ? null : connections.Find(c => c.Name == "signal_in"), item);
}
}
private List<WifiComponent> GetReceiversInRange()
{
return list.FindAll(w =>
w != this && w.channel == channel &&
Vector2.Distance(item.WorldPosition, w.item.WorldPosition) <= Range);
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f) public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power=0.0f)
{ {
//prevent an ininite loop of wificomponents sending messages between each other if (!HasRequiredContainedItems(false)) return;
if (sender.GetComponent<WifiComponent>()!=null) return;
if (LinkToChat)
{
if (item.ParentInventory != null &&
item.ParentInventory.Owner != null &&
item.ParentInventory.Owner == Character.Controlled &&
GameMain.NetworkMember != null)
{
signal = ChatMessage.ApplyDistanceEffect(item, sender, signal, range);
GameMain.NetworkMember.AddChatMessage(signal, ChatMessageType.Radio);
}
}
if (connection == null) return;
switch (connection.Name) switch (connection.Name)
{ {
case "signal_in": case "signal_in":
foreach (WifiComponent wifiComp in list) var receivers = GetReceiversInRange();
foreach (WifiComponent wifiComp in receivers)
{ {
if (wifiComp == this || wifiComp.channel != channel) continue;
wifiComp.item.SendSignal(stepsTaken, signal, "signal_out"); wifiComp.item.SendSignal(stepsTaken, signal, "signal_out");
} }
break; break;
+2 -2
View File
@@ -213,9 +213,9 @@ namespace Barotrauma
if (linkedTo != null) if (linkedTo != null)
{ {
foreach (MapEntity e in linkedTo) for (int i = linkedTo.Count - 1; i >= 0; i-- )
{ {
e.RemoveLinked(this); linkedTo[i].RemoveLinked(this);
} }
linkedTo.Clear(); linkedTo.Clear();
} }
+136
View File
@@ -0,0 +1,136 @@
using Barotrauma.Items.Components;
using Barotrauma.Networking.ReliableMessages;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma.Networking
{
enum ChatMessageType
{
Default, Error, Dead, Server, Radio
}
class ChatMessage
{
public const float SpeakRange = 2000.0f;
public static Color[] MessageColor = { Color.White, Color.Red, new Color(63, 72, 204), Color.LightGreen, Color.Yellow };
public readonly string Text;
public ChatMessageType Type;
public readonly Character Sender;
public readonly string SenderName;
public Color Color
{
get { return MessageColor[(int)Type]; }
}
public string TextWithSender
{
get;
private set;
}
private ChatMessage(string senderName, string text, ChatMessageType type, Character sender)
{
Text = text;
Type = type;
Sender = sender;
SenderName = senderName;
TextWithSender = string.IsNullOrWhiteSpace(senderName) ? text : senderName + ": " + text;
}
public static ChatMessage Create(string senderName, string text, ChatMessageType type, Character sender)
{
return new ChatMessage(senderName, text, type, sender);
}
public static string GetChatMessageCommand(string message, out string messageWithoutCommand)
{
messageWithoutCommand = message;
int separatorIndex = message.IndexOf(";");
if (separatorIndex == -1) return "";
//int colonIndex = message.IndexOf(":");
string command = "";
try
{
command = message.Substring(0, separatorIndex);
command = command.Trim();
}
catch
{
return command;
}
messageWithoutCommand = message.Substring(separatorIndex + 1, message.Length - separatorIndex - 1).TrimStart();
return command;
}
public string ApplyDistanceEffect(Character listener)
{
if (Sender == null) return Text;
return ApplyDistanceEffect(listener, Sender, Text, SpeakRange);
}
public static string ApplyDistanceEffect(Entity listener, Entity Sender, string text, float range)
{
if (listener.WorldPosition == Sender.WorldPosition) return text;
float dist = Vector2.Distance(listener.WorldPosition, Sender.WorldPosition);
if (dist > range) return "";
if (Submarine.CheckVisibility(listener.SimPosition, Sender.SimPosition) != null) dist *= 2.0f;
if (dist > range) return "";
float garbleAmount = dist / range;
if (garbleAmount < 0.5f) return text;
int startIndex = Math.Max(text.IndexOf(':') + 1, 1);
StringBuilder sb = new StringBuilder(text.Length);
for (int i = 0; i < text.Length; i++)
{
sb.Append((i>startIndex && Rand.Range(0.0f, 1.0f) < garbleAmount) ? '-' : text[i]);
}
return sb.ToString();
}
public void WriteNetworkMessage(NetOutgoingMessage msg)
{
msg.WriteRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length, (byte)Type);
msg.Write(Sender == null ? (ushort)0 : Sender.ID);
msg.Write(SenderName);
msg.Write(Text);
}
public static ChatMessage ReadNetworkMessage(NetBuffer msg)
{
ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length);
ushort senderId = msg.ReadUInt16();
string senderName = msg.ReadString();
string text = msg.ReadString();
return new ChatMessage(senderName, text, type, Entity.FindEntityByID(senderId) as Character);
}
}
}
+23 -7
View File
@@ -5,6 +5,8 @@ using System.Collections.Generic;
using Barotrauma.Networking.ReliableMessages; using Barotrauma.Networking.ReliableMessages;
using FarseerPhysics; using FarseerPhysics;
using System.IO; using System.IO;
using System.Linq;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
@@ -555,9 +557,9 @@ namespace Barotrauma.Networking
break; break;
case (byte)PacketTypes.Chatmessage: case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = (ChatMessageType)inc.ReadByte(); //ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
AddChatMessage(inc.ReadString(), messageType); AddChatMessage(ChatMessage.ReadNetworkMessage(inc));
break; break;
case (byte)PacketTypes.NetworkEvent: case (byte)PacketTypes.NetworkEvent:
//read the data from the message and update client state accordingly //read the data from the message and update client state accordingly
@@ -958,19 +960,33 @@ namespace Barotrauma.Networking
return character; return character;
} }
public override void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Default) public override void SendChatMessage(string message)
{ {
//AddChatMessage(message); //AddChatMessage(message);
if (client.ServerConnection == null) return; if (client.ServerConnection == null) return;
type = (Screen.Selected == GameMain.GameScreen && var type = ChatMessageType.Default;
(myCharacter == null || myCharacter.IsDead)) ? ChatMessageType.Dead : ChatMessageType.Default;
if (Screen.Selected == GameMain.GameScreen && (myCharacter == null || myCharacter.IsDead))
{
type = ChatMessageType.Dead;
}
else
{
string command = ChatMessage.GetChatMessageCommand(message, out message).ToLower();
if (CanUseRadio(Character.Controlled)) type = ChatMessageType.Radio;
}
var chatMessage = ChatMessage.Create(
gameStarted && myCharacter != null ? myCharacter.Name : name,
message, type, gameStarted ? myCharacter : null);
ReliableMessage msg = reliableChannel.CreateMessage(); ReliableMessage msg = reliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type); chatMessage.WriteNetworkMessage(msg.InnerMessage);
msg.InnerMessage.Write(message);
reliableChannel.SendMessage(msg, client.ServerConnection); reliableChannel.SendMessage(msg, client.ServerConnection);
} }
+80 -25
View File
@@ -7,6 +7,7 @@ using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using RestSharp; using RestSharp;
using Barotrauma.Networking.ReliableMessages; using Barotrauma.Networking.ReliableMessages;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
@@ -503,9 +504,10 @@ namespace Barotrauma.Networking
break; break;
case (byte)PacketTypes.Chatmessage: case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = (ChatMessageType)inc.ReadByte(); //SendChatMessage(ChatMessage.ReadNetworkMessage(inc));
//!!!!!!!!!!!
SendChatMessage(inc.ReadString(), messageType); ReadChatMessage(inc);
break; break;
case (byte)PacketTypes.PlayerLeft: case (byte)PacketTypes.PlayerLeft:
@@ -953,7 +955,8 @@ namespace Barotrauma.Networking
GameMain.GameScreen.Select(); GameMain.GameScreen.Select();
AddChatMessage("Press TAB to chat. Use ''d;'' to talk to dead players and spectators, and ''player name;'' to only send the message to a specific player.", ChatMessageType.Server); AddChatMessage("Press TAB to chat. Use ''d;'' to talk to dead players and spectators, "
+"and ''player name;'' to only send the message to a specific player.", ChatMessageType.Server);
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
@@ -1081,7 +1084,7 @@ namespace Barotrauma.Networking
if (string.IsNullOrWhiteSpace(msg)) msg = client.name + " has left the server"; if (string.IsNullOrWhiteSpace(msg)) msg = client.name + " has left the server";
if (string.IsNullOrWhiteSpace(targetmsg)) targetmsg = "You have left the server"; if (string.IsNullOrWhiteSpace(targetmsg)) targetmsg = "You have left the server";
Log(msg, messageColor[(int)ChatMessageType.Server]); Log(msg, ChatMessage.MessageColor[(int)ChatMessageType.Server]);
NetOutgoingMessage outmsg = server.CreateMessage(); NetOutgoingMessage outmsg = server.CreateMessage();
outmsg.Write((byte)PacketTypes.KickedOut); outmsg.Write((byte)PacketTypes.KickedOut);
@@ -1370,33 +1373,79 @@ namespace Barotrauma.Networking
} }
return true; return true;
} }
public override void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Server) private void ReadChatMessage(NetIncomingMessage inc)
{
ChatMessage message = ChatMessage.ReadNetworkMessage(inc);
List<Client> recipients = new List<Client>();
foreach (Client c in ConnectedClients)
{
switch (message.Type)
{
case ChatMessageType.Dead:
if (c.Character != null && !c.Character.IsDead) continue;
break;
case ChatMessageType.Default:
if (message.Sender != null && c.Character != null && message.Sender != c.Character)
{
if (Vector2.Distance(message.Sender.WorldPosition, c.Character.WorldPosition) > ChatMessage.SpeakRange) continue;
}
break;
case ChatMessageType.Radio:
if (message.Sender == null) return;
var radio = message.Sender.Inventory.Items.First(i => i != null && i.GetComponent<WifiComponent>() != null);
if (radio == null) message.Type = ChatMessageType.Default;
break;
}
recipients.Add(c);
}
AddChatMessage(message);
foreach (Client c in recipients)
{
ReliableMessage msg = c.ReliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
//msg.InnerMessage.Write((byte)type);
//msg.InnerMessage.Write(message);
message.WriteNetworkMessage(msg.InnerMessage);
c.ReliableChannel.SendMessage(msg, c.Connection);
}
}
public override void SendChatMessage(string message)
{ {
List<Client> recipients = new List<Client>(); List<Client> recipients = new List<Client>();
Client targetClient = null; Client targetClient = null;
if (type == ChatMessageType.Server) ChatMessageType type = gameStarted && myCharacter != null ? ChatMessageType.Default : ChatMessageType.Server;
string command = ChatMessage.GetChatMessageCommand(message, out message).ToLower();
if (command=="dead" || command=="d")
{ {
string command = GetChatMessageCommand(message).ToLower(); type = ChatMessageType.Dead;
}
else if (command=="radio" || command=="r")
{
if (CanUseRadio(Character.Controlled)) type = ChatMessageType.Radio;
}
else if (command != "")
{
targetClient = ConnectedClients.Find(c =>
command == c.name.ToLower() ||
c.Character != null && command == c.Character.Name.ToLower());
if (command=="dead" || command=="d") if (targetClient == null)
{ {
type = ChatMessageType.Dead; AddChatMessage("Player ''" + command + "'' not found!", ChatMessageType.Error);
} return;
else if (command != "")
{
targetClient = ConnectedClients.Find(c =>
command == c.name.ToLower() ||
c.Character != null && command == c.Character.Name.ToLower());
if (targetClient == null)
{
AddChatMessage("Player ''" + command + "'' not found!", ChatMessageType.Admin);
return;
}
} }
} }
@@ -1412,7 +1461,11 @@ namespace Barotrauma.Networking
} }
} }
AddChatMessage(message, type); var chatMessage = ChatMessage.Create(
gameStarted && myCharacter != null ? myCharacter.Name : name,
message, type, gameStarted ? myCharacter : null);
AddChatMessage(chatMessage);
if (!server.Connections.Any()) return; if (!server.Connections.Any()) return;
@@ -1420,8 +1473,10 @@ namespace Barotrauma.Networking
{ {
ReliableMessage msg = c.ReliableChannel.CreateMessage(); ReliableMessage msg = c.ReliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type); //msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message); //msg.InnerMessage.Write(message);
chatMessage.WriteNetworkMessage(msg.InnerMessage);
c.ReliableChannel.SendMessage(msg, c.Connection); c.ReliableChannel.SendMessage(msg, c.Connection);
} }
+82 -36
View File
@@ -1,9 +1,11 @@
using System; using System;
using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using System.Collections.Generic; using System.Collections.Generic;
using Lidgren.Network; using Lidgren.Network;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
@@ -40,11 +42,6 @@ namespace Barotrauma.Networking
SpectateRequest SpectateRequest
} }
enum ChatMessageType
{
Default, Admin, Dead, Server
}
enum VoteType enum VoteType
{ {
Unknown, Unknown,
@@ -55,9 +52,6 @@ namespace Barotrauma.Networking
class NetworkMember class NetworkMember
{ {
protected static Color[] messageColor = { Color.White, Color.Red, new Color(63,72,204), Color.LightGreen };
protected NetPeer netPeer; protected NetPeer netPeer;
protected string name; protected string name;
@@ -139,6 +133,7 @@ namespace Barotrauma.Networking
chatMsgBox.Font = GUI.SmallFont; chatMsgBox.Font = GUI.SmallFont;
chatMsgBox.Padding = Vector4.Zero; chatMsgBox.Padding = Vector4.Zero;
chatMsgBox.OnEnterPressed = EnterChatMessage; chatMsgBox.OnEnterPressed = EnterChatMessage;
chatMsgBox.OnTextChanged = TypingChatMessage;
Voting = new Voting(); Voting = new Voting();
} }
@@ -183,39 +178,98 @@ namespace Barotrauma.Networking
return message; return message;
} }
public bool TypingChatMessage(GUITextBox textBox, string text)
{
string tempStr;
string command = ChatMessage.GetChatMessageCommand(text, out tempStr);
switch (command)
{
case "r":
case "radio":
textBox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Radio];
break;
case "d":
case "dead":
textBox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Dead];
break;
default:
textBox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Default];
break;
}
return true;
}
public bool CanUseRadio(Character sender)
{
if (sender == null) return false;
var radio = sender.Inventory.Items.First(i => i != null && i.GetComponent<WifiComponent>() != null);
if (radio == null) return false;
var radioComponent = radio.GetComponent<WifiComponent>();
return radioComponent.HasRequiredContainedItems(false);
}
public bool EnterChatMessage(GUITextBox textBox, string message) public bool EnterChatMessage(GUITextBox textBox, string message)
{ {
textBox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Default];
if (string.IsNullOrWhiteSpace(message)) return false; if (string.IsNullOrWhiteSpace(message)) return false;
string senderName = gameStarted && characterInfo != null ? characterInfo.Name : name; SendChatMessage(message);
SendChatMessage(senderName + ": " + message);
textBox.Deselect(); textBox.Deselect();
return true; return true;
} }
public void AddChatMessage(string message, ChatMessageType messageType) public void AddChatMessage(string message, ChatMessageType type, string senderName="", Character senderCharacter = null)
{ {
GameMain.NetLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]); AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter));
}
GameServer.Log(message, messageColor[(int)messageType]); public void AddChatMessage(ChatMessage message)
{
if (message.Type == ChatMessageType.Radio && message.Sender != null && message.Sender != myCharacter)
{
var radio = message.Sender.Inventory.Items.First(i => i != null && i.GetComponent<WifiComponent>() != null);
if (radio == null) return;
var radioComponent = radio.GetComponent<WifiComponent>();
radioComponent.Transmit(message.TextWithSender);
return;
}
string displayedText = message.Text;
if (message.Type == ChatMessageType.Default && myCharacter != null && message.Sender != null)
{
displayedText = message.ApplyDistanceEffect(myCharacter);
if (string.IsNullOrWhiteSpace(displayedText)) return;
}
GameMain.NetLobbyScreen.NewChatMessage(message);
GameServer.Log(message.Text, message.Color);
while (chatBox.CountChildren > 20) while (chatBox.CountChildren > 20)
{ {
chatBox.RemoveChild(chatBox.children[1]); chatBox.RemoveChild(chatBox.children[1]);
} }
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), message, if (!string.IsNullOrWhiteSpace(message.SenderName))
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, messageColor[(int)messageType], {
displayedText = message.SenderName + ": " + displayedText;
}
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), displayedText,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, message.Color,
Alignment.Left, null, null, true); Alignment.Left, null, null, true);
msg.Font = GUI.SmallFont; msg.Font = GUI.SmallFont;
msg.Padding = new Vector4(20.0f, 0, 0, 0); msg.Padding = new Vector4(20.0f, 0, 0, 0);
//float prevScroll = chatBox.BarScroll;
float prevSize = chatBox.BarSize; float prevSize = chatBox.BarSize;
msg.Padding = new Vector4(20, 0, 0, 0); msg.Padding = new Vector4(20, 0, 0, 0);
@@ -223,29 +277,21 @@ namespace Barotrauma.Networking
if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f; if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f;
GUI.PlayUISound(GUISoundType.Message); GUISoundType soundType = GUISoundType.Message;
} if (message.Type == ChatMessageType.Radio)
public virtual void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Server) { }
protected string GetChatMessageCommand(string message)
{
int separatorIndex = message.IndexOf(";");
if (separatorIndex == -1) return "";
int colonIndex = message.IndexOf(":");
string command = "";
try
{ {
command = message.Substring(colonIndex + 2, separatorIndex - colonIndex - 2); soundType = GUISoundType.RadioMessage;
}
else if (message.Type == ChatMessageType.Dead)
{
soundType = GUISoundType.DeadMessage;
} }
catch { } GUI.PlayUISound(soundType);
return command;
} }
public virtual void SendChatMessage(string message) { }
public virtual void Update(float deltaTime) public virtual void Update(float deltaTime)
{ {
if (gameStarted && Screen.Selected == GameMain.GameScreen) if (gameStarted && Screen.Selected == GameMain.GameScreen)
+13 -10
View File
@@ -157,7 +157,6 @@ namespace Barotrauma
chatBox = new GUIListBox(new Rectangle(0,0,0,chatFrame.Rect.Height-80), Color.White, GUI.Style, chatFrame); chatBox = new GUIListBox(new Rectangle(0,0,0,chatFrame.Rect.Height-80), Color.White, GUI.Style, chatFrame);
textBox = new GUITextBox(new Rectangle(0, 25, 0, 25), Alignment.Bottom, GUI.Style, chatFrame); textBox = new GUITextBox(new Rectangle(0, 25, 0, 25), Alignment.Bottom, GUI.Style, chatFrame);
textBox.Font = GUI.SmallFont; textBox.Font = GUI.SmallFont;
textBox.OnEnterPressed = EnterChatMessage;
//player info panel ------------------------------------------------------------ //player info panel ------------------------------------------------------------
@@ -292,6 +291,10 @@ namespace Barotrauma
textBox.Select(); textBox.Select();
textBox.OnEnterPressed = GameMain.NetworkMember.EnterChatMessage;
textBox.OnTextChanged = GameMain.NetworkMember.TypingChatMessage;
Character.Controlled = null; Character.Controlled = null;
//GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; //GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
@@ -753,7 +756,7 @@ namespace Barotrauma
spriteBatch.End(); spriteBatch.End();
} }
public void NewChatMessage(string message, Color color) public void NewChatMessage(ChatMessage message)
{ {
float prevSize = chatBox.BarSize; float prevSize = chatBox.BarSize;
@@ -763,8 +766,8 @@ namespace Barotrauma
} }
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20),
message, message.TextWithSender,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, color, ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, message.Color,
Alignment.Left, GUI.Style, null, true); Alignment.Left, GUI.Style, null, true);
msg.Font = GUI.SmallFont; msg.Font = GUI.SmallFont;
msg.CanBeFocused = false; msg.CanBeFocused = false;
@@ -775,14 +778,14 @@ namespace Barotrauma
if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f; if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f;
} }
public bool EnterChatMessage(GUITextBox textBox, string message) //public bool EnterChatMessage(GUITextBox textBox, string message)
{ //{
if (String.IsNullOrEmpty(message)) return false; // if (String.IsNullOrEmpty(message)) return false;
GameMain.NetworkMember.SendChatMessage(GameMain.NetworkMember.Name + ": " + message); // GameMain.NetworkMember.SendChatMessage(ChatMessage.Create(message, ChatMessageType.Default, null));
return true; // return true;
} //}
private void UpdatePreviewPlayer(CharacterInfo characterInfo) private void UpdatePreviewPlayer(CharacterInfo characterInfo)
{ {