Fixing items if sufficient skills+tools, choosing server port
This commit is contained in:
@@ -150,7 +150,7 @@ namespace Subsurface
|
||||
|
||||
public virtual void Apply(ActionType type, float deltaTime, Vector2 position, IPropertyObject target)
|
||||
{
|
||||
if (!targetNames.Contains(target.Name)) return;
|
||||
if (targetNames == null && !targetNames.Contains(target.Name)) return;
|
||||
|
||||
List<IPropertyObject> targets = new List<IPropertyObject>();
|
||||
targets.Add(target);
|
||||
|
||||
@@ -3,8 +3,20 @@
|
||||
name="Nuclear Reactor"
|
||||
type ="Reactor"
|
||||
linkable="true">
|
||||
|
||||
<trigger/>
|
||||
|
||||
<fixrequirement name="Mechanical repairs">
|
||||
<skill name="Construction" level="40"/>
|
||||
<item name="Welding Tool"/>
|
||||
<item name="Wrench"/>
|
||||
</fixrequirement>
|
||||
|
||||
<fixrequirement name="Electrical repairs">
|
||||
<skill name="Electrical Engineering" level="40"/>
|
||||
<item name="Wire"/>
|
||||
<item name="Screwdriver"/>
|
||||
</fixrequirement>
|
||||
|
||||
<Sprite texture ="reactor.png" depth="0.8"/>
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
<StatusEffect type="OnUse" target="UseTarget" targetnames="Door,Windowed Door" Stuck="10.0"/>
|
||||
|
||||
<Fixable name="structure"/>
|
||||
|
||||
<RequiredSkill name="Construction" level="20"/>
|
||||
|
||||
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-100.0" sound="Content/Items/Weapons/stunGrenade.ogg">
|
||||
<Explosion range="5" damage="20" stun="10" force="5.0"/>
|
||||
</StatusEffect>
|
||||
</RepairTool>
|
||||
|
||||
<Pickable slots="Any,BothHands"/>
|
||||
@@ -44,6 +50,12 @@
|
||||
<StatusEffect type="OnUse" target="UseTarget" targetnames="Door,Windowed Door" Stuck="-10.0"/>
|
||||
|
||||
<Fixable name="structure"/>
|
||||
|
||||
<RequiredSkill name="Construction" level="30"/>
|
||||
|
||||
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-100.0" sound="Content/Items/Weapons/stunGrenade.ogg">
|
||||
<Explosion range="5" damage="20" stun="10" force="5.0"/>
|
||||
</StatusEffect>
|
||||
</RepairTool>
|
||||
|
||||
<Pickable slots="Any,RightHand,LeftHand"/>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<RangedWeapon barrelpos="49,10">
|
||||
<Sound file="harpoon1.ogg" type="OnUse"/>
|
||||
<Sound file="harpoon2.ogg" type="OnUse"/>
|
||||
<RequiredItems name="Spear" type="Contained" msg="Spear required to shoot"/>
|
||||
<RequiredItems name="Spear" type="Contained" msg="Spear required to shoot"/>
|
||||
<RequiredSkill name="Weapons" level="30"/>
|
||||
</RangedWeapon>
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Subsurface
|
||||
public Color TextColor
|
||||
{
|
||||
get { return textColor; }
|
||||
set { textColor = value; }
|
||||
}
|
||||
|
||||
public Vector2 CaretPos
|
||||
@@ -64,16 +65,12 @@ namespace Subsurface
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent = null, bool wrap = false)
|
||||
: this(rect, text, style, Alignment.TopLeft, Alignment.TopLeft, parent, wrap)
|
||||
{
|
||||
//hoverColor = style.hoverColor;
|
||||
//selectedColor = style.selectedColor;
|
||||
}
|
||||
|
||||
|
||||
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false)
|
||||
: this (rect, text, null, null, alignment, textAlignment, style, parent, wrap)
|
||||
{
|
||||
//hoverColor = style.hoverColor;
|
||||
//selectedColor = style.selectedColor;
|
||||
}
|
||||
|
||||
public GUITextBlock(Rectangle rect, string text, Color? color, Color? textColor, Alignment textAlignment = Alignment.Left, GUIStyle style = null, GUIComponent parent = null, bool wrap = false)
|
||||
|
||||
@@ -12,7 +12,18 @@ namespace Subsurface
|
||||
public delegate bool OnSelectedHandler(object obj);
|
||||
public OnSelectedHandler OnSelected;
|
||||
|
||||
bool selected;
|
||||
private bool selected;
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get { return selected; }
|
||||
set
|
||||
{
|
||||
if (value == selected) return;
|
||||
selected = value;
|
||||
state = (selected) ? ComponentState.Selected : ComponentState.None;
|
||||
}
|
||||
}
|
||||
|
||||
public GUITickBox(Rectangle rect, string label, Alignment alignment, GUIComponent parent)
|
||||
: base(null)
|
||||
@@ -20,8 +31,11 @@ namespace Subsurface
|
||||
if (parent != null)
|
||||
parent.AddChild(this);
|
||||
|
||||
box = new GUIFrame(new Rectangle(rect.X, rect.Y, 30, 30), Color.LightGray, null, this);
|
||||
text = new GUITextBlock(new Rectangle(rect.X + 40, rect.Y, 200, 30), label, Color.Transparent, Color.White, Alignment.Left | Alignment.CenterY, null, this);
|
||||
box = new GUIFrame(rect, Color.DarkGray, null, this);
|
||||
box.HoverColor = Color.Gray;
|
||||
box.SelectedColor = Color.DarkGray;
|
||||
|
||||
text = new GUITextBlock(new Rectangle(rect.X + 40, rect.Y, 200, 30), label, Color.Transparent, Color.White, Alignment.TopLeft, null, this);
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
@@ -33,28 +47,31 @@ namespace Subsurface
|
||||
box.State = ComponentState.Hover;
|
||||
|
||||
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed)
|
||||
box.State = ComponentState.Selected;
|
||||
{
|
||||
box.State = ComponentState.Selected;
|
||||
}
|
||||
|
||||
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
selected = !selected;
|
||||
Selected = !Selected;
|
||||
if (OnSelected != null) OnSelected(this);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
box.State = ComponentState.None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
DrawChildren(spriteBatch);
|
||||
|
||||
if (selected)
|
||||
if (Selected)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(box.Rect.X + 5, box.Rect.Y + 5, box.Rect.Width - 10, box.Rect.Height - 10), Color.Green * (color.A / 255.0f), true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(box.Rect.X + 2, box.Rect.Y + 2, box.Rect.Width - 4, box.Rect.Height - 4), Color.Green * 0.8f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Subsurface.Items.Components
|
||||
isActive = true;
|
||||
reload = 1.0f;
|
||||
|
||||
bool failed = UseFailed(character);
|
||||
bool failed = DoesUseFail(character);
|
||||
|
||||
List<Body> limbBodies = new List<Body>();
|
||||
foreach (Limb l in character.AnimController.limbs)
|
||||
|
||||
@@ -93,6 +93,9 @@ namespace Subsurface.Items.Components
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null) return false;
|
||||
if (!character.SecondaryKeyDown.State) return false;
|
||||
|
||||
if (DoesUseFail(character)) return false;
|
||||
|
||||
isActive = true;
|
||||
|
||||
|
||||
@@ -356,24 +356,39 @@ namespace Subsurface
|
||||
}
|
||||
|
||||
public bool HasRequiredSkills(Character character)
|
||||
{
|
||||
Skill temp;
|
||||
return HasRequiredSkills(character, out temp);
|
||||
}
|
||||
|
||||
public bool HasRequiredSkills(Character character, out Skill insufficientSkill)
|
||||
{
|
||||
foreach (Skill skill in requiredSkills)
|
||||
{
|
||||
int characterLevel = character.GetSkillLevel(skill.Name);
|
||||
if (characterLevel < skill.Level) return false;
|
||||
if (characterLevel < skill.Level)
|
||||
{
|
||||
insufficientSkill = skill;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
insufficientSkill = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool UseFailed(Character character)
|
||||
protected bool DoesUseFail(Character character)
|
||||
{
|
||||
foreach (Skill skill in requiredSkills)
|
||||
{
|
||||
int characterLevel = character.GetSkillLevel(skill.Name);
|
||||
if (characterLevel > skill.Level) continue;
|
||||
|
||||
if (Rand.Int(characterLevel) - skill.Level < 0) return true;
|
||||
if (Rand.Int(characterLevel) - skill.Level < 0)
|
||||
{
|
||||
item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
|
||||
//Item.ApplyStatusEffects();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace Subsurface.Items.Components
|
||||
|
||||
float xOffset = (graphTimer / (float)updateGraphInterval);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Temperature: " + (int)temperature + " C", new Vector2(x + 30, y + 30), Color.White);
|
||||
DrawGraph(tempGraph, spriteBatch, x + 30, y + 50, 10000.0f, xOffset);
|
||||
|
||||
186
Subsurface/Items/FixRequirement.cs
Normal file
186
Subsurface/Items/FixRequirement.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
class FixRequirement
|
||||
{
|
||||
string name;
|
||||
|
||||
private static GUIFrame frame;
|
||||
|
||||
List<Skill> requiredSkills;
|
||||
List<string> requiredItems;
|
||||
|
||||
public bool Fixed;
|
||||
|
||||
public FixRequirement(XElement element)
|
||||
{
|
||||
name = ToolBox.GetAttributeString(element, "name", "");
|
||||
|
||||
requiredSkills = new List<Skill>();
|
||||
requiredItems = new List<string>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLower())
|
||||
{
|
||||
case "skill":
|
||||
string skillName = ToolBox.GetAttributeString(subElement, "name", "");
|
||||
int level = ToolBox.GetAttributeInt(subElement, "level", 1);
|
||||
|
||||
requiredSkills.Add(new Skill(skillName, level));
|
||||
break;
|
||||
case "item":
|
||||
string itemName = ToolBox.GetAttributeString(subElement, "name", "");
|
||||
|
||||
requiredItems.Add(itemName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Fix(Character character, GUIComponent reqFrame)
|
||||
{
|
||||
bool success = true;
|
||||
foreach (string itemName in requiredItems)
|
||||
{
|
||||
GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName);
|
||||
|
||||
GUITextBlock text = component as GUITextBlock;
|
||||
bool itemFound = (character.Inventory.items.FirstOrDefault(i => i !=null && i.Name == itemName) != null);
|
||||
|
||||
if (!itemFound) success = false;
|
||||
|
||||
if (text != null) text.TextColor = itemFound ? Color.LightGreen : Color.Red;
|
||||
}
|
||||
|
||||
foreach (Skill skill in requiredSkills)
|
||||
{
|
||||
GUIComponent component = reqFrame.children.Find(c => c.UserData as Skill == skill);
|
||||
GUITextBlock text = component as GUITextBlock;
|
||||
|
||||
float characterSkill = character.GetSkillLevel(skill.Name);
|
||||
bool sufficientSkill = characterSkill >= skill.Level;
|
||||
|
||||
if (!sufficientSkill) success = false;
|
||||
|
||||
if (text != null) text.TextColor = sufficientSkill ? Color.LightGreen : Color.Red;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private static void CreateGUIFrame(Item item)
|
||||
{
|
||||
int width = 400, height = 500;
|
||||
int x = 0, y = 0;
|
||||
|
||||
frame = new GUIFrame(new Rectangle(0, 0, width, height), Color.White * 0.8f, Alignment.Center, GUI.style);
|
||||
frame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
frame.UserData = item;
|
||||
|
||||
new GUITextBlock(new Rectangle(0,0,200,20), "Attempting to fix " + item.Name, GUI.style, frame);
|
||||
|
||||
y = y + 40;
|
||||
foreach (FixRequirement requirement in item.FixRequirements)
|
||||
{
|
||||
GUIFrame reqFrame = new GUIFrame(
|
||||
new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15),
|
||||
Color.Transparent, null, frame);
|
||||
reqFrame.UserData = requirement;
|
||||
|
||||
|
||||
var fixButton = new GUIButton(new Rectangle(0, 0, 50, 20), "Fix", GUI.style, reqFrame);
|
||||
fixButton.OnClicked = FixButtonPressed;
|
||||
fixButton.UserData = requirement;
|
||||
|
||||
new GUITickBox(new Rectangle(70, 0, 20,20), requirement.name, Alignment.Left, reqFrame);
|
||||
|
||||
int y2 = 20;
|
||||
foreach (string itemName in requirement.requiredItems)
|
||||
{
|
||||
var itemBlock = new GUITextBlock(new Rectangle(30, y2, 200, 15), itemName, GUI.style, reqFrame);
|
||||
itemBlock.Font = GUI.SmallFont;
|
||||
itemBlock.UserData = itemName;
|
||||
|
||||
y2 += 15;
|
||||
}
|
||||
|
||||
y2 = 20;
|
||||
foreach (Skill skill in requirement.requiredSkills)
|
||||
{
|
||||
var skillBlock = new GUITextBlock(new Rectangle(150, y2, 200, 15), skill.Name + " - " + skill.Level, GUI.style, Alignment.Right, Alignment.TopLeft, reqFrame);
|
||||
skillBlock.Font = GUI.SmallFont;
|
||||
skillBlock.UserData = skill;
|
||||
|
||||
|
||||
y2 += 15;
|
||||
}
|
||||
|
||||
y += reqFrame.Rect.Height;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool FixButtonPressed(GUIButton button, object obj)
|
||||
{
|
||||
FixRequirement requirement = obj as FixRequirement;
|
||||
if (requirement == null) return false;
|
||||
|
||||
requirement.Fixed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void UpdateGUIFrame(Item item, Character character)
|
||||
{
|
||||
bool unfixedFound = false;
|
||||
foreach (GUIComponent child in frame.children)
|
||||
{
|
||||
FixRequirement requirement = child.UserData as FixRequirement;
|
||||
if (requirement == null) continue;
|
||||
|
||||
if (requirement.Fixed)
|
||||
{
|
||||
child.Color = Color.LightGreen * 0.3f;
|
||||
child.GetChild<GUITickBox>().Selected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool canBeFixed = requirement.Fix(character, child);
|
||||
unfixedFound = true;
|
||||
//child.GetChild<GUITickBox>().Selected = canBeFixed;
|
||||
GUITickBox tickBox = child.GetChild<GUITickBox>();
|
||||
if (tickBox.Selected)
|
||||
{
|
||||
tickBox.Selected = canBeFixed;
|
||||
requirement.Fixed = canBeFixed;
|
||||
|
||||
}
|
||||
child.Color = Color.Red * 0.2f;
|
||||
//tickBox.State = GUIComponent.ComponentState.None;
|
||||
}
|
||||
}
|
||||
if (!unfixedFound)
|
||||
{
|
||||
item.Condition = 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawHud(SpriteBatch spriteBatch, Item item, Character character)
|
||||
{
|
||||
if (frame == null || frame.UserData != item)
|
||||
{
|
||||
CreateGUIFrame(item);
|
||||
|
||||
}
|
||||
UpdateGUIFrame(item, character);
|
||||
frame.Update((float)Physics.step);
|
||||
frame.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Subsurface
|
||||
|
||||
public enum ActionType
|
||||
{
|
||||
OnPicked, OnWearing, OnContaining, OnContained, OnActive, OnUse
|
||||
OnPicked, OnWearing, OnContaining, OnContained, OnActive, OnUse, OnFailure
|
||||
}
|
||||
|
||||
class Item : MapEntity, IDamageable, IPropertyObject
|
||||
@@ -27,6 +27,7 @@ namespace Subsurface
|
||||
|
||||
private List<string> tags;
|
||||
|
||||
|
||||
public Hull CurrentHull;
|
||||
|
||||
//components that determine the functionality of the item
|
||||
@@ -47,6 +48,8 @@ namespace Subsurface
|
||||
|
||||
public Item container;
|
||||
|
||||
public List<FixRequirement> FixRequirements;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return prefab.Name; }
|
||||
@@ -57,7 +60,6 @@ namespace Subsurface
|
||||
get { return prefab.sprite; }
|
||||
}
|
||||
|
||||
|
||||
public float Condition
|
||||
{
|
||||
get { return condition; }
|
||||
@@ -69,6 +71,7 @@ namespace Subsurface
|
||||
get { return condition; }
|
||||
}
|
||||
|
||||
|
||||
[Editable, HasDefaultValue("", true)]
|
||||
public string Tags
|
||||
{
|
||||
@@ -181,17 +184,13 @@ namespace Subsurface
|
||||
{
|
||||
prefab = itemPrefab;
|
||||
|
||||
linkedTo = new ObservableCollection<MapEntity>();
|
||||
components = new List<ItemComponent>();
|
||||
|
||||
tags = new List<string>();
|
||||
linkedTo = new ObservableCollection<MapEntity>();
|
||||
components = new List<ItemComponent>();
|
||||
FixRequirements = new List<FixRequirement>();
|
||||
tags = new List<string>();
|
||||
|
||||
rect = newRect;
|
||||
//rect.X -= rect.Width / 2;
|
||||
//rect.Y += rect.Height / 2;
|
||||
|
||||
//dir = 1.0f;
|
||||
|
||||
|
||||
FindHull();
|
||||
|
||||
condition = 100.0f;
|
||||
@@ -210,21 +209,8 @@ namespace Subsurface
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
properties = ObjectProperty.InitProperties(this, element);
|
||||
|
||||
//foreach (XAttribute attribute in element.Attributes())
|
||||
//{
|
||||
// ObjectProperty property = null;
|
||||
// if (!properties.TryGetValue(attribute.Name.ToString().ToLower(), out property)) continue;
|
||||
// if (property.Attributes.OfType<Initable>().Count() == 0) continue;
|
||||
// property.TrySetValue(attribute.Value);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//highlightText = new List<string>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLower())
|
||||
@@ -240,6 +226,9 @@ namespace Subsurface
|
||||
aiTarget.SightRange = ToolBox.GetAttributeFloat(subElement, "sightrange", 1000.0f);
|
||||
aiTarget.SoundRange = ToolBox.GetAttributeFloat(subElement, "soundrange", 0.0f);
|
||||
break;
|
||||
case "fixrequirement":
|
||||
FixRequirements.Add(new FixRequirement(subElement));
|
||||
break;
|
||||
default:
|
||||
ItemComponent ic = ItemComponent.Load(subElement, this, prefab.ConfigFile);
|
||||
if (ic == null) break;
|
||||
@@ -638,16 +627,23 @@ namespace Subsurface
|
||||
|
||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (editingHUD==null || editingHUD.UserData as Item != this)
|
||||
if (condition>0.0f)
|
||||
{
|
||||
editingHUD = CreateEditingHUD(true);
|
||||
if (editingHUD==null || editingHUD.UserData as Item != this)
|
||||
{
|
||||
editingHUD = CreateEditingHUD(true);
|
||||
}
|
||||
|
||||
editingHUD.Draw(spriteBatch);
|
||||
|
||||
foreach (ItemComponent ic in components)
|
||||
{
|
||||
ic.DrawHUD(spriteBatch, character);
|
||||
}
|
||||
}
|
||||
|
||||
editingHUD.Draw(spriteBatch);
|
||||
|
||||
foreach (ItemComponent ic in components)
|
||||
else
|
||||
{
|
||||
ic.DrawHUD(spriteBatch, character);
|
||||
FixRequirement.DrawHud(spriteBatch, this, character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,9 +726,16 @@ namespace Subsurface
|
||||
bool hasRequiredSkills = true;
|
||||
|
||||
bool picked = false, selected = false;
|
||||
|
||||
Skill requiredSkill = null;
|
||||
|
||||
foreach (ItemComponent ic in components)
|
||||
{
|
||||
if (!ic.HasRequiredSkills(picker)) hasRequiredSkills = false;
|
||||
Skill tempRequiredSkill;
|
||||
if (!ic.HasRequiredSkills(picker, out tempRequiredSkill)) hasRequiredSkills = false;
|
||||
|
||||
if (tempRequiredSkill != null) requiredSkill = tempRequiredSkill;
|
||||
|
||||
if (!ic.HasRequiredItems(picker, picker == Character.Controlled) && !forcePick) continue;
|
||||
if ((ic.CanBePicked && ic.Pick(picker)) || (ic.CanBeSelected && ic.Select(picker)))
|
||||
{
|
||||
@@ -751,6 +754,10 @@ namespace Subsurface
|
||||
if (!hasRequiredSkills && Character.Controlled==picker)
|
||||
{
|
||||
GUI.AddMessage("Your skills may be insufficient to use the item!", Color.Red, 5.0f);
|
||||
if (requiredSkill != null)
|
||||
{
|
||||
GUI.AddMessage("("+requiredSkill.Name+" level "+requiredSkill.Level+" required)", Color.Red, 5.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (container!=null) container.RemoveContained(this);
|
||||
|
||||
@@ -25,9 +25,6 @@ namespace Subsurface
|
||||
//how close the character has to be to the item to pick it up
|
||||
private float pickDistance;
|
||||
|
||||
|
||||
//public List<Sound> sounds;
|
||||
|
||||
//an area next to the construction
|
||||
//the construction can be Activated() by a character inside the area
|
||||
public List<Rectangle> Triggers;
|
||||
@@ -144,40 +141,19 @@ namespace Subsurface
|
||||
name = ToolBox.GetAttributeString(element, "name", "");
|
||||
if (name == "") DebugConsole.ThrowError("Unnamed item in "+filePath+"!");
|
||||
|
||||
//if (element.Attribute("sprite") != null)
|
||||
//{
|
||||
// sprite = new Sprite(Path.GetDirectoryName(filePath) + "/" + element.Attribute("sprite").Value, new Vector2(0.5f, 0.5f));
|
||||
// sprite.Depth = 0.5f;
|
||||
//}
|
||||
|
||||
//var initableProperties = GetProperties<Initable>();
|
||||
//foreach (ObjectProperty initableProperty in initableProperties)
|
||||
//{
|
||||
// object value = ToolBox.GetAttributeObject(element, initableProperty.Name.ToLower());
|
||||
// if (value == null)
|
||||
// {
|
||||
// foreach (var ini in initableProperty.Attributes.OfType<Initable>())
|
||||
// {
|
||||
// value = ini.defaultValue;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// initableProperty.TrySetValue(value);
|
||||
//}
|
||||
|
||||
pickDistance = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "pickdistance", 0.0f));
|
||||
|
||||
isLinkable = ToolBox.GetAttributeBool(element, "linkable", false);
|
||||
isLinkable = ToolBox.GetAttributeBool(element, "linkable", false);
|
||||
|
||||
resizeHorizontal = ToolBox.GetAttributeBool(element, "resizehorizontal", false);
|
||||
resizeVertical = ToolBox.GetAttributeBool(element, "resizevertical", false);
|
||||
resizeHorizontal = ToolBox.GetAttributeBool(element, "resizehorizontal", false);
|
||||
resizeVertical = ToolBox.GetAttributeBool(element, "resizevertical", false);
|
||||
|
||||
focusOnSelected = ToolBox.GetAttributeBool(element, "focusonselected", false);
|
||||
focusOnSelected = ToolBox.GetAttributeBool(element, "focusonselected", false);
|
||||
|
||||
offsetOnSelected = ToolBox.GetAttributeFloat(element, "offsetonselected", 0.0f);
|
||||
offsetOnSelected = ToolBox.GetAttributeFloat(element, "offsetonselected", 0.0f);
|
||||
|
||||
Triggers = new List<Rectangle>();
|
||||
Triggers = new List<Rectangle>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLower())
|
||||
@@ -201,18 +177,6 @@ namespace Subsurface
|
||||
}
|
||||
}
|
||||
|
||||
//sounds = new List<Sound>();
|
||||
//var soundElements = element.Descendants();
|
||||
//foreach (XElement soundElement in soundElements)
|
||||
//{
|
||||
// if (soundElement.Name.ToString().ToLower() != "sound") continue;
|
||||
// string soundPath = ToolBox.GetAttributeString(soundElement, "path", "");
|
||||
// if (soundPath == "") continue;
|
||||
|
||||
// Sound sound = Sound.Load(soundPath);
|
||||
// if (sound != null) sounds.Add(sound);
|
||||
//}
|
||||
|
||||
list.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Subsurface
|
||||
{
|
||||
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, position)/range;
|
||||
|
||||
c.AddDamage(limb.SimPosition, DamageType.None, damage * distFactor, 0.0f, stun * distFactor);
|
||||
c.AddDamage(limb.SimPosition, DamageType.None, damage / c.AnimController.limbs.Length * distFactor, 0.0f, stun * distFactor);
|
||||
|
||||
if (force>0.0f)
|
||||
{
|
||||
|
||||
@@ -6,22 +6,20 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Subsurface.Networking
|
||||
{
|
||||
|
||||
|
||||
class GameClient : NetworkMember
|
||||
{
|
||||
NetClient Client;
|
||||
private NetClient client;
|
||||
|
||||
private Character myCharacter;
|
||||
private CharacterInfo characterInfo;
|
||||
|
||||
GUIMessageBox reconnectBox;
|
||||
private GUIMessageBox reconnectBox;
|
||||
|
||||
private bool connected;
|
||||
|
||||
private int myID;
|
||||
|
||||
List<Client> otherClients;
|
||||
private List<Client> otherClients;
|
||||
|
||||
private string serverIP;
|
||||
|
||||
@@ -48,11 +46,28 @@ namespace Subsurface.Networking
|
||||
characterInfo = new CharacterInfo("Content/Characters/Human/human.xml", name);
|
||||
|
||||
otherClients = new List<Client>();
|
||||
|
||||
}
|
||||
|
||||
public void ConnectToServer(string hostIP)
|
||||
{
|
||||
serverIP = hostIP;
|
||||
|
||||
string[] address = hostIP.Split(':');
|
||||
if (address.Length==1)
|
||||
{
|
||||
serverIP = hostIP;
|
||||
Port = DefaultPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverIP = address[0];
|
||||
|
||||
if (!int.TryParse(address[1], out Port))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid port: address[1]!");
|
||||
Port = DefaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
myCharacter = Character.Controlled;
|
||||
|
||||
@@ -63,10 +78,10 @@ namespace Subsurface.Networking
|
||||
//Config.SimulatedMinimumLatency = 0.25f;
|
||||
|
||||
// Create new client, with previously created configs
|
||||
Client = new NetClient(Config);
|
||||
client = new NetClient(Config);
|
||||
|
||||
NetOutgoingMessage outmsg = Client.CreateMessage();
|
||||
Client.Start();
|
||||
NetOutgoingMessage outmsg = client.CreateMessage();
|
||||
client.Start();
|
||||
|
||||
outmsg.Write((byte)PacketTypes.Login);
|
||||
outmsg.Write(Game1.Version.ToString());
|
||||
@@ -75,7 +90,7 @@ namespace Subsurface.Networking
|
||||
// Connect client, to ip previously requested from user
|
||||
try
|
||||
{
|
||||
Client.Connect(hostIP, 14242, outmsg);
|
||||
client.Connect(serverIP, Port, outmsg);
|
||||
}
|
||||
catch (ArgumentNullException e)
|
||||
{
|
||||
@@ -133,7 +148,7 @@ namespace Subsurface.Networking
|
||||
|
||||
NetIncomingMessage inc;
|
||||
// If new messages arrived
|
||||
if ((inc = Client.ReadMessage()) == null) continue;
|
||||
if ((inc = client.ReadMessage()) == null) continue;
|
||||
|
||||
// Switch based on the message types
|
||||
switch (inc.MessageType)
|
||||
@@ -192,7 +207,7 @@ namespace Subsurface.Networking
|
||||
reconnectBox = null;
|
||||
}
|
||||
|
||||
if (Client.ConnectionStatus != NetConnectionStatus.Connected)
|
||||
if (client.ConnectionStatus != NetConnectionStatus.Connected)
|
||||
{
|
||||
var reconnect = new GUIMessageBox("CONNECTION FAILED", "Failed to connect to server.", new string[] { "Retry", "Cancel" });
|
||||
reconnect.Buttons[0].OnClicked += RetryConnection;
|
||||
@@ -226,7 +241,7 @@ namespace Subsurface.Networking
|
||||
|
||||
if (!connected || updateTimer > DateTime.Now) return;
|
||||
|
||||
if (Client.ConnectionStatus == NetConnectionStatus.Disconnected && reconnectBox==null)
|
||||
if (client.ConnectionStatus == NetConnectionStatus.Disconnected && reconnectBox==null)
|
||||
{
|
||||
reconnectBox = new GUIMessageBox("CONNECTION LOST", "You have been disconnected from the server. Reconnecting...", new string[0]);
|
||||
connected = false;
|
||||
@@ -255,13 +270,13 @@ namespace Subsurface.Networking
|
||||
|
||||
foreach (NetworkEvent networkEvent in NetworkEvent.events)
|
||||
{
|
||||
NetOutgoingMessage message = Client.CreateMessage();
|
||||
NetOutgoingMessage message = client.CreateMessage();
|
||||
message.Write((byte)PacketTypes.NetworkEvent);
|
||||
|
||||
|
||||
if (networkEvent.FillData(message))
|
||||
{
|
||||
Client.SendMessage(message,
|
||||
client.SendMessage(message,
|
||||
(networkEvent.IsImportant) ? NetDeliveryMethod.ReliableUnordered : NetDeliveryMethod.Unreliable);
|
||||
}
|
||||
}
|
||||
@@ -284,7 +299,7 @@ namespace Subsurface.Networking
|
||||
// Create new incoming message holder
|
||||
NetIncomingMessage inc;
|
||||
|
||||
while ((inc = Client.ReadMessage()) != null)
|
||||
while ((inc = client.ReadMessage()) != null)
|
||||
{
|
||||
if (inc.MessageType != NetIncomingMessageType.Data) continue;
|
||||
|
||||
@@ -406,18 +421,18 @@ namespace Subsurface.Networking
|
||||
|
||||
public override void Disconnect()
|
||||
{
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.PlayerLeft);
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
Client.Shutdown("");
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
client.Shutdown("");
|
||||
}
|
||||
|
||||
public void SendCharacterData()
|
||||
{
|
||||
if (characterInfo == null) return;
|
||||
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.CharacterInfo);
|
||||
msg.Write(characterInfo.Name);
|
||||
msg.Write(characterInfo.Gender == Gender.Male);
|
||||
@@ -431,7 +446,7 @@ namespace Subsurface.Networking
|
||||
msg.Write(jobPreferences[i].Name);
|
||||
}
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
private Character ReadCharacterData(NetIncomingMessage inc)
|
||||
@@ -486,12 +501,12 @@ namespace Subsurface.Networking
|
||||
|
||||
type = (gameStarted && myCharacter != null && myCharacter.IsDead) ? ChatMessageType.Dead : ChatMessageType.Default;
|
||||
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Chatmessage);
|
||||
msg.Write((byte)type);
|
||||
msg.Write(message);
|
||||
|
||||
Client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -500,7 +515,7 @@ namespace Subsurface.Networking
|
||||
/// </summary>
|
||||
public void SendRandomData()
|
||||
{
|
||||
NetOutgoingMessage msg = Client.CreateMessage();
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
switch (Rand.Int(5))
|
||||
{
|
||||
case 0:
|
||||
@@ -531,7 +546,7 @@ namespace Subsurface.Networking
|
||||
}
|
||||
|
||||
|
||||
Client.SendMessage(msg, (Rand.Int(2)==0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable);
|
||||
client.SendMessage(msg, (Rand.Int(2)==0) ? NetDeliveryMethod.ReliableOrdered : NetDeliveryMethod.Unreliable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@ namespace Subsurface.Networking
|
||||
|
||||
class NetworkMember
|
||||
{
|
||||
protected static Color[] messageColor = { Color.White, Color.Red, Color.LightBlue, Color.LightGreen };
|
||||
public const int DefaultPort = 14242;
|
||||
|
||||
protected static Color[] messageColor = { Color.White, Color.Red, Color.LightBlue, Color.LightGreen };
|
||||
|
||||
protected string name;
|
||||
|
||||
protected TimeSpan updateInterval;
|
||||
@@ -39,6 +41,8 @@ namespace Subsurface.Networking
|
||||
protected GUIFrame inGameHUD;
|
||||
protected GUIListBox chatBox;
|
||||
|
||||
public int Port;
|
||||
|
||||
protected bool gameStarted;
|
||||
|
||||
public string Name
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Subsurface
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server IP:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.JoinServer]);
|
||||
ipBox = new GUITextBox(new Rectangle(0, 130, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.JoinServer]);
|
||||
|
||||
|
||||
GUIButton joinButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Join", Alignment.BottomCenter, GUI.style, menuTabs[(int)Tabs.JoinServer]);
|
||||
joinButton.OnClicked = JoinServer;
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Subsurface
|
||||
selectedTab = (int)obj;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private bool HostServerClicked(GUIButton button, object obj)
|
||||
{
|
||||
Game1.NetLobbyScreen.IsServer = true;
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<Compile Include="Characters\AI\SteeringPath.cs" />
|
||||
<Compile Include="CoroutineManager.cs" />
|
||||
<Compile Include="GUI\TitleScreen.cs" />
|
||||
<Compile Include="Items\FixRequirement.cs" />
|
||||
<Compile Include="Map\LocationType.cs" />
|
||||
<Compile Include="Rand.cs" />
|
||||
<Compile Include="Events\PropertyTask.cs" />
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user