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

View File

@@ -38,7 +38,7 @@
<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"/>
<StatusEffect type="OnWearing" target="Character" ObstructVision="true" setvalue="true" disabledeltatime="true"/>
<StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">

View File

@@ -10,7 +10,7 @@
<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"/>
</Wearable>

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@@ -1,4 +1,29 @@
<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
name="Clown Mask"
category="Equipment"
@@ -10,7 +35,7 @@
<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"/>
</Wearable>
</Item>

View File

@@ -1,17 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<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">
<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>
<Skill name="Weapons" level="50,60"/>
<Skill name="Construction" level="20,30"/>
<Skill name="Electrical Engineering" level="20,30"/>
<Skill name="Medical" level="10,30"/>
</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 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="Medical" level="10,20"/>
</Skills>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Orange Jumpsuit" equip="true"/>
<Items>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Orange Jumpsuit" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</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">
@@ -34,10 +43,15 @@
<Skill name="Electrical Engineering" level="30,35"/>
<Skill name="Medical" level="10,20"/>
</Skills>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Blue Jumpsuit" equip="true"/>
<Items>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Blue Jumpsuit" equip="true"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</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">
@@ -47,12 +61,17 @@
<Skill name="Construction" level="10,20"/>
<Skill name="Electrical Engineering" level="10,20"/>
</Skills>
<Item name="ID Card"/>
<Item name="Stun Baton"/>
<Item name="Battery Cell"/>
<Item name="Handcuffs"/>
<Item name="Body Armor" equip="true"/>
<Item name="Ballistic Helmet" equip="true"/>
<Items>
<Item name="ID Card"/>
<Item name="Stun Baton"/>
<Item name="Battery Cell"/>
<Item name="Handcuffs"/>
<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 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="Medical" level="50,70"/>
</Skills>
<Item name="ID Card"/>
<Item name="Doctor's Coat" equip="true"/>
<Item name="Doctor's Trousers" equip="true"/>
<Item name="Health Scanner HUD"/>
<Item name="Medical Syringe"/>
<Items>
<Item name="ID Card"/>
<Item name="Doctor's Coat" equip="true"/>
<Item name="Doctor's Trousers" equip="true"/>
<Item name="Health Scanner HUD"/>
<Item name="Medical Syringe"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</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">
@@ -76,8 +100,13 @@
<Skill name="Electrical Engineering" level="20,30"/>
<Skill name="Medical" level="10,20"/>
</Skills>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Items>
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
<Item name="Headset" equip="true">
<Item name="Battery Cell"/>
</Item>
</Items>
</Job>
</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

View File

@@ -454,7 +454,7 @@ namespace Barotrauma
{
AnimController = new HumanoidAnimController(this, doc.Root.Element("ragdoll"));
AnimController.TargetDir = Direction.Right;
inventory = new CharacterInventory(15, this);
inventory = new CharacterInventory(16, this);
}
else
{
@@ -594,39 +594,7 @@ namespace Barotrauma
{
if (info == null || info.Job == null) return;
for (int i = 0; i < info.Job.SpawnItemNames.Count; i++ )
{
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);
}
}
}
info.Job.GiveJobItems(this, spawnPoint);
}
public int GetSkillLevel(string skillName)
@@ -988,6 +956,16 @@ namespace Barotrauma
if (!Enabled) return;
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;

View File

