v0.1
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
struct LimbPos
|
||||
{
|
||||
public LimbType limbType;
|
||||
public Vector2 position;
|
||||
}
|
||||
|
||||
class Controller : ItemComponent
|
||||
{
|
||||
//where the limbs of the user should be positioned when using the controller
|
||||
List<LimbPos> limbPositions;
|
||||
|
||||
Direction dir;
|
||||
|
||||
//the x-position where the user walks to when using the controller
|
||||
float userPos;
|
||||
|
||||
Camera cam;
|
||||
|
||||
Character character;
|
||||
|
||||
[HasDefaultValue(1.0f,false)]
|
||||
public float UserPos
|
||||
{
|
||||
set { userPos = value; }
|
||||
}
|
||||
|
||||
public Controller(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
limbPositions = new List<LimbPos>();
|
||||
|
||||
dir = (Direction)Enum.Parse(typeof(Direction), ToolBox.GetAttributeString(element, "direction", "None"), true);
|
||||
|
||||
foreach (XElement el in element.Elements())
|
||||
{
|
||||
if (el.Name != "limbposition") continue;
|
||||
|
||||
LimbPos lp = new LimbPos();
|
||||
try
|
||||
{
|
||||
lp.limbType = (LimbType)Enum.Parse(typeof(LimbType), el.Attribute("limb").Value, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + element + ": " + e.Message, e);
|
||||
}
|
||||
|
||||
lp.position = ToolBox.GetAttributeVector2(el, "position", Vector2.Zero);
|
||||
|
||||
limbPositions.Add(lp);
|
||||
}
|
||||
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
this.cam = cam;
|
||||
|
||||
if (character == null || character.SelectedConstruction != item)
|
||||
{
|
||||
if (character != null)
|
||||
{
|
||||
character.SelectedConstruction = null;
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
character = null;
|
||||
}
|
||||
isActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, character);
|
||||
|
||||
if (userPos != 0.0f && character.AnimController.Anim != AnimController.Animation.UsingConstruction)
|
||||
{
|
||||
Limb torso = character.AnimController.GetLimb(LimbType.Torso);
|
||||
float torsoX = ConvertUnits.ToDisplayUnits(torso.SimPosition.X);
|
||||
|
||||
if (Math.Abs(torsoX - item.Rect.X + userPos) > 10.0f)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
|
||||
character.AnimController.TargetMovement =
|
||||
new Vector2(
|
||||
Math.Min(Math.Max(item.Rect.X + userPos - torsoX, -1.0f), 1.0f),
|
||||
0.0f);
|
||||
character.AnimController.TargetDir = (Math.Sign(torsoX - item.Rect.X + userPos) == 1) ? Direction.Right : Direction.Left;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (limbPositions.Count == 0) return;
|
||||
|
||||
character.AnimController.Anim = AnimController.Animation.UsingConstruction;
|
||||
character.AnimController.ResetPullJoints();
|
||||
if (dir != 0) character.AnimController.TargetDir = dir;
|
||||
|
||||
foreach (LimbPos lb in limbPositions)
|
||||
{
|
||||
Limb limb = character.AnimController.GetLimb(lb.limbType);
|
||||
if (limb == null) continue;
|
||||
|
||||
FixedMouseJoint fmj = limb.pullJoint;
|
||||
if (fmj == null) continue;
|
||||
|
||||
Vector2 position = ConvertUnits.ToSimUnits(lb.position + new Vector2(item.Rect.X, item.Rect.Y));
|
||||
fmj.Enabled = true;
|
||||
fmj.WorldAnchorB = position;
|
||||
}
|
||||
|
||||
//foreach (MapEntity e in item.linkedTo)
|
||||
//{
|
||||
// Item linkedItem = e as Item;
|
||||
// if (linkedItem == null) continue;
|
||||
// linkedItem.Update(cam, deltaTime);
|
||||
//}
|
||||
|
||||
item.SendSignal(ToolBox.Vector2ToString(character.CursorPosition), "position_out");
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character activator = null)
|
||||
{
|
||||
//character = activator;
|
||||
//foreach (MapEntity e in item.linkedTo)
|
||||
//{
|
||||
// Item linkedItem = e as Item;
|
||||
// if (linkedItem == null) continue;
|
||||
// linkedItem.Use(deltaTime, activator);
|
||||
//}
|
||||
|
||||
item.SendSignal("1", "trigger_out");
|
||||
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SecondaryUse(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null) return;
|
||||
|
||||
foreach (Connection c in item.Connections)
|
||||
{
|
||||
if (c.Name != "position_out") continue;
|
||||
|
||||
foreach (Connection c2 in c.Recipients)
|
||||
{
|
||||
if (c2 == null || c2.Item==null || !c2.Item.Prefab.FocusOnSelected) continue;
|
||||
|
||||
Vector2 centerPos = c2.Item.Position;
|
||||
|
||||
if (character == Character.Controlled && cam != null)
|
||||
{
|
||||
Lights.LightManager.ViewPos = centerPos;
|
||||
cam.TargetPos = c2.Item.Position;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//foreach (MapEntity e in item.linkedTo)
|
||||
//{
|
||||
// Item linkedItem = e as Item;
|
||||
// if (linkedItem == null) continue;
|
||||
// linkedItem.SecondaryUse(deltaTime, character);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
item.SendSignal("1", "signal_out");
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Select(Character activator = null)
|
||||
{
|
||||
if (character!=null && character.SelectedConstruction == item)
|
||||
{
|
||||
character = null;
|
||||
isActive = false;
|
||||
if (activator != null) activator.AnimController.Anim = AnimController.Animation.None;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
character = activator;
|
||||
if (activator == null) return false;
|
||||
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
item.SendSignal("1", "signal_out");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class Engine : Powered
|
||||
{
|
||||
|
||||
float force;
|
||||
|
||||
float targetForce;
|
||||
|
||||
float maxForce;
|
||||
|
||||
float powerPerForce;
|
||||
|
||||
[Editable, HasDefaultValue(1.0f, true)]
|
||||
public float PowerPerForce
|
||||
{
|
||||
get { return powerPerForce; }
|
||||
set
|
||||
{
|
||||
powerPerForce = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(2000.0f, true)]
|
||||
public float MaxForce
|
||||
{
|
||||
get { return maxForce; }
|
||||
set
|
||||
{
|
||||
maxForce = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
public float Force
|
||||
{
|
||||
get { return force;}
|
||||
set { force = MathHelper.Clamp(value, -100.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public Engine(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public float CurrentVolume
|
||||
{
|
||||
get { return Math.Abs((force / 100.0f) * (voltage / minVoltage)); }
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
currPowerConsumption = Math.Abs(targetForce) * powerPerForce;
|
||||
|
||||
Force = MathHelper.Lerp(force, (voltage < minVoltage) ? 0.0f : targetForce, 0.1f);
|
||||
if (Force != 0.0f)
|
||||
{
|
||||
Vector2 currForce = new Vector2((force / 100.0f) * maxForce * (voltage / minVoltage), 0.0f);
|
||||
|
||||
Submarine.Loaded.ApplyForce(currForce);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
Game1.ParticleManager.CreateParticle("bubbles", item.SimPosition,
|
||||
-currForce/500.0f + new Vector2(Rand.Range(-1.0f, 1.0f), Rand.Range(-0.5f, 0.5f)));
|
||||
}
|
||||
}
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
//isActive = true;
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
//int width = 300, height = 300;
|
||||
//int x = Game1.GraphicsWidth / 2 - width / 2;
|
||||
//int y = Game1.GraphicsHeight / 2 - height / 2 - 50;
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(GuiFrame.Rect.X + 280, GuiFrame.Rect.Y + 30, 40, 40), "+", true)) targetForce += 1.0f;
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(GuiFrame.Rect.X + 280, GuiFrame.Rect.Y + 80, 40, 40), "-", true)) targetForce -= 1.0f;
|
||||
|
||||
item.NewComponentEvent(this, true);
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
force = MathHelper.Lerp(force, 0.0f, 0.1f);
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f)
|
||||
{
|
||||
base.ReceiveSignal(signal, connection, sender, power);
|
||||
|
||||
if (connection.Name == "set_force")
|
||||
{
|
||||
float tempForce;
|
||||
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out tempForce))
|
||||
{
|
||||
targetForce = tempForce;
|
||||
targetForce = MathHelper.Clamp(targetForce, -100.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
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.Items.Components
|
||||
{
|
||||
class FabricableItem
|
||||
{
|
||||
//public static List<FabricableItem> list = new List<FabricableItem>();
|
||||
|
||||
//public readonly string[] FabricatorTags;
|
||||
|
||||
public readonly ItemPrefab TargetItem;
|
||||
|
||||
public readonly List<ItemPrefab> RequiredItems;
|
||||
|
||||
public readonly float RequiredTime;
|
||||
|
||||
|
||||
//ListOrSomething requiredLevels
|
||||
|
||||
public FabricableItem(XElement element)
|
||||
{
|
||||
string name = ToolBox.GetAttributeString(element, "name", "").ToLower();
|
||||
|
||||
TargetItem = ItemPrefab.list.Find(ip => ip.Name.ToLower() == name) as ItemPrefab;
|
||||
if (TargetItem == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in Fabricable Item! Item ''" + element.Name + "'' not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
RequiredItems = new List<ItemPrefab>();
|
||||
|
||||
string[] requiredItemNames = ToolBox.GetAttributeString(element, "requireditems", "").Split(',');
|
||||
foreach (string requiredItemName in requiredItemNames)
|
||||
{
|
||||
ItemPrefab requiredItem = ItemPrefab.list.Find(ip => ip.Name.ToLower() == requiredItemName.Trim().ToLower()) as ItemPrefab;
|
||||
if (requiredItem == null) continue;
|
||||
RequiredItems.Add(requiredItem);
|
||||
}
|
||||
|
||||
RequiredTime = ToolBox.GetAttributeFloat(element, "requiredtime", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
class Fabricator : ItemComponent
|
||||
{
|
||||
List<FabricableItem> fabricableItems;
|
||||
|
||||
GUIListBox itemList;
|
||||
|
||||
GUIFrame selectedItemFrame;
|
||||
|
||||
FabricableItem fabricatedItem;
|
||||
float timeUntilReady;
|
||||
|
||||
public Fabricator(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
fabricableItems = new List<FabricableItem>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString() != "fabricableitem") continue;
|
||||
|
||||
FabricableItem fabricableItem = new FabricableItem(subElement);
|
||||
if (fabricableItem.TargetItem != null) fabricableItems.Add(fabricableItem);
|
||||
|
||||
}
|
||||
|
||||
int width = 400, height = 300;
|
||||
itemList = new GUIListBox(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, Game1.GraphicsHeight / 2 - height / 2, width, height), Color.White * 0.7f);
|
||||
itemList.OnSelected = SelectItem;
|
||||
//structureList.CheckSelected = MapEntityPrefab.GetSelected;
|
||||
|
||||
foreach (FabricableItem fi in fabricableItems)
|
||||
{
|
||||
Color color = ((itemList.CountChildren % 2) == 0) ? Color.White : Color.LightGray;
|
||||
|
||||
//GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, itemList);
|
||||
//frame.UserData = fi;
|
||||
//frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
//frame.Color = color;
|
||||
//frame.HoverColor = Color.Gold * 0.2f;
|
||||
//frame.SelectedColor = Color.Gold * 0.5f;
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25), fi.TargetItem.Name,
|
||||
color, Color.Black,
|
||||
Alignment.Left, Alignment.Left, null, itemList);
|
||||
textBlock.UserData = fi;
|
||||
textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
|
||||
//if (fi.TargetItem.sprite != null)
|
||||
//{
|
||||
// GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), fi.TargetItem.sprite, Alignment.Left, frame);
|
||||
// img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
private bool SelectItem(object obj)
|
||||
{
|
||||
FabricableItem targetItem = obj as FabricableItem;
|
||||
if (targetItem == null) return false;
|
||||
|
||||
int width = 200, height = 150;
|
||||
selectedItemFrame = new GUIFrame(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, itemList.Rect.Bottom+20, width, height), Color.Black*0.8f);
|
||||
//selectedItemFrame.Padding = GUI.style.smallPadding;
|
||||
|
||||
if (targetItem.TargetItem.sprite != null)
|
||||
{
|
||||
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), targetItem.TargetItem.sprite, Alignment.CenterX, selectedItemFrame);
|
||||
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
|
||||
|
||||
string text = targetItem.TargetItem.Name + "\n";
|
||||
text += "Required items:\n";
|
||||
foreach (ItemPrefab ip in targetItem.RequiredItems)
|
||||
{
|
||||
text += " - " + ip.Name + "\n";
|
||||
}
|
||||
text += "Required time: "+targetItem.RequiredTime+" s";
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 25),
|
||||
text,
|
||||
Color.Transparent, Color.White,
|
||||
Alignment.CenterX | Alignment.CenterY,
|
||||
Alignment.Left, null,
|
||||
selectedItemFrame);
|
||||
|
||||
GUIButton button = new GUIButton(new Rectangle(0,0,100,20), "Create", Color.White, Alignment.CenterX | Alignment.Bottom, GUI.style, selectedItemFrame);
|
||||
button.OnClicked = StartFabricating;
|
||||
button.UserData = targetItem;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
return (picker != null);
|
||||
}
|
||||
|
||||
private bool StartFabricating(GUIButton button, object obj)
|
||||
{
|
||||
GUIComponent listElement = itemList.GetChild(obj);
|
||||
|
||||
listElement.Color = Color.Green;
|
||||
itemList.Enabled = false;
|
||||
|
||||
fabricatedItem = obj as FabricableItem;
|
||||
isActive = true;
|
||||
|
||||
timeUntilReady = fabricatedItem.RequiredTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
timeUntilReady -= deltaTime;
|
||||
|
||||
if (timeUntilReady > 0.0f) return;
|
||||
|
||||
ItemContainer container = item.GetComponent<ItemContainer>();
|
||||
foreach (ItemPrefab ip in fabricatedItem.RequiredItems)
|
||||
{
|
||||
var requiredItem = Array.Find(container.inventory.items, it => it != null && it.Prefab == ip);
|
||||
container.inventory.RemoveItem(requiredItem);
|
||||
}
|
||||
|
||||
new Item(fabricatedItem.TargetItem, item.Position);
|
||||
|
||||
isActive = false;
|
||||
fabricatedItem = null;
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
FabricableItem targetItem = itemList.SelectedData as FabricableItem;
|
||||
if (targetItem != null)
|
||||
{
|
||||
selectedItemFrame.GetChild<GUIButton>().Enabled = true;
|
||||
|
||||
ItemContainer container = item.GetComponent<ItemContainer>();
|
||||
foreach (ItemPrefab ip in targetItem.RequiredItems)
|
||||
{
|
||||
if (Array.Find(container.inventory.items, it => it != null && it.Prefab == ip) != null) continue;
|
||||
selectedItemFrame.GetChild<GUIButton>().Enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
itemList.Update(0.016f);
|
||||
itemList.Draw(spriteBatch);
|
||||
|
||||
if (selectedItemFrame != null)
|
||||
{
|
||||
selectedItemFrame.Update(0.016f);
|
||||
selectedItemFrame.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class MiniMap : Powered
|
||||
{
|
||||
|
||||
public MiniMap(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
currPowerConsumption = powerConsumption;
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
if (picker == null) return false;
|
||||
|
||||
//picker.SelectedConstruction = item;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x,y,width,height), Color.Black, true);
|
||||
|
||||
Rectangle miniMap = new Rectangle(x + 20, y + 40, width - 40, height - 60);
|
||||
|
||||
float size = Math.Min((float)miniMap.Width / (float)Submarine.Borders.Width, (float)miniMap.Height / (float)Submarine.Borders.Height);
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
Rectangle hullRect = new Rectangle(
|
||||
miniMap.X + (int)((hull.Rect.X - Submarine.Borders.X) * size),
|
||||
miniMap.Y - (int)((hull.Rect.Y - Submarine.Borders.Y) * size),
|
||||
(int)(hull.Rect.Width * size),
|
||||
(int)(hull.Rect.Height * size));
|
||||
|
||||
float waterAmount = Math.Min(hull.Volume / hull.FullVolume, 1.0f);
|
||||
|
||||
if (hullRect.Height * waterAmount > 1.0f)
|
||||
{
|
||||
Rectangle waterRect = new Rectangle(
|
||||
hullRect.X,
|
||||
(int)(hullRect.Y + hullRect.Height * (1.0f - waterAmount)),
|
||||
hullRect.Width,
|
||||
(int)(hullRect.Height * waterAmount));
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, waterRect, Color.DarkBlue, true);
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, hullRect, Color.White);
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull!=null) continue;
|
||||
|
||||
Rectangle characterRect = new Rectangle(
|
||||
miniMap.X + (int)((c.Position.X - Submarine.Borders.X) * size),
|
||||
miniMap.Y - (int)((c.Position.Y - Submarine.Borders.Y) * size),
|
||||
5, 5);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, characterRect, Color.White, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class OxygenGenerator : Powered
|
||||
{
|
||||
PropertyTask powerUpTask;
|
||||
|
||||
float powerDownTimer;
|
||||
|
||||
bool running;
|
||||
|
||||
List<Vent> ventList;
|
||||
|
||||
public bool IsRunning()
|
||||
{
|
||||
return (running && item.Condition>0.0f);
|
||||
}
|
||||
|
||||
public OxygenGenerator(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
isActive = true;
|
||||
|
||||
ventList = new List<Vent>();
|
||||
|
||||
item.linkedTo.CollectionChanged += delegate(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{ GetVents(); };
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
currPowerConsumption = powerConsumption;
|
||||
|
||||
if (item.CurrentHull == null) return;
|
||||
|
||||
if (voltage < minVoltage)
|
||||
{
|
||||
powerDownTimer += deltaTime;
|
||||
running = false;
|
||||
if ((powerUpTask==null || powerUpTask.IsFinished) && powerDownTimer>5.0f)
|
||||
{
|
||||
powerUpTask = new PropertyTask(item, IsRunning, 50.0f, "Turn on the oxygen generator");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerDownTimer = 0.0f;
|
||||
}
|
||||
|
||||
running = true;
|
||||
|
||||
float deltaOxygen = Math.Min(voltage, 1.0f) * 50000.0f;
|
||||
item.CurrentHull.Oxygen += deltaOxygen * deltaTime;
|
||||
|
||||
UpdateVents(deltaOxygen);
|
||||
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
powerDownTimer += deltaTime;
|
||||
}
|
||||
|
||||
private void GetVents()
|
||||
{
|
||||
foreach (MapEntity entity in item.linkedTo)
|
||||
{
|
||||
Item linkedItem = entity as Item;
|
||||
if (linkedItem == null) continue;
|
||||
|
||||
Vent vent = linkedItem.GetComponent<Vent>();
|
||||
if (vent != null) ventList.Add(vent);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVents(float deltaOxygen)
|
||||
{
|
||||
if (ventList.Count == 0) return;
|
||||
|
||||
deltaOxygen = deltaOxygen / ventList.Count;
|
||||
foreach (Vent v in ventList)
|
||||
{
|
||||
v.OxygenFlow = deltaOxygen;
|
||||
v.IsActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class Pump : Powered
|
||||
{
|
||||
float flowPercentage;
|
||||
float maxFlow;
|
||||
|
||||
float? targetLevel;
|
||||
|
||||
Hull hull1, hull2;
|
||||
|
||||
[HasDefaultValue(0.0f, true)]
|
||||
private float FlowPercentage
|
||||
{
|
||||
get { return flowPercentage; }
|
||||
set
|
||||
{
|
||||
if (float.IsNaN(flowPercentage)) return;
|
||||
flowPercentage = MathHelper.Clamp(value,-100.0f,100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
[HasDefaultValue(100.0f, false)]
|
||||
public float MaxFlow
|
||||
{
|
||||
get { return maxFlow; }
|
||||
set { maxFlow = value; }
|
||||
}
|
||||
|
||||
public Pump(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
item.linkedTo.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{ GetHulls(); };
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (targetLevel != null)
|
||||
{
|
||||
float hullPercentage = 0.0f;
|
||||
if (hull1 != null) hullPercentage = (hull1.Volume / hull1.FullVolume) * 100.0f;
|
||||
flowPercentage = ((float)targetLevel - hullPercentage);
|
||||
}
|
||||
|
||||
|
||||
currPowerConsumption = powerConsumption * Math.Abs(flowPercentage / 100.0f);
|
||||
|
||||
if (voltage < minVoltage) return;
|
||||
|
||||
if (hull2 == null && hull1 == null) return;
|
||||
|
||||
float powerFactor = (currPowerConsumption==0.0f) ? 1.0f : voltage;
|
||||
//flowPercentage = maxFlow * powerFactor;
|
||||
|
||||
float deltaVolume = 0.0f;
|
||||
|
||||
deltaVolume = (flowPercentage/100.0f) * maxFlow * powerFactor;
|
||||
|
||||
|
||||
hull1.Volume += deltaVolume;
|
||||
if (hull1.Volume > hull1.FullVolume) hull1.Pressure += 0.5f;
|
||||
|
||||
if (hull2 != null)
|
||||
{
|
||||
hull2.Volume -= deltaVolume;
|
||||
if (hull2.Volume > hull1.FullVolume) hull2.Pressure += 0.5f;
|
||||
}
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
private void GetHulls()
|
||||
{
|
||||
hull1 = null;
|
||||
hull2 = null;
|
||||
|
||||
foreach (MapEntity e in item.linkedTo)
|
||||
{
|
||||
Hull hull = e as Hull;
|
||||
if (hull == null) continue;
|
||||
|
||||
if (hull1 == null)
|
||||
{
|
||||
hull1 = hull;
|
||||
}
|
||||
else if (hull2 == null && hull != hull1)
|
||||
{
|
||||
hull2 = hull;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 20, y + 20, 100, 40), ((isActive) ? "TURN OFF" : "TURN ON")))
|
||||
{
|
||||
targetLevel = null;
|
||||
isActive = !isActive;
|
||||
if (!isActive) currPowerConsumption = 0.0f;
|
||||
}
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Flow percentage: " + (int)flowPercentage + " %", new Vector2(x + 20, y + 80), Color.White);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 200, y + 70, 40, 40), "+", true)) FlowPercentage += 1.0f;
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 250, y + 70, 40, 40), "-", true)) FlowPercentage -= 1.0f;
|
||||
|
||||
|
||||
item.NewComponentEvent(this, true);
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f)
|
||||
{
|
||||
base.ReceiveSignal(signal, connection, sender, power);
|
||||
|
||||
if (connection.Name == "toggle")
|
||||
{
|
||||
isActive = !isActive;
|
||||
}
|
||||
else if (connection.Name == "set_active")
|
||||
{
|
||||
isActive = (signal != "0");
|
||||
}
|
||||
else if (connection.Name == "set_speed")
|
||||
{
|
||||
float tempSpeed;
|
||||
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out tempSpeed))
|
||||
{
|
||||
flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
else if (connection.Name == "set_targetlevel")
|
||||
{
|
||||
float tempTarget;
|
||||
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out tempTarget))
|
||||
{
|
||||
targetLevel = MathHelper.Clamp(tempTarget, 0.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isActive) currPowerConsumption = 0.0f;
|
||||
}
|
||||
|
||||
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message)
|
||||
{
|
||||
message.Write(flowPercentage);
|
||||
message.Write(isActive);
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
|
||||
{
|
||||
float newFlow = 0.0f;
|
||||
bool newActive;
|
||||
|
||||
try
|
||||
{
|
||||
newFlow = message.ReadFloat();
|
||||
newActive = message.ReadBoolean();
|
||||
}
|
||||
|
||||
catch { return; }
|
||||
|
||||
FlowPercentage = newFlow;
|
||||
isActive = newActive;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using FarseerPhysics;
|
||||
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.Items.Components
|
||||
{
|
||||
class Radar : Powered
|
||||
{
|
||||
private float range;
|
||||
|
||||
private float pingState;
|
||||
|
||||
private Sprite pingCircle, screenOverlay;
|
||||
|
||||
[HasDefaultValue(0.0f, false)]
|
||||
public float Range
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(range); }
|
||||
set { range = ConvertUnits.ToSimUnits(value); }
|
||||
}
|
||||
|
||||
public Radar(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLower())
|
||||
{
|
||||
case "pingcircle":
|
||||
pingCircle = new Sprite(subElement);
|
||||
break;
|
||||
case "screenoverlay":
|
||||
screenOverlay = new Sprite(subElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//renderTarget = new RenderTarget2D(Game1.CurrGraphicsDevice, GuiFrame.Rect.Width, GuiFrame.Rect.Height);
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
if (voltage>=minVoltage)
|
||||
{
|
||||
pingState = (pingState + deltaTime * 0.5f);
|
||||
if (pingState>1.0f)
|
||||
{
|
||||
item.Use(deltaTime, null);
|
||||
pingState = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pingState = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
return (pingState > 1.0f);
|
||||
}
|
||||
|
||||
public override void DrawHUD(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
if (voltage < minVoltage) return;
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x+20, y+20, 200, 30), "Activate Radar")) isActive = !isActive;
|
||||
|
||||
int radius = GuiFrame.Rect.Height / 2 - 10;
|
||||
DrawRadar(spriteBatch, new Rectangle((int)GuiFrame.Center.X - radius, (int)GuiFrame.Center.Y - radius, radius * 2, radius * 2));
|
||||
|
||||
//voltage = 0.0f;
|
||||
}
|
||||
|
||||
private void DrawRadar(SpriteBatch spriteBatch, Rectangle rect)
|
||||
{
|
||||
|
||||
Vector2 center = new Vector2(rect.Center.X, rect.Center.Y);
|
||||
//lineEnd += new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Math.Min(width, height) / 2.0f;
|
||||
//GUI.DrawLine(spriteBatch, GuiFrame.Center, lineEnd, Color.Green);
|
||||
|
||||
if (!isActive) return;
|
||||
|
||||
if (pingCircle!=null)
|
||||
{
|
||||
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f-pingState), 0.0f, (rect.Width/pingCircle.size.X)*pingState);
|
||||
}
|
||||
|
||||
float radius = pingCircle.size.X / 2.0f;
|
||||
|
||||
float simScale = 1.5f;
|
||||
float displayScale = 0.015f;
|
||||
|
||||
if (Level.Loaded != null)
|
||||
{
|
||||
List<Vector2[]> edges = Level.Loaded.GetCellEdges(-Level.Loaded.Position, 7);
|
||||
Vector2 offset = Vector2.Zero;
|
||||
|
||||
for (int i = 0; i < edges.Count; i++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
center + (edges[i][0] - offset) * displayScale,
|
||||
center + (edges[i][1] - offset) * displayScale, Color.White);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Submarine.Loaded.HullVertices.Count; i++)
|
||||
{
|
||||
Vector2 start = Submarine.Loaded.HullVertices[i] * simScale;
|
||||
start.Y = -start.Y;
|
||||
Vector2 end = Submarine.Loaded.HullVertices[(i + 1) % Submarine.Loaded.HullVertices.Count] * simScale;
|
||||
end.Y = -end.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch, center + start, center + end, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull != null) continue;
|
||||
|
||||
Vector2 pos = c.Position * displayScale;
|
||||
if (c.SimPosition != Vector2.Zero && pos.Length() < radius)
|
||||
{
|
||||
int width = (int)MathHelper.Clamp(c.Mass / 20, 1, 10);
|
||||
|
||||
pos.Y = -pos.Y;
|
||||
pos += center;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - width / 2, (int)pos.Y - width / 2, width, width), Color.White, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (screenOverlay!=null)
|
||||
{
|
||||
screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width/screenOverlay.size.X);
|
||||
}
|
||||
|
||||
//if (Level.Loaded != null)
|
||||
//{
|
||||
|
||||
// for (int i = 0; i < 2; i++)
|
||||
// {
|
||||
// Vector2 targetPos = (i == 0) ? Level.Loaded.StartPosition : Level.Loaded.EndPosition;
|
||||
// targetPos += Level.Loaded.Position;
|
||||
|
||||
// float dist = targetPos.Length();
|
||||
|
||||
// targetPos.Y = -targetPos.Y;
|
||||
// Vector2 markerPos = Vector2.Normalize(targetPos) * (rect.Width * 0.55f);
|
||||
// markerPos += center;
|
||||
|
||||
// GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightGreen);
|
||||
|
||||
// string label;
|
||||
// if (Game1.GameSession.Map!=null)
|
||||
// {
|
||||
// label = (i == 0) ? Game1.GameSession.Map.CurrentLocation.Name : Game1.GameSession.Map.SelectedLocation.Name;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// label = (i == 0) ? "Start" : "End";
|
||||
// }
|
||||
|
||||
// spriteBatch.DrawString(GUI.SmallFont, label, new Vector2(markerPos.X + 10, markerPos.Y), Color.LightGreen);
|
||||
// spriteBatch.DrawString(GUI.SmallFont, (int)(dist / 80.0f) + " m", new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen);
|
||||
// }
|
||||
|
||||
DrawMarker(spriteBatch,
|
||||
(Game1.GameSession.Map == null) ? "Start" : Game1.GameSession.Map.CurrentLocation.Name,
|
||||
(Level.Loaded.StartPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f));
|
||||
|
||||
DrawMarker(spriteBatch,
|
||||
(Game1.GameSession.Map == null) ? "End" : Game1.GameSession.Map.SelectedLocation.Name,
|
||||
(Level.Loaded.EndPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f));
|
||||
|
||||
if (Game1.GameSession.Quest != null)
|
||||
{
|
||||
var quest = Game1.GameSession.Quest;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(quest.RadarLabel))
|
||||
{
|
||||
DrawMarker(spriteBatch,
|
||||
quest.RadarLabel,
|
||||
quest.RadarPosition, displayScale, center, (rect.Width * 0.55f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMarker(SpriteBatch spriteBatch, string label, Vector2 position, float scale, Vector2 center, float radius)
|
||||
{
|
||||
//position += Level.Loaded.Position;
|
||||
|
||||
float dist = position.Length();
|
||||
|
||||
position *= scale;
|
||||
position.Y = -position.Y;
|
||||
|
||||
Vector2 markerPos = (dist*scale>radius) ? Vector2.Normalize(position) * radius : position;
|
||||
markerPos += center;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightGreen);
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, label, new Vector2(markerPos.X + 10, markerPos.Y), Color.LightGreen);
|
||||
spriteBatch.DrawString(GUI.SmallFont, (int)(dist / 80.0f) + " m", new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Subsurface.Networking;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class Reactor : Powered
|
||||
{
|
||||
//the rate at which the reactor is being run un
|
||||
//higher rates generate more power (and heat)
|
||||
float fissionRate;
|
||||
|
||||
//the rate at which the heat is being dissipated
|
||||
float coolingRate;
|
||||
|
||||
float temperature;
|
||||
|
||||
//is automatic temperature control on
|
||||
//(adjusts the cooling rate automatically to keep the
|
||||
//amount of power generated balanced with the load)
|
||||
bool autoTemp;
|
||||
|
||||
//the temperature after which fissionrate is automatically
|
||||
//turned down and cooling increased
|
||||
float shutDownTemp;
|
||||
|
||||
float meltDownTemp;
|
||||
|
||||
//how much power is provided to the grid per 1 temperature unit
|
||||
float powerPerTemp;
|
||||
|
||||
int graphSize = 25;
|
||||
|
||||
float graphTimer;
|
||||
|
||||
int updateGraphInterval = 500;
|
||||
|
||||
float[] fissionRateGraph;
|
||||
float[] coolingRateGraph;
|
||||
float[] tempGraph;
|
||||
|
||||
private PropertyTask powerUpTask;
|
||||
|
||||
[Editable, HasDefaultValue(9500.0f, true)]
|
||||
public float MeltDownTemp
|
||||
{
|
||||
get { return meltDownTemp; }
|
||||
set
|
||||
{
|
||||
meltDownTemp = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(1.0f, true)]
|
||||
public float PowerPerTemp
|
||||
{
|
||||
get { return powerPerTemp; }
|
||||
set
|
||||
{
|
||||
powerPerTemp = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
public float FissionRate
|
||||
{
|
||||
get { return fissionRate; }
|
||||
set { fissionRate = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public float CoolingRate
|
||||
{
|
||||
get { return coolingRate; }
|
||||
set { coolingRate = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public float Temperature
|
||||
{
|
||||
get { return temperature; }
|
||||
set { temperature = MathHelper.Clamp(value, 0.0f, 10000.0f); }
|
||||
}
|
||||
|
||||
public bool IsRunning()
|
||||
{
|
||||
return (temperature > 0.0f);
|
||||
}
|
||||
|
||||
public float ExtraCooling { get; set; }
|
||||
|
||||
public float AvailableFuel { get; set; }
|
||||
|
||||
public Reactor(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
fissionRateGraph = new float[graphSize];
|
||||
coolingRateGraph = new float[graphSize];
|
||||
tempGraph = new float[graphSize];
|
||||
|
||||
meltDownTemp = 9000.0f;
|
||||
|
||||
shutDownTemp = 500.0f;
|
||||
|
||||
powerPerTemp = 1.0f;
|
||||
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
//ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
fissionRate = Math.Min(fissionRate, AvailableFuel);
|
||||
|
||||
float heat = 100 * fissionRate * (AvailableFuel/2000.0f);
|
||||
float heatDissipation = 50 * coolingRate + ExtraCooling;
|
||||
|
||||
float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 1000.0f;
|
||||
Temperature = temperature + deltaTemp;
|
||||
|
||||
if (temperature > meltDownTemp)
|
||||
{
|
||||
MeltDown();
|
||||
return;
|
||||
}
|
||||
else if (temperature == 0.0f)
|
||||
{
|
||||
if (powerUpTask == null || powerUpTask.IsFinished)
|
||||
{
|
||||
powerUpTask = new PropertyTask(item, IsRunning, 50.0f, "Power up the reactor");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.Condition -= temperature * deltaTime * 0.00005f;
|
||||
|
||||
if (temperature > shutDownTemp)
|
||||
{
|
||||
CoolingRate += 0.5f;
|
||||
FissionRate -= 0.5f;
|
||||
}
|
||||
else if (autoTemp)
|
||||
{
|
||||
|
||||
float load = 0.0f;
|
||||
|
||||
List<Connection> connections = item.Connections;
|
||||
if (connections!=null && connections.Count>0)
|
||||
{
|
||||
foreach (Connection connection in connections)
|
||||
{
|
||||
foreach (Connection recipient in connection.Recipients)
|
||||
{
|
||||
Item it = recipient.Item as Item;
|
||||
if (it == null) continue;
|
||||
|
||||
PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
if (pt != null) load += pt.PowerLoad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//foreach (MapEntity e in item.linkedTo)
|
||||
//{
|
||||
// Item it = e as Item;
|
||||
// if (it == null) continue;
|
||||
|
||||
// PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
// if (pt != null) load += pt.PowerLoad;
|
||||
//}
|
||||
|
||||
fissionRate = Math.Min(load / 200.0f, shutDownTemp);
|
||||
//float target = Math.Min(targetTemp, load);
|
||||
CoolingRate = coolingRate + (temperature - Math.Min(load, shutDownTemp) + deltaTemp)*0.1f;
|
||||
}
|
||||
|
||||
//fission rate can't be lowered below a certain amount if the core is too hot
|
||||
FissionRate = Math.Max(fissionRate, heat / 200.0f);
|
||||
|
||||
|
||||
//the power generated by the reactor is equal to the temperature
|
||||
currPowerConsumption = -temperature*powerPerTemp;
|
||||
|
||||
if (item.CurrentHull != null)
|
||||
{
|
||||
//the sound can be heard from 20 000 display units away when everything running at 100%
|
||||
item.CurrentHull.SoundRange += (coolingRate + fissionRate) * 100;
|
||||
}
|
||||
|
||||
UpdateGraph(deltaTime);
|
||||
|
||||
ExtraCooling = 0.0f;
|
||||
AvailableFuel = 0.0f;
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
base.UpdateBroken(deltaTime, cam);
|
||||
|
||||
Temperature -= deltaTime * 1000.0f;
|
||||
FissionRate -= deltaTime * 10.0f;
|
||||
CoolingRate -= deltaTime * 10.0f;
|
||||
|
||||
currPowerConsumption = -temperature;
|
||||
|
||||
UpdateGraph(deltaTime);
|
||||
|
||||
ExtraCooling = 0.0f;
|
||||
}
|
||||
|
||||
private void UpdateGraph(float deltaTime)
|
||||
{
|
||||
graphTimer += deltaTime * 1000.0f;
|
||||
|
||||
if (graphTimer > updateGraphInterval)
|
||||
{
|
||||
UpdateGraph(fissionRateGraph, fissionRate);
|
||||
UpdateGraph(coolingRateGraph, coolingRate);
|
||||
UpdateGraph(tempGraph, temperature);
|
||||
graphTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void MeltDown()
|
||||
{
|
||||
if (item.Condition <= 0.0f) return;
|
||||
|
||||
new RepairTask(item, 60.0f, "Reactor meltdown!");
|
||||
item.Condition = 0.0f;
|
||||
//fissionRate = 0.0f;
|
||||
//coolingRate = 0.0f;
|
||||
|
||||
//PlaySound(ActionType.OnFailure, item.Position);
|
||||
//item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, null);
|
||||
|
||||
//new Explosion(item.SimPosition, 6.0f, 500.0f, 600.0f, 10.0f, 2.0f).Explode();
|
||||
|
||||
if (item.ContainedItems!=null)
|
||||
{
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
if (containedItem == null) continue;
|
||||
containedItem.Condition = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
return (picker != null);
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
base.Draw(spriteBatch);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.Rect.X + item.Rect.Width / 2 - 6, -item.Rect.Y + 29),
|
||||
new Vector2(12, 42), Color.Black);
|
||||
|
||||
if (temperature > 0)
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Vector2(item.Rect.X + item.Rect.Width / 2 - 5, -item.Rect.Y + 30 + (40.0f * (1.0f - temperature / 10000.0f))),
|
||||
new Vector2(10, 40 * (temperature / 10000.0f)), new Color(temperature / 10000.0f, 1.0f - (temperature / 10000.0f), 0.0f, 1.0f), true);
|
||||
}
|
||||
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
isActive = true;
|
||||
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
float xOffset = (graphTimer / (float)updateGraphInterval);
|
||||
|
||||
//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);
|
||||
|
||||
y += 130;
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y + 30), Color.White);
|
||||
DrawGraph(fissionRateGraph, spriteBatch, x + 30, y + 50, 100.0f, xOffset);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 30, 40, 40), "+", true)) FissionRate += 1.0f;
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 80, 40, 40), "-", true)) FissionRate -= 1.0f;
|
||||
|
||||
y += 130;
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 30, y + 30), Color.White);
|
||||
DrawGraph(coolingRateGraph, spriteBatch, x + 30, y + 50, 100.0f, xOffset);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 30, 40, 40), "+", true)) CoolingRate += 1.0f;
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 80, 40, 40), "-", true)) CoolingRate -= 1.0f;
|
||||
|
||||
y = y - 260;
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 400, y + 30), Color.White);
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 400, y + 60, 100, 40), ((autoTemp) ? "TURN OFF" : "TURN ON"))) autoTemp = !autoTemp;
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Shutdown Temperature: " + shutDownTemp, new Vector2(x + 400, y + 150), Color.White);
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 400, y + 180, 40, 40), "+", true)) shutDownTemp += 100.0f;
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 450, y + 180, 40, 40), "-", true)) shutDownTemp -= 100.0f;
|
||||
|
||||
item.NewComponentEvent(this, true);
|
||||
}
|
||||
|
||||
static void UpdateGraph<T>(IList<T> graph, T newValue)
|
||||
{
|
||||
for (int i = graph.Count - 1; i > 0; i--)
|
||||
{
|
||||
graph[i] = graph[i - 1];
|
||||
}
|
||||
graph[0] = newValue;
|
||||
}
|
||||
|
||||
static void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, int x, int y, float maxVal, float xOffset)
|
||||
{
|
||||
int width = 200;
|
||||
int height = 100;
|
||||
|
||||
float lineWidth = (float)width / (float)(graph.Count - 2);
|
||||
float yScale = (float)height / maxVal;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.White);
|
||||
|
||||
Vector2 prevPoint = new Vector2(x + width, y + height - (graph[1] + (graph[0] - graph[1]) * xOffset) * yScale);
|
||||
|
||||
float currX = x + width - ((xOffset - 1.0f) * lineWidth);
|
||||
|
||||
for (int i = 1; i < graph.Count - 1; i++)
|
||||
{
|
||||
currX -= lineWidth;
|
||||
|
||||
Vector2 newPoint = new Vector2(currX, y + height - graph[i] * yScale);
|
||||
|
||||
GUI.DrawLine(spriteBatch, prevPoint, newPoint, Color.White);
|
||||
|
||||
prevPoint = newPoint;
|
||||
}
|
||||
|
||||
Vector2 lastPoint = new Vector2(x,
|
||||
y + height - (graph[graph.Count - 1] + (graph[graph.Count - 2] - graph[graph.Count - 1]) * xOffset) * yScale);
|
||||
|
||||
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, Color.White);
|
||||
}
|
||||
|
||||
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message)
|
||||
{
|
||||
message.Write(autoTemp);
|
||||
message.Write(temperature);
|
||||
message.Write(shutDownTemp);
|
||||
|
||||
message.Write(coolingRate);
|
||||
message.Write(fissionRate);
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
|
||||
{
|
||||
bool newAutoTemp;
|
||||
float newTemperature, newShutDownTemp;
|
||||
float newCoolingRate, newFissionRate;
|
||||
|
||||
try
|
||||
{
|
||||
newAutoTemp = message.ReadBoolean();
|
||||
newTemperature = message.ReadFloat();
|
||||
newShutDownTemp = message.ReadFloat();
|
||||
|
||||
newCoolingRate = message.ReadFloat();
|
||||
newFissionRate = message.ReadFloat();
|
||||
}
|
||||
|
||||
catch { return; }
|
||||
|
||||
autoTemp = newAutoTemp;
|
||||
Temperature = newTemperature;
|
||||
shutDownTemp = newShutDownTemp;
|
||||
|
||||
CoolingRate = newCoolingRate;
|
||||
FissionRate = newFissionRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class Steering : ItemComponent
|
||||
{
|
||||
private Vector2 currVelocity;
|
||||
private Vector2 targetVelocity;
|
||||
|
||||
private bool autoPilot;
|
||||
|
||||
private SteeringPath steeringPath;
|
||||
|
||||
private static PathFinder pathFinder;
|
||||
|
||||
bool AutoPilot
|
||||
{
|
||||
get { return autoPilot; }
|
||||
set
|
||||
{
|
||||
if (value == autoPilot) return;
|
||||
|
||||
autoPilot = value;
|
||||
|
||||
if (autoPilot)
|
||||
{
|
||||
if (pathFinder==null) pathFinder = new PathFinder(WayPoint.WayPointList, false);
|
||||
steeringPath = pathFinder.FindPath(
|
||||
ConvertUnits.ToSimUnits(Level.Loaded.Position),
|
||||
ConvertUnits.ToSimUnits(Level.Loaded.EndPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 TargetVelocity
|
||||
{
|
||||
get { return targetVelocity;}
|
||||
set
|
||||
{
|
||||
if (float.IsNaN(value.X) || float.IsNaN(value.Y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f);
|
||||
targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public Steering(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
if (autoPilot)
|
||||
{
|
||||
//if (steeringPath==null)
|
||||
//{
|
||||
// PathFinder pathFinder = new PathFinder(WayPoint.WayPointList, false);
|
||||
// steeringPath = pathFinder.FindPath(
|
||||
// ConvertUnits.ToSimUnits(Level.Loaded.StartPosition),
|
||||
// ConvertUnits.ToSimUnits(Level.Loaded.EndPosition));
|
||||
//}
|
||||
|
||||
steeringPath.GetNode(Vector2.Zero, 20.0f);
|
||||
|
||||
if (steeringPath.CurrentNode!=null)
|
||||
{
|
||||
float prediction = 10.0f;
|
||||
|
||||
Vector2 futurePosition = Submarine.Loaded.Speed * prediction;
|
||||
|
||||
Vector2 targetSpeed = (steeringPath.CurrentNode.Position - futurePosition);
|
||||
|
||||
//float dist = targetSpeed.Length();
|
||||
targetSpeed = Vector2.Normalize(targetSpeed);
|
||||
|
||||
TargetVelocity = targetSpeed*100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
item.SendSignal(targetVelocity.X.ToString(CultureInfo.InvariantCulture), "velocity_x_out");
|
||||
item.SendSignal((-targetVelocity.Y).ToString(CultureInfo.InvariantCulture), "velocity_y_out");
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
|
||||
int x = GuiFrame.Rect.X;
|
||||
int y = GuiFrame.Rect.Y;
|
||||
|
||||
GuiFrame.Draw(spriteBatch);
|
||||
|
||||
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
|
||||
GUI.DrawRectangle(spriteBatch, velRect, Color.White, false);
|
||||
|
||||
if (GUI.DrawButton(spriteBatch, new Rectangle(x + width - 150, y + height - 30, 150, 30), "Autopilot"))
|
||||
{
|
||||
AutoPilot = !AutoPilot;
|
||||
|
||||
item.NewComponentEvent(this, true);
|
||||
}
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(velRect.Center.X,velRect.Center.Y),
|
||||
new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y),
|
||||
Color.Gray);
|
||||
|
||||
Vector2 targetVelPos = new Vector2(velRect.Center.X + targetVelocity.X, velRect.Center.Y - targetVelocity.Y);
|
||||
|
||||
GUI.DrawLine(spriteBatch,
|
||||
new Vector2(velRect.Center.X, velRect.Center.Y),
|
||||
targetVelPos,
|
||||
Color.LightGray);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 5, (int)targetVelPos.Y - 5, 10, 10), Color.White);
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X -10, (int)targetVelPos.Y - 10, 20, 20), Color.Red);
|
||||
|
||||
if (PlayerInput.LeftButtonDown())
|
||||
{
|
||||
targetVelocity = PlayerInput.MousePosition - new Vector2(velRect.Center.X, velRect.Center.Y);
|
||||
targetVelocity.Y = -targetVelocity.Y;
|
||||
|
||||
item.NewComponentEvent(this, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f)
|
||||
{
|
||||
if (connection.Name == "velocity_in")
|
||||
{
|
||||
currVelocity = ToolBox.ParseToVector2(signal, false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message)
|
||||
{
|
||||
message.Write(targetVelocity.X);
|
||||
message.Write(targetVelocity.Y);
|
||||
|
||||
message.Write(autoPilot);
|
||||
}
|
||||
|
||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
|
||||
{
|
||||
Vector2 newTargetVelocity = Vector2.Zero;
|
||||
bool newAutoPilot = false;
|
||||
|
||||
try
|
||||
{
|
||||
newTargetVelocity = new Vector2(message.ReadFloat(), message.ReadFloat());
|
||||
newAutoPilot = message.ReadBoolean();
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TargetVelocity = newTargetVelocity;
|
||||
AutoPilot = newAutoPilot;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Subsurface.Items.Components
|
||||
{
|
||||
class Vent : ItemComponent
|
||||
{
|
||||
private float oxygenFlow;
|
||||
|
||||
public float OxygenFlow
|
||||
{
|
||||
get { return oxygenFlow; }
|
||||
set { oxygenFlow = Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
public Vent (Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
if (item.CurrentHull == null) return;
|
||||
|
||||
item.CurrentHull.Oxygen += oxygenFlow * deltaTime;
|
||||
OxygenFlow -= deltaTime * 1000.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user