@@ -26,15 +26,15 @@ namespace Barotrauma
get { return prefab; }
}
public List<string> SpawnItemNames
public XElement SpawnItems
{
get { return prefab.ItemNames; }
get { return prefab.Items; }
}
public List<bool> EquipSpawnItem
{
get { return prefab.EquipItem; }
}
//public List<bool> EquipSpawnItem
//{
// get { return prefab.EquipItem; }
//}
public List<Skill> Skills
{
@@ -84,6 +84,57 @@ namespace Barotrauma
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)
{
XElement jobElement = new XElement("job");

View File

@@ -10,9 +10,9 @@ namespace Barotrauma
{
public static List<JobPrefab> List;
//names of the items the Character spawns with
public List<string> ItemNames;
public List<bool> EquipItem;
public readonly XElement Items;
public readonly List<string> ItemNames;
//public List<bool> EquipItem;
public List<SkillPrefab> Skills;
@@ -71,7 +71,7 @@ namespace Barotrauma
AllowAlways = ToolBox.GetAttributeBool(element, "allowalways", false);
ItemNames = new List<string>();
EquipItem = new List<bool>();
//EquipItem = new List<bool>();
Skills = new List<SkillPrefab>();
@@ -79,14 +79,20 @@ namespace Barotrauma
{
switch (subElement.Name.ToString().ToLower())
{
case "item":
string itemName = ToolBox.GetAttributeString(subElement, "name", "");
bool equipItem = ToolBox.GetAttributeBool(subElement, "equip", false);
if (!string.IsNullOrEmpty(itemName))
case "items":
Items = subElement;
foreach (XElement itemElement in subElement.Elements())
{
string itemName = ToolBox.GetAttributeString(subElement, "name", "");
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;
case "skills":
foreach (XElement skillElement in subElement.Elements())

View File

@@ -18,8 +18,10 @@ namespace Barotrauma
public enum GUISoundType
{
Message = 0,
Click = 1
Message,
RadioMessage,
DeadMessage,
Click
}
public class GUI
@@ -75,8 +77,10 @@ namespace Barotrauma
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.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);
}

View File

@@ -72,6 +72,12 @@ namespace Barotrauma
}
}
public Color TextColor
{
get { return textBlock.TextColor; }
set { textBlock.TextColor = value; }
}
public override Color HoverColor
{
get

View File

@@ -11,7 +11,7 @@ namespace Barotrauma
[Flags]
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
@@ -21,7 +21,7 @@ namespace Barotrauma
private Character character;
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};
@@ -58,7 +58,7 @@ namespace Barotrauma
case 3:
case 4:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 3),
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2),
GameMain.GraphicsHeight - (spacing + rectHeight)*3);
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;
default:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 3)%5),
GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>9) ? 2 : 1));
spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6)%5),
GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>10) ? 2 : 1));
break;
}
}
@@ -298,6 +304,13 @@ namespace Barotrauma
new Vector2(18.0f, 20.0f), Vector2.One,
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++)
@@ -334,7 +347,7 @@ namespace Barotrauma
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;
}

View File

@@ -1,4 +1,6 @@
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -6,11 +8,19 @@ namespace Barotrauma.Items.Components
{
class WifiComponent : ItemComponent
{
private static List<WifiComponent> list = new List<WifiComponent>();
private float range;
private int channel;
[HasDefaultValue(20000.0f, false)]
public float Range
{
get { return range; }
set { range = Math.Max(value, 0.0f); }
}
[InGameEditable, HasDefaultValue(1, true)]
public int Channel
{
@@ -21,24 +31,66 @@ namespace Barotrauma.Items.Components
}
}
[Editable, HasDefaultValue(false, false)]
public bool LinkToChat
{
get;
set;
}
public WifiComponent(Item item, XElement element)
: base (item, element)
{
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)
{
//prevent an ininite loop of wificomponents sending messages between each other
if (sender.GetComponent<WifiComponent>()!=null) return;
if (!HasRequiredContainedItems(false)) 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)
{
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");
}
break;

View File

@@ -213,9 +213,9 @@ namespace Barotrauma
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();
}

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);
}
}
}

View File

@@ -5,6 +5,8 @@ using System.Collections.Generic;
using Barotrauma.Networking.ReliableMessages;
using FarseerPhysics;
using System.IO;
using System.Linq;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking
{
@@ -555,9 +557,9 @@ namespace Barotrauma.Networking
break;
case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
//ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
AddChatMessage(inc.ReadString(), messageType);
AddChatMessage(ChatMessage.ReadNetworkMessage(inc));
break;
case (byte)PacketTypes.NetworkEvent:
//read the data from the message and update client state accordingly
@@ -958,19 +960,33 @@ namespace Barotrauma.Networking
return character;
}
public override void SendChatMessage(string message, ChatMessageType type = ChatMessageType.Default)
public override void SendChatMessage(string message)
{
//AddChatMessage(message);
if (client.ServerConnection == null) return;
type = (Screen.Selected == GameMain.GameScreen &&
(myCharacter == null || myCharacter.IsDead)) ? ChatMessageType.Dead : ChatMessageType.Default;
var type = 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();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
chatMessage.WriteNetworkMessage(msg.InnerMessage);
reliableChannel.SendMessage(msg, client.ServerConnection);
}

View File

@@ -7,6 +7,7 @@ using Lidgren.Network;
using Microsoft.Xna.Framework;
using RestSharp;
using Barotrauma.Networking.ReliableMessages;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking
{
@@ -503,9 +504,10 @@ namespace Barotrauma.Networking
break;
case (byte)PacketTypes.Chatmessage:
ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
//SendChatMessage(ChatMessage.ReadNetworkMessage(inc));
//!!!!!!!!!!!
SendChatMessage(inc.ReadString(), messageType);
ReadChatMessage(inc);
break;
case (byte)PacketTypes.PlayerLeft:
@@ -953,7 +955,8 @@ namespace Barotrauma.Networking
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;
}
@@ -1081,7 +1084,7 @@ namespace Barotrauma.Networking
if (string.IsNullOrWhiteSpace(msg)) msg = client.name + " has 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();
outmsg.Write((byte)PacketTypes.KickedOut);
@@ -1370,33 +1373,79 @@ namespace Barotrauma.Networking
}
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>();
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;
}
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;
}
AddChatMessage("Player ''" + command + "'' not found!", ChatMessageType.Error);
return;
}
}
@@ -1411,8 +1460,12 @@ namespace Barotrauma.Networking
if (type != ChatMessageType.Dead || (c.Character == null || c.Character.IsDead)) recipients.Add(c);
}
}
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;
@@ -1420,8 +1473,10 @@ namespace Barotrauma.Networking
{
ReliableMessage msg = c.ReliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
msg.InnerMessage.Write((byte)type);
msg.InnerMessage.Write(message);
//msg.InnerMessage.Write((byte)type);
//msg.InnerMessage.Write(message);
chatMessage.WriteNetworkMessage(msg.InnerMessage);
c.ReliableChannel.SendMessage(msg, c.Connection);
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;
using Lidgren.Network;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking
{
@@ -40,11 +42,6 @@ namespace Barotrauma.Networking
SpectateRequest
}
enum ChatMessageType
{
Default, Admin, Dead, Server
}
enum VoteType
{
Unknown,
@@ -55,9 +52,6 @@ namespace Barotrauma.Networking
class NetworkMember
{
protected static Color[] messageColor = { Color.White, Color.Red, new Color(63,72,204), Color.LightGreen };
protected NetPeer netPeer;
protected string name;
@@ -139,6 +133,7 @@ namespace Barotrauma.Networking
chatMsgBox.Font = GUI.SmallFont;
chatMsgBox.Padding = Vector4.Zero;
chatMsgBox.OnEnterPressed = EnterChatMessage;
chatMsgBox.OnTextChanged = TypingChatMessage;
Voting = new Voting();
}
@@ -183,39 +178,98 @@ namespace Barotrauma.Networking
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)
{
textBox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Default];
if (string.IsNullOrWhiteSpace(message)) return false;
string senderName = gameStarted && characterInfo != null ? characterInfo.Name : name;
SendChatMessage(senderName + ": " + message);
SendChatMessage(message);
textBox.Deselect();
return true;
}
public void AddChatMessage(string message, ChatMessageType messageType)
{
GameMain.NetLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]);
GameServer.Log(message, messageColor[(int)messageType]);
public void AddChatMessage(string message, ChatMessageType type, string senderName="", Character senderCharacter = null)
{
AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter));
}
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)
{
chatBox.RemoveChild(chatBox.children[1]);
}
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), message,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, messageColor[(int)messageType],
if (!string.IsNullOrWhiteSpace(message.SenderName))
{
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);
msg.Font = GUI.SmallFont;
msg.Padding = new Vector4(20.0f, 0, 0, 0);
//float prevScroll = chatBox.BarScroll;
float prevSize = chatBox.BarSize;
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;
GUI.PlayUISound(GUISoundType.Message);
}
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
GUISoundType soundType = GUISoundType.Message;
if (message.Type == ChatMessageType.Radio)
{
command = message.Substring(colonIndex + 2, separatorIndex - colonIndex - 2);
soundType = GUISoundType.RadioMessage;
}
else if (message.Type == ChatMessageType.Dead)
{
soundType = GUISoundType.DeadMessage;
}
catch { }
return command;
GUI.PlayUISound(soundType);
}
public virtual void SendChatMessage(string message) { }
public virtual void Update(float deltaTime)
{
if (gameStarted && Screen.Selected == GameMain.GameScreen)

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);
textBox = new GUITextBox(new Rectangle(0, 25, 0, 25), Alignment.Bottom, GUI.Style, chatFrame);
textBox.Font = GUI.SmallFont;
textBox.OnEnterPressed = EnterChatMessage;
//player info panel ------------------------------------------------------------
@@ -292,6 +291,10 @@ namespace Barotrauma
textBox.Select();
textBox.OnEnterPressed = GameMain.NetworkMember.EnterChatMessage;
textBox.OnTextChanged = GameMain.NetworkMember.TypingChatMessage;
Character.Controlled = null;
//GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
@@ -753,7 +756,7 @@ namespace Barotrauma
spriteBatch.End();
}
public void NewChatMessage(string message, Color color)
public void NewChatMessage(ChatMessage message)
{
float prevSize = chatBox.BarSize;
@@ -763,8 +766,8 @@ namespace Barotrauma
}
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20),
message,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, color,
message.TextWithSender,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, message.Color,
Alignment.Left, GUI.Style, null, true);
msg.Font = GUI.SmallFont;
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;
}
public bool EnterChatMessage(GUITextBox textBox, string message)
{
if (String.IsNullOrEmpty(message)) return false;
//public bool EnterChatMessage(GUITextBox textBox, string message)
//{
// 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)
{